xref: /aosp_15_r20/external/eigen/Eigen/src/OrderingMethods/Ordering.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
1*bf2c3715SXin Li 
2*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library
3*bf2c3715SXin Li // for linear algebra.
4*bf2c3715SXin Li //
5*bf2c3715SXin Li // Copyright (C) 2012  Désiré Nuentsa-Wakam <[email protected]>
6*bf2c3715SXin Li //
7*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla
8*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed
9*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10*bf2c3715SXin Li 
11*bf2c3715SXin Li #ifndef EIGEN_ORDERING_H
12*bf2c3715SXin Li #define EIGEN_ORDERING_H
13*bf2c3715SXin Li 
14*bf2c3715SXin Li namespace Eigen {
15*bf2c3715SXin Li 
16*bf2c3715SXin Li #include "Eigen_Colamd.h"
17*bf2c3715SXin Li 
18*bf2c3715SXin Li namespace internal {
19*bf2c3715SXin Li 
20*bf2c3715SXin Li /** \internal
21*bf2c3715SXin Li   * \ingroup OrderingMethods_Module
22*bf2c3715SXin Li   * \param[in] A the input non-symmetric matrix
23*bf2c3715SXin Li   * \param[out] symmat the symmetric pattern A^T+A from the input matrix \a A.
24*bf2c3715SXin Li   * FIXME: The values should not be considered here
25*bf2c3715SXin Li   */
26*bf2c3715SXin Li template<typename MatrixType>
ordering_helper_at_plus_a(const MatrixType & A,MatrixType & symmat)27*bf2c3715SXin Li void ordering_helper_at_plus_a(const MatrixType& A, MatrixType& symmat)
28*bf2c3715SXin Li {
29*bf2c3715SXin Li   MatrixType C;
30*bf2c3715SXin Li   C = A.transpose(); // NOTE: Could be  costly
31*bf2c3715SXin Li   for (int i = 0; i < C.rows(); i++)
32*bf2c3715SXin Li   {
33*bf2c3715SXin Li       for (typename MatrixType::InnerIterator it(C, i); it; ++it)
34*bf2c3715SXin Li         it.valueRef() = typename MatrixType::Scalar(0);
35*bf2c3715SXin Li   }
36*bf2c3715SXin Li   symmat = C + A;
37*bf2c3715SXin Li }
38*bf2c3715SXin Li 
39*bf2c3715SXin Li }
40*bf2c3715SXin Li 
41*bf2c3715SXin Li /** \ingroup OrderingMethods_Module
42*bf2c3715SXin Li   * \class AMDOrdering
43*bf2c3715SXin Li   *
44*bf2c3715SXin Li   * Functor computing the \em approximate \em minimum \em degree ordering
45*bf2c3715SXin Li   * If the matrix is not structurally symmetric, an ordering of A^T+A is computed
46*bf2c3715SXin Li   * \tparam  StorageIndex The type of indices of the matrix
47*bf2c3715SXin Li   * \sa COLAMDOrdering
48*bf2c3715SXin Li   */
49*bf2c3715SXin Li template <typename StorageIndex>
50*bf2c3715SXin Li class AMDOrdering
51*bf2c3715SXin Li {
52*bf2c3715SXin Li   public:
53*bf2c3715SXin Li     typedef PermutationMatrix<Dynamic, Dynamic, StorageIndex> PermutationType;
54*bf2c3715SXin Li 
55*bf2c3715SXin Li     /** Compute the permutation vector from a sparse matrix
56*bf2c3715SXin Li      * This routine is much faster if the input matrix is column-major
57*bf2c3715SXin Li      */
58*bf2c3715SXin Li     template <typename MatrixType>
operator()59*bf2c3715SXin Li     void operator()(const MatrixType& mat, PermutationType& perm)
60*bf2c3715SXin Li     {
61*bf2c3715SXin Li       // Compute the symmetric pattern
62*bf2c3715SXin Li       SparseMatrix<typename MatrixType::Scalar, ColMajor, StorageIndex> symm;
63*bf2c3715SXin Li       internal::ordering_helper_at_plus_a(mat,symm);
64*bf2c3715SXin Li 
65*bf2c3715SXin Li       // Call the AMD routine
66*bf2c3715SXin Li       //m_mat.prune(keep_diag());
67*bf2c3715SXin Li       internal::minimum_degree_ordering(symm, perm);
68*bf2c3715SXin Li     }
69*bf2c3715SXin Li 
70*bf2c3715SXin Li     /** Compute the permutation with a selfadjoint matrix */
71*bf2c3715SXin Li     template <typename SrcType, unsigned int SrcUpLo>
operator()72*bf2c3715SXin Li     void operator()(const SparseSelfAdjointView<SrcType, SrcUpLo>& mat, PermutationType& perm)
73*bf2c3715SXin Li     {
74*bf2c3715SXin Li       SparseMatrix<typename SrcType::Scalar, ColMajor, StorageIndex> C; C = mat;
75*bf2c3715SXin Li 
76*bf2c3715SXin Li       // Call the AMD routine
77*bf2c3715SXin Li       // m_mat.prune(keep_diag()); //Remove the diagonal elements
78*bf2c3715SXin Li       internal::minimum_degree_ordering(C, perm);
79*bf2c3715SXin Li     }
80*bf2c3715SXin Li };
81*bf2c3715SXin Li 
82*bf2c3715SXin Li /** \ingroup OrderingMethods_Module
83*bf2c3715SXin Li   * \class NaturalOrdering
84*bf2c3715SXin Li   *
85*bf2c3715SXin Li   * Functor computing the natural ordering (identity)
86*bf2c3715SXin Li   *
87*bf2c3715SXin Li   * \note Returns an empty permutation matrix
88*bf2c3715SXin Li   * \tparam  StorageIndex The type of indices of the matrix
89*bf2c3715SXin Li   */
90*bf2c3715SXin Li template <typename StorageIndex>
91*bf2c3715SXin Li class NaturalOrdering
92*bf2c3715SXin Li {
93*bf2c3715SXin Li   public:
94*bf2c3715SXin Li     typedef PermutationMatrix<Dynamic, Dynamic, StorageIndex> PermutationType;
95*bf2c3715SXin Li 
96*bf2c3715SXin Li     /** Compute the permutation vector from a column-major sparse matrix */
97*bf2c3715SXin Li     template <typename MatrixType>
operator()98*bf2c3715SXin Li     void operator()(const MatrixType& /*mat*/, PermutationType& perm)
99*bf2c3715SXin Li     {
100*bf2c3715SXin Li       perm.resize(0);
101*bf2c3715SXin Li     }
102*bf2c3715SXin Li 
103*bf2c3715SXin Li };
104*bf2c3715SXin Li 
105*bf2c3715SXin Li /** \ingroup OrderingMethods_Module
106*bf2c3715SXin Li   * \class COLAMDOrdering
107*bf2c3715SXin Li   *
108*bf2c3715SXin Li   * \tparam  StorageIndex The type of indices of the matrix
109*bf2c3715SXin Li   *
110*bf2c3715SXin Li   * Functor computing the \em column \em approximate \em minimum \em degree ordering
111*bf2c3715SXin Li   * The matrix should be in column-major and \b compressed format (see SparseMatrix::makeCompressed()).
112*bf2c3715SXin Li   */
113*bf2c3715SXin Li template<typename StorageIndex>
114*bf2c3715SXin Li class COLAMDOrdering
115*bf2c3715SXin Li {
116*bf2c3715SXin Li   public:
117*bf2c3715SXin Li     typedef PermutationMatrix<Dynamic, Dynamic, StorageIndex> PermutationType;
118*bf2c3715SXin Li     typedef Matrix<StorageIndex, Dynamic, 1> IndexVector;
119*bf2c3715SXin Li 
120*bf2c3715SXin Li     /** Compute the permutation vector \a perm form the sparse matrix \a mat
121*bf2c3715SXin Li       * \warning The input sparse matrix \a mat must be in compressed mode (see SparseMatrix::makeCompressed()).
122*bf2c3715SXin Li       */
123*bf2c3715SXin Li     template <typename MatrixType>
operator()124*bf2c3715SXin Li     void operator() (const MatrixType& mat, PermutationType& perm)
125*bf2c3715SXin Li     {
126*bf2c3715SXin Li       eigen_assert(mat.isCompressed() && "COLAMDOrdering requires a sparse matrix in compressed mode. Call .makeCompressed() before passing it to COLAMDOrdering");
127*bf2c3715SXin Li 
128*bf2c3715SXin Li       StorageIndex m = StorageIndex(mat.rows());
129*bf2c3715SXin Li       StorageIndex n = StorageIndex(mat.cols());
130*bf2c3715SXin Li       StorageIndex nnz = StorageIndex(mat.nonZeros());
131*bf2c3715SXin Li       // Get the recommended value of Alen to be used by colamd
132*bf2c3715SXin Li       StorageIndex Alen = internal::Colamd::recommended(nnz, m, n);
133*bf2c3715SXin Li       // Set the default parameters
134*bf2c3715SXin Li       double knobs [internal::Colamd::NKnobs];
135*bf2c3715SXin Li       StorageIndex stats [internal::Colamd::NStats];
136*bf2c3715SXin Li       internal::Colamd::set_defaults(knobs);
137*bf2c3715SXin Li 
138*bf2c3715SXin Li       IndexVector p(n+1), A(Alen);
139*bf2c3715SXin Li       for(StorageIndex i=0; i <= n; i++)   p(i) = mat.outerIndexPtr()[i];
140*bf2c3715SXin Li       for(StorageIndex i=0; i < nnz; i++)  A(i) = mat.innerIndexPtr()[i];
141*bf2c3715SXin Li       // Call Colamd routine to compute the ordering
142*bf2c3715SXin Li       StorageIndex info = internal::Colamd::compute_ordering(m, n, Alen, A.data(), p.data(), knobs, stats);
143*bf2c3715SXin Li       EIGEN_UNUSED_VARIABLE(info);
144*bf2c3715SXin Li       eigen_assert( info && "COLAMD failed " );
145*bf2c3715SXin Li 
146*bf2c3715SXin Li       perm.resize(n);
147*bf2c3715SXin Li       for (StorageIndex i = 0; i < n; i++) perm.indices()(p(i)) = i;
148*bf2c3715SXin Li     }
149*bf2c3715SXin Li };
150*bf2c3715SXin Li 
151*bf2c3715SXin Li } // end namespace Eigen
152*bf2c3715SXin Li 
153*bf2c3715SXin Li #endif
154