1818#include < gtsam/linear/linearExceptions.h>
1919#include < gtsam/linear/GaussianConditional.h>
2020#include < gtsam/linear/VectorValues.h>
21+ #include < gtsam/linear/Sampler.h>
2122
2223#include < boost/format.hpp>
2324#ifdef __GNUC__
3435#include < list>
3536#include < string>
3637
38+ // In Wrappers we have no access to this so have a default ready
39+ static std::mt19937_64 kRandomNumberGenerator (42 );
40+
3741using namespace std ;
3842
3943namespace gtsam {
@@ -43,19 +47,47 @@ namespace gtsam {
4347 Key key, const Vector& d, const Matrix& R, const SharedDiagonal& sigmas) :
4448 BaseFactor (key, R, d, sigmas), BaseConditional(1 ) {}
4549
46- /* ************************************************************************* */
47- GaussianConditional::GaussianConditional (
48- Key key, const Vector& d, const Matrix& R,
49- Key name1, const Matrix& S, const SharedDiagonal& sigmas) :
50- BaseFactor (key, R, name1, S, d, sigmas), BaseConditional(1 ) {}
50+ /* ************************************************************************ */
51+ GaussianConditional::GaussianConditional (Key key, const Vector& d,
52+ const Matrix& R, Key parent1,
53+ const Matrix& S,
54+ const SharedDiagonal& sigmas)
55+ : BaseFactor(key, R, parent1, S, d, sigmas), BaseConditional(1 ) {}
56+
57+ /* ************************************************************************ */
58+ GaussianConditional::GaussianConditional (Key key, const Vector& d,
59+ const Matrix& R, Key parent1,
60+ const Matrix& S, Key parent2,
61+ const Matrix& T,
62+ const SharedDiagonal& sigmas)
63+ : BaseFactor(key, R, parent1, S, parent2, T, d, sigmas),
64+ BaseConditional (1 ) {}
65+
66+ /* ************************************************************************ */
67+ GaussianConditional GaussianConditional::FromMeanAndStddev (
68+ Key key, const Matrix& A, Key parent, const Vector& b, double sigma) {
69+ // |Rx + Sy - d| = |x-(Ay + b)|/sigma
70+ const Matrix R = Matrix::Identity (b.size (), b.size ());
71+ const Matrix S = -A;
72+ const Vector d = b;
73+ return GaussianConditional (key, d, R, parent, S,
74+ noiseModel::Isotropic::Sigma (b.size (), sigma));
75+ }
5176
52- /* ************************************************************************* */
53- GaussianConditional::GaussianConditional (
54- Key key, const Vector& d, const Matrix& R,
55- Key name1, const Matrix& S, Key name2, const Matrix& T, const SharedDiagonal& sigmas) :
56- BaseFactor (key, R, name1, S, name2, T, d, sigmas), BaseConditional(1 ) {}
77+ /* ************************************************************************ */
78+ GaussianConditional GaussianConditional::FromMeanAndStddev (
79+ Key key, const Matrix& A1, Key parent1, const Matrix& A2, Key parent2,
80+ const Vector& b, double sigma) {
81+ // |Rx + Sy + Tz - d| = |x-(A1 y + A2 z + b)|/sigma
82+ const Matrix R = Matrix::Identity (b.size (), b.size ());
83+ const Matrix S = -A1;
84+ const Matrix T = -A2;
85+ const Vector d = b;
86+ return GaussianConditional (key, d, R, parent1, S, parent2, T,
87+ noiseModel::Isotropic::Sigma (b.size (), sigma));
88+ }
5789
58- /* ************************************************************************* */
90+ /* ************************************************************************ */
5991 void GaussianConditional::print (const string &s, const KeyFormatter& formatter) const {
6092 cout << s << " Conditional density " ;
6193 for (const_iterator it = beginFrontals (); it != endFrontals (); ++it) {
@@ -192,7 +224,88 @@ namespace gtsam {
192224 }
193225 }
194226
195- /* ************************************************************************* */
227+ /* ************************************************************************ */
228+ JacobianFactor::shared_ptr GaussianConditional::likelihood (
229+ const VectorValues& frontalValues) const {
230+ // Error is |Rx - (d - Sy - Tz - ...)|^2
231+ // so when we instantiate x (which has to be completely known) we beget:
232+ // |Sy + Tz + ... - (d - Rx)|^2
233+ // The noise model just transfers over!
234+
235+ // Get frontalValues as vector
236+ const Vector x =
237+ frontalValues.vector (KeyVector (beginFrontals (), endFrontals ()));
238+
239+ // Copy the augmented Jacobian matrix:
240+ auto newAb = Ab_;
241+
242+ // Restrict view to parent blocks
243+ newAb.firstBlock () += nrFrontals_;
244+
245+ // Update right-hand-side (last column)
246+ auto last = newAb.matrix ().cols () - 1 ;
247+ const auto RR = R ().triangularView <Eigen::Upper>();
248+ newAb.matrix ().col (last) -= RR * x;
249+
250+ // The keys now do not include the frontal keys:
251+ KeyVector newKeys;
252+ newKeys.reserve (nrParents ());
253+ for (auto && key : parents ()) newKeys.push_back (key);
254+
255+ // Hopefully second newAb copy below is optimized out...
256+ return boost::make_shared<JacobianFactor>(newKeys, newAb, model_);
257+ }
258+
259+ /* **************************************************************************/
260+ JacobianFactor::shared_ptr GaussianConditional::likelihood (
261+ const Vector& frontal) const {
262+ if (nrFrontals () != 1 )
263+ throw std::invalid_argument (
264+ " GaussianConditional Single value likelihood can only be invoked on "
265+ " single-variable conditional" );
266+ VectorValues values;
267+ values.insert (keys_[0 ], frontal);
268+ return likelihood (values);
269+ }
270+
271+ /* ************************************************************************ */
272+ VectorValues GaussianConditional::sample (const VectorValues& parentsValues,
273+ std::mt19937_64* rng) const {
274+ if (nrFrontals () != 1 ) {
275+ throw std::invalid_argument (
276+ " GaussianConditional::sample can only be called on single variable "
277+ " conditionals" );
278+ }
279+ if (!model_) {
280+ throw std::invalid_argument (
281+ " GaussianConditional::sample can only be called if a diagonal noise "
282+ " model was specified at construction." );
283+ }
284+ VectorValues solution = solve (parentsValues);
285+ Key key = firstFrontalKey ();
286+ const Vector& sigmas = model_->sigmas ();
287+ solution[key] += Sampler::sampleDiagonal (sigmas, rng);
288+ return solution;
289+ }
290+
291+ VectorValues GaussianConditional::sample (std::mt19937_64* rng) const {
292+ if (nrParents () != 0 )
293+ throw std::invalid_argument (
294+ " sample() can only be invoked on no-parent prior" );
295+ VectorValues values;
296+ return sample (values);
297+ }
298+
299+ /* ************************************************************************ */
300+ VectorValues GaussianConditional::sample () const {
301+ return sample (&kRandomNumberGenerator );
302+ }
303+
304+ VectorValues GaussianConditional::sample (const VectorValues& given) const {
305+ return sample (given, &kRandomNumberGenerator );
306+ }
307+
308+ /* ************************************************************************ */
196309#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V42
197310 void GTSAM_DEPRECATED
198311 GaussianConditional::scaleFrontalsBySigma (VectorValues& gy) const {
0 commit comments