MixtureFactor.h
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2 
3  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4  * Atlanta, Georgia 30332-0415
5  * All Rights Reserved
6  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8  * See LICENSE for the license information
9 
10  * -------------------------------------------------------------------------- */
11 
20 #pragma once
21 
27 #include <gtsam/nonlinear/Symbol.h>
28 
29 #include <algorithm>
30 #include <cmath>
31 #include <limits>
32 #include <vector>
33 
34 namespace gtsam {
35 
47 class MixtureFactor : public HybridFactor {
48  public:
49  using Base = HybridFactor;
51  using shared_ptr = std::shared_ptr<MixtureFactor>;
52  using sharedFactor = std::shared_ptr<NonlinearFactor>;
53 
59 
60  private:
64 
65  public:
66  MixtureFactor() = default;
67 
78  const Factors& factors, bool normalized = false)
79  : Base(keys, discreteKeys), factors_(factors), normalized_(normalized) {}
80 
97  template <typename FACTOR>
99  const std::vector<std::shared_ptr<FACTOR>>& factors,
100  bool normalized = false)
101  : Base(keys, discreteKeys), normalized_(normalized) {
102  std::vector<NonlinearFactor::shared_ptr> nonlinear_factors;
103  KeySet continuous_keys_set(keys.begin(), keys.end());
104  KeySet factor_keys_set;
105  for (auto&& f : factors) {
106  // Insert all factor continuous keys in the continuous keys set.
107  std::copy(f->keys().begin(), f->keys().end(),
108  std::inserter(factor_keys_set, factor_keys_set.end()));
109 
110  if (auto nf = std::dynamic_pointer_cast<NonlinearFactor>(f)) {
111  nonlinear_factors.push_back(nf);
112  } else {
113  throw std::runtime_error(
114  "Factors passed into MixtureFactor need to be nonlinear!");
115  }
116  }
117  factors_ = Factors(discreteKeys, nonlinear_factors);
118 
119  if (continuous_keys_set != factor_keys_set) {
120  throw std::runtime_error(
121  "The specified continuous keys and the keys in the factors don't "
122  "match!");
123  }
124  }
125 
134  AlgebraicDecisionTree<Key> error(const Values& continuousValues) const {
135  // functor to convert from sharedFactor to double error value.
136  auto errorFunc = [continuousValues](const sharedFactor& factor) {
137  return factor->error(continuousValues);
138  };
139  DecisionTree<Key, double> errorTree(factors_, errorFunc);
140  return errorTree;
141  }
142 
150  double error(const Values& continuousValues,
151  const DiscreteValues& discreteValues) const {
152  // Retrieve the factor corresponding to the assignment in discreteValues.
153  auto factor = factors_(discreteValues);
154  // Compute the error for the selected factor
155  const double factorError = factor->error(continuousValues);
156  if (normalized_) return factorError;
157  return factorError + this->nonlinearFactorLogNormalizingConstant(
158  factor, continuousValues);
159  }
160 
167  double error(const HybridValues& values) const override {
168  return error(values.nonlinear(), values.discrete());
169  }
170 
176  size_t dim() const {
177  const auto assignments = DiscreteValues::CartesianProduct(discreteKeys_);
178  auto factor = factors_(assignments.at(0));
179  return factor->dim();
180  }
181 
184 
186  void print(
187  const std::string& s = "",
188  const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
189  std::cout << (s.empty() ? "" : s + " ");
190  Base::print("", keyFormatter);
191  std::cout << "\nMixtureFactor\n";
192  auto valueFormatter = [](const sharedFactor& v) {
193  if (v) {
194  return "Nonlinear factor on " + std::to_string(v->size()) + " keys";
195  } else {
196  return std::string("nullptr");
197  }
198  };
199  factors_.print("", keyFormatter, valueFormatter);
200  }
201 
203  bool equals(const HybridFactor& other, double tol = 1e-9) const override {
204  // We attempt a dynamic cast from HybridFactor to MixtureFactor. If it
205  // fails, return false.
206  if (!dynamic_cast<const MixtureFactor*>(&other)) return false;
207 
208  // If the cast is successful, we'll properly construct a MixtureFactor
209  // object from `other`
210  const MixtureFactor& f(static_cast<const MixtureFactor&>(other));
211 
212  // Ensure that this MixtureFactor and `f` have the same `factors_`.
213  auto compare = [tol](const sharedFactor& a, const sharedFactor& b) {
214  return traits<NonlinearFactor>::Equals(*a, *b, tol);
215  };
216  if (!factors_.equals(f.factors_, compare)) return false;
217 
218  // If everything above passes, and the keys_, discreteKeys_ and normalized_
219  // member variables are identical, return true.
220  return (std::equal(keys_.begin(), keys_.end(), f.keys().begin()) &&
221  (discreteKeys_ == f.discreteKeys_) &&
222  (normalized_ == f.normalized_));
223  }
224 
226 
230  const Values& continuousValues,
231  const DiscreteValues& discreteValues) const {
232  auto factor = factors_(discreteValues);
233  return factor->linearize(continuousValues);
234  }
235 
237  std::shared_ptr<GaussianMixtureFactor> linearize(
238  const Values& continuousValues) const {
239  // functional to linearize each factor in the decision tree
240  auto linearizeDT = [continuousValues](const sharedFactor& factor) {
241  return factor->linearize(continuousValues);
242  };
243 
245  factors_, linearizeDT);
246 
247  return std::make_shared<GaussianMixtureFactor>(
248  continuousKeys_, discreteKeys_, linearized_factors);
249  }
250 
259  const Values& values) const {
260  // Information matrix (inverse covariance matrix) for the factor.
261  Matrix infoMat;
262 
263  // If this is a NoiseModelFactor, we'll use its noiseModel to
264  // otherwise noiseModelFactor will be nullptr
265  if (auto noiseModelFactor =
266  std::dynamic_pointer_cast<NoiseModelFactor>(factor)) {
267  // If dynamic cast to NoiseModelFactor succeeded, see if the noise model
268  // is Gaussian
269  auto noiseModel = noiseModelFactor->noiseModel();
270 
271  auto gaussianNoiseModel =
272  std::dynamic_pointer_cast<noiseModel::Gaussian>(noiseModel);
273  if (gaussianNoiseModel) {
274  // If the noise model is Gaussian, retrieve the information matrix
275  infoMat = gaussianNoiseModel->information();
276  } else {
277  // If the factor is not a Gaussian factor, we'll linearize it to get
278  // something with a normalized noise model
279  // TODO(kevin): does this make sense to do? I think maybe not in
280  // general? Should we just yell at the user?
281  auto gaussianFactor = factor->linearize(values);
282  infoMat = gaussianFactor->information();
283  }
284  }
285 
286  // Compute the (negative) log of the normalizing constant
287  return -(factor->dim() * log(2.0 * M_PI) / 2.0) -
288  (log(infoMat.determinant()) / 2.0);
289  }
290 };
291 
292 } // namespace gtsam
Factors factors_
Decision tree of Gaussian factors indexed by discrete keys.
Definition: MixtureFactor.h:62
A set of GaussianFactors, indexed by a set of discrete keys.
bool compare
DecisionTree< Key, sharedFactor > Factors
typedef for DecisionTree which has Keys as node labels and NonlinearFactor as leaf nodes...
Definition: MixtureFactor.h:58
Factor Graph consisting of non-linear factors.
const DiscreteKeys & discreteKeys() const
Return the discrete keys for this factor.
Definition: HybridFactor.h:129
Eigen::MatrixXd Matrix
Definition: base/Matrix.h:39
#define M_PI
Definition: main.h:106
leaf::MyValues values
const GaussianFactorGraph factors
MixtureFactor(const KeyVector &keys, const DiscreteKeys &discreteKeys, const std::vector< std::shared_ptr< FACTOR >> &factors, bool normalized=false)
Convenience constructor that generates the underlying factor decision tree for us.
Definition: MixtureFactor.h:98
KeyVector keys_
The keys involved in this factor.
Definition: Factor.h:87
MixtureFactor(const KeyVector &keys, const DiscreteKeys &discreteKeys, const Factors &factors, bool normalized=false)
Construct from Decision tree.
Definition: MixtureFactor.h:77
std::shared_ptr< NonlinearFactor > sharedFactor
Definition: MixtureFactor.h:52
static std::string valueFormatter(const double &v)
EIGEN_DEVICE_FUNC const LogReturnType log() const
static const KeyFormatter DefaultKeyFormatter
Definition: Key.h:43
bool equals(const HybridFactor &other, double tol=1e-9) const override
Check equality.
static std::vector< DiscreteValues > CartesianProduct(const DiscreteKeys &keys)
Return a vector of DiscreteValues, one for each possible combination of values.
std::shared_ptr< HybridFactor > shared_ptr
shared_ptr to this class
Definition: HybridFactor.h:68
AlgebraicDecisionTree< Key > error(const Values &continuousValues) const
Compute error of the MixtureFactor as a tree.
void print(const std::string &s="HybridFactor\, const KeyFormatter &formatter=DefaultKeyFormatter) const override
print
GaussianFactor::shared_ptr linearize(const Values &continuousValues, const DiscreteValues &discreteValues) const
Array< int, Dynamic, 1 > v
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print to stdout
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
double nonlinearFactorLogNormalizingConstant(const sharedFactor &factor, const Values &values) const
Array< double, 1, 3 > e(1./3., 0.5, 2.)
RealScalar s
bool equals(const DecisionTree &other, const CompareFunc &compare=&DefaultCompare) const
HybridFactor()=default
std::function< std::string(Key)> KeyFormatter
Typedef for a function to format a key, i.e. to convert it to a string.
Definition: Key.h:35
KeyVector continuousKeys_
Record continuous keys for book-keeping.
Definition: HybridFactor.h:62
const G & b
Definition: Group.h:86
std::shared_ptr< This > shared_ptr
shared_ptr to this class
traits
Definition: chartTesting.h:28
void print(const std::string &s, const LabelFormatter &labelFormatter, const ValueFormatter &valueFormatter) const
GTSAM-style print.
double error(const Values &continuousValues, const DiscreteValues &discreteValues) const
Compute error of factor given both continuous and discrete values.
Non-linear factor base classes.
size_t dim() const
Get the dimension of the factor (number of rows on linearization). Returns the dimension of the first...
const DiscreteValues & discrete() const
Return the discrete values.
Definition: HybridValues.h:92
const KeyVector & keys() const
Access the factor&#39;s involved variable keys.
Definition: Factor.h:142
const G double tol
Definition: Group.h:86
double error(const HybridValues &values) const override
Compute error of factor given hybrid values.
Implementation of a discrete conditional mixture factor.
Definition: MixtureFactor.h:47
const Values & nonlinear() const
Return the nonlinear values.
Definition: HybridValues.h:95
virtual Matrix information() const
Compute information matrix.
Definition: NoiseModel.cpp:239
Vector factorError(const Point3 &T1, const Point3 &T2, const TranslationFactor &factor)
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:86
DiscreteKeys discreteKeys_
Definition: HybridFactor.h:60
bool equal(const T &obj1, const T &obj2, double tol)
Definition: Testable.h:85
std::shared_ptr< GaussianMixtureFactor > linearize(const Values &continuousValues) const
Linearize all the continuous factors to get a GaussianMixtureFactor.
DiscreteKeys is a set of keys that can be assembled using the & operator.
Definition: DiscreteKey.h:41


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:34:56