bayesmith.dispatch.classify
Source-derived signatures and contracts. See the reference index for coverage and conventions.
Module contract
Which latents an exact method applies to, and how they group. Affine groups are discovered from the primal computation with complementary latents kept symbolic. ``linear_in`` remains compatible input metadata, but neither its presence nor its absence decides membership. Structural proof, finite numerical checks, Gaussian eligibility and covariance movement remain separate evidence. **Nothing here samples, and nothing here is jittable.** Every guard it calls -- :func:`~bayesmith.exact.gaussian.check_gaussian`, :func:`~bayesmith.exact.linearity.check_linearity`, :func:`~bayesmith.exact.gls.check_prediction_dependence` -- runs on concrete values and raises, so this whole module runs once, at compile time, outside any trace. **Exceptions are discriminated by raise SITE, not by type.** :class:`~bayesmith.errors.NotGaussian` is a verdict about an ordinary model and is caught wherever it appears. :class:`~bayesmith.errors.StructureError` is caught at exactly one call site -- ``check_linearity``'s, where it means a false ``linear_in`` and the block falls to NUTS naming its members -- and is deliberately allowed through everywhere else, because from ``check_gaussian`` it means a node whose own ``log_prob`` contradicts the ``loc``/``scale`` read off it, and routing that to NUTS would hide a broken model behind an ordinary-looking fallback.
SIGMA_RTOL
Defined in bayesmith.dispatch.classify, line 63.
SIGMA_RTOL = 1e-08Classification
Defined in bayesmith.dispatch.classify, line 81.
class Classification
exact: tuple[str, ...]
nuts: tuple[str, ...]
method: str
reason: str
linearity: dict[int, dict[float, float]] | None
sigma_movement: float | None
sigma_needs_rebuild: bool
structure: dict | None = None
discovery: Any = NoneThe partition of one graph, and the evidence behind it.
Attributes:
exact: the single exact block, sorted. Empty if there is none.
nuts: every other latent, sorted.
method: ``"gcr"``, ``"gcr+snis"``, ``"gcr+mh"`` or ``"nuts"``.
reason: why -- named members on a refusal, so a user one declaration
away from an exact solve can see that from the plan.
linearity: ``check_linearity``'s per-at-point errors, or ``None``.
sigma_movement: the largest relative movement of sigma with the
block, or ``None`` if there is no block. Measured from TWO
anchors -- prior-scale probes around the prior centre, and the
block's own Wiener solution, which is where the data put the
posterior. See :func:`_sigma_movement` for why one of them is not
enough.
sigma_needs_rebuild: whether any observed node's scale has a latent
ANCESTOR outside the block, in which case ``noise_std`` must be
recomputed every sweep rather than hoisted. Distinct from
``sigma_movement``, which only sees movement with the BLOCK.block_at
Defined in bayesmith.dispatch.classify, line 120.
block_at(graph: Graph, names: tuple[str, ...], *, env: dict[str, Any] | None=None) -> dict[str, Any]``{outside latent: prior centre}`` -- where a block is built.
A block is affine *given* the latents outside it, so it has to be
anchored somewhere, and the prior's centre is the "before seeing
anything" point. Anchoring at zero instead is not equivalent and is not
merely a different starting guess: ``affine_only_at_zero``'s prediction is
affine exactly where its outside latent is zero, so a zero anchor accepts
at the caller's own at-point a model that the prior's centre refuses
there.partition
Defined in bayesmith.dispatch.classify, line 526.
partition(graph: Graph, *, key: jax.Array | None=None) -> ClassificationDerive the exact block and its method from the graph's structure.