mixle.reason.modality module

Structured modality views for belief-centered cross-modal reasoning.

Each modality is represented as its own typed Mixle sub-model: a SequenceEncodableProbabilityDistribution that can be scored and sampled, with a declared symmetry group such as "translation", "permutation", or "none". A ModalityView keeps that structure visible until a receiver explicitly asks for a task-specific representation.

This module provides the view contract and ModalityGraph, which groups multiple named views for one entity. Cross-modal claims should be compared against an appropriate fixed-width baseline using measured accuracy and calibration, not assumed from representation shape alone.

class ModalityView(name, dist, symmetry_group='none', notes=<factory>)[source]

Bases: object

One modality as a typed structured belief: a real mixle distribution plus its symmetry group.

dist is any fitted SequenceEncodableProbabilityDistribution: for example a categorical model over labels, a Gaussian or Student-t model over measurements, a neural density over an embedding-shaped field, or a Bayesian network over a structured record. symmetry_group names the invariance the modality declares, such as "none", "translation", "permutation", or "rotation".

Parameters:
score(x)[source]

Return log p(x) under this modality’s structured belief.

Parameters:

x (Any)

Return type:

float

sample(n=1, *, seed=None)[source]

Draw from this modality’s own sampler.

Parameters:
Return type:

Any

seq_score(xs)[source]

Return vectorized log p(x) over a batch via the modality encoder.

Parameters:

xs (Any)

Return type:

Any

class ModalityGraph(views=<factory>)[source]

Bases: object

A named collection of ModalityView for one entity.

Belief walks hop across this joint representation. A receiver reads named modalities and their own scores rather than an implicit shared vector.

Parameters:

views (dict[str, ModalityView])

add(view, *, replace=False)[source]

Add a modality view and return the graph for chaining.

A modality identity is unique inside one graph. Assigning by name alone silently destroyed the previous view – its distribution AND its notes – so a second "sensor" belief changed every later joint score with no trace. A duplicate name is rejected unless replace=True makes the substitution explicit; the replaced view is returned to the caller’s own bookkeeping through __getitem__() before it is dropped.

Parameters:
  • view (ModalityView)

  • replace (bool)

Return type:

ModalityGraph

modalities()[source]

Return modality names in sorted order.

Return type:

list[str]

joint_score(observations)[source]

Return per-modality log p(x) for named observations.

Every observation must name a modality this graph actually holds. Filtering unknown names away meant a query mentioning "missing_sensor" was answered from a different evidence set than the caller supplied – silently, and indistinguishably from having scored it.

Raises:

KeyError – if any observation names a modality that is not in the graph.

Parameters:

observations (dict[str, Any])

Return type:

dict[str, float]