chore(release): v0.11.0
Bump Cargo.toml to 0.11.0, pin the README install snippet to "0.11",
and add the 0.11.0 CHANGELOG section.
Release highlights:
- a full permutation crossover/mutation toolkit (OX, PMX, CX, ERX
crossovers; Inversion, Insertion, Scramble mutations);
- a micro-benchmark-guided performance pass over the combinatorial
operators and the Pareto/metrics machinery;
- a whole-program profiling campaign that cut the `compare`
workload's instruction count 357.06B -> 165.31B (-53.7%), all
bit-identical.
No public-API breaks — the release is purely additive.
This commit is contained in:
@@ -7,6 +7,92 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.11.0] — 2026-05-14
|
||||
|
||||
Theme: a full permutation-operator toolkit, plus two sweeping
|
||||
performance passes. The first is a micro-benchmark-guided pass over
|
||||
the combinatorial operators and the Pareto/metrics machinery; the
|
||||
second is a whole-program profiling campaign that roughly halved the
|
||||
instruction count of the `compare` example workload. Every
|
||||
performance change is bit-identical — verified against per-algorithm
|
||||
exact-output snapshot tests — so results are unchanged, only faster.
|
||||
|
||||
No public-API breaks. The release is purely additive: new permutation
|
||||
operators, plus internal-only performance work.
|
||||
|
||||
### Added
|
||||
|
||||
- A full permutation crossover/mutation toolkit in
|
||||
`heuropt::operators`, all re-exported from the prelude:
|
||||
`OrderCrossover` (OX), `PartiallyMappedCrossover` (PMX),
|
||||
`CycleCrossover` (CX), and `EdgeRecombinationCrossover` (ERX)
|
||||
crossovers, and `InversionMutation`, `InsertionMutation`, and
|
||||
`ScrambleMutation` mutations — joining the pre-existing
|
||||
`SwapMutation`. The mutations preserve both strict permutations and
|
||||
multisets.
|
||||
- Combinatorial problems in the `compare` example: a bi-objective
|
||||
ring TSP, a 3-objective FT06 job-shop schedule, and a bi-objective
|
||||
knapsack — plus standalone Ulysses16 TSP and FT06 JSS benchmark
|
||||
examples and a bi-objective TSP crossover-comparison demo.
|
||||
- Many-objective problems in the `compare` example: DTLZ at 4, 8, and
|
||||
10 objectives.
|
||||
- `benches/compare_profile.rs` — a gungraun/callgrind benchmark that
|
||||
profiles the entire `compare` workload as one unit; the harness
|
||||
behind this release's profiling campaign.
|
||||
- A permutation-toolkit and multi-objective-combinatorial cookbook
|
||||
chapter in the mdbook.
|
||||
|
||||
### Performance
|
||||
|
||||
All changes below are bit-identical — outputs are byte-for-byte
|
||||
unchanged, verified by the per-algorithm snapshot tests.
|
||||
|
||||
- **Whole-program profiling campaign.** Profiling the full `compare`
|
||||
workload under callgrind cut its instruction count from 357.06B to
|
||||
165.31B (−53.7%):
|
||||
- `pareto_compare` is now allocation-free — it no longer
|
||||
materializes two minimization-oriented `Vec<f64>`s per call. This
|
||||
alone was −38%, the single biggest win.
|
||||
- `pareto_front` precomputes its oriented buffers once and skips
|
||||
candidates already known to be dominated.
|
||||
- `ibea` pre-exponentiates its indicator matrix, turning the
|
||||
survival loop's `exp` sweep into plain additions.
|
||||
- `hype` reuses its per-Monte-Carlo-sample scratch buffer instead
|
||||
of reallocating it thousands of times per call.
|
||||
- `age_moea` scores only the splitting front rather than the whole
|
||||
combined population.
|
||||
- **Combinatorial-operator pass.** `CycleCrossover`,
|
||||
`PartiallyMappedCrossover`, and `OrderCrossover` are now O(n) via
|
||||
position-index tables; `EdgeRecombinationCrossover` removes edges
|
||||
in O(degree) per step.
|
||||
- **Pareto / metrics pass.** `non_dominated_sort` halves its
|
||||
dominance comparisons and reads from a flattened objective buffer;
|
||||
`crowding_distance` sorts without `Vec<Vec<f64>>` indirection;
|
||||
`hypervolume_nd` no longer re-sorts prefixes per slice.
|
||||
- **Algorithm hot paths.** `ant_colony_tsp` hoists `powf` out of its
|
||||
tour-building loop; `tpe` computes KDE bandwidths once per
|
||||
iteration instead of once per call; `bayesian_opt` reuses scratch
|
||||
buffers in the expected-improvement acquisition loop.
|
||||
|
||||
### Changed
|
||||
|
||||
- Documentation now recommends MOEA/D as the default multi- and
|
||||
many-objective algorithm, with disconnected-front and sequencing
|
||||
guidance corrected against fresh `compare` results.
|
||||
- The `compare` example's result tables are realigned and sorted,
|
||||
and its workload now lives in a reusable module shared with the
|
||||
profiling benchmark.
|
||||
|
||||
### Internal
|
||||
|
||||
- A large mutation-testing-driven test-hardening pass: per-algorithm
|
||||
exact-output snapshots and pinned helper-function tests across the
|
||||
whole algorithm catalog and operator set, raising the cargo-mutants
|
||||
catch rate from ~74% to ~85%. See `.cargo/mutants.toml` for the
|
||||
campaign notes and the residual equivalent-mutant categories.
|
||||
|
||||
[0.11.0]: https://github.com/swaits/heuropt/releases/tag/v0.11.0
|
||||
|
||||
## [0.10.0] — 2026-05-06
|
||||
|
||||
Theme: every algorithm now returns its **canonical name** as it
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "heuropt"
|
||||
version = "0.10.0"
|
||||
version = "0.11.0"
|
||||
edition = "2024"
|
||||
rust-version = "1.85"
|
||||
authors = ["Stephen Waits <steve@waits.net>"]
|
||||
|
||||
@@ -21,7 +21,7 @@ Docs: [user guide](https://swaits.github.io/heuropt/) · [API reference](https:/
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
heuropt = "0.10"
|
||||
heuropt = "0.11"
|
||||
|
||||
# Optional features:
|
||||
# - "serde": derive Serialize/Deserialize on the core data types.
|
||||
@@ -30,7 +30,7 @@ heuropt = "0.10"
|
||||
# - "async": AsyncProblem / AsyncPartialProblem traits and a
|
||||
# run_async(&problem, concurrency).await method on
|
||||
# every algorithm — for IO-bound evaluations.
|
||||
# heuropt = { version = "0.10", features = ["serde", "parallel", "async"] }
|
||||
# heuropt = { version = "0.11", features = ["serde", "parallel", "async"] }
|
||||
```
|
||||
|
||||
## Define a problem and run an optimizer
|
||||
|
||||
Reference in New Issue
Block a user