update
This commit is contained in:
		| @@ -0,0 +1,3 @@ | ||||
| #ifndef EIGEN_METISSUPPORT_MODULE_H | ||||
| #error "Please include Eigen/MetisSupport instead of including headers inside the src directory directly." | ||||
| #endif | ||||
| @@ -0,0 +1,125 @@ | ||||
| // 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> | ||||
| // | ||||
| // 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/. | ||||
| #ifndef METIS_SUPPORT_H | ||||
| #define METIS_SUPPORT_H | ||||
|  | ||||
| // IWYU pragma: private | ||||
| #include "./InternalHeaderCheck.h" | ||||
|  | ||||
| namespace Eigen { | ||||
| /** | ||||
|  * Get the fill-reducing ordering from the METIS package | ||||
|  * | ||||
|  * If A is the original matrix and Ap is the permuted matrix, | ||||
|  * the fill-reducing permutation is defined as follows : | ||||
|  * Row (column) i of A is the matperm(i) row (column) of Ap. | ||||
|  * WARNING: As computed by METIS, this corresponds to the vector iperm (instead of perm) | ||||
|  */ | ||||
| template <typename StorageIndex> | ||||
| class MetisOrdering { | ||||
|  public: | ||||
|   typedef PermutationMatrix<Dynamic, Dynamic, StorageIndex> PermutationType; | ||||
|   typedef Matrix<StorageIndex, Dynamic, 1> IndexVector; | ||||
|  | ||||
|   template <typename MatrixType> | ||||
|   void get_symmetrized_graph(const MatrixType& A) { | ||||
|     Index m = A.cols(); | ||||
|     eigen_assert((A.rows() == A.cols()) && "ONLY FOR SQUARED MATRICES"); | ||||
|     // Get the transpose of the input matrix | ||||
|     MatrixType At = A.transpose(); | ||||
|     // Get the number of nonzeros elements in each row/col of At+A | ||||
|     Index TotNz = 0; | ||||
|     IndexVector visited(m); | ||||
|     visited.setConstant(-1); | ||||
|     for (StorageIndex j = 0; j < m; j++) { | ||||
|       // Compute the union structure of of A(j,:) and At(j,:) | ||||
|       visited(j) = j;  // Do not include the diagonal element | ||||
|       // Get the nonzeros in row/column j of A | ||||
|       for (typename MatrixType::InnerIterator it(A, j); it; ++it) { | ||||
|         Index idx = it.index();  // Get the row index (for column major) or column index (for row major) | ||||
|         if (visited(idx) != j) { | ||||
|           visited(idx) = j; | ||||
|           ++TotNz; | ||||
|         } | ||||
|       } | ||||
|       // Get the nonzeros in row/column j of At | ||||
|       for (typename MatrixType::InnerIterator it(At, j); it; ++it) { | ||||
|         Index idx = it.index(); | ||||
|         if (visited(idx) != j) { | ||||
|           visited(idx) = j; | ||||
|           ++TotNz; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     // Reserve place for A + At | ||||
|     m_indexPtr.resize(m + 1); | ||||
|     m_innerIndices.resize(TotNz); | ||||
|  | ||||
|     // Now compute the real adjacency list of each column/row | ||||
|     visited.setConstant(-1); | ||||
|     StorageIndex CurNz = 0; | ||||
|     for (StorageIndex j = 0; j < m; j++) { | ||||
|       m_indexPtr(j) = CurNz; | ||||
|  | ||||
|       visited(j) = j;  // Do not include the diagonal element | ||||
|       // Add the pattern of row/column j of A to A+At | ||||
|       for (typename MatrixType::InnerIterator it(A, j); it; ++it) { | ||||
|         StorageIndex idx = it.index();  // Get the row index (for column major) or column index (for row major) | ||||
|         if (visited(idx) != j) { | ||||
|           visited(idx) = j; | ||||
|           m_innerIndices(CurNz) = idx; | ||||
|           CurNz++; | ||||
|         } | ||||
|       } | ||||
|       // Add the pattern of row/column j of At to A+At | ||||
|       for (typename MatrixType::InnerIterator it(At, j); it; ++it) { | ||||
|         StorageIndex idx = it.index(); | ||||
|         if (visited(idx) != j) { | ||||
|           visited(idx) = j; | ||||
|           m_innerIndices(CurNz) = idx; | ||||
|           ++CurNz; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     m_indexPtr(m) = CurNz; | ||||
|   } | ||||
|  | ||||
|   template <typename MatrixType> | ||||
|   void operator()(const MatrixType& A, PermutationType& matperm) { | ||||
|     StorageIndex m = internal::convert_index<StorageIndex>( | ||||
|         A.cols());  // must be StorageIndex, because it is passed by address to METIS | ||||
|     IndexVector perm(m), iperm(m); | ||||
|     // First, symmetrize the matrix graph. | ||||
|     get_symmetrized_graph(A); | ||||
|     int output_error; | ||||
|  | ||||
|     // Call the fill-reducing routine from METIS | ||||
|     output_error = METIS_NodeND(&m, m_indexPtr.data(), m_innerIndices.data(), NULL, NULL, perm.data(), iperm.data()); | ||||
|  | ||||
|     if (output_error != METIS_OK) { | ||||
|       // FIXME The ordering interface should define a class of possible errors | ||||
|       std::cerr << "ERROR WHILE CALLING THE METIS PACKAGE \n"; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     // Get the fill-reducing permutation | ||||
|     // NOTE:  If Ap is the permuted matrix then perm and iperm vectors are defined as follows | ||||
|     // Row (column) i of Ap is the perm(i) row(column) of A, and row (column) i of A is the iperm(i) row(column) of Ap | ||||
|  | ||||
|     matperm.resize(m); | ||||
|     for (int j = 0; j < m; j++) matperm.indices()(iperm(j)) = j; | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
|   IndexVector m_indexPtr;      // Pointer to the adjacenccy list of each row/column | ||||
|   IndexVector m_innerIndices;  // Adjacency list | ||||
| }; | ||||
|  | ||||
| }  // namespace Eigen | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user