Monty. Frameworks. Models. EvidenceMatching. EvidenceSlopeTracker
(ExTbpMonty.Core v0.1.0)
Copy Markdown
View Source
The slope of each hypothesis's evidence over a sliding window.
Mirrors tbp/monty/frameworks/models/evidence_matching/evidence_slope_tracker.py.
A learning module uses it to drop hypotheses whose evidence is not merely low
but falling: a hypothesis that arrived late has not had time to prove
itself, so only ones older than min_age updates can be removed.
Slopes are per channel per step, so they stay comparable when the number of input channels active at a step changes. That is the whole reason the channel counts are buffered alongside the evidence: a step fed by three channels accumulates evidence three times as fast, and a slope that ignored it would make hypotheses look better simply because more sensors were on them.
The evidence is a ring of bytes shared by every hypothesis: evidence is
hypotheses * window_size f64, cursor names the slot the next update
overwrites — which is also the oldest value in every window — and a window in
order is cursor, cursor + 1, … wrap. Every hypothesis' window slides by one
slot on the same update, so recording a step writes one value per hypothesis
and moves the cursor; no window is rebuilt. Sliding ten-slot lists a step was
the single largest thing a matching step allocated.
An unfilled slot is a NaN — Monty's nil, which a flat window's slope of zero
must not be mistaken for — so a window cannot be read as floats directly, and
calculate_slopes/1 is a kernel over these bytes.
Summary
Types
evidence is hypotheses * window_size f64 in ring order, channels the
channel count at each window slot oldest first, and cursor the slot the next
update writes.
Functions
Adds hypotheses, each with an empty window and an age of zero.
The average per-channel slope of every hypothesis, or nil for one whose
window holds no two consecutive observations.
Forgets every hypothesis, keeping the window size and minimum age.
The age of every tracked hypothesis, in updates.
A tracker for window_size evidence points per hypothesis, allowing removal
once a hypothesis is min_age updates old.
Which hypotheses are old enough to be considered for removal.
Removes the hypotheses at the given indices, keeping the rest in order.
Which hypotheses to keep, given a slope threshold.
How many hypotheses are tracked.
Records this step's evidence and moves every window on by one slot.
Types
@type t() :: %Monty.Frameworks.Models.EvidenceMatching.EvidenceSlopeTracker{ ages: [non_neg_integer()], channels: [pos_integer()], cursor: non_neg_integer(), evidence: binary(), min_age: non_neg_integer(), window_size: pos_integer() }
evidence is hypotheses * window_size f64 in ring order, channels the
channel count at each window slot oldest first, and cursor the slot the next
update writes.
@type value() :: float() | nil
Functions
@spec add_hyp(t(), non_neg_integer()) :: t()
Adds hypotheses, each with an empty window and an age of zero.
A hypothesis that has never been updated is all padding: it has no slope, and
calculate_slopes/1 says so with nil rather than with zero.
The average per-channel slope of every hypothesis, or nil for one whose
window holds no two consecutive observations.
Each step's difference is divided by the number of channels that contributed at the later slot of the pair, then averaged over the window's valid steps.
Forgets every hypothesis, keeping the window size and minimum age.
@spec hyp_ages(t()) :: [non_neg_integer()]
The age of every tracked hypothesis, in updates.
A tracker for window_size evidence points per hypothesis, allowing removal
once a hypothesis is min_age updates old.
Which hypotheses are old enough to be considered for removal.
@spec remove_hyp(t(), [non_neg_integer()]) :: t()
Removes the hypotheses at the given indices, keeping the rest in order.
@spec select_hypotheses(t(), float()) :: Monty.Frameworks.Models.EvidenceMatching.EvidenceSlopeTracker.HypothesesSelection.t()
Which hypotheses to keep, given a slope threshold.
A hypothesis is kept when its slope is at least the threshold or when it is too young to remove: the second half is what stops a module from throwing away a hypothesis in the same step it was proposed.
@spec total_size(t()) :: non_neg_integer()
How many hypotheses are tracked.
@spec update(t(), [float()] | binary(), keyword()) :: {:ok, t()} | {:error, :wrong_number_of_values}
Records this step's evidence and moves every window on by one slot.
values is one evidence value per hypothesis — all of them, every step:
a hypothesis that skipped a step would have a slope over a different number of
steps from its neighbours, which is how slopes stop being comparable.
Returns {:error, :wrong_number_of_values} rather than raising, because the
caller is a learning module mid-episode: Monty raises ValueError, and the
reason is the same either way.