2012-06-11 18:52:26 +02:00
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
//
2013-02-06 11:30:33 +01:00
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
2012-06-11 18:52:26 +02:00
# ifndef EIGEN_ORDERING_H
# define EIGEN_ORDERING_H
namespace Eigen {
2012-09-10 12:41:26 +02:00
# include "Eigen_Colamd.h"
2012-07-06 13:34:06 +02:00
namespace internal {
2012-06-13 18:26:05 +02:00
2013-01-12 11:56:56 +01:00
/** \internal
* \ ingroup OrderingMethods_Module
* \ returns the symmetric pattern A ^ T + A from the input matrix A .
* FIXME : The values should not be considered here
*/
template < typename MatrixType >
void ordering_helper_at_plus_a ( const MatrixType & mat , MatrixType & symmat )
{
MatrixType C ;
C = mat . transpose ( ) ; // NOTE: Could be costly
for ( int i = 0 ; i < C . rows ( ) ; i + + )
{
for ( typename MatrixType : : InnerIterator it ( C , i ) ; it ; + + it )
it . valueRef ( ) = 0.0 ;
}
symmat = C + mat ;
}
2012-06-11 18:52:26 +02:00
2012-07-06 13:34:06 +02:00
}
2013-02-06 11:30:33 +01:00
# ifndef EIGEN_MPL2_ONLY
2013-01-12 11:56:56 +01:00
/** \ingroup OrderingMethods_Module
* \ class AMDOrdering
*
* Functor computing the \ em approximate \ em minimum \ em degree ordering
* If the matrix is not structurally symmetric , an ordering of A ^ T + A is computed
* \ tparam Index The type of indices of the matrix
* \ sa COLAMDOrdering
*/
2012-07-06 13:34:06 +02:00
template < typename Index >
class AMDOrdering
2012-06-11 18:52:26 +02:00
{
public :
2012-06-13 18:26:05 +02:00
typedef PermutationMatrix < Dynamic , Dynamic , Index > PermutationType ;
2012-07-06 13:34:06 +02:00
2012-07-06 20:18:16 +02:00
/** Compute the permutation vector from a sparse matrix
* This routine is much faster if the input matrix is column - major
*/
2012-07-06 13:34:06 +02:00
template < typename MatrixType >
void operator ( ) ( const MatrixType & mat , PermutationType & perm )
2012-06-11 18:52:26 +02:00
{
// Compute the symmetric pattern
2012-07-06 13:34:06 +02:00
SparseMatrix < typename MatrixType : : Scalar , ColMajor , Index > symm ;
internal : : ordering_helper_at_plus_a ( mat , symm ) ;
2012-06-11 18:52:26 +02:00
// Call the AMD routine
2012-07-06 13:34:06 +02:00
//m_mat.prune(keep_diag());
internal : : minimum_degree_ordering ( symm , perm ) ;
2012-06-11 18:52:26 +02:00
}
2012-07-06 13:34:06 +02:00
2012-07-06 20:18:16 +02:00
/** Compute the permutation with a selfadjoint matrix */
2012-06-11 18:52:26 +02:00
template < typename SrcType , unsigned int SrcUpLo >
2012-07-06 13:34:06 +02:00
void operator ( ) ( const SparseSelfAdjointView < SrcType , SrcUpLo > & mat , PermutationType & perm )
{
2012-12-07 15:32:04 +01:00
SparseMatrix < typename SrcType : : Scalar , ColMajor , Index > C ; C = mat ;
2012-06-11 18:52:26 +02:00
// Call the AMD routine
2012-07-06 13:34:06 +02:00
// m_mat.prune(keep_diag()); //Remove the diagonal elements
internal : : minimum_degree_ordering ( C , perm ) ;
2012-06-11 18:52:26 +02:00
}
2012-06-13 18:26:05 +02:00
} ;
2013-02-06 11:30:33 +01:00
# endif // EIGEN_MPL2_ONLY
2013-01-12 11:56:56 +01:00
/** \ingroup OrderingMethods_Module
* \ class NaturalOrdering
*
* Functor computing the natural ordering ( identity )
*
* \ note Returns an empty permutation matrix
* \ tparam Index The type of indices of the matrix
*/
2015-03-09 14:33:15 +01:00
template < typename StorageIndex >
2012-07-06 20:18:16 +02:00
class NaturalOrdering
{
public :
2015-03-09 14:33:15 +01:00
typedef PermutationMatrix < Dynamic , Dynamic , StorageIndex > PermutationType ;
2012-07-06 20:18:16 +02:00
/** Compute the permutation vector from a column-major sparse matrix */
template < typename MatrixType >
2012-12-07 15:32:04 +01:00
void operator ( ) ( const MatrixType & /*mat*/ , PermutationType & perm )
2012-07-06 20:18:16 +02:00
{
perm . resize ( 0 ) ;
}
} ;
2012-06-13 18:26:05 +02:00
2013-01-12 11:56:56 +01:00
/** \ingroup OrderingMethods_Module
* \ class COLAMDOrdering
*
* Functor computing the \ em column \ em approximate \ em minimum \ em degree ordering
2014-06-20 14:43:47 +02:00
* The matrix should be in column - major and \ b compressed format ( see SparseMatrix : : makeCompressed ( ) ) .
2013-01-12 11:56:56 +01:00
*/
2015-02-16 13:19:05 +01:00
template < typename StorageIndex >
2012-07-18 16:59:00 +02:00
class COLAMDOrdering
{
public :
2015-02-16 13:19:05 +01:00
typedef PermutationMatrix < Dynamic , Dynamic , StorageIndex > PermutationType ;
typedef Matrix < StorageIndex , Dynamic , 1 > IndexVector ;
2013-01-12 11:56:56 +01:00
2014-06-20 14:43:47 +02:00
/** Compute the permutation vector \a perm form the sparse matrix \a mat
* \ warning The input sparse matrix \ a mat must be in compressed mode ( see SparseMatrix : : makeCompressed ( ) ) .
*/
2012-07-18 16:59:00 +02:00
template < typename MatrixType >
void operator ( ) ( const MatrixType & mat , PermutationType & perm )
{
2014-06-20 14:43:47 +02:00
eigen_assert ( mat . isCompressed ( ) & & " COLAMDOrdering requires a sparse matrix in compressed mode. Call .makeCompressed() before passing it to COLAMDOrdering " ) ;
2015-02-16 13:19:05 +01:00
StorageIndex m = StorageIndex ( mat . rows ( ) ) ;
StorageIndex n = StorageIndex ( mat . cols ( ) ) ;
StorageIndex nnz = StorageIndex ( mat . nonZeros ( ) ) ;
2013-01-12 11:56:56 +01:00
// Get the recommended value of Alen to be used by colamd
2015-02-16 13:19:05 +01:00
StorageIndex Alen = internal : : colamd_recommended ( nnz , m , n ) ;
2013-01-12 11:56:56 +01:00
// Set the default parameters
double knobs [ COLAMD_KNOBS ] ;
2015-02-16 13:19:05 +01:00
StorageIndex stats [ COLAMD_STATS ] ;
2013-01-12 11:56:56 +01:00
internal : : colamd_set_defaults ( knobs ) ;
IndexVector p ( n + 1 ) , A ( Alen ) ;
2015-02-16 13:19:05 +01:00
for ( StorageIndex i = 0 ; i < = n ; i + + ) p ( i ) = mat . outerIndexPtr ( ) [ i ] ;
for ( StorageIndex i = 0 ; i < nnz ; i + + ) A ( i ) = mat . innerIndexPtr ( ) [ i ] ;
2013-01-12 11:56:56 +01:00
// Call Colamd routine to compute the ordering
2015-02-16 13:19:05 +01:00
StorageIndex info = internal : : colamd ( m , n , Alen , A . data ( ) , p . data ( ) , knobs , stats ) ;
2014-07-08 18:38:34 +02:00
EIGEN_UNUSED_VARIABLE ( info ) ;
2013-01-12 11:56:56 +01:00
eigen_assert ( info & & " COLAMD failed " ) ;
perm . resize ( n ) ;
2015-02-16 13:19:05 +01:00
for ( StorageIndex i = 0 ; i < n ; i + + ) perm . indices ( ) ( p ( i ) ) = i ;
2012-07-18 16:59:00 +02:00
}
} ;
2012-06-11 18:52:26 +02:00
} // end namespace Eigen
2013-01-12 11:56:56 +01:00
# endif