38template <
typename Space,
typename Scalar>
41 CategoricalPredictedJoint<Space, Scalar>
const & joint,
42 CategoricalParams<Space, Scalar>
const & smoothedNext
46 smoothedNext.logTotalWeight() &&
"the smoothed distribution at the step's end must have valid weights"
48 Scalar
const minusInfinity = -Eigen::NumTraits<Scalar>::infinity();
49 auto const logNext = logProbabilitiesOf(smoothedNext);
50 auto const logPredicted = logProbabilitiesOf(joint.predicted);
51 Scalar scale = minusInfinity;
52 for (Eigen::Index j = 0; j < logNext.size(); ++j)
54 if (logNext(j) != minusInfinity)
57 logPredicted(j) != minusInfinity &&
"a value the prediction rules out has smoothed probability"
59 scale = Eigen::numext::maxi(scale, Scalar(logNext(j) - logPredicted(j)));
69template <
typename Space,
typename Scalar>
72 CategoricalPredictedJoint<Space, Scalar>
const & joint,
73 CategoricalParams<Space, Scalar>
const & smoothedNext
76 EMRYS_FILTER_ASSERT(joint.filtered.space() == smoothedNext.space() &&
"the distributions are on different spaces");
77 Scalar
const minusInfinity = -Eigen::NumTraits<Scalar>::infinity();
78 Scalar
const scale = smoothingRatioScale(joint, smoothedNext);
79 auto const logNext = logProbabilitiesOf(smoothedNext);
80 auto const logPredicted = logProbabilitiesOf(joint.predicted);
82 ratios.resize(logNext.size());
83 for (Eigen::Index j = 0; j < logNext.size(); ++j)
86 logNext(j) == minusInfinity ? Scalar(0) : Eigen::numext::exp(Scalar(logNext(j) - logPredicted(j) - scale));
112template <
typename Space,
typename Scalar>
120 ArrayType
const ratios = internal::smoothingRatios(joint, smoothedNext);
121 ArrayType
const logSmoothed = internal::logProbabilitiesOf(joint.
filtered)
122 + internal::multiply(joint.
transitions, ratios.matrix()).array().log();
125 [[maybe_unused]]
auto const normalized = smoothed.
normalize();
126 EMRYS_FILTER_ASSERT(normalized &&
"no value smoothed at the step's end came from a value at its start");
143template <
typename Space,
typename Scalar>
151 ArrayType
const ratios = internal::smoothingRatios(joint, smoothedNext);
152 ArrayType
const filtered = internal::logProbabilitiesOf(joint.
filtered).exp();
154 filtered.matrix().asDiagonal() * joint.
transitions * ratios.matrix().asDiagonal();
155 posterior /= posterior.sum();
191template <DiscreteSpace Space_, RealScalar Scalar_ =
double,
typename Allocator_ = DefaultAllocator>
216 using StepAllocator = internal::ReBound<Allocator_, Step>;
217 using ListType = std::list<Step, StepAllocator>;
228 : m_steps(StepAllocator(allocator))
233 : m_steps(StepAllocator(allocator))
236 EMRYS_FILTER_ASSERT(
lag.steps > 0 &&
"a fixed-lag history keeps at least one step");
246 : m_steps(other.m_steps, StepAllocator(allocator))
257 : m_steps(std::move(other.m_steps), StepAllocator(allocator))
279 [[nodiscard]] std::optional<Index>
282 return m_lag > 0 ? std::optional<Index>{m_lag} : std::nullopt;
289 return Index(m_steps.size());
296 return m_steps.empty();
300 [[nodiscard]] Step
const &
303 EMRYS_FILTER_ASSERT(!
empty() &&
"the history is empty");
304 return m_steps.front();
308 [[nodiscard]] Step
const &
311 EMRYS_FILTER_ASSERT(!
empty() &&
"the history is empty");
312 return m_steps.back();
319 return m_steps.begin();
326 return m_steps.end();
335 if (m_lag > 0 &&
size() == m_lag)
337 m_steps.splice(m_steps.end(), m_steps, m_steps.begin());
338 Step & step = m_steps.back();
339 step.
joint = std::move(joint);
345 m_steps.push_back(
Step{std::move(joint), std::move(smoothed)});
357 for (
auto step = m_steps.rbegin(); step != m_steps.rend(); ++step)
359 step->smoothed =
smoothStep(step->joint, *next);
360 next = &step->smoothed;
385template <DiscreteSpace Space, RealScalar Scalar,
typename Allocator = DefaultAllocator>
389 internal::Buffer<Eigen::Index, Allocator>
values;
417template <
typename Space,
typename Scalar,
typename Allocator>
425 Scalar
const minusInfinity = -Eigen::NumTraits<Scalar>::infinity();
427 std::size_t
const steps = std::size_t(history.
size());
428 auto backPointers = internal::bufferOf<Eigen::Index>(history.
get_allocator());
429 backPointers.resize(steps * std::size_t(count));
432 auto next = ArrayType{};
435 for (
auto step = history.
begin(); step != history.
end(); ++step, ++k)
437 auto const following = std::next(step);
438 auto const filtered =
439 internal::logProbabilitiesOf(following == history.
end() ? latest : following->joint.filtered);
440 auto const predicted = internal::logProbabilitiesOf(step->joint.predicted);
441 for (Eigen::Index j = 0; j < count; ++j)
443 Scalar best = minusInfinity;
444 Eigen::Index from = 0;
445 for (Eigen::Index i = 0; i < count; ++i)
447 Scalar
const candidate = delta(i) + Eigen::numext::log(step->joint.transitions(i, j));
448 if (candidate > best)
454 backPointers[k * std::size_t(count) + std::size_t(j)] = from;
455 bool const reachable = best != minusInfinity && predicted(j) != minusInfinity;
456 next(j) = reachable ? Scalar(best + filtered(j) - predicted(j)) : minusInfinity;
465 result.
values.resize(steps + 1);
466 Eigen::Index value = 0;
467 result.logProbability = delta.maxCoeff(&value);
468 result.values[steps] = value;
469 for (std::size_t s = steps; s > 0; --s)
471 value = backPointers[(s - 1) * std::size_t(count) + std::size_t(value)];
472 result.values[s - 1] = value;
The allocator conventions of decisions.md [allocation]: DefaultAllocator, Capacity,...
The distribution over a discrete space (decisions.md [discrete-spaces], [params-and-density]): Catego...
Discrete spaces (decisions.md [discrete-spaces]): the DiscreteSpace concept; Finite,...
HiddenMarkovFilter (decisions.md [filters-and-recursions], [emissions], [update-outcomes]): a Categor...
Lag, the number of steps a fixed-lag history keeps, which every history of the Smoothers layer takes ...
The macros every header includes first.
Mathematical constants and scalar functions that work in every scalar type the library accepts,...
Products of fixed-size matrices by Eigen's fixed-size product at every size: multiply() is by Eigen'...
The Space concept and what every continuous space shares (decisions.md [sizes-and-dimensions]): the t...
Log-weights: the WeightError a normalization can fail with (NumericError.h), and the streaming log-su...
The record of a HiddenMarkovFilter's forward pass that a smoother runs backward over: one Categorical...
Definition CategoricalHistory.h:193
CategoricalHistory()=default
An empty history that keeps every step.
CategoricalHistory(CategoricalHistory const &other, Allocator_ const &allocator)
Copies other's steps into nodes from allocator.
Definition CategoricalHistory.h:245
CategoricalHistory(Allocator_ const &allocator)
An empty history that keeps every step, with nodes from allocator.
Definition CategoricalHistory.h:227
CategoricalParams< Space_, Scalar_ > CategoricalType
the smoothed distribution's type
Definition CategoricalHistory.h:198
void push(JointType joint)
Records joint as the newest step.
Definition CategoricalHistory.h:333
const_iterator begin() const
Definition CategoricalHistory.h:317
Allocator_ allocator_type
the allocator the steps come from
Definition CategoricalHistory.h:200
CategoricalHistory & operator=(CategoricalHistory const &other)=default
Copies other's steps and lag.
Index size() const
Definition CategoricalHistory.h:287
std::optional< Index > lag() const
Definition CategoricalHistory.h:280
CategoricalHistory(CategoricalHistory const &other)
Copies the steps into nodes from other's allocator (see Allocation).
Definition CategoricalHistory.h:240
bool empty() const
Definition CategoricalHistory.h:294
void clear()
Drops every step, keeping the lag.
Definition CategoricalHistory.h:366
CategoricalHistory(CategoricalHistory &&other)=default
Takes other's steps.
Step const & back() const
Definition CategoricalHistory.h:309
typename ListType::const_iterator const_iterator
iterates the steps, oldest first
Definition CategoricalHistory.h:221
CategoricalPredictedJoint< Space_, Scalar_ > JointType
what each step records
Definition CategoricalHistory.h:199
CategoricalHistory & operator=(CategoricalHistory &&other)=default
Takes other's steps and lag, as std::list's move assignment does.
Space_ SpaceType
the discrete space
Definition CategoricalHistory.h:197
void smooth(CategoricalType const &latest)
Fills every step's smoothed distribution by smoothStep(), from the newest back, given latest,...
Definition CategoricalHistory.h:354
CategoricalHistory(CategoricalHistory &&other, Allocator_ const &allocator)
Moves other's steps into nodes from allocator, taking its nodes when the allocators are equal.
Definition CategoricalHistory.h:256
allocator_type get_allocator() const
Definition CategoricalHistory.h:273
Step const & front() const
Definition CategoricalHistory.h:301
const_iterator end() const
Definition CategoricalHistory.h:324
Eigen::Index Index
Eigen's index type.
Definition CategoricalHistory.h:201
Scalar_ Scalar
the scalar type
Definition CategoricalHistory.h:196
CategoricalHistory(Lag lag, Allocator_ const &allocator={})
An empty history that keeps the newest lag steps, with nodes from allocator.
Definition CategoricalHistory.h:232
The parameters of a probability distribution over a discrete space: one weight per value.
Definition Categorical.h:257
Space_ const & space() const
Definition Categorical.h:330
Eigen::Index cardinality() const
Definition Categorical.h:337
std::expected< void, WeightError > normalize()
Shifts the log-weights so that the weights sum to one, or returns the WeightError that stops it,...
Definition Categorical.h:467
Eigen::Array< Scalar_, CardinalityAtCompileTime, 1, Eigen::ColMajor, MaxCardinalityAtCompileTime, 1 > ArrayType
One entry per value, in flat-index order.
Definition Categorical.h:268
ValueSequence< Space, Scalar, Allocator > mostProbableSequence(CategoricalHistory< Space, Scalar, Allocator > const &history, CategoricalParams< Space, Scalar > const &latest)
Definition CategoricalHistory.h:419
CategoricalPredictedJoint< Space, Scalar >::MatrixType transitionPosterior(CategoricalPredictedJoint< Space, Scalar > const &joint, CategoricalParams< Space, Scalar > const &smoothedNext)
Definition CategoricalHistory.h:145
CategoricalParams< Space, Scalar > smoothStep(CategoricalPredictedJoint< Space, Scalar > const &joint, CategoricalParams< Space, Scalar > const &smoothedNext)
Definition CategoricalHistory.h:114
One recorded prediction and its smoothed distribution.
Definition CategoricalHistory.h:205
CategoricalType smoothed
for the step's (joint.filtered), as of the last smooth(); a copy of joint.filtered until then
Definition CategoricalHistory.h:211
JointType joint
the prediction as predictJoint() returned it
Definition CategoricalHistory.h:206
One prediction of a HiddenMarkovFilter as a smoother needs it: the distribution the step started from...
Definition HiddenMarkovFilter.h:58
CategoricalParams< Space, Scalar > filtered
, the state before the step
Definition HiddenMarkovFilter.h:61
MatrixType transitions
, with predicted filtered
Definition HiddenMarkovFilter.h:63
typename MarkovChain< Space, Scalar >::MatrixType MatrixType
the transitions' type
Definition HiddenMarkovFilter.h:59
The number of steps a fixed-lag history keeps.
Definition Lag.h:17
The most probable sequence of values over a CategoricalHistory, and its posterior probability,...
Definition CategoricalHistory.h:387
internal::Buffer< Eigen::Index, Allocator > values
The flat index of each value, oldest first: one per step of the history, then the latest.
Definition CategoricalHistory.h:389
Scalar logProbability
, the sequence's posterior log-probability
Definition CategoricalHistory.h:392