lyapunov_discrete.cpp
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 
26 
29 
30 #include <Eigen/Core>
31 #include <Eigen/Dense>
32 #include <Eigen/Eigenvalues>
33 #include <algorithm>
34 
35 namespace corbo {
36 
38 {
39  assert(is_square(A));
40  assert(have_equal_size(A, Q));
41 
42  Eigen::ComplexSchur<Eigen::MatrixXd> A_schur(A, true);
43 
44  if (A_schur.info() == Eigen::NoConvergence) return false;
45 
46  const Eigen::MatrixXcd& T = A_schur.matrixT();
47  const Eigen::MatrixXcd& U = A_schur.matrixU();
48 
49  // transform rhs
50  Eigen::MatrixXcd F = U.adjoint() * Q * U;
51 
52  const int n = A.rows();
53  Eigen::MatrixXcd Y(n, n);
54  Y.setZero();
55 
57 
58  Eigen::MatrixXcd lhs(n, n);
59  lhs.setIdentity();
60 
61  Eigen::MatrixXcd T_adjoint = T.adjoint();
62 
63  // solve T Y T^T - Y + F = 0
64  // construct transformed solution by backwards substitution
65  for (int k = n - 1; k >= 0; --k)
66  {
67  Eigen::VectorXcd rhs = F.col(k) + T * Y * T_adjoint.col(k);
68  // move non-zero diagonal elements to lhs and multiply by T
69  // (this is the non-zero part of T Y T^T which depends only on Y.col(k)).
70  const std::complex<double> factor = T_adjoint(k, k);
71  lhs -= T * factor;
72  // compute SVD
73  // TODO(roesmann): here is place for improving efficiency
74  // and robustness by avoiding the SVD (see references).
75  lhs_svd.compute(lhs);
76  // solve linear system
77  Y.col(k) = lhs_svd.solve(rhs);
78  // revert rhs diagonal element for subsequent iteration
79  if (k > 0) lhs.setIdentity();
80  }
81 
82  // transform back
83  X = (U * Y * U.adjoint()).real();
84 
85  return true;
86 }
87 
89 {
90  if (!is_square(A)) return false;
91 
92  Eigen::VectorXcd eigvals_A = A.eigenvalues();
93 
94  for (int i = 0; i < eigvals_A.size(); ++i)
95  {
96  for (int j = i; j < eigvals_A.size(); ++j)
97  {
98  std::complex<double> product = eigvals_A[i] * eigvals_A[j];
99  if (approx_equal(product.real(), 1) && approx_equal(product.imag(), 0)) // TODO(roesman) is 1+i0 correct, or unit circle in general?
100  return false;
101  }
102  }
103  return true;
104 }
105 
106 } // namespace corbo
bool have_equal_size(const Eigen::MatrixBase< DerivedA > &matrix1, const Eigen::MatrixBase< DerivedB > &matrix2)
Determine if two matrices exhibit equal sizes/dimensions.
float real
Definition: datatypes.h:10
bool approx_equal(double a, double b, double epsilon=1e-6)
Check if two doubles are appoximately equal.
bool is_square(const Eigen::MatrixBase< Derived > &matrix)
Determine if a given matrix is square.
ComputationInfo info() const
Reports whether previous computation was successful.
Definition: ComplexSchur.h:217
const Solve< JacobiSVD< _MatrixType, QRPreconditioner >, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition: SVDBase.h:208
MatrixType A(a, *n, *n, *lda)
A matrix or vector expression mapping an existing expression.
Definition: Ref.h:192
static bool hasUniqueSolution(const Eigen::Ref< const Eigen::MatrixXd > &A)
Determine if the Lyapunov equation exhibits a unique solution.
const ComplexMatrixType & matrixU() const
Returns the unitary matrix in the Schur decomposition.
Definition: ComplexSchur.h:138
Two-sided Jacobi SVD decomposition of a rectangular matrix.
static bool solve(const Eigen::Ref< const Eigen::MatrixXd > &A, const Eigen::Ref< const Eigen::MatrixXd > &Q, Eigen::MatrixXd &X)
Solve discrete-time Lyapunov equation.
JacobiSVD & compute(const MatrixType &matrix, unsigned int computationOptions)
Method performing the decomposition of given matrix using custom options.
Definition: JacobiSVD.h:663
Performs a complex Schur decomposition of a real or complex square matrix.
Definition: ComplexSchur.h:51
#define X
Definition: icosphere.cpp:20
PlainMatrixType mat * n
Definition: eigenvalues.cpp:41
const ComplexMatrixType & matrixT() const
Returns the triangular matrix in the Schur decomposition.
Definition: ComplexSchur.h:162


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