67template <Space Space_, RealScalar Scalar_ =
double>
106 : m_space{std::move(
space)}
118 template <MatrixExpression Reference, MatrixExpression Root, MatrixExpression Offset>
119 requires internal::SizedByLength<Space_>
121 : m_reference{std::forward<Reference>(
reference)}
122 , m_root{std::forward<Root>(root)}
131 template <MatrixExpression Reference, MatrixExpression Root, MatrixExpression Offset>
133 : m_reference{std::forward<Reference>(
reference)}
134 , m_root{std::forward<Root>(root)}
136 , m_space{std::move(
space)}
156 [[nodiscard]] Space_
const &
183 return m_whitenedOffset;
191 internal::multiply(internal::asTriangular<Eigen::Upper>(m_root).transpose(), m_whitenedOffset);
203 template <
typename Derived>
207 m_stamp.touchValues();
212 m_whitenedOffset.noalias() -= internal::multiply(internal::asTriangular<Eigen::Upper>(m_root), shift);
216 AugmentedType stacked(n, n + 1);
217 stacked.leftCols(n) = m_root;
218 internal::forEachInverseResetJacobian(
223 [&](Eigen::Index differences,
auto const & gInverse) {
224 Eigen::Index
const k = gInverse.rows();
225 stacked.middleCols(differences, k) = m_root.middleCols(differences, k) * gInverse;
228 stacked.col(n) = m_whitenedOffset;
230 m_root = stacked.leftCols(n);
231 m_whitenedOffset = stacked.col(n);
233 m_reference = std::move(moved);
239 template <MatrixExpression Root, MatrixExpression Offset>
243 m_stamp.touchValues();
248 m_root = std::forward<Root>(root);
249 m_root.template triangularView<Eigen::StrictlyLower>().setZero();
256 [[nodiscard]] std::expected<VectorType, GaussianError>
259 if (
auto checked = checkRoot(); !checked)
261 return std::unexpected{checked.error()};
269 [[nodiscard]] std::expected<MomentsType, GaussianError>
272 if (
auto checked = checkRoot(); !checked)
274 return std::unexpected{checked.error()};
276 return momentsWithMean(solvedMean());
282 [[nodiscard]] std::expected<MatrixType, GaussianError>
288 return std::unexpected{inverse.error()};
290 MatrixType result = internal::multiply(*inverse, inverse->transpose());
295 [[nodiscard]] std::expected<MatrixType, GaussianError>
298 MatrixType result = internal::multiply(m_root.transpose(), internal::asTriangular<Eigen::Upper>(m_root));
305 [[nodiscard]] std::expected<MatrixType, GaussianError>
308 if (
auto checked = checkRoot(); !checked)
310 return std::unexpected{checked.error()};
313 internal::solveInPlace(m_root.template triangularView<Eigen::Upper>(), result);
318 [[nodiscard]] std::expected<MatrixType, GaussianError>
331 [[nodiscard]] std::expected<DensityType, GaussianError>
334 if (
auto checked = checkRoot(); !checked)
336 return std::unexpected{checked.error()};
338 m_densityMean = solvedMean();
339 m_logDeterminant =
Scalar(-2) * m_root.diagonal().array().abs().log().sum();
363 template <typename Path>
367 return internal::marginalOverPath<Path>(m_space, [&](
auto const & kept,
auto const & keptSpace) {
368 return marginalAt(kept, keptSpace);
375 template <
typename Path>
379 return internal::marginalOverElement<Path>(m_space, element, [&](
auto const & kept,
auto const & keptSpace) {
380 return marginalAt(kept, keptSpace);
395 template <
typename GivenPath,
typename Derived>
399 return internal::tagConditional<GivenPath>(
401 [&](
auto const & target,
auto const &
given,
auto const & targetSpace,
auto const & givenSpace) {
402 using GivenSpace = std::remove_cvref_t<
decltype(givenSpace)>;
406 constexpr int TargetSize = Result::DifferenceDimensionAtCompileTime;
407 constexpr int TargetMaxSize = Result::MaxDifferenceDimensionAtCompileTime;
408 using GivenVector = Eigen::Matrix<Scalar, GivenSize, 1, Eigen::ColMajor, GivenMaxSize, 1>;
409 using Stacked = internal::MatrixOf<
412 TargetSize == Eigen::Dynamic ? Eigen::Dynamic : TargetSize + 1,
414 TargetMaxSize == Eigen::Dynamic ? Eigen::Dynamic : TargetMaxSize + 1>;
415 EMRYS_FILTER_ASSERT(values.size() ==
given.values.size());
418 Eigen::Index
const t = target.differences.size();
419 typename Result::VectorType
reference = m_reference(target.values);
420 auto root =
typename Result::MatrixType{};
422 auto whitened =
typename Result::DifferenceVectorType{};
425 if constexpr (TargetSize != 0 && GivenSize != 0)
427 GivenVector
const offset =
Emrys::minus(givenSpace, values, m_reference(
given.values));
428 Stacked stacked(n, t + 1);
429 stacked.leftCols(t) = m_root(Eigen::placeholders::all, target.differences);
430 stacked.col(t) = m_whitenedOffset
431 - internal::multiply(m_root(Eigen::placeholders::all,
given.differences), offset);
433 root = stacked.topLeftCorner(t, t);
434 whitened = stacked.col(t).head(t);
438 root = m_root(target.differences, target.differences);
439 whitened = m_whitenedOffset(target.differences);
441 return Result{targetSpace, std::move(
reference), std::move(root), std::move(whitened)};
452 friend class internal::ValuesCheck;
455 using AugmentedType = internal::MatrixOf<
466 [[nodiscard]] std::expected<void, GaussianError>
473 if ((m_root.diagonal().array() ==
Scalar(0)).any())
483 template <
typename Kept,
typename KeptSpace>
484 [[nodiscard]] std::expected<SqrtInfoGaussianParams<KeptSpace, Scalar>,
GaussianError>
485 marginalAt(Kept
const & kept, KeptSpace
const & keptSpace)
const
488 using Expected = std::expected<Result, GaussianError>;
492 Eigen::Index
const k = kept.differences.size();
494 internal::resolveIndices<D, DMax>(n, internal::complementIndices<D, DMax>(n, kept.differences));
495 Eigen::Index
const r = rest.size();
497 typename Result::VectorType
reference = m_reference(kept.values);
498 AugmentedType stacked(n, n + 1);
499 stacked.leftCols(r) = m_root(Eigen::placeholders::all, rest);
500 stacked.middleCols(r, k) = m_root(Eigen::placeholders::all, kept.differences);
501 stacked.col(n) = m_whitenedOffset;
503 if ((stacked.diagonal().head(r).array() ==
Scalar(0)).any())
507 typename Result::MatrixType root = stacked.block(r, r, k, k);
508 typename Result::DifferenceVectorType whitened = stacked.col(n).tail(k);
509 return Expected{Result{keptSpace, std::move(
reference), std::move(root), std::move(whitened)}};
515 template <
typename Kept,
typename KeptSpace>
517 densityMarginalAt(Kept
const & kept, KeptSpace
const & keptSpace)
const
519 auto result = marginalAt(kept, keptSpace);
520 EMRYS_FILTER_ASSERT(result.has_value() &&
"a checked root's marginal cannot be singular");
521 return std::move(*result);
541 densityMoments()
const
543 return momentsWithMean(m_densityMean);
550 DifferenceVectorType const offset = m_root.template triangularView<Eigen::Upper>().solve(m_whitenedOffset);
559 return m_densityMean;
566 residual = internal::multiply(internal::asTriangular<Eigen::Upper>(m_root), residual).eval();
571 colorInto(
auto & colored,
auto const & normals)
const
574 internal::solveInPlace(m_root.template triangularView<Eigen::Upper>(), colored);
583 internal::fitValueDimension(m_space, m_reference.size());
587 &&
"the root and whitened offset must have a row per difference coordinate of the space"
590 m_root.template triangularView<Eigen::StrictlyLower>().setZero();
598 mutable Scalar m_logDeterminant{};
600 internal::Stamp m_stamp;
611template <Space Space_, RealScalar Scalar_ =
double>
624template <Space Space_, RealScalar Scalar_>
629 constexpr int D = Result::DifferenceDimensionAtCompileTime;
630 constexpr int DMax = Result::MaxDifferenceDimensionAtCompileTime;
631 using Stacked = internal::MatrixOf<
633 D == Eigen::Dynamic ? Eigen::Dynamic : 2 * D,
634 D == Eigen::Dynamic ? Eigen::Dynamic : D + 1,
635 DMax == Eigen::Dynamic ? Eigen::Dynamic : 2 * DMax,
636 DMax == Eigen::Dynamic ? Eigen::Dynamic : DMax + 1>;
640 Result moved = second;
642 Stacked stacked(2 * n, n + 1);
643 stacked.topLeftCorner(n, n) = first.
infoRoot();
645 stacked.bottomLeftCorner(n, n) = moved.infoRoot();
646 stacked.bottomRightCorner(n, 1) = moved.whitenedOffset();
650 auto root =
typename Result::MatrixType{stacked.topLeftCorner(n, n)};
651 root.template triangularView<Eigen::StrictlyLower>().setZero();
656 typename Result::DifferenceVectorType{stacked.topRightCorner(n, 1)}
672template <GaussianForm G>
673[[nodiscard]] std::expected<SqrtInfoGaussianParams<typename G::SpaceType, typename G::Scalar>,
GaussianError>
677 if constexpr (std::is_same_v<G, Result>)
683 auto root = form.precisionRoot();
686 return std::unexpected{root.error()};
690 typename Result::DifferenceVectorType whitened =
691 root->transpose().template triangularView<Eigen::Lower>().solve(form.infoVector());
692 return Result{form.space(), form.reference(), std::move(*root), std::move(whitened)};
696 std::expected<typename G::VectorType, GaussianError> mean = form.mean();
699 return std::unexpected{mean.error()};
706 Result::DifferenceVectorType::Zero(form.differenceDimension())
714#ifndef EMRYS_FILTER_NO_IO
725template <
typename Space_,
typename Scalar_>
727describe(std::ostream & stream, SqrtInfoGaussianParams<Space_, Scalar_>
const & gaussian, Indent indent)
729 stream << indent <<
"square-root information Gaussian";
730 printDimension(stream, gaussian.valueDimension(), gaussian.differenceDimension());
731 printMoments(stream, indent.deeper(), gaussian.moments());
Spaces built from other spaces (decisions.md [sizes-and-dimensions], [several-resizable-blocks]): Com...
How a function that stores a matrix argument takes it (decisions.md [forwarded-matrices]): the concep...
The Gaussian: its parameters GaussianParams, the Gaussian that evaluates the density,...
What marginals and conditionals are built from: resolving Eigen index sets against a space; the share...
The macros every header includes first.
Mathematical constants and scalar functions that work in every scalar type the library accepts,...
Moments: the mean and covariance that a Gaussian carries and that a mixture or a sample set is moment...
Products of fixed-size matrices by Eigen's fixed-size product at every size: multiply() is by Eigen'...
Printing: operator<< and std::formatter for every distribution, every filter (which prints its name a...
The covariance reset (decisions.md [covariance-reset]): hasIdentityReset<>, resetJacobian(),...
Solving by a factorization of a small matrix: transposedSolve() gives , the shape of a Kalman gain an...
The Space concept and what every continuous space shares (decisions.md [sizes-and-dimensions]): the t...
What parameters and their views share (decisions.md [view-stamp], [params-and-density]): Stamp,...
Triangularization: the triangular factor of a stacked matrix by Householder reflections,...
First and second moments (mean and covariance) of a distribution.
Definition Moments.h:55
Scalar_ Scalar
Definition Moments.h:58
Eigen::Index Index
Definition Moments.h:59
DifferenceMatrix< Space_, Space_, Scalar > MatrixType
Definition Moments.h:76
DifferenceVector< Space_, Scalar > DifferenceVectorType
Definition Moments.h:75
ValueVector< Space_, Scalar > VectorType
Definition Moments.h:74
static constexpr int MaxDifferenceDimensionAtCompileTime
Definition Moments.h:72
static constexpr int DifferenceDimensionAtCompileTime
Definition Moments.h:69
static constexpr int MaxValueDimensionAtCompileTime
Definition Moments.h:66
static constexpr int ValueDimensionAtCompileTime
Definition Moments.h:63
A Gaussian kept as an upper-triangular root of its precision and a whitened offset,...
Definition SqrtInfoGaussian.h:69
Space_ SpaceType
the space the values live in
Definition SqrtInfoGaussian.h:78
SqrtInfoGaussianParams(Space_ space, Reference &&reference, Root &&root, Offset &&whitenedOffset)
SqrtInfoGaussianParams(reference, root, whitenedOffset) in space, which is resized to fit them if it ...
Definition SqrtInfoGaussian.h:132
static constexpr int MaxValueDimensionAtCompileTime
a bound on the length of a value, or Eigen::Dynamic
Definition SqrtInfoGaussian.h:85
static constexpr int ValueDimensionAtCompileTime
the length of a value, or Eigen::Dynamic
Definition SqrtInfoGaussian.h:82
DifferenceVectorType infoVector() const
Definition SqrtInfoGaussian.h:188
std::expected< MatrixType, GaussianError > covarianceRoot() const
Definition SqrtInfoGaussian.h:306
std::expected< MatrixType, GaussianError > precision() const
Definition SqrtInfoGaussian.h:296
Moments< Space_, Scalar_ > MomentsType
the mean and covariance together
Definition SqrtInfoGaussian.h:72
typename MomentsType::VectorType VectorType
a value, such as the reference
Definition SqrtInfoGaussian.h:75
VectorType const & reference() const
Definition SqrtInfoGaussian.h:164
Space_ const & space() const
Definition SqrtInfoGaussian.h:157
static constexpr bool IsSqrtForm
holds a triangular root
Definition SqrtInfoGaussian.h:95
typename MomentsType::Index Index
Eigen's index type.
Definition SqrtInfoGaussian.h:74
std::expected< MatrixType, GaussianError > precisionRoot() const
Definition SqrtInfoGaussian.h:319
FormGaussian< SqrtInfoGaussianParams > DensityType
the view toDensity() returns
Definition SqrtInfoGaussian.h:79
typename MomentsType::MatrixType MatrixType
a matrix over differences
Definition SqrtInfoGaussian.h:77
Index valueDimension() const
Definition SqrtInfoGaussian.h:143
static constexpr int MaxDifferenceDimensionAtCompileTime
a bound on the length of a difference, or Eigen::Dynamic
Definition SqrtInfoGaussian.h:91
void toDensity() const &&=delete
A density of a temporary would outlive it.
void setRoot(Root &&root, Offset &&whitenedOffset)
Sets to the upper triangle of root and to whitenedOffset, about the current reference,...
Definition SqrtInfoGaussian.h:241
static constexpr int DifferenceDimensionAtCompileTime
the length of a difference and the rows of the root, or Eigen::Dynamic
Definition SqrtInfoGaussian.h:88
SqrtInfoGaussianParams(Space_ space)
Constructs a SqrtInfoGaussianParams in space, with a zero reference and no information.
Definition SqrtInfoGaussian.h:105
SqrtInfoGaussianParams()
Constructs a SqrtInfoGaussianParams in a default space, with a zero reference and no information.
Definition SqrtInfoGaussian.h:100
std::expected< MatrixType, GaussianError > covariance() const
Definition SqrtInfoGaussian.h:283
auto marginal(Index element) const
marginal<Path>() of repetition element of the repeated block Path starts at (see GaussianParams::marg...
Definition SqrtInfoGaussian.h:377
auto marginal() const
Definition SqrtInfoGaussian.h:365
typename MomentsType::Scalar Scalar
the scalar type
Definition SqrtInfoGaussian.h:73
void setReference(Eigen::MatrixBase< Derived > const &reference)
Moves the reference to reference, normalized by the space, and re-expresses the data array about it.
Definition SqrtInfoGaussian.h:205
static constexpr bool IsParams
parameters, which views check
Definition SqrtInfoGaussian.h:93
std::expected< MomentsType, GaussianError > moments() const
Definition SqrtInfoGaussian.h:270
Index differenceDimension() const
Definition SqrtInfoGaussian.h:150
std::expected< VectorType, GaussianError > mean() const
Definition SqrtInfoGaussian.h:257
typename MomentsType::DifferenceVectorType DifferenceVectorType
a difference, or the whitened offset
Definition SqrtInfoGaussian.h:76
SqrtInfoGaussianParams(Reference &&reference, Root &&root, Offset &&whitenedOffset)
Constructs a SqrtInfoGaussianParams about reference, with the upper triangle of root as and whitened...
Definition SqrtInfoGaussian.h:120
std::expected< DensityType, GaussianError > toDensity() const &
Checks the root, solves for the mean, and computes , writing both to a cache each time,...
Definition SqrtInfoGaussian.h:332
MatrixType const & infoRoot() const
Definition SqrtInfoGaussian.h:174
DifferenceVectorType const & whitenedOffset() const
Definition SqrtInfoGaussian.h:181
static constexpr bool IsInfoForm
holds a root of the precision
Definition SqrtInfoGaussian.h:94
auto conditional(Eigen::MatrixBase< Derived > const &values) const
Definition SqrtInfoGaussian.h:397
void triangularize(M &&m)
Reduces m to upper-triangular form in place by Householder reflections from the left,...
Definition Triangularization.h:52
bool allFinite(Eigen::DenseBase< Derived > const &x)
Definition Math.h:354
#define EMRYS_FILTER_NO_UNIQUE_ADDRESS
Assertion used for programmer errors (misuse of the API).
Definition Macros.h:38
@ NonFinite
a matrix, a factor, or a log-weight holds NaN or infinity (+inf, for a log-weight)
Definition NumericError.h:33
@ Singular
the precision is not positive definite, so the mean and covariance are undefined
Definition NumericError.h:32
NumericError GaussianError
Reasons a Gaussian, in any of its forms (decisions.md [gaussian-forms]), can fail to give a density,...
Definition NumericError.h:45
FormGaussian< SqrtInfoGaussianParams< Space_, Scalar_ > > SqrtInfoGaussian
The Gaussian in square-root information form, which evaluates its density: what SqrtInfoGaussianParam...
Definition SqrtInfoGaussian.h:612
InfoGaussianParams< Space_, Scalar_ > multiply(InfoGaussianParams< Space_, Scalar_ > const &first, InfoGaussianParams< Space_, Scalar_ > const &second)
Definition InfoGaussian.h:771
constexpr bool isInfoForm
Whether the GaussianForm G holds the precision, as InfoGaussianParams and SqrtInfoGaussianParams do,...
Definition GaussianForm.h:69
std::expected< SqrtInfoGaussianParams< typename G::SpaceType, typename G::Scalar >, GaussianError > toSqrtInfo(G const &form)
Definition SqrtInfoGaussian.h:674
GivenBlock< Space, P, Value > given(Space const &space, Value const &value)
Definition Measurement.h:917
constexpr Residual< Inner > residual(Inner inner={})
Definition Resampling.h:544
Eigen::Index valueDimension(S const &space)
Definition Space.h:272
auto plus(S const &space, Eigen::MatrixBase< XDerived > const &x, Eigen::MatrixBase< DDerived > const &d)
Definition Space.h:675
auto minus(S const &space, Eigen::MatrixBase< ADerived > const &a, Eigen::MatrixBase< BDerived > const &b)
Definition Space.h:715
constexpr bool hasIdentityReset
Whether the reset Jacobian of S is the identity, so that a covariance needs no change when its mean m...
Definition Reset.h:100
Eigen::Index differenceDimension(S const &space)
Definition Space.h:284
void resetCovariance(S const &space, Eigen::MatrixBase< XDerived > const &x, Eigen::MatrixBase< DDerived > const &d, Eigen::MatrixBase< CovDerived > const &cov)
Carries the covariance cov from the tangent space at x to the one at , in place: ,...
Definition Reset.h:426
constexpr int valueDimensionAtCompileTime
The value dimension of Space at compile time, or Eigen::Dynamic if it is resizable.
Definition Space.h:251
constexpr int maxValueDimensionAtCompileTime
The largest valid value dimension of Space, or Eigen::Dynamic if it is unbounded.
Definition Space.h:258
void normalizeValues(S const &space, Eigen::MatrixBase< Derived > const &block)
Brings the values in block (rows are space's coordinates, columns samples) into canonical form,...
Definition Space.h:331