From bf22a49504749af3a1b33faa21fd11346b9e5aae Mon Sep 17 00:00:00 2001 From: Andrew Melim Date: Mon, 13 Oct 2014 13:15:05 -0400 Subject: [PATCH] Working ordering format for Metis_NodeND --- gtsam/inference/MetisIndex-inl.h | 59 +++++++++++++++++++ gtsam/inference/MetisIndex.cpp | 0 gtsam/inference/MetisIndex.h | 78 ++++++++++++++++++++++++++ gtsam/inference/Ordering.cpp | 13 ++++- gtsam/inference/Ordering.h | 9 ++- gtsam/inference/tests/testOrdering.cpp | 42 +++++++++++++- 6 files changed, 196 insertions(+), 5 deletions(-) create mode 100644 gtsam/inference/MetisIndex-inl.h create mode 100644 gtsam/inference/MetisIndex.cpp create mode 100644 gtsam/inference/MetisIndex.h diff --git a/gtsam/inference/MetisIndex-inl.h b/gtsam/inference/MetisIndex-inl.h new file mode 100644 index 000000000..35d8c00fc --- /dev/null +++ b/gtsam/inference/MetisIndex-inl.h @@ -0,0 +1,59 @@ +/* ---------------------------------------------------------------------------- + +* GTSAM Copyright 2010, Georgia Tech Research Corporation, +* Atlanta, Georgia 30332-0415 +* All Rights Reserved +* Authors: Frank Dellaert, et al. (see THANKS for the full author list) + +* See LICENSE for the license information + +* -------------------------------------------------------------------------- */ + +/** +* @file MetisIndex-inl.h +* @author Andrew Melim +* @date Oct. 10, 2014 +*/ + +#include +#include + +namespace gtsam { + + MetisIndex::~MetisIndex(){} + + std::vector MetisIndex::xadj() const { return xadj_; } + std::vector MetisIndex::adj() const { return adj_; } + + /* ************************************************************************* */ + template + void MetisIndex::augment(const FactorGraph& factors) + { + std::map > adjMap; + std::map >::iterator adjMapIt; + + /* ********** Convert to CSR format ********** */ + // Assuming that vertex numbering starts from 0 (C style), + // then the adjacency list of vertex i is stored in array adjncy + // starting at index xadj[i] and ending at(but not including) + // index xadj[i + 1](i.e., adjncy[xadj[i]] through + // and including adjncy[xadj[i + 1] - 1]). + for (size_t i = 0; i < factors.size(); i++){ + if (factors[i]) + BOOST_FOREACH(const Key& k1, *factors[i]) + BOOST_FOREACH(const Key& k2, *factors[i]) + if (k1 != k2) + adjMap[k1].insert(adjMap[k1].end(), k2); // Insert at the end + } + + + xadj_.push_back(0);// Always set the first index to zero + for (adjMapIt = adjMap.begin(); adjMapIt != adjMap.end(); ++adjMapIt) { + vector temp; + copy(adjMapIt->second.begin(), adjMapIt->second.end(), std::back_inserter(temp)); + adj_.insert(adj_.end(), temp.begin(), temp.end()); + //adj_.push_back(temp); + xadj_.push_back(adj_.size()); + } + } +} diff --git a/gtsam/inference/MetisIndex.cpp b/gtsam/inference/MetisIndex.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/gtsam/inference/MetisIndex.h b/gtsam/inference/MetisIndex.h new file mode 100644 index 000000000..57b999d7d --- /dev/null +++ b/gtsam/inference/MetisIndex.h @@ -0,0 +1,78 @@ +/* ---------------------------------------------------------------------------- + +* GTSAM Copyright 2010, Georgia Tech Research Corporation, +* Atlanta, Georgia 30332-0415 +* All Rights Reserved +* Authors: Frank Dellaert, et al. (see THANKS for the full author list) + +* See LICENSE for the license information + +* -------------------------------------------------------------------------- */ + + +/** +* @file MetisIndex.h +* @author Andrew Melim +* @date Oct. 10, 2014 +*/ + +#pragma once + +#include +#include + +#include +#include +#include +#include + +namespace gtsam { + /** + * The MetisIndex class converts a factor graph into the Compressed Sparse Row format for use in + * METIS algorithms. Specifically, two vectors store the adjacency structure of the graph. It is built + * fromt a factor graph prior to elimination, and stores the list of factors + * that involve each variable. + * \nosubgrouping + */ +class GTSAM_EXPORT MetisIndex +{ +public: + typedef boost::shared_ptr shared_ptr; + +private: + FastVector xadj_; // Index of node's adjacency list in adj + FastVector adj_; // Stores ajacency lists of all nodes, appended into a single vector + size_t nFactors_; // Number of factors in the original factor graph + size_t nValues_; // + +public: + /// @name Standard Constructors + /// @{ + + /** Default constructor, creates empty MetisIndex */ + MetisIndex() : nFactors_(0), nValues_(0) {} + + template + MetisIndex(const FG& factorGraph) : nFactors_(0), nValues_(0) { + augment(factorGraph); } + + ~MetisIndex(); + /// @} + /// @name Advanced Interface + /// @{ + + /** + * Augment the variable index with new factors. This can be used when + * solving problems incrementally. + */ + template + void augment(const FactorGraph& factors); + + std::vector xadj() const; + std::vector adj() const; + + /// @} +}; +} + +#include diff --git a/gtsam/inference/Ordering.cpp b/gtsam/inference/Ordering.cpp index 7d3d7cc0b..33cf2092d 100644 --- a/gtsam/inference/Ordering.cpp +++ b/gtsam/inference/Ordering.cpp @@ -197,10 +197,21 @@ namespace gtsam { return Ordering::COLAMDConstrained(variableIndex, cmember); } + /* ************************************************************************* */ - Ordering Ordering::METIS(const VariableIndex& variableIndex) + template + Ordering Ordering::METIS(const FactorGraph& graph) { gttic(Ordering_METIS); + // First develop the adjacency matrix for the + // graph as described in Section 5.5 of the METIS manual + // CSR Format + // xadj is of size n+1 + // metis vars + + + //METIS_NodeND(graph.keys().size(), xadj, adj); + } /* ************************************************************************* */ diff --git a/gtsam/inference/Ordering.h b/gtsam/inference/Ordering.h index 1260c15fb..fad9fe9e9 100644 --- a/gtsam/inference/Ordering.h +++ b/gtsam/inference/Ordering.h @@ -146,13 +146,15 @@ namespace gtsam { return Ordering(keys); } + /// METIS Formatting function + template + static GTSAM_EXPORT void CSRFormat(std::vector& xadj, std::vector& adj, const FactorGraph& graph); /// Compute an ordering determined by METIS from a VariableIndex - static GTSAM_EXPORT Ordering METIS(const VariableIndex& variableIndex); + //static GTSAM_EXPORT Ordering METIS(const VariableIndex& variableIndex); template - static Ordering METIS(const FactorGraph& graph){ - return METIS(VariableIndex(graph)); } + static GTSAM_EXPORT Ordering METIS(const FactorGraph& graph); /// @} @@ -169,6 +171,7 @@ namespace gtsam { static GTSAM_EXPORT Ordering COLAMDConstrained( const VariableIndex& variableIndex, std::vector& cmember); + /** Serialization function */ friend class boost::serialization::access; template diff --git a/gtsam/inference/tests/testOrdering.cpp b/gtsam/inference/tests/testOrdering.cpp index 5fcac15b4..252106f88 100644 --- a/gtsam/inference/tests/testOrdering.cpp +++ b/gtsam/inference/tests/testOrdering.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -78,7 +79,46 @@ TEST(Ordering, grouped_constrained_ordering) { } /* ************************************************************************* */ -TEST(Ordering, metis_ordering) { +TEST(Ordering, csr_format) { + + + // Example in METIS manual + SymbolicFactorGraph sfg; + sfg.push_factor(0, 1); + sfg.push_factor(1, 2); + sfg.push_factor(2, 3); + sfg.push_factor(3, 4); + sfg.push_factor(5, 6); + sfg.push_factor(6, 7); + sfg.push_factor(7, 8); + sfg.push_factor(8, 9); + sfg.push_factor(10, 11); + sfg.push_factor(11, 12); + sfg.push_factor(12, 13); + sfg.push_factor(13, 14); + + sfg.push_factor(0, 5); + sfg.push_factor(5, 10); + sfg.push_factor(1, 6); + sfg.push_factor(6, 11); + sfg.push_factor(2, 7); + sfg.push_factor(7, 12); + sfg.push_factor(3, 8); + sfg.push_factor(8, 13); + sfg.push_factor(4, 9); + sfg.push_factor(9, 14); + + MetisIndex mi(sfg); + + vector xadjExpected{ 0, 2, 5, 8, 11, 13, 16, 20, 24, 28, 31, 33, 36, 39, 42, 44}; + vector adjExpected{ 1, 5, 0, 2, 6, 1, 3, 7, 2, 4, 8, 3, 9, 0, 6, 10, 1, 5, 7, 11, + 2, 6, 8, 12, 3, 7, 9, 13, 4, 8, 14, 5, 11, 6, 10, 12, 7, 11, + 13, 8, 12, 14, 9, 13 }; + + EXPECT(xadjExpected == mi.xadj()); + EXPECT(adjExpected.size() == mi.adj().size()); + EXPECT( adjExpected == mi.adj()); + }