Theme: documentation and project polish. No public-API changes; this
is the v0.5 release that elevates heuropt's docs/onboarding/governance
to bar-setting status.
Adds:
- mdbook user guide at docs/book/ with intro, getting-started,
defining-problems, choosing-an-algorithm, cookbook (7 recipes),
comparison vs other libraries, stability/SemVer, migration guides.
Deploys to https://swaits.github.io/heuropt/ via .github/workflows/
docs.yml.
- Runnable rustdoc examples on every algorithm (35 of them), all
exercised by cargo test --doc.
- Three real-world examples: portfolio.rs (multi-obj with budget
constraint), hyperparam_tuning.rs (BO + TPE), scheduling.rs
(permutation via SA + SwapMutation against Smith's-rule oracle).
- Governance: CONTRIBUTING.md, SECURITY.md, CODE_OF_CONDUCT.md
(adopting builderscode.org's Builder's Code of Conduct), GitHub
issue templates, PR template.
Polishes:
- README hero with badges + user-guide link.
- lib.rs crate-level docs.
- CHANGELOG entry for 0.5.0.
Bumps Cargo.toml to 0.5.0.
Hand-rolled symmetric-matrix eigendecomposition via the cyclic Jacobi
rotation method. Returns sorted (eigenvalue, eigenvector) pairs in
descending order. Pure f64 row-major `Vec<Vec<f64>>` interface so we
don't pull in nalgebra for one algorithm.
Lives in `src/internal/eigen.rs` (new module). Used by the upcoming
CMA-ES implementation to maintain the covariance matrix's
eigendecomposition each generation. Tested against the standard
2x2 case, the diagonal case, and a known 3x3 result.
Adds:
- README.md following spec §19.1 (what / install / define problem /
run NSGA-II / custom optimizer / current algorithms / design
philosophy).
- A short-but-runnable crate-level //! example in lib.rs for
`cargo doc` (spec §19.2).
Standard Schott spacing: for each front point compute the Manhattan
distance to its nearest neighbor on minimization-oriented objective
values; the spacing metric is the population standard deviation of
those nearest-neighbor distances.
Returns 0.0 for empty or single-point fronts (spec §14.1).
The reference baseline and the spec's recommended starting example. Per
iteration it asks the initializer for `batch_size` decisions, evaluates
each, and accumulates them. At the end it returns the full population
plus the Pareto front and (if single-objective) the best feasible
candidate. `generations` equals `iterations`; `evaluations` equals
`iterations * batch_size` (spec §12.1).
Includes a tiny single-objective sphere test problem under
`tests_support` that later algorithm tests will reuse.
`select_random` samples `count` decisions with replacement and clones
them out of the population (spec §10.1).
`tournament_select_single_objective` runs binary-or-larger tournaments
with the spec's tiebreak order: feasible beats infeasible, lower
violation among infeasibles, and direction-correct objective comparison
among feasibles. Panics if not exactly one objective (spec §10.2).
Selection helpers stay under `heuropt::selection` and are not part of
the prelude (spec §15).
`RealBounds` (Initializer<Vec<f64>>) samples each variable uniformly in
its inclusive (lo, hi) range; panics if any bound has lo > hi
(spec §11.1).
`GaussianMutation` (Variation<Vec<f64>>) clones the first parent and
adds Normal(0, sigma) noise to every element; panics on sigma <= 0.0;
does not enforce bounds in v1 (spec §11.2).
A single `use heuropt::prelude::*;` brings in the common user-facing
types and traits available so far. Subsequent commits add Pareto
helpers, operators, and algorithms to the same prelude as they land.
The three operator-level traits the algorithms consume, plus the single
trait users implement to add a new optimizer (`Optimizer<P>`). All take
`&mut Rng` directly rather than being generic over the RNG (spec §7.8).
Plain-data structs and the seeded Rng alias from spec §7. Each lives in
its own file under src/core/ with unit tests:
- Direction, Objective, ObjectiveSpace (with as_minimization negating
only Maximize axes)
- Evaluation (is_feasible == constraint_violation <= 0.0)
- Candidate<D>, Population<D> (concrete, public fields, From<Vec<...>>)
- OptimizationResult<D>
- type Rng = rand::rngs::StdRng + rng_from_seed, so no public trait is
generic over the RNG (spec §2.5)
All public types behind #[cfg_attr(feature = "serde", derive(...))] so
the optional feature wires up without changing the default surface.
Initial state from `cargo new --lib` plus the technical design spec at
docs/heuropt_tech_design_spec.md, which is the source of truth for the
crate's public API and v1 acceptance criteria.