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:
@@ -1 +0,0 @@
|
||||
{"sessionId":"ac44d107-52ca-4cd4-9586-ae2fe91bc9f7","pid":2366937,"procStart":"77336928","acquiredAt":1778002505967}
|
||||
@@ -1,2 +1,5 @@
|
||||
/target
|
||||
/Cargo.lock
|
||||
|
||||
# Generated by `cargo run --example pick_a_car`
|
||||
/pick_a_car.json
|
||||
|
||||
+146
-1
@@ -7,6 +7,151 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.10.0] — 2026-05-06
|
||||
|
||||
Theme: every algorithm now returns its **canonical name** as it
|
||||
appears in the literature, with an academic long form available
|
||||
alongside, and the docs use those names everywhere. Plus the
|
||||
explorer JSON export now carries both forms so display tools can
|
||||
show the short name with a hover tooltip for the long one.
|
||||
|
||||
No public-API breaks beyond the value of `AlgorithmInfo::name()`,
|
||||
which previously returned the Rust type name and now returns the
|
||||
literature short name (`"NSGA-II"` vs `"Nsga2"`). If your code
|
||||
matched on those strings you'll need to update — but the trait
|
||||
shape itself is unchanged and `algorithm.name()` continues to be
|
||||
the way to read it.
|
||||
|
||||
### Added
|
||||
|
||||
- `AlgorithmInfo::full_name(&self) -> &'static str` — academic
|
||||
long form, e.g. `"Non-dominated Sorting Genetic Algorithm II"`.
|
||||
Defaults to `name()` for algorithms whose short and long forms
|
||||
coincide (Random Search, Hill Climber, Tabu Search).
|
||||
- Every built-in algorithm overrides `full_name()` with its
|
||||
expanded literature name. Mapping table is in the cookbook
|
||||
recipe at `docs/book/src/cookbook/explorer.md`.
|
||||
- `ExplorerExport`'s `RunMeta` gained an optional
|
||||
`algorithm_full_name: Option<String>` field. The
|
||||
`with_algorithm_info()` builder populates both that and
|
||||
`algorithm` from the same `AlgorithmInfo` source. Schema
|
||||
version stays at **1** — the new field is `#[serde(default)]`,
|
||||
so older readers tolerate it and older writers' output still
|
||||
loads cleanly.
|
||||
|
||||
### Changed
|
||||
|
||||
- `AlgorithmInfo::name()` return values for every built-in
|
||||
algorithm. Examples: `"Nsga2"` → `"NSGA-II"`, `"Cmaes"` →
|
||||
`"CMA-ES"`, `"Mopso"` → `"MOPSO"`, `"Moead"` → `"MOEA/D"`,
|
||||
`"EpsilonMoea"` → `"ε-MOEA"`. Full table in the cookbook recipe.
|
||||
- README, mdbook chapters, decision tree, choosing-an-algorithm
|
||||
guide, comparison page, getting-started, defining-problems,
|
||||
cookbook recipes, and migration notes now all use the canonical
|
||||
algorithm names in body prose. Code blocks (which reference the
|
||||
Rust types like `Nsga2::new(...)` or `Nsga2Config { … }`)
|
||||
unchanged — those are still the API.
|
||||
- Default `cargo run --release --example pick_a_car` output now
|
||||
reads `"algorithm": "NSGA-III", "algorithm_full_name":
|
||||
"Non-dominated Sorting Genetic Algorithm III"` in the JSON
|
||||
envelope instead of `"Nsga3"`.
|
||||
|
||||
### Migration
|
||||
|
||||
If you display `optimizer.name()` in your own UI, you'll suddenly
|
||||
get the proper short name for free — usually a strict improvement.
|
||||
The only break: code that pattern-matched on the Rust-type-shaped
|
||||
strings (e.g. `if name == "Nsga3"`) needs updating to the new
|
||||
canonical strings. The names are stable now (they match the
|
||||
literature), so this is a one-time fix.
|
||||
|
||||
[0.10.0]: https://github.com/swaits/heuropt/releases/tag/v0.10.0
|
||||
|
||||
## [0.9.0] — 2026-05-06
|
||||
|
||||
Theme: explorer JSON export. Real Pareto fronts have 50–200+
|
||||
candidates spanning 2–7+ objectives — too many to read as numbers
|
||||
in a terminal. 0.9.0 adds a tiny additive surface that turns any
|
||||
`OptimizationResult` into a self-describing JSON file you can drop
|
||||
into [heuropt-explorer](https://swaits.github.io/heuropt-explorer/)
|
||||
to filter, brush, pin, and rank candidates interactively.
|
||||
|
||||
No public-API breaks. The new surface lives behind the existing
|
||||
`serde` feature and the new methods on `Problem` / the new
|
||||
`AlgorithmInfo` trait have working defaults so existing impls
|
||||
compile untouched.
|
||||
|
||||
### Added
|
||||
|
||||
#### Explorer export (the headline feature)
|
||||
|
||||
- New `heuropt::explorer` module (gated on the `serde` feature).
|
||||
Defines `ExplorerExport`, `ExplorerCandidate`, `RunMeta`, the
|
||||
`ToDecisionValues` adapter trait, and free functions
|
||||
`to_json` / `to_writer` / `to_file`.
|
||||
- Schema is versioned (`SCHEMA_VERSION = 1`); the explorer webapp
|
||||
refuses to load files with an unknown version.
|
||||
- `front_rank` is computed once via `non_dominated_sort` at export
|
||||
time and attached to every candidate so downstream tools don't
|
||||
have to re-derive it.
|
||||
- `ToDecisionValues` is implemented for `Vec<f64>`, `Vec<bool>`,
|
||||
`Vec<usize>`, and `Vec<i64>` out of the box; users with custom
|
||||
decision types implement it themselves (one method).
|
||||
|
||||
#### Problem-side metadata (single source of truth, no duplication)
|
||||
|
||||
- `Objective` gained optional `label: Option<String>` and
|
||||
`unit: Option<String>` fields plus fluent builders
|
||||
`.with_label("Price")` / `.with_unit("$k")`. Existing
|
||||
`Objective::minimize("name")` / `Objective::maximize("name")`
|
||||
unchanged. Backwards-compatible at source level and at the JSON
|
||||
level (the new fields use `#[serde(default,
|
||||
skip_serializing_if = "Option::is_none")]`).
|
||||
- `Problem` trait gained an optional `fn decision_schema(&self)
|
||||
-> Vec<DecisionVariable>` with default empty impl. Override it
|
||||
to provide pretty names / labels / units / bounds for the
|
||||
explorer; the default produces fallback `x[0]`, `x[1]`, … names.
|
||||
- New `DecisionVariable` type at `heuropt::core::DecisionVariable`,
|
||||
re-exported via the prelude. Builder methods: `with_label`,
|
||||
`with_unit`, `with_bounds`.
|
||||
|
||||
#### Algorithm metadata for the export header
|
||||
|
||||
- New `heuropt::traits::AlgorithmInfo` trait with `name() ->
|
||||
&'static str` (required) and `seed() -> Option<u64>` (default
|
||||
`None`). Every built-in algorithm — all 33 — implements it.
|
||||
Separate from `Optimizer<P>` so multi-fidelity algorithms
|
||||
(Hyperband, which uses `PartialProblem`) implement it uniformly.
|
||||
- `ExplorerExport::with_algorithm_info(&optimizer)` pulls the
|
||||
algorithm name and seed from this trait into the export's `run`
|
||||
metadata.
|
||||
|
||||
#### Worked example
|
||||
|
||||
- New `examples/pick_a_car.rs` (gated on `serde`). Implements the
|
||||
README's `PickACar` multi-objective problem with a fully
|
||||
enriched `decision_schema` and labelled / unit-tagged objectives,
|
||||
runs NSGA-III, and writes `pick_a_car.json` ready to drop into
|
||||
the explorer.
|
||||
|
||||
#### Documentation
|
||||
|
||||
- New cookbook recipe at `docs/book/src/cookbook/explorer.md`
|
||||
covering Problem enrichment, the export call, the JSON schema,
|
||||
and custom decision-type handling.
|
||||
|
||||
### Notes
|
||||
|
||||
- The explorer webapp itself lives in a separate repo
|
||||
(`heuropt-explorer`) on its own release cadence. The schema in
|
||||
`heuropt::explorer` is the contract between them; bumping
|
||||
`SCHEMA_VERSION` is reserved for breaking changes.
|
||||
- Phase 1 is additive only. No existing test breaks; the lib test
|
||||
count went from 229 to 242 (10 new explorer tests + 3 from the
|
||||
new `Objective` / `DecisionVariable` builders).
|
||||
|
||||
[0.9.0]: https://github.com/swaits/heuropt/releases/tag/v0.9.0
|
||||
|
||||
## [0.8.0] — 2026-05-06
|
||||
|
||||
Theme: async evaluation, plus the docs / governance / CI catch-up
|
||||
@@ -552,5 +697,5 @@ Initial release.
|
||||
`RandomSearch`, `Nsga2`, and `DifferentialEvolution`. Seeded runs stay
|
||||
bit-identical to serial mode.
|
||||
|
||||
[Unreleased]: https://github.com/swaits/heuropt/compare/v0.8.0...HEAD
|
||||
[Unreleased]: https://github.com/swaits/heuropt/compare/v0.10.0...HEAD
|
||||
[0.1.0]: https://github.com/swaits/heuropt/releases/tag/v0.1.0
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "heuropt"
|
||||
version = "0.9.0"
|
||||
version = "0.10.0"
|
||||
edition = "2024"
|
||||
rust-version = "1.85"
|
||||
authors = ["Stephen Waits <steve@waits.net>"]
|
||||
|
||||
@@ -12,7 +12,7 @@ sync `run` and an async `run_async`. One small set of traits. Bit-identical
|
||||
seeded determinism. No trait objects, no GATs, no generic-RNG plumbing in
|
||||
the public API.
|
||||
|
||||
If you can write a `Problem` impl and read `RandomSearch`, you can write your
|
||||
If you can write a `Problem` impl and read Random Search, you can write your
|
||||
own optimizer. That's the whole pitch.
|
||||
|
||||
Docs: [user guide](https://swaits.github.io/heuropt/) · [API reference](https://docs.rs/heuropt).
|
||||
@@ -21,7 +21,7 @@ Docs: [user guide](https://swaits.github.io/heuropt/) · [API reference](https:/
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
heuropt = "0.8"
|
||||
heuropt = "0.10"
|
||||
|
||||
# Optional features:
|
||||
# - "serde": derive Serialize/Deserialize on the core data types.
|
||||
@@ -30,7 +30,7 @@ heuropt = "0.8"
|
||||
# - "async": AsyncProblem / AsyncPartialProblem traits and a
|
||||
# run_async(&problem, concurrency).await method on
|
||||
# every algorithm — for IO-bound evaluations.
|
||||
# heuropt = { version = "0.8", features = ["serde", "parallel", "async"] }
|
||||
# heuropt = { version = "0.10", features = ["serde", "parallel", "async"] }
|
||||
```
|
||||
|
||||
## Define a problem and run an optimizer
|
||||
@@ -186,6 +186,32 @@ back in 0-60. The optimizer doesn't tell you what to buy — it
|
||||
hands you the frontier of *every defensible compromise* and lets
|
||||
you pick by your own priorities.
|
||||
|
||||
### Explore it interactively
|
||||
|
||||
Six hand-picked rows out of a hundred is a sample, not a search.
|
||||
With the `serde` feature enabled, the same result becomes one JSON
|
||||
file you can drop into the [heuropt-explorer](https://swaits.github.io/heuropt-explorer/)
|
||||
webapp to browse interactively — parallel coordinates, scatter,
|
||||
range filters, weighted ranking:
|
||||
|
||||
```rust,ignore
|
||||
heuropt::explorer::ExplorerExport::from_result(&PickACar, &result)
|
||||
.with_algorithm_info(&optimizer)
|
||||
.with_problem_name("Pick a car")
|
||||
.to_file("results.json")?;
|
||||
```
|
||||
|
||||
The full worked example (which produces this output verbatim) is at
|
||||
`examples/pick_a_car.rs`:
|
||||
|
||||
```text
|
||||
cargo run --release --example pick_a_car --features serde
|
||||
```
|
||||
|
||||
See the [Explore your results](https://swaits.github.io/heuropt/cookbook/explorer.html)
|
||||
cookbook recipe for the export schema and how to enrich your `Problem`
|
||||
with display labels and units.
|
||||
|
||||
## Implement a custom optimizer
|
||||
|
||||
A new optimizer is just an implementation of `Optimizer<P>`:
|
||||
@@ -288,12 +314,12 @@ you need a **sample-efficient** or **multi-fidelity** approach:
|
||||
|
||||
- **Cheap (1k+ evals affordable):** any of the population-based
|
||||
algorithms — DE, GA, CMA-ES, NSGA-II, etc.
|
||||
- **Expensive (50–500 evals):** `BayesianOpt` (Gaussian-process
|
||||
surrogate + Expected Improvement) or `Tpe` (Parzen-density
|
||||
- **Expensive (50–500 evals):** Bayesian Optimization (Gaussian-process
|
||||
surrogate + Expected Improvement) or TPE (Parzen-density
|
||||
surrogate, cheaper per step, more robust without hyperparameter
|
||||
tuning).
|
||||
- **Multi-fidelity (each eval has a tunable budget — epochs, sim
|
||||
steps, MC samples):** `Hyperband`. Implement the `PartialProblem`
|
||||
steps, MC samples):** Hyperband. Implement the `PartialProblem`
|
||||
trait on your problem and Hyperband allocates compute aggressively
|
||||
across promising configs.
|
||||
|
||||
@@ -339,12 +365,12 @@ START
|
||||
│ │
|
||||
│ ├─ Yes → sample-efficient regime
|
||||
│ │ ├─ Standard expensive black-box, single-objective
|
||||
│ │ │ → BayesianOpt (GP + Expected Improvement; gold
|
||||
│ │ │ → Bayesian Optimization (GP + Expected Improvement; gold
|
||||
│ │ │ standard *with* per-problem kernel
|
||||
│ │ │ tuning. The default RBF kernel at
|
||||
│ │ │ 60 evals is honestly bad — give it
|
||||
│ │ │ more evals or tune the kernel.)
|
||||
│ │ │ → Tpe (KDE-based; cheaper per-step,
|
||||
│ │ │ → TPE (KDE-based; cheaper per-step,
|
||||
│ │ │ more robust without tuning)
|
||||
│ │ │
|
||||
│ │ └─ Each eval has a tunable fidelity (epochs, sim steps, …)
|
||||
@@ -359,20 +385,20 @@ START
|
||||
│ │
|
||||
│ ├─ Decision is Vec<f64> (continuous)
|
||||
│ │ ├─ Smooth landscape (well-conditioned)
|
||||
│ │ │ → CmaEs (full-cov adaptive Gaussian)
|
||||
│ │ │ → SeparableNes (cheaper diag-cov; high-dim)
|
||||
│ │ │ → NelderMead (low-dim, deterministic, simple)
|
||||
│ │ │ → CMA-ES (full-cov adaptive Gaussian)
|
||||
│ │ │ → sNES (cheaper diag-cov; high-dim)
|
||||
│ │ │ → Nelder-Mead (low-dim, deterministic, simple)
|
||||
│ │ ├─ Multimodal landscape
|
||||
│ │ │ → IpopCmaEs (CMA-ES with restart;
|
||||
│ │ │ → IPOP-CMA-ES (CMA-ES with restart;
|
||||
│ │ │ fixes vanilla CMA-ES's
|
||||
│ │ │ multimodal failure)
|
||||
│ │ │ → Differential Evolution (rarely beaten on cheap
|
||||
│ │ │ multimodal continuous)
|
||||
│ │ │ → Simulated Annealing (cheap & generic)
|
||||
│ │ ├─ Want parameter-free (no F, CR, w, σ to tune)
|
||||
│ │ │ → Tlbo
|
||||
│ │ │ → TLBO
|
||||
│ │ ├─ Want minimum self-adapting baseline
|
||||
│ │ │ → OnePlusOneEs (one-fifth rule,
|
||||
│ │ │ → (1+1)-ES (one-fifth rule,
|
||||
│ │ │ smallest possible ES)
|
||||
│ │ ├─ Just want a strong default for cheap continuous
|
||||
│ │ │ → Differential Evolution
|
||||
@@ -381,13 +407,13 @@ START
|
||||
│ │
|
||||
│ ├─ Decision is Vec<bool> (binary)
|
||||
│ │ ├─ Independent bits, smooth fitness
|
||||
│ │ │ → Umda (per-bit marginal EDA)
|
||||
│ │ │ → UMDA (per-bit marginal EDA)
|
||||
│ │ └─ Bit interactions matter
|
||||
│ │ → GeneticAlgorithm with BitFlipMutation +
|
||||
│ │ → GA with BitFlipMutation +
|
||||
│ │ a bit-string crossover
|
||||
│ │
|
||||
│ ├─ Decision is Vec<usize> (permutation, e.g., TSP)
|
||||
│ │ → AntColonyTsp (with a distance matrix)
|
||||
│ │ → Ant Colony (with a distance matrix)
|
||||
│ │ → Tabu Search (with your own neighbor function)
|
||||
│ │ → Simulated Annealing with SwapMutation
|
||||
│ │
|
||||
@@ -398,21 +424,21 @@ START
|
||||
├─ 2 or 3 (multi-objective)
|
||||
│ │
|
||||
│ ├─ Strong default, fast, well-understood
|
||||
│ │ → Nsga2
|
||||
│ │ → NSGA-II
|
||||
│ │
|
||||
│ ├─ Real-valued, smooth front, want best convergence
|
||||
│ │ → Mopso (multi-objective PSO; on the benches
|
||||
│ │ → MOPSO (multi-objective PSO; on the benches
|
||||
│ │ here it wins ZDT1 on both HV and
|
||||
│ │ convergence by 100× over the
|
||||
│ │ dominance-based methods)
|
||||
│ │
|
||||
│ ├─ Want better front quality than NSGA-II
|
||||
│ │ → Ibea (indicator-based; consistently the best
|
||||
│ │ → IBEA (indicator-based; consistently the best
|
||||
│ │ of the dominance-based methods on these
|
||||
│ │ benches — wins ZDT3 HV and DTLZ2 mean
|
||||
│ │ dist by 24×)
|
||||
│ │ → Spea2 (strength + density)
|
||||
│ │ → SmsEmoa (hypervolume-contribution selection;
|
||||
│ │ → SPEA2 (strength + density)
|
||||
│ │ → SMS-EMOA (hypervolume-contribution selection;
|
||||
│ │ elegant in theory but underperforms
|
||||
│ │ NSGA-II on these benches at our budgets —
|
||||
│ │ only worth its higher per-step cost on
|
||||
@@ -420,42 +446,42 @@ START
|
||||
│ │ the right discriminator)
|
||||
│ │
|
||||
│ ├─ Want decomposition / weight-vector style
|
||||
│ │ → Moead (very fast per generation, scales well)
|
||||
│ │ → MOEA/D (very fast per generation, scales well)
|
||||
│ │
|
||||
│ ├─ Disconnected or non-convex front
|
||||
│ │ → AgeMoea (estimates front geometry adaptively)
|
||||
│ │ → Knea (favors knee points)
|
||||
│ │ → Ibea
|
||||
│ │ → AGE-MOEA (estimates front geometry adaptively)
|
||||
│ │ → KnEA (favors knee points)
|
||||
│ │ → IBEA
|
||||
│ │
|
||||
│ ├─ Want region-based diversity
|
||||
│ │ → PesaII (grid hyperboxes drive selection)
|
||||
│ │ → EpsilonMoea (ε-grid archive,
|
||||
│ │ → PESA-II (grid hyperboxes drive selection)
|
||||
│ │ → ε-MOEA (ε-grid archive,
|
||||
│ │ archive size auto-limits)
|
||||
│ │
|
||||
│ └─ Just one starting decision (no population budget)
|
||||
│ → Paes (1+1 ES with a Pareto archive)
|
||||
│ → PAES (1+1 ES with a Pareto archive)
|
||||
│
|
||||
└─ 4+ (many-objective)
|
||||
│
|
||||
├─ Linear / simplex-shaped front (e.g., DTLZ1)
|
||||
│ → Grea (grid coords drive ranking; on DTLZ1
|
||||
│ → GrEA (grid coords drive ranking; on DTLZ1
|
||||
│ here it beats NSGA-III by 3× and
|
||||
│ AGE-MOEA by 2.5×)
|
||||
│ → Moead (decomposition shines on linear fronts;
|
||||
│ → MOEA/D (decomposition shines on linear fronts;
|
||||
│ second on DTLZ1, also among the
|
||||
│ fastest per generation)
|
||||
│
|
||||
├─ Curved / unknown front geometry
|
||||
│ → Nsga3 (reference-point niching, canonical;
|
||||
│ → NSGA-III (reference-point niching, canonical;
|
||||
│ a strong default when the front
|
||||
│ isn't simplex-shaped)
|
||||
│ → AgeMoea (estimates L_p geometry per generation)
|
||||
│ → Rvea (reference vectors with adaptive penalty)
|
||||
│ → AGE-MOEA (estimates L_p geometry per generation)
|
||||
│ → RVEA (reference vectors with adaptive penalty)
|
||||
│
|
||||
├─ Want indicator-based selection
|
||||
│ → Ibea (additive ε-indicator; doesn't degrade
|
||||
│ → IBEA (additive ε-indicator; doesn't degrade
|
||||
│ at high obj count)
|
||||
│ → Hype (Monte Carlo HV estimation; scales
|
||||
│ → HypE (Monte Carlo HV estimation; scales
|
||||
│ to arbitrary M)
|
||||
```
|
||||
|
||||
@@ -465,54 +491,54 @@ START
|
||||
|
||||
| Algorithm | Objectives | Decision | Strengths |
|
||||
|---|---|---|---|
|
||||
| `BayesianOpt` | 1 | `Vec<f64>` | GP surrogate + EI; gold standard *with* per-problem kernel tuning (default RBF at 60 evals is honestly bad) |
|
||||
| `Tpe` | 1 | `Vec<f64>` | KDE surrogate; robust without hyperparameter tuning |
|
||||
| `Hyperband` | 1 | any | multi-fidelity; needs `PartialProblem` |
|
||||
| **Bayesian Optimization** | 1 | `Vec<f64>` | GP surrogate + EI; gold standard *with* per-problem kernel tuning (default RBF at 60 evals is honestly bad) |
|
||||
| **TPE** | 1 | `Vec<f64>` | KDE surrogate; robust without hyperparameter tuning |
|
||||
| **Hyperband** | 1 | any | multi-fidelity; needs `PartialProblem` |
|
||||
|
||||
**Single-objective continuous (`Vec<f64>`):**
|
||||
|
||||
| Algorithm | Strengths |
|
||||
|---|---|
|
||||
| `RandomSearch` | sanity baseline |
|
||||
| `HillClimber` | simplest greedy local search |
|
||||
| `OnePlusOneEs` | one-fifth-rule self-adapting baseline |
|
||||
| `SimulatedAnnealing` | escapes local optima |
|
||||
| `GeneticAlgorithm` | classic SO GA with elitism |
|
||||
| `ParticleSwarm` | simple swarm baseline |
|
||||
| `DifferentialEvolution` | strong default for cheap continuous |
|
||||
| `Tlbo` | parameter-free (no F, CR, w, σ) |
|
||||
| `CmaEs` | smooth landscapes; full covariance |
|
||||
| `IpopCmaEs` | CMA-ES + restart for multimodal |
|
||||
| `SeparableNes` | diagonal-cov NES; cheap per-step |
|
||||
| `NelderMead` | classical simplex; deterministic |
|
||||
| **Random Search** | sanity baseline |
|
||||
| **Hill Climber** | simplest greedy local search |
|
||||
| **(1+1)-ES** | one-fifth-rule self-adapting baseline |
|
||||
| **Simulated Annealing** | escapes local optima |
|
||||
| **GA** | classic SO GA with elitism |
|
||||
| **PSO** | simple swarm baseline |
|
||||
| **Differential Evolution** | strong default for cheap continuous |
|
||||
| **TLBO** | parameter-free (no F, CR, w, σ) |
|
||||
| **CMA-ES** | smooth landscapes; full covariance |
|
||||
| **IPOP-CMA-ES** | CMA-ES + restart for multimodal |
|
||||
| **sNES** | diagonal-cov NES; cheap per-step |
|
||||
| **Nelder-Mead** | classical simplex; deterministic |
|
||||
|
||||
**Single-objective other decision types:**
|
||||
|
||||
| Algorithm | Decision | Strengths |
|
||||
|---|---|---|
|
||||
| `Umda` | `Vec<bool>` | independent-bit EDA |
|
||||
| `TabuSearch` | any | discrete, you supply neighbors |
|
||||
| `AntColonyTsp` | `Vec<usize>` | TSP / permutation |
|
||||
| **UMDA** | `Vec<bool>` | independent-bit EDA |
|
||||
| **Tabu Search** | any | discrete, you supply neighbors |
|
||||
| **Ant Colony** | `Vec<usize>` | TSP / permutation |
|
||||
|
||||
**Multi-objective (2–3) and many-objective (4+):**
|
||||
|
||||
| Algorithm | Objectives | Strengths |
|
||||
|---|---|---|
|
||||
| `Paes` | 2–3 | 1+1 ES with Pareto archive |
|
||||
| `Nsga2` | 2–3 | canonical Pareto-based EA |
|
||||
| `Spea2` | 2–3 | strength + density |
|
||||
| `Mopso` | 2–3 | multi-objective PSO; best convergence on smooth real-valued 2-obj fronts |
|
||||
| `Ibea` | 2+ | indicator-based; consistently best of the dominance-based methods |
|
||||
| `SmsEmoa` | 2+ | exact HV-contribution selection; high per-step cost, modest gain |
|
||||
| `Hype` | 2+ | Monte Carlo HV estimation |
|
||||
| `EpsilonMoea` | 2+ | ε-grid archive; auto-sized |
|
||||
| `PesaII` | 2+ | grid-based region selection |
|
||||
| `AgeMoea` | 2+ | adaptive front-geometry estimation |
|
||||
| `Knea` | 2+ | knee-point favored survival |
|
||||
| `Moead` | 2+ | decomposition; fast per-gen |
|
||||
| `Nsga3` | 4+ | reference-point niching; strong on curved fronts |
|
||||
| `Rvea` | 4+ | reference vectors with penalty |
|
||||
| `Grea` | 4+ | grid coords drive selection; particularly strong on linear/simplex fronts |
|
||||
| **PAES** | 2–3 | 1+1 ES with Pareto archive |
|
||||
| **NSGA-II** | 2–3 | canonical Pareto-based EA |
|
||||
| **SPEA2** | 2–3 | strength + density |
|
||||
| **MOPSO** | 2–3 | multi-objective PSO; best convergence on smooth real-valued 2-obj fronts |
|
||||
| **IBEA** | 2+ | indicator-based; consistently best of the dominance-based methods |
|
||||
| **SMS-EMOA** | 2+ | exact HV-contribution selection; high per-step cost, modest gain |
|
||||
| **HypE** | 2+ | Monte Carlo HV estimation |
|
||||
| **ε-MOEA** | 2+ | ε-grid archive; auto-sized |
|
||||
| **PESA-II** | 2+ | grid-based region selection |
|
||||
| **AGE-MOEA** | 2+ | adaptive front-geometry estimation |
|
||||
| **KnEA** | 2+ | knee-point favored survival |
|
||||
| **MOEA/D** | 2+ | decomposition; fast per-gen |
|
||||
| **NSGA-III** | 4+ | reference-point niching; strong on curved fronts |
|
||||
| **RVEA** | 4+ | reference vectors with penalty |
|
||||
| **GrEA** | 4+ | grid coords drive selection; particularly strong on linear/simplex fronts |
|
||||
|
||||
## Current algorithms
|
||||
|
||||
@@ -520,48 +546,48 @@ The full list with one-line descriptions:
|
||||
|
||||
**Sample-efficient / multi-fidelity:**
|
||||
|
||||
- `BayesianOpt` — Gaussian-process surrogate + Expected Improvement.
|
||||
- `Tpe` — Bergstra et al. 2011 Tree-structured Parzen Estimator.
|
||||
- `Hyperband` — Li et al. 2017 multi-fidelity (uses `PartialProblem`).
|
||||
- **Bayesian Optimization** — Gaussian-process surrogate + Expected Improvement.
|
||||
- **TPE** — Bergstra et al. 2011 Tree-structured Parzen Estimator.
|
||||
- **Hyperband** — Li et al. 2017 multi-fidelity (uses `PartialProblem`).
|
||||
|
||||
**Single-objective:**
|
||||
|
||||
- `RandomSearch` — sample-evaluate-keep baseline.
|
||||
- `HillClimber` — greedy single-step local search.
|
||||
- `OnePlusOneEs` — Rechenberg 1973 (1+1)-ES with one-fifth rule.
|
||||
- `SimulatedAnnealing` — Kirkpatrick et al. 1983, generic over decision type.
|
||||
- `TabuSearch` — Glover 1986, with a user-supplied neighbor generator.
|
||||
- `GeneticAlgorithm` — generational GA with tournament selection + elitism.
|
||||
- `ParticleSwarm` — Eberhart & Kennedy 1995 PSO for `Vec<f64>`.
|
||||
- `DifferentialEvolution` — Storn & Price DE/rand/1/bin for `Vec<f64>`.
|
||||
- `Tlbo` — Rao 2011 Teaching-Learning-Based Optimization (parameter-free).
|
||||
- `CmaEs` — Hansen & Ostermeier 2001 covariance-matrix adaptation.
|
||||
- `IpopCmaEs` — Auger & Hansen 2005 CMA-ES with restart, for multimodal.
|
||||
- `SeparableNes` — Wierstra et al. 2008/2014 diagonal-cov NES.
|
||||
- `NelderMead` — Nelder & Mead 1965 simplex direct search.
|
||||
- `Umda` — Mühlenbein 1997 univariate marginal-distribution EDA for `Vec<bool>`.
|
||||
- `AntColonyTsp` — Dorigo Ant System for permutation problems.
|
||||
- **Random Search** — sample-evaluate-keep baseline.
|
||||
- **Hill Climber** — greedy single-step local search.
|
||||
- **(1+1)-ES** — Rechenberg 1973 (1+1)-ES with one-fifth rule.
|
||||
- **Simulated Annealing** — Kirkpatrick et al. 1983, generic over decision type.
|
||||
- **Tabu Search** — Glover 1986, with a user-supplied neighbor generator.
|
||||
- **GA** — generational GA with tournament selection + elitism.
|
||||
- **PSO** — Eberhart & Kennedy 1995 PSO for `Vec<f64>`.
|
||||
- **Differential Evolution** — Storn & Price DE/rand/1/bin for `Vec<f64>`.
|
||||
- **TLBO** — Rao 2011 Teaching-Learning-Based Optimization (parameter-free).
|
||||
- **CMA-ES** — Hansen & Ostermeier 2001 covariance-matrix adaptation.
|
||||
- **IPOP-CMA-ES** — Auger & Hansen 2005 CMA-ES with restart, for multimodal.
|
||||
- **sNES** — Wierstra et al. 2008/2014 diagonal-cov NES.
|
||||
- **Nelder-Mead** — Nelder & Mead 1965 simplex direct search.
|
||||
- **UMDA** — Mühlenbein 1997 univariate marginal-distribution EDA for `Vec<bool>`.
|
||||
- **Ant Colony** — Dorigo Ant System for permutation problems.
|
||||
|
||||
**Multi-objective:**
|
||||
|
||||
- `Paes` — Knowles & Corne 1999 Pareto Archived Evolution Strategy.
|
||||
- `Nsga2` — Deb et al. 2002, the canonical Pareto-based EA.
|
||||
- `Spea2` — Zitzler, Laumanns & Thiele 2001 strength-Pareto EA.
|
||||
- `Moead` — Zhang & Li 2007 decomposition-based MOEA with Tchebycheff scalarization.
|
||||
- `Mopso` — Coello, Pulido & Lechuga 2004 multi-objective PSO.
|
||||
- `Ibea` — Zitzler & Künzli 2004 indicator-based EA.
|
||||
- `SmsEmoa` — Beume, Naujoks & Emmerich 2007 hypervolume-selection EMOA.
|
||||
- `Hype` — Bader & Zitzler 2011 Hypervolume Estimation Algorithm.
|
||||
- `EpsilonMoea` — Deb, Mohan & Mishra 2003 ε-dominance MOEA.
|
||||
- `PesaII` — Corne et al. 2001 Pareto Envelope Selection II.
|
||||
- `AgeMoea` — Panichella 2019 Adaptive Geometry Estimation MOEA.
|
||||
- `Knea` — Zhang, Tian & Jin 2015 Knee point-driven EA.
|
||||
- **PAES** — Knowles & Corne 1999 Pareto Archived Evolution Strategy.
|
||||
- **NSGA-II** — Deb et al. 2002, the canonical Pareto-based EA.
|
||||
- **SPEA2** — Zitzler, Laumanns & Thiele 2001 strength-Pareto EA.
|
||||
- **MOEA/D** — Zhang & Li 2007 decomposition-based MOEA with Tchebycheff scalarization.
|
||||
- **MOPSO** — Coello, Pulido & Lechuga 2004 multi-objective PSO.
|
||||
- **IBEA** — Zitzler & Künzli 2004 indicator-based EA.
|
||||
- **SMS-EMOA** — Beume, Naujoks & Emmerich 2007 hypervolume-selection EMOA.
|
||||
- **HypE** — Bader & Zitzler 2011 Hypervolume Estimation Algorithm.
|
||||
- **ε-MOEA** — Deb, Mohan & Mishra 2003 ε-dominance MOEA.
|
||||
- **PESA-II** — Corne et al. 2001 Pareto Envelope Selection II.
|
||||
- **AGE-MOEA** — Panichella 2019 Adaptive Geometry Estimation MOEA.
|
||||
- **KnEA** — Zhang, Tian & Jin 2015 Knee point-driven EA.
|
||||
|
||||
**Many-objective (4+):**
|
||||
|
||||
- `Nsga3` — Deb & Jain 2014 reference-point NSGA-III.
|
||||
- `Rvea` — Cheng et al. 2016 Reference Vector-guided EA.
|
||||
- `Grea` — Yang et al. 2013 Grid-based EA.
|
||||
- **NSGA-III** — Deb & Jain 2014 reference-point NSGA-III.
|
||||
- **RVEA** — Cheng et al. 2016 Reference Vector-guided EA.
|
||||
- **GrEA** — Yang et al. 2013 Grid-based EA.
|
||||
|
||||
**Reusable utilities:** `pareto_compare`, `pareto_front`, `best_candidate`,
|
||||
`non_dominated_sort`, `crowding_distance`, `ParetoArchive`, `das_dennis`,
|
||||
@@ -576,7 +602,7 @@ and the metrics `spacing` and `hypervolume_2d`.
|
||||
user-facing APIs, no generic-RNG plumbing — `Rng` is a single concrete type
|
||||
alias.
|
||||
- **Readable algorithms.** Built-ins are written for clarity, not maximum
|
||||
abstraction reuse. `RandomSearch` is the recommended file to read before
|
||||
abstraction reuse. Random Search is the recommended file to read before
|
||||
writing your own optimizer.
|
||||
- **One crate first.** No premature splitting into `-core`/`-algorithms`/
|
||||
`-operators`. Split later if the crate grows.
|
||||
|
||||
+2
-2
@@ -8,8 +8,8 @@ needed.
|
||||
|
||||
| Version | Supported |
|
||||
|---------|--------------------|
|
||||
| 0.8.x | ✅ |
|
||||
| ≤ 0.7.x | ❌ (please upgrade) |
|
||||
| 0.10.x | ✅ |
|
||||
| ≤ 0.9.x | ❌ (please upgrade) |
|
||||
|
||||
heuropt is pre-1.0; the public API may change between minor versions.
|
||||
Once 1.0.0 ships, the support window will be at least the latest two
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,11 +64,11 @@ 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,
|
||||
DE, PSO, GA, TLBO, (1+1)-ES, Nelder-Mead, Random Search, Hill Climber,
|
||||
Simulated Annealing) covers the canonical baselines and several modern
|
||||
variants.
|
||||
|
||||
|
||||
@@ -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 50–500-eval
|
||||
— Bayesian Optimization, TPE, and Hyperband for the 50–500-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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 (2–3): `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 (2–3): 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,
|
||||
|
||||
@@ -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;
|
||||
@@ -115,7 +179,7 @@ existing call sites need a `.. CmaEsConfig { initial_mean: None,
|
||||
### From 0.1.x
|
||||
|
||||
**Additive.** New algorithms across the catalog (Hill Climber, SA,
|
||||
GA, PSO, CMA-ES, TabuSearch, AntColonyTsp, Umda, TLBO, MOPSO, IBEA,
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -426,7 +426,10 @@ fn estimate_p(front_indices: &[usize], translated: &[Vec<f64>], m: usize) -> f64
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for AgeMoea<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"AgeMoea"
|
||||
"AGE-MOEA"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Adaptive Geometry Estimation Multi-Objective Evolutionary Algorithm"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -431,7 +431,10 @@ fn better_than_so(
|
||||
|
||||
impl crate::traits::AlgorithmInfo for AntColonyTsp {
|
||||
fn name(&self) -> &'static str {
|
||||
"AntColonyTsp"
|
||||
"Ant Colony"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Ant Colony System for TSP"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -542,7 +542,10 @@ impl BayesianOpt {
|
||||
|
||||
impl crate::traits::AlgorithmInfo for BayesianOpt {
|
||||
fn name(&self) -> &'static str {
|
||||
"BayesianOpt"
|
||||
"Bayesian Optimization"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Gaussian Process Bayesian Optimization with Expected Improvement"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -630,7 +630,10 @@ fn better_than_so(
|
||||
|
||||
impl crate::traits::AlgorithmInfo for CmaEs {
|
||||
fn name(&self) -> &'static str {
|
||||
"CmaEs"
|
||||
"CMA-ES"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Covariance Matrix Adaptation Evolution Strategy"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -305,6 +305,9 @@ fn pick_three_distinct(
|
||||
|
||||
impl crate::traits::AlgorithmInfo for DifferentialEvolution {
|
||||
fn name(&self) -> &'static str {
|
||||
"DE"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Differential Evolution"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
|
||||
@@ -398,7 +398,10 @@ fn box_dominates(a: &[i64], b: &[i64]) -> bool {
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for EpsilonMoea<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"EpsilonMoea"
|
||||
"ε-MOEA"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"ε-dominance Multi-Objective Evolutionary Algorithm"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -319,6 +319,9 @@ fn compare_for_fitness<D>(
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for GeneticAlgorithm<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"GA"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Genetic Algorithm"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
|
||||
@@ -336,7 +336,10 @@ fn environmental_selection<D: Clone>(
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for Grea<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"Grea"
|
||||
"GrEA"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Grid-based Evolutionary Algorithm"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -228,6 +228,9 @@ impl<I, V> crate::traits::AlgorithmInfo for HillClimber<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"Hill Climber"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Hill Climbing"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
}
|
||||
|
||||
@@ -461,7 +461,10 @@ fn binary_tournament(fitness: &[f64], rng: &mut Rng) -> usize {
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for Hype<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"Hype"
|
||||
"HypE"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Hypervolume Estimation Algorithm"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -337,6 +337,9 @@ where
|
||||
fn name(&self) -> &'static str {
|
||||
"Hyperband"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Hyperband multi-fidelity bandit search"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
}
|
||||
|
||||
@@ -387,7 +387,10 @@ fn binary_tournament(fitness: &[f64], rng: &mut Rng) -> usize {
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for Ibea<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"Ibea"
|
||||
"IBEA"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Indicator-Based Evolutionary Algorithm"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -289,7 +289,10 @@ fn better(a: &Evaluation, b: &Evaluation, direction: Direction) -> bool {
|
||||
|
||||
impl crate::traits::AlgorithmInfo for IpopCmaEs {
|
||||
fn name(&self) -> &'static str {
|
||||
"IpopCmaEs"
|
||||
"IPOP-CMA-ES"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Increasing-Population CMA-ES with Restarts"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -330,7 +330,10 @@ fn perpendicular_distance(point: &[f64], extremes: &[usize], oriented: &[Vec<f64
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for Knea<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"Knea"
|
||||
"KnEA"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Knee point-driven Evolutionary Algorithm"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -365,7 +365,10 @@ fn weight_distance(a: &[f64], b: &[f64]) -> f64 {
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for Moead<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"Moead"
|
||||
"MOEA/D"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Multi-Objective Evolutionary Algorithm based on Decomposition"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -332,7 +332,10 @@ impl Mopso {
|
||||
|
||||
impl crate::traits::AlgorithmInfo for Mopso {
|
||||
fn name(&self) -> &'static str {
|
||||
"Mopso"
|
||||
"MOPSO"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Multi-Objective Particle Swarm Optimization"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -452,7 +452,10 @@ impl NelderMead {
|
||||
|
||||
impl crate::traits::AlgorithmInfo for NelderMead {
|
||||
fn name(&self) -> &'static str {
|
||||
"NelderMead"
|
||||
"Nelder-Mead"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Nelder-Mead simplex direct search"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -366,7 +366,10 @@ fn binary_tournament<D>(entries: &[Nsga2Entry<D>], rng: &mut Rng) -> usize {
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for Nsga2<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"Nsga2"
|
||||
"NSGA-II"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Non-dominated Sorting Genetic Algorithm II"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -544,7 +544,10 @@ fn associate(
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for Nsga3<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"Nsga3"
|
||||
"NSGA-III"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Non-dominated Sorting Genetic Algorithm III"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -287,7 +287,10 @@ impl OnePlusOneEs {
|
||||
|
||||
impl crate::traits::AlgorithmInfo for OnePlusOneEs {
|
||||
fn name(&self) -> &'static str {
|
||||
"OnePlusOneEs"
|
||||
"(1+1)-ES"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"(1+1) Evolution Strategy with one-fifth success rule"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -244,7 +244,10 @@ impl<I, V> Paes<I, V> {
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for Paes<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"Paes"
|
||||
"PAES"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Pareto Archived Evolution Strategy"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -359,7 +359,10 @@ fn best_index(values: &[f64], direction: Direction) -> usize {
|
||||
|
||||
impl crate::traits::AlgorithmInfo for ParticleSwarm {
|
||||
fn name(&self) -> &'static str {
|
||||
"ParticleSwarm"
|
||||
"PSO"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Particle Swarm Optimization"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -411,7 +411,10 @@ fn truncate_by_grid<D: Clone>(archive: &mut ParetoArchive<D>, max_size: usize, d
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for PesaII<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"PesaII"
|
||||
"PESA-II"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Pareto Envelope-based Selection Algorithm II"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -468,7 +468,10 @@ fn smallest_neighbor_angle(references: &[Vec<f64>]) -> f64 {
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for Rvea<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"Rvea"
|
||||
"RVEA"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Reference Vector-guided Evolutionary Algorithm"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -291,7 +291,10 @@ fn pick_drop_index<D>(
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for SmsEmoa<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"SmsEmoa"
|
||||
"SMS-EMOA"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"S-Metric Selection Evolutionary Multi-Objective Algorithm"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -391,7 +391,10 @@ fn better(a: &Evaluation, b: &Evaluation, direction: Direction) -> bool {
|
||||
|
||||
impl crate::traits::AlgorithmInfo for SeparableNes {
|
||||
fn name(&self) -> &'static str {
|
||||
"SeparableNes"
|
||||
"sNES"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Separable Natural Evolution Strategy"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -505,7 +505,10 @@ fn binary_tournament(fitness: &[f64], rng: &mut Rng) -> usize {
|
||||
|
||||
impl<I, V> crate::traits::AlgorithmInfo for Spea2<I, V> {
|
||||
fn name(&self) -> &'static str {
|
||||
"Spea2"
|
||||
"SPEA2"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Strength Pareto Evolutionary Algorithm 2"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -327,7 +327,10 @@ fn better(a: &Evaluation, b: &Evaluation, direction: Direction) -> bool {
|
||||
|
||||
impl crate::traits::AlgorithmInfo for Tlbo {
|
||||
fn name(&self) -> &'static str {
|
||||
"Tlbo"
|
||||
"TLBO"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Teaching-Learning-Based Optimization"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -481,7 +481,10 @@ impl Tpe {
|
||||
|
||||
impl crate::traits::AlgorithmInfo for Tpe {
|
||||
fn name(&self) -> &'static str {
|
||||
"Tpe"
|
||||
"TPE"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Tree-structured Parzen Estimator"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
@@ -354,7 +354,10 @@ fn better_than_so(
|
||||
|
||||
impl crate::traits::AlgorithmInfo for Umda {
|
||||
fn name(&self) -> &'static str {
|
||||
"Umda"
|
||||
"UMDA"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Univariate Marginal Distribution Algorithm"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(self.config.seed)
|
||||
|
||||
+19
-4
@@ -101,10 +101,16 @@ pub struct RunMeta {
|
||||
/// Optional human-readable problem name (e.g. `"Pick a car"`).
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub problem_name: Option<String>,
|
||||
/// Canonical algorithm name (e.g. `"Nsga3"`). Pulled from
|
||||
/// [`AlgorithmInfo::name`] when an algorithm is provided.
|
||||
/// Canonical short algorithm name (e.g. `"NSGA-III"`). Pulled
|
||||
/// from [`AlgorithmInfo::name`] when an algorithm is provided.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub algorithm: Option<String>,
|
||||
/// Academic long form (e.g. `"Non-dominated Sorting Genetic
|
||||
/// Algorithm III"`). Pulled from [`AlgorithmInfo::full_name`]
|
||||
/// when an algorithm is provided. Display tools render this
|
||||
/// as a tooltip / aria-label on the short name.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub algorithm_full_name: Option<String>,
|
||||
/// Seed driving this run, if applicable. Pulled from
|
||||
/// [`AlgorithmInfo::seed`].
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
@@ -216,10 +222,12 @@ impl ExplorerExport {
|
||||
}
|
||||
}
|
||||
|
||||
/// Populate `algorithm` and `seed` from anything implementing
|
||||
/// [`AlgorithmInfo`] — every built-in algorithm does.
|
||||
/// Populate `algorithm`, `algorithm_full_name`, and `seed`
|
||||
/// from anything implementing [`AlgorithmInfo`] — every
|
||||
/// built-in algorithm does.
|
||||
pub fn with_algorithm_info<A: AlgorithmInfo>(mut self, algorithm: &A) -> Self {
|
||||
self.run.algorithm = Some(algorithm.name().to_owned());
|
||||
self.run.algorithm_full_name = Some(algorithm.full_name().to_owned());
|
||||
self.run.seed = algorithm.seed();
|
||||
self
|
||||
}
|
||||
@@ -412,6 +420,9 @@ mod tests {
|
||||
fn name(&self) -> &'static str {
|
||||
"DummyAlgo"
|
||||
}
|
||||
fn full_name(&self) -> &'static str {
|
||||
"Dummy Test Algorithm"
|
||||
}
|
||||
fn seed(&self) -> Option<u64> {
|
||||
Some(123)
|
||||
}
|
||||
@@ -513,6 +524,10 @@ mod tests {
|
||||
let result = make_result(vec![vec![0.0, 1.0]], |d| d.to_vec());
|
||||
let export = ExplorerExport::from_result(&problem, &result).with_algorithm_info(&DummyAlgo);
|
||||
assert_eq!(export.run.algorithm.as_deref(), Some("DummyAlgo"));
|
||||
assert_eq!(
|
||||
export.run.algorithm_full_name.as_deref(),
|
||||
Some("Dummy Test Algorithm"),
|
||||
);
|
||||
assert_eq!(export.run.seed, Some(123));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +1,45 @@
|
||||
//! Lightweight metadata about an algorithm — its short canonical name
|
||||
//! and the seed driving the current run.
|
||||
//! Lightweight metadata about an algorithm — its canonical short
|
||||
//! name, an academic long name, and the seed driving the current
|
||||
//! run.
|
||||
//!
|
||||
//! `AlgorithmInfo` is separate from [`Optimizer<P>`](super::Optimizer)
|
||||
//! so multi-fidelity algorithms (which use `PartialProblem` instead of
|
||||
//! `Problem`) can implement it uniformly. Every built-in algorithm in
|
||||
//! `heuropt` implements `AlgorithmInfo`; the explorer JSON export reads
|
||||
//! these methods to populate `algorithm` and `seed` fields in the
|
||||
//! exported run metadata.
|
||||
//! so multi-fidelity algorithms (which use `PartialProblem` instead
|
||||
//! of `Problem`) can implement it uniformly. Every built-in
|
||||
//! algorithm in `heuropt` implements `AlgorithmInfo`; the explorer
|
||||
//! JSON export reads these methods to populate the `algorithm` and
|
||||
//! `algorithm_full_name` fields in the exported run metadata.
|
||||
|
||||
/// Algorithm metadata used by tooling such as the explorer JSON export.
|
||||
/// Algorithm metadata used by tooling such as the explorer JSON
|
||||
/// export.
|
||||
///
|
||||
/// Implementors return a short canonical name like `"Nsga3"` or
|
||||
/// `"DifferentialEvolution"`, and the seed driving their current run
|
||||
/// when applicable.
|
||||
/// Implementors return:
|
||||
/// - **`name`** — the canonical short display name as it appears
|
||||
/// in the literature: `"NSGA-II"`, `"MOEA/D"`, `"ε-MOEA"`,
|
||||
/// `"CMA-ES"`. *Not* the Rust type name.
|
||||
/// - **`full_name`** — the academic long form, e.g.
|
||||
/// `"Non-dominated Sorting Genetic Algorithm II"`. Defaults to
|
||||
/// `name()` when not overridden, which is the right answer for
|
||||
/// algorithms whose short name *is* their full name (Random
|
||||
/// Search, Hill Climber, Tabu Search, …).
|
||||
/// - **`seed`** — the deterministic seed driving this run, when
|
||||
/// the algorithm uses one. Defaults to `None`.
|
||||
pub trait AlgorithmInfo {
|
||||
/// Short, canonical algorithm name — e.g. `"Nsga3"`,
|
||||
/// `"DifferentialEvolution"`, `"BayesianOpt"`.
|
||||
/// Canonical short algorithm name — e.g. `"NSGA-II"`,
|
||||
/// `"DE"`, `"CMA-ES"`. This is the form that should appear
|
||||
/// in tables, plot legends, and exported JSON metadata.
|
||||
fn name(&self) -> &'static str;
|
||||
|
||||
/// The deterministic seed driving this run, if the algorithm uses
|
||||
/// one. Default: `None`. Built-in algorithms return
|
||||
/// Academic long name, expanded — e.g.
|
||||
/// `"Non-dominated Sorting Genetic Algorithm II"`. Defaults
|
||||
/// to `name()` for algorithms whose short and long forms
|
||||
/// coincide (Random Search, Hill Climber, Tabu Search,
|
||||
/// Hyperband, …).
|
||||
fn full_name(&self) -> &'static str {
|
||||
self.name()
|
||||
}
|
||||
|
||||
/// The deterministic seed driving this run, if the algorithm
|
||||
/// uses one. Default: `None`. Built-in algorithms return
|
||||
/// `Some(self.config.seed)`.
|
||||
fn seed(&self) -> Option<u64> {
|
||||
None
|
||||
|
||||
Reference in New Issue
Block a user