Commit Graph

41 Commits

Author SHA1 Message Date
Manuel Raimann 36c6262dbc refactor: remove visualization and fanova feature flags
Always build visualization and fanova code unconditionally.
2026-02-11 23:06:28 +01:00
Manuel Raimann 0a6f2345a8 feat: add Storage trait and JSONL journal backend
Replace the internal Vec<CompletedTrial<V>> with a pluggable Storage<V>
trait. MemoryStorage is the default (no behavior change for existing
users). Behind the `journal` feature flag, JournalStorage persists
trials to a JSONL file with fs2 file locking for multi-process safety.

- Storage<V> trait with push(), trials_arc(), refresh() methods
- MemoryStorage<V> wraps Arc<RwLock<Vec<CompletedTrial<V>>>>
- JournalStorage<V> appends JSON lines with exclusive file locks
- Study::with_sampler_and_storage() general constructor
- Study::with_journal() convenience constructor (journal feature)
- Refresh from storage on create_trial() for multi-process discovery
- MSRV bumped to 1.89
2026-02-11 22:58:38 +01:00
Manuel Raimann 24a0bdd473 feat: add Differential Evolution sampler
Population-based optimizer with mutation + crossover. Supports three
strategies (Rand1, Best1, CurrentToBest1), configurable F and CR,
and auto-sized populations. No extra dependencies needed.
2026-02-11 22:04:23 +01:00
Manuel Raimann 8239cc58a1 refactor: replace rand 0.10 with fastrand 2.3
fastrand is smaller, faster, and has no dependencies. Add rng_util
helper for f64 range generation since fastrand lacks a built-in
equivalent. Migrate all samplers, KDE modules, and fANOVA to use
fastrand's concrete Rng type instead of rand's trait-based generics.
2026-02-11 21:54:34 +01:00
Manuel Raimann 906e5296de fix: seed importance tests to eliminate flakiness
The no_effect_parameter test (and others) used unseeded random sampling,
causing spurious correlations between the noise parameter and the
objective in unlucky runs. Seed all importance tests with
RandomSampler::with_seed(42) for deterministic results.
2026-02-11 21:30:21 +01:00
Manuel Raimann 947701e83f feat: add Gaussian Process sampler with Expected Improvement
Implement a classical Bayesian optimization sampler using a GP surrogate
with Matérn 5/2 kernel and Expected Improvement acquisition function.
Feature-gated behind `gp = ["dep:nalgebra"]`.
2026-02-11 21:27:40 +01:00
Manuel Raimann dff58340a4 feat: add fANOVA parameter importance via random forest
Implement functional ANOVA decomposition behind the `fanova` feature
flag. A self-contained random forest is trained on trial data, then
marginal predictions are used to compute per-parameter main effects
and pairwise interaction effects, normalized to sum to 1.0.

Adds Study::fanova() / fanova_with_config(), FanovaResult, and
FanovaConfig. Includes unit and integration tests covering dominant
parameters, interaction detection, consistency with correlation-based
importance, and error handling.
2026-02-11 20:51:24 +01:00
Manuel Raimann e359392a00 feat: add HTML visualization reports with Plotly.js charts
Add a `visualization` feature flag that generates self-contained HTML
reports with interactive Plotly.js charts for offline visualization of
optimization results. Charts include optimization history, slice plots,
parallel coordinates, parameter importance, trial timeline, and
intermediate values (learning curves).
2026-02-11 20:12:35 +01:00
Manuel Raimann d851aad548 feat: add CSV and JSON data export for visualization
Add to_csv(), export_csv(), and export_json() methods to Study for
exporting trial data to external visualization tools. CSV export works
without extra dependencies; JSON export requires the serde feature.
2026-02-11 20:02:35 +01:00
Manuel Raimann bcc4549e66 feat: add multi-objective optimization with NSGA-II
Add MultiObjectiveStudy for optimizing multiple objectives simultaneously,
backed by NSGA-II (Non-dominated Sorting Genetic Algorithm II) with SBX
crossover, polynomial mutation, and constraint-aware dominance.

New public API:
- MultiObjectiveStudy with optimize(), pareto_front(), ask()/tell()
- MultiObjectiveTrial with get(), is_feasible(), user attributes
- MultiObjectiveSampler trait for custom MO samplers
- Nsga2Sampler with builder for population size, crossover/mutation params
- ObjectiveDimensionMismatch error variant
2026-02-11 19:35:18 +01:00
Manuel Raimann b36137bc96 feat: add benchmark suite with criterion and standard test functions
Add micro-benchmarks for TPE, Random, and Grid samplers with varying
history sizes, end-to-end optimization benchmarks on Sphere and
Rosenbrock, and a convergence tracking example that outputs CSV data.
Includes 6 standard test functions (Sphere, Rosenbrock, Rastrigin,
Ackley, Branin, Hartmann6) with correctness tests at known optima.
2026-02-11 19:05:33 +01:00
Manuel Raimann 0cae3b4227 feat: add parameter importance via Spearman rank correlation
Compute per-parameter importance scores by measuring the absolute
Spearman rank correlation between each parameter's values and the
objective across completed trials. Scores are normalized to sum to 1.0
and returned sorted by descending importance.
2026-02-11 18:56:19 +01:00
Manuel Raimann 09480a973b feat: add constraint handling with feasibility-aware trial ranking
Add constraint support so that optimization problems with constraints
(e.g., "model size < 100MB") prefer feasible solutions. Convention:
constraint value <= 0.0 means feasible.

- Add constraint_values field to Trial with set_constraints/getter
- Add constraints field to CompletedTrial with is_feasible() method
- Propagate constraints through complete_trial/prune_trial
- Make best_trial() and top_trials() constraint-aware: feasible trials
  rank above infeasible, infeasible ranked by total violation
2026-02-11 18:49:08 +01:00
Manuel Raimann aa9734587a feat: add BOHB sampler for budget-aware Bayesian optimization
BOHB combines TPE's model-guided sampling with Hyperband's budget-aware
evaluation by conditioning the TPE model on trials at specific budget
levels, producing better-calibrated parameter proposals.
2026-02-11 18:42:09 +01:00
Manuel Raimann a1dd6d393c feat: add CMA-ES sampler behind cma-es feature flag
Implement CMA-ES (Covariance Matrix Adaptation Evolution Strategy) as a
new sampler for continuous optimization. Uses nalgebra for matrix
operations and implements the full Hansen 2016 algorithm: mean update,
evolution paths, covariance matrix adaptation, and cumulative step-size
adaptation.

Key features:
- Builder API with configurable sigma0, population_size, and seed
- Three-phase state machine: discovery, active sampling, generation update
- Rejection sampling with bounds clipping fallback
- Log-scale and step parameter support via internal-space mapping
- Categorical parameters handled via random sampling fallback
- Numerical robustness: eigenvalue clamping, symmetry enforcement
2026-02-11 18:31:12 +01:00
Manuel Raimann 9b4a8321b5 feat: implement IntoIterator for &Study and add iter() method
Enables idiomatic `for trial in &study` iteration over completed trials.
2026-02-11 17:54:09 +01:00
Manuel Raimann db0314a1d1 feat: add optimize_with_retries() for automatic retry of failed trials 2026-02-11 17:51:36 +01:00
Manuel Raimann 5061df9876 feat: add optimize_with_checkpoint() and atomic save writes
Adds a convenience method that combines optimize_with_callback + save
to automatically checkpoint every N trials. Also makes save() use
atomic writes (write to temp file, then rename) to prevent corrupt
files on crash.
2026-02-11 17:37:57 +01:00
Manuel Raimann 5fe0a75f78 feat: add serde serialization support behind serde feature flag
Add Serialize/Deserialize derives to all public data types (ParamValue,
Distribution, Direction, TrialState, ParamId, AttrValue, CompletedTrial)
gated behind a `serde` feature flag. Introduce StudySnapshot struct and
Study::save()/Study::load() for persisting and restoring study state as
human-readable JSON.
2026-02-11 17:33:48 +01:00
Manuel Raimann dcf3403261 feat: add Study::summary() and Display impl
Add a human-readable summary method and Display trait for Study<V>
where V: Display. The summary shows optimization direction, trial
counts (with complete/pruned breakdown), best value, and best
parameters with their labels.

Also derive PartialOrd + Ord on ParamId for deterministic parameter
ordering in summary output.
2026-02-11 17:27:43 +01:00
Manuel Raimann f4b0631178 feat: add enqueue_trial() for pre-specified parameter evaluation
Add Study::enqueue() to push specific parameter configurations onto a
FIFO queue. The next call to ask()/create_trial() or the next iteration
in optimize() pops the front entry and injects it into the trial so
that suggest_param() returns the pre-filled value instead of sampling.

Parameters missing from an enqueued map fall back to normal sampling,
and once the queue is drained regular sampler-driven trials resume.
2026-02-11 17:23:25 +01:00
Manuel Raimann 52f3c074dc feat: add trial user attributes for logging and analysis
Add AttrValue enum (Float, Int, String, Bool) with From impls and
set_user_attr/user_attr/user_attrs methods on both Trial and
CompletedTrial. Attributes set during optimization are propagated
through complete_trial and prune_trial. AttrValue is re-exported
at crate root and in the prelude.
2026-02-11 17:18:17 +01:00
Manuel Raimann f67188e3a7 feat: add ask() and tell() methods for ask-and-tell interface 2026-02-11 17:11:38 +01:00
Manuel Raimann 72da883add feat: add Study::top_trials(n) for retrieving best N trials
Returns the top N completed trials sorted by objective value,
respecting the study's optimization direction. Pruned and failed
trials are excluded.
2026-02-11 17:08:10 +01:00
Manuel Raimann bc278d83a3 feat: add timeout-based optimization methods (optimize_until)
Add duration-based variants of all optimization methods that run trials
until a wall-clock deadline rather than for a fixed trial count:

- optimize_until(duration, objective)
- optimize_until_with_callback(duration, objective, callback)
- optimize_until_async(duration, objective)
- optimize_until_parallel(duration, concurrency, objective)
2026-02-11 17:06:08 +01:00
Manuel Raimann 432c74b927 feat: add MedianPruner for statistics-based trial pruning
Prunes trials whose intermediate values are worse than the median
of completed trials at the same step. Supports configurable warmup
steps and minimum trial count before pruning activates.
2026-02-11 16:32:03 +01:00
Manuel Raimann 8199ba6b43 feat: add ThresholdPruner for fixed-bound trial pruning 2026-02-11 16:28:22 +01:00
Manuel Raimann 5dc81fa0ab Implement Parameters API
- Add `.name()` builder method on all 5 parameter types for custom labels
- Add `CompletedTrial::get(&param)` for typed parameter access
- Add `Display` impl on `ParamValue`
- Add prelude module at `optimizer::prelude::*`
- Shadow `_with_sampler` methods on `Study<f64>` so `optimize()` auto-uses
  the configured sampler; deprecate `_with_sampler` variants
- Use runtime `Any` downcasting with `trial_factory` to avoid E0592
- Update all examples and tests to use the new API

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 18:54:55 +01:00
Manuel Raimann 55e50e6afb Implement Parameters API 2026-02-06 17:15:47 +01:00
Manuel Raimann 02ec9498c4 refactor: reorganize sampler module and update imports 2026-02-04 13:14:22 +01:00
Manuel Raimann 4ce4311c68 Implement Multivariant TPE 2026-02-02 17:25:50 +01:00
Manuel Raimann b9a90ebec3 Format 2026-01-31 11:56:37 +01:00
Manuel Raimann 747e1928b9 feat: add tests for suggest_bool and suggest_range methods 2026-01-31 11:34:36 +01:00
Manuel Raimann b482d56e89 Implement grid search 2026-01-30 22:01:44 +01:00
Manuel Raimann d8ef4352c3 refactor: replace TpeError with Error in the optimizer library 2026-01-30 19:24:58 +01:00
Manuel Raimann 3898136341 Refactor 2026-01-30 19:21:54 +01:00
Manuel Raimann daab3ea202 Remove Serde 2026-01-30 18:43:45 +01:00
Manuel Raimann 530faba61c refactor: rename library from optimize to optimizer 2026-01-30 18:08:13 +01:00
Manuel Raimann 482354b251 fix: update condition to use is_multiple_of for better readability 2026-01-30 17:46:13 +01:00
Manuel Raimann bb5ef05c10 feat: add async integration tests for optimization library 2026-01-30 17:45:11 +01:00
Manuel Raimann 4db6e56466 Initial Implementation 2026-01-30 17:24:56 +01:00