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

The straightforward updater: accumulate evidence, start channels, displace.

Mirrors
`tbp/monty/frameworks/models/evidence_matching/hypotheses_updater.py::DefaultHypothesesUpdater`,
the updater Monty pairs with the plain displacer — no bursting. Every step it
brings any channel that has just started reporting into the hypothesis space,
then adds this observation's evidence to the hypotheses already there.

## Starting hypotheses

Two ways, chosen by whether the experiment seeds poses:

  * **informed** — each node's stored pose is aligned with what the sensor
    sees, once per direction the sensed pose allows. This is how Monty
    recognises an object turned any way: the alignment tells it which rotation
    would explain the observation.
  * **fixed** — every node is tried with each configured rotation, which is
    what a `uniform` experiment means.

All of them start with the evidence the first observation already gives them:
the feature evidence of the node they sit on. Nothing has been ruled out yet —
every node is a hypothesis — but a node whose colour and curvature look like
what the sensor just saw starts ahead of one that does not, which is what
Monty's first hypothesis space is worth.

## A channel that joins late

A sensor can start reporting after another channel has already accumulated
evidence. Its hypotheses enter with the *mean* of the evidence already there,
so a newcomer is not silently out of the running against hypotheses that have
had several steps to climb.

# `t`

```elixir
@type t() ::
  %Monty.Frameworks.Models.EvidenceMatching.HypothesesUpdater.DefaultHypothesesUpdater{
    displacer: term(),
    graph_memory: term(),
    initial_possible_poses: term(),
    initialised_channels: term(),
    scorer: term(),
    umbilical_num_poses: term()
  }
```

# `begin_step`

```elixir
@spec begin_step(t()) :: t()
```

Nothing to prepare: this updater keeps every hypothesis it has and spends no
step sampling new ones, so each step looks like every other.

# `displace_hypotheses`

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

Move every hypothesis by `displacement`, as its own orientation sees it.

# `end_step`

```elixir
@spec end_step(t()) :: t()
```

Nothing to wind down, for the same reason `begin_step/1` has nothing to set up.

# `new`

```elixir
@spec new(Monty.Frameworks.Models.GraphMatching.GraphMemory.t(), keyword()) :: t()
```

An updater over `memory`.

`:initial_possible_poses` is `:first_observation` for informed sampling, or a
list of 3×3 pose matrices for fixed poses.

# `reset`

```elixir
@spec reset(t()) :: t()
```

Forget which channels this episode has started.

# `update_evidence`

```elixir
@spec update_evidence(
  t(),
  Monty.Frameworks.Models.EvidenceMatching.Hypotheses.t(),
  %{optional(String.t()) =&gt; map()},
  String.t(),
  float()
) :: {t(), Monty.Frameworks.Models.EvidenceMatching.Hypotheses.t() | nil, map()}
```

Bring the hypothesis space up to date with this observation.

Starts the space on the first step, adds a channel that has just begun
reporting, and otherwise adds the observation's evidence to what is there.
Returns `nil` and no telemetry when no stored channel was observed.

---

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