Monty.Frameworks.Models.NoResetEvidenceMatching.NoResetEvidenceGraphLM (ExTbpMonty.Core v0.1.0)

Copy Markdown View Source

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.

Summary

Types

t()

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

Functions

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

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

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

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

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

Types

t()

@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.

Functions

exploratory_step(percepts, ctx, lm)

@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(config, options \\ [])

@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(percepts, ctx, lm)

@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(lm)

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

reset_stm(lm)

@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.