diff --git a/.cproject b/.cproject index f41da3e32..ef7985e39 100644 --- a/.cproject +++ b/.cproject @@ -317,6 +317,7 @@ make + clean true true @@ -476,7 +477,6 @@ make - testBayesTree.run true false @@ -484,6 +484,7 @@ make + testSymbolicBayesNet.run true false @@ -491,7 +492,6 @@ make - testSymbolicFactorGraph.run true false @@ -683,7 +683,6 @@ make - testGraph.run true false @@ -739,6 +738,7 @@ make + testSimulated2D.run true false @@ -786,7 +786,6 @@ make - testErrors.run true false @@ -794,7 +793,6 @@ make - testDSF.run true true @@ -810,7 +808,6 @@ make - testConstraintOptimizer.run true true @@ -818,6 +815,7 @@ make + testBTree.run true true @@ -825,12 +823,19 @@ make - testSimulated2DOriented.run true false true + +make + +testDSFVector.run +true +true +true + make -j2 diff --git a/cpp/DSF.h b/cpp/DSF.h index eff4bdd8e..ce12068cc 100644 --- a/cpp/DSF.h +++ b/cpp/DSF.h @@ -110,7 +110,7 @@ namespace gtsam { } // get the nodes in the tree with the given label - Set set(const Label& label) { + Set set(const Label& label) const { Set set; BOOST_FOREACH(const KeyLabel& pair, (Tree)*this) { if (pair.second == label || findSet(pair.second) == label) diff --git a/cpp/DSFVector.cpp b/cpp/DSFVector.cpp new file mode 100644 index 000000000..2e1ccc305 --- /dev/null +++ b/cpp/DSFVector.cpp @@ -0,0 +1,58 @@ +/* + * DSFVector.cpp + * + * Created on: Jun 25, 2010 + * Author: nikai + * Description: a faster implementation for DSF, which uses vector rather than btree. + * As a result, the size of the forest is prefixed. + */ + +#include "DSFVector.h" + +using namespace std; + +namespace gtsam { + + /* ************************************************************************* */ + DSFVector::DSFVector (const size_t numNodes) { + resize(numNodes); + int index = 0; + for(iterator it = begin(); it!=end(); it++, index++) + *it = index; + } + + /* ************************************************************************* */ + size_t DSFVector::findSet(const size_t& key) const { + size_t parent = at(key); + return parent == key ? key : findSet(parent); + } + + /* ************************************************************************* */ + std::set DSFVector::set(const std::size_t& label) const { + std::set set; + size_t key = 0; + std::vector::const_iterator it = begin(); + for (; it != end(); it++, key++) { + if (*it == label || findSet(*it) == label) + set.insert(key); + } + return set; + } + + /* ************************************************************************* */ + void DSFVector::makeUnionInPlace(const std::size_t& i1, const std::size_t& i2) { + at(findSet(i2)) = findSet(i1); + } + + /* ************************************************************************* */ + std::map > DSFVector::sets() const { + std::map > sets; + size_t key = 0; + std::vector::const_iterator it = begin(); + for (; it != end(); it++, key++) { + sets[findSet(*it)].insert(key); + } + return sets; + } + +} diff --git a/cpp/DSFVector.h b/cpp/DSFVector.h new file mode 100644 index 000000000..e8f0bc6b2 --- /dev/null +++ b/cpp/DSFVector.h @@ -0,0 +1,41 @@ +/* + * DSFVector.h + * + * Created on: Jun 25, 2010 + * Author: nikai + * Description: a faster implementation for DSF, which uses vector rather than btree. + * As a result, the size of the forest is prefixed. + */ + +#pragma once + +#include +#include +#include + +namespace gtsam { + + /** + * A fast impelementation of disjoint set forests + */ + class DSFVector : protected std::vector { + private: + + public: + // constructor + DSFVector(const std::size_t numNodes); + + // find the label of the set in which {key} lives + size_t findSet(const size_t& key) const; + + // the in-place version of makeUnion + void makeUnionInPlace(const std::size_t& i1, const std::size_t& i2); + + // get the nodes in the tree with the given label + std::set set(const std::size_t& label) const; + + // return all sets, i.e. a partition of all elements + std::map > sets() const; + }; + +} diff --git a/cpp/Makefile.am b/cpp/Makefile.am index 143a97729..b7f889373 100644 --- a/cpp/Makefile.am +++ b/cpp/Makefile.am @@ -40,15 +40,17 @@ testMatrix_LDADD = libgtsam.la # The header files will be installed in ~/include/gtsam headers = gtsam.h Value.h Testable.h Factor.h Conditional.h headers += Ordering.h IndexTable.h numericalDerivative.h -headers += BTree.h DSF.h -sources += Ordering.cpp smallExample.cpp -check_PROGRAMS += testOrdering testBTree testDSF +headers += BTree.h DSF.h DSFVector.h +sources += Ordering.cpp smallExample.cpp DSFVector.cpp +check_PROGRAMS += testOrdering testBTree testDSF testDSFVector testOrdering_SOURCES = testOrdering.cpp testOrdering_LDADD = libgtsam.la testBTree_SOURCES = testBTree.cpp testBTree_LDADD = libgtsam.la testDSF_SOURCES = testDSF.cpp testDSF_LDADD = libgtsam.la +testDSFVector_SOURCES = testDSFVector.cpp +testDSFVector_LDADD = libgtsam.la # Symbolic Inference headers += SymbolicConditional.h diff --git a/cpp/SymbolicFactor.h b/cpp/SymbolicFactor.h index 53c01b2e0..8f68d930c 100644 --- a/cpp/SymbolicFactor.h +++ b/cpp/SymbolicFactor.h @@ -99,6 +99,10 @@ namespace gtsam { return keys_.empty(); } + /** get the size of the factor */ + std::size_t size() const { + return keys_.size(); + } }; diff --git a/cpp/testDSFVector.cpp b/cpp/testDSFVector.cpp new file mode 100644 index 000000000..6028d8a24 --- /dev/null +++ b/cpp/testDSFVector.cpp @@ -0,0 +1,109 @@ +/* + * testDSF.cpp + * + * Created on: June 25, 2010 + * Author: nikai + * Description: unit tests for DSF + */ + +#include +#include +#include +using namespace boost::assign; +#include + +#include "DSFVector.h" +#include "Key.h" + +using namespace std; +using namespace gtsam; + +/* ************************************************************************* */ +TEST(DSFVectorVector, findSet) { + DSFVector dsf(3); + CHECK(dsf.findSet(0) != dsf.findSet(2)); +} + +/* ************************************************************************* */ +TEST(DSFVectorVector, makeUnionInPlace) { + DSFVector dsf(3); + dsf.makeUnionInPlace(0,2); + CHECK(dsf.findSet(0) == dsf.findSet(2)); +} + +/* ************************************************************************* */ +TEST(DSFVector, makeUnion2) { + DSFVector dsf(3); + dsf.makeUnionInPlace(2,0); + CHECK(dsf.findSet(0) == dsf.findSet(2)); +} + +/* ************************************************************************* */ +TEST(DSFVector, makeUnion3) { + DSFVector dsf(3); + dsf.makeUnionInPlace(0,1); + dsf.makeUnionInPlace(1,2); + CHECK(dsf.findSet(0) == dsf.findSet(2)); +} + +/* ************************************************************************* */ +TEST(DSFVector, sets) { + DSFVector dsf(2); + dsf.makeUnionInPlace(0,1); + map > sets = dsf.sets(); + LONGS_EQUAL(1, sets.size()); + + set expected; expected += 0, 1; + CHECK(expected == sets[dsf.findSet(0)]); +} + +/* ************************************************************************* */ +TEST(DSFVector, sets2) { + DSFVector dsf(3); + dsf.makeUnionInPlace(0,1); + dsf.makeUnionInPlace(1,2); + map > sets = dsf.sets(); + LONGS_EQUAL(1, sets.size()); + + set expected; expected += 0, 1, 2; + CHECK(expected == sets[dsf.findSet(0)]); +} + +/* ************************************************************************* */ +TEST(DSFVector, sets3) { + DSFVector dsf(3); + dsf.makeUnionInPlace(0,1); + map > sets = dsf.sets(); + LONGS_EQUAL(2, sets.size()); + + set expected; expected += 0, 1; + CHECK(expected == sets[dsf.findSet(0)]); +} + +/* ************************************************************************* */ +TEST(DSFVector, set) { + DSFVector dsf(3); + dsf.makeUnionInPlace(0,1); + set set = dsf.set(0); + LONGS_EQUAL(2, set.size()); + + std::set expected; expected += 0, 1; + CHECK(expected == set); +} + +/* ************************************************************************* */ +TEST(DSFVector, set2) { + DSFVector dsf(3); + dsf.makeUnionInPlace(0,1); + dsf.makeUnionInPlace(1,2); + set set = dsf.set(0); + LONGS_EQUAL(3, set.size()); + + std::set expected; expected += 0, 1, 2; + CHECK(expected == set); +} + +/* ************************************************************************* */ +int main() { TestResult tr; return TestRegistry::runAllTests(tr);} +/* ************************************************************************* */ +