schur.hpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement
4  *
5  * Copyright (c) 2020,
6  * TU Dortmund - Institute of Control Theory and Systems Engineering.
7  * All rights reserved.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  *
22  * Authors: Christoph Rösmann
23  *********************************************************************/
24 
27 #include <corbo-numerics/schur.h>
28 
29 #include <utility>
30 #include <vector>
31 
32 namespace corbo {
33 
34 template <class Predicate>
35 bool reorder_schur_blocks(Eigen::Ref<Eigen::MatrixXd> T, Eigen::Ref<Eigen::MatrixXd> Q, Predicate predicate, int* subspace_dim, bool standardize)
36 {
37  assert(is_square(T));
38  assert(have_equal_size(T, Q));
39 
40  if (T.rows() < 2) return true;
41 
42  std::vector<std::pair<int, int>> blocks; // row_idx, block size
43  blocks.reserve(T.rows());
44  std::vector<int> selected;
45  selected.reserve(T.rows());
46 
47  int subspace_dim_internal = 0;
48 
49  // search for blocks and determine if they are selected (predicate == true)
50  int row = 0;
51  while (row < T.rows())
52  {
53  // check, if we have a 1 x 1 or 2 x 2 block
54  int p;
55  if (row + 1 >= T.rows())
56  p = 1;
57  else if (approx_zero(T(row + 1, row), 1e-10))
58  p = 1;
59  else
60  p = 2;
61 
62  if (predicate(T.block(row, row, p, p)))
63  {
64  selected.push_back((int)blocks.size()); // add current block index
65  subspace_dim_internal += p;
66  }
67 
68  blocks.emplace_back(row, p);
69 
70  row += p;
71  }
72 
73  if (selected.empty())
74  {
75  if (subspace_dim) *subspace_dim = 0;
76  return true;
77  }
78 
79  int top = 0;
80  for (int l = 0; l < (int)selected.size(); ++l)
81  {
82  int current_idx = selected[l]; // current_idx is is increasing only with l
83  for (int i = current_idx; i >= top + 1; --i)
84  {
85  // swap A_{i-1} with A_{i}
86  if (!swap_schur_blocks(T, blocks[i - 1].first, blocks[i - 1].second, blocks[i].second, Q, standardize)) return false;
87  // update index
88  int p_prev = blocks[i - 1].second;
89  blocks[i - 1].second = blocks[i].second;
90  blocks[i].first = blocks[i - 1].first + blocks[i].second;
91  blocks[i].second = p_prev;
92  }
93  ++top;
94  }
95 
96  if (subspace_dim) *subspace_dim = subspace_dim_internal;
97  return true;
98 }
99 
100 } // namespace corbo
bool have_equal_size(const Eigen::MatrixBase< DerivedA > &matrix1, const Eigen::MatrixBase< DerivedB > &matrix2)
Determine if two matrices exhibit equal sizes/dimensions.
return int(ret)+1
bool swap_schur_blocks(Eigen::Ref< Eigen::MatrixXd > T, int ra11, int p, int q, Eigen::Ref< Eigen::MatrixXd > Q, bool standardize)
Definition: schur.cpp:170
bool is_square(const Eigen::MatrixBase< Derived > &matrix)
Determine if a given matrix is square.
bool reorder_schur_blocks(Eigen::Ref< Eigen::MatrixXd > T, Eigen::Ref< Eigen::MatrixXd > Q, Predicate predicate, int *subspace_dim, bool standardize)
Definition: schur.hpp:35
A matrix or vector expression mapping an existing expression.
Definition: Ref.h:192
bool approx_zero(double val, double epsilon=1e-10)
Check if a double is appoximately zero.
EIGEN_DEVICE_FUNC RowXpr row(Index i)
This is the const version of row(). */.
Definition: BlockMethods.h:859


control_box_rst
Author(s): Christoph Rösmann
autogenerated on Mon Feb 28 2022 22:07:16