mixle.inference.planning module

Estimation planning and evidence-backed certificates.

Planning and certification are deliberately different. Model structure can suggest an estimator and an upper bound on what it could prove, but a class name or capability marker cannot prove that a particular fit is identified, converged, or globally optimal. A certificate therefore reports both the candidate guarantee and the guarantee established by checked conditions or explicit verification receipts.

class Guarantee(*values)[source]

Bases: IntEnum

How strong the solution to an estimation block is, as an ordered ladder (higher = stronger).

property label: str

Return the enum name used in reports.

class ProofObligation(check, required_for, description)[source]

Bases: object

A condition that must be evidenced before a block may claim a guarantee.

Parameters:
  • check (str)

  • required_for (Guarantee)

  • description (str)

class VerificationReceipt(receipt_id, block, guarantee, checks, source, evidence, subject_hash='')[source]

Bases: object

Evidence that named checks were performed for one estimation block.

Receipts are explicit audit inputs, not Boolean assertions. evidence must contain the measurements or result metadata supporting the checks.

Parameters:
evidence_as_dict()[source]

Return the evidence as plain JSON-compatible data.

Return type:

dict[str, Any]

class BlockPlan(name, kind, method, guarantee, gradient, placement, reason, candidate_guarantee=None, proof_obligations=(), verified_checks=(), receipt_ids=(), verified_by='', unbound_receipt_ids=())[source]

Bases: object

One estimation block and the distinction between planned and verified strength.

Parameters:
  • name (str)

  • kind (str)

  • method (str)

  • guarantee (Guarantee)

  • gradient (bool)

  • placement (str)

  • reason (str)

  • candidate_guarantee (Guarantee | None)

  • proof_obligations (tuple[ProofObligation, ...])

  • verified_checks (tuple[str, ...])

  • receipt_ids (tuple[str, ...])

  • verified_by (str)

  • unbound_receipt_ids (tuple[str, ...])

class EstimationCertificate(guarantee, blocks=<factory>, escape_tested=False)[source]

Bases: object

The auditable proof of how a model was (or would be) estimated: per-block plans + the aggregate.

guarantee is the minimum over blocks. why_not_adam summarizes where gradient optimization was used and why those blocks could not use a stronger closed-form or convex route.

Parameters:
  • guarantee (Guarantee)

  • blocks (list[BlockPlan])

  • escape_tested (bool)

property gradient_blocks: list[BlockPlan]

Return blocks that require gradient optimization.

property closed_form_blocks: list[BlockPlan]

Return blocks with global or stronger guarantees.

as_dict()[source]

Return the certificate as JSON-compatible data.

Return type:

dict[str, Any]

why_not_adam()[source]

The audit: which blocks needed gradient descent and why – everything else got a stronger method.

Return type:

str

table()[source]

Render a human-readable block-level estimation table.

Return type:

str

class EstimationSchedule(passes=<factory>, latent=False)[source]

Bases: object

The block-coordinate schedule planner v2 produces (A3): ordered passes + the loop structure.

A fully-factorized model schedules one independent pass per block (no loop). A latent model schedules the EM loop explicitly: an E-step over the latent, then one M-step pass PER BLOCK per round – each M-step named with its own method, so the schedule shows exactly where the closed forms live inside the iteration (and which pass, if any, is the gradient block a pool would take).

Parameters:
  • passes (list[SchedulePass])

  • latent (bool)

property per_round: list[SchedulePass]

Return schedule passes repeated inside each latent-variable round.

property gradient_passes: list[SchedulePass]

Return schedule passes assigned to gradient optimization.

describe()[source]

Return a compact prose description of the estimation schedule.

Return type:

str

class SchedulePass(order, kind, block, method, placement, repeat)[source]

Bases: object

One pass of the estimation schedule: what runs, on which block, how, where, and how often.

Parameters:
certify(model, *, data=None, receipts=(), escape_tested=False, penalized=False)[source]

Return the EstimationCertificate for a fitted model (or distribution prototype).

Model structure supplies only a candidate guarantee. data is checked by verify_estimation_conditions(); additional optimizer evidence may be supplied as structured receipts. A bare escape_tested=True is rejected because a caller assertion is not verification evidence.

Pass penalized (a reason string, or True) when the fit optimized a penalized objective – soft constraints, conservation/PINN residual factors, potentials (E2). The optimum is then of the penalized surrogate, not the likelihood, so no block may claim more than STATIONARY however clean its own solver is: every stronger block is downgraded with the penalty named in its reason.

Parameters:
Return type:

EstimationCertificate

receipt_subject(model)[source]

Return the subject identifier a VerificationReceipt must carry to be about model.

A caller supplying optimizer evidence the library cannot produce itself – multi-start escape testing, a solver’s own convergence report – names the model it verified:

VerificationReceipt(..., subject_hash=receipt_subject(model))

Requiring this is the point (MXR-080-1877): before it, naming the right check strings was the whole test, so a receipt whose evidence read {"trust": "me"} upgraded an arbitrary GaussianDistribution(999, 1) to GLOBAL_UNIQUE. Binding does not make forgery impossible – anyone holding the model can compute this – but it means a receipt cannot be written without the model, cannot be reused against a different one, and stops applying the moment the parameters change. What a reader gains is in the certificate: BlockPlan.verified_by names who established each guarantee, so library-checked conditions no longer read identically to a caller’s assertion.

Parameters:

model (Any)

Return type:

str

verify_estimation_conditions(model, data)[source]

Check data-dependent proof obligations for supported analytic estimators.

Unsupported or iterative estimators produce no receipt rather than a guessed guarantee. The returned receipts can be passed to certify().

Parameters:
Return type:

list[VerificationReceipt]

plan_estimation(model)[source]

Return a pre-fit plan whose guarantees remain explicitly unverified.

Parameters:

model (Any)

Return type:

EstimationCertificate

schedule(model, *, escape_tested=False, receipts=())[source]

Plan the block-coordinate estimation schedule for model (planner v2, A3).

Built from the same block classification as certify(): EM blocks make the schedule a loop (E-step + per-block M-steps, repeated until convergence); without a latent block every block is one independent pass. Gradient blocks appear as explicit gradient passes with their pool placement, so the schedule is also the offload plan for the hybrid case.

receipts exists because escape_tested was otherwise unusable in both directions (MXR-080-1905). It forwards to certify(), which refuses escape_tested=True with “supply a VerificationReceipt” – and this function had no parameter through which to supply one, so the only non-default value raised an error naming a remedy the caller could not reach. Pass escape evidence here instead, bound to the model via receipt_subject() (MXR-080-1877).

Parameters:
  • model (Any)

  • escape_tested (bool)

  • receipts (Iterable[VerificationReceipt])

Return type:

EstimationSchedule