You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat!: move CMA-ES distribution into CmaEsState (B8)
CMA-ES was the one solver parking its iterate — the search distribution
(m, σ, C, B/D, evolution paths) — on the solver struct, which forced its
canonical TolX test to be a hardcoded `terminate` hook that ignored its
state argument (routing around tenet 3) and contradicted the crate's own
articulated principle that working state lives in the state, not the
solver (see LbfgsState).
Introduce `CmaEsState<V, M, F>` (core/state/cma_es.rs): one shared state
for both CmaEs and BoundedCmaEs, holding the distribution plus the
population, with the bounded variant's adaptive-penalty bookkeeping
riding along as `Option<BoundPenalty>` (mirroring LbfgsState::work). No
bespoke trait — the new `CmaEsTolerance` criterion binds the concrete
state and fires `TerminationReason::CmaEsTolerance`.
Both solvers become configuration-only: `CmaEs::new(seed)` /
`BoundedCmaEs::new(seed)`, with mean/σ/stds on
`CmaEsState::new(mean, σ).with_stds(...)` and the old `with_tol_x`
replaced by the criterion. Derived constants + RNG are cached on the
solver.
Result semantics follow canonical CMA-ES: `param()`/`cost()` return the
distribution mean (xfavorite; the solver evaluates f(m) once per
generation), while `best_param()`/`best_cost()` return the best
evaluated sample (xbest) — an OptimizationResult surfaces both. The
PopulationState contract is relaxed so `param()` need not equal
candidates[0]; MaLsChCma's chain write-back reads best_param().
Updates the injection/chain consumers, lib re-exports, wasm bindings,
benches, the CMA test suite across all backends, and docs (AGENTS.md
observer-KV note, audit B8 marked resolved, solver-composition rule).
Verified: cargo test --workspace --all-features (699 pass), clippy
(all targets/features), doc build, wasm target, web build.
BREAKING CHANGE: CMA-ES public API changed. `CmaEs::new` /
`BoundedCmaEs::new` now take only `(seed)`; the initial mean and σ move
to `CmaEsState::new(mean, sigma)`, and the Executor state for both
solvers is now `CmaEsState<V, M>` instead of `BasicPopulationState<V>`.
`CmaEs::with_stds` / `with_tol_x` are removed — use
`CmaEsState::with_stds(...)` and the `CmaEsTolerance` termination
criterion. `OptimizationResult::param()` / `cost()` now return the
distribution mean (xfavorite), not the best sample; use `best_param()` /
`best_cost()` for the best evaluated point. Standalone CMA-ES no longer
self-terminates on TolX unless a `CmaEsTolerance` criterion is registered.
0 commit comments