test_sylvester_continuous.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 
27 #include <corbo-core/macros.h>
28 
29 #include "gtest/gtest.h"
30 
32 
33 class TestSylvesterEquationContinuousTime : public testing::Test
34 {
35  protected:
36  // You can do set-up work for each test here.
38  // You can do clean-up work that doesn't throw exceptions here.
40  // If the constructor and destructor are not enough for setting up
41  // and cleaning up each test, you can define the following methods:
42 
43  // Code here will be called immediately after the constructor (right
44  // before each test).
45  // virtual void SetUp() {}
46  // Code here will be called immediately after each test (right
47  // before the destructor).
48  // virtual void TearDown();
49 };
50 
52 {
54  A << 5;
55  Eigen::Matrix2d B;
56  B << 4, 3, 4, 3;
57 
59  C << 2, 1;
60 
61  EXPECT_TRUE(SylvesterContinuous::hasUniqueSolution(A, B));
62 
63  Eigen::MatrixXd X;
64  bool solve_success = SylvesterContinuous::solve(A, B, C, X);
65  EXPECT_TRUE(solve_success);
66 
68  X_sol << -0.2, -0.05;
69 
70  EXPECT_EQ_MATRIX(X, X_sol, 1e-5);
71 }
72 
74 {
75  Eigen::Matrix2d A;
76  A << 1, 2, -3, -4;
77 
78  Eigen::Matrix2d B = A.transpose();
79 
80  Eigen::Matrix2d C;
81  C << 3, 1, 1, 1;
82 
83  EXPECT_TRUE(SylvesterContinuous::hasUniqueSolution(A, B));
84 
85  Eigen::MatrixXd X;
86  bool solve_success = SylvesterContinuous::solve(A, B, C, X);
87  EXPECT_TRUE(solve_success);
88 
89  Eigen::Matrix2d X_sol;
90  X_sol << 6.166666, -3.8333333, -3.8333333, 3;
91 
92  EXPECT_EQ_MATRIX(X, X_sol, 1e-5);
93 }
94 
96 {
97  // this test differs from solve_feasible 1-2 such that
98  // the underlying Schur solver in the current implementation must be
99  // of complex type (rather than real) in order to find the correct solution.
100  Eigen::MatrixXd A(5, 5);
101  A << -2.5, -2.3, -0.95, -0.1689, -0.095, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0;
102 
103  Eigen::MatrixXd B(5, 5);
104  B << -2, -1, -0.5, -0.1, -0.005, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0;
105 
106  Eigen::MatrixXd C = Eigen::MatrixXd::Identity(5, 5);
107 
108  EXPECT_TRUE(SylvesterContinuous::hasUniqueSolution(A, B));
109 
110  Eigen::MatrixXd X;
111  bool solve_success = SylvesterContinuous::solve(A, B, C, X);
112  EXPECT_TRUE(solve_success);
113 
114  Eigen::MatrixXd X_sol(5, 5);
115  X_sol << -0.2099, -0.8702, -0.0400, 0.0221, 0.0016, 0.3106, 0.8311, 0.1808, 0.1953, 0.0089, 1.7890, 3.2674, 0.9579, -0.2863, -0.0164, -3.2772,
116  -8.3434, -6.5446, -2.5965, -1.0414, -8.2753, -13.2734, 0.0681, 2.4069, 1.7689;
117 
118  EXPECT_EQ_MATRIX(X, X_sol, 1e-5);
119 }
120 
122 {
123  Eigen::MatrixXd A = Eigen::MatrixXd::Random(4, 4);
124  Eigen::MatrixXd B = Eigen::MatrixXd::Random(5, 5);
125  Eigen::MatrixXd C = Eigen::MatrixXd::Random(5, 4); // dimensions switched here
126 
127  Eigen::MatrixXd X;
128  EXPECT_DEBUG_DEATH(SylvesterContinuous::solve(A, B, C, X), "");
129 }
130 
131 TEST_F(TestSylvesterEquationContinuousTime, has_unique_solution_false1)
132 {
133  Eigen::Matrix3d A = Eigen::Matrix3d::Ones();
134  Eigen::Matrix3d B = A.transpose();
135 
136  EXPECT_FALSE(SylvesterContinuous::hasUniqueSolution(A, B));
137 }
138 
139 TEST_F(TestSylvesterEquationContinuousTime, has_unique_solution_false2)
140 {
141  Eigen::MatrixXd A = Eigen::MatrixXd::Zero(10, 10);
142  Eigen::MatrixXd B = Eigen::MatrixXd::Zero(10, 10);
143 
144  EXPECT_FALSE(SylvesterContinuous::hasUniqueSolution(A, B));
145 }
146 
147 TEST_F(TestSylvesterEquationContinuousTime, has_unique_solution_non_square)
148 {
149  Eigen::MatrixXd A = Eigen::MatrixXd::Random(5, 4);
150  Eigen::MatrixXd B = Eigen::MatrixXd::Random(5, 5);
151 
152  Eigen::MatrixXd X;
153  EXPECT_FALSE(SylvesterContinuous::hasUniqueSolution(A, B));
154  EXPECT_FALSE(SylvesterContinuous::hasUniqueSolution(B, A));
155 }
TestSylvesterEquationContinuousTime::TestSylvesterEquationContinuousTime
TestSylvesterEquationContinuousTime()
Definition: test_sylvester_continuous.cpp:37
corbo::SylvesterContinuous
Methods for dealing with continuous-time sylvester equations.
Definition: sylvester_continuous.h:78
TEST_F
TEST_F(TestSylvesterEquationContinuousTime, solve_feasible1)
Definition: test_sylvester_continuous.cpp:51
macros.h
TestSylvesterEquationContinuousTime
Definition: test_sylvester_continuous.cpp:33
X
#define X
Definition: icosphere.cpp:20
sylvester_continuous.h
B
MatrixType B(b, *n, *nrhs, *ldb)
EXPECT_EQ_MATRIX
#define EXPECT_EQ_MATRIX(A, B, tol)
Definition: macros.h:61
Eigen::Matrix
The matrix class, also used for vectors and row-vectors.
Definition: Matrix.h:178
A
MatrixType A(a, *n, *n, *lda)
TestSylvesterEquationContinuousTime::~TestSylvesterEquationContinuousTime
virtual ~TestSylvesterEquationContinuousTime()
Definition: test_sylvester_continuous.cpp:39


control_box_rst
Author(s): Christoph Rösmann
autogenerated on Wed Mar 2 2022 00:07:06