# `Monty.Frameworks.Models.NoResetEvidenceMatching.NoResetEvidenceGraphLM`
[🔗](https://github.com/d-led/ex.tbp.monty/blob/v0.1.0/packages/ex_tbp_monty_core/lib/monty/frameworks/models/no_reset_evidence_matching/no_reset_evidence_graph_lm.ex#L1)

An evidence learning module that is never told an episode has ended.

Mirrors `frameworks/models/no_reset_evidence_matching.py::NoResetEvidenceGraphLM`,
the module an unsupervised-inference experiment runs: the object under the
sensor changes without any signal that it changed, so the module cannot be
reset between objects — it has to notice the change itself, from evidence
falling away. Its whole reason to exist is the comparison the ordinary module
makes at an episode boundary.

## What it changes

  * **It remembers where the sensor was**, itself. `EvidenceGraphLM` reads the
    buffer for that, and the model empties every module's buffer when the
    object changes (`NoResetEvidenceGraphMatching.reset/0`), so the buffer
    cannot be the memory here. Both are kept in step: `_add_displacements`
    writes the location to this module *and* to the buffer.
  * **"The agent has moved" means "this module has seen the sensor before"**,
    not "the buffer has an entry". On the first step after an object change the
    buffer is empty and the sensor has moved — the module must displace its
    hypotheses by the journey from the old object to the new one, which is
    exactly what the ordinary module does *not* do on its first step.
  * **A location-only step displaces the hypotheses** without touching
    evidence, from this module's own memory of the last place.
  * **The goal generator does not wait longer** between objects
    (`wait_growth_multiplier` 1): waiting is for a sensor that cannot find the
    object it is on, and here the object is simply replaced.
  * **It always updates hypotheses by burst sampling**, which is Monty's
    constructor: `kwargs["hypotheses_updater_class"]` is set whenever the
    attribute is missing *from the dict*, which is always, so a config cannot
    choose another updater for this class.

## Why a wrapper rather than inheritance

In Monty this is a subclass of `EvidenceGraphLM` that overrides four methods.
Elixir has no inheritance, so — the same decision `SurfacePolicyCurvatureInformed`
and `InformedPolicy` already carry (`docs/monty-differences.md` §2.9) — it is a
second struct holding an `EvidenceGraphLM` and answering the learning module's
callbacks by delegation, with the four overrides written out. The four are
`matching_step`, `exploratory_step`, `reset_stm` and the displacement helpers.

# `t`

```elixir
@type t() :: %Monty.Frameworks.Models.NoResetEvidenceMatching.NoResetEvidenceGraphLM{
  last_location: [float()] | nil,
  lm:
    Monty.Frameworks.Models.EvidenceMatching.LearningModule.EvidenceGraphLM.t()
}
```

The module Monty's unsupervised-inference experiments run: an evidence
learning module plus where the sensor was when it last reported.

`last_location` is `nil` until the module has seen a sensor percept, and is
the one thing a reset clears along with the rest of the short-term memory.

# `exploratory_step`

```elixir
@spec exploratory_step([Monty.Cmp.Message.t()], Monty.Context.t(), t()) ::
  {:ok, t()} | {:error, term()}
```

One exploratory step: buffer what was seen, move the hypotheses with the
sensor, test nothing.

# `from_config`

```elixir
@spec from_config(map(), keyword()) :: {:ok, t()} | {:error, term()}
```

The module a config's `_target_` names, built from it.

Two things about the config are this class's rather than the evidence
module's, and both are replaced before the evidence module reads it. The
target is this class — the config asked for it — while the module it wraps is
`EvidenceGraphLM`, which refuses to be built from a config naming anything
else. And the updater is forced to burst sampling, which is what Monty's
`__init__` does (`if not hasattr(kwargs, "hypotheses_updater_class")` asks a
dict whether it has an attribute: it never does), so the module's
`hypotheses_updater_args` are honoured and its choice of updater is not.

# `matching_step`

```elixir
@spec matching_step([Monty.Cmp.Message.t()], Monty.Context.t(), t()) ::
  {:ok, t()} | {:error, term()}
```

One matching step, and the difference from `EvidenceGraphLM`'s is one line.

Monty's override asks *this module* whether the agent has moved, and displaces
from *this module's* memory of where the sensor was; everything after that is
the evidence module's step, with the mixin's statistics in place of its own.

# `new`

```elixir
@spec new(Monty.Frameworks.Models.EvidenceMatching.LearningModule.EvidenceGraphLM.t()) ::
  t()
```

A no-reset module over the memory `EvidenceGraphLM.new/2` was given.

# `reset_stm`

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

Clears the short-term memory, remembering nothing of where the sensor was.

Monty's `reset_stm`: the evidence module's, plus this module's own field —
which is what makes the next step an unmoved one again.

---

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