From dbf1d9fd1a44373e742539ae32e7017878d9c976 Mon Sep 17 00:00:00 2001 From: Frank Dellaert Date: Sat, 31 Dec 2022 01:11:48 -0500 Subject: [PATCH 1/8] Initializer list and insert/update chaining --- gtsam/linear/VectorValues.cpp | 26 ++++++++++++++----------- gtsam/linear/VectorValues.h | 15 +++++++++----- gtsam/linear/tests/testVectorValues.cpp | 16 +++++++++++++++ 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/gtsam/linear/VectorValues.cpp b/gtsam/linear/VectorValues.cpp index 62996af27d..04792b6ba7 100644 --- a/gtsam/linear/VectorValues.cpp +++ b/gtsam/linear/VectorValues.cpp @@ -98,30 +98,34 @@ namespace gtsam { } /* ************************************************************************ */ - void VectorValues::update(const VectorValues& values) - { + VectorValues& VectorValues::update(const VectorValues& values) { iterator hint = begin(); - for(const KeyValuePair& key_value: values) - { - // Use this trick to find the value using a hint, since we are inserting from another sorted map + for (const KeyValuePair& key_value : values) { + // Use this trick to find the value using a hint, since we are inserting + // from another sorted map size_t oldSize = values_.size(); hint = values_.insert(hint, key_value); - if(values_.size() > oldSize) { + if (values_.size() > oldSize) { values_.unsafe_erase(hint); - throw out_of_range("Requested to update a VectorValues with another VectorValues that contains keys not present in the first."); + throw out_of_range( + "Requested to update a VectorValues with another VectorValues that " + "contains keys not present in the first."); } else { hint->second = key_value.second; } } + return *this; } /* ************************************************************************ */ - void VectorValues::insert(const VectorValues& values) - { + VectorValues& VectorValues::insert(const VectorValues& values) { size_t originalSize = size(); values_.insert(values.begin(), values.end()); - if(size() != originalSize + values.size()) - throw invalid_argument("Requested to insert a VectorValues into another VectorValues that already contains one or more of its keys."); + if (size() != originalSize + values.size()) + throw invalid_argument( + "Requested to insert a VectorValues into another VectorValues that " + "already contains one or more of its keys."); + return *this; } /* ************************************************************************ */ diff --git a/gtsam/linear/VectorValues.h b/gtsam/linear/VectorValues.h index 4e1f793a03..6a645150f2 100644 --- a/gtsam/linear/VectorValues.h +++ b/gtsam/linear/VectorValues.h @@ -88,11 +88,16 @@ namespace gtsam { /// @name Standard Constructors /// @{ - /** - * Default constructor creates an empty VectorValues. - */ + /// Default constructor creates an empty VectorValues. VectorValues() {} + /// Construct from initializer list. + VectorValues(std::initializer_list> init) { + for (const auto& p : init) { + values_.insert(p); // Insert key-value pair into map + } + } + /** Merge two VectorValues into one, this is more efficient than inserting * elements one by one. */ VectorValues(const VectorValues& first, const VectorValues& second); @@ -167,7 +172,7 @@ namespace gtsam { /** For all key/value pairs in \c values, replace values with corresponding keys in this class * with those in \c values. Throws std::out_of_range if any keys in \c values are not present * in this class. */ - void update(const VectorValues& values); + VectorValues& update(const VectorValues& values); /** Insert a vector \c value with key \c j. Throws an invalid_argument exception if the key \c * j is already used. @@ -198,7 +203,7 @@ namespace gtsam { /** Insert all values from \c values. Throws an invalid_argument exception if any keys to be * inserted are already used. */ - void insert(const VectorValues& values); + VectorValues& insert(const VectorValues& values); /** insert that mimics the STL map insert - if the value already exists, the map is not modified * and an iterator to the existing value is returned, along with 'false'. If the value did not diff --git a/gtsam/linear/tests/testVectorValues.cpp b/gtsam/linear/tests/testVectorValues.cpp index 521cc2289e..5974f8320d 100644 --- a/gtsam/linear/tests/testVectorValues.cpp +++ b/gtsam/linear/tests/testVectorValues.cpp @@ -73,6 +73,22 @@ TEST(VectorValues, basics) CHECK_EXCEPTION(actual.dim(3), out_of_range); } +/* ************************************************************************* */ + +static const VectorValues kExample = {{99, Vector2(2, 3)}}; + +// Check insert +TEST(VectorValues, Insert) { + VectorValues actual; + EXPECT(assert_equal(kExample, actual.insert(kExample))); +} + +// Check update. +TEST(VectorValues, Update) { + VectorValues actual(kExample); + EXPECT(assert_equal(kExample, actual.update(kExample))); +} + /* ************************************************************************* */ TEST(VectorValues, combine) { From 5ee85b55f8fde88324e3b31f5ac5968bc1ecbd0f Mon Sep 17 00:00:00 2001 From: Frank Dellaert Date: Sat, 31 Dec 2022 01:12:25 -0500 Subject: [PATCH 2/8] Initializer list and insert/update --- gtsam/discrete/Assignment.h | 7 ++++ gtsam/discrete/DiscreteValues.cpp | 42 ++++++++++++++++++++ gtsam/discrete/DiscreteValues.h | 43 ++++++++++++++++----- gtsam/discrete/tests/testDiscreteValues.cpp | 26 +++++++++---- 4 files changed, 101 insertions(+), 17 deletions(-) diff --git a/gtsam/discrete/Assignment.h b/gtsam/discrete/Assignment.h index 0ea84e4501..56a0ed3276 100644 --- a/gtsam/discrete/Assignment.h +++ b/gtsam/discrete/Assignment.h @@ -51,6 +51,13 @@ class Assignment : public std::map { public: using std::map::operator=; + // Define the implicit default constructor. + Assignment() = default; + + // Construct from initializer list. + Assignment(std::initializer_list> init) + : std::map{init} {} + void print(const std::string& s = "Assignment: ", const std::function& labelFormatter = &DefaultFormatter) const { diff --git a/gtsam/discrete/DiscreteValues.cpp b/gtsam/discrete/DiscreteValues.cpp index 5d0c8dd3d5..b0427e91b7 100644 --- a/gtsam/discrete/DiscreteValues.cpp +++ b/gtsam/discrete/DiscreteValues.cpp @@ -17,6 +17,7 @@ #include +#include #include using std::cout; @@ -26,6 +27,7 @@ using std::stringstream; namespace gtsam { +/* ************************************************************************ */ void DiscreteValues::print(const string& s, const KeyFormatter& keyFormatter) const { cout << s << ": "; @@ -34,6 +36,44 @@ void DiscreteValues::print(const string& s, cout << endl; } +/* ************************************************************************ */ +bool DiscreteValues::equals(const DiscreteValues& x, double tol) const { + if (this->size() != x.size()) return false; + for (const auto values : boost::combine(*this, x)) { + if (values.get<0>() != values.get<1>()) return false; + } + return true; +} + +/* ************************************************************************ */ +DiscreteValues& DiscreteValues::insert(const DiscreteValues& values) { + for (const auto& kv : values) { + if (count(kv.first)) { + throw std::out_of_range( + "Requested to insert a DiscreteValues into another DiscreteValues " + "that already contains one or more of its keys."); + } else { + this->emplace(kv); + } + } + return *this; +} + +/* ************************************************************************ */ +DiscreteValues& DiscreteValues::update(const DiscreteValues& values) { + for (const auto& kv : values) { + if (!count(kv.first)) { + throw std::out_of_range( + "Requested to update a DiscreteValues with another DiscreteValues " + "that contains keys not present in the first."); + } else { + (*this)[kv.first] = kv.second; + } + } + return *this; +} + +/* ************************************************************************ */ string DiscreteValues::Translate(const Names& names, Key key, size_t index) { if (names.empty()) { stringstream ss; @@ -60,6 +100,7 @@ string DiscreteValues::markdown(const KeyFormatter& keyFormatter, return ss.str(); } +/* ************************************************************************ */ string DiscreteValues::html(const KeyFormatter& keyFormatter, const Names& names) const { stringstream ss; @@ -84,6 +125,7 @@ string DiscreteValues::html(const KeyFormatter& keyFormatter, return ss.str(); } +/* ************************************************************************ */ string markdown(const DiscreteValues& values, const KeyFormatter& keyFormatter, const DiscreteValues::Names& names) { return values.markdown(keyFormatter, names); diff --git a/gtsam/discrete/DiscreteValues.h b/gtsam/discrete/DiscreteValues.h index 72bb240816..6a1f550b6e 100644 --- a/gtsam/discrete/DiscreteValues.h +++ b/gtsam/discrete/DiscreteValues.h @@ -27,21 +27,16 @@ namespace gtsam { -/** A map from keys to values - * TODO(dellaert): Do we need this? Should we just use gtsam::DiscreteValues? - * We just need another special DiscreteValue to represent labels, - * However, all other Lie's operators are undefined in this class. - * The good thing is we can have a Hybrid graph of discrete/continuous variables - * together.. - * Another good thing is we don't need to have the special DiscreteKey which - * stores cardinality of a Discrete variable. It should be handled naturally in - * the new class DiscreteValue, as the variable's type (domain) +/** + * A map from keys to values * @ingroup discrete */ class GTSAM_EXPORT DiscreteValues : public Assignment { public: using Base = Assignment; // base class + /// @name Standard Constructors + /// @{ using Assignment::Assignment; // all constructors // Define the implicit default constructor. @@ -50,14 +45,44 @@ class GTSAM_EXPORT DiscreteValues : public Assignment { // Construct from assignment. explicit DiscreteValues(const Base& a) : Base(a) {} + // Construct from initializer list. + DiscreteValues(std::initializer_list> init) + : Assignment{init} {} + + /// @} + /// @name Testable + /// @{ + + /// print required by Testable. void print(const std::string& s = "", const KeyFormatter& keyFormatter = DefaultKeyFormatter) const; + /// equals required by Testable for unit testing. + bool equals(const DiscreteValues& x, double tol = 1e-9) const; + + /// @} + /// @name Standard Interface + /// @{ + + /** Insert all values from \c values. Throws an invalid_argument exception if + * any keys to be inserted are already used. */ + DiscreteValues& insert(const DiscreteValues& values); + + /** For all key/value pairs in \c values, replace values with corresponding + * keys in this object with those in \c values. Throws std::out_of_range if + * any keys in \c values are not present in this object. */ + DiscreteValues& update(const DiscreteValues& values); + + /** + * @brief Return a vector of DiscreteValues, one for each possible + * combination of values. + */ static std::vector CartesianProduct( const DiscreteKeys& keys) { return Base::CartesianProduct(keys); } + /// @} /// @name Wrapper support /// @{ diff --git a/gtsam/discrete/tests/testDiscreteValues.cpp b/gtsam/discrete/tests/testDiscreteValues.cpp index c8a1fa1680..6cfc115314 100644 --- a/gtsam/discrete/tests/testDiscreteValues.cpp +++ b/gtsam/discrete/tests/testDiscreteValues.cpp @@ -27,12 +27,25 @@ using namespace boost::assign; using namespace std; using namespace gtsam; +static const DiscreteValues kExample{{12, 1}, {5, 0}}; + +/* ************************************************************************* */ +// Check insert +TEST(DiscreteValues, Insert) { + EXPECT(assert_equal({{12, 1}, {5, 0}, {13, 2}}, + DiscreteValues(kExample).insert({{13, 2}}))); +} + +/* ************************************************************************* */ +// Check update. +TEST(DiscreteValues, Update) { + EXPECT(assert_equal({{12, 2}, {5, 0}}, + DiscreteValues(kExample).update({{12, 2}}))); +} + /* ************************************************************************* */ // Check markdown representation with a value formatter. TEST(DiscreteValues, markdownWithValueFormatter) { - DiscreteValues values; - values[12] = 1; // A - values[5] = 0; // B string expected = "|Variable|value|\n" "|:-:|:-:|\n" @@ -40,16 +53,13 @@ TEST(DiscreteValues, markdownWithValueFormatter) { "|A|One|\n"; auto keyFormatter = [](Key key) { return key == 12 ? "A" : "B"; }; DiscreteValues::Names names{{12, {"Zero", "One", "Two"}}, {5, {"-", "+"}}}; - string actual = values.markdown(keyFormatter, names); + string actual = kExample.markdown(keyFormatter, names); EXPECT(actual == expected); } /* ************************************************************************* */ // Check html representation with a value formatter. TEST(DiscreteValues, htmlWithValueFormatter) { - DiscreteValues values; - values[12] = 1; // A - values[5] = 0; // B string expected = "
\n" "\n" @@ -64,7 +74,7 @@ TEST(DiscreteValues, htmlWithValueFormatter) { ""; auto keyFormatter = [](Key key) { return key == 12 ? "A" : "B"; }; DiscreteValues::Names names{{12, {"Zero", "One", "Two"}}, {5, {"-", "+"}}}; - string actual = values.html(keyFormatter, names); + string actual = kExample.html(keyFormatter, names); EXPECT(actual == expected); } From 6a36275803b96aa807b173f30eebdf70ff356bb4 Mon Sep 17 00:00:00 2001 From: Frank Dellaert Date: Sat, 31 Dec 2022 01:12:45 -0500 Subject: [PATCH 3/8] insert/update --- gtsam/hybrid/HybridBayesNet.cpp | 2 +- gtsam/hybrid/HybridValues.h | 53 +++++++++++++++++++++++-- gtsam/hybrid/tests/testHybridValues.cpp | 35 +++++++++++++--- 3 files changed, 79 insertions(+), 11 deletions(-) diff --git a/gtsam/hybrid/HybridBayesNet.cpp b/gtsam/hybrid/HybridBayesNet.cpp index 8be314c4e2..e471cb02f0 100644 --- a/gtsam/hybrid/HybridBayesNet.cpp +++ b/gtsam/hybrid/HybridBayesNet.cpp @@ -112,7 +112,7 @@ std::function &, double)> prunerFunc( DiscreteValues::CartesianProduct(set_diff); for (const DiscreteValues &assignment : assignments) { DiscreteValues augmented_values(values); - augmented_values.insert(assignment.begin(), assignment.end()); + augmented_values.insert(assignment); // If any one of the sub-branches are non-zero, // we need this probability. diff --git a/gtsam/hybrid/HybridValues.h b/gtsam/hybrid/HybridValues.h index ff896041ea..efe65bc31b 100644 --- a/gtsam/hybrid/HybridValues.h +++ b/gtsam/hybrid/HybridValues.h @@ -104,6 +104,28 @@ class GTSAM_EXPORT HybridValues { * @param j The index with which the value will be associated. */ void insert(Key j, const Vector& value) { continuous_.insert(j, value); } + /** Insert all continuous values from \c values. Throws an invalid_argument + * exception if any keys to be inserted are already used. */ + HybridValues& insert(const VectorValues& values) { + continuous_.insert(values); + return *this; + } + + /** Insert all discrete values from \c values. Throws an invalid_argument + * exception if any keys to be inserted are already used. */ + HybridValues& insert(const DiscreteValues& values) { + discrete_.insert(values); + return *this; + } + + /** Insert all values from \c values. Throws an invalid_argument exception if + * any keys to be inserted are already used. */ + HybridValues& insert(const HybridValues& values) { + continuous_.insert(values.continuous()); + discrete_.insert(values.discrete()); + return *this; + } + // TODO(Shangjie)- insert_or_assign() , similar to Values.h /** @@ -118,10 +140,33 @@ class GTSAM_EXPORT HybridValues { */ Vector& at(Key j) { return continuous_.at(j); }; - /** For all key/value pairs in \c values, replace values with corresponding keys in this class - * with those in \c values. Throws std::out_of_range if any keys in \c values are not present - * in this class. */ - void update(const VectorValues& values) { continuous_.update(values); } + /** For all key/value pairs in \c values, replace continuous values with + * corresponding keys in this object with those in \c values. Throws + * std::out_of_range if any keys in \c values are not present in this object. + */ + HybridValues& update(const VectorValues& values) { + continuous_.update(values); + return *this; + } + + /** For all key/value pairs in \c values, replace discrete values with + * corresponding keys in this object with those in \c values. Throws + * std::out_of_range if any keys in \c values are not present in this object. + */ + HybridValues& update(const DiscreteValues& values) { + discrete_.update(values); + return *this; + } + + /** For all key/value pairs in \c values, replace all values with + * corresponding keys in this object with those in \c values. Throws + * std::out_of_range if any keys in \c values are not present in this object. + */ + HybridValues& update(const HybridValues& values) { + continuous_.update(values.continuous()); + discrete_.update(values.discrete()); + return *this; + } /// @} /// @name Wrapper support diff --git a/gtsam/hybrid/tests/testHybridValues.cpp b/gtsam/hybrid/tests/testHybridValues.cpp index 6f510601d4..02e1cb733d 100644 --- a/gtsam/hybrid/tests/testHybridValues.cpp +++ b/gtsam/hybrid/tests/testHybridValues.cpp @@ -32,22 +32,45 @@ using namespace std; using namespace gtsam; -TEST(HybridValues, basics) { +static const HybridValues kExample{{{99, Vector2(2, 3)}}, {{100, 3}}}; + +/* ************************************************************************* */ +TEST(HybridValues, Basics) { HybridValues values; values.insert(99, Vector2(2, 3)); values.insert(100, 3); + EXPECT(assert_equal(kExample, values)); EXPECT(assert_equal(values.at(99), Vector2(2, 3))); EXPECT(assert_equal(values.atDiscrete(100), int(3))); - values.print(); - HybridValues values2; values2.insert(100, 3); values2.insert(99, Vector2(2, 3)); - EXPECT(assert_equal(values2, values)); + EXPECT(assert_equal(kExample, values2)); +} - values2.insert(98, Vector2(2, 3)); - EXPECT(!assert_equal(values2, values)); +/* ************************************************************************* */ +// Check insert +TEST(HybridValues, Insert) { + HybridValues actual; + EXPECT(assert_equal({{}, {{100, 3}}}, // + actual.insert(DiscreteValues{{100, 3}}))); + EXPECT(assert_equal(kExample, // + actual.insert(VectorValues{{99, Vector2(2, 3)}}))); + HybridValues actual2; + EXPECT(assert_equal(kExample, actual2.insert(kExample))); +} + +/* ************************************************************************* */ +// Check update. +TEST(HybridValues, Update) { + HybridValues actual(kExample); + EXPECT(assert_equal({{{99, Vector2(2, 3)}}, {{100, 2}}}, + actual.update(DiscreteValues{{100, 2}}))); + EXPECT(assert_equal({{{99, Vector1(4)}}, {{100, 2}}}, + actual.update(VectorValues{{99, Vector1(4)}}))); + HybridValues actual2(kExample); + EXPECT(assert_equal(kExample, actual2.update(kExample))); } /* ************************************************************************* */ From 89cb910395b579897a44e7c2029f04eab385a2aa Mon Sep 17 00:00:00 2001 From: Frank Dellaert Date: Sat, 31 Dec 2022 01:43:21 -0500 Subject: [PATCH 4/8] Make sure boost:assign still works. --- gtsam/discrete/DiscreteValues.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gtsam/discrete/DiscreteValues.h b/gtsam/discrete/DiscreteValues.h index 6a1f550b6e..8a6d6f9303 100644 --- a/gtsam/discrete/DiscreteValues.h +++ b/gtsam/discrete/DiscreteValues.h @@ -64,6 +64,11 @@ class GTSAM_EXPORT DiscreteValues : public Assignment { /// @name Standard Interface /// @{ + // insert in base class; + std::pair insert( const value_type& value ){ + return Base::insert(value); + } + /** Insert all values from \c values. Throws an invalid_argument exception if * any keys to be inserted are already used. */ DiscreteValues& insert(const DiscreteValues& values); From d2fd155a3abd626b0ef155b043c499d66383343a Mon Sep 17 00:00:00 2001 From: Frank Dellaert Date: Sat, 31 Dec 2022 01:53:10 -0500 Subject: [PATCH 5/8] Use brace initializers for DiscreteValues --- .../tests/testAlgebraicDecisionTree.cpp | 3 - gtsam/discrete/tests/testDecisionTree.cpp | 3 - .../discrete/tests/testDecisionTreeFactor.cpp | 3 - gtsam/discrete/tests/testDiscreteBayesNet.cpp | 13 +- .../discrete/tests/testDiscreteBayesTree.cpp | 3 - .../tests/testDiscreteConditional.cpp | 3 - gtsam/discrete/tests/testDiscreteFactor.cpp | 3 - .../tests/testDiscreteFactorGraph.cpp | 125 +----------------- .../discrete/tests/testDiscreteLookupDAG.cpp | 7 +- .../discrete/tests/testDiscreteMarginals.cpp | 3 - gtsam/discrete/tests/testDiscreteValues.cpp | 3 - gtsam/discrete/tests/testSignature.cpp | 10 +- .../discrete/examples/schedulingExample.cpp | 3 - .../discrete/examples/schedulingQuals12.cpp | 3 - .../discrete/examples/schedulingQuals13.cpp | 3 - gtsam_unstable/discrete/tests/testCSP.cpp | 12 +- .../discrete/tests/testScheduler.cpp | 3 - gtsam_unstable/discrete/tests/testSudoku.cpp | 15 ++- 18 files changed, 24 insertions(+), 194 deletions(-) diff --git a/gtsam/discrete/tests/testAlgebraicDecisionTree.cpp b/gtsam/discrete/tests/testAlgebraicDecisionTree.cpp index 6a3fb23884..ac5eccd14f 100644 --- a/gtsam/discrete/tests/testAlgebraicDecisionTree.cpp +++ b/gtsam/discrete/tests/testAlgebraicDecisionTree.cpp @@ -25,10 +25,7 @@ #include // for convert only #define DISABLE_TIMING -#include -#include #include -using namespace boost::assign; #include #include diff --git a/gtsam/discrete/tests/testDecisionTree.cpp b/gtsam/discrete/tests/testDecisionTree.cpp index 5ccbcf9162..63b14b05e6 100644 --- a/gtsam/discrete/tests/testDecisionTree.cpp +++ b/gtsam/discrete/tests/testDecisionTree.cpp @@ -27,9 +27,6 @@ #include -#include -using namespace boost::assign; - using namespace std; using namespace gtsam; diff --git a/gtsam/discrete/tests/testDecisionTreeFactor.cpp b/gtsam/discrete/tests/testDecisionTreeFactor.cpp index 84e45a0f54..1829db0340 100644 --- a/gtsam/discrete/tests/testDecisionTreeFactor.cpp +++ b/gtsam/discrete/tests/testDecisionTreeFactor.cpp @@ -23,9 +23,6 @@ #include #include -#include -using namespace boost::assign; - using namespace std; using namespace gtsam; diff --git a/gtsam/discrete/tests/testDiscreteBayesNet.cpp b/gtsam/discrete/tests/testDiscreteBayesNet.cpp index 19af676f7d..6303a5487f 100644 --- a/gtsam/discrete/tests/testDiscreteBayesNet.cpp +++ b/gtsam/discrete/tests/testDiscreteBayesNet.cpp @@ -26,11 +26,6 @@ #include -#include -#include - -using namespace boost::assign; - #include #include #include @@ -115,11 +110,11 @@ TEST(DiscreteBayesNet, Asia) { EXPECT(assert_equal(expected2, *chordal->back())); // now sample from it - DiscreteValues expectedSample; + DiscreteValues expectedSample{{Asia.first, 1}, {Dyspnea.first, 1}, + {XRay.first, 1}, {Tuberculosis.first, 0}, + {Smoking.first, 1}, {Either.first, 1}, + {LungCancer.first, 1}, {Bronchitis.first, 0}}; SETDEBUG("DiscreteConditional::sample", false); - insert(expectedSample)(Asia.first, 1)(Dyspnea.first, 1)(XRay.first, 1)( - Tuberculosis.first, 0)(Smoking.first, 1)(Either.first, 1)( - LungCancer.first, 1)(Bronchitis.first, 0); auto actualSample = chordal2->sample(); EXPECT(assert_equal(expectedSample, actualSample)); } diff --git a/gtsam/discrete/tests/testDiscreteBayesTree.cpp b/gtsam/discrete/tests/testDiscreteBayesTree.cpp index ab69e82d77..0a7dc72f42 100644 --- a/gtsam/discrete/tests/testDiscreteBayesTree.cpp +++ b/gtsam/discrete/tests/testDiscreteBayesTree.cpp @@ -21,9 +21,6 @@ #include #include -#include -using namespace boost::assign; - #include #include diff --git a/gtsam/discrete/tests/testDiscreteConditional.cpp b/gtsam/discrete/tests/testDiscreteConditional.cpp index 13a34dd19d..9098f7a1d6 100644 --- a/gtsam/discrete/tests/testDiscreteConditional.cpp +++ b/gtsam/discrete/tests/testDiscreteConditional.cpp @@ -17,10 +17,7 @@ * @date Feb 14, 2011 */ -#include -#include #include -using namespace boost::assign; #include #include diff --git a/gtsam/discrete/tests/testDiscreteFactor.cpp b/gtsam/discrete/tests/testDiscreteFactor.cpp index db0491c9d6..7fc5ee248b 100644 --- a/gtsam/discrete/tests/testDiscreteFactor.cpp +++ b/gtsam/discrete/tests/testDiscreteFactor.cpp @@ -21,9 +21,6 @@ #include #include -#include -using namespace boost::assign; - using namespace std; using namespace gtsam; using namespace gtsam::serializationTestHelpers; diff --git a/gtsam/discrete/tests/testDiscreteFactorGraph.cpp b/gtsam/discrete/tests/testDiscreteFactorGraph.cpp index 3d9621affa..2d79b9de9e 100644 --- a/gtsam/discrete/tests/testDiscreteFactorGraph.cpp +++ b/gtsam/discrete/tests/testDiscreteFactorGraph.cpp @@ -23,9 +23,6 @@ #include -#include -using namespace boost::assign; - using namespace std; using namespace gtsam; @@ -49,9 +46,7 @@ TEST_UNSAFE(DiscreteFactorGraph, debugScheduler) { // Check MPE. auto actualMPE = graph.optimize(); - DiscreteValues mpe; - insert(mpe)(0, 2)(1, 1)(2, 0)(3, 0); - EXPECT(assert_equal(mpe, actualMPE)); + EXPECT(assert_equal({{0, 2}, {1, 1}, {2, 0}, {3, 0}}, actualMPE)); } /* ************************************************************************* */ @@ -149,8 +144,7 @@ TEST(DiscreteFactorGraph, test) { EXPECT(assert_equal(expectedBayesNet, *actual2)); // Test mpe - DiscreteValues mpe; - insert(mpe)(0, 0)(1, 0)(2, 0); + DiscreteValues mpe { {0, 0}, {1, 0}, {2, 0}}; auto actualMPE = graph.optimize(); EXPECT(assert_equal(mpe, actualMPE)); EXPECT_DOUBLES_EQUAL(9, graph(mpe), 1e-5); // regression @@ -182,8 +176,7 @@ TEST_UNSAFE(DiscreteFactorGraph, testMaxProduct) { graph.add(C & B, "0.1 0.9 0.4 0.6"); // Created expected MPE - DiscreteValues mpe; - insert(mpe)(0, 0)(1, 1)(2, 1); + DiscreteValues mpe{{0, 0}, {1, 1}, {2, 1}}; // Do max-product with different orderings for (Ordering::OrderingType orderingType : @@ -209,8 +202,7 @@ TEST(DiscreteFactorGraph, marginalIsNotMPE) { bayesNet.add(A % "10/9"); // The expected MPE is A=1, B=1 - DiscreteValues mpe; - insert(mpe)(0, 1)(1, 1); + DiscreteValues mpe { {0, 1}, {1, 1} }; // Which we verify using max-product: DiscreteFactorGraph graph(bayesNet); @@ -240,8 +232,7 @@ TEST(DiscreteFactorGraph, testMPE_Darwiche09book_p244) { graph.add(T1 & T2 & A, "1 0 0 1 0 1 1 0"); graph.add(A, "1 0"); // evidence, A = yes (first choice in Darwiche) - DiscreteValues mpe; - insert(mpe)(4, 0)(2, 1)(3, 1)(0, 1)(1, 1); + DiscreteValues mpe { {0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 0}}; EXPECT_DOUBLES_EQUAL(0.33858, graph(mpe), 1e-5); // regression // You can check visually by printing product: // graph.product().print("Darwiche-product"); @@ -267,112 +258,6 @@ TEST(DiscreteFactorGraph, testMPE_Darwiche09book_p244) { EXPECT_LONGS_EQUAL(2, bayesTree->size()); } -#ifdef OLD - -/* ************************************************************************* */ -/** - * Key type for discrete conditionals - * Includes name and cardinality - */ -class Key2 { -private: -std::string wff_; -size_t cardinality_; -public: -/** Constructor, defaults to binary */ -Key2(const std::string& name, size_t cardinality = 2) : -wff_(name), cardinality_(cardinality) { -} -const std::string& name() const { - return wff_; -} - -/** provide streaming */ -friend std::ostream& operator <<(std::ostream &os, const Key2 &key); -}; - -struct Factor2 { -std::string wff_; -Factor2() : -wff_("@") { -} -Factor2(const std::string& s) : -wff_(s) { -} -Factor2(const Key2& key) : -wff_(key.name()) { -} - -friend std::ostream& operator <<(std::ostream &os, const Factor2 &f); -friend Factor2 operator -(const Key2& key); -}; - -std::ostream& operator <<(std::ostream &os, const Factor2 &f) { -os << f.wff_; -return os; -} - -/** negation */ -Factor2 operator -(const Key2& key) { -return Factor2("-" + key.name()); -} - -/** OR */ -Factor2 operator ||(const Factor2 &factor1, const Factor2 &factor2) { -return Factor2(std::string("(") + factor1.wff_ + " || " + factor2.wff_ + ")"); -} - -/** AND */ -Factor2 operator &&(const Factor2 &factor1, const Factor2 &factor2) { -return Factor2(std::string("(") + factor1.wff_ + " && " + factor2.wff_ + ")"); -} - -/** implies */ -Factor2 operator >>(const Factor2 &factor1, const Factor2 &factor2) { -return Factor2(std::string("(") + factor1.wff_ + " >> " + factor2.wff_ + ")"); -} - -struct Graph2: public std::list { - -/** Add a factor graph*/ -// void operator +=(const Graph2& graph) { -// for(const Factor2& f: graph) -// push_back(f); -// } -friend std::ostream& operator <<(std::ostream &os, const Graph2& graph); - -}; - -/** Add a factor */ -//Graph2 operator +=(Graph2& graph, const Factor2& factor) { -// graph.push_back(factor); -// return graph; -//} -std::ostream& operator <<(std::ostream &os, const Graph2& graph) { -for(const Factor2& f: graph) -os << f << endl; -return os; -} - -/* ************************************************************************* */ -TEST(DiscreteFactorGraph, Sugar) -{ -Key2 M("Mythical"), I("Immortal"), A("Mammal"), H("Horned"), G("Magical"); - -// Test this desired construction -Graph2 unicorns; -unicorns += M >> -A; -unicorns += (-M) >> (-I && A); -unicorns += (I || A) >> H; -unicorns += H >> G; - -// should be done by adapting boost::assign: -// unicorns += (-M) >> (-I && A), (I || A) >> H , H >> G; - -cout << unicorns; -} -#endif - /* ************************************************************************* */ TEST(DiscreteFactorGraph, Dot) { // Create Factor graph diff --git a/gtsam/discrete/tests/testDiscreteLookupDAG.cpp b/gtsam/discrete/tests/testDiscreteLookupDAG.cpp index 04b8597804..8c3ff5a1da 100644 --- a/gtsam/discrete/tests/testDiscreteLookupDAG.cpp +++ b/gtsam/discrete/tests/testDiscreteLookupDAG.cpp @@ -20,11 +20,7 @@ #include #include -#include -#include - using namespace gtsam; -using namespace boost::assign; /* ************************************************************************* */ TEST(DiscreteLookupDAG, argmax) { @@ -43,8 +39,7 @@ TEST(DiscreteLookupDAG, argmax) { dag.add(1, DiscreteKeys{A}, adtA); // The expected MPE is A=1, B=1 - DiscreteValues mpe; - insert(mpe)(0, 1)(1, 1); + DiscreteValues mpe{{0, 1}, {1, 1}}; // check: auto actualMPE = dag.argmax(); diff --git a/gtsam/discrete/tests/testDiscreteMarginals.cpp b/gtsam/discrete/tests/testDiscreteMarginals.cpp index 3208f81c53..3213e514f1 100644 --- a/gtsam/discrete/tests/testDiscreteMarginals.cpp +++ b/gtsam/discrete/tests/testDiscreteMarginals.cpp @@ -19,9 +19,6 @@ #include -#include -using namespace boost::assign; - #include using namespace std; diff --git a/gtsam/discrete/tests/testDiscreteValues.cpp b/gtsam/discrete/tests/testDiscreteValues.cpp index 6cfc115314..47989481cf 100644 --- a/gtsam/discrete/tests/testDiscreteValues.cpp +++ b/gtsam/discrete/tests/testDiscreteValues.cpp @@ -21,9 +21,6 @@ #include #include -#include -using namespace boost::assign; - using namespace std; using namespace gtsam; diff --git a/gtsam/discrete/tests/testSignature.cpp b/gtsam/discrete/tests/testSignature.cpp index 737bd8aef0..02e7a1d109 100644 --- a/gtsam/discrete/tests/testSignature.cpp +++ b/gtsam/discrete/tests/testSignature.cpp @@ -21,12 +21,10 @@ #include #include -#include #include using namespace std; using namespace gtsam; -using namespace boost::assign; DiscreteKey X(0, 2), Y(1, 3), Z(2, 2); @@ -57,12 +55,8 @@ TEST(testSignature, simple_conditional) { /* ************************************************************************* */ TEST(testSignature, simple_conditional_nonparser) { - Signature::Table table; - Signature::Row row1, row2, row3; - row1 += 1.0, 1.0; - row2 += 2.0, 3.0; - row3 += 1.0, 4.0; - table += row1, row2, row3; + Signature::Row row1{1, 1}, row2{2, 3}, row3{1, 4}; + Signature::Table table{row1, row2, row3}; Signature sig(X | Y = table); CHECK(sig.key() == X); diff --git a/gtsam_unstable/discrete/examples/schedulingExample.cpp b/gtsam_unstable/discrete/examples/schedulingExample.cpp index 487edc97a3..c9024e018e 100644 --- a/gtsam_unstable/discrete/examples/schedulingExample.cpp +++ b/gtsam_unstable/discrete/examples/schedulingExample.cpp @@ -12,14 +12,11 @@ #include #include -#include -#include #include #include #include -using namespace boost::assign; using namespace std; using namespace gtsam; diff --git a/gtsam_unstable/discrete/examples/schedulingQuals12.cpp b/gtsam_unstable/discrete/examples/schedulingQuals12.cpp index 830d59ba73..d3529cb55e 100644 --- a/gtsam_unstable/discrete/examples/schedulingQuals12.cpp +++ b/gtsam_unstable/discrete/examples/schedulingQuals12.cpp @@ -12,14 +12,11 @@ #include #include -#include -#include #include #include #include -using namespace boost::assign; using namespace std; using namespace gtsam; diff --git a/gtsam_unstable/discrete/examples/schedulingQuals13.cpp b/gtsam_unstable/discrete/examples/schedulingQuals13.cpp index b24f9bf0a4..27c9596750 100644 --- a/gtsam_unstable/discrete/examples/schedulingQuals13.cpp +++ b/gtsam_unstable/discrete/examples/schedulingQuals13.cpp @@ -12,14 +12,11 @@ #include #include -#include -#include #include #include #include -using namespace boost::assign; using namespace std; using namespace gtsam; diff --git a/gtsam_unstable/discrete/tests/testCSP.cpp b/gtsam_unstable/discrete/tests/testCSP.cpp index fb386b2553..5756cb99ce 100644 --- a/gtsam_unstable/discrete/tests/testCSP.cpp +++ b/gtsam_unstable/discrete/tests/testCSP.cpp @@ -8,8 +8,6 @@ #include #include -#include -using boost::assign::insert; #include #include @@ -133,8 +131,7 @@ TEST(CSP, allInOne) { // Solve auto mpe = csp.optimize(); - DiscreteValues expected; - insert(expected)(ID.first, 1)(UT.first, 0)(AZ.first, 1); + DiscreteValues expected {{ID.first, 1}, {UT.first, 0}, {AZ.first, 1}}; EXPECT(assert_equal(expected, mpe)); EXPECT_DOUBLES_EQUAL(1, csp(mpe), 1e-9); } @@ -172,8 +169,8 @@ TEST(CSP, WesternUS) { csp.addAllDiff(WY, CO); csp.addAllDiff(CO, NM); - DiscreteValues mpe; - insert(mpe)(0, 2)(1, 3)(2, 2)(3, 1)(4, 1)(5, 3)(6, 3)(7, 2)(8, 0)(9, 1)(10, 0); + DiscreteValues mpe{{0, 2}, {1, 3}, {2, 2}, {3, 1}, {4, 1}, {5, 3}, + {6, 3}, {7, 2}, {8, 0}, {9, 1}, {10, 0}}; // Create ordering according to example in ND-CSP.lyx Ordering ordering; @@ -224,8 +221,7 @@ TEST(CSP, ArcConsistency) { // Solve auto mpe = csp.optimize(); - DiscreteValues expected; - insert(expected)(ID.first, 1)(UT.first, 0)(AZ.first, 2); + DiscreteValues expected {{ID.first, 1}, {UT.first, 0}, {AZ.first, 2}}; EXPECT(assert_equal(expected, mpe)); EXPECT_DOUBLES_EQUAL(1, csp(mpe), 1e-9); diff --git a/gtsam_unstable/discrete/tests/testScheduler.cpp b/gtsam_unstable/discrete/tests/testScheduler.cpp index 086057a466..3b0528360f 100644 --- a/gtsam_unstable/discrete/tests/testScheduler.cpp +++ b/gtsam_unstable/discrete/tests/testScheduler.cpp @@ -10,11 +10,8 @@ #include #include -#include -#include #include -using namespace boost::assign; using namespace std; using namespace gtsam; diff --git a/gtsam_unstable/discrete/tests/testSudoku.cpp b/gtsam_unstable/discrete/tests/testSudoku.cpp index 8b28581699..9796c25f1a 100644 --- a/gtsam_unstable/discrete/tests/testSudoku.cpp +++ b/gtsam_unstable/discrete/tests/testSudoku.cpp @@ -9,8 +9,6 @@ #include #include -#include -using boost::assign::insert; #include #include @@ -128,11 +126,14 @@ TEST(Sudoku, small) { // optimize and check auto solution = csp.optimize(); DiscreteValues expected; - insert(expected)(csp.key(0, 0), 0)(csp.key(0, 1), 1)(csp.key(0, 2), 2)( - csp.key(0, 3), 3)(csp.key(1, 0), 2)(csp.key(1, 1), 3)(csp.key(1, 2), 0)( - csp.key(1, 3), 1)(csp.key(2, 0), 3)(csp.key(2, 1), 2)(csp.key(2, 2), 1)( - csp.key(2, 3), 0)(csp.key(3, 0), 1)(csp.key(3, 1), 0)(csp.key(3, 2), 3)( - csp.key(3, 3), 2); + expected = {{csp.key(0, 0), 0}, {csp.key(0, 1), 1}, + {csp.key(0, 2), 2}, {csp.key(0, 3), 3}, // + {csp.key(1, 0), 2}, {csp.key(1, 1), 3}, + {csp.key(1, 2), 0}, {csp.key(1, 3), 1}, // + {csp.key(2, 0), 3}, {csp.key(2, 1), 2}, + {csp.key(2, 2), 1}, {csp.key(2, 3), 0}, // + {csp.key(3, 0), 1}, {csp.key(3, 1), 0}, + {csp.key(3, 2), 3}, {csp.key(3, 3), 2}}; EXPECT(assert_equal(expected, solution)); // csp.printAssignment(solution); From fee651a35708ba0a2d4f903de31bc5d24bba1144 Mon Sep 17 00:00:00 2001 From: Frank Dellaert Date: Sat, 31 Dec 2022 01:53:59 -0500 Subject: [PATCH 6/8] Fix insert --- gtsam/hybrid/GaussianMixture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtsam/hybrid/GaussianMixture.cpp b/gtsam/hybrid/GaussianMixture.cpp index 65c0e85229..892a07d2df 100644 --- a/gtsam/hybrid/GaussianMixture.cpp +++ b/gtsam/hybrid/GaussianMixture.cpp @@ -210,7 +210,7 @@ GaussianMixture::prunerFunc(const DecisionTreeFactor &decisionTree) { DiscreteValues::CartesianProduct(set_diff); for (const DiscreteValues &assignment : assignments) { DiscreteValues augmented_values(values); - augmented_values.insert(assignment.begin(), assignment.end()); + augmented_values.insert(assignment); // If any one of the sub-branches are non-zero, // we need this conditional. From b86c8bb5941546c7f434d572bbe548180458ce13 Mon Sep 17 00:00:00 2001 From: Frank Dellaert Date: Sat, 31 Dec 2022 01:54:12 -0500 Subject: [PATCH 7/8] Use brace initializers for DiscreteValues in hybrid --- gtsam/hybrid/tests/testHybridBayesNet.cpp | 3 +-- gtsam/hybrid/tests/testHybridGaussianFactorGraph.cpp | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/gtsam/hybrid/tests/testHybridBayesNet.cpp b/gtsam/hybrid/tests/testHybridBayesNet.cpp index 58230cfdea..fe8cdcd640 100644 --- a/gtsam/hybrid/tests/testHybridBayesNet.cpp +++ b/gtsam/hybrid/tests/testHybridBayesNet.cpp @@ -237,8 +237,7 @@ TEST(HybridBayesNet, Error) { EXPECT(assert_equal(expected_pruned_error, pruned_error_tree, 1e-9)); // Verify error computation and check for specific error value - DiscreteValues discrete_values; - boost::assign::insert(discrete_values)(M(0), 1)(M(1), 1); + DiscreteValues discrete_values {{M(0), 1}, {M(1), 1}}; double total_error = 0; for (size_t idx = 0; idx < hybridBayesNet->size(); idx++) { diff --git a/gtsam/hybrid/tests/testHybridGaussianFactorGraph.cpp b/gtsam/hybrid/tests/testHybridGaussianFactorGraph.cpp index 1bdb6d4db1..171b91d51f 100644 --- a/gtsam/hybrid/tests/testHybridGaussianFactorGraph.cpp +++ b/gtsam/hybrid/tests/testHybridGaussianFactorGraph.cpp @@ -40,7 +40,6 @@ #include #include -#include #include #include #include @@ -49,8 +48,6 @@ #include "Switching.h" -using namespace boost::assign; - using namespace std; using namespace gtsam; From 2c27669d6552075b1006bc7101c91bc8e771c336 Mon Sep 17 00:00:00 2001 From: Frank Dellaert Date: Sat, 31 Dec 2022 01:58:48 -0500 Subject: [PATCH 8/8] Fix wrapper --- gtsam/hybrid/hybrid.i | 9 +++++++++ gtsam/linear/linear.i | 1 + 2 files changed, 10 insertions(+) diff --git a/gtsam/hybrid/hybrid.i b/gtsam/hybrid/hybrid.i index 3c74d1ee20..21a496eee5 100644 --- a/gtsam/hybrid/hybrid.i +++ b/gtsam/hybrid/hybrid.i @@ -15,9 +15,18 @@ class HybridValues { const gtsam::KeyFormatter& keyFormatter = gtsam::DefaultKeyFormatter) const; bool equals(const gtsam::HybridValues& other, double tol) const; + void insert(gtsam::Key j, int value); void insert(gtsam::Key j, const gtsam::Vector& value); + + void insert(const gtsam::VectorValues& values); + void insert(const gtsam::DiscreteValues& values); + void insert(const gtsam::HybridValues& values); + void update(const gtsam::VectorValues& values); + void update(const gtsam::DiscreteValues& values); + void update(const gtsam::HybridValues& values); + size_t& atDiscrete(gtsam::Key j); gtsam::Vector& at(gtsam::Key j); }; diff --git a/gtsam/linear/linear.i b/gtsam/linear/linear.i index 6f241da55f..0b6445c6c7 100644 --- a/gtsam/linear/linear.i +++ b/gtsam/linear/linear.i @@ -237,6 +237,7 @@ class VectorValues { void insert(size_t j, Vector value); Vector vector() const; Vector at(size_t j) const; + void insert(const gtsam::VectorValues& values); void update(const gtsam::VectorValues& values); //Advanced Interface