- 3.0.2 core module.
Inverses.h
Go to the documentation of this file.
1 /**********************************************************************************************************************
2 This file is part of the Control Toolbox (https://github.com/ethz-adrl/control-toolbox), copyright by ETH Zurich.
3 Licensed under the BSD-2 license (see LICENSE file in main directory)
4 **********************************************************************************************************************/
5 
6 #pragma once
7 
8 namespace ct {
9 namespace core {
10 namespace inverseHelperfunctions {
11 // Custom LU factorization
12 template <typename SCALAR>
13 //only square matrices
14 void lu(const Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& A,
15  Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& LU)
16 {
17  const int n = A.rows();
18  for (int k = 0; k < n; ++k)
19  {
20  for (int i = k; i < n; ++i)
21  {
22  SCALAR sum(0.0);
23  for (int p = 0; p < k; ++p)
24  {
25  sum += LU(i, p) * LU(p, k);
26  }
27  LU(i, k) = A(i, k) - sum; // not dividing by diagonals
28  }
29  for (int j = k + 1; j < n; ++j)
30  {
31  SCALAR sum(0.0);
32  for (int p = 0; p < k; ++p)
33  {
34  sum += LU(k, p) * LU(p, j);
35  }
36  LU(k, j) = (A(k, j) - sum) / LU(k, k);
37  }
38  }
39 }
40 
41 // Custom LU solver
42 template <typename SCALAR>
43 void solveLU(const Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& LU,
44  const Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& b,
45  Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& x)
46 {
47  const int n = LU.rows();
48  const int m = b.cols();
49  Eigen::Matrix<SCALAR, Eigen::Dynamic, 1> y(n);
50  for (int j = 0; j < m; ++j)
51  {
52  // Solve LU for jth-column on b
53  for (int i = 0; i < n; ++i)
54  {
55  SCALAR sum(0.0);
56  for (int k = 0; k < i; ++k)
57  {
58  sum += LU(i, k) * y[k];
59  }
60  y(i) = (b(i, j) - sum) / LU(i, i);
61  }
62  for (int i = n - 1; i >= 0; --i)
63  {
64  SCALAR sum(0.0);
65  for (int k = i + 1; k < n; ++k)
66  {
67  sum += LU(i, k) * x(k, j);
68  }
69  x(i, j) = (y(i) - sum); // not dividing by diagonals
70  }
71  }
72 }
73 
74 // Custom LDLT factorization (Algorithm from https://en.wikipedia.org/wiki/Cholesky_decomposition)
75 template <typename SCALAR>
76 //only square matrices
77 void ldlt(const Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& A,
78  Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& L,
79  Eigen::Matrix<SCALAR, Eigen::Dynamic, 1>& d)
80 {
81  const int n = A.rows();
82  L.setIdentity();
83  for (int j = 0; j < n; ++j)
84  {
85  SCALAR sum(0.0);
86  for (int k = 0; k < j; ++k)
87  {
88  sum += L(j, k) * L(j, k) * d(k);
89  }
90  d(j) = A(j, j) - sum;
91 
92  for (int i = j + 1; i < n; i++)
93  {
94  SCALAR sum(0.0);
95  for (int k = 0; k < j; ++k)
96  {
97  sum += L(i, k) * L(j, k) * d(k);
98  }
99  L(i, j) = (A(i, j) - sum) / d(j);
100  }
101  }
102 }
103 
104 // Custom LDLT solver
105 template <typename SCALAR>
106 // solves X = A^(-1) * B, with A nxn and b nxm
107 void solveLDLT(const Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& L,
108  const Eigen::Matrix<SCALAR, Eigen::Dynamic, 1>& d,
109  const Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& b,
110  Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& x)
111 {
112  const int n = L.rows();
113  const int m = b.cols();
114  Eigen::Matrix<SCALAR, Eigen::Dynamic, 1> y(n);
115  for (int j = 0; j < m; ++j)
116  {
117  // Solve LDLT for j-th column of b
118  // 1. solve L*y = b
119  for (int i = 0; i < n; ++i)
120  {
121  SCALAR sum(0.0);
122  for (int k = 0; k < i; k++)
123  {
124  sum += L(i, k) * y(k);
125  }
126  y(i) = (b(i, j) - sum);
127  }
128  // 2. solve D L^T x = y
129  for (int i = n - 1; i >= 0; --i)
130  {
131  SCALAR sum(0.0);
132  for (int k = i + 1; k < n; ++k)
133  {
134  sum += L(k, i) * x(k, j);
135  }
136  x(i, j) = (y(i) / d(i) - sum);
137  }
138  }
139 }
140 
141 
142 } // namespace inverseHelperfunctions
143 
144 /***
145  * LU-based inverse solver
146  * This implementation does NOT use pivoting. Therefore we can only invert well-conditioned positive definite matrices
147  * having a positive semi-definite A is not tested
148  */
149 template <typename SCALAR>
150 // solves X = A^(-1) * B, with A nxn and b nxm
151 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> LUsolve(
152  const Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& A,
153  const Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& B)
154 {
155  const int n = A.rows();
156  const int m = B.cols();
157  Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> LU(n, n);
158  inverseHelperfunctions::lu<SCALAR>(A, LU);
159 
160  Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> X(n, m);
161  inverseHelperfunctions::solveLU<SCALAR>(LU, B, X);
162 
163  return X;
164 }
165 
166 /***
167  * LDLT-based inverse solver with dynamic sizing
168  * Only use for symmetric(!) positive (semi)-definite matrices.
169  * This implementation does NOT use pivoting, but this algorithm has good stability properties for positive definite matrices in general.
170  */
171 template <typename SCALAR>
172 // solves X = A^(-1) * B, with A nxn and b nxm
173 Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> LDLTsolve(
174  const Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& A,
175  const Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>& B)
176 {
177  // Compute the decomposition
178  const int n = A.rows();
179  const int m = B.cols();
180  Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> L(n, n);
181  Eigen::Matrix<SCALAR, Eigen::Dynamic, 1> d(n);
183 
184  // Solve the LDLT * X = B system
185  Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic> X(n, m);
187 
188  return X;
189 }
190 }
191 }
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > LUsolve(const Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &A, const Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &B)
Definition: Inverses.h:151
void lu(const Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &A, Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &LU)
Definition: Inverses.h:14
CppAD::AD< CppAD::cg::CG< double > > SCALAR
constexpr size_t n
Definition: MatrixInversionTest.cpp:14
for i
void solveLDLT(const Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &L, const Eigen::Matrix< SCALAR, Eigen::Dynamic, 1 > &d, const Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &b, Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &x)
Definition: Inverses.h:107
void solveLU(const Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &LU, const Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &b, Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &x)
Definition: Inverses.h:43
X
void ldlt(const Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &A, Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &L, Eigen::Matrix< SCALAR, Eigen::Dynamic, 1 > &d)
Definition: Inverses.h:77
Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > LDLTsolve(const Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &A, const Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > &B)
Definition: Inverses.h:173