STK++ 0.9.13
STK::SymEigen< SquareArray > Class Template Reference

The class SymEigen compute the eigenvalue Decomposition of a symmetric ArrayXX. More...

#include <STK_SymEigen.h>

Inheritance diagram for STK::SymEigen< SquareArray >:
Inheritance graph

Public Types

typedef ISymEigen< SymEigen< SquareArray > > Base
 

Public Member Functions

 SymEigen ()
 Default Constructor.
 
 SymEigen (SquareArray const &data, bool ref=false)
 Constructor.
 
template<class Derived >
 SymEigen (ExprBase< Derived > const &data)
 constructor.
 
 SymEigen (SymEigen const &S)
 Copy constructor.
 
virtual ~SymEigen ()
 virtual destructor
 
bool runImpl ()
 Diagonalization of eigenVectors_.
 
SymEigenoperator= (const SymEigen &S)
 Operator = : overwrite the SymEigen with S.
 
 SymEigen (CSquareX const &data, bool ref)
 
- Public Member Functions inherited from STK::ISymEigen< SymEigen< SquareArray > >
 ~ISymEigen ()
 virtual destructor
 
ISymEigenoperator= (ISymEigen const &eigen)
 Operator = : overwrite the ISymEigen with eigen.
 
Range constrange () const
 
Type constnorm () const
 
int constrank () const
 
Type constdet () const
 
Type consttrace () const
 
CArraySquare< Type, size_ > constrotation () const
 
CArraySquare< Type, size_ > consteigenVectors () const
 
CArrayVector< Type, size_ > consteigenValues () const
 
void setData (ExprBase< OtherDerived > const &data)
 overloading of setData.
 
ArraySquareginv (ArraySquare &res) const
 Compute the generalized inverse of the symmetric matrix and put the result in res.
 
ArraySquareginvsqrt (ArraySquare &res) const
 Compute the generalized square root inverse of the symmetric matrix and put the result in res.
 
ArraySquaregsqrt (ArraySquare &res) const
 Compute the square root of the symmetric matrix and put the result in res.
 
virtual bool run ()
 Find the eigenvalues and eigenvectors of the matrix.
 
- Public Member Functions inherited from STK::IRunnerBase
String consterror () const
 get the last error message.
 
- Public Member Functions inherited from STK::IRecursiveTemplate< Derived >
Derived & asDerived ()
 static cast : return a reference of this with a cast to the derived class.
 
Derived constasDerived () const
 static cast : return a const reference of this with a cast to the derived class.
 
Derived * asPtrDerived ()
 static cast : return a ptr on a Derived of this with a cast to the derived class.
 
Derived constasPtrDerived () const
 static cast : return a ptr on a constant Derived of this with a cast to the derived class.
 
Derived * clone () const
 create a leaf using the copy constructor of the Derived class.
 
Derived * clone (bool isRef) const
 create a leaf using the copy constructor of the Derived class and a flag determining if the clone is a reference or not.
 

Private Member Functions

void tridiagonalize ()
 compute the tri-diagonalization of eigenVectors_
 
void compHouse ()
 compute the Householder matrix and P
 
void diagonalize ()
 computing the diagonalization of eigenValues_ and F_
 

Private Attributes

VectorX F_
 Temporary vector.
 

Additional Inherited Members

- Protected Types inherited from STK::ISymEigen< SymEigen< SquareArray > >
enum  
 
typedef IRunnerBase Base
 
typedef hidden::AlgebraTraits< SymEigen< SquareArray > >::SquareArray SquareArray
 
typedef hidden::Traits< SquareArray >::Type Type
 
- Protected Member Functions inherited from STK::ISymEigen< SymEigen< SquareArray > >
 ISymEigen ()
 Default constructor.
 
 ISymEigen (SquareArray const &data, bool ref=false)
 Constructor The original data set can be overwritten by the eigenvectors if it is stored in a CSquareXd.
 
 ISymEigen (ExprBase< OtherDerived > const &data)
 template constructor
 
 ISymEigen (ISymEigen const &eigen)
 Copy constructor.
 
void finalizeStep ()
 finalize the computation by computing the trace, rank, trace norm and determinant of the matrix.
 
- Protected Member Functions inherited from STK::IRunnerBase
 IRunnerBase ()
 default constructor
 
 IRunnerBase (IRunnerBase const &runner)
 copy constructor
 
virtual ~IRunnerBase ()
 destructor
 
virtual void update ()
 update the runner.
 
- Protected Member Functions inherited from STK::IRecursiveTemplate< Derived >
 IRecursiveTemplate ()
 constructor.
 
 ~IRecursiveTemplate ()
 destructor.
 
- Protected Attributes inherited from STK::ISymEigen< SymEigen< SquareArray > >
Range range_
 range of the original data set.
 
Type trace_
 trace norm
 
Type norm_
 trace norm
 
int rank_
 rank
 
Type det_
 determinant
 
CArraySquare< Type, size_ > eigenVectors_
 Square matrix or the eigenvectors.
 
CArrayVector< Type, size_ > eigenValues_
 Array of the eigenvalues.
 
CVectorXi SupportEigenVectors_
 Array for the support of the eigenvectors.
 
- Protected Attributes inherited from STK::IRunnerBase
String msg_error_
 String with the last error message.
 
bool hasRun_
 true if run has been used, false otherwise
 

Detailed Description

template<class SquareArray>
class STK::SymEigen< SquareArray >

The class SymEigen compute the eigenvalue Decomposition of a symmetric ArrayXX.

The decomposition of a symmetric matrix require

  • Input: A symmetric matrix A of size (n,n)
  • Output:
    1. P Array of size (n,n).
    2. D Vector of dimension n
    3. $ A = PDP' $ The matrix A can be copied or overwritten by the class.

The 2-norm (operator norm) of the matrix is given. if the 2-norm is less than the arithmetic precision of the type Real, the rank is not full. Thus the user can be faced with a deficient rank matrix and with a norm and a determinant very small (but not exactly 0.0).

See also
STK::ISymEigen, STK::lapack::SymEigen

Definition at line 85 of file STK_SymEigen.h.

Member Typedef Documentation

◆ Base

Definition at line 88 of file STK_SymEigen.h.

Constructor & Destructor Documentation

◆ SymEigen() [1/5]

template<class SquareArray >
STK::SymEigen< SquareArray >::SymEigen ( )

Default Constructor.

Definition at line 144 of file STK_SymEigen.h.

144: Base() {}
ISymEigen< SymEigen< SquareArray > > Base

◆ SymEigen() [2/5]

template<class SquareArray >
STK::SymEigen< SquareArray >::SymEigen ( SquareArray const data,
bool  ref = false 
)

Constructor.

Parameters
datareference on a symmetric square matrix
reftrue if we overwrite the data set, false otherwise
Note
data can be a reference if and only if it is a CSquareX

Definition at line 150 of file STK_SymEigen.h.

151 : Base(data)
152{}

◆ SymEigen() [3/5]

template<class SquareArray >
template<class Derived >
STK::SymEigen< SquareArray >::SymEigen ( ExprBase< Derived > const data)

constructor.

Parameters
dataA reference on a symmetric expression matrix to decompose.

Definition at line 167 of file STK_SymEigen.h.

167: Base(data) {}

◆ SymEigen() [4/5]

template<class SquareArray >
STK::SymEigen< SquareArray >::SymEigen ( SymEigen< SquareArray > const S)

Copy constructor.

Parameters
Sthe EigenValue to copy

Definition at line 172 of file STK_SymEigen.h.

172: Base(S) {}

◆ ~SymEigen()

template<class SquareArray >
virtual STK::SymEigen< SquareArray >::~SymEigen ( )
inlinevirtual

virtual destructor

Definition at line 114 of file STK_SymEigen.h.

114{}

◆ SymEigen() [5/5]

STK::SymEigen< CSquareX >::SymEigen ( CSquareX const data,
bool  ref 
)
inline

Definition at line 158 of file STK_SymEigen.h.

159 : Base(data, ref)
160{}

Member Function Documentation

◆ compHouse()

template<class SquareArray >
void STK::SymEigen< SquareArray >::compHouse ( )
private

compute the Householder matrix and P

Definition at line 292 of file STK_SymEigen.h.

293{
294 // compute eigenVectors_
295 // iter0 is the column of the Householder vector
296 // iter is the current column to compute
297 for ( int iter0=range_.lastIdx()-1, iter=range_.lastIdx(), iter1=range_.lastIdx()+1
298 ; iter0>=range_.begin()
299 ; iter0--, iter--, iter1--)
300 {
301 // reference on the Householder vector
302 typename hidden::Traits<CSquareX>::Col v(eigenVectors_.col(Range(iter, range_.lastIdx(), 0), iter0));
303 // Get Beta
304 Real beta = v[iter];
305 if (beta)
306 {
307 // Compute Col iter -> eigenVectors_ e_{iter}= e_{iter}+ beta v
308 eigenVectors_(iter, iter) = 1.0 + beta /* *1.0 */;
309 for (int i=iter1; i<range_.end(); i++)
310 { eigenVectors_(i, iter) = beta * v[i];}
311
312 // Update the other Cols
313 for (int i=iter1; i<range_.end(); i++)
314 {
315 // compute beta*<v, eigenVectors_^i>
316 Real aux = 0.0;
317 for (int j=iter1; j<range_.end(); j++)
318 { aux += eigenVectors_(j, i) * v[j]; }
319 aux *= beta;
320 // range_.begin() row (iter)
321 eigenVectors_(iter, i) = aux;
322 // other rows
323 for (int j=iter1; j<range_.end(); j++)
324 { eigenVectors_(j, i) += aux * v[j];}
325 }
326 }
327 else // beta = 0, nothing to do
328 { eigenVectors_(iter,iter)=1.0;
329 for (int j=iter1; j<range_.end(); j++)
330 { eigenVectors_(iter, j) =0.0; eigenVectors_(j, iter) = 0.0;}
331 }
332 }
333 // range_.begin() row and range_.begin() col
335 for (int j=range_.begin()+1; j<range_.end(); j++)
336 { eigenVectors_(range_.begin(), j) = 0.0; eigenVectors_(j, range_.begin()) = 0.0;}
337}
hidden::CSlice< Derived, sizeRows_, 1 >::Result col(int j) const
implement the col operator using a reference on the column of the allocator
Range range_
range of the original data set.
CArraySquare< Type, size_ > eigenVectors_
Square matrix or the eigenvectors.
int begin() const
get the first index of the TRange.
Definition STK_Range.h:93
int lastIdx() const
get the last index of the TRange.
Definition STK_Range.h:313
int end() const
get the ending index of the TRange.
Definition STK_Range.h:299
double Real
STK fundamental type of Real values.
TRange< UnknownSize > Range
Definition STK_Range.h:59

◆ diagonalize()

template<class SquareArray >
void STK::SymEigen< SquareArray >::diagonalize ( )
private

computing the diagonalization of eigenValues_ and F_

Definition at line 341 of file STK_SymEigen.h.

342{
343 // Diagonalisation of eigenVectors_
344 for (int iend=range_.lastIdx(); iend>=range_.begin()+1; iend--)
345 {
346 int iter;
347 for (iter=0; iter<MAXITER; iter++) // fix the number of iterations max
348 {
349 // check cv for the last element
350 Real sum = std::abs(eigenValues_[iend]) + std::abs(eigenValues_[iend-1]);
351 // if the first element of the small subdiagonal
352 // is 0. we stop the QR iterations and increment iend
353 if (std::abs(F_[iend-1])+sum == sum)
354 { F_[iend-1] = 0.0 ; break;}
355 // look for a single small subdiagonal element to split the matrix
356 int ibeg = iend-1;
357 while (ibeg>range_.begin())
358 {
359 ibeg--;
360 // if a subdiagonal is zero, we get a sub matrix unreduced
361 //sum = std::abs(eigenValues_[ibeg])+std::abs(eigenValues_[ibeg+1]);
362 if (std::abs(F_[ibeg])+std::abs(eigenValues_[ibeg]) == std::abs(eigenValues_[ibeg]))
363 { F_[ibeg] = 0.; ibeg++; break;}
364 };
365 // QR rotations between the rows/cols ibeg et iend
366 // Computation of the Wilkinson's shift
367 Real aux = (eigenValues_[iend-1] - eigenValues_[iend])/(2.0 * F_[iend-1]);
368 // initialisation of the matrix of rotation
369 // y is the current F_[k-1],
370 Real y = eigenValues_[ibeg]-eigenValues_[iend] + F_[iend-1]/sign(aux, STK::norm(aux,1.0));
371 // z is the element to annulate
372 Real z = F_[ibeg];
373 // Fk is the temporary F_[k]
374 Real Fk = z;
375 // temporary DeltaD(k)
376 Real DeltaDk = 0.0;
377 // Index of the columns
378 int k,k1;
379 // Givens rotation to restore tridiaonal form
380 for (k=ibeg, k1=ibeg+1; k<iend; k++, k1++)
381 {
382 // underflow ? we have a tridiagonal form exit now
383 if (z == 0.0) { F_[k]=Fk; break;}
384 // Rotation columns (k,k+1)
385 F_[k-1] = (aux = STK::norm(y,z)); // compute final F_[k-1]
386 // compute cosinus and sinus
387 Real cosinus = y/aux, sinus = -z/aux;
388 Real Dk = eigenValues_[k] + DeltaDk; // compute current D[k]
389 Real aux1 = 2.0 * cosinus * Fk + sinus * (Dk - eigenValues_[k1]);
390 // compute DeltaD(k+1)
391 eigenValues_[k] = Dk - (DeltaDk = sinus * aux1); // compute eigenValues_[k]
392 y = cosinus*aux1 - Fk; // temporary F_[k]
393 Fk = cosinus * F_[k1]; // temporary F_[k+1]
394 z = -sinus * F_[k1]; // temporary z
395 // update eigenVectors_
396 rightGivens(eigenVectors_, k1, k, cosinus, sinus);
397 }
398 // k=iend if z!=0 and k<iend if z==0
399 eigenValues_[k] += DeltaDk ; F_[k-1] = y;
400 // restore F[ibeg-1]
401 F_[ibeg-1] = 0.;
402 } // iter
403 if (iter == MAXITER)
404 { this->msg_error_ = _T("Warning, max iteration reached in SymEigen::diagonalize()\n");}
405 // We have to sort the eigenvalues : we use a basic strategy
406 Real z = eigenValues_[iend]; // current value
407 for (int i=iend+1; i<eigenValues_.end(); i++)
408 { if (eigenValues_[i] > z) // if the ith eigenvalue is greater
409 { eigenValues_.swap(i-1, i); // swap the cols
410 eigenVectors_.swapCols(i-1, i);
411 }
412 else break;
413 } // end sort
414 } // iend
415 // sort first value
416 Real z = eigenValues_[range_.begin()]; // current value
417 for (int i=range_.begin()+1; i<eigenValues_.end(); i++)
418 { if (eigenValues_[i] > z) // if the ith eigenvalue is greater
419 {
420 eigenValues_.swap(i-1, i); // swap the cols
421 eigenVectors_.swapCols(i-1, i);
422 }
423 else break;
424 } // end sort
425 // clear auxiliary array
426 F_.clear();
427}
#define MAXITER
#define _T(x)
Let x unmodified.
void clear()
clear the object.
void swapCols(int pos1, int pos2)
void swap(int i, int j)
swap two elements: only for vectors an points.
String msg_error_
String with the last error message.
Definition STK_IRunner.h:96
CArrayVector< Type, size_ > eigenValues_
Array of the eigenvalues.
VectorX F_
Temporary vector.
void rightGivens(ArrayBase< TContainer2D > &M, int j1, int j2, typename TContainer2D::Type const &cosinus, typename TContainer2D::Type const &sinus)
Apply Givens rotation.
Definition STK_Givens.h:119
Arrays::SumOp< Lhs, Rhs >::result_type sum(Lhs const &lhs, Rhs const &rhs)
convenience function for summing two arrays
Type sign(Type const &x, Type const &y=Type(1))
template sign value sign(x) * y: Type should be an integral type
Definition STK_Misc.h:53
Real norm(Real const &x, Real const &y)
Computation of sqrt(x^2 + y^2) without underflow or overflow.
Definition STK_Misc.h:93

References _T, MAXITER, STK::IRunnerBase::msg_error_, STK::norm(), STK::rightGivens(), STK::sign(), and STK::sum().

◆ operator=()

template<class SquareArray >
SymEigen & STK::SymEigen< SquareArray >::operator= ( const SymEigen< SquareArray > &  S)
inline

Operator = : overwrite the SymEigen with S.

Parameters
SSymEigen to copy
Returns
a reference on this

Definition at line 124 of file STK_SymEigen.h.

125 {
127 return *this;
128 }
ISymEigen & operator=(ISymEigen const &eigen)
Operator = : overwrite the ISymEigen with eigen.

References STK::ISymEigen< SymEigen< SquareArray > >::operator=().

◆ runImpl()

template<class SquareArray >
bool STK::SymEigen< SquareArray >::runImpl ( )

Diagonalization of eigenVectors_.

Returns
true if no error occur, false otherwise

Definition at line 177 of file STK_SymEigen.h.

178{
179#ifdef STK_ALGEBRA_VERBOSE
180 stk_cout << _T("Entering in SymEigen::run()\n");
181#endif
182 try
183 {
184 // copy data
186 norm_ = 0.;
187 rank_ = 0;
188 det_ = 0.;
189#ifdef STK_ALGEBRA_VERBOSE
190 stk_cout << _T("calling SymEigen::tridiagonalize()\n");
191#endif
192 // tridiagonalize eigenVectors_
194#ifdef STK_ALGEBRA_VERBOSE
195 stk_cout << _T("calling SymEigen::compHouse()\n");
196#endif
197 // compute eigenVectors_
198 compHouse();
199#ifdef STK_ALGEBRA_VERBOSE
200 stk_cout << _T("calling SymEigen::diagonalize()\n");
201#endif
202 // Diagonalize
203 diagonalize();
204#ifdef STK_ALGEBRA_VERBOSE
205 stk_cout << _T("calling SymEigen::finalize()\n");
206#endif
207 // compute rank, norm and determinant
208 this->finalizeStep();
209 }
210 catch (Exception const& e)
211 {
212 this->msg_error_ = e.error();
213 return false;
214 }
215 return true;
216}
#define stk_cout
Standard stk output stream.
Derived & resize(Range const &I, Range const &J)
resize the Array.
void finalizeStep()
finalize the computation by computing the trace, rank, trace norm and determinant of the matrix.
void tridiagonalize()
compute the tri-diagonalization of eigenVectors_
void compHouse()
compute the Householder matrix and P
void diagonalize()
computing the diagonalization of eigenValues_ and F_

References _T, STK::Exception::error(), STK::IRegression< Array, Array, Weight >::finalizeStep(), STK::IRunnerBase::msg_error_, and stk_cout.

◆ tridiagonalize()

template<class SquareArray >
void STK::SymEigen< SquareArray >::tridiagonalize ( )
private

compute the tri-diagonalization of eigenVectors_

Definition at line 223 of file STK_SymEigen.h.

224{
225 // Upper diagonal values
227 F_.front() = 0.0; F_.back() =0.0;
228 // initial range of the Householder vectors
229 Range range1(Range(range_.begin()+1, range_.lastIdx(), 0));
230 Range range2(Range(range_.begin()+2, range_.lastIdx(), 0));
231 // Bidiagonalization of eigenVectors_
232 // loop on the cols and rows
233 for ( int i=range_.begin(), i1=range_.begin()+1, i2=range_.begin()+2; i<range_.lastIdx()
234 ; i++, i1++, i2++, range1.incFirst(1), range2.incFirst(1)
235 )
236 {
237 // ref on the current column iter in the range iter1:last
238 typename hidden::Traits<CSquareX>::Col v(eigenVectors_.col(range1, i));
239 // Compute Householder vector and get subdiagonal element
240 F_[i] = house(v);
241 // Save diagonal element
242 eigenValues_[i] = eigenVectors_(i,i);
243 // get beta
244 Real beta = v.front();
245 if (beta)
246 {
247 // ref on the current column iter1 in the range iter1:last
248 typename hidden::Traits<CSquareX>::Col M1(eigenVectors_.col(range1, i1));
249 // aux1 will contain <v,p>
250 Real aux1 = 0.0;
251 // apply left and right Householder to eigenVectors_
252 // compute D(iter1:range_.last_) = p and aux1 = <p,v>
253 // Computation of p_iter1 = beta * eigenVectors_ v using the lower part of eigenVectors_
254 // save p_iter1 in the unused part of eigenValues_ and compute p'v
255 aux1 += (eigenValues_[i1] = beta*(M1[i1] + M1.sub(range2).dot(v.sub(range2)))) /* *1.0 */;
256 // other cols
257 for (int k=i2; k<range_.end(); k++)
258 {
259 // Computation of p_i = beta * eigenVectors_ v using the lower part of eigenVectors_
260 // save p_i in the unusued part of eigenValues_ and compute p'v
261 Real aux = M1[k] /* *1.0 */;
262 for (int j=i2; j<=k; j++) { aux += eigenVectors_(k,j)*v[j];}
263 for (int j=k+1; j<range_.end(); j++) { aux += eigenVectors_(j,k)*v[j];}
264 // save p_i in the unusued part of eigenValues_ and compute p'v
265 aux1 += (eigenValues_[k] = beta*aux) * v[k];
266 }
267 // update diagonal element M_ii+= 2 v_i * q_i = 2* q_i (i=iter1)
268 // aux = q_iter1 and aux1 = beta*<p,v>/2 (we don't save aux in eigenValues_)
269 Real aux = (eigenValues_[i1] + (aux1 *= (beta/2.0)));
270 M1[i1] += 2.0*aux;
271 // update lower part: all rows
272 // compute q_i and update the lower part of eigenVectors_
273 for (int k=i2; k<range_.end(); k++)
274 {
275 // get q_i and save it in eigenValues_i=q_i = p_i + <p,v> * beta * v_i/2
276 eigenValues_[k] += aux1 * v[k];
277 // Compute eigenVectors_ + u q' + q u',
278 // update the row i, range_.begin() element
279 M1[k] += eigenValues_[k] /* *1.0 */+ v[k] * aux;
280 // update the row i: all cols under the diagonal
281 for (int j=i2; j<=k; j++)
282 eigenVectors_(k,j) += v[j] * eigenValues_[k] + v[k] * eigenValues_[j];
283 }
284 }
285 }
286 // Last col
288}
Derived & resize(Range const &I, Range const &J)
resize the array.
Real house(ArrayBase< Vector > &x)
Compute the Householder vector v of a vector x.

References STK::house().

Member Data Documentation

◆ F_

template<class SquareArray >
VectorX STK::SymEigen< SquareArray >::F_
private

Temporary vector.

Values of the subdiagonal.

Definition at line 132 of file STK_SymEigen.h.


The documentation for this class was generated from the following file: