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.
Adds proptest as a dev-dependency and a `tests/properties.rs`
integration suite that probes invariants on randomly generated
inputs:
Pareto invariants:
- `pareto_compare` is anti-symmetric: A→B is opposite of B→A for
Dominates / DominatedBy
- `pareto_compare` is reflexive on equal candidates (returns Equal)
- `pareto_front` output is internally non-dominated
- `non_dominated_sort` puts every member into exactly one front
- `crowding_distance` returns Vec same length as front; boundary
points are infinity for fronts of size ≥ 2 in any axis-sortable
configuration
Operator invariants:
- `SimulatedBinaryCrossover` returns 2 children of the right length,
all in bounds
- `PolynomialMutation` returns 1 child of the right length, in bounds
- `BoundedGaussianMutation` returns 1 child in bounds
- `ClampToBounds` repair always lands in bounds
- `ProjectToSimplex` repair always sums to total and is non-negative
Algorithm invariants:
- For any seed, `Optimizer::run` is deterministic across two calls
- Final population has the documented size for population-based
algorithms
These are the invariants the existing 226 fixed-input unit tests
collectively check; proptest gives us coverage on inputs they don't
cover individually.