attempt to fix elimination
parent
3d821ec22b
commit
0095f73130
|
|
@ -62,6 +62,7 @@ class GTSAM_EXPORT GaussianMixtureFactor : public HybridFactor {
|
|||
// Note: constant is log of normalization constant for probabilities.
|
||||
// Errors is the negative log-likelihood,
|
||||
// hence we subtract the constant here.
|
||||
if (!factor) return 0.0; // If nullptr, return 0.0 error
|
||||
return factor->error(values) - constant;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -199,14 +199,14 @@ hybridElimination(const HybridGaussianFactorGraph &factors,
|
|||
DiscreteKeys discreteSeparator(discreteSeparatorSet.begin(),
|
||||
discreteSeparatorSet.end());
|
||||
|
||||
// Collect all the frontal factors to create Gaussian factor graphs
|
||||
// indexed on the discrete keys.
|
||||
// Collect all the factors to create a set of Gaussian factor graphs in a
|
||||
// decision tree indexed by all discrete keys involved.
|
||||
GaussianMixtureFactor::Sum sum = factors.SumFrontals();
|
||||
|
||||
// If a tree leaf contains nullptr,
|
||||
// convert that leaf to an empty GaussianFactorGraph.
|
||||
// Needed since the DecisionTree will otherwise create
|
||||
// a GFG with a single (null) factor.
|
||||
// If a tree leaf contains nullptr, convert that leaf to an empty
|
||||
// GaussianFactorGraph. Needed since the DecisionTree will otherwise create a
|
||||
// GFG with a single (null) factor.
|
||||
// TODO(dellaert): can SumFrontals not guarantee this?
|
||||
auto emptyGaussian =
|
||||
[](const GaussianMixtureFactor::GraphAndConstant &graph_z) {
|
||||
bool hasNull = std::any_of(
|
||||
|
|
@ -222,7 +222,6 @@ hybridElimination(const HybridGaussianFactorGraph &factors,
|
|||
using EliminationPair = std::pair<boost::shared_ptr<GaussianConditional>,
|
||||
GaussianMixtureFactor::FactorAndConstant>;
|
||||
|
||||
KeyVector keysOfEliminated; // Not the ordering
|
||||
KeyVector keysOfSeparator;
|
||||
|
||||
// This is the elimination method on the leaf nodes
|
||||
|
|
@ -236,24 +235,21 @@ hybridElimination(const HybridGaussianFactorGraph &factors,
|
|||
gttic_(hybrid_eliminate);
|
||||
#endif
|
||||
|
||||
std::pair<boost::shared_ptr<GaussianConditional>,
|
||||
boost::shared_ptr<GaussianFactor>>
|
||||
conditional_factor =
|
||||
EliminatePreferCholesky(graph_z.graph, frontalKeys);
|
||||
boost::shared_ptr<GaussianConditional> conditional;
|
||||
boost::shared_ptr<GaussianFactor> newFactor;
|
||||
boost::tie(conditional, newFactor) =
|
||||
EliminatePreferCholesky(graph_z.graph, frontalKeys);
|
||||
|
||||
// Initialize the keysOfEliminated to be the keys of the
|
||||
// eliminated GaussianConditional
|
||||
keysOfEliminated = conditional_factor.first->keys();
|
||||
keysOfSeparator = conditional_factor.second->keys();
|
||||
// TODO(dellaert): always the same, and we already computed this in caller?
|
||||
keysOfSeparator = newFactor->keys();
|
||||
|
||||
#ifdef HYBRID_TIMING
|
||||
gttoc_(hybrid_eliminate);
|
||||
#endif
|
||||
|
||||
GaussianConditional::shared_ptr conditional = conditional_factor.first;
|
||||
// Get the log of the log normalization constant inverse.
|
||||
double logZ = -conditional->logNormalizationConstant() + graph_z.constant;
|
||||
return {conditional, {conditional_factor.second, logZ}};
|
||||
return {conditional, {newFactor, logZ}};
|
||||
};
|
||||
|
||||
// Perform elimination!
|
||||
|
|
@ -266,44 +262,31 @@ hybridElimination(const HybridGaussianFactorGraph &factors,
|
|||
|
||||
// Separate out decision tree into conditionals and remaining factors.
|
||||
auto pair = unzip(eliminationResults);
|
||||
const auto &separatorFactors = pair.second;
|
||||
|
||||
// Create the GaussianMixture from the conditionals
|
||||
auto conditional = boost::make_shared<GaussianMixture>(
|
||||
frontalKeys, keysOfSeparator, discreteSeparator, pair.first);
|
||||
|
||||
// If there are no more continuous parents, then we should create here a
|
||||
// DiscreteFactor, with the error for each discrete choice.
|
||||
// If there are no more continuous parents, then we should create a
|
||||
// DiscreteFactor here, with the error for each discrete choice.
|
||||
const auto &separatorFactors = pair.second;
|
||||
if (keysOfSeparator.empty()) {
|
||||
auto factorProb =
|
||||
[&](const GaussianMixtureFactor::FactorAndConstant &factor_z) {
|
||||
GaussianFactor::shared_ptr factor = factor_z.factor;
|
||||
if (!factor) {
|
||||
return 0.0; // If nullptr, return 0.0 probability
|
||||
} else {
|
||||
// This is the probability q(μ) at the MLE point.
|
||||
double error = factor_z.error(VectorValues());
|
||||
return std::exp(-error);
|
||||
}
|
||||
// This is the probability q(μ) at the MLE point.
|
||||
return factor_z.error(VectorValues());
|
||||
};
|
||||
DecisionTree<Key, double> fdt(separatorFactors, factorProb);
|
||||
// Normalize the values of decision tree to be valid probabilities
|
||||
double sum = 0.0;
|
||||
auto visitor = [&](double y) { sum += y; };
|
||||
fdt.visit(visitor);
|
||||
// fdt = DecisionTree<Key, double>(fdt,
|
||||
// [sum](const double &x) { return x / sum;
|
||||
// });
|
||||
|
||||
auto discreteFactor =
|
||||
const DecisionTree<Key, double> fdt(separatorFactors, factorProb);
|
||||
const auto discreteFactor =
|
||||
boost::make_shared<DecisionTreeFactor>(discreteSeparator, fdt);
|
||||
|
||||
return {boost::make_shared<HybridConditional>(conditional),
|
||||
boost::make_shared<HybridDiscreteFactor>(discreteFactor)};
|
||||
|
||||
} else {
|
||||
// Create a resulting GaussianMixtureFactor on the separator.
|
||||
auto factor = boost::make_shared<GaussianMixtureFactor>(
|
||||
// Keys can be computed from the factors, so we should not need to pass them
|
||||
// in.
|
||||
const auto factor = boost::make_shared<GaussianMixtureFactor>(
|
||||
KeyVector(continuousSeparator.begin(), continuousSeparator.end()),
|
||||
discreteSeparator, separatorFactors);
|
||||
return {boost::make_shared<HybridConditional>(conditional), factor};
|
||||
|
|
|
|||
Loading…
Reference in New Issue