78template <
internal::ComponentOrInfoForm Component_,
typename Allocator_>
81template <
internal::ComponentOrInfoForm Component_,
typename Allocator_>
84template <
typename Source,
typename Selection,
typename SubSpace>
89struct MixtureLineageAccess;
125template <RealScalar Scalar_,
typename Allocator_ = DefaultAllocator>
134 MixtureLineage() =
default;
138 : m_logShares(ScalarAllocator(allocator))
148 : m_logShares(other.m_logShares, ScalarAllocator(allocator))
149 , m_parentCount{other.m_parentCount}
150 , m_count{other.m_count}
160 : m_logShares(std::move(other.m_logShares), ScalarAllocator(allocator))
161 , m_parentCount{other.m_parentCount}
162 , m_count{other.m_count}
173 ~MixtureLineage() =
default;
195 return m_parentCount;
202 return m_parentCount == 0 ?
Index(0) :
Index(m_logShares.size()) / m_parentCount;
206 [[nodiscard]] std::span<Scalar const>
209 EMRYS_FILTER_ASSERT(i >= 0 && i <
size() &&
"the component has no row");
210 return {m_logShares.data() + i * m_parentCount, std::size_t(m_parentCount)};
217 EMRYS_FILTER_ASSERT(parent >= 0 && parent < m_parentCount &&
"no such parent");
218 return logShares(i)[std::size_t(parent)];
228 template <
typename Parents,
typename Children>
230 carry(Eigen::MatrixBase<Parents>
const & parents, Eigen::MatrixBase<Children> & children,
Scalar orphan = 0)
const
233 parents.size() ==
parentCount() && children.size() ==
size() &&
"one value per parent and per component"
235 Scalar const none = -Eigen::NumTraits<Scalar>::infinity();
239 Scalar const top = *std::ranges::max_element(shares);
242 children(i) = orphan;
247 for (
Index parent = 0; parent < m_parentCount; ++parent)
249 Scalar const share = Eigen::numext::exp(
Scalar(shares[std::size_t(parent)] - top));
250 sum += share * parents(parent);
253 children(i) = sum / total;
260 template <
internal::ComponentOrInfoForm,
typename>
263 friend struct internal::MixtureLineageAccess;
265 using ScalarAllocator = internal::ReBound<Allocator_, Scalar>;
278 start(
Index components, std::optional<Index> capacity)
281 m_parentCount = components;
284 m_logShares.reserve(std::size_t(*capacity * components));
286 m_logShares.assign(std::size_t(components * components), -Eigen::NumTraits<Scalar>::infinity());
287 for (
Index i = 0; i < components; ++i)
289 m_logShares[std::size_t(i * components + i)] =
Scalar(0);
315 m_logShares.resize(m_logShares.size() + std::size_t(m_parentCount), -Eigen::NumTraits<Scalar>::infinity());
321 push(std::span<Scalar const> row)
325 EMRYS_FILTER_ASSERT(
Index(row.size()) == m_parentCount &&
"the row must have a share per parent");
326 m_logShares.insert(m_logShares.end(), row.begin(), row.end());
336 std::size_t
const end = m_logShares.size();
337 m_logShares.resize(end + std::size_t(m_parentCount));
339 m_logShares.begin() + i * m_parentCount,
341 m_logShares.begin() + std::ptrdiff_t(end)
350 if (tracking() && from != to)
353 m_logShares.begin() + from * m_parentCount,
355 m_logShares.begin() + to * m_parentCount
366 m_logShares.resize(std::size_t(rows * m_parentCount));
376 moveRow(
size() - 1, i);
377 truncate(
size() - 1);
391 auto total = LogSumExp<Scalar>{};
393 total.add(logAbsorb);
394 Scalar const logTotal = total.value();
399 Scalar *
const kept = m_logShares.data() +
keep * m_parentCount;
400 Scalar const *
const absorbed = m_logShares.data() + absorb * m_parentCount;
401 for (
Index n = 0; n < m_parentCount; ++n)
403 auto share = LogSumExp<Scalar>{};
404 share.add(kept[n] + logKeep - logTotal);
405 share.add(absorbed[n] + logAbsorb - logTotal);
406 kept[n] = share.value();
412 swap(MixtureLineage & other)
414 m_logShares.swap(other.m_logShares);
415 std::swap(m_parentCount, other.m_parentCount);
416 std::swap(m_count, other.m_count);
419 internal::Buffer<Scalar, Allocator_> m_logShares;
420 Index m_parentCount = 0;
430struct MixtureLineageAccess
433 template <
typename Scalar,
typename ToAllocator,
typename FromAllocator>
435 assign(MixtureLineage<Scalar, ToAllocator> & to, MixtureLineage<Scalar, FromAllocator>
const & from)
437 to.m_logShares.assign(from.m_logShares.begin(), from.m_logShares.end());
438 to.m_parentCount = from.m_parentCount;
439 to.m_count = from.m_count;
443 template <
typename MixtureType>
445 copy(MixtureType & to, MixtureType
const & from)
447 to.m_lineage = from.m_lineage;
451 template <
typename MixtureType>
453 startFrom(MixtureType & to, MixtureType
const & from)
455 EMRYS_FILTER_ASSERT(to.empty() &&
"the mixture must have no components");
456 to.m_lineage.m_logShares.clear();
457 to.m_lineage.m_parentCount = from.m_lineage.m_parentCount;
458 to.m_lineage.m_count = from.m_lineage.m_count;
462 template <
typename MixtureType>
464 inherit(MixtureType & to, MixtureType
const & from, Eigen::Index i)
466 if (from.m_lineage.tracking())
468 to.m_lineage.truncate(to.size() - 1);
469 to.m_lineage.push(from.m_lineage.logShares(i));
477template <
typename Source,
typename Target,
typename Given,
typename Derived,
typename TargetSpace,
typename GivenSpace>
480 Source
const & source,
481 Target
const & target,
483 Eigen::MatrixBase<Derived>
const & values,
484 TargetSpace
const & targetSpace,
485 GivenSpace
const & givenSpace
488 EMRYS_FILTER_ASSERT(distinctIndices(target.values,
given.values) &&
"target and given indices must be distinct");
489 using Params = MixtureParams<Gaussian<TargetSpace, typename Source::Scalar>,
typename Source::allocator_type>;
490 using Result = std::expected<Params, GaussianError>;
491 auto result =
Params{targetSpace, source.get_allocator()};
492 result.reserve(source.size());
493 for (
auto const & entry : source)
495 auto conditioned = conditionMomentsWithEvidence(
496 entry.component.mean(),
497 entry.component.covarianceLower(),
509 entry.logWeight + conditioned->logLikelihood,
510 std::move(conditioned->moments.mean),
511 std::move(conditioned->moments.cov)
514 return Result{std::move(result)};
518template <
typename GivenPath,
typename Source,
typename Derived>
520tagConditionalMixture(Source
const & source, Eigen::MatrixBase<Derived>
const & values)
522 return tagConditional<GivenPath>(
524 [&](
auto const & target,
auto const &
given,
auto const & targetSpace,
auto const & givenSpace) {
525 return conditionalMixtureIn(source, target, given, values, targetSpace, givenSpace);
577template <
internal::ComponentOrInfoForm Component_,
typename Allocator_ = DefaultAllocator>
582 "a Gaussian in an information form is not a mixture component, having no collapse; convert each "
583 "with toGaussian() or toSqrt() and hold a Gaussian or a SqrtGaussian (decisions.md [gaussian-forms])"
592 using Scalar =
typename ComponentType::Scalar;
618 struct Entry : internal::AllocatorTypeOf<ComponentType>
627 template <
typename A>
628 requires(std::is_constructible_v<ComponentType, ComponentType const &, A const &>)
635 template <
typename A>
636 requires(std::is_constructible_v<ComponentType, ComponentType &&, A const &>)
639 ,
component{std::move(other.component), allocator}
659 using const_iterator =
typename internal::Buffer<Entry, Allocator_>::const_iterator;
664 template <
bool ReturnRemovedWeight>
665 using RemovalResult = std::conditional_t<ReturnRemovedWeight, std::expected<Scalar, WeightError>,
void>;
686 return m_entry.logWeight;
700 return m_entry.component;
706 template <
typename C>
712 component.space() == m_entry.component.space() &&
"the component must be in the mixture's space"
714 MixtureParams::assignComponent(m_entry, std::forward<C>(
component));
720 template <
typename F>
721 requires std::invocable<F &, ComponentType &>
725 return internal::keepingSpace(m_entry.component, f);
753 template <MatrixExpression Mean>
758 m_entry.component.setMean(std::forward<Mean>(
mean));
762 template <MatrixExpression Cov>
767 m_entry.component.setCovariance(std::forward<Cov>(cov));
775 MixtureParams::assignComponent(m_entry, std::move(
moments));
780 friend MixtureParams;
792 MixtureParams() =
default;
796 : m_entries(EntryAllocator(allocator))
797 , m_weightScratch(ScalarAllocator(allocator))
798 , m_lineage(allocator)
813 requires internal::SizedByLength<SpaceType>
823 m_space = std::move(
space);
855 : MixtureParams{allocator}
857 m_space = other.m_space;
858 if (other.m_capacity)
862 m_entries.assign(other.m_entries.begin(), other.m_entries.end());
867 : m_entries{std::move(other.m_entries)}
868 , m_space{std::move(other.m_space)}
869 , m_capacity{other.m_capacity}
870 , m_weightScratch{std::move(other.m_weightScratch)}
871 , m_lineage{std::move(other.m_lineage)}
873 other.m_stamp.touchShape();
880 : m_entries{std::move(other.m_entries), EntryAllocator(allocator)}
881 , m_space{std::move(other.m_space)}
882 , m_capacity{other.m_capacity}
883 , m_weightScratch(ScalarAllocator(allocator))
884 , m_lineage{std::move(other.m_lineage), allocator}
886 other.m_stamp.touchShape();
896 m_stamp.touchShape();
901 assertCapacity(other.size());
902 m_entries.assign(other.m_entries.begin(), other.m_entries.end());
903 m_space = other.m_space;
916 m_stamp.touchShape();
917 other.m_stamp.touchShape();
922 if (std::allocator_traits<Allocator_>::propagate_on_container_move_assignment::value
928 m_weightScratch = std::move(other.m_weightScratch);
930 m_entries = std::move(other.m_entries);
931 m_capacity = other.m_capacity;
932 m_lineage = std::move(other.m_lineage);
937 assertCapacity(other.size());
939 std::make_move_iterator(other.m_entries.begin()),
940 std::make_move_iterator(other.m_entries.end())
942 m_lineage = other.m_lineage;
944 m_space = std::move(other.m_space);
959 return Index(m_entries.size());
966 return m_entries.empty();
970 [[nodiscard]] std::optional<Index>
982 EMRYS_FILTER_ASSERT(
capacity >=
size() &&
"the capacity is smaller than the mixture");
1016 m_stamp.touchShape();
1017 internal::fitValueDimension(m_space, n);
1018 for (
auto & entry : m_entries)
1020 entry.component.resize(n);
1029 template <
typename Path,
typename MeanDerived,
typename CovDerived,
typename CrossDerived>
1034 Eigen::MatrixBase<MeanDerived>
const & mean,
1035 Eigen::MatrixBase<CovDerived>
const & cov,
1036 Eigen::MatrixBase<CrossDerived>
const & cross
1039 m_stamp.touchShape();
1040 static_cast<void>(internal::growBlock<Path>(m_space, element, mean.size()));
1041 for (
auto & entry : m_entries)
1043 entry.component.template
insert<Path>(element, mean, cov, cross);
1048 template <
typename Path,
typename MeanDerived,
typename CovDerived>
1051 insert(
Index element, Eigen::MatrixBase<MeanDerived>
const & mean, Eigen::MatrixBase<CovDerived>
const & cov)
1053 using Cross = internal::MatrixOf<
1057 CovDerived::MaxRowsAtCompileTime,
1058 MomentsType::MatrixType::MaxColsAtCompileTime>;
1065 template <
typename Path>
1070 m_stamp.touchShape();
1071 static_cast<void>(internal::shrinkBlock<Path>(m_space, element, count));
1072 for (
auto & entry : m_entries)
1074 entry.component.template
erase<Path>(element, count);
1082 m_stamp.touchValues();
1084 m_entries.reserve(std::size_t(n));
1092 m_stamp.touchShape();
1094 m_lineage.clearRows();
1105 m_stamp.touchShape();
1106 other.m_stamp.touchShape();
1107 EMRYS_FILTER_ASSERT(
get_allocator() == other.get_allocator() &&
"the mixtures must have equal allocators");
1108 assertCapacity(other.size());
1109 other.assertCapacity(
size());
1110 m_entries.swap(other.m_entries);
1111 std::swap(m_space, other.m_space);
1112 m_lineage.swap(other.m_lineage);
1132 m_stamp.touchValues();
1133 m_lineage.start(
size(), m_capacity);
1140 return m_entries.cbegin();
1147 return m_entries.cend();
1154 [[nodiscard]] Entry
const &
1167 m_stamp.touchShape();
1168 EMRYS_FILTER_ASSERT(component.space() == m_space &&
"the component must be in the mixture's space");
1169 assertCapacity(
size() + 1);
1170 m_entries.push_back(Entry{logWeight, std::move(component)});
1171 m_lineage.pushOrphan();
1180 EMRYS_FILTER_ASSERT(
1189 template <MatrixExpression Mean, MatrixExpression Cov>
1194 return add(logWeight,
MomentsType{std::forward<Mean>(mean), std::forward<Cov>(cov)});
1202 m_stamp.touchShape();
1210 EMRYS_FILTER_ASSERT(component.space() == m_space &&
"the component must be in the mixture's space");
1211 assignComponent(mutableAt(i), std::move(component));
1219 assignComponent(mutableAt(i), std::move(moments));
1223 template <MatrixExpression Mean>
1228 mutableAt(i).component.setMean(std::forward<Mean>(mean));
1232 template <MatrixExpression Cov>
1237 mutableAt(i).component.setCovariance(std::forward<Cov>(cov));
1244 mutableAt(i).logWeight = logWeight;
1251 mutableAt(i).logWeight += logScale;
1258 m_stamp.touchValues();
1259 for (
auto & entry : m_entries)
1261 entry.logWeight += logScale;
1268 [[nodiscard]] std::expected<Scalar, WeightError>
1271 return internal::logTotalWeight<Scalar>(m_entries | std::views::transform(&
Entry::logWeight));
1278 [[nodiscard]] std::expected<void, WeightError>
1281 m_stamp.touchValues();
1285 return std::unexpected{total.error()};
1297 [[nodiscard]] std::expected<Scalar, WeightError>
1301 return essGiven(total);
1314 EMRYS_FILTER_ASSERT(!
empty() &&
"the most probable component of an empty mixture");
1315 return Index(std::ranges::max_element(m_entries, std::ranges::less{}, &
Entry::logWeight) - m_entries.begin());
1324 template <std::ranges::input_range R>
1329 if constexpr (std::ranges::sized_range<R>)
1333 for (
auto && [logWeight, component] : components)
1335 add(logWeight, component);
1345 m_stamp.touchShape();
1346 EMRYS_FILTER_ASSERT(other.m_space == m_space &&
"cannot append a mixture in a different space");
1347 std::size_t
const n = other.m_entries.size();
1349 m_entries.reserve(m_entries.size() + n);
1350 for (std::size_t i = 0; i < n; ++i)
1352 m_entries.push_back(other.m_entries[i]);
1353 m_lineage.pushOrphan();
1362 template <
typename F>
1373 template <ExecutionPolicy P,
typename F>
1378 std::is_void_v<std::invoke_result_t<F &, MutableEntry &>>,
1379 "forEach() takes a callback that returns nothing; one that returns a log scale factor goes to reweight()"
1381 visitEntries(std::forward<P>(policy), [&](MutableEntry & handle, Entry &) {
1382 std::invoke(f, handle);
1389 template <
typename F>
1397 template <ExecutionPolicy P,
typename F>
1402 std::floating_point<std::remove_cvref_t<std::invoke_result_t<F &, MutableEntry &>>>,
1403 "reweight() takes a callback that returns a log scale factor, a floating-point number"
1405 visitEntries(std::forward<P>(policy), [&](MutableEntry & handle, Entry & entry) {
1406 entry.logWeight +=
Scalar(std::invoke(f, handle));
1436 assertIndex(second);
1437 Index const pair[2] = {first, second};
1438 EMRYS_FILTER_ASSERT(pair[0] != pair[1] &&
"cannot merge a component with itself");
1442 return at(pair[i]).component;
1445 return at(pair[i]).logWeight;
1460 return mergeInto(keep, absorb, std::move(component));
1475 return mergeInto(keep, absorb, std::move(moments));
1486 template <std::ranges::forward_range R>
1491 m_stamp.touchShape();
1492 EMRYS_FILTER_ASSERT(!std::ranges::empty(children));
1494 for ([[maybe_unused]]
auto && [logRelativeWeight, child] : children)
1496 relativeTotal.add(logRelativeWeight);
1498 Scalar const logTotal = relativeTotal.value();
1499 EMRYS_FILTER_ASSERT(
isFinite(logTotal) &&
"relative weights must have a finite, nonzero sum");
1500 Scalar const logBase = at(i).logWeight - logTotal;
1502 for (
auto && [logRelativeWeight, child] : children)
1506 at(i).logWeight = logBase + logRelativeWeight;
1507 assignComponent(at(i), child);
1512 add(logBase + logRelativeWeight, child);
1513 m_lineage.truncate(
size() - 1);
1514 m_lineage.pushCopyOf(i);
1526 template <
bool ReturnRemovedWeight = false,
typename Pred>
1527 requires(!ReturnRemovedWeight)
1531 removeEntriesIf<false>(std::move(pred));
1537 template <
bool ReturnRemovedWeight,
typename Pred>
1538 requires ReturnRemovedWeight
1539 [[nodiscard]] std::expected<Scalar, WeightError>
1542 return removeEntriesIf<true>(std::move(pred));
1557 [[nodiscard]] std::expected<Scalar, WeightError>
1560 return pruneWith(internal::PruneBelowRule<Scalar>{logThreshold});
1573 [[nodiscard]] std::expected<Scalar, WeightError>
1576 return pruneWith(internal::PruneTailRule<Scalar>{logFraction});
1588 [[nodiscard]] std::expected<Scalar, WeightError>
1591 return pruneWith(internal::PruneToSizeRule{maxSize});
1601 template <
typename Path>
1605 return internal::tagMarginal<MixtureMarginal, Path>(*
this);
1609 template <
typename Path>
1614 template <typename Path>
1618 return internal::elementMarginal<MixtureMarginal, Path>(*
this, element);
1622 template <
typename Path>
1639 template <
typename GivenPath,
typename Derived>
1644 return internal::tagConditionalMixture<GivenPath>(*
this, values);
1661 [[nodiscard]] std::expected<void, MixtureError>
1664 return factorizeComponents(*
this, internal::NoRepair{});
1679 template <
typename R>
1680 [[nodiscard]] std::expected<void, MixtureError>
1683 m_stamp.touchValues();
1684 return factorizeComponents(*
this, repair);
1691 [[nodiscard]] std::expected<DensityType, MixtureError>
1696 return std::unexpected{result.error()};
1698 return DensityType{*
this};
1710 template <typename R>
1714 if (
auto result =
factorize(repair); !result)
1716 return std::unexpected{result.error()};
1718 return DensityType{*
this};
1722 template <
typename R>
1732 essGiven(
Scalar total)
const
1735 for (
auto const & entry : m_entries)
1737 sumOfSquares += Eigen::numext::abs2(Eigen::numext::exp(entry.logWeight - total));
1739 return Scalar(1) / sumOfSquares;
1744 friend class internal::ValuesCheck;
1748 friend class internal::ShapeCheck;
1750 friend struct internal::MixtureLineageAccess;
1756 template <
typename Self,
typename R>
1757 [[nodiscard]]
static std::expected<void, MixtureError>
1758 factorizeComponents(Self & self, R
const & repair)
1760 constexpr bool Repairs = !std::is_same_v<R, internal::NoRepair>;
1761 auto const factorizeOne = [&](
auto & component) {
1762 if constexpr (Repairs)
1764 return component.factorize(repair);
1768 return component.factorize();
1771 auto const total = self.logTotalWeight();
1776 if constexpr (Repairs)
1781 for (
Index i = 0; i < self.size(); ++i)
1783 auto const & component = std::as_const(self.at(i).component);
1784 if (!component.factorize())
1787 if (
auto result = factorizeOne(trial); !result)
1789 return std::unexpected{
MixtureError{ComponentError{i, result.error()}}};
1794 for (
Index i = 0; i < self.size(); ++i)
1796 if (
auto result = factorizeOne(self.at(i).component); !result)
1798 return std::unexpected{
MixtureError{ComponentError{i, result.error()}}};
1803 if (self.m_logTotalWeight != *total)
1805 self.m_logTotalWeight = *total;
1810 using EntryAllocator = internal::ReBound<Allocator_, Entry>;
1811 using ScalarAllocator = internal::ReBound<Allocator_, Scalar>;
1817 internal::fitValueDimension(m_space, n);
1825 entry.component.setMean(moments.mean());
1826 entry.component.setCovariance(moments.covarianceLower());
1834 entry.component.setMean(std::move(moments.mean()));
1835 entry.component.setCovariance(std::move(moments.covarianceLower()));
1839 template <
bool ReturnRemovedWeight,
typename Pred>
1841 removeEntriesIf(Pred pred)
1843 m_stamp.touchShape();
1844 auto const guard = internal::CallbackGuard{m_stamp};
1845 auto const removeAtIndex = [&](
Index i) {
1847 if constexpr (std::is_invocable_v<Pred &, Index, Entry const &>)
1849 remove =
static_cast<bool>(std::invoke(pred, i, std::as_const(at(i))));
1853 remove =
static_cast<bool>(std::invoke(pred, std::as_const(at(i))));
1858 if constexpr (ReturnRemovedWeight)
1863 return std::unexpected{total.error()};
1865 return compact(removeAtIndex) - *total;
1869 compact(removeAtIndex);
1876 template <ExecutionPolicy P,
typename Visit>
1878 visitEntries(P && policy, Visit
const & visit)
1880 m_stamp.touchValues();
1881 auto const guard = internal::CallbackGuard{m_stamp};
1882 internal::forEachIndex(std::forward<P>(policy),
size(), [&](
Index i) {
1883 auto & entry = m_entries[std::size_t(i)];
1885 visit(handle, entry);
1894 entry.component = component;
1901 entry.component = std::move(component);
1907 template <
typename Replacement>
1909 mergeInto(
Index k,
Index a, Replacement && replacement)
1913 m_stamp.touchShape();
1914 EMRYS_FILTER_ASSERT(k != a &&
"cannot merge a component with itself");
1915 auto weight = LogSumExp<Scalar>{};
1916 weight.add(at(k).logWeight);
1917 weight.add(at(a).logWeight);
1918 m_lineage.merge(k, a, at(k).logWeight, at(a).logWeight);
1919 at(k).logWeight = weight.value();
1920 assignComponent(at(k), std::forward<Replacement>(replacement));
1921 bool const keepWasLast = k ==
size() - 1;
1923 return keepWasLast ? a : k;
1928 assertCapacity([[maybe_unused]]
Index count)
const
1930 EMRYS_FILTER_ASSERT(
1931 (!m_capacity || count <= *m_capacity) &&
"the mixture would hold more components than its capacity"
1937 reserveScratch(
Index count)
1939 auto const n = std::size_t(count);
1940 m_entries.reserve(n);
1941 m_weightScratch.reserve(n);
1946 assertIndex([[maybe_unused]]
Index i)
const
1948 EMRYS_FILTER_ASSERT(i >= 0 && i <
size() &&
"component index out of range");
1952 [[nodiscard]]
Entry &
1955 return m_entries[std::size_t(i)];
1959 [[nodiscard]]
Entry const &
1962 return m_entries[std::size_t(i)];
1966 [[nodiscard]]
Entry &
1970 m_stamp.touchValues();
1978 if (i !=
size() - 1)
1980 at(i) = std::move(m_entries.back());
1982 m_entries.pop_back();
1983 m_lineage.removeAt(i);
1993 template <
typename Rule>
1994 [[nodiscard]] std::expected<Scalar, WeightError>
1995 pruneWith(Rule
const & rule)
2000 return std::unexpected{total.error()};
2002 m_stamp.touchShape();
2006 return at(i).logWeight;
2012 return cut.removes(at(i).logWeight);
2016 return removed - *total;
2023 template <
typename RemoveAtIndex>
2025 compact(RemoveAtIndex removeAtIndex)
2027 auto removed = LogSumExp<Scalar>{};
2031 if (removeAtIndex(i))
2033 removed.add(at(i).logWeight);
2038 at(out) = std::move(at(i));
2039 m_lineage.moveRow(i, out);
2043 m_entries.erase(m_entries.begin() + out, m_entries.end());
2044 m_lineage.truncate(out);
2045 return removed.value();
2048 internal::Buffer<Entry, Allocator_> m_entries;
2050 std::optional<Index> m_capacity;
2053 internal::Buffer<Scalar, Allocator_> m_weightScratch;
2058 mutable Scalar m_logTotalWeight{};
2060 internal::Stamp m_stamp;
2071template <Space Space_, RealScalar Scalar_ =
double,
typename Allocator_ = DefaultAllocator>
2088template <
internal::ComponentOrInfoForm Component_,
typename Allocator_ = DefaultAllocator>
2097 using Entry =
typename ParamsType::Entry;
2124 return source().size();
2131 return source().valueDimension();
2138 return source().differenceDimension();
2145 return source().space();
2152 return source().get_allocator();
2159 return source().begin();
2166 return source().end();
2170 [[nodiscard]]
typename ParamsType::Entry
const &
2180 return source().m_logTotalWeight;
2200 return source().mostProbable();
2214 return (*
this)[i].component;
2217 return (*
this)[i].logWeight;
2244 template <
typename Derived>
2248 static_assert(Derived::IsVectorAtCompileTime,
"logDensity() expects a vector");
2251 for (
auto const & entry : *
this)
2253 if (entry.logWeight == -Eigen::NumTraits<Scalar>::infinity())
2268 template <
typename Derived>
2270 density(Eigen::MatrixBase<Derived>
const & x)
const
2276 template <
typename Path>
2280 return internal::tagMarginal<MixtureMarginal, Path>(*
this);
2284 template <
typename Path>
2288 return internal::elementMarginal<MixtureMarginal, Path>(*
this, element);
2292 template <
typename GivenPath,
typename Derived>
2297 return internal::tagConditionalMixture<GivenPath>(*
this, values);
2315 return m_check.get();
2318 internal::ValuesCheck<ParamsType> m_check;
2329template <Space Space_, RealScalar Scalar_ =
double,
typename Allocator_ = DefaultAllocator>
2340template <
typename Source>
2346template <Component Component_,
typename Allocator_>
2350 template <
typename Source>
2351 [[nodiscard]]
static auto
2352 logWeight(Source
const & source, Eigen::Index i)
2354 return source[i].logWeight;
2358 template <
typename Source>
2359 [[nodiscard]]
static auto const &
2360 component(Source
const & source, Eigen::Index i)
2362 return source[i].component;
2366 template <
typename ComponentParams>
2372 template <
typename Source,
typename Marginal>
2373 [[nodiscard]]
static auto
2374 copy(Source
const &, Marginal
const & marginal, Allocator_
const & allocator)
2376 auto result = CopyType<typename Marginal::ComponentMarginalType::ParamsType>{marginal.space(), allocator};
2377 result.
reserve(marginal.size());
2378 for (
auto const & element : marginal)
2380 result.add(element.logWeight, element.component.copy());
2387template <Component Component_,
typename Allocator_>
2388struct ElementsOf<
Mixture<Component_, Allocator_>> : ElementsOf<MixtureParams<Component_, Allocator_>>
2421template <
typename Source,
typename Selection,
typename SubSpace>
2447 using ResolvedType =
typename internal::SelectionHolder<Source, Selection, SubSpace>::ResolvedType;
2457 ComponentType>::template MarginalType<internal::SharedSelection<ResolvedType>, SubSpace>;
2472 typename internal::ElementsOf<Source>::template CopyType<typename ComponentMarginalType::ParamsType>;
2476 requires(!internal::isSharedSelection<Selection>)
2478 , m_selection{source, selection, std::move(
space)}
2483 requires(internal::isSharedSelection<Selection>)
2485 , m_selection{shared}
2489 [[nodiscard]] SubSpace
const &
2492 return m_selection.get().space;
2499 return source().get_allocator();
2506 return source().size();
2527 return m_selection.get().indices;
2534 return m_selection.get().differenceIndices;
2538 [[nodiscard]] Element
2541 EMRYS_FILTER_ASSERT(i >= 0 && i <
size() &&
"component index out of range");
2542 Source
const & from = source();
2544 Elements::logWeight(from, i),
2546 Elements::component(from, i),
2547 internal::SharedSelection<ResolvedType>{&m_selection.get()}
2580 return Elements::copy(source(), *
this, allocator);
2585 using Elements = internal::ElementsOf<Source>;
2588 [[nodiscard]] Source
const &
2591 return m_holder.get();
2594 internal::HolderFor<Source> m_holder;
2595 internal::SelectionHolder<Source, Selection, SubSpace> m_selection;
2615 std::uniform_random_bit_generator G,
2623 R
const & resampler = {}
2626 EMRYS_FILTER_ASSERT(n >= 0);
2628 auto weights = internal::bufferOf<Scalar>(mixture.get_allocator());
2629 weights.reserve(std::size_t(mixture.size()));
2630 for (
auto const & entry : mixture)
2632 weights.push_back(Eigen::numext::exp(entry.logWeight - mixture.logTotalWeight()));
2634 auto ancestors = internal::bufferOf<Eigen::Index>(mixture.get_allocator());
2635 ancestors.resize(std::size_t(n));
2636 resampler(std::span<Scalar const>{weights}, std::span<Eigen::Index>{ancestors}, rng);
2639 Normals
const noise = internal::standardNormal<Normals>(mixture.differenceDimension(), n, rng);
2640 auto samples = SampleSetType{mixture.valueDimension(), n};
2641 for (Eigen::Index j = 0; j < n; ++j)
2643 auto const gaussian = mixture[ancestors[std::size_t(j)]].component.toDensity();
2647 internal::multiply(internal::asTriangular<Eigen::Lower>(gaussian->llt().matrixLLT()), noise.col(j))
2659template <
typename Scalar,
typename Space,
typename Allocator, std::uniform_random_bit_generator G>
2663 Eigen::Index
const picked = internal::drawIndex<Scalar>(
2665 [&](Eigen::Index k) {
2666 return Eigen::numext::exp(Scalar(mixture[k].logWeight - mixture.logTotalWeight()));
2670 auto const gaussian = mixture[picked].component.toDensity();
2688 std::uniform_random_bit_generator G,
2689 typename R = resamplers::Multinomial>
2690 requires Resampler<R, Scalar, G>
2691[[nodiscard]] SamplesWithLogDensity<Space, Scalar>
2696 R
const & resampler = {}
2712 std::uniform_random_bit_generator G,
2721 R
const & resampler = {}
2724 auto result = SamplesWithLogDensity<Space, Scalar>{
drawSamples(mixture, n, rng, resampler), {}};
2725 result.logDensity.resize(n);
2726 internal::forEachIndex(std::forward<P>(policy), n, [&](Eigen::Index j) {
2727 result.logDensity(j) = mixture.logDensity(result.samples.col(j));
2737template <
typename Scalar,
typename Space,
typename Allocator, std::uniform_random_bit_generator G>
2742 result.
logDensity = mixture.logDensity(result.sample);
2748#ifndef EMRYS_FILTER_NO_IO
2760template <
typename Component_,
typename Allocator_>
2762describe(std::ostream & stream, MixtureParams<Component_, Allocator_>
const & mixture, Indent indent)
2765 stream << indent <<
"mixture of ";
2766 printCount(stream, mixture.size(),
"component");
2767 printDimension(stream, mixture.valueDimension(), mixture.differenceDimension());
2768 auto const logTotal = mixture.logTotalWeight();
2774 return mixture[i].component;
2776 [&](Eigen::Index i) {
2777 return mixture[i].logWeight;
2780 printMoments(stream, indent.deeper(), ComponentTraits<
Params<Component_>>::moments(collapsed));
2785 describe(stream, logTotal.error(), indent.deeper());
2788 for (
auto const & entry : mixture)
2790 stream <<
'\n' << indent.deeper() <<
"component " << i <<
", ";
2793 stream <<
"weight " << Eigen::numext::exp(Scalar(entry.logWeight - *logTotal));
2797 stream <<
"log-weight " << entry.logWeight;
2800 describe(stream, entry.component, indent.deeper().deeper());
The allocator conventions of decisions.md [allocation]: DefaultAllocator, Capacity,...
What a container of several Gaussians needs of each one (decisions.md [component-first]): the Compone...
Spaces built from other spaces (decisions.md [sizes-and-dimensions], [several-resizable-blocks]): Com...
Execution policies (decisions.md [execution-policies]): execution::sequential, the ExecutionPolicy co...
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 resamplers: function objects that draw ancestors in proportion to weights, which ParticleSet::res...
SampleSet: a matrix whose columns are samples in a space, which the samplers return and the unscented...
Drawing samples: SamplesWithLogDensity and SampleWithLogDensity, the Gaussian draws drawSamples(),...
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,...
Weighted statistics over points, all in internal, which the containers of weighted elements (Gaussian...
Subspaces, and growing and shrinking blocks (decisions.md [several-resizable-blocks]).
Log-weights: the WeightError a normalization can fail with (NumericError.h), and the streaming log-su...
The density of a Gaussian whose covariance has been factorized: a read-only view.
Definition Gaussian.h:1011
Streaming log-sum-exp: accumulates without overflow.
Definition Weights.h:46
Scalar value() const
Definition Weights.h:133
How each component of a Mixture descends from the components it had at its last startLineage(): each ...
Definition Mixture.h:127
MixtureLineage(MixtureLineage const &other, Allocator_ const &allocator)
Copies other into storage from allocator.
Definition Mixture.h:147
Scalar_ Scalar
the scalar type
Definition Mixture.h:130
std::span< Scalar const > logShares(Index i) const
Definition Mixture.h:207
Index count() const
Definition Mixture.h:186
Allocator_ allocator_type
the allocator the shares come from
Definition Mixture.h:131
MixtureLineage(MixtureLineage const &other)
Copies the record into storage from other's allocator (see Allocation).
Definition Mixture.h:142
void carry(Eigen::MatrixBase< Parents > const &parents, Eigen::MatrixBase< Children > &children, Scalar orphan=0) const
Carries a value per parent to the components, as a statistic kept per hypothesis follows them through...
Definition Mixture.h:230
MixtureLineage(MixtureLineage &&other)=default
Takes other's record.
Eigen::Index Index
Eigen's index type.
Definition Mixture.h:132
Scalar logShare(Index i, Index parent) const
Definition Mixture.h:215
MixtureLineage(MixtureLineage &&other, Allocator_ const &allocator)
Moves other into storage from allocator, taking its storage when the allocators are equal.
Definition Mixture.h:159
MixtureLineage(Allocator_ const &allocator)
An empty record, with no mark, whose shares come from allocator.
Definition Mixture.h:137
MixtureLineage & operator=(MixtureLineage const &other)=default
Copies other's record into this one's storage.
Index size() const
Definition Mixture.h:200
Index parentCount() const
Definition Mixture.h:193
allocator_type get_allocator() const
Definition Mixture.h:177
friend class MixtureParams
Definition Mixture.h:261
MixtureLineage & operator=(MixtureLineage &&other)=default
Takes other's record, as std::vector's move assignment does.
Read-only view of a subset of the coordinates of every component of a mixture or a hybrid,...
Definition Mixture.h:2423
typename Type::Scalar Scalar
Definition Mixture.h:2426
typename internal::ElementsOf< Type >::template CopyType< typename ComponentMarginalType::ParamsType > ParamsType
Definition Mixture.h:2471
const_iterator end() const
Definition Mixture.h:2561
Index differenceDimension() const
Definition Mixture.h:2518
Element value_type
Definition Mixture.h:2466
DifferenceIndexVectorType const & differenceIndices() const
Definition Mixture.h:2532
static constexpr int MaxDifferenceDimensionAtCompileTime
Definition Mixture.h:2439
const_iterator begin() const
Definition Mixture.h:2554
SubSpace const & space() const
Definition Mixture.h:2490
IndexVectorType const & indices() const
Definition Mixture.h:2525
typename Type::ComponentType ComponentType
Definition Mixture.h:2444
MixtureMarginal(Source const &source, Selection const &selection, SubSpace space)
Selects selection's coordinates, which form space.
Definition Mixture.h:2475
allocator_type get_allocator() const
Definition Mixture.h:2497
const_iterator iterator
Definition Mixture.h:2468
decltype(ResolvedType::indices) IndexVectorType
Definition Mixture.h:2450
ParamsType copy() const
Definition Mixture.h:2571
Element operator[](Index i) const
Definition Mixture.h:2539
typename Type::allocator_type allocator_type
Definition Mixture.h:2443
typename ComponentTraits< ComponentType >::template MarginalType< internal::SharedSelection< ResolvedType >, SubSpace > ComponentMarginalType
Definition Mixture.h:2456
static constexpr int MaxValueDimensionAtCompileTime
Definition Mixture.h:2433
decltype(ResolvedType::differenceIndices) DifferenceIndexVectorType
Definition Mixture.h:2453
typename internal::SelectionHolder< Type, Selection, SubSpace >::ResolvedType ResolvedType
Definition Mixture.h:2447
static constexpr int DifferenceDimensionAtCompileTime
Definition Mixture.h:2436
SubSpace SpaceType
Definition Mixture.h:2442
static constexpr int ValueDimensionAtCompileTime
Definition Mixture.h:2430
Eigen::Index Index
Definition Mixture.h:2427
internal::ElementIterator< MixtureMarginal > const_iterator
Definition Mixture.h:2467
MixtureMarginal(Source const &source, Selection shared)
Selects the coordinates of source that shared resolved, borrowing them.
Definition Mixture.h:2482
ParamsType copy(allocator_type const &allocator) const
copy() with storage from allocator.
Definition Mixture.h:2578
Index valueDimension() const
Definition Mixture.h:2511
Index size() const
Definition Mixture.h:2504
Writable access to one entry during forEach().
Definition Mixture.h:673
MatrixType const & covarianceLower() const
Definition Mixture.h:746
MomentsType const & moments() const
Definition Mixture.h:730
void setComponent(C &&component)
Replaces the entry's component with component, which must be in the mixture's space; see MixtureParam...
Definition Mixture.h:709
VectorType const & mean() const
Definition Mixture.h:738
Index index() const
Definition Mixture.h:691
Scalar logWeight() const
Definition Mixture.h:684
void setMean(Mean &&mean)
Sets the component's mean; see GaussianParams::setMean().
Definition Mixture.h:756
decltype(auto) updateComponent(F &&f)
Definition Mixture.h:723
MutableEntry(MutableEntry const &)=delete
lives only inside the callback
void setMoments(MomentsType moments)
Sets the component's mean and covariance to moments.
Definition Mixture.h:772
MutableEntry & operator=(MutableEntry const &)=delete
Lives only inside the callback.
void setCovariance(Cov &&cov)
Sets the component's covariance; see GaussianParams::setCovariance().
Definition Mixture.h:765
ComponentType const & component() const
Definition Mixture.h:698
A weighted sum of components of one type, all in one space.
Definition Mixture.h:579
Mixture< Component_, Allocator_ > DensityType
the view toDensity() returns
Definition Mixture.h:597
void setLogWeight(Index i, Scalar logWeight)
Definition Mixture.h:1242
Index differenceDimension() const
Definition Mixture.h:996
allocator_type get_allocator() const
Definition Mixture.h:950
void split(Index i, R &&children)
Definition Mixture.h:1488
Index add(Scalar logWeight, ComponentType component)
Definition Mixture.h:1165
MixtureLineage< Scalar, Allocator_ > LineageType
what lineage() returns
Definition Mixture.h:598
static constexpr int MaxValueDimensionAtCompileTime
Definition Mixture.h:604
void setCovariance(Index i, Cov &&cov)
Definition Mixture.h:1235
void reweight(P &&policy, F &&f)
Definition Mixture.h:1399
ComponentType merged(Index first, Index second) const
Definition Mixture.h:1433
MixtureParams(Index valueDimension, Allocator_ const &allocator={})
Definition Mixture.h:812
void setCapacity(Index capacity)
Reserves room for capacity components, and the scratch for that many, and makes holding more a precon...
Definition Mixture.h:980
std::expected< Scalar, WeightError > pruneTail(Scalar logFraction)
Definition Mixture.h:1574
void setComponent(Index i, ComponentType component)
Definition Mixture.h:1208
typename ComponentType::MomentsType MomentsType
a mean and covariance together
Definition Mixture.h:591
typename internal::Buffer< Entry, Allocator_ >::const_iterator const_iterator
iterates the entries
Definition Mixture.h:659
static constexpr int DifferenceDimensionAtCompileTime
Definition Mixture.h:607
std::expected< void, MixtureError > factorize() const
Definition Mixture.h:1662
void startLineage()
Definition Mixture.h:1130
void insert(Index element, Eigen::MatrixBase< MeanDerived > const &mean, Eigen::MatrixBase< CovDerived > const &cov)
Definition Mixture.h:1051
void toDensity() const &&=delete
std::expected< Scalar, WeightError > logTotalWeight() const
Definition Mixture.h:1269
Eigen::Index Index
Eigen's index type.
Definition Mixture.h:593
static constexpr int MaxDifferenceDimensionAtCompileTime
Definition Mixture.h:610
std::expected< DensityType, MixtureError > toDensity() const &
Definition Mixture.h:1692
std::expected< Scalar, WeightError > pruneBelow(Scalar logThreshold)
Definition Mixture.h:1558
Params< Component_ > ComponentType
a component
Definition Mixture.h:588
Index size() const
Definition Mixture.h:957
void append(MixtureParams const &other)
Definition Mixture.h:1343
void marginal(Index element) const &&=delete
std::conditional_t< ReturnRemovedWeight, std::expected< Scalar, WeightError >, void > RemovalResult
Result of removeIf(): the log of the removed fraction of the total weight, or nothing when ReturnRemo...
Definition Mixture.h:665
void swap(MixtureParams &other)
Definition Mixture.h:1103
MixtureParams(MixtureParams &&other, Allocator_ const &allocator)
Definition Mixture.h:879
auto marginal() const &
Definition Mixture.h:1603
typename ComponentType::SpaceType SpaceType
the components' space
Definition Mixture.h:589
static constexpr bool IsParams
Definition Mixture.h:612
void assign(R &&components)
Definition Mixture.h:1326
Index merge(Index keep, Index absorb)
Definition Mixture.h:1419
void reweight(F &&f)
Definition Mixture.h:1391
void toDensity(R const &) &&=delete
MixtureParams(SpaceType space, Capacity capacity, Allocator_ const &allocator={})
Definition Mixture.h:827
Entry const & operator[](Index i) const
Definition Mixture.h:1155
Index merge(Index keep, Index absorb, MomentsType moments)
Definition Mixture.h:1472
std::expected< void, MixtureError > factorize(R const &repair)
Definition Mixture.h:1681
MixtureParams(MixtureParams &&other) noexcept
Definition Mixture.h:866
typename ComponentType::Scalar Scalar
the scalar type
Definition Mixture.h:592
bool empty() const
Definition Mixture.h:964
void resizeComponents(Index n)
Definition Mixture.h:1013
void setMean(Index i, Mean &&mean)
Definition Mixture.h:1226
void marginal() const &&=delete
MixtureParams(Allocator_ const &allocator)
Definition Mixture.h:795
Index merge(Index keep, Index absorb, ComponentType component)
Definition Mixture.h:1458
void remove(Index i)
Definition Mixture.h:1199
LineageType const & lineage() const
Definition Mixture.h:1119
Index add(Scalar logWeight, MomentsType moments)
Definition Mixture.h:1177
void reserve(Index n)
Definition Mixture.h:1080
void forEach(P &&policy, F &&f)
Definition Mixture.h:1375
void setMoments(Index i, MomentsType moments)
Definition Mixture.h:1216
void insert(Index element, Eigen::MatrixBase< MeanDerived > const &mean, Eigen::MatrixBase< CovDerived > const &cov, Eigen::MatrixBase< CrossDerived > const &cross)
Definition Mixture.h:1032
typename MomentsType::DifferenceVectorType DifferenceVectorType
a difference
Definition Mixture.h:595
MixtureParams(MixtureParams const &other, Allocator_ const &allocator)
Definition Mixture.h:854
MixtureParams & operator=(MixtureParams &&other) noexcept
Definition Mixture.h:914
std::expected< void, WeightError > normalize()
Definition Mixture.h:1279
MixtureParams(MixtureParams const &other)
Definition Mixture.h:847
void forEach(F &&f)
Definition Mixture.h:1364
std::expected< Scalar, WeightError > ess() const
Definition Mixture.h:1298
std::expected< Scalar, WeightError > pruneToSize(Index maxSize)
Definition Mixture.h:1589
MixtureParams(SpaceType space, Index valueDimension, Allocator_ const &allocator={})
Definition Mixture.h:837
std::optional< Index > capacity() const
Definition Mixture.h:971
auto conditional(Eigen::MatrixBase< Derived > const &values) const
Definition Mixture.h:1642
Index mostProbable() const
Definition Mixture.h:1312
typename MomentsType::MatrixType MatrixType
a matrix over differences
Definition Mixture.h:596
const_iterator begin() const
Definition Mixture.h:1138
MixtureParams(Capacity capacity, Allocator_ const &allocator={})
Definition Mixture.h:804
void clear()
Definition Mixture.h:1090
Index valueDimension() const
Definition Mixture.h:989
SpaceType const & space() const
Definition Mixture.h:1003
void erase(Index element, Index count=1)
Definition Mixture.h:1068
MixtureParams(SpaceType space, Allocator_ const &allocator={})
Definition Mixture.h:820
std::expected< Scalar, WeightError > removeIf(Pred pred)
Definition Mixture.h:1540
void scaleWeight(Index i, Scalar logScale)
Definition Mixture.h:1249
const_iterator end() const
Definition Mixture.h:1145
Allocator_ allocator_type
the allocator, re-bound per buffer
Definition Mixture.h:590
MixtureParams & operator=(MixtureParams const &other)
Definition Mixture.h:894
Index add(Scalar logWeight, Mean &&mean, Cov &&cov)
Definition Mixture.h:1192
typename MomentsType::VectorType VectorType
a value, such as a mean
Definition Mixture.h:594
void removeIf(Pred pred)
Definition Mixture.h:1529
void scaleWeights(Scalar logScale)
Definition Mixture.h:1256
static constexpr int ValueDimensionAtCompileTime
Definition Mixture.h:601
The density of a Mixture whose components have been factorized: a read-only view.
Definition Mixture.h:2090
typename ParamsType::MatrixType MatrixType
Definition Mixture.h:2104
const_iterator end() const
Definition Mixture.h:2164
typename ParamsType::Scalar Scalar
Definition Mixture.h:2100
Scalar logTotalWeight() const
Definition Mixture.h:2178
Index mostProbable() const
Definition Mixture.h:2198
typename ParamsType::VectorType VectorType
Definition Mixture.h:2102
MomentsType moments() const
Definition Mixture.h:2232
typename ParamsType::Index Index
Definition Mixture.h:2101
allocator_type get_allocator() const
Definition Mixture.h:2150
Index size() const
Definition Mixture.h:2122
static constexpr int MaxValueDimensionAtCompileTime
Definition Mixture.h:2110
static constexpr bool IsParams
Definition Mixture.h:2118
Scalar density(Eigen::MatrixBase< Derived > const &x) const
Definition Mixture.h:2270
SpaceType const & space() const
Definition Mixture.h:2143
auto marginal(Index element) const
marginal() of one repetition of a repeated block; see GaussianParams::marginal(element).
Definition Mixture.h:2286
static constexpr int MaxDifferenceDimensionAtCompileTime
Definition Mixture.h:2116
Index differenceDimension() const
Definition Mixture.h:2136
typename ParamsType::Entry Entry
Definition Mixture.h:2097
static constexpr int DifferenceDimensionAtCompileTime
Definition Mixture.h:2113
auto conditional(Eigen::MatrixBase< Derived > const &values) const
Definition Mixture.h:2295
static constexpr int ValueDimensionAtCompileTime
Definition Mixture.h:2107
Index valueDimension() const
Definition Mixture.h:2129
ParamsType::Entry const & operator[](Index i) const
Definition Mixture.h:2171
Allocator_ allocator_type
Definition Mixture.h:2096
typename ParamsType::const_iterator const_iterator
Definition Mixture.h:2098
typename ParamsType::MomentsType MomentsType
Definition Mixture.h:2099
const_iterator begin() const
Definition Mixture.h:2157
ComponentType collapsed() const
Definition Mixture.h:2209
typename ParamsType::SpaceType SpaceType
Definition Mixture.h:2095
MixtureParams< Component_, Allocator_ > ParamsType
Definition Mixture.h:2093
Scalar logDensity(Eigen::MatrixBase< Derived > const &x) const
Definition Mixture.h:2246
Scalar ess() const
Definition Mixture.h:2187
Params< Component_ > ComponentType
Definition Mixture.h:2094
auto marginal() const
marginal() of the subspace named by the tag path Path; see MixtureParams::marginal().
Definition Mixture.h:2278
typename ParamsType::DifferenceVectorType DifferenceVectorType
Definition Mixture.h:2103
ValueVector< Space_, Scalar > VectorType
a value, such as the mean
Definition Moments.h:74
The distribution that a container of several holds one of per element (decisions.md [component-first]...
Definition Component.h:299
An execution policy: execution::sequential, a policy of the standard library such as std::execution::...
Definition Execution.h:459
A space whose instance holds nothing, so that S{} is the only one there is: a space of fixed size,...
Definition Space.h:217
Requirements on a resampler for scalar type Scalar and random generator G.
Definition Resampling.h:61
A type usable as the space of a distribution.
Definition Space.h:186
#define EMRYS_FILTER_NO_UNIQUE_ADDRESS
Assertion used for programmer errors (misuse of the API).
Definition Macros.h:38
bool isFinite(T const &x)
Definition Math.h:305
NumericError
Reasons a computation from parameters the caller gave can fail: a matrix that does not factorize or a...
Definition NumericError.h:30
@ NotPositiveDefinite
the covariance is not positive definite, so it has no Cholesky factor or inverse
Definition NumericError.h:31
Mixture< Gaussian< Space_, Scalar_ >, Allocator_ > GaussianMixture
The Mixture of a GaussianMixtureParams, the spelling for the common case (decisions....
Definition Mixture.h:2330
SampleWithLogDensity< Space, Scalar > drawSampleWithLogDensity(Gamma< Space, Scalar > const &gamma, G &rng)
Definition Gamma.h:546
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
MixtureParams< Gaussian< Space_, Scalar_ >, Allocator_ > GaussianMixtureParams
A Mixture of Gaussians in covariance form, the spelling for the common case (decisions....
Definition Mixture.h:2072
MixtureError GaussianMixtureError
MixtureError by the name it had when every mixture was a GaussianMixtureParams.
Definition Mixture.h:76
Eigen::Index drawSample(Categorical< Space, Scalar > const &distribution, G &rng)
Definition Categorical.h:1111
constexpr bool isGaussian
Whether C is a Gaussian in covariance form: the component for which a container offers the convenienc...
Definition Component.h:111
std::variant< WeightError, ComponentError > MixtureError
Reasons MixtureParams::toDensity() can fail.
Definition Mixture.h:71
std::vector< Eigen::Index > drawSamples(Categorical< Space, Scalar > const &distribution, Eigen::Index n, G &rng)
Definition Categorical.h:1087
SamplesWithLogDensity< Space, Scalar > drawSamplesWithLogDensity(Gamma< Space, Scalar > const &gamma, Eigen::Index n, G &rng)
Definition Gamma.h:529
typename ParamsOf< D >::type Params
The parameters of the density D: GaussianParams for a Gaussian, and D itself for a distribution whose...
Definition Params.h:42
constexpr Sequential sequential
The default execution policy: plain loops on the calling thread, in index order (Sequential).
Definition Execution.h:128
constexpr Keep keep()
Definition Reduction.h:371
GivenBlock< Space, P, Value > given(Space const &space, Value const &value)
Definition Measurement.h:917
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
Eigen::Index differenceDimension(S const &space)
Definition Space.h:284
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
The most elements a container will hold, reserved once: a mixture's components or a particle set's pa...
Definition Allocation.h:54
A mixture component that could not be factorized.
Definition Mixture.h:59
Eigen::Index index
position of the component in the mixture
Definition Mixture.h:60
NumericError error
why factorization failed: a Gaussian's covariance, or a Hybrid's mode weights
Definition Mixture.h:61
friend bool operator==(ComponentError const &, ComponentError const &)=default
Equal when the position and the error are.
What a container does with a component beyond the component's own members (decisions....
Definition Component.h:104
One component's log-weight, as in the source, and its marginal.
Definition Mixture.h:2461
Scalar logWeight
the component's log-weight
Definition Mixture.h:2462
ComponentMarginalType component
the component's marginal
Definition Mixture.h:2463
One weighted component.
Definition Mixture.h:619
Entry & operator=(Entry &&)=default
Moves the weight and the component.
Entry(Scalar weight, ComponentType held)
The component held with log-weight weight.
Definition Mixture.h:621
Entry & operator=(Entry const &)=default
Copies into the component's storage.
ComponentType component
the component, in the mixture's space
Definition Mixture.h:656
Entry(Entry &&other, A const &allocator)
Moves other with its component into storage from allocator.
Definition Mixture.h:637
Scalar logWeight
the log of the component's (unnormalized) weight
Definition Mixture.h:655
Entry(Entry const &other, A const &allocator)
Copies other with its component in storage from allocator.
Definition Mixture.h:629
Entry(Entry &&)=default
moves the weight and the component
Entry(Entry const &)=default
copies the weight and the component
One sample in Space, in a vector sized by the space, together with the log of the density it was draw...
Definition Sampling.h:50
Scalar logDensity
the log-density at sample
Definition Sampling.h:52
Samples in Space together with the log of the density they were drawn from, evaluated at each.
Definition Sampling.h:36
Draws each ancestor independently.
Definition Resampling.h:219