HybridNonlinearFactor.cpp
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 
23 
24 #include <memory>
25 
26 namespace gtsam {
27 
28 /* *******************************************************************************/
30  KeyVector continuousKeys; // Continuous keys extracted from factors
31  DiscreteKeys discreteKeys; // Discrete keys provided to the constructors
33 
35  if (!factor) return;
36  if (continuousKeys.empty()) {
37  continuousKeys = factor->keys();
38  } else if (factor->keys() != continuousKeys) {
39  throw std::runtime_error(
40  "HybridNonlinearFactor: all factors should have the same keys!");
41  }
42  }
43 
44  ConstructorHelper(const DiscreteKey& discreteKey,
45  const std::vector<NoiseModelFactor::shared_ptr>& factors)
46  : discreteKeys({discreteKey}) {
47  std::vector<NonlinearFactorValuePair> pairs;
48  // Extract continuous keys from the first non-null factor
49  for (const auto& factor : factors) {
50  pairs.emplace_back(factor, 0.0);
52  }
53  factorTree = FactorValuePairs({discreteKey}, pairs);
54  }
55 
56  ConstructorHelper(const DiscreteKey& discreteKey,
57  const std::vector<NonlinearFactorValuePair>& pairs)
58  : discreteKeys({discreteKey}) {
59  // Extract continuous keys from the first non-null factor
60  for (const auto& pair : pairs) {
61  copyOrCheckContinuousKeys(pair.first);
62  }
63  factorTree = FactorValuePairs({discreteKey}, pairs);
64  }
65 
67  const FactorValuePairs& factorPairs)
68  : discreteKeys(discreteKeys), factorTree(factorPairs) {
69  // Extract continuous keys from the first non-null factor
70  factorPairs.visit([&](const NonlinearFactorValuePair& pair) {
71  copyOrCheckContinuousKeys(pair.first);
72  });
73  }
74 };
75 
76 /* *******************************************************************************/
78  : Base(helper.continuousKeys, helper.discreteKeys),
79  factors_(helper.factorTree) {}
80 
82  const DiscreteKey& discreteKey,
83  const std::vector<NoiseModelFactor::shared_ptr>& factors)
85 
87  const DiscreteKey& discreteKey,
88  const std::vector<NonlinearFactorValuePair>& pairs)
89  : HybridNonlinearFactor(ConstructorHelper(discreteKey, pairs)) {}
90 
94 
95 /* *******************************************************************************/
97  const Values& continuousValues) const {
98  // functor to convert from sharedFactor to double error value.
99  auto errorFunc =
100  [continuousValues](const std::pair<sharedFactor, double>& f) {
101  auto [factor, val] = f;
102  return factor ? factor->error(continuousValues) + val
103  : std::numeric_limits<double>::infinity();
104  };
105  return {factors_, errorFunc};
106 }
107 
108 /* *******************************************************************************/
110  const Values& continuousValues,
111  const DiscreteValues& discreteValues) const {
112  // Retrieve the factor corresponding to the assignment in discreteValues.
113  auto [factor, val] = factors_(discreteValues);
114  // Compute the error for the selected factor
115  const double factorError = factor->error(continuousValues);
116  return factorError + val;
117 }
118 
119 /* *******************************************************************************/
121  return error(values.nonlinear(), values.discrete());
122 }
123 
124 /* *******************************************************************************/
126  const auto assignments = DiscreteValues::CartesianProduct(discreteKeys_);
127  auto [factor, val] = factors_(assignments.at(0));
128  return factor->dim();
129 }
130 
131 /* *******************************************************************************/
132 void HybridNonlinearFactor::print(const std::string& s,
133  const KeyFormatter& keyFormatter) const {
134  std::cout << (s.empty() ? "" : s + " ");
135  Base::print("", keyFormatter);
136  std::cout << "\nHybridNonlinearFactor\n";
137  auto valueFormatter = [&keyFormatter](const std::pair<sharedFactor, double>& v) {
138  auto [factor, val] = v;
139  if (factor) {
140  RedirectCout rd;
141  factor->print("", keyFormatter);
142  return rd.str();
143  } else {
144  return std::string("nullptr");
145  }
146  };
147  factors_.print("", keyFormatter, valueFormatter);
148 }
149 
150 /* *******************************************************************************/
152  double tol) const {
153  // We attempt a dynamic cast from HybridFactor to HybridNonlinearFactor. If
154  // it fails, return false.
155  if (!dynamic_cast<const HybridNonlinearFactor*>(&other)) return false;
156 
157  // If the cast is successful, we'll properly construct a
158  // HybridNonlinearFactor object from `other`
159  const HybridNonlinearFactor& f(
160  static_cast<const HybridNonlinearFactor&>(other));
161 
162  // Ensure that this HybridNonlinearFactor and `f` have the same `factors_`.
163  auto compare = [tol](const std::pair<sharedFactor, double>& a,
164  const std::pair<sharedFactor, double>& b) {
165  return a.first->equals(*b.first, tol) && (a.second == b.second);
166  };
167  if (!factors_.equals(f.factors_, compare)) return false;
168 
169  // If everything above passes, and the keys_ and discreteKeys_
170  // member variables are identical, return true.
171  return (std::equal(keys_.begin(), keys_.end(), f.keys().begin()) &&
172  (discreteKeys_ == f.discreteKeys_));
173 }
174 
175 /* *******************************************************************************/
177  const Values& continuousValues,
178  const DiscreteValues& discreteValues) const {
179  auto factor = factors_(discreteValues).first;
180  return factor->linearize(continuousValues);
181 }
182 
183 /* *******************************************************************************/
184 std::shared_ptr<HybridGaussianFactor> HybridNonlinearFactor::linearize(
185  const Values& continuousValues) const {
186  // functional to linearize each factor in the decision tree
187  auto linearizeDT =
188  [continuousValues](
189  const std::pair<sharedFactor, double>& f) -> GaussianFactorValuePair {
190  auto [factor, val] = f;
191  // Check if valid factor. If not, return null and infinite error.
192  if (!factor) {
193  return {nullptr, std::numeric_limits<double>::infinity()};
194  }
195 
196  if (auto gaussian = std::dynamic_pointer_cast<noiseModel::Gaussian>(
197  factor->noiseModel())) {
198  return {factor->linearize(continuousValues),
199  val + gaussian->negLogConstant()};
200  } else {
201  throw std::runtime_error(
202  "HybridNonlinearFactor: linearize() only supports NoiseModelFactors "
203  "with Gaussian (or derived) noise models.");
204  }
205  };
206 
208  linearized_factors(factors_, linearizeDT);
209 
210  return std::make_shared<HybridGaussianFactor>(discreteKeys_,
211  linearized_factors);
212 }
213 
214 /* *******************************************************************************/
216  const DecisionTreeFactor& discreteProbs) const {
217  // Find keys in discreteProbs.keys() but not in this->keys():
218  std::set<Key> mine(this->keys().begin(), this->keys().end());
219  std::set<Key> theirs(discreteProbs.keys().begin(),
220  discreteProbs.keys().end());
221  std::vector<Key> diff;
222  std::set_difference(theirs.begin(), theirs.end(), mine.begin(), mine.end(),
223  std::back_inserter(diff));
224 
225  // Find maximum probability value for every combination of our keys.
226  Ordering keys(diff);
227  auto max = discreteProbs.max(keys);
228 
229  // Check the max value for every combination of our keys.
230  // If the max value is 0.0, we can prune the corresponding conditional.
231  auto pruner =
232  [&](const Assignment<Key>& choices,
234  if (max->evaluate(choices) == 0.0)
235  return {nullptr, std::numeric_limits<double>::infinity()};
236  else
237  return pair;
238  };
239 
240  FactorValuePairs prunedFactors = factors().apply(pruner);
241  return std::make_shared<HybridNonlinearFactor>(discreteKeys(), prunedFactors);
242 }
243 
244 /* ************************************************************************ */
245 std::shared_ptr<Factor> HybridNonlinearFactor::restrict(
246  const DiscreteValues& assignment) const {
247  auto restrictedFactors = factors_.restrict(assignment);
248  auto filtered = assignment.filter(discreteKeys_);
249  if (filtered.size() == discreteKeys_.size()) {
250  auto [nonlinearFactor, val] = factors_(filtered);
251  return nonlinearFactor;
252  } else {
253  auto remainingKeys = assignment.missingKeys(discreteKeys());
254  return std::make_shared<HybridNonlinearFactor>(remainingKeys,
255  factors_.restrict(filtered));
256  }
257 }
258 
259 /* ************************************************************************ */
260 
261 } // namespace gtsam
gtsam::HybridNonlinearFactor::HybridNonlinearFactor
HybridNonlinearFactor()=default
Default constructor, mainly for serialization.
compare
bool compare
Definition: SolverComparer.cpp:98
gtsam::DecisionTreeFactor
Definition: DecisionTreeFactor.h:45
gtsam::HybridValues
Definition: HybridValues.h:37
gtsam::HybridNonlinearFactor::ConstructorHelper::continuousKeys
KeyVector continuousKeys
Definition: HybridNonlinearFactor.cpp:30
gtsam::HybridNonlinearFactor::print
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print to stdout
Definition: HybridNonlinearFactor.cpp:132
s
RealScalar s
Definition: level1_cplx_impl.h:126
gtsam::HybridNonlinearFactor::ConstructorHelper::ConstructorHelper
ConstructorHelper(const DiscreteKeys &discreteKeys, const FactorValuePairs &factorPairs)
Definition: HybridNonlinearFactor.cpp:66
gtsam::HybridNonlinearFactor::restrict
std::shared_ptr< Factor > restrict(const DiscreteValues &assignment) const override
Restrict the factor to the given discrete values.
Definition: HybridNonlinearFactor.cpp:245
gtsam::DecisionTree::equals
bool equals(const DecisionTree &other, const CompareFunc &compare=&DefaultCompare) const
Definition: DecisionTree-inl.h:975
simple_graph::factors
const GaussianFactorGraph factors
Definition: testJacobianFactor.cpp:213
gtsam::RedirectCout
Definition: base/utilities.h:16
gtsam::HybridNonlinearFactor::ConstructorHelper
Definition: HybridNonlinearFactor.cpp:29
gtsam::HybridFactor
Definition: HybridFactor.h:51
different_sigmas::values
HybridValues values
Definition: testHybridBayesNet.cpp:247
gtsam::Factor
Definition: Factor.h:70
gtsam::DiscreteKeys
DiscreteKeys is a set of keys that can be assembled using the & operator.
Definition: DiscreteKey.h:41
gtsam::DecisionTree::print
void print(const std::string &s, const LabelFormatter &labelFormatter, const ValueFormatter &valueFormatter) const
GTSAM-style print.
Definition: DecisionTree-inl.h:981
gtsam::NoiseModelFactor::shared_ptr
std::shared_ptr< This > shared_ptr
Definition: NonlinearFactor.h:210
gtsam::Factor::begin
const_iterator begin() const
Definition: Factor.h:146
gtsam::HybridNonlinearFactor::error
double error(const Values &continuousValues, const DiscreteValues &assignment) const
Compute error of factor given both continuous and discrete values.
Definition: HybridNonlinearFactor.cpp:109
gtsam::KeyVector
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:92
gtsam::AlgebraicDecisionTree< Key >
pruning_fixture::factor
DecisionTreeFactor factor(D &C &B &A, "0.0 0.0 0.0 0.60658897 0.61241912 0.61241969 0.61247685 0.61247742 0.0 " "0.0 0.0 0.99995287 1.0 1.0 1.0 1.0")
gtsam::HybridNonlinearFactor::ConstructorHelper::ConstructorHelper
ConstructorHelper(const DiscreteKey &discreteKey, const std::vector< NoiseModelFactor::shared_ptr > &factors)
Definition: HybridNonlinearFactor.cpp:44
gtsam::HybridNonlinearFactor::ConstructorHelper::discreteKeys
DiscreteKeys discreteKeys
Definition: HybridNonlinearFactor.cpp:31
gtsam::GaussianFactorValuePair
std::pair< GaussianFactor::shared_ptr, double > GaussianFactorValuePair
Alias for pair of GaussianFactor::shared_pointer and a double value.
Definition: HybridGaussianFactor.h:38
gtsam::DiscreteValues::CartesianProduct
static std::vector< DiscreteValues > CartesianProduct(const DiscreteKeys &keys)
Return a vector of DiscreteValues, one for each possible combination of values.
Definition: DiscreteValues.h:148
gtsam::HybridNonlinearFactor::equals
bool equals(const HybridFactor &other, double tol=1e-9) const override
Check equality.
Definition: HybridNonlinearFactor.cpp:151
gtsam::KeyFormatter
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
gtsam::DiscreteValues::filter
DiscreteValues filter(const DiscreteKeys &keys) const
Filter values by keys.
Definition: DiscreteValues.h:118
gtsam::GaussianFactor::shared_ptr
std::shared_ptr< This > shared_ptr
shared_ptr to this class
Definition: GaussianFactor.h:42
gtsam::DecisionTree::visit
void visit(Func f) const
Visit all leaves in depth-first fashion.
Definition: DecisionTree-inl.h:841
gtsam::HybridNonlinearFactor::shared_ptr
std::shared_ptr< HybridNonlinearFactor > shared_ptr
Definition: HybridNonlinearFactor.h:62
gtsam::Assignment< Key >
gtsam::HybridFactor::discreteKeys_
DiscreteKeys discreteKeys_
Definition: HybridFactor.h:62
gtsam::DecisionTree::restrict
DecisionTree restrict(const Assignment< L > &assignment) const
Definition: DecisionTree.h:397
gtsam::DecisionTree::apply
DecisionTree apply(const Unary &op) const
Definition: DecisionTree-inl.h:1003
gtsam::Factor::end
const_iterator end() const
Definition: Factor.h:149
tree::f
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
Definition: testExpression.cpp:218
NonlinearFactor.h
Non-linear factor base classes.
gtsam::DecisionTree< Key, NonlinearFactorValuePair >
gtsam::b
const G & b
Definition: Group.h:79
gtsam::HybridFactor::print
void print(const std::string &s="HybridFactor\n", const KeyFormatter &formatter=DefaultKeyFormatter) const override
print
Definition: HybridFactor.cpp:96
HybridNonlinearFactor.h
A set of nonlinear factors indexed by a set of discrete keys.
a
ArrayXXi a
Definition: Array_initializer_list_23_cxx11.cpp:1
gtsam
traits
Definition: SFMdata.h:40
gtsam::DiscreteValues::missingKeys
DiscreteKeys missingKeys(const DiscreteKeys &keys) const
Return the keys that are not present in the DiscreteValues object.
Definition: DiscreteValues.h:133
gtsam::DecisionTreeFactor::max
double max() const override
Find the maximum value in the factor.
Definition: DecisionTreeFactor.h:211
gtsam::Factor::keys_
KeyVector keys_
The keys involved in this factor.
Definition: Factor.h:88
NoiseModel.h
gtsam::DiscreteValues
Definition: DiscreteValues.h:34
gtsam::Values
Definition: Values.h:65
gtsam::Factor::keys
const KeyVector & keys() const
Access the factor's involved variable keys.
Definition: Factor.h:143
gtsam::DiscreteKey
std::pair< Key, size_t > DiscreteKey
Definition: DiscreteKey.h:38
gtsam::HybridNonlinearFactor::ConstructorHelper::ConstructorHelper
ConstructorHelper(const DiscreteKey &discreteKey, const std::vector< NonlinearFactorValuePair > &pairs)
Definition: HybridNonlinearFactor.cpp:56
v
Array< int, Dynamic, 1 > v
Definition: Array_initializer_list_vector_cxx11.cpp:1
gtsam::HybridNonlinearFactor::dim
size_t dim() const
Get the dimension of the factor (number of rows on linearization). Returns the dimension of the first...
Definition: HybridNonlinearFactor.cpp:125
gtsam::HybridNonlinearFactor::ConstructorHelper::copyOrCheckContinuousKeys
void copyOrCheckContinuousKeys(const NoiseModelFactor::shared_ptr &factor)
Definition: HybridNonlinearFactor.cpp:34
gtsam::tol
const G double tol
Definition: Group.h:79
gtsam::HybridNonlinearFactor::prune
HybridNonlinearFactor::shared_ptr prune(const DecisionTreeFactor &discreteProbs) const
Prune this factor based on the discrete probabilities.
Definition: HybridNonlinearFactor.cpp:215
gtsam::HybridNonlinearFactor::factors_
FactorValuePairs factors_
Decision tree of nonlinear factors indexed by discrete keys.
Definition: HybridNonlinearFactor.h:73
gtsam::NonlinearFactorValuePair
std::pair< NoiseModelFactor::shared_ptr, double > NonlinearFactorValuePair
Alias for a NoiseModelFactor shared pointer and double scalar pair.
Definition: HybridNonlinearFactor.h:35
gtsam::valueFormatter
static std::string valueFormatter(const double &v)
Definition: DecisionTreeFactor.cpp:292
max
#define max(a, b)
Definition: datatypes.h:20
gtsam::HybridNonlinearFactor::errorTree
AlgebraicDecisionTree< Key > errorTree(const VectorValues &continuousValues) const override
HybridFactor method implementation. Should not be used.
Definition: HybridNonlinearFactor.h:76
gtsam::Ordering
Definition: inference/Ordering.h:33
gtsam::HybridNonlinearFactor::FactorValuePairs
DecisionTree< Key, NonlinearFactorValuePair > FactorValuePairs
typedef for DecisionTree which has Keys as node labels and pairs of NoiseModelFactor & an arbitrary s...
Definition: HybridNonlinearFactor.h:69
gtsam::HybridNonlinearFactor::factors
const FactorValuePairs & factors() const
Getter for NonlinearFactor decision tree.
Definition: HybridNonlinearFactor.h:176
DecisionTreeFactor.h
gtsam::equal
bool equal(const T &obj1, const T &obj2, double tol)
Definition: Testable.h:85
gtsam::HybridFactor::discreteKeys
const DiscreteKeys & discreteKeys() const
Return the discrete keys for this factor.
Definition: HybridFactor.h:131
gtsam::HybridNonlinearFactor::linearize
GaussianFactor::shared_ptr linearize(const Values &continuousValues, const DiscreteValues &assignment) const
Definition: HybridNonlinearFactor.cpp:176
gtsam::RedirectCout::str
std::string str() const
return the string
Definition: utilities.cpp:5
gtsam::HybridNonlinearFactor
Implementation of a discrete-conditioned hybrid factor.
Definition: HybridNonlinearFactor.h:58
pybind_wrapper_test_script.other
other
Definition: pybind_wrapper_test_script.py:42
gtsam::HybridNonlinearFactor::ConstructorHelper::factorTree
FactorValuePairs factorTree
Definition: HybridNonlinearFactor.cpp:32
factorError
Vector factorError(const Point3 &T1, const Point3 &T2, const TranslationFactor &factor)
Definition: testTranslationFactor.cpp:74


gtsam
Author(s):
autogenerated on Wed Mar 19 2025 03:01:48