Skip to content

Gaia Bayes API

Status: Generated from current Python docstrings and type hints.

Hypothesis-data model comparison helpers, Bayes runtime actions, likelihood DSL verbs, and scipy-backed distribution literals.

gaia.engine.bayes

gaia.engine.bayes - hypothesis-data inference verbs.

The user-facing surface is two verbs plus Bayes runtime records:

  • :func:model - declare a predictive model for one hypothesis.
  • :func:compare - compare equal-positioned predictive models against data.
  • :class:PrecomputedLikelihoods - audit-bearing return type for external-solver wrappers (PyMC / Stan / NumPyro / ...). Always pair with the standard :func:gaia.engine.lang.compute decorator to record the wrapper's fn / code_hash provenance.

Distributions live at :mod:gaia.engine.lang (the same factories that back the quantity-with-predicate surface). The pydantic _BaseDistribution types at :mod:gaia.engine.bayes.distributions are internal scipy-backend implementations - they are not part of the authoring surface.

BayesInference dataclass

BayesInference(label: str | None = None, rationale: str = '', background: list[Knowledge] = list(), metadata: dict[str, Any] = dict(), warrants: list[Claim] = list())

Bases: Reasoning

Bayes-family reasoning record (marker base class).

Model dataclass

Model(label: str | None = None, rationale: str = '', background: list[Knowledge] = list(), metadata: dict[str, Any] = dict(), warrants: list[Claim] = list(), hypothesis: Claim | None = None, observable: Variable | None = None, distribution: Distribution | None = None, helper: Claim | None = None)

Bases: BayesInference

Predictive model: ties a hypothesis to a distribution over an observable.

ModelCompare dataclass

ModelCompare(label: str | None = None, rationale: str = '', background: list[Knowledge] = list(), metadata: dict[str, Any] = dict(), warrants: list[Claim] = list(), helper: Claim | None = None, models: tuple[Claim, ...] = (), data: tuple[Claim, ...] = (), exclusivity: str = 'exhaustive_pairwise_complement', precomputed: Any | None = None, log_likelihoods: dict[Claim, float] = dict())

Bases: BayesInference

Equal-positioned list of competing predictive models.

PrecomputedLikelihoods dataclass

PrecomputedLikelihoods(content: str | None = None, *, log_likelihoods: dict[Claim, float] | None = None, diagnostics: dict[str, Any] | None = None, solver: str = '', label: str | None = None, metadata: dict[str, Any] | None = None, **kwargs: Any)

Bases: Claim

Externally computed log-likelihoods packaged as a Claim.

Attributes:

log_likelihoods: Mapping from hypothesis :class:Claim (the original objects passed to :func:gaia.engine.bayes.model) to log P(data | H_i). Same key shape as the legacy compare(precomputed=...) dict. diagnostics: Solver-specific convergence and provenance fields. Opaque to Gaia; consumed by gaia audit rules and reviewers. Recommended keys: r_hat_max, ess_min, divergences, seed, model_spec_hash. solver: Free-form solver label, e.g. "pymc-nuts-4000" or "custom".

Initialise the precomputed-likelihoods Claim.

Source code in gaia/engine/bayes/runtime/precomputed.py
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
def __init__(
    self,
    content: str | None = None,
    *,
    log_likelihoods: dict[Claim, float] | None = None,
    diagnostics: dict[str, Any] | None = None,
    solver: str = "",
    label: str | None = None,
    metadata: dict[str, Any] | None = None,
    **kwargs: Any,
) -> None:
    """Initialise the precomputed-likelihoods Claim."""
    likelihoods = dict(log_likelihoods or {})
    if any(not isinstance(k, Claim) for k in likelihoods):
        raise TypeError(
            "PrecomputedLikelihoods(log_likelihoods=...) keys must be "
            "the original hypothesis Claim objects."
        )
    for key, value in likelihoods.items():
        if not isinstance(value, (int, float)) or isinstance(value, bool):
            raise TypeError(
                f"PrecomputedLikelihoods(log_likelihoods=...) value for "
                f"{key.label or key.content[:40]!r} must be a numeric "
                f"log-likelihood, got {type(value).__name__}: {value!r}."
            )
        float_value = float(value)
        # NaN is never a meaningful log-likelihood; +inf would later be
        # Cromwell-clamped to near-1 and silently dominate. -inf ("zero
        # likelihood under this hypothesis") is allowed; the comparison
        # lowering rejects the case where *all* hypotheses are -inf.
        if math.isnan(float_value):
            raise ValueError(
                "PrecomputedLikelihoods log-likelihood for "
                f"{key.label or key.content[:40]!r} is NaN. Fix the "
                "wrapper to record a real log-likelihood, not a missing "
                "sentinel."
            )
        if math.isinf(float_value) and float_value > 0:
            raise ValueError(
                "PrecomputedLikelihoods log-likelihood for "
                f"{key.label or key.content[:40]!r} is +inf. A finite "
                "log-likelihood is required; +inf would silently dominate "
                "the comparison."
            )

    resolved_content = content or _default_content(solver, len(likelihoods))
    merged_metadata = dict(metadata or {})
    merged_metadata.setdefault("kind", "precomputed_likelihoods")
    merged_metadata.setdefault("solver", solver)
    # Mirror diagnostics onto metadata so the IR / gaia build check / gaia
    # explain can introspect them without walking back to the runtime
    # PrecomputedLikelihoods instance. The dataclass-field
    # ``self.diagnostics`` remains the canonical runtime accessor; this
    # mirror is the IR-visible projection.
    merged_metadata.setdefault("diagnostics", dict(diagnostics or {}))

    super().__init__(
        content=resolved_content,
        metadata=merged_metadata,
        label=label,
        **kwargs,
    )
    self.log_likelihoods = {key: float(value) for key, value in likelihoods.items()}
    self.diagnostics = dict(diagnostics or {})
    self.solver = solver