Monty. Frameworks. Models. EvidenceMatching. Hypotheses
(ExTbpMonty.Core v0.1.0)
Copy Markdown
View Source
A set of hypotheses: their evidence, the location each implies, the pose each implies, and whether each can still be possible.
Mirrors tbp/monty/frameworks/models/evidence_matching/hypotheses.py. The
four fields are parallel — an index is one hypothesis in all of them — which
is why Monty keeps them as separate arrays rather than a list of records: a
learning module selects, masks and weights whole columns of them with one
operation.
In Elixir possible is a list, one flag per hypothesis, and evidence,
locations and poses are the same rows as bytes: eight little-endian
f64 of evidence, then three of location and nine of rotation each, in the
order the hypothesis index names them. That is the form a step needs them in —
it displaces every hypothesis, blends what each earned into a column, then
asks the k-d index about every location and a kernel for the evidence at each
— so holding them this way stops a step from rebuilding a list, and eight or
three or nine boxed floats a hypothesis, once per pass. evidence/1,
evidence_at/2, locations/1, location/2, poses/1 and pose/2 read them
back, one hypothesis at a time where that is all a caller wants.
empty/0 is the identity for concatenate/1, which is what lets a learning
module build a step's hypotheses from however many sources voted.
Summary
Types
evidence is hypotheses f64, locations hypotheses * 3 f64 and poses
hypotheses * 9 f64, all in the hypothesis's own order; possible has one
entry each.
Functions
The index of the most likely hypothesis — the first of several equal maxima.
One set of hypotheses from several, in order.
How many hypotheses the set holds.
The hypotheses of nothing: the identity for concatenate/1.
Every hypothesis' evidence, as the numbers they are.
One hypothesis' evidence.
The evidence column as a step holds it: one f64 per hypothesis.
Indices as the u32 bytes a kernel reads them from.
Indices as Elixir values, read out of the u32 bytes a kernel answers with.
The indices of the hypotheses within percentage per cent of the best one.
One hypothesis' location.
The bytes of one location, as a step holds it.
Every hypothesis' location, as the three values each one is.
The locations in bytes, as values — the reference's way of reading them.
The highest evidence any hypothesis holds.
The lowest evidence any hypothesis holds — the threshold that updates them all.
One set of hypotheses from the rows of each, in order.
One hypothesis per node per pose — the shape a burst samples in.
One hypothesis' rotation.
The bytes of one rotation, row by row, as a step holds it.
Every hypothesis' rotation, as the matrix each one is.
The rotations in bytes, as values — the reference's way of reading them.
The same hypotheses with a new evidence column, given as numbers.
The same hypotheses with a new evidence column a kernel has written.
The rows of the hypotheses at indices, as the bytes a kernel reads.
The index of the runner-up hypothesis, or nil when there is no second one.
The hypotheses at the given indices, in the order asked for.
Types
@type location() :: [float()]
@type pose() :: [[float()]]
@type t() :: %Monty.Frameworks.Models.EvidenceMatching.Hypotheses{ evidence: binary(), locations: binary(), poses: binary(), possible: [boolean()] }
evidence is hypotheses f64, locations hypotheses * 3 f64 and poses
hypotheses * 9 f64, all in the hypothesis's own order; possible has one
entry each.
Functions
@spec argmax_evidence(t()) :: non_neg_integer()
The index of the most likely hypothesis — the first of several equal maxima.
Asked far more often than any other question of the column, so it is asked of the bytes: a kernel when they are loaded, and the same walk in Elixir otherwise.
One set of hypotheses from several, in order.
Monty concatenates along the hypothesis axis, so votes from two learning modules produce their votes first and the receiving module's hypotheses second, in the order the caller passes them.
@spec count(t()) :: non_neg_integer()
How many hypotheses the set holds.
@spec empty() :: t()
The hypotheses of nothing: the identity for concatenate/1.
Every hypothesis' evidence, as the numbers they are.
@spec evidence_at(t(), non_neg_integer()) :: float() | nil
One hypothesis' evidence.
The evidence column as a step holds it: one f64 per hypothesis.
What a kernel reads, where evidence/1 is what a reporter or an argmax wants.
@spec index_bytes([non_neg_integer()]) :: binary()
Indices as the u32 bytes a kernel reads them from.
@spec index_list(binary()) :: [non_neg_integer()]
Indices as Elixir values, read out of the u32 bytes a kernel answers with.
@spec indices_within(t(), float(), number()) :: [non_neg_integer()]
The indices of the hypotheses within percentage per cent of the best one.
Monty's get_possible_hypothesis_ids: np.where(evidence > max - max / 100 * x_percent_threshold), once the best clears floor. A learning module asks
once per object per step, so it is answered from the bytes.
Two edges are numpy's rather than Elixir's, and they are the reason the answer
is stated here: a column with a NaN in it has no best at all — np.max
propagates the NaN, every comparison against one is false — so nothing is
possible; and the band is strict, so a hypothesis exactly at the threshold is
out.
@spec location(t(), non_neg_integer()) :: location()
One hypothesis' location.
The bytes of one location, as a step holds it.
Every hypothesis' location, as the three values each one is.
The locations in bytes, as values — the reference's way of reading them.
The highest evidence any hypothesis holds.
The lowest evidence any hypothesis holds — the threshold that updates them all.
evidence_threshold_config: "all" asks this once per graph per step, and the
answer is one number: asked of the bytes, a minimum of six thousand of them no
longer costs six thousand decoded floats.
One set of hypotheses from the rows of each, in order.
The caller speaks in the shapes it has — evidence as a number, a location as
[x, y, z], a pose as three rows — and this is the one place those become the
bytes a step reads.
One hypothesis per node per pose — the shape a burst samples in.
locations and evidence name the chosen nodes once; poses holds one
matrix per hypothesis in that order, pose-major, which is what aligning each
sensed direction against the nodes produces. The node block is encoded once
and copied, where new/1 would encode the same few hundred nodes once per
sensed direction: a burst samples eight poses at each of a few hundred nodes,
ten graphs at a time, so that is tens of thousands of rows of the same values
every step.
@spec pose(t(), non_neg_integer()) :: pose()
One hypothesis' rotation.
The bytes of one rotation, row by row, as a step holds it.
Every hypothesis' rotation, as the matrix each one is.
The rotations in bytes, as values — the reference's way of reading them.
The same hypotheses with a new evidence column, given as numbers.
The same hypotheses with a new evidence column a kernel has written.
@spec rows_at(t(), [non_neg_integer()]) :: {binary(), binary()}
The rows of the hypotheses at indices, as the bytes a kernel reads.
What a step needs when it asks about a subset — the hypotheses worth testing this observation — without decoding them into values first.
@spec second_argmax_evidence(t()) :: non_neg_integer() | nil
The index of the runner-up hypothesis, or nil when there is no second one.
Monty reads it as argsort(evidence)[-2] to weigh a vote between the two best
hypotheses, and a step asks once per object. Asked of the bytes: the sort it
stands for needs every value decoded and a tuple for each.
@spec take(t(), [non_neg_integer()]) :: t()
The hypotheses at the given indices, in the order asked for.
Used by a learning module to keep the hypotheses it still considers possible without rebuilding four columns by hand. A kept row is copied out of the row it was already in, so this does not go back through the values themselves.