# `Monty.Frameworks.Models.EvidenceMatching.LearningModule`
[🔗](https://github.com/d-led/ex.tbp.monty/blob/v0.1.0/packages/ex_tbp_monty_core/lib/monty/frameworks/models/evidence_matching/learning_module.ex#L1)

How much evidence a hypothesis needs before this step is worth spending on it.

Mirrors `tbp/monty/frameworks/models/evidence_matching/learning_module.py`,
whose module-level part is this one decision. The learning module itself is
`Monty.Frameworks.Models.EvidenceMatching.LearningModule.EvidenceGraphLM`.

## Why a threshold at all

A step compares the observation against every hypothesis of every object.
Most of them are hopeless, and testing them costs the same as testing the
good ones. So a hypothesis is only updated if its evidence is above a
threshold derived from the *best* hypothesis so far: near the top of the
field is where a step can still change the answer.

A hypothesis below the threshold is not deleted — it keeps exactly the
evidence it had. That matters: an object that looks wrong now can still be
right later, and Monty's later steps are what make burst sampling worth
anything.

## The settings

  * a **number** — a fixed threshold in evidence units, ignoring the field;
  * `"mean"` / `"median"` — the average or middle of all hypotheses' evidence;
  * `"all"` — the lowest evidence of the field, i.e. update everything. This
    is Monty's default and what the experiments run;
  * `"[n]%"` — the best hypothesis minus `n` per cent of its evidence, so
    "within 5% of the leader";
  * `"x_percent_threshold"` — the same rule using the learning module's
    `x_percent_threshold`, which is the setting Monty's configs actually set.

The last two are one rule with two spellings, so both parse to
`{:percent_of_max, percentage}`; the pairing of `"x_percent_threshold"` with
the module's `x_percent_threshold` happens once, when the config is parsed.

# `config`

```elixir
@type config() :: number() | :mean | :median | :all | {:percent_of_max, float()}
```

A threshold setting, parsed: the forms above, with the two percentage
spellings already resolved to one.

# `evidence_update_threshold`

```elixir
@spec evidence_update_threshold(
  config(),
  number(),
  [number()] | Monty.Frameworks.Models.EvidenceMatching.Hypotheses.t()
) :: float() | nil
```

The evidence a hypothesis must reach to be updated this step.

With no evidence at all there is nothing to compare against, so the threshold
is zero and every hypothesis — there are none — passes it. That case is the
first step of an episode for every object in memory.

The column arrives as the numbers it holds or as the hypothesis set that keeps
them. The setting the experiments run — `"all"` — needs only the lowest of
them, and a step asks once per graph, so the set is answered from its bytes:
decoding six thousand floats to take their minimum was the largest single
Elixir cost in a ten-object step.

# `parse_config`

```elixir
@spec parse_config(term(), number()) ::
  {:ok, config()}
  | {:error,
     Monty.Frameworks.Models.EvidenceMatching.LearningModule.InvalidEvidenceThresholdConfig.t()}
```

Reads a threshold setting, resolving `"x_percent_threshold"` against the
learning module's own `x_percent_threshold`.

Parsed once when the learning module is built, because a setting is
configuration: if it is wrong, the experiment should not start.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
