convert all optional Ordering to function overloads
compiles and passes tests, but some potentially code-breaking changes in: Marginals.h - order of arguments had to change since `factorization` has a default value EliminatableFactorGraph.h - marginalMultifrontalBayesNet and marginalMultifrontalBayesTree no longer accept `boost::none` as a placeholder to specify later arguments Notes: EliminateableFactorGraph.h - `orderingType` is no longer needed in function overloads that specify ordering, but I left it for the time being to avoid potential code breakingrelease/4.3a0
parent
5a358489dc
commit
1733f3ac98
|
@ -262,7 +262,7 @@ namespace gtsam {
|
||||||
|
|
||||||
// Now, marginalize out everything that is not variable j
|
// Now, marginalize out everything that is not variable j
|
||||||
BayesNetType marginalBN = *cliqueMarginal.marginalMultifrontalBayesNet(
|
BayesNetType marginalBN = *cliqueMarginal.marginalMultifrontalBayesNet(
|
||||||
Ordering(cref_list_of<1,Key>(j)), boost::none, function);
|
Ordering(cref_list_of<1,Key>(j)), function);
|
||||||
|
|
||||||
// The Bayes net should contain only one conditional for variable j, so return it
|
// The Bayes net should contain only one conditional for variable j, so return it
|
||||||
return marginalBN.front();
|
return marginalBN.front();
|
||||||
|
@ -383,7 +383,7 @@ namespace gtsam {
|
||||||
}
|
}
|
||||||
|
|
||||||
// now, marginalize out everything that is not variable j1 or j2
|
// now, marginalize out everything that is not variable j1 or j2
|
||||||
return p_BC1C2.marginalMultifrontalBayesNet(Ordering(cref_list_of<2,Key>(j1)(j2)), boost::none, function);
|
return p_BC1C2.marginalMultifrontalBayesNet(Ordering(cref_list_of<2,Key>(j1)(j2)), function);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
|
@ -171,7 +171,7 @@ namespace gtsam {
|
||||||
|
|
||||||
// The variables we want to keepSet are exactly the ones in S
|
// The variables we want to keepSet are exactly the ones in S
|
||||||
KeyVector indicesS(this->conditional()->beginParents(), this->conditional()->endParents());
|
KeyVector indicesS(this->conditional()->beginParents(), this->conditional()->endParents());
|
||||||
cachedSeparatorMarginal_ = *p_Cp.marginalMultifrontalBayesNet(Ordering(indicesS), boost::none, function);
|
cachedSeparatorMarginal_ = *p_Cp.marginalMultifrontalBayesNet(Ordering(indicesS), function);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,33 +28,19 @@ namespace gtsam {
|
||||||
template<class FACTORGRAPH>
|
template<class FACTORGRAPH>
|
||||||
boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesNetType>
|
boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesNetType>
|
||||||
EliminateableFactorGraph<FACTORGRAPH>::eliminateSequential(
|
EliminateableFactorGraph<FACTORGRAPH>::eliminateSequential(
|
||||||
OptionalOrdering ordering, const Eliminate& function,
|
const Eliminate& function, OptionalVariableIndex variableIndex,
|
||||||
OptionalVariableIndex variableIndex, OptionalOrderingType orderingType) const
|
OptionalOrderingType orderingType) const {
|
||||||
{
|
if(!variableIndex) {
|
||||||
if(ordering && variableIndex) {
|
|
||||||
gttic(eliminateSequential);
|
|
||||||
// Do elimination
|
|
||||||
EliminationTreeType etree(asDerived(), *variableIndex, *ordering);
|
|
||||||
boost::shared_ptr<BayesNetType> bayesNet;
|
|
||||||
boost::shared_ptr<FactorGraphType> factorGraph;
|
|
||||||
boost::tie(bayesNet,factorGraph) = etree.eliminate(function);
|
|
||||||
// If any factors are remaining, the ordering was incomplete
|
|
||||||
if(!factorGraph->empty())
|
|
||||||
throw InconsistentEliminationRequested();
|
|
||||||
// Return the Bayes net
|
|
||||||
return bayesNet;
|
|
||||||
}
|
|
||||||
else if(!variableIndex) {
|
|
||||||
// If no VariableIndex provided, compute one and call this function again IMPORTANT: we check
|
// If no VariableIndex provided, compute one and call this function again IMPORTANT: we check
|
||||||
// for no variable index first so that it's always computed if we need to call COLAMD because
|
// for no variable index first so that it's always computed if we need to call COLAMD because
|
||||||
// no Ordering is provided.
|
// no Ordering is provided. When removing optional from VariableIndex, create VariableIndex
|
||||||
|
// before creating ordering.
|
||||||
VariableIndex computedVariableIndex(asDerived());
|
VariableIndex computedVariableIndex(asDerived());
|
||||||
return eliminateSequential(ordering, function, computedVariableIndex, orderingType);
|
return eliminateSequential(function, computedVariableIndex, orderingType);
|
||||||
}
|
}
|
||||||
else /*if(!ordering)*/ {
|
else {
|
||||||
// If no Ordering provided, compute one and call this function again. We are guaranteed to
|
// Compute an ordering and call this function again. We are guaranteed to have a
|
||||||
// have a VariableIndex already here because we computed one if needed in the previous 'else'
|
// VariableIndex already here because we computed one if needed in the previous 'if' block.
|
||||||
// block.
|
|
||||||
if (orderingType == Ordering::METIS) {
|
if (orderingType == Ordering::METIS) {
|
||||||
Ordering computedOrdering = Ordering::Metis(asDerived());
|
Ordering computedOrdering = Ordering::Metis(asDerived());
|
||||||
return eliminateSequential(computedOrdering, function, variableIndex, orderingType);
|
return eliminateSequential(computedOrdering, function, variableIndex, orderingType);
|
||||||
|
@ -67,15 +53,73 @@ namespace gtsam {
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template<class FACTORGRAPH>
|
template<class FACTORGRAPH>
|
||||||
boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesTreeType>
|
boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesNetType>
|
||||||
EliminateableFactorGraph<FACTORGRAPH>::eliminateMultifrontal(
|
EliminateableFactorGraph<FACTORGRAPH>::eliminateSequential(
|
||||||
OptionalOrdering ordering, const Eliminate& function,
|
const Ordering& ordering, const Eliminate& function,
|
||||||
OptionalVariableIndex variableIndex, OptionalOrderingType orderingType) const
|
OptionalVariableIndex variableIndex, OptionalOrderingType orderingType) const
|
||||||
{
|
{
|
||||||
if(ordering && variableIndex) {
|
if(!variableIndex) {
|
||||||
|
// If no VariableIndex provided, compute one and call this function again
|
||||||
|
VariableIndex computedVariableIndex(asDerived());
|
||||||
|
return eliminateSequential(ordering, function, computedVariableIndex, orderingType);
|
||||||
|
} else {
|
||||||
|
gttic(eliminateSequential);
|
||||||
|
// Do elimination
|
||||||
|
EliminationTreeType etree(asDerived(), *variableIndex, ordering);
|
||||||
|
boost::shared_ptr<BayesNetType> bayesNet;
|
||||||
|
boost::shared_ptr<FactorGraphType> factorGraph;
|
||||||
|
boost::tie(bayesNet,factorGraph) = etree.eliminate(function);
|
||||||
|
// If any factors are remaining, the ordering was incomplete
|
||||||
|
if(!factorGraph->empty())
|
||||||
|
throw InconsistentEliminationRequested();
|
||||||
|
// Return the Bayes net
|
||||||
|
return bayesNet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class FACTORGRAPH>
|
||||||
|
boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesTreeType>
|
||||||
|
EliminateableFactorGraph<FACTORGRAPH>::eliminateMultifrontal(
|
||||||
|
const Eliminate& function, OptionalVariableIndex variableIndex,
|
||||||
|
OptionalOrderingType orderingType) const
|
||||||
|
{
|
||||||
|
if(!variableIndex) {
|
||||||
|
// If no VariableIndex provided, compute one and call this function again IMPORTANT: we check
|
||||||
|
// for no variable index first so that it's always computed if we need to call COLAMD because
|
||||||
|
// no Ordering is provided. When removing optional from VariableIndex, create VariableIndex
|
||||||
|
// before creating ordering.
|
||||||
|
VariableIndex computedVariableIndex(asDerived());
|
||||||
|
return eliminateMultifrontal(function, computedVariableIndex, orderingType);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Compute an ordering and call this function again. We are guaranteed to have a
|
||||||
|
// VariableIndex already here because we computed one if needed in the previous 'if' block.
|
||||||
|
if (orderingType == Ordering::METIS) {
|
||||||
|
Ordering computedOrdering = Ordering::Metis(asDerived());
|
||||||
|
return eliminateMultifrontal(computedOrdering, function, variableIndex, orderingType);
|
||||||
|
} else {
|
||||||
|
Ordering computedOrdering = Ordering::Colamd(*variableIndex);
|
||||||
|
return eliminateMultifrontal(computedOrdering, function, variableIndex, orderingType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class FACTORGRAPH>
|
||||||
|
boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesTreeType>
|
||||||
|
EliminateableFactorGraph<FACTORGRAPH>::eliminateMultifrontal(
|
||||||
|
const Ordering& ordering, const Eliminate& function,
|
||||||
|
OptionalVariableIndex variableIndex, OptionalOrderingType orderingType) const
|
||||||
|
{
|
||||||
|
if(!variableIndex) {
|
||||||
|
// If no VariableIndex provided, compute one and call this function again
|
||||||
|
VariableIndex computedVariableIndex(asDerived());
|
||||||
|
return eliminateMultifrontal(ordering, function, computedVariableIndex, orderingType);
|
||||||
|
} else {
|
||||||
gttic(eliminateMultifrontal);
|
gttic(eliminateMultifrontal);
|
||||||
// Do elimination with given ordering
|
// Do elimination with given ordering
|
||||||
EliminationTreeType etree(asDerived(), *variableIndex, *ordering);
|
EliminationTreeType etree(asDerived(), *variableIndex, ordering);
|
||||||
JunctionTreeType junctionTree(etree);
|
JunctionTreeType junctionTree(etree);
|
||||||
boost::shared_ptr<BayesTreeType> bayesTree;
|
boost::shared_ptr<BayesTreeType> bayesTree;
|
||||||
boost::shared_ptr<FactorGraphType> factorGraph;
|
boost::shared_ptr<FactorGraphType> factorGraph;
|
||||||
|
@ -86,25 +130,6 @@ namespace gtsam {
|
||||||
// Return the Bayes tree
|
// Return the Bayes tree
|
||||||
return bayesTree;
|
return bayesTree;
|
||||||
}
|
}
|
||||||
else if(!variableIndex) {
|
|
||||||
// If no VariableIndex provided, compute one and call this function again IMPORTANT: we check
|
|
||||||
// for no variable index first so that it's always computed if we need to call COLAMD because
|
|
||||||
// no Ordering is provided.
|
|
||||||
VariableIndex computedVariableIndex(asDerived());
|
|
||||||
return eliminateMultifrontal(ordering, function, computedVariableIndex, orderingType);
|
|
||||||
}
|
|
||||||
else /*if(!ordering)*/ {
|
|
||||||
// If no Ordering provided, compute one and call this function again. We are guaranteed to
|
|
||||||
// have a VariableIndex already here because we computed one if needed in the previous 'else'
|
|
||||||
// block.
|
|
||||||
if (orderingType == Ordering::METIS) {
|
|
||||||
Ordering computedOrdering = Ordering::Metis(asDerived());
|
|
||||||
return eliminateMultifrontal(computedOrdering, function, variableIndex, orderingType);
|
|
||||||
} else {
|
|
||||||
Ordering computedOrdering = Ordering::Colamd(*variableIndex);
|
|
||||||
return eliminateMultifrontal(computedOrdering, function, variableIndex, orderingType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
@ -191,57 +216,65 @@ namespace gtsam {
|
||||||
boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesNetType>
|
boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesNetType>
|
||||||
EliminateableFactorGraph<FACTORGRAPH>::marginalMultifrontalBayesNet(
|
EliminateableFactorGraph<FACTORGRAPH>::marginalMultifrontalBayesNet(
|
||||||
boost::variant<const Ordering&, const KeyVector&> variables,
|
boost::variant<const Ordering&, const KeyVector&> variables,
|
||||||
OptionalOrdering marginalizedVariableOrdering,
|
|
||||||
const Eliminate& function, OptionalVariableIndex variableIndex) const
|
const Eliminate& function, OptionalVariableIndex variableIndex) const
|
||||||
{
|
{
|
||||||
if(variableIndex)
|
if(!variableIndex) {
|
||||||
{
|
// If no variable index is provided, compute one and call this function again
|
||||||
if(marginalizedVariableOrdering)
|
VariableIndex index(asDerived());
|
||||||
{
|
return marginalMultifrontalBayesNet(variables, function, index);
|
||||||
gttic(marginalMultifrontalBayesNet);
|
|
||||||
// An ordering was provided for the marginalized variables, so we can first eliminate them
|
|
||||||
// in the order requested.
|
|
||||||
boost::shared_ptr<BayesTreeType> bayesTree;
|
|
||||||
boost::shared_ptr<FactorGraphType> factorGraph;
|
|
||||||
boost::tie(bayesTree,factorGraph) =
|
|
||||||
eliminatePartialMultifrontal(*marginalizedVariableOrdering, function, *variableIndex);
|
|
||||||
|
|
||||||
if(const Ordering* varsAsOrdering = boost::get<const Ordering&>(&variables))
|
|
||||||
{
|
|
||||||
// An ordering was also provided for the unmarginalized variables, so we can also
|
|
||||||
// eliminate them in the order requested.
|
|
||||||
return factorGraph->eliminateSequential(*varsAsOrdering, function);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No ordering was provided for the unmarginalized variables, so order them with COLAMD.
|
|
||||||
return factorGraph->eliminateSequential(boost::none, function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No ordering was provided for the marginalized variables, so order them using constrained
|
|
||||||
// COLAMD.
|
|
||||||
bool unmarginalizedAreOrdered = (boost::get<const Ordering&>(&variables) != 0);
|
|
||||||
const KeyVector* variablesOrOrdering =
|
|
||||||
unmarginalizedAreOrdered ?
|
|
||||||
boost::get<const Ordering&>(&variables) : boost::get<const KeyVector&>(&variables);
|
|
||||||
|
|
||||||
Ordering totalOrdering =
|
|
||||||
Ordering::ColamdConstrainedLast(*variableIndex, *variablesOrOrdering, unmarginalizedAreOrdered);
|
|
||||||
|
|
||||||
// Split up ordering
|
|
||||||
const size_t nVars = variablesOrOrdering->size();
|
|
||||||
Ordering marginalizationOrdering(totalOrdering.begin(), totalOrdering.end() - nVars);
|
|
||||||
Ordering marginalVarsOrdering(totalOrdering.end() - nVars, totalOrdering.end());
|
|
||||||
|
|
||||||
// Call this function again with the computed orderings
|
|
||||||
return marginalMultifrontalBayesNet(marginalVarsOrdering, marginalizationOrdering, function, *variableIndex);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
// No ordering was provided for the marginalized variables, so order them using constrained
|
||||||
|
// COLAMD.
|
||||||
|
bool unmarginalizedAreOrdered = (boost::get<const Ordering&>(&variables) != 0);
|
||||||
|
const KeyVector* variablesOrOrdering =
|
||||||
|
unmarginalizedAreOrdered ?
|
||||||
|
boost::get<const Ordering&>(&variables) : boost::get<const KeyVector&>(&variables);
|
||||||
|
|
||||||
|
Ordering totalOrdering =
|
||||||
|
Ordering::ColamdConstrainedLast(*variableIndex, *variablesOrOrdering, unmarginalizedAreOrdered);
|
||||||
|
|
||||||
|
// Split up ordering
|
||||||
|
const size_t nVars = variablesOrOrdering->size();
|
||||||
|
Ordering marginalizationOrdering(totalOrdering.begin(), totalOrdering.end() - nVars);
|
||||||
|
Ordering marginalVarsOrdering(totalOrdering.end() - nVars, totalOrdering.end());
|
||||||
|
|
||||||
|
// Call this function again with the computed orderings
|
||||||
|
return marginalMultifrontalBayesNet(marginalVarsOrdering, marginalizationOrdering, function, *variableIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class FACTORGRAPH>
|
||||||
|
boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesNetType>
|
||||||
|
EliminateableFactorGraph<FACTORGRAPH>::marginalMultifrontalBayesNet(
|
||||||
|
boost::variant<const Ordering&, const KeyVector&> variables,
|
||||||
|
const Ordering& marginalizedVariableOrdering,
|
||||||
|
const Eliminate& function, OptionalVariableIndex variableIndex) const
|
||||||
|
{
|
||||||
|
if(!variableIndex) {
|
||||||
// If no variable index is provided, compute one and call this function again
|
// If no variable index is provided, compute one and call this function again
|
||||||
VariableIndex index(asDerived());
|
VariableIndex index(asDerived());
|
||||||
return marginalMultifrontalBayesNet(variables, marginalizedVariableOrdering, function, index);
|
return marginalMultifrontalBayesNet(variables, marginalizedVariableOrdering, function, index);
|
||||||
|
} else {
|
||||||
|
gttic(marginalMultifrontalBayesNet);
|
||||||
|
// An ordering was provided for the marginalized variables, so we can first eliminate them
|
||||||
|
// in the order requested.
|
||||||
|
boost::shared_ptr<BayesTreeType> bayesTree;
|
||||||
|
boost::shared_ptr<FactorGraphType> factorGraph;
|
||||||
|
boost::tie(bayesTree,factorGraph) =
|
||||||
|
eliminatePartialMultifrontal(marginalizedVariableOrdering, function, *variableIndex);
|
||||||
|
|
||||||
|
if(const Ordering* varsAsOrdering = boost::get<const Ordering&>(&variables))
|
||||||
|
{
|
||||||
|
// An ordering was also provided for the unmarginalized variables, so we can also
|
||||||
|
// eliminate them in the order requested.
|
||||||
|
return factorGraph->eliminateSequential(*varsAsOrdering, function);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No ordering was provided for the unmarginalized variables, so order them with COLAMD.
|
||||||
|
return factorGraph->eliminateSequential(function);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,57 +283,65 @@ namespace gtsam {
|
||||||
boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesTreeType>
|
boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesTreeType>
|
||||||
EliminateableFactorGraph<FACTORGRAPH>::marginalMultifrontalBayesTree(
|
EliminateableFactorGraph<FACTORGRAPH>::marginalMultifrontalBayesTree(
|
||||||
boost::variant<const Ordering&, const KeyVector&> variables,
|
boost::variant<const Ordering&, const KeyVector&> variables,
|
||||||
OptionalOrdering marginalizedVariableOrdering,
|
|
||||||
const Eliminate& function, OptionalVariableIndex variableIndex) const
|
const Eliminate& function, OptionalVariableIndex variableIndex) const
|
||||||
{
|
{
|
||||||
if(variableIndex)
|
if(!variableIndex) {
|
||||||
{
|
// If no variable index is provided, compute one and call this function again
|
||||||
if(marginalizedVariableOrdering)
|
VariableIndex computedVariableIndex(asDerived());
|
||||||
{
|
return marginalMultifrontalBayesTree(variables, function, computedVariableIndex);
|
||||||
gttic(marginalMultifrontalBayesTree);
|
|
||||||
// An ordering was provided for the marginalized variables, so we can first eliminate them
|
|
||||||
// in the order requested.
|
|
||||||
boost::shared_ptr<BayesTreeType> bayesTree;
|
|
||||||
boost::shared_ptr<FactorGraphType> factorGraph;
|
|
||||||
boost::tie(bayesTree,factorGraph) =
|
|
||||||
eliminatePartialMultifrontal(*marginalizedVariableOrdering, function, *variableIndex);
|
|
||||||
|
|
||||||
if(const Ordering* varsAsOrdering = boost::get<const Ordering&>(&variables))
|
|
||||||
{
|
|
||||||
// An ordering was also provided for the unmarginalized variables, so we can also
|
|
||||||
// eliminate them in the order requested.
|
|
||||||
return factorGraph->eliminateMultifrontal(*varsAsOrdering, function);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No ordering was provided for the unmarginalized variables, so order them with COLAMD.
|
|
||||||
return factorGraph->eliminateMultifrontal(boost::none, function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No ordering was provided for the marginalized variables, so order them using constrained
|
|
||||||
// COLAMD.
|
|
||||||
bool unmarginalizedAreOrdered = (boost::get<const Ordering&>(&variables) != 0);
|
|
||||||
const KeyVector* variablesOrOrdering =
|
|
||||||
unmarginalizedAreOrdered ?
|
|
||||||
boost::get<const Ordering&>(&variables) : boost::get<const KeyVector&>(&variables);
|
|
||||||
|
|
||||||
Ordering totalOrdering =
|
|
||||||
Ordering::ColamdConstrainedLast(*variableIndex, *variablesOrOrdering, unmarginalizedAreOrdered);
|
|
||||||
|
|
||||||
// Split up ordering
|
|
||||||
const size_t nVars = variablesOrOrdering->size();
|
|
||||||
Ordering marginalizationOrdering(totalOrdering.begin(), totalOrdering.end() - nVars);
|
|
||||||
Ordering marginalVarsOrdering(totalOrdering.end() - nVars, totalOrdering.end());
|
|
||||||
|
|
||||||
// Call this function again with the computed orderings
|
|
||||||
return marginalMultifrontalBayesTree(marginalVarsOrdering, marginalizationOrdering, function, *variableIndex);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
// No ordering was provided for the marginalized variables, so order them using constrained
|
||||||
|
// COLAMD.
|
||||||
|
bool unmarginalizedAreOrdered = (boost::get<const Ordering&>(&variables) != 0);
|
||||||
|
const KeyVector* variablesOrOrdering =
|
||||||
|
unmarginalizedAreOrdered ?
|
||||||
|
boost::get<const Ordering&>(&variables) : boost::get<const KeyVector&>(&variables);
|
||||||
|
|
||||||
|
Ordering totalOrdering =
|
||||||
|
Ordering::ColamdConstrainedLast(*variableIndex, *variablesOrOrdering, unmarginalizedAreOrdered);
|
||||||
|
|
||||||
|
// Split up ordering
|
||||||
|
const size_t nVars = variablesOrOrdering->size();
|
||||||
|
Ordering marginalizationOrdering(totalOrdering.begin(), totalOrdering.end() - nVars);
|
||||||
|
Ordering marginalVarsOrdering(totalOrdering.end() - nVars, totalOrdering.end());
|
||||||
|
|
||||||
|
// Call this function again with the computed orderings
|
||||||
|
return marginalMultifrontalBayesTree(marginalVarsOrdering, marginalizationOrdering, function, *variableIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class FACTORGRAPH>
|
||||||
|
boost::shared_ptr<typename EliminateableFactorGraph<FACTORGRAPH>::BayesTreeType>
|
||||||
|
EliminateableFactorGraph<FACTORGRAPH>::marginalMultifrontalBayesTree(
|
||||||
|
boost::variant<const Ordering&, const KeyVector&> variables,
|
||||||
|
const Ordering& marginalizedVariableOrdering,
|
||||||
|
const Eliminate& function, OptionalVariableIndex variableIndex) const
|
||||||
|
{
|
||||||
|
if(!variableIndex) {
|
||||||
// If no variable index is provided, compute one and call this function again
|
// If no variable index is provided, compute one and call this function again
|
||||||
VariableIndex computedVariableIndex(asDerived());
|
VariableIndex computedVariableIndex(asDerived());
|
||||||
return marginalMultifrontalBayesTree(variables, marginalizedVariableOrdering, function, computedVariableIndex);
|
return marginalMultifrontalBayesTree(variables, marginalizedVariableOrdering, function, computedVariableIndex);
|
||||||
|
} else {
|
||||||
|
gttic(marginalMultifrontalBayesTree);
|
||||||
|
// An ordering was provided for the marginalized variables, so we can first eliminate them
|
||||||
|
// in the order requested.
|
||||||
|
boost::shared_ptr<BayesTreeType> bayesTree;
|
||||||
|
boost::shared_ptr<FactorGraphType> factorGraph;
|
||||||
|
boost::tie(bayesTree,factorGraph) =
|
||||||
|
eliminatePartialMultifrontal(marginalizedVariableOrdering, function, *variableIndex);
|
||||||
|
|
||||||
|
if(const Ordering* varsAsOrdering = boost::get<const Ordering&>(&variables))
|
||||||
|
{
|
||||||
|
// An ordering was also provided for the unmarginalized variables, so we can also
|
||||||
|
// eliminate them in the order requested.
|
||||||
|
return factorGraph->eliminateMultifrontal(*varsAsOrdering, function);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No ordering was provided for the unmarginalized variables, so order them with COLAMD.
|
||||||
|
return factorGraph->eliminateMultifrontal(function);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,9 +88,6 @@ namespace gtsam {
|
||||||
/// The function type that does a single dense elimination step on a subgraph.
|
/// The function type that does a single dense elimination step on a subgraph.
|
||||||
typedef boost::function<EliminationResult(const FactorGraphType&, const Ordering&)> Eliminate;
|
typedef boost::function<EliminationResult(const FactorGraphType&, const Ordering&)> Eliminate;
|
||||||
|
|
||||||
/// Typedef for an optional ordering as an argument to elimination functions
|
|
||||||
typedef const boost::optional<Ordering>& OptionalOrdering;
|
|
||||||
|
|
||||||
/// Typedef for an optional variable index as an argument to elimination functions
|
/// Typedef for an optional variable index as an argument to elimination functions
|
||||||
typedef const boost::optional<VariableIndex>& OptionalVariableIndex;
|
typedef const boost::optional<VariableIndex>& OptionalVariableIndex;
|
||||||
|
|
||||||
|
@ -108,25 +105,40 @@ namespace gtsam {
|
||||||
* <b> Example - METIS ordering for elimination
|
* <b> Example - METIS ordering for elimination
|
||||||
* \code
|
* \code
|
||||||
* boost::shared_ptr<GaussianBayesNet> result = graph.eliminateSequential(OrderingType::METIS);
|
* boost::shared_ptr<GaussianBayesNet> result = graph.eliminateSequential(OrderingType::METIS);
|
||||||
*
|
|
||||||
* <b> Example - Full QR elimination in specified order:
|
|
||||||
* \code
|
|
||||||
* boost::shared_ptr<GaussianBayesNet> result = graph.eliminateSequential(EliminateQR, myOrdering);
|
|
||||||
* \endcode
|
* \endcode
|
||||||
*
|
*
|
||||||
* <b> Example - Reusing an existing VariableIndex to improve performance, and using COLAMD ordering: </b>
|
* <b> Example - Reusing an existing VariableIndex to improve performance, and using COLAMD ordering: </b>
|
||||||
* \code
|
* \code
|
||||||
* VariableIndex varIndex(graph); // Build variable index
|
* VariableIndex varIndex(graph); // Build variable index
|
||||||
* Data data = otherFunctionUsingVariableIndex(graph, varIndex); // Other code that uses variable index
|
* Data data = otherFunctionUsingVariableIndex(graph, varIndex); // Other code that uses variable index
|
||||||
* boost::shared_ptr<GaussianBayesNet> result = graph.eliminateSequential(EliminateQR, boost::none, varIndex);
|
* boost::shared_ptr<GaussianBayesNet> result = graph.eliminateSequential(EliminateQR, varIndex, boost::none);
|
||||||
* \endcode
|
* \endcode
|
||||||
* */
|
* */
|
||||||
boost::shared_ptr<BayesNetType> eliminateSequential(
|
boost::shared_ptr<BayesNetType> eliminateSequential(
|
||||||
OptionalOrdering ordering = boost::none,
|
|
||||||
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
||||||
OptionalVariableIndex variableIndex = boost::none,
|
OptionalVariableIndex variableIndex = boost::none,
|
||||||
OptionalOrderingType orderingType = boost::none) const;
|
OptionalOrderingType orderingType = boost::none) const;
|
||||||
|
|
||||||
|
/** Do sequential elimination of all variables to produce a Bayes net.
|
||||||
|
*
|
||||||
|
* <b> Example - Full QR elimination in specified order:
|
||||||
|
* \code
|
||||||
|
* boost::shared_ptr<GaussianBayesNet> result = graph.eliminateSequential(myOrdering, EliminateQR);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* <b> Example - Reusing an existing VariableIndex to improve performance: </b>
|
||||||
|
* \code
|
||||||
|
* VariableIndex varIndex(graph); // Build variable index
|
||||||
|
* Data data = otherFunctionUsingVariableIndex(graph, varIndex); // Other code that uses variable index
|
||||||
|
* boost::shared_ptr<GaussianBayesNet> result = graph.eliminateSequential(myOrdering, EliminateQR, varIndex, boost::none);
|
||||||
|
* \endcode
|
||||||
|
* */
|
||||||
|
boost::shared_ptr<BayesNetType> eliminateSequential(
|
||||||
|
const Ordering& ordering,
|
||||||
|
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
||||||
|
OptionalVariableIndex variableIndex = boost::none,
|
||||||
|
OptionalOrderingType orderingType = boost::none) const; // orderingType is not necessary anymore, kept for backwards compatibility
|
||||||
|
|
||||||
/** Do multifrontal elimination of all variables to produce a Bayes tree. If an ordering is not
|
/** Do multifrontal elimination of all variables to produce a Bayes tree. If an ordering is not
|
||||||
* provided, the ordering will be computed using either COLAMD or METIS, dependeing on
|
* provided, the ordering will be computed using either COLAMD or METIS, dependeing on
|
||||||
* the parameter orderingType (Ordering::COLAMD or Ordering::METIS)
|
* the parameter orderingType (Ordering::COLAMD or Ordering::METIS)
|
||||||
|
@ -136,11 +148,6 @@ namespace gtsam {
|
||||||
* boost::shared_ptr<GaussianBayesTree> result = graph.eliminateMultifrontal(EliminateCholesky);
|
* boost::shared_ptr<GaussianBayesTree> result = graph.eliminateMultifrontal(EliminateCholesky);
|
||||||
* \endcode
|
* \endcode
|
||||||
*
|
*
|
||||||
* <b> Example - Full QR elimination in specified order:
|
|
||||||
* \code
|
|
||||||
* boost::shared_ptr<GaussianBayesTree> result = graph.eliminateMultifrontal(EliminateQR, myOrdering);
|
|
||||||
* \endcode
|
|
||||||
*
|
|
||||||
* <b> Example - Reusing an existing VariableIndex to improve performance, and using COLAMD ordering: </b>
|
* <b> Example - Reusing an existing VariableIndex to improve performance, and using COLAMD ordering: </b>
|
||||||
* \code
|
* \code
|
||||||
* VariableIndex varIndex(graph); // Build variable index
|
* VariableIndex varIndex(graph); // Build variable index
|
||||||
|
@ -149,11 +156,25 @@ namespace gtsam {
|
||||||
* \endcode
|
* \endcode
|
||||||
* */
|
* */
|
||||||
boost::shared_ptr<BayesTreeType> eliminateMultifrontal(
|
boost::shared_ptr<BayesTreeType> eliminateMultifrontal(
|
||||||
OptionalOrdering ordering = boost::none,
|
|
||||||
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
||||||
OptionalVariableIndex variableIndex = boost::none,
|
OptionalVariableIndex variableIndex = boost::none,
|
||||||
OptionalOrderingType orderingType = boost::none) const;
|
OptionalOrderingType orderingType = boost::none) const;
|
||||||
|
|
||||||
|
/** Do multifrontal elimination of all variables to produce a Bayes tree. If an ordering is not
|
||||||
|
* provided, the ordering will be computed using either COLAMD or METIS, dependeing on
|
||||||
|
* the parameter orderingType (Ordering::COLAMD or Ordering::METIS)
|
||||||
|
*
|
||||||
|
* <b> Example - Full QR elimination in specified order:
|
||||||
|
* \code
|
||||||
|
* boost::shared_ptr<GaussianBayesTree> result = graph.eliminateMultifrontal(EliminateQR, myOrdering);
|
||||||
|
* \endcode
|
||||||
|
* */
|
||||||
|
boost::shared_ptr<BayesTreeType> eliminateMultifrontal(
|
||||||
|
const Ordering& ordering,
|
||||||
|
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
||||||
|
OptionalVariableIndex variableIndex = boost::none,
|
||||||
|
OptionalOrderingType orderingType = boost::none) const; // orderingType no longer needed
|
||||||
|
|
||||||
/** Do sequential elimination of some variables, in \c ordering provided, to produce a Bayes net
|
/** Do sequential elimination of some variables, in \c ordering provided, to produce a Bayes net
|
||||||
* and a remaining factor graph. This computes the factorization \f$ p(X) = p(A|B) p(B) \f$,
|
* and a remaining factor graph. This computes the factorization \f$ p(X) = p(A|B) p(B) \f$,
|
||||||
* where \f$ A = \f$ \c variables, \f$ X \f$ is all the variables in the factor graph, and \f$
|
* where \f$ A = \f$ \c variables, \f$ X \f$ is all the variables in the factor graph, and \f$
|
||||||
|
@ -194,20 +215,47 @@ namespace gtsam {
|
||||||
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
||||||
OptionalVariableIndex variableIndex = boost::none) const;
|
OptionalVariableIndex variableIndex = boost::none) const;
|
||||||
|
|
||||||
/** Compute the marginal of the requested variables and return the result as a Bayes net.
|
/** Compute the marginal of the requested variables and return the result as a Bayes net. Uses
|
||||||
|
* COLAMD marginalization ordering by default
|
||||||
* @param variables Determines the variables whose marginal to compute, if provided as an
|
* @param variables Determines the variables whose marginal to compute, if provided as an
|
||||||
* Ordering they will be ordered in the returned BayesNet as specified, and if provided
|
* Ordering they will be ordered in the returned BayesNet as specified, and if provided
|
||||||
* as a KeyVector they will be ordered using constrained COLAMD.
|
* as a KeyVector they will be ordered using constrained COLAMD.
|
||||||
* @param marginalizedVariableOrdering Optional ordering for the variables being marginalized
|
|
||||||
* out, i.e. all variables not in \c variables. If this is boost::none, the ordering
|
|
||||||
* will be computed with COLAMD.
|
|
||||||
* @param function Optional dense elimination function, if not provided the default will be
|
* @param function Optional dense elimination function, if not provided the default will be
|
||||||
* used.
|
* used.
|
||||||
* @param variableIndex Optional pre-computed VariableIndex for the factor graph, if not
|
* @param variableIndex Optional pre-computed VariableIndex for the factor graph, if not
|
||||||
* provided one will be computed. */
|
* provided one will be computed. */
|
||||||
boost::shared_ptr<BayesNetType> marginalMultifrontalBayesNet(
|
boost::shared_ptr<BayesNetType> marginalMultifrontalBayesNet(
|
||||||
boost::variant<const Ordering&, const KeyVector&> variables,
|
boost::variant<const Ordering&, const KeyVector&> variables,
|
||||||
OptionalOrdering marginalizedVariableOrdering = boost::none,
|
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
||||||
|
OptionalVariableIndex variableIndex = boost::none) const;
|
||||||
|
|
||||||
|
/** Compute the marginal of the requested variables and return the result as a Bayes net.
|
||||||
|
* @param variables Determines the variables whose marginal to compute, if provided as an
|
||||||
|
* Ordering they will be ordered in the returned BayesNet as specified, and if provided
|
||||||
|
* as a KeyVector they will be ordered using constrained COLAMD.
|
||||||
|
* @param marginalizedVariableOrdering Ordering for the variables being marginalized out,
|
||||||
|
* i.e. all variables not in \c variables.
|
||||||
|
* @param function Optional dense elimination function, if not provided the default will be
|
||||||
|
* used.
|
||||||
|
* @param variableIndex Optional pre-computed VariableIndex for the factor graph, if not
|
||||||
|
* provided one will be computed. */
|
||||||
|
boost::shared_ptr<BayesNetType> marginalMultifrontalBayesNet(
|
||||||
|
boost::variant<const Ordering&, const KeyVector&> variables,
|
||||||
|
const Ordering& marginalizedVariableOrdering, // this no longer takes boost::none - potentially code breaking
|
||||||
|
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
||||||
|
OptionalVariableIndex variableIndex = boost::none) const;
|
||||||
|
|
||||||
|
/** Compute the marginal of the requested variables and return the result as a Bayes tree. Uses
|
||||||
|
* COLAMD marginalization order by default
|
||||||
|
* @param variables Determines the variables whose marginal to compute, if provided as an
|
||||||
|
* Ordering they will be ordered in the returned BayesNet as specified, and if provided
|
||||||
|
* as a KeyVector they will be ordered using constrained COLAMD.
|
||||||
|
* @param function Optional dense elimination function, if not provided the default will be
|
||||||
|
* used.
|
||||||
|
* @param variableIndex Optional pre-computed VariableIndex for the factor graph, if not
|
||||||
|
* provided one will be computed. */
|
||||||
|
boost::shared_ptr<BayesTreeType> marginalMultifrontalBayesTree(
|
||||||
|
boost::variant<const Ordering&, const KeyVector&> variables,
|
||||||
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
||||||
OptionalVariableIndex variableIndex = boost::none) const;
|
OptionalVariableIndex variableIndex = boost::none) const;
|
||||||
|
|
||||||
|
@ -215,16 +263,15 @@ namespace gtsam {
|
||||||
* @param variables Determines the variables whose marginal to compute, if provided as an
|
* @param variables Determines the variables whose marginal to compute, if provided as an
|
||||||
* Ordering they will be ordered in the returned BayesNet as specified, and if provided
|
* Ordering they will be ordered in the returned BayesNet as specified, and if provided
|
||||||
* as a KeyVector they will be ordered using constrained COLAMD.
|
* as a KeyVector they will be ordered using constrained COLAMD.
|
||||||
* @param marginalizedVariableOrdering Optional ordering for the variables being marginalized
|
* @param marginalizedVariableOrdering Ordering for the variables being marginalized out,
|
||||||
* out, i.e. all variables not in \c variables. If this is boost::none, the ordering
|
* i.e. all variables not in \c variables.
|
||||||
* will be computed with COLAMD.
|
|
||||||
* @param function Optional dense elimination function, if not provided the default will be
|
* @param function Optional dense elimination function, if not provided the default will be
|
||||||
* used.
|
* used.
|
||||||
* @param variableIndex Optional pre-computed VariableIndex for the factor graph, if not
|
* @param variableIndex Optional pre-computed VariableIndex for the factor graph, if not
|
||||||
* provided one will be computed. */
|
* provided one will be computed. */
|
||||||
boost::shared_ptr<BayesTreeType> marginalMultifrontalBayesTree(
|
boost::shared_ptr<BayesTreeType> marginalMultifrontalBayesTree(
|
||||||
boost::variant<const Ordering&, const KeyVector&> variables,
|
boost::variant<const Ordering&, const KeyVector&> variables,
|
||||||
OptionalOrdering marginalizedVariableOrdering = boost::none,
|
const Ordering& marginalizedVariableOrdering, // this no longer takes boost::none - potentially code breaking
|
||||||
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
|
||||||
OptionalVariableIndex variableIndex = boost::none) const;
|
OptionalVariableIndex variableIndex = boost::none) const;
|
||||||
|
|
||||||
|
|
|
@ -282,8 +282,13 @@ namespace gtsam {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
VectorValues GaussianFactorGraph::optimize(OptionalOrdering ordering, const Eliminate& function) const
|
VectorValues GaussianFactorGraph::optimize(const Eliminate& function) const {
|
||||||
{
|
gttic(GaussianFactorGraph_optimize);
|
||||||
|
return BaseEliminateable::eliminateMultifrontal(function)->optimize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
VectorValues GaussianFactorGraph::optimize(const Ordering& ordering, const Eliminate& function) const {
|
||||||
gttic(GaussianFactorGraph_optimize);
|
gttic(GaussianFactorGraph_optimize);
|
||||||
return BaseEliminateable::eliminateMultifrontal(ordering, function)->optimize();
|
return BaseEliminateable::eliminateMultifrontal(ordering, function)->optimize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,7 +282,14 @@ namespace gtsam {
|
||||||
* the dense elimination function specified in \c function (default EliminatePreferCholesky),
|
* the dense elimination function specified in \c function (default EliminatePreferCholesky),
|
||||||
* followed by back-substitution in the Bayes tree resulting from elimination. Is equivalent
|
* followed by back-substitution in the Bayes tree resulting from elimination. Is equivalent
|
||||||
* to calling graph.eliminateMultifrontal()->optimize(). */
|
* to calling graph.eliminateMultifrontal()->optimize(). */
|
||||||
VectorValues optimize(OptionalOrdering ordering = boost::none,
|
VectorValues optimize(
|
||||||
|
const Eliminate& function = EliminationTraitsType::DefaultEliminate) const;
|
||||||
|
|
||||||
|
/** Solve the factor graph by performing multifrontal variable elimination in COLAMD order using
|
||||||
|
* the dense elimination function specified in \c function (default EliminatePreferCholesky),
|
||||||
|
* followed by back-substitution in the Bayes tree resulting from elimination. Is equivalent
|
||||||
|
* to calling graph.eliminateMultifrontal()->optimize(). */
|
||||||
|
VectorValues optimize(const Ordering&,
|
||||||
const Eliminate& function = EliminationTraitsType::DefaultEliminate) const;
|
const Eliminate& function = EliminationTraitsType::DefaultEliminate) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -82,29 +82,20 @@ string IterativeOptimizationParameters::verbosityTranslator(
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
VectorValues IterativeSolver::optimize(const GaussianFactorGraph &gfg,
|
||||||
|
boost::optional<const KeyInfo&> keyInfo,
|
||||||
|
boost::optional<const std::map<Key, Vector>&> lambda) {
|
||||||
|
return optimize(gfg, keyInfo ? *keyInfo : KeyInfo(gfg),
|
||||||
|
lambda ? *lambda : std::map<Key, Vector>());
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
VectorValues IterativeSolver::optimize(const GaussianFactorGraph &gfg,
|
VectorValues IterativeSolver::optimize(const GaussianFactorGraph &gfg,
|
||||||
const KeyInfo &keyInfo, const std::map<Key, Vector> &lambda) {
|
const KeyInfo &keyInfo, const std::map<Key, Vector> &lambda) {
|
||||||
return optimize(gfg, keyInfo, lambda, keyInfo.x0());
|
return optimize(gfg, keyInfo, lambda, keyInfo.x0());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
VectorValues IterativeSolver::optimize(const GaussianFactorGraph &gfg,
|
|
||||||
const KeyInfo& keyInfo) {
|
|
||||||
return optimize(gfg, keyInfo, std::map<Key, Vector>());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
VectorValues IterativeSolver::optimize(const GaussianFactorGraph &gfg,
|
|
||||||
const std::map<Key, Vector>& lambda) {
|
|
||||||
return optimize(gfg, KeyInfo(gfg), lambda);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
VectorValues IterativeSolver::optimize(const GaussianFactorGraph &gfg) {
|
|
||||||
return optimize(gfg, KeyInfo(gfg), std::map<Key, Vector>());
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
KeyInfo::KeyInfo(const GaussianFactorGraph &fg, const Ordering &ordering) :
|
KeyInfo::KeyInfo(const GaussianFactorGraph &fg, const Ordering &ordering) :
|
||||||
ordering_(ordering) {
|
ordering_(ordering) {
|
||||||
|
|
|
@ -91,21 +91,15 @@ public:
|
||||||
virtual ~IterativeSolver() {
|
virtual ~IterativeSolver() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* interface to the nonlinear optimizer, without metadata, damping and initial estimate */
|
||||||
|
GTSAM_EXPORT VectorValues optimize(const GaussianFactorGraph &gfg,
|
||||||
|
boost::optional<const KeyInfo&> = boost::none,
|
||||||
|
boost::optional<const std::map<Key, Vector>&> lambda = boost::none);
|
||||||
|
|
||||||
/* interface to the nonlinear optimizer, without initial estimate */
|
/* interface to the nonlinear optimizer, without initial estimate */
|
||||||
GTSAM_EXPORT VectorValues optimize(const GaussianFactorGraph &gfg, const KeyInfo &keyInfo,
|
GTSAM_EXPORT VectorValues optimize(const GaussianFactorGraph &gfg, const KeyInfo &keyInfo,
|
||||||
const std::map<Key, Vector> &lambda);
|
const std::map<Key, Vector> &lambda);
|
||||||
|
|
||||||
/* interface to the nonlinear optimizer, without damping and initial estimate */
|
|
||||||
GTSAM_EXPORT VectorValues optimize(const GaussianFactorGraph &gfg,
|
|
||||||
const KeyInfo& keyInfo);
|
|
||||||
|
|
||||||
/* interface to the nonlinear optimizer, without metadata and initial estimate */
|
|
||||||
GTSAM_EXPORT VectorValues optimize(const GaussianFactorGraph &gfg,
|
|
||||||
const std::map<Key, Vector>& lambda);
|
|
||||||
|
|
||||||
/* interface to the nonlinear optimizer, without metadata, damping and initial estimate */
|
|
||||||
GTSAM_EXPORT VectorValues optimize(const GaussianFactorGraph &gfg);
|
|
||||||
|
|
||||||
/* interface to the nonlinear optimizer that the subclasses have to implement */
|
/* interface to the nonlinear optimizer that the subclasses have to implement */
|
||||||
virtual VectorValues optimize(const GaussianFactorGraph &gfg,
|
virtual VectorValues optimize(const GaussianFactorGraph &gfg,
|
||||||
const KeyInfo &keyInfo, const std::map<Key, Vector> &lambda,
|
const KeyInfo &keyInfo, const std::map<Key, Vector> &lambda,
|
||||||
|
|
|
@ -34,17 +34,7 @@ string SlotEntry::toString() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Scatter::Scatter(const GaussianFactorGraph& gfg,
|
void Scatter::ScatterHelper(const GaussianFactorGraph& gfg, size_t sortStart) {
|
||||||
boost::optional<const Ordering&> ordering) {
|
|
||||||
gttic(Scatter_Constructor);
|
|
||||||
|
|
||||||
// If we have an ordering, pre-fill the ordered variables first
|
|
||||||
if (ordering) {
|
|
||||||
for (Key key : *ordering) {
|
|
||||||
add(key, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now, find dimensions of variables and/or extend
|
// Now, find dimensions of variables and/or extend
|
||||||
for (const auto& factor : gfg) {
|
for (const auto& factor : gfg) {
|
||||||
if (!factor)
|
if (!factor)
|
||||||
|
@ -68,10 +58,30 @@ Scatter::Scatter(const GaussianFactorGraph& gfg,
|
||||||
|
|
||||||
// To keep the same behavior as before, sort the keys after the ordering
|
// To keep the same behavior as before, sort the keys after the ordering
|
||||||
iterator first = begin();
|
iterator first = begin();
|
||||||
if (ordering) first += ordering->size();
|
first += sortStart;
|
||||||
if (first != end()) std::sort(first, end());
|
if (first != end()) std::sort(first, end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Scatter::Scatter(const GaussianFactorGraph& gfg) {
|
||||||
|
gttic(Scatter_Constructor);
|
||||||
|
|
||||||
|
ScatterHelper(gfg, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Scatter::Scatter(const GaussianFactorGraph& gfg,
|
||||||
|
const Ordering& ordering) {
|
||||||
|
gttic(Scatter_Constructor);
|
||||||
|
|
||||||
|
// pre-fill the ordered variables first
|
||||||
|
for (Key key : ordering) {
|
||||||
|
add(key, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScatterHelper(gfg, ordering.size());
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
void Scatter::add(Key key, size_t dim) {
|
void Scatter::add(Key key, size_t dim) {
|
||||||
emplace_back(SlotEntry(key, dim));
|
emplace_back(SlotEntry(key, dim));
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
#include <gtsam/base/FastMap.h>
|
#include <gtsam/base/FastMap.h>
|
||||||
#include <gtsam/dllexport.h>
|
#include <gtsam/dllexport.h>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
class GaussianFactorGraph;
|
class GaussianFactorGraph;
|
||||||
|
@ -53,15 +51,21 @@ class Scatter : public FastVector<SlotEntry> {
|
||||||
/// Default Constructor
|
/// Default Constructor
|
||||||
Scatter() {}
|
Scatter() {}
|
||||||
|
|
||||||
/// Construct from gaussian factor graph, with optional (partial or complete) ordering
|
/// Construct from gaussian factor graph, without ordering
|
||||||
Scatter(const GaussianFactorGraph& gfg,
|
explicit Scatter(const GaussianFactorGraph& gfg);
|
||||||
boost::optional<const Ordering&> ordering = boost::none);
|
|
||||||
|
/// Construct from gaussian factor graph, with (partial or complete) ordering
|
||||||
|
explicit Scatter(const GaussianFactorGraph& gfg, const Ordering& ordering);
|
||||||
|
|
||||||
/// Add a key/dim pair
|
/// Add a key/dim pair
|
||||||
void add(Key key, size_t dim);
|
void add(Key key, size_t dim);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/// Helper function for constructors, adds/finds dimensions of variables and
|
||||||
|
// sorts starting from sortStart
|
||||||
|
void ScatterHelper(const GaussianFactorGraph& gfg, size_t sortStart);
|
||||||
|
|
||||||
/// Find the SlotEntry with the right key (linear time worst case)
|
/// Find the SlotEntry with the right key (linear time worst case)
|
||||||
iterator find(Key key);
|
iterator find(Key key);
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,8 +26,16 @@ using namespace std;
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Marginals::Marginals(const NonlinearFactorGraph& graph, const Values& solution, Factorization factorization,
|
Marginals::Marginals(const NonlinearFactorGraph& graph, const Values& solution, Factorization factorization)
|
||||||
EliminateableFactorGraph<GaussianFactorGraph>::OptionalOrdering ordering)
|
: values_(solution), factorization_(factorization) {
|
||||||
|
gttic(MarginalsConstructor);
|
||||||
|
graph_ = *graph.linearize(solution);
|
||||||
|
computeBayesTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Marginals::Marginals(const NonlinearFactorGraph& graph, const Values& solution, const Ordering& ordering,
|
||||||
|
Factorization factorization)
|
||||||
: values_(solution), factorization_(factorization) {
|
: values_(solution), factorization_(factorization) {
|
||||||
gttic(MarginalsConstructor);
|
gttic(MarginalsConstructor);
|
||||||
graph_ = *graph.linearize(solution);
|
graph_ = *graph.linearize(solution);
|
||||||
|
@ -35,28 +43,52 @@ Marginals::Marginals(const NonlinearFactorGraph& graph, const Values& solution,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Marginals::Marginals(const GaussianFactorGraph& graph, const VectorValues& solution, Factorization factorization,
|
Marginals::Marginals(const GaussianFactorGraph& graph, const Values& solution, Factorization factorization)
|
||||||
EliminateableFactorGraph<GaussianFactorGraph>::OptionalOrdering ordering)
|
: graph_(graph), values_(solution), factorization_(factorization) {
|
||||||
: graph_(graph), factorization_(factorization) {
|
|
||||||
gttic(MarginalsConstructor);
|
gttic(MarginalsConstructor);
|
||||||
Values vals;
|
computeBayesTree();
|
||||||
for (const auto& keyValue: solution) {
|
|
||||||
vals.insert(keyValue.first, keyValue.second);
|
|
||||||
}
|
|
||||||
values_ = vals;
|
|
||||||
computeBayesTree(ordering);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Marginals::Marginals(const GaussianFactorGraph& graph, const Values& solution, Factorization factorization,
|
Marginals::Marginals(const GaussianFactorGraph& graph, const Values& solution, const Ordering& ordering,
|
||||||
EliminateableFactorGraph<GaussianFactorGraph>::OptionalOrdering ordering)
|
Factorization factorization)
|
||||||
: graph_(graph), values_(solution), factorization_(factorization) {
|
: graph_(graph), values_(solution), factorization_(factorization) {
|
||||||
gttic(MarginalsConstructor);
|
gttic(MarginalsConstructor);
|
||||||
computeBayesTree(ordering);
|
computeBayesTree(ordering);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
void Marginals::computeBayesTree(EliminateableFactorGraph<GaussianFactorGraph>::OptionalOrdering ordering) {
|
Marginals::Marginals(const GaussianFactorGraph& graph, const VectorValues& solution, Factorization factorization)
|
||||||
|
: graph_(graph), factorization_(factorization) {
|
||||||
|
gttic(MarginalsConstructor);
|
||||||
|
for (const auto& keyValue: solution) {
|
||||||
|
values_.insert(keyValue.first, keyValue.second);
|
||||||
|
}
|
||||||
|
computeBayesTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
Marginals::Marginals(const GaussianFactorGraph& graph, const VectorValues& solution, const Ordering& ordering,
|
||||||
|
Factorization factorization)
|
||||||
|
: graph_(graph), factorization_(factorization) {
|
||||||
|
gttic(MarginalsConstructor);
|
||||||
|
for (const auto& keyValue: solution) {
|
||||||
|
values_.insert(keyValue.first, keyValue.second);
|
||||||
|
}
|
||||||
|
computeBayesTree(ordering);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
void Marginals::computeBayesTree() {
|
||||||
|
// Compute BayesTree
|
||||||
|
if(factorization_ == CHOLESKY)
|
||||||
|
bayesTree_ = *graph_.eliminateMultifrontal(EliminatePreferCholesky);
|
||||||
|
else if(factorization_ == QR)
|
||||||
|
bayesTree_ = *graph_.eliminateMultifrontal(EliminateQR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
void Marginals::computeBayesTree(const Ordering& ordering) {
|
||||||
// Compute BayesTree
|
// Compute BayesTree
|
||||||
if(factorization_ == CHOLESKY)
|
if(factorization_ == CHOLESKY)
|
||||||
bayesTree_ = *graph_.eliminateMultifrontal(ordering, EliminatePreferCholesky);
|
bayesTree_ = *graph_.eliminateMultifrontal(ordering, EliminatePreferCholesky);
|
||||||
|
@ -128,9 +160,9 @@ JointMarginal Marginals::jointMarginalInformation(const KeyVector& variables) co
|
||||||
jointFG = *bayesTree_.joint(variables[0], variables[1], EliminateQR);
|
jointFG = *bayesTree_.joint(variables[0], variables[1], EliminateQR);
|
||||||
} else {
|
} else {
|
||||||
if(factorization_ == CHOLESKY)
|
if(factorization_ == CHOLESKY)
|
||||||
jointFG = GaussianFactorGraph(*graph_.marginalMultifrontalBayesTree(variables, boost::none, EliminatePreferCholesky));
|
jointFG = GaussianFactorGraph(*graph_.marginalMultifrontalBayesTree(variables, EliminatePreferCholesky));
|
||||||
else if(factorization_ == QR)
|
else if(factorization_ == QR)
|
||||||
jointFG = GaussianFactorGraph(*graph_.marginalMultifrontalBayesTree(variables, boost::none, EliminateQR));
|
jointFG = GaussianFactorGraph(*graph_.marginalMultifrontalBayesTree(variables, EliminateQR));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get information matrix
|
// Get information matrix
|
||||||
|
|
|
@ -55,10 +55,33 @@ public:
|
||||||
* @param graph The factor graph defining the full joint density on all variables.
|
* @param graph The factor graph defining the full joint density on all variables.
|
||||||
* @param solution The linearization point about which to compute Gaussian marginals (usually the MLE as obtained from a NonlinearOptimizer).
|
* @param solution The linearization point about which to compute Gaussian marginals (usually the MLE as obtained from a NonlinearOptimizer).
|
||||||
* @param factorization The linear decomposition mode - either Marginals::CHOLESKY (faster and suitable for most problems) or Marginals::QR (slower but more numerically stable for poorly-conditioned problems).
|
* @param factorization The linear decomposition mode - either Marginals::CHOLESKY (faster and suitable for most problems) or Marginals::QR (slower but more numerically stable for poorly-conditioned problems).
|
||||||
* @param ordering An optional variable ordering for elimination.
|
|
||||||
*/
|
*/
|
||||||
Marginals(const NonlinearFactorGraph& graph, const Values& solution, Factorization factorization = CHOLESKY,
|
Marginals(const NonlinearFactorGraph& graph, const Values& solution, Factorization factorization = CHOLESKY);
|
||||||
EliminateableFactorGraph<GaussianFactorGraph>::OptionalOrdering ordering = boost::none);
|
|
||||||
|
/** Construct a marginals class from a nonlinear factor graph.
|
||||||
|
* @param graph The factor graph defining the full joint density on all variables.
|
||||||
|
* @param solution The linearization point about which to compute Gaussian marginals (usually the MLE as obtained from a NonlinearOptimizer).
|
||||||
|
* @param factorization The linear decomposition mode - either Marginals::CHOLESKY (faster and suitable for most problems) or Marginals::QR (slower but more numerically stable for poorly-conditioned problems).
|
||||||
|
* @param ordering The ordering for elimination.
|
||||||
|
*/
|
||||||
|
Marginals(const NonlinearFactorGraph& graph, const Values& solution, const Ordering& ordering, // argument order switch due to default value of factorization, potentially code breaking
|
||||||
|
Factorization factorization = CHOLESKY);
|
||||||
|
|
||||||
|
/** Construct a marginals class from a linear factor graph.
|
||||||
|
* @param graph The factor graph defining the full joint density on all variables.
|
||||||
|
* @param solution The solution point to compute Gaussian marginals.
|
||||||
|
* @param factorization The linear decomposition mode - either Marginals::CHOLESKY (faster and suitable for most problems) or Marginals::QR (slower but more numerically stable for poorly-conditioned problems).
|
||||||
|
*/
|
||||||
|
Marginals(const GaussianFactorGraph& graph, const Values& solution, Factorization factorization = CHOLESKY);
|
||||||
|
|
||||||
|
/** Construct a marginals class from a linear factor graph.
|
||||||
|
* @param graph The factor graph defining the full joint density on all variables.
|
||||||
|
* @param solution The solution point to compute Gaussian marginals.
|
||||||
|
* @param factorization The linear decomposition mode - either Marginals::CHOLESKY (faster and suitable for most problems) or Marginals::QR (slower but more numerically stable for poorly-conditioned problems).
|
||||||
|
* @param ordering The ordering for elimination.
|
||||||
|
*/
|
||||||
|
Marginals(const GaussianFactorGraph& graph, const Values& solution, const Ordering& ordering, // argument order switch due to default value of factorization, potentially code breaking
|
||||||
|
Factorization factorization = CHOLESKY);
|
||||||
|
|
||||||
/** Construct a marginals class from a linear factor graph.
|
/** Construct a marginals class from a linear factor graph.
|
||||||
* @param graph The factor graph defining the full joint density on all variables.
|
* @param graph The factor graph defining the full joint density on all variables.
|
||||||
|
@ -66,8 +89,7 @@ public:
|
||||||
* @param factorization The linear decomposition mode - either Marginals::CHOLESKY (faster and suitable for most problems) or Marginals::QR (slower but more numerically stable for poorly-conditioned problems).
|
* @param factorization The linear decomposition mode - either Marginals::CHOLESKY (faster and suitable for most problems) or Marginals::QR (slower but more numerically stable for poorly-conditioned problems).
|
||||||
* @param ordering An optional variable ordering for elimination.
|
* @param ordering An optional variable ordering for elimination.
|
||||||
*/
|
*/
|
||||||
Marginals(const GaussianFactorGraph& graph, const Values& solution, Factorization factorization = CHOLESKY,
|
Marginals(const GaussianFactorGraph& graph, const VectorValues& solution, Factorization factorization = CHOLESKY);
|
||||||
EliminateableFactorGraph<GaussianFactorGraph>::OptionalOrdering ordering = boost::none);
|
|
||||||
|
|
||||||
/** Construct a marginals class from a linear factor graph.
|
/** Construct a marginals class from a linear factor graph.
|
||||||
* @param graph The factor graph defining the full joint density on all variables.
|
* @param graph The factor graph defining the full joint density on all variables.
|
||||||
|
@ -75,8 +97,8 @@ public:
|
||||||
* @param factorization The linear decomposition mode - either Marginals::CHOLESKY (faster and suitable for most problems) or Marginals::QR (slower but more numerically stable for poorly-conditioned problems).
|
* @param factorization The linear decomposition mode - either Marginals::CHOLESKY (faster and suitable for most problems) or Marginals::QR (slower but more numerically stable for poorly-conditioned problems).
|
||||||
* @param ordering An optional variable ordering for elimination.
|
* @param ordering An optional variable ordering for elimination.
|
||||||
*/
|
*/
|
||||||
Marginals(const GaussianFactorGraph& graph, const VectorValues& solution, Factorization factorization = CHOLESKY,
|
Marginals(const GaussianFactorGraph& graph, const VectorValues& solution, const Ordering& ordering, // argument order switch due to default value of factorization, potentially code breaking
|
||||||
EliminateableFactorGraph<GaussianFactorGraph>::OptionalOrdering ordering = boost::none);
|
Factorization factorization = CHOLESKY);
|
||||||
|
|
||||||
/** print */
|
/** print */
|
||||||
void print(const std::string& str = "Marginals: ", const KeyFormatter& keyFormatter = DefaultKeyFormatter) const;
|
void print(const std::string& str = "Marginals: ", const KeyFormatter& keyFormatter = DefaultKeyFormatter) const;
|
||||||
|
@ -103,7 +125,10 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** Compute the Bayes Tree as a helper function to the constructor */
|
/** Compute the Bayes Tree as a helper function to the constructor */
|
||||||
void computeBayesTree(EliminateableFactorGraph<GaussianFactorGraph>::OptionalOrdering ordering);
|
void computeBayesTree();
|
||||||
|
|
||||||
|
/** Compute the Bayes Tree as a helper function to the constructor */
|
||||||
|
void computeBayesTree(const Ordering& ordering);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,14 @@ using namespace std;
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
/// Find the best total assignment - can be expensive
|
/// Find the best total assignment - can be expensive
|
||||||
CSP::sharedValues CSP::optimalAssignment(OptionalOrdering ordering) const {
|
CSP::sharedValues CSP::optimalAssignment() const {
|
||||||
|
DiscreteBayesNet::shared_ptr chordal = this->eliminateSequential();
|
||||||
|
sharedValues mpe = chordal->optimize();
|
||||||
|
return mpe;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find the best total assignment - can be expensive
|
||||||
|
CSP::sharedValues CSP::optimalAssignment(const Ordering& ordering) const {
|
||||||
DiscreteBayesNet::shared_ptr chordal = this->eliminateSequential(ordering);
|
DiscreteBayesNet::shared_ptr chordal = this->eliminateSequential(ordering);
|
||||||
sharedValues mpe = chordal->optimize();
|
sharedValues mpe = chordal->optimize();
|
||||||
return mpe;
|
return mpe;
|
||||||
|
|
|
@ -60,7 +60,10 @@ namespace gtsam {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/// Find the best total assignment - can be expensive
|
/// Find the best total assignment - can be expensive
|
||||||
sharedValues optimalAssignment(OptionalOrdering ordering = boost::none) const;
|
sharedValues optimalAssignment() const;
|
||||||
|
|
||||||
|
/// Find the best total assignment - can be expensive
|
||||||
|
sharedValues optimalAssignment(const Ordering& ordering) const;
|
||||||
|
|
||||||
// /*
|
// /*
|
||||||
// * Perform loopy belief propagation
|
// * Perform loopy belief propagation
|
||||||
|
|
|
@ -206,7 +206,7 @@ TEST(GaussianFactorGraph, optimize_Cholesky) {
|
||||||
GaussianFactorGraph fg = createGaussianFactorGraph();
|
GaussianFactorGraph fg = createGaussianFactorGraph();
|
||||||
|
|
||||||
// optimize the graph
|
// optimize the graph
|
||||||
VectorValues actual = fg.optimize(boost::none, EliminateCholesky);
|
VectorValues actual = fg.optimize(EliminateCholesky);
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
VectorValues expected = createCorrectDelta();
|
VectorValues expected = createCorrectDelta();
|
||||||
|
@ -220,7 +220,7 @@ TEST( GaussianFactorGraph, optimize_QR )
|
||||||
GaussianFactorGraph fg = createGaussianFactorGraph();
|
GaussianFactorGraph fg = createGaussianFactorGraph();
|
||||||
|
|
||||||
// optimize the graph
|
// optimize the graph
|
||||||
VectorValues actual = fg.optimize(boost::none, EliminateQR);
|
VectorValues actual = fg.optimize(EliminateQR);
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
VectorValues expected = createCorrectDelta();
|
VectorValues expected = createCorrectDelta();
|
||||||
|
|
Loading…
Reference in New Issue