docs(0.9): release notes, cookbook recipe, README polish

Companion to the feat(explorer) commit. Bumps the version and
brings every cross-referencing doc up to v0.9 currency.

- Cargo.toml: version 0.8.0 -> 0.9.0.
- CHANGELOG: 0.9.0 entry covering the explorer export, the
  Problem-side metadata additions, the AlgorithmInfo trait, the
  pick_a_car example, and the new cookbook recipe.
- README: closing paragraph of the PickACar example points users
  at the explorer with a one-call snippet
  (`ExplorerExport::from_result(...).with_algorithm_info(...)
  .to_file(...)?`). Version snippets bumped 0.8 -> 0.9.
- New cookbook recipe at docs/book/src/cookbook/explorer.md
  covering: enabling the serde feature, enriching Problem with
  labels/units/decision-schema, the export call, the JSON schema,
  and custom decision-type handling.
- SUMMARY.md and cookbook.md link the new recipe.
- migration.md: new "To 0.9" section documenting the additive
  changes (purely backwards-compatible upgrade from 0.8.x).
- introduction.md, comparison.md, choosing-an-algorithm.md,
  stability.md: version refs bumped 0.8 -> 0.9.
- cookbook/parallel.md, cookbook/async.md: version refs bumped
  0.8 -> 0.9.
- getting-started.md: version refs bumped, serde feature
  description expanded to mention the explorer module.
- SECURITY.md: supported-versions table moves to 0.9.x.
This commit is contained in:
2026-05-06 22:45:59 -06:00
parent 729842c260
commit 6371d82f40
55 changed files with 721 additions and 354 deletions
+1
View File
@@ -18,6 +18,7 @@
- [Optimize a permutation (TSP-style)](./cookbook/permutation.md)
- [Constrain your search with `Repair`](./cookbook/constraints.md)
- [Pick one answer off a Pareto front](./cookbook/pick-one.md)
- [Explore your results in a webapp](./cookbook/explorer.md)
- [Write your own algorithm](./cookbook/custom-optimizer.md)
# Reference
+87 -87
View File
@@ -17,9 +17,9 @@ after it.
For the cheap-eval branch, you have the run of the catalog. For the
expensive branch, classical evolutionary methods waste your evaluation
budget — go to [`BayesianOpt`] or [`Tpe`]. For the *very* expensive
budget — go to [Bayesian Optimization][BayesianOpt] or [TPE]. For the *very* expensive
branch where each eval has a tunable budget (epochs, MC samples, sim
steps), [`Hyperband`] over the [`PartialProblem`] trait is the move.
steps), [Hyperband] over the [`PartialProblem`] trait is the move.
## Step 1: How many objectives?
@@ -51,48 +51,48 @@ These all take `Vec<f64>` decisions.
### Smooth, low-to-moderate dimension
[`CmaEs`] is the strong default. It adapts the search distribution's
[CMA-ES][CmaEs] is the strong default. It adapts the search distribution's
covariance to the local landscape. On the comparison harness it
hits machine epsilon on Rosenbrock at 30 000 evaluations.
For very low-dimensional smooth problems (≤ 5 dim), [`NelderMead`] is
For very low-dimensional smooth problems (≤ 5 dim), [Nelder-Mead][NelderMead] is
deterministic and converges to f = 0 exactly on Rosenbrock.
### High dimension, smooth
[`SeparableNes`] uses a diagonal covariance — cheaper per step than
CmaEs at the cost of being unable to model rotated landscapes. Worth
trying when CmaEs's `O(d²)` per-step cost hurts.
[sNES][SeparableNes] uses a diagonal covariance — cheaper per step than
CMA-ES at the cost of being unable to model rotated landscapes. Worth
trying when CMA-ES's `O(d²)` per-step cost hurts.
### Multimodal landscapes
Multimodal = many local minima that aren't the global one. Rastrigin
and Ackley are classic traps.
[`IpopCmaEs`] is CmaEs with an increasing-population restart strategy
specifically designed for this. On the harness it drops vanilla CmaEs's
[IPOP-CMA-ES][IpopCmaEs] is CMA-ES with an increasing-population restart strategy
specifically designed for this. On the harness it drops vanilla CMA-ES's
Rastrigin score from f = 2.35 to f = 0.13.
[`DifferentialEvolution`] is rarely beaten on cheap multimodal
[Differential Evolution][DifferentialEvolution] is rarely beaten on cheap multimodal
continuous problems. On Rastrigin it ties with `(1+1)-ES` at f = 0.
[`SimulatedAnnealing`] is a cheap, generic baseline that escapes local
[Simulated Annealing][SimulatedAnnealing] is a cheap, generic baseline that escapes local
optima via temperature decay.
### Want parameter-free
[`Tlbo`] (Teaching-Learning-Based Optimization) has no `F`, `CR`, `w`,
[TLBO][Tlbo] (Teaching-Learning-Based Optimization) has no `F`, `CR`, `w`,
or `σ` to tune. Often a respectable middle-of-the-pack performer.
### Smallest possible self-adapting baseline
[`OnePlusOneEs`] — Rechenberg's 1973 `(1+1)`-ES with the one-fifth
[(1+1)-ES][OnePlusOneEs] — Rechenberg's 1973 `(1+1)`-ES with the one-fifth
success rule. On the harness it hits f = 0 on Rastrigin in 50 000
evaluations.
### Just want a baseline
[`RandomSearch`]. Useful as a sanity check: if your fancy optimizer
[Random Search][RandomSearch]. Useful as a sanity check: if your fancy optimizer
can't beat random search, something is wrong (with the fancy
optimizer or with the problem).
@@ -100,69 +100,69 @@ optimizer or with the problem).
| Decision type | Algorithm | Notes |
|---|---|---|
| `Vec<bool>` | [`Umda`] | Per-bit marginal EDA. Independent-bit assumption. |
| `Vec<bool>` | [`GeneticAlgorithm`] + [`BitFlipMutation`] | When bit interactions matter. |
| `Vec<usize>` (permutation) | [`AntColonyTsp`] | TSP-style with a distance matrix. |
| `Vec<usize>` (permutation) | [`SimulatedAnnealing`] + [`SwapMutation`] | Generic discrete baseline. |
| `Vec<usize>` or custom | [`TabuSearch`] | You supply the neighbor function. |
| Custom struct | [`SimulatedAnnealing`] / [`HillClimber`] | With your own `Variation` impl. |
| `Vec<bool>` | [UMDA][Umda] | Per-bit marginal EDA. Independent-bit assumption. |
| `Vec<bool>` | [GA][GeneticAlgorithm] + [`BitFlipMutation`] | When bit interactions matter. |
| `Vec<usize>` (permutation) | [Ant Colony][AntColonyTsp] | TSP-style with a distance matrix. |
| `Vec<usize>` (permutation) | [Simulated Annealing][SimulatedAnnealing] + [`SwapMutation`] | Generic discrete baseline. |
| `Vec<usize>` or custom | [Tabu Search][TabuSearch] | You supply the neighbor function. |
| Custom struct | [Simulated Annealing][SimulatedAnnealing] / [Hill Climber][HillClimber] | With your own `Variation` impl. |
## Step 2 — multi-objective (2 or 3)
### Strong default
[`Nsga2`] is the canonical Pareto-based EA. Fast, well-understood,
[NSGA-II][Nsga2] is the canonical Pareto-based EA. Fast, well-understood,
maintains diversity via crowding distance. On the harness it lands
on the Pareto front of every test problem.
### Real-valued, smooth front, want best convergence
[`Mopso`] (multi-objective PSO with archive). On ZDT1 it wins
[MOPSO][Mopso] (multi-objective PSO with archive). On ZDT1 it wins
hypervolume outright and converges 100× tighter than the
dominance-based methods.
### Better front quality than NSGA-II
[`Ibea`] (indicator-based) is consistently the best of the
[IBEA][Ibea] (indicator-based) is consistently the best of the
dominance-based methods on the harness — wins ZDT3 hypervolume and
DTLZ2 mean distance by 24×. It uses an additive ε-indicator for
selection rather than dominance + crowding.
[`Spea2`] (strength + density) — solid alternative; explicit external
[SPEA2][Spea2] (strength + density) — solid alternative; explicit external
archive separate from the population.
[`SmsEmoa`] uses exact hypervolume contribution for selection. Elegant
[SMS-EMOA][SmsEmoa] uses exact hypervolume contribution for selection. Elegant
in theory; in practice on the harness budgets here it underperforms
NSGA-II. Worth the higher per-step cost only when exact HV
contribution is the right discriminator.
### Decomposition / weight-vector style
[`Moead`] decomposes the multi-objective problem into many scalar
[MOEA/D][Moead] decomposes the multi-objective problem into many scalar
sub-problems (Tchebycheff or weighted sum) and solves them in
parallel. Very fast per generation; scales naturally to many
objectives.
### Disconnected or non-convex front
[`AgeMoea`] estimates the front geometry adaptively (the L_p
[AGE-MOEA][AgeMoea] estimates the front geometry adaptively (the L_p
parameter `p` is fit from data each generation).
[`Knea`] favors knee points — the regions of the front where small
[KnEA][Knea] favors knee points — the regions of the front where small
gains in one objective cost large losses in another.
[`Ibea`] also handles disconnected fronts well.
[IBEA][Ibea] also handles disconnected fronts well.
### Region-based diversity
[`PesaII`] uses grid hyperboxes to drive selection — divide the
[PESA-II][PesaII] uses grid hyperboxes to drive selection — divide the
objective space into a grid, pick from the least-crowded boxes.
[`EpsilonMoea`] uses an ε-grid archive that auto-limits its size.
[ε-MOEA][EpsilonMoea] uses an ε-grid archive that auto-limits its size.
### Just one starting decision (no population budget)
[`Paes`] — `(1+1)`-ES with a Pareto archive. Cheap, simple, useful
[PAES][Paes] — `(1+1)`-ES with a Pareto archive. Cheap, simple, useful
when your evaluations are expensive enough that you can't afford a
population.
@@ -170,26 +170,26 @@ population.
### Linear / simplex-shaped front (e.g., DTLZ1)
[`Grea`] — grid coords drive ranking. On DTLZ1 it beats NSGA-III by
[GrEA][Grea] — grid coords drive ranking. On DTLZ1 it beats NSGA-III by
3× and AGE-MOEA by 2.5×.
[`Moead`] — decomposition shines on linear fronts; second on DTLZ1
[MOEA/D][Moead] — decomposition shines on linear fronts; second on DTLZ1
and among the fastest per generation.
### Curved / unknown front geometry
[`Nsga3`] — reference-point niching; canonical many-objective method;
[NSGA-III][Nsga3] — reference-point niching; canonical many-objective method;
strong default when the front isn't simplex-shaped.
[`AgeMoea`] — estimates L_p geometry per generation.
[AGE-MOEA][AgeMoea] — estimates L_p geometry per generation.
[`Rvea`] — reference vectors with adaptive penalty.
[RVEA][Rvea] — reference vectors with adaptive penalty.
### Indicator-based selection
[`Ibea`] — additive ε-indicator; doesn't degrade at high obj count.
[IBEA][Ibea] — additive ε-indicator; doesn't degrade at high obj count.
[`HypE`] — Monte Carlo hypervolume estimation; scales to arbitrary
[HypE][Hype] — Monte Carlo hypervolume estimation; scales to arbitrary
objective count where exact HV is too expensive.
## Step 3: Are there hard constraints?
@@ -216,13 +216,13 @@ for worked examples.
## Step 4: Should you parallelize?
Enable the `parallel` feature flag if your `evaluate` takes more
than ~50 µs. Population-based algorithms ([`RandomSearch`], [`Nsga2`],
[`DifferentialEvolution`], [`Spea2`], [`Ibea`], [`Mopso`], …) batch-
than ~50 µs. Population-based algorithms ([Random Search][RandomSearch], [NSGA-II][Nsga2],
[Differential Evolution][DifferentialEvolution], [SPEA2][Spea2], [IBEA][Ibea], [MOPSO][Mopso], …) batch-
evaluate via rayon when the feature is on. **Seeded runs stay
bit-identical** to serial mode.
```toml
heuropt = { version = "0.8", features = ["parallel"] }
heuropt = { version = "0.10", features = ["parallel"] }
```
If your evaluation is **IO-bound** (HTTP request, RPC, subprocess)
@@ -235,55 +235,55 @@ method on every algorithm in the catalog. See the
| Situation | Pick |
|---|---|
| Smooth single-objective continuous | [`CmaEs`] |
| Multimodal single-objective continuous | [`IpopCmaEs`] or [`DifferentialEvolution`] |
| Expensive single-objective | [`BayesianOpt`] or [`Tpe`] |
| Multi-fidelity single-objective | [`Hyperband`] |
| 2- or 3-objective default | [`Nsga2`] |
| 2-objective real-valued smooth front | [`Mopso`] |
| Disconnected / non-convex front | [`Ibea`] |
| Many-objective default (curved front) | [`Nsga3`] |
| Many-objective linear / simplex front | [`Grea`] |
| Permutation problem | [`AntColonyTsp`] |
| Binary problem | [`Umda`] |
| Custom decision type | [`SimulatedAnnealing`] + your `Variation` |
| Sanity baseline | [`RandomSearch`] |
| Smooth single-objective continuous | [CMA-ES][CmaEs] |
| Multimodal single-objective continuous | [IPOP-CMA-ES][IpopCmaEs] or [Differential Evolution][DifferentialEvolution] |
| Expensive single-objective | [Bayesian Optimization][BayesianOpt] or [TPE] |
| Multi-fidelity single-objective | [Hyperband] |
| 2- or 3-objective default | [NSGA-II][Nsga2] |
| 2-objective real-valued smooth front | [MOPSO][Mopso] |
| Disconnected / non-convex front | [IBEA][Ibea] |
| Many-objective default (curved front) | [NSGA-III][Nsga3] |
| Many-objective linear / simplex front | [GrEA][Grea] |
| Permutation problem | [Ant Colony][AntColonyTsp] |
| Binary problem | [UMDA][Umda] |
| Custom decision type | [Simulated Annealing][SimulatedAnnealing] + your `Variation` |
| Sanity baseline | [Random Search][RandomSearch] |
[`CmaEs`]: https://docs.rs/heuropt/latest/heuropt/algorithms/cma_es/struct.CmaEs.html
[`IpopCmaEs`]: https://docs.rs/heuropt/latest/heuropt/algorithms/ipop_cma_es/struct.IpopCmaEs.html
[`SeparableNes`]: https://docs.rs/heuropt/latest/heuropt/algorithms/snes/struct.SeparableNes.html
[`NelderMead`]: https://docs.rs/heuropt/latest/heuropt/algorithms/nelder_mead/struct.NelderMead.html
[`DifferentialEvolution`]: https://docs.rs/heuropt/latest/heuropt/algorithms/differential_evolution/struct.DifferentialEvolution.html
[`SimulatedAnnealing`]: https://docs.rs/heuropt/latest/heuropt/algorithms/simulated_annealing/struct.SimulatedAnnealing.html
[`Tlbo`]: https://docs.rs/heuropt/latest/heuropt/algorithms/tlbo/struct.Tlbo.html
[`OnePlusOneEs`]: https://docs.rs/heuropt/latest/heuropt/algorithms/one_plus_one_es/struct.OnePlusOneEs.html
[`RandomSearch`]: https://docs.rs/heuropt/latest/heuropt/algorithms/random_search/struct.RandomSearch.html
[`HillClimber`]: https://docs.rs/heuropt/latest/heuropt/algorithms/hill_climber/struct.HillClimber.html
[`BayesianOpt`]: https://docs.rs/heuropt/latest/heuropt/algorithms/bayesian_opt/struct.BayesianOpt.html
[`Tpe`]: https://docs.rs/heuropt/latest/heuropt/algorithms/tpe/struct.Tpe.html
[`Hyperband`]: https://docs.rs/heuropt/latest/heuropt/algorithms/hyperband/struct.Hyperband.html
[CmaEs]: https://docs.rs/heuropt/latest/heuropt/algorithms/cma_es/struct.CmaEs.html
[IpopCmaEs]: https://docs.rs/heuropt/latest/heuropt/algorithms/ipop_cma_es/struct.IpopCmaEs.html
[SeparableNes]: https://docs.rs/heuropt/latest/heuropt/algorithms/snes/struct.SeparableNes.html
[NelderMead]: https://docs.rs/heuropt/latest/heuropt/algorithms/nelder_mead/struct.NelderMead.html
[DifferentialEvolution]: https://docs.rs/heuropt/latest/heuropt/algorithms/differential_evolution/struct.DifferentialEvolution.html
[SimulatedAnnealing]: https://docs.rs/heuropt/latest/heuropt/algorithms/simulated_annealing/struct.SimulatedAnnealing.html
[Tlbo]: https://docs.rs/heuropt/latest/heuropt/algorithms/tlbo/struct.Tlbo.html
[OnePlusOneEs]: https://docs.rs/heuropt/latest/heuropt/algorithms/one_plus_one_es/struct.OnePlusOneEs.html
[RandomSearch]: https://docs.rs/heuropt/latest/heuropt/algorithms/random_search/struct.RandomSearch.html
[HillClimber]: https://docs.rs/heuropt/latest/heuropt/algorithms/hill_climber/struct.HillClimber.html
[BayesianOpt]: https://docs.rs/heuropt/latest/heuropt/algorithms/bayesian_opt/struct.BayesianOpt.html
[TPE]: https://docs.rs/heuropt/latest/heuropt/algorithms/tpe/struct.Tpe.html
[Hyperband]: https://docs.rs/heuropt/latest/heuropt/algorithms/hyperband/struct.Hyperband.html
[`PartialProblem`]: https://docs.rs/heuropt/latest/heuropt/core/partial_problem/trait.PartialProblem.html
[`Umda`]: https://docs.rs/heuropt/latest/heuropt/algorithms/umda/struct.Umda.html
[`GeneticAlgorithm`]: https://docs.rs/heuropt/latest/heuropt/algorithms/genetic_algorithm/struct.GeneticAlgorithm.html
[Umda]: https://docs.rs/heuropt/latest/heuropt/algorithms/umda/struct.Umda.html
[GeneticAlgorithm]: https://docs.rs/heuropt/latest/heuropt/algorithms/genetic_algorithm/struct.GeneticAlgorithm.html
[`BitFlipMutation`]: https://docs.rs/heuropt/latest/heuropt/operators/struct.BitFlipMutation.html
[`AntColonyTsp`]: https://docs.rs/heuropt/latest/heuropt/algorithms/ant_colony_tsp/struct.AntColonyTsp.html
[AntColonyTsp]: https://docs.rs/heuropt/latest/heuropt/algorithms/ant_colony_tsp/struct.AntColonyTsp.html
[`SwapMutation`]: https://docs.rs/heuropt/latest/heuropt/operators/struct.SwapMutation.html
[`TabuSearch`]: https://docs.rs/heuropt/latest/heuropt/algorithms/tabu_search/struct.TabuSearch.html
[`Nsga2`]: https://docs.rs/heuropt/latest/heuropt/algorithms/nsga2/struct.Nsga2.html
[`Nsga3`]: https://docs.rs/heuropt/latest/heuropt/algorithms/nsga3/struct.Nsga3.html
[`Mopso`]: https://docs.rs/heuropt/latest/heuropt/algorithms/mopso/struct.Mopso.html
[`Ibea`]: https://docs.rs/heuropt/latest/heuropt/algorithms/ibea/struct.Ibea.html
[`Spea2`]: https://docs.rs/heuropt/latest/heuropt/algorithms/spea2/struct.Spea2.html
[`SmsEmoa`]: https://docs.rs/heuropt/latest/heuropt/algorithms/sms_emoa/struct.SmsEmoa.html
[`Moead`]: https://docs.rs/heuropt/latest/heuropt/algorithms/moead/struct.Moead.html
[`AgeMoea`]: https://docs.rs/heuropt/latest/heuropt/algorithms/age_moea/struct.AgeMoea.html
[`Knea`]: https://docs.rs/heuropt/latest/heuropt/algorithms/knea/struct.Knea.html
[`PesaII`]: https://docs.rs/heuropt/latest/heuropt/algorithms/pesa2/struct.PesaII.html
[`EpsilonMoea`]: https://docs.rs/heuropt/latest/heuropt/algorithms/epsilon_moea/struct.EpsilonMoea.html
[`Paes`]: https://docs.rs/heuropt/latest/heuropt/algorithms/paes/struct.Paes.html
[`Grea`]: https://docs.rs/heuropt/latest/heuropt/algorithms/grea/struct.Grea.html
[`Rvea`]: https://docs.rs/heuropt/latest/heuropt/algorithms/rvea/struct.Rvea.html
[`HypE`]: https://docs.rs/heuropt/latest/heuropt/algorithms/hype/struct.Hype.html
[TabuSearch]: https://docs.rs/heuropt/latest/heuropt/algorithms/tabu_search/struct.TabuSearch.html
[Nsga2]: https://docs.rs/heuropt/latest/heuropt/algorithms/nsga2/struct.Nsga2.html
[Nsga3]: https://docs.rs/heuropt/latest/heuropt/algorithms/nsga3/struct.Nsga3.html
[Mopso]: https://docs.rs/heuropt/latest/heuropt/algorithms/mopso/struct.Mopso.html
[Ibea]: https://docs.rs/heuropt/latest/heuropt/algorithms/ibea/struct.Ibea.html
[Spea2]: https://docs.rs/heuropt/latest/heuropt/algorithms/spea2/struct.Spea2.html
[SmsEmoa]: https://docs.rs/heuropt/latest/heuropt/algorithms/sms_emoa/struct.SmsEmoa.html
[Moead]: https://docs.rs/heuropt/latest/heuropt/algorithms/moead/struct.Moead.html
[AgeMoea]: https://docs.rs/heuropt/latest/heuropt/algorithms/age_moea/struct.AgeMoea.html
[Knea]: https://docs.rs/heuropt/latest/heuropt/algorithms/knea/struct.Knea.html
[PesaII]: https://docs.rs/heuropt/latest/heuropt/algorithms/pesa2/struct.PesaII.html
[EpsilonMoea]: https://docs.rs/heuropt/latest/heuropt/algorithms/epsilon_moea/struct.EpsilonMoea.html
[Paes]: https://docs.rs/heuropt/latest/heuropt/algorithms/paes/struct.Paes.html
[Grea]: https://docs.rs/heuropt/latest/heuropt/algorithms/grea/struct.Grea.html
[Rvea]: https://docs.rs/heuropt/latest/heuropt/algorithms/rvea/struct.Rvea.html
[Hype]: https://docs.rs/heuropt/latest/heuropt/algorithms/hype/struct.Hype.html
[`Repair<D>`]: https://docs.rs/heuropt/latest/heuropt/traits/trait.Repair.html
[`ClampToBounds`]: https://docs.rs/heuropt/latest/heuropt/operators/struct.ClampToBounds.html
[`ProjectToSimplex`]: https://docs.rs/heuropt/latest/heuropt/operators/struct.ProjectToSimplex.html
+5 -5
View File
@@ -15,7 +15,7 @@ The columns:
| Library | Lang | Algorithms | Multi-obj | Surrogates | Determinism | Async |
|---|---|---|---|---|---|---|
| **heuropt 0.8** | Rust | 33 | ✅ NSGA-II/III, SPEA2, IBEA, MOEA/D, MOPSO, SMS-EMOA, HypE, AGE-MOEA, GrEA, KnEA, RVEA, PESA-II, ε-MOEA, PAES | ✅ BO, TPE, Hyperband | ✅ bit-identical seeded | ✅ `AsyncProblem` + `run_async` on every algorithm |
| **heuropt 0.10** | Rust | 33 | ✅ NSGA-II/III, SPEA2, IBEA, MOEA/D, MOPSO, SMS-EMOA, HypE, AGE-MOEA, GrEA, KnEA, RVEA, PESA-II, ε-MOEA, PAES | ✅ BO, TPE, Hyperband | ✅ bit-identical seeded | ✅ `AsyncProblem` + `run_async` on every algorithm |
| pymoo | Python | ~25 | ✅ extensive | partial (BO via plug-ins) | ✅ | ❌ |
| DEAP | Python | flexible toolbox | ✅ | ❌ | ✅ | ❌ |
| hyperopt | Python | TPE-focused | ❌ | ✅ TPE | partial | partial |
@@ -36,7 +36,7 @@ The columns:
otherwise.
- You want a **small, readable codebase** — every algorithm is
written for clarity, no trait-object plumbing, no GATs in user-
facing APIs. Reading `RandomSearch` should be enough to write a
facing APIs. Reading Random Search should be enough to write a
new optimizer.
- You have **IO-bound evaluations** — calling an HTTP service, an
RPC, or a subprocess — and want first-class `async fn evaluate`
@@ -64,12 +64,12 @@ heuropt covers the same major Pareto MOEAs as pymoo and MOEA Framework:
NSGA-II/III, SPEA2, IBEA, MOEA/D, MOPSO, SMS-EMOA, HypE, AGE-MOEA,
GrEA, KnEA, RVEA, PESA-II, ε-MOEA, PAES.
The expensive-evaluation regime: BayesianOpt + TPE + Hyperband. This
The expensive-evaluation regime: Bayesian Optimization + TPE + Hyperband. This
is comparable to optuna's coverage but in pure Rust.
The single-objective continuous catalog (CMA-ES, IPOP-CMA-ES, sNES,
DE, PSO, GA, TLBO, (1+1)-ES, NelderMead, RandomSearch, HillClimber,
SimulatedAnnealing) covers the canonical baselines and several modern
DE, PSO, GA, TLBO, (1+1)-ES, Nelder-Mead, Random Search, Hill Climber,
Simulated Annealing) covers the canonical baselines and several modern
variants.
What heuropt does **not** ship that some libraries do:
+6 -2
View File
@@ -14,17 +14,21 @@ project.
optimizer await many evaluations concurrently. The differentiating
feature vs other optimization libraries.
- [Tune a model with expensive evaluations](./cookbook/expensive-evaluations.md)
`BayesianOpt`, `Tpe`, and `Hyperband` for the 50500-eval
— Bayesian Optimization, TPE, and Hyperband for the 50500-eval
regime.
- [Compare two algorithms on your problem](./cookbook/compare.md) —
multi-seed harness pattern straight from `examples/compare.rs`.
- [Optimize a permutation (TSP-style)](./cookbook/permutation.md) —
`AntColonyTsp` with a distance matrix.
Ant Colony with a distance matrix.
- [Constrain your search with `Repair`](./cookbook/constraints.md) —
bounds, simplex projection, custom repair.
- [Pick one answer off a Pareto front](./cookbook/pick-one.md) — the
a-posteriori weighted-decision pattern from the `jiggly_tuning`
example.
- [Explore your results in a webapp](./cookbook/explorer.md) — export
an `OptimizationResult` to JSON and browse it interactively at
[heuropt-explorer](https://swaits.github.io/heuropt-explorer/) —
parallel coordinates, scatter, range filters, weighted ranking.
- [Write your own algorithm](./cookbook/custom-optimizer.md) —
implement `Optimizer<P>` from scratch, à la the
`examples/custom_optimizer.rs` walkthrough.
+3 -3
View File
@@ -13,7 +13,7 @@ evaluation path.
```toml
[dependencies]
heuropt = { version = "0.8", features = ["async"] }
heuropt = { version = "0.10", features = ["async"] }
# Pick whatever async runtime you want; heuropt itself depends only on
# `futures`. The example below uses tokio.
@@ -112,8 +112,8 @@ results back to the algorithm.
## What the worked example shows
`examples/async_eval.rs` runs `RandomSearch` (200 evaluations × 20 ms
each) at `concurrency = 1, 4, 16` and `DifferentialEvolution` at
`examples/async_eval.rs` runs Random Search (200 evaluations × 20 ms
each) at `concurrency = 1, 4, 16` and Differential Evolution at
`concurrency = 8`. On a recent machine:
```text
@@ -7,9 +7,9 @@ algorithms aimed at this regime.
| Algorithm | Surrogate | Best for |
|---|---|---|
| [`BayesianOpt`] | Gaussian process + Expected Improvement | The textbook choice; needs kernel tuning to shine |
| [`Tpe`] | Kernel-density estimate of good vs bad points | Cheaper per step; more robust without tuning |
| [`Hyperband`] | (none — it's a multi-fidelity scheduler) | When each eval has a tunable budget (epochs, MC samples) |
| [Bayesian Optimization][BayesianOpt] | Gaussian process + Expected Improvement | The textbook choice; needs kernel tuning to shine |
| [TPE] | Kernel-density estimate of good vs bad points | Cheaper per step; more robust without tuning |
| [Hyperband] | (none — it's a multi-fidelity scheduler) | When each eval has a tunable budget (epochs, MC samples) |
## When each is right
@@ -101,7 +101,7 @@ canonical Bergstra value.
## Hyperband
[`Hyperband`] needs your problem to implement [`PartialProblem`] —
[Hyperband] needs your problem to implement [`PartialProblem`] —
that is, you can evaluate at a tunable fidelity (e.g. number of
training epochs). The algorithm schedules many cheap-fidelity runs
and promotes only the survivors to higher fidelity.
@@ -156,9 +156,9 @@ The state of the art (BOHB) combines BO with Hyperband: TPE picks the
configurations Hyperband then evaluates at increasing fidelity.
heuropt doesn't ship a unified BOHB but the building blocks are
there — wrap your `PartialProblem` with a TPE-driven sampler and
feed the picks into `Hyperband`. PRs welcome.
feed the picks into Hyperband. PRs welcome.
[`BayesianOpt`]: https://docs.rs/heuropt/latest/heuropt/algorithms/bayesian_opt/struct.BayesianOpt.html
[`Tpe`]: https://docs.rs/heuropt/latest/heuropt/algorithms/tpe/struct.Tpe.html
[`Hyperband`]: https://docs.rs/heuropt/latest/heuropt/algorithms/hyperband/struct.Hyperband.html
[BayesianOpt]: https://docs.rs/heuropt/latest/heuropt/algorithms/bayesian_opt/struct.BayesianOpt.html
[TPE]: https://docs.rs/heuropt/latest/heuropt/algorithms/tpe/struct.Tpe.html
[Hyperband]: https://docs.rs/heuropt/latest/heuropt/algorithms/hyperband/struct.Hyperband.html
[`PartialProblem`]: https://docs.rs/heuropt/latest/heuropt/core/partial_problem/trait.PartialProblem.html
+1 -1
View File
@@ -14,7 +14,7 @@ install needed beyond a browser.
```toml
[dependencies]
heuropt = { version = "0.9", features = ["serde"] }
heuropt = { version = "0.10", features = ["serde"] }
```
The export uses `serde_json` under the hood, so the explorer module
+29 -29
View File
@@ -9,7 +9,7 @@ population, and rayon parallelizes that batch.
```toml
[dependencies]
heuropt = { version = "0.8", features = ["parallel"] }
heuropt = { version = "0.10", features = ["parallel"] }
```
There's nothing else to opt into in your code. The
@@ -29,14 +29,14 @@ pass.
Algorithms with a per-generation `evaluate_batch`:
- [`RandomSearch`], [`Nsga2`], [`Nsga3`], [`Spea2`], [`Moead`],
[`Mopso`], [`Ibea`], [`SmsEmoa`], [`HypE`], [`PesaII`],
[`EpsilonMoea`], [`AgeMoea`], [`Knea`], [`Grea`], [`Rvea`].
- [`DifferentialEvolution`] and [`GeneticAlgorithm`] benefit on the
- [Random Search][RandomSearch], [NSGA-II][Nsga2], [NSGA-III][Nsga3], [SPEA2][Spea2], [MOEA/D][Moead],
[MOPSO][Mopso], [IBEA][Ibea], [SMS-EMOA][SmsEmoa], [HypE][Hype], [PESA-II][PesaII],
[ε-MOEA][EpsilonMoea], [AGE-MOEA][AgeMoea], [KnEA][Knea], [GrEA][Grea], [RVEA][Rvea].
- [Differential Evolution][DifferentialEvolution] and [GA][GeneticAlgorithm] benefit on the
initial population and offspring batches.
Steady-state algorithms ([`Paes`], [`SimulatedAnnealing`],
[`HillClimber`], [`OnePlusOneEs`]) only evaluate one or a few
Steady-state algorithms ([PAES][Paes], [Simulated Annealing][SimulatedAnnealing],
[Hill Climber][HillClimber], [(1+1)-ES][OnePlusOneEs]) only evaluate one or a few
candidates per iteration, so the parallel feature gives them
nothing — leave it off if those are your primary optimizers.
@@ -102,7 +102,7 @@ to scope it.
- You're already running multiple seeds in parallel at the harness
level (see [Compare two algorithms](./compare.md)). Stacking
parallelism rarely helps.
- The algorithm is steady-state (Paes, SA, hill climber).
- The algorithm is steady-state (PAES, SA, hill climber).
## `parallel` vs `async`
@@ -114,24 +114,24 @@ to scope it.
Both can be on at once if your evaluation does *both* substantial
CPU work *and* IO. The two features are independent.
[`RandomSearch`]: https://docs.rs/heuropt/latest/heuropt/algorithms/random_search/struct.RandomSearch.html
[`Nsga2`]: https://docs.rs/heuropt/latest/heuropt/algorithms/nsga2/struct.Nsga2.html
[`Nsga3`]: https://docs.rs/heuropt/latest/heuropt/algorithms/nsga3/struct.Nsga3.html
[`Spea2`]: https://docs.rs/heuropt/latest/heuropt/algorithms/spea2/struct.Spea2.html
[`Moead`]: https://docs.rs/heuropt/latest/heuropt/algorithms/moead/struct.Moead.html
[`Mopso`]: https://docs.rs/heuropt/latest/heuropt/algorithms/mopso/struct.Mopso.html
[`Ibea`]: https://docs.rs/heuropt/latest/heuropt/algorithms/ibea/struct.Ibea.html
[`SmsEmoa`]: https://docs.rs/heuropt/latest/heuropt/algorithms/sms_emoa/struct.SmsEmoa.html
[`HypE`]: https://docs.rs/heuropt/latest/heuropt/algorithms/hype/struct.Hype.html
[`PesaII`]: https://docs.rs/heuropt/latest/heuropt/algorithms/pesa2/struct.PesaII.html
[`EpsilonMoea`]: https://docs.rs/heuropt/latest/heuropt/algorithms/epsilon_moea/struct.EpsilonMoea.html
[`AgeMoea`]: https://docs.rs/heuropt/latest/heuropt/algorithms/age_moea/struct.AgeMoea.html
[`Knea`]: https://docs.rs/heuropt/latest/heuropt/algorithms/knea/struct.Knea.html
[`Grea`]: https://docs.rs/heuropt/latest/heuropt/algorithms/grea/struct.Grea.html
[`Rvea`]: https://docs.rs/heuropt/latest/heuropt/algorithms/rvea/struct.Rvea.html
[`DifferentialEvolution`]: https://docs.rs/heuropt/latest/heuropt/algorithms/differential_evolution/struct.DifferentialEvolution.html
[`GeneticAlgorithm`]: https://docs.rs/heuropt/latest/heuropt/algorithms/genetic_algorithm/struct.GeneticAlgorithm.html
[`Paes`]: https://docs.rs/heuropt/latest/heuropt/algorithms/paes/struct.Paes.html
[`SimulatedAnnealing`]: https://docs.rs/heuropt/latest/heuropt/algorithms/simulated_annealing/struct.SimulatedAnnealing.html
[`HillClimber`]: https://docs.rs/heuropt/latest/heuropt/algorithms/hill_climber/struct.HillClimber.html
[`OnePlusOneEs`]: https://docs.rs/heuropt/latest/heuropt/algorithms/one_plus_one_es/struct.OnePlusOneEs.html
[RandomSearch]: https://docs.rs/heuropt/latest/heuropt/algorithms/random_search/struct.RandomSearch.html
[Nsga2]: https://docs.rs/heuropt/latest/heuropt/algorithms/nsga2/struct.Nsga2.html
[Nsga3]: https://docs.rs/heuropt/latest/heuropt/algorithms/nsga3/struct.Nsga3.html
[Spea2]: https://docs.rs/heuropt/latest/heuropt/algorithms/spea2/struct.Spea2.html
[Moead]: https://docs.rs/heuropt/latest/heuropt/algorithms/moead/struct.Moead.html
[Mopso]: https://docs.rs/heuropt/latest/heuropt/algorithms/mopso/struct.Mopso.html
[Ibea]: https://docs.rs/heuropt/latest/heuropt/algorithms/ibea/struct.Ibea.html
[SmsEmoa]: https://docs.rs/heuropt/latest/heuropt/algorithms/sms_emoa/struct.SmsEmoa.html
[Hype]: https://docs.rs/heuropt/latest/heuropt/algorithms/hype/struct.Hype.html
[PesaII]: https://docs.rs/heuropt/latest/heuropt/algorithms/pesa2/struct.PesaII.html
[EpsilonMoea]: https://docs.rs/heuropt/latest/heuropt/algorithms/epsilon_moea/struct.EpsilonMoea.html
[AgeMoea]: https://docs.rs/heuropt/latest/heuropt/algorithms/age_moea/struct.AgeMoea.html
[Knea]: https://docs.rs/heuropt/latest/heuropt/algorithms/knea/struct.Knea.html
[Grea]: https://docs.rs/heuropt/latest/heuropt/algorithms/grea/struct.Grea.html
[Rvea]: https://docs.rs/heuropt/latest/heuropt/algorithms/rvea/struct.Rvea.html
[DifferentialEvolution]: https://docs.rs/heuropt/latest/heuropt/algorithms/differential_evolution/struct.DifferentialEvolution.html
[GeneticAlgorithm]: https://docs.rs/heuropt/latest/heuropt/algorithms/genetic_algorithm/struct.GeneticAlgorithm.html
[Paes]: https://docs.rs/heuropt/latest/heuropt/algorithms/paes/struct.Paes.html
[SimulatedAnnealing]: https://docs.rs/heuropt/latest/heuropt/algorithms/simulated_annealing/struct.SimulatedAnnealing.html
[HillClimber]: https://docs.rs/heuropt/latest/heuropt/algorithms/hill_climber/struct.HillClimber.html
[OnePlusOneEs]: https://docs.rs/heuropt/latest/heuropt/algorithms/one_plus_one_es/struct.OnePlusOneEs.html
+9 -9
View File
@@ -2,11 +2,11 @@
When your decision is "an ordering" — visiting cities, scheduling
jobs, routing — the natural representation is `Vec<usize>` and the
specialized algorithm is [`AntColonyTsp`]. Generic alternatives are
[`SimulatedAnnealing`] + [`SwapMutation`] for any permutation, and
[`TabuSearch`] when you have a custom neighbor function.
specialized algorithm is [Ant Colony][AntColonyTsp]. Generic alternatives are
[Simulated Annealing][SimulatedAnnealing] + [`SwapMutation`] for any permutation, and
[Tabu Search][TabuSearch] when you have a custom neighbor function.
## TSP with `AntColonyTsp`
## TSP with Ant Colony
```rust,no_run
use heuropt::prelude::*;
@@ -138,10 +138,10 @@ println!("schedule: {:?}", best.decision);
`SwapMutation` swaps two random indices in the permutation —
preserves the "every element appears once" invariant for free.
## Custom neighborhoods: `TabuSearch`
## Custom neighborhoods: Tabu Search
When swap isn't the right move set (e.g., 2-opt for TSP, insert /
shift for scheduling), use [`TabuSearch`] with your own neighbor
shift for scheduling), use [Tabu Search][TabuSearch] with your own neighbor
function.
```rust,ignore
@@ -161,7 +161,7 @@ let neighbors = |x: &Vec<usize>, _rng: &mut Rng| -> Vec<Vec<usize>> {
// Pass `neighbors` to TabuSearch::new(...).
```
[`AntColonyTsp`]: https://docs.rs/heuropt/latest/heuropt/algorithms/ant_colony_tsp/struct.AntColonyTsp.html
[`SimulatedAnnealing`]: https://docs.rs/heuropt/latest/heuropt/algorithms/simulated_annealing/struct.SimulatedAnnealing.html
[AntColonyTsp]: https://docs.rs/heuropt/latest/heuropt/algorithms/ant_colony_tsp/struct.AntColonyTsp.html
[SimulatedAnnealing]: https://docs.rs/heuropt/latest/heuropt/algorithms/simulated_annealing/struct.SimulatedAnnealing.html
[`SwapMutation`]: https://docs.rs/heuropt/latest/heuropt/operators/struct.SwapMutation.html
[`TabuSearch`]: https://docs.rs/heuropt/latest/heuropt/algorithms/tabu_search/struct.TabuSearch.html
[TabuSearch]: https://docs.rs/heuropt/latest/heuropt/algorithms/tabu_search/struct.TabuSearch.html
+15 -15
View File
@@ -87,8 +87,8 @@ impl Problem for Zdt1 {
```
For multi-objective problems, pick a Pareto-aware optimizer:
[`Nsga2`] is the canonical default; [`Mopso`] often wins on
smooth-front 2-objective problems; [`Ibea`] often wins on
[NSGA-II][Nsga2] is the canonical default; [MOPSO][Mopso] often wins on
smooth-front 2-objective problems; [IBEA][Ibea] often wins on
disconnected fronts. See [choosing-an-algorithm](./choosing-an-algorithm.md).
## Maximizing instead of minimizing
@@ -166,8 +166,8 @@ impl Problem for OneMax {
}
```
For `Vec<bool>` problems, [`Umda`] is a parameter-free EDA;
[`GeneticAlgorithm`] with [`BitFlipMutation`] is the GA route.
For `Vec<bool>` problems, [UMDA][Umda] is a parameter-free EDA;
[GA][GeneticAlgorithm] with [`BitFlipMutation`] is the GA route.
### Permutations (`Vec<usize>`)
@@ -191,9 +191,9 @@ impl Problem for Tsp {
}
```
For permutations, [`AntColonyTsp`] specializes on TSP-style problems;
[`TabuSearch`] takes a user-supplied neighbor function for arbitrary
discrete neighborhoods; [`SimulatedAnnealing`] with [`SwapMutation`]
For permutations, [Ant Colony][AntColonyTsp] specializes on TSP-style problems;
[Tabu Search][TabuSearch] takes a user-supplied neighbor function for arbitrary
discrete neighborhoods; [Simulated Annealing][SimulatedAnnealing] with [`SwapMutation`]
is the simplest baseline.
### Custom decision types
@@ -232,13 +232,13 @@ through the decision tree.
[`Evaluation`]: https://docs.rs/heuropt/latest/heuropt/core/evaluation/struct.Evaluation.html
[`Evaluation::new`]: https://docs.rs/heuropt/latest/heuropt/core/evaluation/struct.Evaluation.html#method.new
[`Evaluation::constrained`]: https://docs.rs/heuropt/latest/heuropt/core/evaluation/struct.Evaluation.html#method.constrained
[`Nsga2`]: https://docs.rs/heuropt/latest/heuropt/algorithms/nsga2/struct.Nsga2.html
[`Mopso`]: https://docs.rs/heuropt/latest/heuropt/algorithms/mopso/struct.Mopso.html
[`Ibea`]: https://docs.rs/heuropt/latest/heuropt/algorithms/ibea/struct.Ibea.html
[`Umda`]: https://docs.rs/heuropt/latest/heuropt/algorithms/umda/struct.Umda.html
[`GeneticAlgorithm`]: https://docs.rs/heuropt/latest/heuropt/algorithms/genetic_algorithm/struct.GeneticAlgorithm.html
[Nsga2]: https://docs.rs/heuropt/latest/heuropt/algorithms/nsga2/struct.Nsga2.html
[Mopso]: https://docs.rs/heuropt/latest/heuropt/algorithms/mopso/struct.Mopso.html
[Ibea]: https://docs.rs/heuropt/latest/heuropt/algorithms/ibea/struct.Ibea.html
[Umda]: https://docs.rs/heuropt/latest/heuropt/algorithms/umda/struct.Umda.html
[GeneticAlgorithm]: https://docs.rs/heuropt/latest/heuropt/algorithms/genetic_algorithm/struct.GeneticAlgorithm.html
[`BitFlipMutation`]: https://docs.rs/heuropt/latest/heuropt/operators/struct.BitFlipMutation.html
[`AntColonyTsp`]: https://docs.rs/heuropt/latest/heuropt/algorithms/ant_colony_tsp/struct.AntColonyTsp.html
[`TabuSearch`]: https://docs.rs/heuropt/latest/heuropt/algorithms/tabu_search/struct.TabuSearch.html
[`SimulatedAnnealing`]: https://docs.rs/heuropt/latest/heuropt/algorithms/simulated_annealing/struct.SimulatedAnnealing.html
[AntColonyTsp]: https://docs.rs/heuropt/latest/heuropt/algorithms/ant_colony_tsp/struct.AntColonyTsp.html
[TabuSearch]: https://docs.rs/heuropt/latest/heuropt/algorithms/tabu_search/struct.TabuSearch.html
[SimulatedAnnealing]: https://docs.rs/heuropt/latest/heuropt/algorithms/simulated_annealing/struct.SimulatedAnnealing.html
[`SwapMutation`]: https://docs.rs/heuropt/latest/heuropt/operators/struct.SwapMutation.html
+8 -6
View File
@@ -6,19 +6,21 @@ The shortest path from a fresh project to a working optimizer.
```toml
[dependencies]
heuropt = "0.8"
heuropt = "0.10"
```
The default feature set is small. Optional features:
- `parallel` — rayon-backed parallel population evaluation.
- `serde``Serialize` / `Deserialize` derives on the core data
types.
types, plus the `heuropt::explorer` JSON export module for the
[heuropt-explorer](https://swaits.github.io/heuropt-explorer/)
webapp.
- `async``AsyncProblem` trait + per-algorithm `run_async` for
IO-bound evaluations.
```toml
heuropt = { version = "0.8", features = ["parallel"] }
heuropt = { version = "0.10", features = ["parallel"] }
```
## 2. Define a problem and run an optimizer
@@ -31,7 +33,7 @@ how to score one decision.
We'll fit a straight line to a handful of `(x, y)` data points by
finding the slope and intercept that minimize the sum of squared
errors — same objective as least-squares regression. For a smooth
single-objective continuous problem like this, [`CmaEs`] is a strong
single-objective continuous problem like this, [CMA-ES][CmaEs] is a strong
default.
```rust,no_run
@@ -138,7 +140,7 @@ problems this clean in well under that budget.
## 4. What just happened
- [`Problem`] is the **what** you're optimizing.
- [`CmaEs`] (or any other optimizer) is the **how**.
- [CMA-ES][CmaEs] (or any other optimizer) is the **how**.
- [`CmaEsConfig`] is a plain public-field struct: there are no
builders, no chained setters, just public fields you set
directly.
@@ -163,5 +165,5 @@ problems this clean in well under that budget.
[`Problem`]: https://docs.rs/heuropt/latest/heuropt/core/problem/trait.Problem.html
[`Optimizer::run`]: https://docs.rs/heuropt/latest/heuropt/traits/trait.Optimizer.html
[`OptimizationResult`]: https://docs.rs/heuropt/latest/heuropt/core/result/struct.OptimizationResult.html
[`CmaEs`]: https://docs.rs/heuropt/latest/heuropt/algorithms/cma_es/struct.CmaEs.html
[CmaEs]: https://docs.rs/heuropt/latest/heuropt/algorithms/cma_es/struct.CmaEs.html
[`CmaEsConfig`]: https://docs.rs/heuropt/latest/heuropt/algorithms/cma_es/struct.CmaEsConfig.html
+12 -14
View File
@@ -28,7 +28,7 @@ hyperopt, optuna, DEAP). heuropt's design priorities:
1. **Approachable code.** No trait objects in the public API. No
GATs, HRTBs, generic-RNG plumbing. A junior Rust engineer should
be able to read `RandomSearch` and write a new optimizer by
be able to read Random Search and write a new optimizer by
implementing only the `Optimizer<P>` trait.
2. **One concrete RNG type.** Seeded determinism is a property tested
across the crate; identical inputs always produce identical
@@ -44,20 +44,18 @@ hyperopt, optuna, DEAP). heuropt's design priorities:
## What's in the box
heuropt v0.8 ships **33 algorithms** spanning:
heuropt v0.10 ships **33 algorithms** spanning:
- Single-objective continuous: `RandomSearch`, `HillClimber`,
`OnePlusOneEs`, `SimulatedAnnealing`, `GeneticAlgorithm`,
`ParticleSwarm`, `DifferentialEvolution`, `Tlbo`, `CmaEs`,
`IpopCmaEs`, `SeparableNes`, `NelderMead`.
- Single-objective other types: `Umda` (binary), `TabuSearch`
(any), `AntColonyTsp` (permutation).
- Multi-objective (23): `Paes`, `Nsga2`, `Spea2`, `Mopso`, `Ibea`,
`SmsEmoa`, `HypE`, `EpsilonMoea`, `PesaII`, `AgeMoea`, `Knea`,
`Moead`.
- Many-objective (4+): `Nsga3`, `Rvea`, `Grea`.
- Sample-efficient / multi-fidelity: `BayesianOpt`, `Tpe`,
`Hyperband`.
- Single-objective continuous: Random Search, Hill Climber,
(1+1)-ES, Simulated Annealing, GA, PSO, Differential Evolution,
TLBO, CMA-ES, IPOP-CMA-ES, sNES, Nelder-Mead.
- Single-objective other types: UMDA (binary), Tabu Search (any),
Ant Colony (permutation).
- Multi-objective (23): PAES, NSGA-II, SPEA2, MOPSO, IBEA,
SMS-EMOA, HypE, ε-MOEA, PESA-II, AGE-MOEA, KnEA, MOEA/D.
- Many-objective (4+): NSGA-III, RVEA, GrEA.
- Sample-efficient / multi-fidelity: Bayesian Optimization, TPE,
Hyperband.
Plus the operators (SBX, PolynomialMutation, BoundedGaussianMutation,
LevyMutation, BitFlipMutation, SwapMutation, ClampToBounds,
+69 -5
View File
@@ -3,6 +3,70 @@
Per-release notes for upgrading between heuropt versions. Skip the
sections that don't apply to your starting version.
## To 0.10
### From 0.9.x
**Almost additive.** Bumping `heuropt = "0.10"` recompiles
without touching most code. The one breaking change is the value
returned by `AlgorithmInfo::name()`:
| Before (`0.9`) | After (`0.10`) |
|---|---|
| `"Nsga2"` | `"NSGA-II"` |
| `"Nsga3"` | `"NSGA-III"` |
| `"Cmaes"` | `"CMA-ES"` |
| `"Mopso"` | `"MOPSO"` |
| `"Moead"` | `"MOEA/D"` |
| `"EpsilonMoea"` | `"ε-MOEA"` |
| (and 27 more) | … |
If you pattern-matched on those strings (e.g. for branching
display logic), update to the new canonical strings. They now
match the literature and will be stable going forward.
What's new and additive:
- `AlgorithmInfo::full_name(&self) -> &'static str` — academic
long form (`"Non-dominated Sorting Genetic Algorithm II"`).
Defaults to `name()` for algorithms whose long and short
forms coincide.
- `ExplorerExport`'s `RunMeta` gained `algorithm_full_name:
Option<String>`. Schema version stays at **1** (the new field
is `#[serde(default)]`); display tools can use the long form
as a hover tooltip on the short name.
## To 0.9
### From 0.8.x
**Additive only.** Bumping `heuropt = "0.9"` works for all 0.8.x
code untouched. The new surfaces ship behind the existing `serde`
feature.
What's new:
- `heuropt::explorer` module (gated on `serde`) — turns an
`OptimizationResult` into a self-describing JSON file that the
[heuropt-explorer](https://swaits.github.io/heuropt-explorer/)
webapp can load. See the
[Explore your results](./cookbook/explorer.md) recipe.
- `Objective` gained optional `label` and `unit` fields with
fluent builders `.with_label("…")` / `.with_unit("…")`. Existing
`Objective::minimize("…")` / `Objective::maximize("…")` are
unchanged. The serde representation is forward- and backward-
compatible (new fields are `#[serde(default)]`).
- `Problem` trait gained a default-empty
`fn decision_schema(&self) -> Vec<DecisionVariable>` method.
Existing impls compile untouched; override it to provide pretty
names / labels / units / bounds for the explorer.
- `heuropt::traits::AlgorithmInfo` — every built-in algorithm
exposes its short canonical name (`"Nsga3"`, …) and its seed.
Used by the explorer JSON export.
If you don't want any of this, no migration needed — just bump
the version.
## To 0.8
### From 0.5.x
@@ -101,9 +165,9 @@ from v0.3 are still numerically accurate but will run faster.
### From 0.2.x
**Additive only.** New algorithms (`BayesianOpt`, `Tpe`,
`OnePlusOneEs`, `IpopCmaEs`, `SeparableNes`, `NelderMead`,
`Hyperband`), new operators (`LevyMutation`, `ClampToBounds`,
**Additive only.** New algorithms (Bayesian Optimization, TPE,
(1+1)-ES, IPOP-CMA-ES, sNES, Nelder-Mead,
Hyperband), new operators (`LevyMutation`, `ClampToBounds`,
`ProjectToSimplex`), new traits (`PartialProblem`, `Repair<D>`).
`CmaEsConfig` gained an `initial_mean: Option<Vec<f64>>` field;
@@ -114,8 +178,8 @@ existing call sites need a `.. CmaEsConfig { initial_mean: None,
### From 0.1.x
**Additive.** New algorithms across the catalog (HillClimber, SA,
GA, PSO, CMA-ES, TabuSearch, AntColonyTsp, Umda, TLBO, MOPSO, IBEA,
**Additive.** New algorithms across the catalog (Hill Climber, SA,
GA, PSO, CMA-ES, Tabu Search, Ant Colony, UMDA, TLBO, MOPSO, IBEA,
SMS-EMOA, HypE, RVEA, PESA-II, ε-MOEA, AGE-MOEA, GrEA, KnEA), new
operators (`SimulatedBinaryCrossover`, `PolynomialMutation`,
`CompositeVariation`, `BoundedGaussianMutation`), and the
+3 -3
View File
@@ -18,10 +18,10 @@ versions — use them at your own risk.
While we are pre-1.0:
- **Minor bumps (`0.8 → 0.9`) may break the public API.** The
- **Minor bumps (`0.10 → 0.11`) may break the public API.** The
CHANGELOG calls out everything that changed, and a **migration
guide** in this book documents the move.
- **Patch bumps (`0.8.0 → 0.8.1`) only contain bug fixes,
- **Patch bumps (`0.10.0 → 0.10.1`) only contain bug fixes,
performance improvements, and additive non-breaking features.**
No deprecations, no removals.
@@ -61,7 +61,7 @@ optimizations has been bit-identical against the v0.3.0 reference.
## MSRV (minimum supported Rust version)
heuropt's MSRV is **1.85** as of v0.8. This is tested in CI against
heuropt's MSRV is **1.85** as of v0.10. This is tested in CI against
every PR.
MSRV bumps are treated as patch-bump-eligible (they don't break the