bug fixes after COLAMD activiation: BayesTree::insert was wrong, BayesTree::removeTop/Path fixed and simplified
parent
66607897a5
commit
d2291a38d1
|
|
@ -264,11 +264,11 @@ namespace gtsam {
|
|||
|
||||
/* ************************************************************************* */
|
||||
template<class Conditional>
|
||||
void BayesTree<Conditional>::insert(const sharedConditional& conditional)
|
||||
void BayesTree<Conditional>::insert(const sharedConditional& conditional, const list<Symbol>* ordering)
|
||||
{
|
||||
// get key and parents
|
||||
const Symbol& key = conditional->key();
|
||||
list<Symbol> parents = conditional->parents(); // rtodo: const reference?
|
||||
list<Symbol> parents = conditional->parents(); // todo: const reference?
|
||||
|
||||
// if no parents, start a new root clique
|
||||
if (parents.empty()) {
|
||||
|
|
@ -277,7 +277,18 @@ namespace gtsam {
|
|||
}
|
||||
|
||||
// otherwise, find the parent clique
|
||||
Symbol parent = parents.front();
|
||||
Symbol parent;
|
||||
if (!ordering) {
|
||||
parent = parents.front(); // assumes parents are in current variable order, which is not the case (after COLAMD was activated)
|
||||
} else {
|
||||
for (list<Symbol>::const_iterator it = ordering->begin(); it!=ordering->end(); it++) {
|
||||
list<Symbol>::iterator pit = find(parents.begin(), parents.end(), *it);
|
||||
if (pit!=parents.end()) {
|
||||
parent = *pit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
sharedClique parent_clique = (*this)[parent];
|
||||
|
||||
// if the parents and parent clique have the same size, add to parent clique
|
||||
|
|
@ -370,20 +381,25 @@ namespace gtsam {
|
|||
/* ************************************************************************* */
|
||||
template<class Conditional>
|
||||
template<class Factor>
|
||||
pair<FactorGraph<Factor>, typename BayesTree<Conditional>::Cliques>
|
||||
BayesTree<Conditional>::removePath(sharedClique clique) {
|
||||
|
||||
FactorGraph<Factor> factors;
|
||||
Cliques orphans;
|
||||
void BayesTree<Conditional>::removePath(sharedClique clique,
|
||||
FactorGraph<Factor> &factors, typename BayesTree<Conditional>::Cliques& orphans) {
|
||||
|
||||
// base case is NULL, if so we do nothing and return empties above
|
||||
if (clique!=NULL) {
|
||||
|
||||
#if 0
|
||||
printf("++++++ removing\n");
|
||||
clique->print();
|
||||
#endif
|
||||
|
||||
// remove the clique from orphans in case it has been added earlier
|
||||
orphans.remove(clique);
|
||||
|
||||
// remove me
|
||||
this->removeClique(clique);
|
||||
|
||||
// remove path above me
|
||||
boost::tie(factors,orphans) = this->removePath<Factor>(clique->parent_);
|
||||
this->removePath<Factor>(clique->parent_, factors, orphans);
|
||||
|
||||
// add children to list of orphans (splice also removed them from clique->children_)
|
||||
orphans.splice (orphans.begin(), clique->children_);
|
||||
|
|
@ -394,31 +410,30 @@ namespace gtsam {
|
|||
// add to the list of "invalidated" factors
|
||||
factors.push_back(clique_factors);
|
||||
|
||||
}
|
||||
#if 0
|
||||
printf("++++++ factors\n");
|
||||
factors.print();
|
||||
printf("++++++ orphans\n");
|
||||
orphans.print();
|
||||
#endif
|
||||
|
||||
return make_pair(factors,orphans);
|
||||
}
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
template<class Conditional>
|
||||
template<class Factor>
|
||||
void BayesTree<Conditional>::removeTop(const list<Symbol>& keys,
|
||||
FactorGraph<Factor> &factors, typename BayesTree<Conditional>::Cliques& orphans) {
|
||||
FactorGraph<Factor> &factors, typename BayesTree<Conditional>::Cliques& orphans) {
|
||||
|
||||
// process each key of the new factor
|
||||
BOOST_FOREACH(const Symbol& key, keys)
|
||||
try {
|
||||
// get the clique and remove it from orphans (if it exists)
|
||||
// get the clique
|
||||
sharedClique clique = (*this)[key];
|
||||
orphans.remove(clique);
|
||||
|
||||
// remove path from clique to root
|
||||
FactorGraph<Factor> factors1; Cliques orphans1;
|
||||
boost::tie(factors1,orphans1) = this->removePath<Factor>(clique);
|
||||
|
||||
// add to global factors and orphans
|
||||
factors.push_back(factors1);
|
||||
orphans.splice (orphans.begin(), orphans1);
|
||||
this->removePath<Factor>(clique, factors, orphans);
|
||||
|
||||
} catch (std::invalid_argument e) {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ namespace gtsam {
|
|||
bool equals(const BayesTree<Conditional>& other, double tol = 1e-9) const;
|
||||
|
||||
/** insert a new conditional */
|
||||
void insert(const sharedConditional& conditional);
|
||||
void insert(const sharedConditional& conditional, const std::list<Symbol>* ordering = NULL);
|
||||
|
||||
/** number of cliques */
|
||||
inline size_t size() const {
|
||||
|
|
@ -171,7 +171,7 @@ namespace gtsam {
|
|||
* plus a list of orphaned subtree roots. Used in removeTop below.
|
||||
*/
|
||||
template<class Factor>
|
||||
std::pair<FactorGraph<Factor>, Cliques> removePath(sharedClique clique);
|
||||
void removePath(sharedClique clique, FactorGraph<Factor> &factors, Cliques& orphans);
|
||||
|
||||
/**
|
||||
* Given a list of keys, turn "contaminated" part of the tree back into a factor graph.
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace gtsam {
|
|||
boost::shared_ptr<GaussianConditional> conditional;
|
||||
boost::tie(conditional, factor) = joint_factor->eliminate(key);
|
||||
|
||||
// remember the intermediate result to be able to later restart computation in the middle
|
||||
// ADDED: remember the intermediate result to be able to later restart computation in the middle
|
||||
cached[key] = factor;
|
||||
|
||||
// add new factor on separator back into the graph
|
||||
|
|
@ -119,12 +119,14 @@ namespace gtsam {
|
|||
void ISAM2<Conditional, Config>::update_internal(const NonlinearFactorGraph<Config>& newFactors,
|
||||
const Config& config, Cliques& orphans) {
|
||||
|
||||
|
||||
#if 1
|
||||
// determine which variables to relinearize
|
||||
|
||||
FactorGraph<GaussianFactor> affectedFactors;
|
||||
list<Symbol> newFactorsKeys = newFactors.keys();
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
|
||||
// relinearize all keys that are in newFactors, and already exist (not new variables!)
|
||||
list<Symbol> keysToRelinearize;
|
||||
|
|
@ -155,6 +157,15 @@ namespace gtsam {
|
|||
list<Symbol> keysToBeRemoved = nonlinearFactors_.keys();
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
printf("original tree\n");
|
||||
this->print();
|
||||
printf("ToBeRemoved\n");
|
||||
BOOST_FOREACH(string key, keysToBeRemoved) {
|
||||
printf("%s ", key.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
// remove affected factors
|
||||
this->removeTop(keysToBeRemoved, affectedFactors, orphans);
|
||||
|
||||
|
|
@ -170,9 +181,23 @@ namespace gtsam {
|
|||
list<Symbol> affectedKeys = affectedFactors.keys();
|
||||
FactorGraph<GaussianFactor> factors = relinearizeAffectedFactors(affectedKeys); // todo: searches through all factors, potentially expensive
|
||||
|
||||
#if 0
|
||||
printf("affected factors:\n");
|
||||
factors.print();
|
||||
#endif
|
||||
|
||||
// ... add the cached intermediate results from the boundary of the orphans ...
|
||||
FactorGraph<GaussianFactor> cachedBoundary = getCachedBoundaryFactors(orphans);
|
||||
factors.push_back(cachedBoundary);
|
||||
#else
|
||||
// todo - debug only: batch operation
|
||||
FactorGraph<GaussianFactor> affectedFactors;
|
||||
list<Symbol> keysToBeRemoved = nonlinearFactors_.keys();
|
||||
this->removeTop(keysToBeRemoved, affectedFactors, orphans);
|
||||
this->print("---------------");
|
||||
linPoint_ = expmap(linPoint_, delta_); // todo-debug only
|
||||
FactorGraph<GaussianFactor> factors = nonlinearFactors_.linearize(linPoint_);
|
||||
#endif
|
||||
|
||||
// add new variables
|
||||
linPoint_.insert(config);
|
||||
|
|
@ -198,8 +223,16 @@ namespace gtsam {
|
|||
|
||||
// insert conditionals back in, straight into the topless bayesTree
|
||||
typename BayesNet<Conditional>::const_reverse_iterator rit;
|
||||
for ( rit=bayesNet.rbegin(); rit != bayesNet.rend(); ++rit )
|
||||
this->insert(*rit);
|
||||
for ( rit=bayesNet.rbegin(); rit != bayesNet.rend(); ++rit ) {
|
||||
this->insert(*rit, &ordering);
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("new factors\n");
|
||||
newFactors.print();
|
||||
printf("orphans:\n");
|
||||
orphans.print();
|
||||
#endif
|
||||
|
||||
// add orphans to the bottom of the new tree
|
||||
BOOST_FOREACH(sharedClique orphan, orphans) {
|
||||
|
|
@ -211,6 +244,8 @@ namespace gtsam {
|
|||
orphan->parent_ = parent; // set new parent!
|
||||
}
|
||||
|
||||
// this->print();
|
||||
|
||||
// update solution - todo: potentially expensive
|
||||
delta_ = optimize2(*this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ TEST( BayesTree, removePath )
|
|||
|
||||
FactorGraph<SymbolicFactor> factors;
|
||||
SymbolicBayesTree::Cliques orphans;
|
||||
boost::tie(factors,orphans) = bayesTree.removePath<SymbolicFactor>(bayesTree["C"]);
|
||||
bayesTree.removePath<SymbolicFactor>(bayesTree["C"], factors, orphans);
|
||||
CHECK(assert_equal((FactorGraph<SymbolicFactor>)expected, factors));
|
||||
CHECK(assert_equal(expectedOrphans, orphans));
|
||||
|
||||
|
|
@ -155,9 +155,11 @@ TEST( BayesTree, removePath )
|
|||
SymbolicBayesTree::Cliques expectedOrphans2;
|
||||
expectedOrphans2 += bayesTree["F"];
|
||||
|
||||
boost::tie(factors,orphans) = bayesTree.removePath<SymbolicFactor>(bayesTree["E"]);
|
||||
CHECK(assert_equal((FactorGraph<SymbolicFactor>)expected2, factors));
|
||||
CHECK(assert_equal(expectedOrphans2, orphans));
|
||||
FactorGraph<SymbolicFactor> factors2;
|
||||
SymbolicBayesTree::Cliques orphans2;
|
||||
bayesTree.removePath<SymbolicFactor>(bayesTree["E"], factors2, orphans2);
|
||||
CHECK(assert_equal((FactorGraph<SymbolicFactor>)expected2, factors2));
|
||||
CHECK(assert_equal(expectedOrphans2, orphans2));
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
@ -168,7 +170,7 @@ TEST( BayesTree, removePath2 )
|
|||
// Call remove-path with clique B
|
||||
FactorGraph<SymbolicFactor> factors;
|
||||
SymbolicBayesTree::Cliques orphans;
|
||||
boost::tie(factors,orphans) = bayesTree.removePath<SymbolicFactor>(bayesTree["B"]);
|
||||
bayesTree.removePath<SymbolicFactor>(bayesTree["B"], factors, orphans);
|
||||
|
||||
// Check expected outcome
|
||||
SymbolicFactorGraph expected;
|
||||
|
|
@ -189,7 +191,7 @@ TEST( BayesTree, removePath3 )
|
|||
// Call remove-path with clique S
|
||||
FactorGraph<SymbolicFactor> factors;
|
||||
SymbolicBayesTree::Cliques orphans;
|
||||
boost::tie(factors,orphans) = bayesTree.removePath<SymbolicFactor>(bayesTree["S"]);
|
||||
bayesTree.removePath<SymbolicFactor>(bayesTree["S"], factors, orphans);
|
||||
|
||||
// Check expected outcome
|
||||
SymbolicFactorGraph expected;
|
||||
|
|
@ -238,7 +240,6 @@ TEST( BayesTree, removeTop )
|
|||
CHECK(assert_equal(expectedOrphans2, orphans2));
|
||||
}
|
||||
|
||||
|
||||
/* ************************************************************************* */
|
||||
TEST( BayesTree, removeTop2 )
|
||||
{
|
||||
|
|
@ -267,6 +268,32 @@ TEST( BayesTree, removeTop2 )
|
|||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
TEST( BayesTree, removeTop3 )
|
||||
{
|
||||
// simple test case that failed after COLAMD was fixed/activated
|
||||
SymbolicConditional::shared_ptr
|
||||
X(new SymbolicConditional("l5")),
|
||||
A(new SymbolicConditional("x4", "l5")),
|
||||
B(new SymbolicConditional("x3", "x4")),
|
||||
C(new SymbolicConditional("x2", "x3"));
|
||||
|
||||
SymbolicBayesTree bayesTree;
|
||||
bayesTree.insert(X);
|
||||
bayesTree.insert(A);
|
||||
bayesTree.insert(B);
|
||||
bayesTree.insert(C);
|
||||
|
||||
// remove all
|
||||
list<Symbol> keys;
|
||||
keys += "l5", "x2", "x3", "x4";
|
||||
FactorGraph<SymbolicFactor> factors;
|
||||
SymbolicBayesTree::Cliques orphans;
|
||||
bayesTree.removeTop<SymbolicFactor>(keys, factors, orphans);
|
||||
|
||||
CHECK(orphans.size() == 0);
|
||||
}
|
||||
/* ************************************************************************* */
|
||||
|
||||
int main() {
|
||||
TestResult tr;
|
||||
return TestRegistry::runAllTests(tr);
|
||||
|
|
|
|||
Loading…
Reference in New Issue