19namespace Emrys::internal
28template <
typename MatrixType,
typename DeviationsDerived,
typename WeightsDerived>
29[[nodiscard]] MatrixType
30weightedCovariance(Eigen::MatrixBase<DeviationsDerived>
const & deviations, Eigen::ArrayBase<WeightsDerived>
const & w)
32 using Scalar =
typename MatrixType::Scalar;
33 using Deviations = MatrixOf<
35 MatrixType::RowsAtCompileTime,
36 DeviationsDerived::ColsAtCompileTime,
37 MatrixType::MaxRowsAtCompileTime,
38 DeviationsDerived::MaxColsAtCompileTime>;
39 Deviations
const scaled = deviations * w.sqrt().matrix().asDiagonal();
40 auto cov = MatrixType{deviations.rows(), deviations.rows()};
41 if constexpr (MatrixType::MaxRowsAtCompileTime == 1)
44 cov.setConstant(scaled.squaredNorm());
49 cov.template selfadjointView<Eigen::Lower>().rankUpdate(scaled);
50 for (Eigen::Index j = 1; j < cov.cols(); ++j)
52 for (Eigen::Index i = 0; i < j; ++i)
54 cov(i, j) = cov(j, i);
64template <
typename Derived>
66mirrorLower(Eigen::MatrixBase<Derived> & cov)
68 cov.template triangularView<Eigen::StrictlyUpper>() = cov.transpose();
85template <
typename MomentsType,
typename Space,
typename MeanAt,
typename LogWeightAt>
86[[nodiscard]] MomentsType
91 LogWeightAt logWeightAt,
92 typename MomentsType::Scalar logTotal
95 using Scalar =
typename MomentsType::Scalar;
96 using DifferenceVectorType =
typename MomentsType::DifferenceVectorType;
97 auto const weight = [&](Eigen::Index i) {
98 return Eigen::numext::exp(Scalar(logWeightAt(i)) - logTotal);
100 auto const skip = [&](Eigen::Index i) {
101 return Scalar(logWeightAt(i)) == -Eigen::NumTraits<Scalar>::infinity();
104 auto & cov = result.covarianceLower();
110 auto const addCov = [&](DifferenceVectorType
const & deviation, Scalar w) {
111 if constexpr (DifferenceVectorType::SizeAtCompileTime != Eigen::Dynamic)
113 cov.template triangularView<Eigen::Lower>() += deviation.lazyProduct((w * deviation).transpose());
117 cov.template selfadjointView<Eigen::Lower>().rankUpdate(deviation, w);
122 result.mean().setZero();
123 for (Eigen::Index i = 0; i < count; ++i)
127 result.mean() += weight(i) * meanAt(i);
130 for (Eigen::Index i = 0; i < count; ++i)
134 addCov(DifferenceVectorType{meanAt(i) - result.mean()}, weight(i));
141 Eigen::Index reference = 0;
142 for (Eigen::Index i = 1; i < count; ++i)
144 if (logWeightAt(i) > logWeightAt(reference))
149 result.mean() = meanAt(reference);
150 auto shift = DifferenceVectorType{};
151 for (
int pass = 0; pass < 2; ++pass)
154 for (Eigen::Index i = 0; i < count; ++i)
158 shift += weight(i) *
Emrys::minus(space, meanAt(i), result.mean());
163 for (Eigen::Index i = 0; i < count; ++i)
167 addCov(DifferenceVectorType{
Emrys::minus(space, meanAt(i), result.mean()) - shift}, weight(i));
171 result.mean() =
Emrys::plus(space, result.mean(), shift);
184template <
typename MomentsType,
typename Space,
typename StatesDerived,
typename WeightsDerived>
185[[nodiscard]] MomentsType
188 Eigen::MatrixBase<StatesDerived>
const & states,
189 Eigen::ArrayBase<WeightsDerived>
const & logWeights,
190 typename MomentsType::Scalar logTotal
193 MomentsType result = pointMomentsIn<MomentsType>(
196 [&](Eigen::Index i) {
197 return states.col(i);
199 [&](Eigen::Index i) {
200 return logWeights.derived()(i);
204 mirrorLower(result.covarianceLower());
215template <
typename MomentsType, ExecutionPolicy P,
typename Space,
typename StatesDerived,
typename WeightsDerived>
216[[nodiscard]] MomentsType
220 Eigen::MatrixBase<StatesDerived>
const & states,
221 Eigen::ArrayBase<WeightsDerived>
const & logWeights,
222 typename MomentsType::Scalar logTotal
225 if constexpr (isSequential<P>)
227 return weightedMomentsIn<MomentsType>(space, states, logWeights, logTotal);
231 using Scalar =
typename MomentsType::Scalar;
232 using VectorType =
typename MomentsType::VectorType;
233 using DifferenceVectorType =
typename MomentsType::DifferenceVectorType;
234 using MatrixType =
typename MomentsType::MatrixType;
236 using Weights = Eigen::Array<Scalar, Eigen::Dynamic, 1>;
237 Eigen::Index
const count = states.cols();
238 auto const weightsOf = [&](Eigen::Index begin, Eigen::Index length) {
239 return Weights{(logWeights.derived().segment(begin, length) - logTotal).exp()};
241 auto const add = [](
auto a,
auto const & b) {
246 auto const covarianceAbout = [&](
auto const & center, DifferenceVectorType
const & shift) {
250 [&](Eigen::Index begin, Eigen::Index length) {
251 Deviations deviations =
Emrys::minus(space, states.middleCols(begin, length), center);
252 deviations.colwise() -= shift;
253 return weightedCovariance<MatrixType>(deviations, weightsOf(begin, length));
261 result.mean() = reduceRanges(
264 [&](Eigen::Index begin, Eigen::Index length) {
265 return VectorType{states.middleCols(begin, length) * weightsOf(begin, length).matrix()};
269 result.covarianceLower() =
282 Heaviest
const heaviest = reduceRanges(
285 [&](Eigen::Index begin, Eigen::Index length) {
286 Eigen::Index index = 0;
287 Scalar
const logWeight = logWeights.derived().segment(begin, length).maxCoeff(&index);
288 return Heaviest{logWeight, begin + index};
290 [](Heaviest
const & a, Heaviest
const & b) {
291 return b.logWeight > a.logWeight ? b : a;
294 auto const shiftFrom = [&](VectorType
const & center) {
298 [&](Eigen::Index begin, Eigen::Index length) {
299 return DifferenceVectorType{
300 Emrys::minus(space, states.middleCols(begin, length), center)
301 * weightsOf(begin, length).matrix()
307 VectorType
const reference = states.col(heaviest.index);
308 VectorType
const center =
Emrys::plus(space, reference, shiftFrom(reference));
309 DifferenceVectorType
const shift = shiftFrom(center);
311 result.covarianceLower() = covarianceAbout(center, shift);
327template <
typename MomentsType,
typename Space,
typename MeanAt,
typename CovAt,
typename LogWeightAt>
328[[nodiscard]] MomentsType
334 LogWeightAt logWeightAt,
335 typename MomentsType::Scalar logTotal
338 using Scalar =
typename MomentsType::Scalar;
339 MomentsType result = pointMomentsIn<MomentsType>(space, count, meanAt, logWeightAt, logTotal);
340 for (Eigen::Index i = 0; i < count; ++i)
342 if (Scalar(logWeightAt(i)) != -Eigen::NumTraits<Scalar>::infinity())
344 result.covarianceLower().template triangularView<Eigen::Lower>() +=
345 Eigen::numext::exp(Scalar(logWeightAt(i)) - logTotal) * covAt(i);
348 mirrorLower(result.covarianceLower());
357template <
typename WeightsDerived>
358[[nodiscard]]
typename WeightsDerived::Scalar
359ess(Eigen::ArrayBase<WeightsDerived>
const & logWeights,
typename WeightsDerived::Scalar logTotal)
361 using Scalar =
typename WeightsDerived::Scalar;
362 return Scalar(1) / (logWeights - logTotal).exp().square().sum();
368template <ExecutionPolicy P,
typename WeightsDerived>
369[[nodiscard]]
typename WeightsDerived::Scalar
370ess(P && policy, Eigen::ArrayBase<WeightsDerived>
const & logWeights,
typename WeightsDerived::Scalar logTotal)
372 using Scalar =
typename WeightsDerived::Scalar;
373 if constexpr (isSequential<P>)
375 return ess(logWeights, logTotal);
379 Scalar
const sumOfSquares = reduceRanges(
380 std::forward<P>(policy),
382 [&](Eigen::Index begin, Eigen::Index length) {
383 return Scalar((logWeights.derived().segment(begin, length) - logTotal).exp().square().sum());
385 [](Scalar a, Scalar b) {
389 return Scalar(1) / sumOfSquares;
Execution policies (decisions.md [execution-policies]): execution::sequential, the ExecutionPolicy co...
The macros every header includes first.
SampleSet: a matrix whose columns are samples in a space, which the samplers return and the unscented...
The Space concept and what every continuous space shares (decisions.md [sizes-and-dimensions]): the t...
Eigen::Matrix< Scalar, valueDimensionAtCompileTime< Space >, Eigen::Dynamic,(maxValueDimensionAtCompileTime< Space >==1 ? Eigen::RowMajor :Eigen::ColMajor), maxValueDimensionAtCompileTime< Space >, Eigen::Dynamic > SampleSet
A matrix whose columns are samples in Space (see Spaces), with the space's size and storage bound.
Definition SampleSet.h:33
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
Eigen::Index differenceDimension(S const &space)
Definition Space.h:284
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
constexpr bool hasPlainDifferences
Whether the differences of S are plain: its difference space has no normalize(), and it has neither p...
Definition Space.h:311