18
18
#include < gtsam/linear/linearExceptions.h>
19
19
#include < gtsam/linear/GaussianConditional.h>
20
20
#include < gtsam/linear/VectorValues.h>
21
+ #include < gtsam/linear/Sampler.h>
21
22
22
23
#include < boost/format.hpp>
23
24
#ifdef __GNUC__
34
35
#include < list>
35
36
#include < string>
36
37
38
+ // In Wrappers we have no access to this so have a default ready
39
+ static std::mt19937_64 kRandomNumberGenerator (42 );
40
+
37
41
using namespace std ;
38
42
39
43
namespace gtsam {
@@ -43,19 +47,47 @@ namespace gtsam {
43
47
Key key, const Vector& d, const Matrix& R, const SharedDiagonal& sigmas) :
44
48
BaseFactor (key, R, d, sigmas), BaseConditional(1 ) {}
45
49
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
+ }
51
76
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
+ }
57
89
58
- /* ************************************************************************* */
90
+ /* ************************************************************************ */
59
91
void GaussianConditional::print (const string &s, const KeyFormatter& formatter) const {
60
92
cout << s << " Conditional density " ;
61
93
for (const_iterator it = beginFrontals (); it != endFrontals (); ++it) {
@@ -192,7 +224,88 @@ namespace gtsam {
192
224
}
193
225
}
194
226
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
+ /* ************************************************************************ */
196
309
#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V42
197
310
void GTSAM_DEPRECATED
198
311
GaussianConditional::scaleFrontalsBySigma (VectorValues& gy) const {
0 commit comments