Commit Graph
4 Commits
Author SHA1 Message Date
swaits 3085359d01 test(async): parity sweep — run_async must match run with same seed
Phase 0.2 of the mutation-testing campaign. Adds a module gated on
#[cfg(feature = "async")] that, for every algorithm with a run_async,
asserts that the async runner produces the same result as the sync
runner given the same Config + seed + problem.

Before: nothing exercised run_async, so cargo mutants survived
'replace run_async body with OptimizationResult::new()' and every
comparison/arithmetic mutant inside the async loop for every
async-capable algorithm — about 25-30 algorithms * 5-10 mutants each.
After: every such mutant is killed because the parity test detects
any divergence in best.evaluation.objectives or pareto-front
objective tuples.

Coverage:
- Single-objective real (Sphere1D fixture): RandomSearch,
  HillClimber, OnePlusOneEs, SimulatedAnnealing, GA, PSO, DE, CmaEs,
  IpopCmaEs, sNES, TLBO, NelderMead, BayesianOpt, TPE.
- Multi-objective real (SchafferN1 fixture): NSGA-II/III, SPEA2,
  MOEA/D, MOPSO, IBEA, SMS-EMOA, HypE, PESA-II, ε-MOEA, AGE-MOEA,
  GrEA, KnEA, RVEA, PAES.
- Binary (OneMax): UMDA.
- Permutation (TinyTsp fixture): AntColonyTsp.
- Integer (AbsInt fixture): TabuSearch.
- Multi-fidelity (Sphere1DPartial fixture): Hyperband.

Run with: cargo test --features async --test algorithm_properties async_parity
2026-05-13 19:47:33 -06:00
swaits a773a1eaf6 test(algorithm_info): pin name/full_name/seed for every algorithm
Phase 0.1 of the mutation-testing campaign: a sweep test per algorithm
(33 total) asserting the exact strings returned by AlgorithmInfo::name()
and AlgorithmInfo::full_name() plus the seed propagated through
AlgorithmInfo::seed().

Before: cargo mutants survived dozens of mutants per algorithm replacing
the name/full_name return values with "" or "xyzzy", and the seed
return with None/Some(0)/Some(1). After: every such mutant is caught
by an exact-equality assertion.

NelderMead is deterministic and has no seed override (intentionally);
its test asserts seed() == None to pin the default-trait-impl behavior.
2026-05-13 19:43:17 -06:00
swaits 4a59041d1a style: apply rustfmt drift across the crate 2026-05-05 11:40:14 -06:00
swaits 8a8c32f125 test(proptest): massive property-test expansion for every algorithm and operator
Goes from 10 properties to 50+, organized into four files:

- tests/properties.rs (existing) — Pareto-utility invariants
- tests/algorithm_properties.rs (new) — every Optimizer impl gets:
  * determinism-with-seed property
  * no-panic-on-random-valid-input property
  * population-size-as-documented property where applicable
- tests/operator_properties.rs (new) — every Variation/Initializer/
  Repair impl gets the right size + in-bounds + no-panic properties
- tests/metric_properties.rs (new) — every metric gets monotonicity
  / non-negativity / dim-checking properties
- tests/numerical_stability.rs (new) — single-point populations,
  duplicate populations, near-zero bounds, very large bounds,
  algorithms-on-flat-fitness — none of which should panic.

Total: 226 unit tests + this much-larger property suite. Strategies
are factored into a small `prop_helpers` module shared across files
so the random-input generators stay consistent.
2026-05-05 11:01:36 -06:00