mixle.experimental.typed_runtime.local module

First executable typed local path: budgeted component-coordinate EM.

class TypedMixtureRoundReceipt(round_index, schedule, schedule_completion, coordinator_nodes, objective_before, candidate_objective, committed_objective, accepted, realized_gain, gain_attribution, active_components, invalidation, work)[source]

Bases: object

Selection, objective gate, invalidation, and work for one local round.

Parameters:
  • round_index (int)

  • schedule (ScheduleReceipt)

  • schedule_completion (ScheduleCompletionReceipt)

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

  • objective_before (float)

  • candidate_objective (float)

  • committed_objective (float)

  • accepted (bool)

  • realized_gain (float)

  • gain_attribution (str)

  • active_components (tuple[int, ...])

  • invalidation (InvalidationReceipt | None)

  • work (WorkMeasurement)

as_dict()[source]

Return a JSON-compatible execution receipt.

Return type:

dict[str, Any]

class TypedMixtureRun(model, graph, rounds)[source]

Bases: object

Final model and immutable evidence from a typed local mixture fit.

Parameters:
  • model (MixtureDistribution)

  • graph (UpdateGraph)

  • rounds (tuple[TypedMixtureRoundReceipt, ...])

property objective_trace: tuple[float, ...]

Committed observed-data objective after every round.

property total_model_evaluations: int

Total real component log-density calls across the fit.

as_dict()[source]

Return run metadata and receipts without serializing the model graph objects.

Return type:

dict[str, Any]

run_typed_mixture_em(enc_data, estimator, initial_model, *, max_its=10, delta=1.0e-9, stall_patience=3, accept_tolerance=1.0e-9, scheduler=None, gain_provider=None)[source]

Run objective-gated component EM selected by the typed scheduler.

The root mixture-weight update is an explicit always-on coordinator. Only component nodes enter the scheduler’s budget. Internal gain evidence comes from committed global-objective improvement and is therefore labelled joint_with_coordinator rather than misrepresented as an isolated causal contribution. A caller with better per-block probes may supply gain_provider; objective compatibility is still enforced by the scheduler.

Budgeting changes convergence dynamics, not only speed: leaving a component’s parameters fixed for one or more rounds makes this a different asynchronous coordinate-ascent process than full-tree EM, and on a non-convex mixture likelihood the two can settle at different fixed points – occasionally a meaningfully worse one – even though each trajectory is individually monotone in its own committed objective. This is not something a gentler scheduler fixes: the gap shrinks but does not vanish at every budget short of updating every component every round (see mixle/tests/typed_local_mixture_test.py’s LocalOptimumDivergenceRiskTestCase). A caller that needs the same fixed point full EM would reach should pass a scheduler with budget_fraction=1.0, or use mixle.inference.freeze_rollup instead, which reaches an identical fixed point by construction – it only skips a component once its own convergence has already been demonstrated, rather than rationing updates among components before any evidence exists.

Parameters:
  • enc_data (Any)

  • estimator (MixtureEstimator)

  • initial_model (MixtureDistribution)

  • max_its (int)

  • delta (float | None)

  • stall_patience (int)

  • accept_tolerance (float)

  • scheduler (GainPerCostScheduler | None)

  • gain_provider (Callable[[int, MixtureDistribution, UpdateGraph, tuple[TypedMixtureRoundReceipt, ...]], Mapping[str, GainEvidence]] | None)

Return type:

TypedMixtureRun