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

Monty's model for evidence-graph matching:
`tbp/monty/frameworks/models/evidence_matching/model.py`.

In Monty this class is the base model with a graph memory whose learning
modules carry hypotheses and accumulate evidence for them; its `__init__`
builds the model out of the config's sensor modules, learning modules and the
connectivity between them, and the base class steps it.

Here the two halves are separated, which is the split this port makes
everywhere: *what* the model is — the sensor modules, the learning modules,
the matrices — is read from the config by `Monty.Studio.Setup.model_spec/2`,
and *running* it is the runtime's business (`Monty.Runtime.Model` registers the
modules, the step coordinator and the episode's random stream as processes).
This module is the name a run uses for that model, which is what makes the
class in a config the class a run actually starts.

What the model does rather than owns is here: `combine_votes/2`, the one piece
of `_combine_votes` that is arithmetic rather than message passing.
`Monty.Runtime.Step.State` routes votes and calls it.

A config that names a model this port has not written is not run through this
one: `Monty.Studio.Setup.model_class/1` answers what a config resolves to, and
says plainly when the answer is this port's own runtime instead.

# `vote`

```elixir
@type vote() ::
  nil
  | %{
      possible_states: %{optional(term()) =&gt; [Monty.Cmp.Message.t()]},
      sensed_pose_rel_body: [[float()]]
    }
```

What a learning module says when it is asked to vote.

`possible_states` holds the hypotheses that stood out above the module's vote
threshold, one list per object; `sensed_pose_rel_body` is the pose of the
sensor that fed it — the location, then its three pose vectors. `nil` is a
module with nothing to say this step.

# `child_spec`

```elixir
@spec child_spec(map()) :: Supervisor.child_spec()
```

The model as something a supervisor can start.

Monty's constructor builds the model; here it is `spec` — what the config
resolved to — and starting it is the runtime's.

# `combine_votes`

```elixir
@spec combine_votes(%{optional(term()) =&gt; vote()}, %{optional(term()) =&gt; [term()]}) ::
  %{
    optional(term()) =&gt; %{optional(term()) =&gt; [Monty.Cmp.Message.t()]}
  }
```

`EvidenceGraphModel._combine_votes`: what a module hears, in the frame of its
own sensor.

Two learning modules look at the object through different sensors, so a vote
for a place on it only means something once it has been moved between them:
*"if I am here, you should be there."* The displacement between the sending
and the receiving sensor moves the vote's location, and the rotation that
takes the sending sensor's pose vectors to the receiving one's turns the
vote's own pose — vote rotations are not read yet, in Monty either.

The answer is keyed by receiver, then by object, which is the shape
`EvidenceGraphLM.receive_votes/2` reads. A module that did not vote this step
hears nothing, and neither does one whose sources were all silent: a module
with no opinion of its own is not a place to put other modules' opinions.

# `fixme_set_ground_truth`

```elixir
@spec fixme_set_ground_truth(atom() | String.t(), map() | nil, keyword()) :: :ok
```

`MontyForGraphMatching.fixme_set_ground_truth`: what this episode is about.

The experiment is the only one that knows, and a module that is never told cannot
say whether it recognised anything — so this is part of the model's public
surface, not the experiment's private business.

Monty's own signature takes the world's `semantic_id_to_label` beside the
target, and both come from the same place: the world that chose the object also
numbered it. It is an option here rather than a second positional argument,
because a world without semantics has none to give.

# `set_experiment_mode`

```elixir
@spec set_experiment_mode(
  atom() | String.t(),
  Monty.Frameworks.Models.AbstractMontyClasses.LearningModule.mode()
) :: :ok
```

`MontyBase.set_experiment_mode`: whether this episode trains or evaluates.

The experiment knows — it runs training epochs or evaluation epochs — but what
an episode is working *towards* is the model's own business: an evaluation that
recognises its object ends, a training episode switches to exploring, and a
model that was told nothing does neither. Monty calls this on the model before
an epoch steps, so this port does too.

# `state`

```elixir
@spec state(atom() | String.t()) :: Monty.Runtime.Step.State.t()
```

The coordinator's state, which is where an episode's conclusion lives.

# `status`

```elixir
@spec status(atom() | String.t()) :: Monty.Experiment.RecognitionStrategy.model()
```

The four things a recognition policy may read off the model.

# `step`

```elixir
@spec step(atom() | String.t(), map(), map(), Monty.Context.t()) ::
  {:ok, [map()], map()}
```

One timestep: what the modules were given and what they made of it.

Monty's `Monty.step`, without the model having to be a value: the modules are
processes and the coordinator keeps the step count.

# `stop`

```elixir
@spec stop(atom() | String.t()) :: :ok | {:error, :not_found}
```

Stops the model's processes.

# `supervise`

```elixir
@spec supervise(atom() | String.t(), map(), [number()], [String.t()]) :: :ok
```

`MontySupervisedObjectPretrainingExperiment._pass_target_info_to_model`.

The modules the experiment names are told the object, the pose it was placed
with and where it stood; the others have their hypotheses dropped. What a
module does with that is the graph module's own business, so the model passes
it on rather than deciding it.

# `switch_to_exploratory_step`

```elixir
@spec switch_to_exploratory_step(atom() | String.t()) :: :ok
```

`Monty.switch_to_exploratory_step`: what a recognition policy can ask for.

# `time_out`

```elixir
@spec time_out(atom() | String.t()) :: :ok
```

`Monty.time_out_lms`: what a recognition policy can ask for instead of stopping.

# `update_ltm`

```elixir
@spec update_ltm(atom() | String.t()) :: :ok
```

`MontyBase.update_ltm`: write the episode into long-term memory.

The experiment calls it once per episode, after the episode has been logged
(`monty_experiment.py`, `post_episode`); each learning module decides whether
the episode it had is one to learn from.

---

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