Adds a tiny additive surface that turns any OptimizationResult into
a self-describing JSON file the heuropt-explorer webapp can load.
Real Pareto fronts have 50–200+ candidates spanning 2–7+ objectives;
reading them as numbers in a terminal scales badly. This commit
ships the heuropt-side of the explorer — the schema and the export
API. The webapp itself lives in a separate repo on its own cadence.
Three trait/type extensions, all with working defaults so existing
impls compile untouched:
- Objective gains 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)` are
unchanged. Both fields are #[serde(default,
skip_serializing_if = \"Option::is_none\")] so existing JSON
round-trips cleanly.
- Problem trait gains 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` with builder methods.
- New `heuropt::traits::AlgorithmInfo` trait with `name()`
(required) and `seed()` (default None). Every built-in algorithm
— all 33 — implements it. Separate from Optimizer<P> so
multi-fidelity Hyperband (which uses PartialProblem) implements
it uniformly.
The new explorer module:
- `heuropt::explorer::ExplorerExport` envelope with versioned
schema (SCHEMA_VERSION = 1).
- ExplorerCandidate per row, with front_rank from
non_dominated_sort attached at export time so downstream tools
don't re-derive it.
- ToDecisionValues adapter trait with provided impls for Vec<f64>,
Vec<bool>, Vec<usize>, Vec<i64>; custom decision types implement
one method.
- Free functions to_json / to_writer / to_file plus a builder API
(with_algorithm_info, with_problem_name, with_wall_clock,
with_timestamp).
- Gated on the existing `serde` feature, which now also pulls in
`serde_json` as a dep.
The example:
- `examples/pick_a_car.rs` — promotes the README's PickACar to a
real example, fully enriched with Objective labels/units and a
decision_schema. Runs NSGA-III for 200 generations, prints a
sample slice, writes pick_a_car.json. Gated on `serde`.
10 new explorer unit tests cover round-trip serde, fallback
decision-variable names, enriched export, AlgorithmInfo flow,
front-rank correctness, and the ToDecisionValues impls. Lib test
count went from 229 to 242.
28 lines
1.1 KiB
Rust
28 lines
1.1 KiB
Rust
//! Lightweight metadata about an algorithm — its short canonical 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.
|
|
|
|
/// 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.
|
|
pub trait AlgorithmInfo {
|
|
/// Short, canonical algorithm name — e.g. `"Nsga3"`,
|
|
/// `"DifferentialEvolution"`, `"BayesianOpt"`.
|
|
fn name(&self) -> &'static str;
|
|
|
|
/// 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
|
|
}
|
|
}
|