Skip to content

Inference-first 0.3.0: likelihoods as programs, optimizer mode, Pareto posterior, prior-owned encodings - #20

Merged
alexnodeland merged 2 commits into
mainfrom
feat/inference-first-0.3
Jul 28, 2026
Merged

Inference-first 0.3.0: likelihoods as programs, optimizer mode, Pareto posterior, prior-owned encodings#20
alexnodeland merged 2 commits into
mainfrom
feat/inference-first-0.3

Conversation

@alexnodeland

Copy link
Copy Markdown
Owner

Closes the three caveats left by the 0.2.0 refactor (#19), completing the identity: fugue-evo is an implementation of fugue for running evolutionary algorithms as Bayesian inference (plus a standalone classic EC toolkit). Follow-up to #18.

Fix A — likelihoods as programs

GenomeLikelihood<G> replaces "fitness" as the conditioning abstraction: an observation program p(data|g) that may contain per-datum observe statements, factors, and — the capability the scalar factor could never express — latent nuisance parameters jointly inferred with the genome. The black-box mode survives as the FactorFitness adapter, now explicitly labeled as the Gibbs/generalized-Bayes posterior. EvolutionModel::new(prior, fitness) is source-compatible; from_likelihood accepts any observation program.

Demonstrated where it matters: GaussianRegression with NoiseSpec::Infer puts the observation noise σ at a latent site inside the likelihood — test_symreg_infers_noise_jointly generates data with σ=0.3 and recovers it from the particle traces while simultaneously finding the generating program.

Fix B1 — optimizer mode

EvolutionSMC::anneal(β_max, steps) continues the tempering ladder past β=1, built entirely from fugue's exported primitives (incremental reweight → normalize → resample → π_β-invariant rejuvenation → optional crossover sweep). On the sphere benchmark it reaches within ~1e-4 of the optimum while still reporting population uncertainty and log-evidence (examples/optimize_by_inference.rs, head-to-head with SimpleGA). Single-objective optimization is no longer the classic layer's monopoly.

Fix B2 — multi-objective as inference

ParetoScalarization puts the scalarization weight inside the model (uniform-simplex stick-breaking Beta sites): the joint posterior's marginal over genomes traces the Pareto front, and particle_weights reads each particle's front position off its trace — a posterior over the front, with evidence, which NSGA-II cannot express. Validated analytically: biobjective f1=x², f2=(x−2)² with Pareto set exactly [0,2] — >90% of mass on the set, both ends covered, and particles sit near their own weight's scalarized optimum x*(w)=2(1−w). (Weighted-sum = convex fronts; Chebyshev is noted future work, same architecture. CMA-ES deliberately stays a baseline — it is not a posterior sampler.)

Fix C — prior-owned encodings + cost

GenomePrior::trace_of encodes a genome under the prior's address scheme (grammar prior overrides with the exact inverse of its generative walk — pinned by an inversion test and a hand-computed PCFG score). EvolutionModel::score/to_weighted_trace now work for grammar trees, and EvolutionChain::init_from warm-starts a chain from any in-support genome — including a classic GA/GP result. MemoizedFitness (exact-key, shared-cache) removes repeated evaluations under replay-heavy inference.

Fix B3 — identity

  • New classic feature (default on) gates algorithms/operators/population/hyperparameter/interactive/checkpoint/diagnostics/termination. MultiObjectiveFitness/ClosureMultiObjective moved to core fitness::multi_objective (re-exported from nsga2 for compat).
  • --no-default-features --features std,ppl builds the inference layer with no classic EC code; std,parallel,checkpoint,classic builds classic with no fugue. Both configs check clean with --all-targets.
  • Crate description and README now lead with the inference identity.

Validation

  • Default: 9/9 suites, 0 failures (49 inference-layer tests incl. the new noise-inference, anneal-concentration, Pareto-front, encoding-inversion, and memoization anchors).
  • Both minimal feature configs: zero errors, --all-targets.
  • clippy 0 warnings, fmt clean, wasm crate unchanged and green.
  • All prior anchors still green: EV-16 (+analytic evidence), EV-52, EV-90, EV-53, dead-chain, symreg recovery.

Version 0.2.0 → 0.3.0 (pre-1.0 breaking-minor: EvolutionModel generics; feature gating).

🤖 Generated with Claude Code

https://claude.ai/code/session_01HmWLBR9Zq6hPG5o7URDuNJ

…eto posterior, prior-owned encodings

Closes the three caveats left by the 0.2.0 refactor, completing the
"implementation of fugue for running evolutionary algorithms as Bayesian
inference" identity:

Fix A — likelihoods as programs (inference/likelihood.rs):
- GenomeLikelihood<G>: observation program p(data|g) with observes, factors,
  and latent nuisance parameters jointly inferred with the genome.
- tempered_observe helper; FactorFitness adapter (black-box mode = explicit
  Gibbs/generalized-Bayes posterior); NoLikelihood; MemoizedFitness
  (exact-key shared cache).
- EvolutionModel<P, L> generalization; new(prior, fitness) still works via
  FactorFitness; from_likelihood accepts any observation program.
- GaussianRegression with NoiseSpec::Infer: observation noise as a latent
  site, posterior read off particle traces (test recovers sigma=0.3).

Fix B1 — optimizer mode: EvolutionSMC::anneal continues the tempering
ladder past beta=1 (fugue primitives only: incremental reweight, normalize,
resample, rejuvenate, optional crossover sweep), concentrating on optima
with uncertainty attached. Head-to-head example vs SimpleGA.

Fix B2 — multi-objective as inference (inference/pareto.rs):
ParetoScalarization puts the scalarization weight inside the model
(uniform-simplex stick-breaking), so the posterior marginal traces the
Pareto front; particle_weights locates each particle on it. Analytic
biobjective validation (Pareto set [0,2], x*(w) = 2(1-w)).

Fix C — prior-owned encodings: GenomePrior::trace_of (grammar prior
overrides with the exact inverse of its generative walk; pinned by
inversion + hand-computed PCFG score tests); score/to_weighted_trace work
for grammar trees; EvolutionChain::init_from warm-starts from any genome.

Fix B3 — identity: `classic` feature gates the EC toolkit
(MultiObjectiveFitness moved to core fitness::multi_objective); std,ppl
builds inference standalone; std,parallel,checkpoint,classic builds classic
fugue-free; README/description lead with the inference identity.

All 9 suites green in default config; both minimal configs check clean;
clippy/fmt clean; wasm unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HmWLBR9Zq6hPG5o7URDuNJ
Copilot AI review requested due to automatic review settings July 28, 2026 14:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@alexnodeland
alexnodeland merged commit 0b052b2 into main Jul 28, 2026
7 checks passed
@alexnodeland
alexnodeland deleted the feat/inference-first-0.3 branch July 28, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants