Minor change to shortcut

release/4.3a0
Abhijit Kundu 2012-06-24 04:13:49 +00:00
parent 2d0ce1c3ca
commit bfc033d3f7
1 changed files with 88 additions and 90 deletions

View File

@ -102,114 +102,112 @@ namespace gtsam {
return changed; return changed;
} }
/* ************************************************************************* */ /* ************************************************************************* */
// The shortcut density is a conditional P(S|R) of the separator of this // The shortcut density is a conditional P(S|R) of the separator of this
// clique on the root. We can compute it recursively from the parent shortcut // clique on the root. We can compute it recursively from the parent shortcut
// P(Sp|R) as \int P(Fp|Sp) P(Sp|R), where Fp are the frontal nodes in p // P(Sp|R) as \int P(Fp|Sp) P(Sp|R), where Fp are the frontal nodes in p
/* ************************************************************************* */ /* ************************************************************************* */
template<class DERIVED, class CONDITIONAL> template<class DERIVED, class CONDITIONAL>
BayesNet<CONDITIONAL> BayesTreeCliqueBase<DERIVED, CONDITIONAL>::shortcut( BayesNet<CONDITIONAL> BayesTreeCliqueBase<DERIVED, CONDITIONAL>::shortcut(
derived_ptr R, Eliminate function) const{ derived_ptr R, Eliminate function) const{
static const bool debug = false; static const bool debug = false;
BayesNet<ConditionalType> p_S_R; //shortcut P(S|R) BayesNet<ConditionalType> p_S_R; //shortcut P(S|R) This is empty now
//Check if the ShortCut already exists //Check if the ShortCut already exists
if(!cachedShortcut_){ if(!cachedShortcut_){
// A first base case is when this clique or its parent is the root, // A first base case is when this clique or its parent is the root,
// in which case we return an empty Bayes net. // in which case we return an empty Bayes net.
derived_ptr parent(parent_.lock()); derived_ptr parent(parent_.lock());
if (R.get() != this && parent != R) {
if (R.get() == this || parent == R) { // The root conditional
BayesNet<ConditionalType> empty; FactorGraph<FactorType> p_R(BayesNet<ConditionalType>(R->conditional()));
return empty;
}
// The root conditional // The parent clique has a ConditionalType for each frontal node in Fp
FactorGraph<FactorType> p_R(BayesNet<ConditionalType>(R->conditional())); // so we can obtain P(Fp|Sp) in factor graph form
FactorGraph<FactorType> p_Fp_Sp(BayesNet<ConditionalType>(parent->conditional()));
// The parent clique has a ConditionalType for each frontal node in Fp // If not the base case, obtain the parent shortcut P(Sp|R) as factors
// so we can obtain P(Fp|Sp) in factor graph form FactorGraph<FactorType> p_Sp_R(parent->shortcut(R, function));
FactorGraph<FactorType> p_Fp_Sp(BayesNet<ConditionalType>(parent->conditional()));
// If not the base case, obtain the parent shortcut P(Sp|R) as factors // now combine P(Cp|R) = P(Fp|Sp) * P(Sp|R)
FactorGraph<FactorType> p_Sp_R(parent->shortcut(R, function)); FactorGraph<FactorType> p_Cp_R;
p_Cp_R.push_back(p_R);
p_Cp_R.push_back(p_Fp_Sp);
p_Cp_R.push_back(p_Sp_R);
// now combine P(Cp|R) = P(Fp|Sp) * P(Sp|R) // Eliminate into a Bayes net with ordering designed to integrate out
FactorGraph<FactorType> p_Cp_R; // any variables not in *our* separator. Variables to integrate out must be
p_Cp_R.push_back(p_R); // eliminated first hence the desired ordering is [Cp\S S].
p_Cp_R.push_back(p_Fp_Sp); // However, an added wrinkle is that Cp might overlap with the root.
p_Cp_R.push_back(p_Sp_R); // Keys corresponding to the root should not be added to the ordering at all.
// Eliminate into a Bayes net with ordering designed to integrate out if(debug) {
// any variables not in *our* separator. Variables to integrate out must be p_R.print("p_R: ");
// eliminated first hence the desired ordering is [Cp\S S]. p_Fp_Sp.print("p_Fp_Sp: ");
// However, an added wrinkle is that Cp might overlap with the root. p_Sp_R.print("p_Sp_R: ");
// Keys corresponding to the root should not be added to the ordering at all. }
if(debug) { // We want to factor into a conditional of the clique variables given the
p_R.print("p_R: "); // root and the marginal on the root, integrating out all other variables.
p_Fp_Sp.print("p_Fp_Sp: "); // The integrands include any parents of this clique and the variables of
p_Sp_R.print("p_Sp_R: "); // the parent clique.
} FastSet<Index> variablesAtBack;
FastSet<Index> separator;
size_t uniqueRootVariables = 0;
BOOST_FOREACH(const Index separatorIndex, this->conditional()->parents()) {
variablesAtBack.insert(separatorIndex);
separator.insert(separatorIndex);
if(debug) std::cout << "At back (this): " << separatorIndex << std::endl;
}
BOOST_FOREACH(const Index key, R->conditional()->keys()) {
if(variablesAtBack.insert(key).second)
++ uniqueRootVariables;
if(debug) std::cout << "At back (root): " << key << std::endl;
}
// We want to factor into a conditional of the clique variables given the Permutation toBack = Permutation::PushToBack(
// root and the marginal on the root, integrating out all other variables. std::vector<Index>(variablesAtBack.begin(), variablesAtBack.end()),
// The integrands include any parents of this clique and the variables of R->conditional()->lastFrontalKey() + 1);
// the parent clique. Permutation::shared_ptr toBackInverse(toBack.inverse());
FastSet<Index> variablesAtBack; BOOST_FOREACH(const typename FactorType::shared_ptr& factor, p_Cp_R) {
FastSet<Index> separator; factor->permuteWithInverse(*toBackInverse); }
size_t uniqueRootVariables = 0; typename BayesNet<ConditionalType>::shared_ptr eliminated(EliminationTree<
BOOST_FOREACH(const Index separatorIndex, this->conditional()->parents()) { FactorType>::Create(p_Cp_R)->eliminate(function));
variablesAtBack.insert(separatorIndex);
separator.insert(separatorIndex);
if(debug) std::cout << "At back (this): " << separatorIndex << std::endl;
}
BOOST_FOREACH(const Index key, R->conditional()->keys()) {
if(variablesAtBack.insert(key).second)
++ uniqueRootVariables;
if(debug) std::cout << "At back (root): " << key << std::endl;
}
Permutation toBack = Permutation::PushToBack( // Take only the conditionals for p(S|R). We check for each variable being
std::vector<Index>(variablesAtBack.begin(), variablesAtBack.end()), // in the separator set because if some separator variables overlap with
R->conditional()->lastFrontalKey() + 1); // root variables, we cannot rely on the number of root variables, and also
Permutation::shared_ptr toBackInverse(toBack.inverse()); // want to include those variables in the conditional.
BOOST_FOREACH(const typename FactorType::shared_ptr& factor, p_Cp_R) { BOOST_REVERSE_FOREACH(typename ConditionalType::shared_ptr conditional, *eliminated) {
factor->permuteWithInverse(*toBackInverse); } assert(conditional->nrFrontals() == 1);
typename BayesNet<ConditionalType>::shared_ptr eliminated(EliminationTree< if(separator.find(toBack[conditional->firstFrontalKey()]) != separator.end()) {
FactorType>::Create(p_Cp_R)->eliminate(function)); if(debug)
conditional->print("Taking C|R conditional: ");
p_S_R.push_front(conditional);
}
if(p_S_R.size() == separator.size())
break;
}
// Take only the conditionals for p(S|R). We check for each variable being // Undo the permutation
// in the separator set because if some separator variables overlap with if(debug) toBack.print("toBack: ");
// root variables, we cannot rely on the number of root variables, and also p_S_R.permuteWithInverse(toBack);
// want to include those variables in the conditional. }
BOOST_REVERSE_FOREACH(typename ConditionalType::shared_ptr conditional, *eliminated) {
assert(conditional->nrFrontals() == 1);
if(separator.find(toBack[conditional->firstFrontalKey()]) != separator.end()) {
if(debug)
conditional->print("Taking C|R conditional: ");
p_S_R.push_front(conditional);
}
if(p_S_R.size() == separator.size())
break;
}
// Undo the permutation cachedShortcut_ = p_S_R;
if(debug) toBack.print("toBack: "); }
p_S_R.permuteWithInverse(toBack); else
p_S_R = *cachedShortcut_; // return the cached version
assertInvariants(); assertInvariants();
cachedShortcut_ = p_S_R;
}
else
p_S_R = *cachedShortcut_;
// return the shortcut P(S|R) // return the shortcut P(S|R)
return p_S_R; return p_S_R;
} }
/* ************************************************************************* */ /* ************************************************************************* */