MatrixFunction.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2009-2011 Jitse Niesen <jitse@maths.leeds.ac.uk>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef EIGEN_MATRIX_FUNCTION
11 #define EIGEN_MATRIX_FUNCTION
12 
13 #include "StemFunction.h"
14 #include "MatrixFunctionAtomic.h"
15 
16 
17 namespace Eigen {
18 
34 template <typename MatrixType,
35  typename AtomicType,
36  int IsComplex = NumTraits<typename internal::traits<MatrixType>::Scalar>::IsComplex>
38 {
39  public:
40 
49  MatrixFunction(const MatrixType& A, AtomicType& atomic);
50 
59  template <typename ResultType>
60  void compute(ResultType &result);
61 };
62 
63 
67 template <typename MatrixType, typename AtomicType>
68 class MatrixFunction<MatrixType, AtomicType, 0>
69 {
70  private:
71 
73  typedef typename Traits::Scalar Scalar;
74  static const int Rows = Traits::RowsAtCompileTime;
75  static const int Cols = Traits::ColsAtCompileTime;
76  static const int Options = MatrixType::Options;
77  static const int MaxRows = Traits::MaxRowsAtCompileTime;
78  static const int MaxCols = Traits::MaxColsAtCompileTime;
79 
80  typedef std::complex<Scalar> ComplexScalar;
82 
83  public:
84 
90  MatrixFunction(const MatrixType& A, AtomicType& atomic) : m_A(A), m_atomic(atomic) { }
91 
101  template <typename ResultType>
102  void compute(ResultType& result)
103  {
104  ComplexMatrix CA = m_A.template cast<ComplexScalar>();
105  ComplexMatrix Cresult;
107  mf.compute(Cresult);
108  result = Cresult.real();
109  }
110 
111  private:
113  AtomicType& m_atomic;
115  MatrixFunction& operator=(const MatrixFunction&);
116 };
117 
118 
122 template <typename MatrixType, typename AtomicType>
123 class MatrixFunction<MatrixType, AtomicType, 1>
124 {
125  private:
126 
128  typedef typename MatrixType::Scalar Scalar;
129  typedef typename MatrixType::Index Index;
130  static const int RowsAtCompileTime = Traits::RowsAtCompileTime;
131  static const int ColsAtCompileTime = Traits::ColsAtCompileTime;
132  static const int Options = MatrixType::Options;
137  typedef std::list<Scalar> Cluster;
138  typedef std::list<Cluster> ListOfClusters;
140 
141  public:
142 
143  MatrixFunction(const MatrixType& A, AtomicType& atomic);
144  template <typename ResultType> void compute(ResultType& result);
145 
146  private:
147 
148  void computeSchurDecomposition();
149  void partitionEigenvalues();
150  typename ListOfClusters::iterator findCluster(Scalar key);
151  void computeClusterSize();
152  void computeBlockStart();
153  void constructPermutation();
154  void permuteSchur();
155  void swapEntriesInSchur(Index index);
156  void computeBlockAtomic();
157  Block<MatrixType> block(MatrixType& A, Index i, Index j);
158  void computeOffDiagonal();
159  DynMatrixType solveTriangularSylvester(const DynMatrixType& A, const DynMatrixType& B, const DynMatrixType& C);
160 
162  AtomicType& m_atomic;
163  MatrixType m_T;
164  MatrixType m_U;
165  MatrixType m_fT;
166  ListOfClusters m_clusters;
167  DynamicIntVectorType m_eivalToCluster;
168  DynamicIntVectorType m_clusterSize;
169  DynamicIntVectorType m_blockStart;
170  IntVectorType m_permutation;
178  static const RealScalar separation() { return static_cast<RealScalar>(0.1); }
179 
180  MatrixFunction& operator=(const MatrixFunction&);
181 };
182 
188 template <typename MatrixType, typename AtomicType>
189 MatrixFunction<MatrixType,AtomicType,1>::MatrixFunction(const MatrixType& A, AtomicType& atomic)
190  : m_A(A), m_atomic(atomic)
191 {
192  /* empty body */
193 }
194 
200 template <typename MatrixType, typename AtomicType>
201 template <typename ResultType>
203 {
204  computeSchurDecomposition();
205  partitionEigenvalues();
206  computeClusterSize();
207  computeBlockStart();
208  constructPermutation();
209  permuteSchur();
210  computeBlockAtomic();
211  computeOffDiagonal();
212  result = m_U * (m_fT.template triangularView<Upper>() * m_U.adjoint());
213 }
214 
216 template <typename MatrixType, typename AtomicType>
218 {
219  const ComplexSchur<MatrixType> schurOfA(m_A);
220  m_T = schurOfA.matrixT();
221  m_U = schurOfA.matrixU();
222 }
223 
235 template <typename MatrixType, typename AtomicType>
237 {
238  using std::abs;
239  const Index rows = m_T.rows();
240  VectorType diag = m_T.diagonal(); // contains eigenvalues of A
241 
242  for (Index i=0; i<rows; ++i) {
243  // Find set containing diag(i), adding a new set if necessary
244  typename ListOfClusters::iterator qi = findCluster(diag(i));
245  if (qi == m_clusters.end()) {
246  Cluster l;
247  l.push_back(diag(i));
248  m_clusters.push_back(l);
249  qi = m_clusters.end();
250  --qi;
251  }
252 
253  // Look for other element to add to the set
254  for (Index j=i+1; j<rows; ++j) {
255  if (abs(diag(j) - diag(i)) <= separation() && std::find(qi->begin(), qi->end(), diag(j)) == qi->end()) {
256  typename ListOfClusters::iterator qj = findCluster(diag(j));
257  if (qj == m_clusters.end()) {
258  qi->push_back(diag(j));
259  } else {
260  qi->insert(qi->end(), qj->begin(), qj->end());
261  m_clusters.erase(qj);
262  }
263  }
264  }
265  }
266 }
267 
273 template <typename MatrixType, typename AtomicType>
275 {
276  typename Cluster::iterator j;
277  for (typename ListOfClusters::iterator i = m_clusters.begin(); i != m_clusters.end(); ++i) {
278  j = std::find(i->begin(), i->end(), key);
279  if (j != i->end())
280  return i;
281  }
282  return m_clusters.end();
283 }
284 
286 template <typename MatrixType, typename AtomicType>
288 {
289  const Index rows = m_T.rows();
290  VectorType diag = m_T.diagonal();
291  const Index numClusters = static_cast<Index>(m_clusters.size());
292 
293  m_clusterSize.setZero(numClusters);
294  m_eivalToCluster.resize(rows);
295  Index clusterIndex = 0;
296  for (typename ListOfClusters::const_iterator cluster = m_clusters.begin(); cluster != m_clusters.end(); ++cluster) {
297  for (Index i = 0; i < diag.rows(); ++i) {
298  if (std::find(cluster->begin(), cluster->end(), diag(i)) != cluster->end()) {
299  ++m_clusterSize[clusterIndex];
300  m_eivalToCluster[i] = clusterIndex;
301  }
302  }
303  ++clusterIndex;
304  }
305 }
306 
308 template <typename MatrixType, typename AtomicType>
310 {
311  m_blockStart.resize(m_clusterSize.rows());
312  m_blockStart(0) = 0;
313  for (Index i = 1; i < m_clusterSize.rows(); i++) {
314  m_blockStart(i) = m_blockStart(i-1) + m_clusterSize(i-1);
315  }
316 }
317 
319 template <typename MatrixType, typename AtomicType>
321 {
322  DynamicIntVectorType indexNextEntry = m_blockStart;
323  m_permutation.resize(m_T.rows());
324  for (Index i = 0; i < m_T.rows(); i++) {
325  Index cluster = m_eivalToCluster[i];
326  m_permutation[i] = indexNextEntry[cluster];
327  ++indexNextEntry[cluster];
328  }
329 }
330 
332 template <typename MatrixType, typename AtomicType>
334 {
335  IntVectorType p = m_permutation;
336  for (Index i = 0; i < p.rows() - 1; i++) {
337  Index j;
338  for (j = i; j < p.rows(); j++) {
339  if (p(j) == i) break;
340  }
341  eigen_assert(p(j) == i);
342  for (Index k = j-1; k >= i; k--) {
343  swapEntriesInSchur(k);
344  std::swap(p.coeffRef(k), p.coeffRef(k+1));
345  }
346  }
347 }
348 
350 template <typename MatrixType, typename AtomicType>
352 {
353  JacobiRotation<Scalar> rotation;
354  rotation.makeGivens(m_T(index, index+1), m_T(index+1, index+1) - m_T(index, index));
355  m_T.applyOnTheLeft(index, index+1, rotation.adjoint());
356  m_T.applyOnTheRight(index, index+1, rotation);
357  m_U.applyOnTheRight(index, index+1, rotation);
358 }
359 
366 template <typename MatrixType, typename AtomicType>
368 {
369  m_fT.resize(m_T.rows(), m_T.cols());
370  m_fT.setZero();
371  for (Index i = 0; i < m_clusterSize.rows(); ++i) {
372  block(m_fT, i, i) = m_atomic.compute(block(m_T, i, i));
373  }
374 }
375 
377 template <typename MatrixType, typename AtomicType>
379 {
380  return A.block(m_blockStart(i), m_blockStart(j), m_clusterSize(i), m_clusterSize(j));
381 }
382 
390 template <typename MatrixType, typename AtomicType>
392 {
393  for (Index diagIndex = 1; diagIndex < m_clusterSize.rows(); diagIndex++) {
394  for (Index blockIndex = 0; blockIndex < m_clusterSize.rows() - diagIndex; blockIndex++) {
395  // compute (blockIndex, blockIndex+diagIndex) block
396  DynMatrixType A = block(m_T, blockIndex, blockIndex);
397  DynMatrixType B = -block(m_T, blockIndex+diagIndex, blockIndex+diagIndex);
398  DynMatrixType C = block(m_fT, blockIndex, blockIndex) * block(m_T, blockIndex, blockIndex+diagIndex);
399  C -= block(m_T, blockIndex, blockIndex+diagIndex) * block(m_fT, blockIndex+diagIndex, blockIndex+diagIndex);
400  for (Index k = blockIndex + 1; k < blockIndex + diagIndex; k++) {
401  C += block(m_fT, blockIndex, k) * block(m_T, k, blockIndex+diagIndex);
402  C -= block(m_T, blockIndex, k) * block(m_fT, k, blockIndex+diagIndex);
403  }
404  block(m_fT, blockIndex, blockIndex+diagIndex) = solveTriangularSylvester(A, B, C);
405  }
406  }
407 }
408 
432 template <typename MatrixType, typename AtomicType>
434  const DynMatrixType& A,
435  const DynMatrixType& B,
436  const DynMatrixType& C)
437 {
438  eigen_assert(A.rows() == A.cols());
439  eigen_assert(A.isUpperTriangular());
440  eigen_assert(B.rows() == B.cols());
441  eigen_assert(B.isUpperTriangular());
442  eigen_assert(C.rows() == A.rows());
443  eigen_assert(C.cols() == B.rows());
444 
445  Index m = A.rows();
446  Index n = B.rows();
447  DynMatrixType X(m, n);
448 
449  for (Index i = m - 1; i >= 0; --i) {
450  for (Index j = 0; j < n; ++j) {
451 
452  // Compute AX = \sum_{k=i+1}^m A_{ik} X_{kj}
453  Scalar AX;
454  if (i == m - 1) {
455  AX = 0;
456  } else {
457  Matrix<Scalar,1,1> AXmatrix = A.row(i).tail(m-1-i) * X.col(j).tail(m-1-i);
458  AX = AXmatrix(0,0);
459  }
460 
461  // Compute XB = \sum_{k=1}^{j-1} X_{ik} B_{kj}
462  Scalar XB;
463  if (j == 0) {
464  XB = 0;
465  } else {
466  Matrix<Scalar,1,1> XBmatrix = X.row(i).head(j) * B.col(j).head(j);
467  XB = XBmatrix(0,0);
468  }
469 
470  X(i,j) = (C(i,j) - AX - XB) / (A(i,i) + B(j,j));
471  }
472  }
473  return X;
474 }
475 
488 template<typename Derived> class MatrixFunctionReturnValue
489 : public ReturnByValue<MatrixFunctionReturnValue<Derived> >
490 {
491  public:
492 
493  typedef typename Derived::Scalar Scalar;
494  typedef typename Derived::Index Index;
496 
503  MatrixFunctionReturnValue(const Derived& A, StemFunction f) : m_A(A), m_f(f) { }
504 
510  template <typename ResultType>
511  inline void evalTo(ResultType& result) const
512  {
513  typedef typename Derived::PlainObject PlainObject;
514  typedef internal::traits<PlainObject> Traits;
515  static const int RowsAtCompileTime = Traits::RowsAtCompileTime;
516  static const int ColsAtCompileTime = Traits::ColsAtCompileTime;
517  static const int Options = PlainObject::Options;
518  typedef std::complex<typename NumTraits<Scalar>::Real> ComplexScalar;
520  typedef MatrixFunctionAtomic<DynMatrixType> AtomicType;
521  AtomicType atomic(m_f);
522 
523  const PlainObject Aevaluated = m_A.eval();
524  MatrixFunction<PlainObject, AtomicType> mf(Aevaluated, atomic);
525  mf.compute(result);
526  }
527 
528  Index rows() const { return m_A.rows(); }
529  Index cols() const { return m_A.cols(); }
530 
531  private:
533  StemFunction *m_f;
534 
536 };
537 
538 namespace internal {
539 template<typename Derived>
541 {
542  typedef typename Derived::PlainObject ReturnType;
543 };
544 }
545 
546 
547 /********** MatrixBase methods **********/
548 
549 
550 template <typename Derived>
552 {
553  eigen_assert(rows() == cols());
554  return MatrixFunctionReturnValue<Derived>(derived(), f);
555 }
556 
557 template <typename Derived>
559 {
560  eigen_assert(rows() == cols());
561  typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar;
563 }
564 
565 template <typename Derived>
567 {
568  eigen_assert(rows() == cols());
569  typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar;
571 }
572 
573 template <typename Derived>
575 {
576  eigen_assert(rows() == cols());
577  typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar;
579 }
580 
581 template <typename Derived>
583 {
584  eigen_assert(rows() == cols());
585  typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar;
587 }
588 
589 } // end namespace Eigen
590 
591 #endif // EIGEN_MATRIX_FUNCTION
std::complex< typename NumTraits< Scalar >::Real > ComplexScalar
void makeGivens(const Scalar &p, const Scalar &q, Scalar *z=0)
Definition: Jacobi.h:148
DynamicIntVectorType m_eivalToCluster
m_eivalToCluster[i] = j means i-th ei&#39;val is in j-th cluster
DynamicIntVectorType m_blockStart
Row index at which block corresponding to i-th cluster starts.
iterative scaling algorithm to equilibrate rows and column norms in matrices
Definition: matrix.hpp:471
Rotation given by a cosine-sine pair.
Block< Derived > block(Index startRow, Index startCol, Index blockRows, Index blockCols)
Definition: BlockMethods.h:56
Holds information about the various numeric (i.e. scalar) types allowed by Eigen. ...
Definition: NumTraits.h:88
void compute(ResultType &result)
Compute the matrix function.
Matrix< Scalar, Traits::RowsAtCompileTime, 1 > VectorType
Class for computing matrix functions.
const MatrixFunctionReturnValue< Derived > sinh() const
Proxy for the matrix function of some matrix (expression).
static const RealScalar separation()
Maximum distance allowed between eigenvalues to be considered "close".
const MatrixFunctionReturnValue< Derived > cos() const
MatrixFunctionReturnValue(const Derived &A, StemFunction f)
Constructor.
EIGEN_STRONG_INLINE Index rows() const
EIGEN_STRONG_INLINE const CwiseUnaryOp< internal::scalar_abs_op< Scalar >, const Derived > abs() const
internal::nested< MatrixType >::type m_A
Reference to argument of matrix function.
internal::nested< Derived >::type m_A
const MatrixFunctionReturnValue< Derived > cosh() const
EIGEN_STRONG_INLINE Scalar & coeffRef(Index rowId, Index colId)
EIGEN_STRONG_INLINE void resize(Index nbRows, Index nbCols)
Provides a generic way to set and pass user-specified options.
Definition: options.hpp:65
void compute(ResultType &result)
Compute the matrix function.
JacobiRotation adjoint() const
Definition: Jacobi.h:62
DynamicIntVectorType m_clusterSize
Number of eigenvalues in each clusters.
MatrixType m_U
Unitary part of Schur decomposition.
const ComplexMatrixType & matrixT() const
Returns the triangular matrix in the Schur decomposition.
Definition: ComplexSchur.h:161
Derived & setZero(Index size)
Stem functions corresponding to standard mathematical functions.
Definition: StemFunction.h:19
Matrix< Index, Traits::RowsAtCompileTime, 1 > IntVectorType
Helper class for computing matrix functions of atomic matrices.
MatrixType m_fT
Matrix function applied to m_T
internal::stem_function< Scalar >::type StemFunction
void evalTo(ResultType &result) const
Compute the matrix function.
MatrixFunction(const MatrixType &A, AtomicType &atomic)
Constructor.
MatrixType m_T
Triangular part of Schur decomposition.
Expression of a fixed-size or dynamic-size block.
Definition: Core/Block.h:102
IntVectorType m_permutation
Permutation which groups ei&#39;vals in the same cluster together.
ListOfClusters m_clusters
Partition of eigenvalues into clusters of ei&#39;vals "close" to each other.
Matrix< ComplexScalar, Rows, Cols, Options, MaxRows, MaxCols > ComplexMatrix
const MatrixFunctionReturnValue< Derived > matrixFunction(StemFunction f) const
AtomicType & m_atomic
Class for computing matrix function of atomic blocks.
The matrix class, also used for vectors and row-vectors.
Definition: Matrix.h:127
EIGEN_STRONG_INLINE Index cols() const
#define eigen_assert(x)
const ComplexMatrixType & matrixU() const
Returns the unitary matrix in the Schur decomposition.
Definition: ComplexSchur.h:137
Matrix< Scalar, Dynamic, Dynamic, Options, RowsAtCompileTime, ColsAtCompileTime > DynMatrixType
const MatrixFunctionReturnValue< Derived > sin() const
AtomicType & m_atomic
Class for computing matrix function of atomic blocks.
MatrixFunction(const MatrixType &A, AtomicType &atomic)
Constructor.
internal::nested< MatrixType >::type m_A
Reference to argument of matrix function.


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Mon Jun 10 2019 12:34:52