Skip to content

Commit 8809168

Browse files
authored
feat(probability): add verified finite-table mutual information (#1300)
* refactor(checkers): let declarations own provider runtimes Compose declaration-owned clean-process runtimes with the latest batched checker-identity path. Existing checker families retain the legacy registry; new declarations may carry one unassigned provider runtime, and the composition root batches identity material across the full declaration set before authorization. * fix(checkers): defer declaration runtime measurement Store passive provider-runtime factories on exact replay declarations and realize each runtime once, at installation. Importing domain declarations no longer identifies or hashes checker source, while the existing installer and authorization boundary keep the same resolved runtime contract. * refactor(checkers): keep direct runtime migration compatibility Retain the existing direct provider_runtime constructor as a temporary compatibility seam while making provider_runtime_factory lazy and cached. Reject dual ownership and preserve pre-authorization invariants for both forms. * fix(checkers): type the lazy runtime accessor Declare the compatibility accessor's dynamic return as Any so mypy accepts the dataclass field interception while the public provider_runtime field retains its precise declared type. * feat(probability): add bounded native mutual information Rebuild the finite-table mutual-information port as one domain-owned commit on the corrected declaration-runtime base. Keep native Fraction semantics separate from canonical wire contracts, preflight bounded collections, recognize rational powers of composite bases, and independently replay large exact products without decimal-conversion limits. * test: include check-all in the primary help contract * fix declaration-owned checker runtime compatibility * bound mutual-information replay inputs and certificates * fix(checkers): satisfy static validation * fix(probability): harden mutual-information boundaries * fix(probability): bind mutual-information candidate support * fix(probability): keep import isolation in approved process suite * fix(probability): bound replay candidates by producer limits * fix(probability): enforce native input rational bounds
1 parent da58870 commit 8809168

13 files changed

Lines changed: 1708 additions & 8 deletions

File tree

src/jacobian/domains/probability/bundle.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
from jacobian.domains.probability.gaussian_inputs import (
1010
CanonicalGaussianPolynomialMomentRequest,
1111
)
12+
from jacobian.domains.probability.mutual_information import (
13+
MUTUAL_INFORMATION_CAPABILITY,
14+
)
1215
from jacobian.domains.probability.operations import FINITE_PROBABILITY_CAPABILITIES
1316
from jacobian.operations import DomainDiagnostics, DomainSemantics
1417
from jacobian.provider_runtime import PYTHON_FLINT_VERSION
@@ -34,12 +37,13 @@ def build_finite_probability_bundle() -> DomainBundle:
3437
schema_namespace="jacobian.validated-analysis",
3538
semantics=DomainSemantics(
3639
name="jacobian.probability",
37-
version="4",
40+
version="5",
3841
definition={
3942
"description": "bounded exact rational probability operations",
4043
"scope": (
4144
"raw moments, explicit event mass and conditioning, total "
42-
"pushforwards, independent finite convolutions, and one fixed-order "
45+
"pushforwards, independent finite convolutions, exact mutual "
46+
"information for bounded rational joint tables, one fixed-order "
4347
"moment of a sparse complex-rational polynomial in independent "
4448
"standard real Gaussian variables, and exact small-graph terminal "
4549
"connection reliability"
@@ -49,18 +53,22 @@ def build_finite_probability_bundle() -> DomainBundle:
4953
),
5054
provider_runtime=python_flint_probability_provider_runtime(),
5155
backend_version=f"python-flint-{PYTHON_FLINT_VERSION}",
52-
capabilities=tuple(
53-
_operation_with_canonical_gaussian_input(operation)
54-
for operation in FINITE_PROBABILITY_CAPABILITIES
56+
capabilities=(
57+
MUTUAL_INFORMATION_CAPABILITY,
58+
*(
59+
_operation_with_canonical_gaussian_input(operation)
60+
for operation in FINITE_PROBABILITY_CAPABILITIES
61+
),
5562
),
5663
diagnostics=DomainDiagnostics(
5764
invalid_request=CapabilityDiagnostic(
5865
code="INVALID_FINITE_PROBABILITY_REQUEST",
5966
stage="finite_probability_input_validation",
6067
message="Input does not satisfy the bounded exact-probability contract.",
6168
hint=(
62-
"Use a bounded normalized finite distribution or a bounded "
63-
"Gaussian polynomial request, or a fully weighted small graph."
69+
"Use a bounded normalized finite distribution or joint table, "
70+
"a bounded Gaussian polynomial request, or a fully weighted "
71+
"small graph."
6472
),
6573
)
6674
),

src/jacobian/domains/probability/checkers.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
"""Independent checker declarations owned by the probability domain."""
22

33
from jacobian.checker_operations import ExactReplayCheckerDeclaration
4-
from jacobian.contracts.capabilities import CapabilityProviderRuntime
4+
from jacobian.contracts.capabilities import (
5+
CapabilityInstallTier,
6+
CapabilityProviderRuntime,
7+
)
58
from jacobian.contracts.probability import (
69
FiniteConvolutionRequest,
710
FiniteEventRequest,
@@ -12,6 +15,10 @@
1215
from jacobian.domains.probability.gaussian_inputs import (
1316
CanonicalGaussianPolynomialMomentRequest,
1417
)
18+
from jacobian.domains.probability.mutual_information import (
19+
FiniteJointTableMutualInformationRequest,
20+
)
21+
from jacobian.provider_runtime import source_provider_runtime
1522
from jacobian.providers import flint_runtime
1623

1724
_ENTRYPOINT = "jacobian_checkers.exact_probability_operations"
@@ -21,6 +28,24 @@
2128
)
2229

2330

31+
def _mutual_information_checker_runtime(
32+
*, checker_ids: tuple[str, ...] = ()
33+
) -> CapabilityProviderRuntime:
34+
"""Measure the checker source only when authorization installs it."""
35+
36+
return source_provider_runtime(
37+
"jacobian.mutual-information-checker",
38+
version="1",
39+
entrypoint=(
40+
"jacobian_checkers.mutual_information:check_finite_joint_mutual_information"
41+
),
42+
install_tier=CapabilityInstallTier.T1,
43+
license_id="MIT",
44+
features=("standard-library-fraction-replay", "clean-process-checker"),
45+
checker_ids=checker_ids,
46+
)
47+
48+
2449
def _probability_runtime(
2550
*, checker_ids: tuple[str, ...] = ()
2651
) -> CapabilityProviderRuntime:
@@ -30,6 +55,33 @@ def _probability_runtime(
3055

3156

3257
PROBABILITY_EXACT_REPLAY_CHECKERS = (
58+
ExactReplayCheckerDeclaration(
59+
"probability.joint.mutual_information.compute",
60+
FiniteJointTableMutualInformationRequest,
61+
"check_finite_joint_mutual_information",
62+
"probability.finite-joint-mutual-information.fraction-replay",
63+
entrypoint_module="jacobian_checkers.mutual_information",
64+
replay_method="standard-library Fraction logarithmic-product replay",
65+
reason=(
66+
"operator-authorized standard-library Fraction checker independently "
67+
"reconstructs marginals, likelihood ratios, and the scaled log product"
68+
),
69+
provider_runtime_factory=_mutual_information_checker_runtime,
70+
verification_capability_id="probability.joint.mutual_information.verify",
71+
verification_title="Verify a finite-table mutual-information certificate",
72+
verification_description=(
73+
"Independently reconstruct ordered marginals, positive-support "
74+
"likelihood ratios, and the exact scaled logarithmic product for one "
75+
"bounded normalized rational joint table."
76+
),
77+
verification_tags=(
78+
"verification",
79+
"exact",
80+
"probability",
81+
"information-theory",
82+
"mutual-information",
83+
),
84+
),
3385
ExactReplayCheckerDeclaration(
3486
"probability.finite_distribution.raw_moment.compute",
3587
FiniteRawMomentRequest,

0 commit comments

Comments
 (0)