- Replace Mutex<fastrand::Rng> with a stored seed + MurmurHash3 mixer
in RandomSampler, TpeSampler, and MotpeSampler so parallel workers
no longer serialize on a shared lock
- Add mix_seed() and distribution_fingerprint() to rng_util for
deterministic per-call RNG derivation from (seed, trial_id, distribution)
- Include an AtomicU64 call counter to disambiguate parameters that
share the same distribution within a trial
Remove the conditional guard on pruned trial assertions since the test
explicitly prunes 2 trials. Assert the expected count first, then check
summary content unconditionally to catch regressions.
- Add `CompletedTrial::validate()` checking all f64 fields are finite
- Call validate after deserializing each trial in journal storage
- Make `distribution` and `param` modules public (types already in public fields)
- Add blanket `impl Objective<V> for Fn(&mut Trial) -> Result<V, E>`
so closures work directly with `optimize`
- Rewrite optimize, optimize_async, optimize_parallel to accept
`impl Objective<V>` with before_trial/after_trial hooks
- Remove optimize_with, optimize_with_async, optimize_with_parallel
- Remove max_retries and retry logic from Objective trait
- Add explicit closure type annotations for HRTB inference
- Convert FnMut test closures to Fn via RefCell/Cell
- Delete 20 duplicate tests already covered by parameter_tests.rs
- Move 11 pure Trial unit tests into src/trial.rs
- Split remaining 84 integration tests into tests/study/ (9 modules)
- Group sampler tests into tests/sampler/ (7 modules)
- Group pruner tests into tests/pruner/ (2 modules)
- Split pruning_and_callbacks into pruning and early_stopping
- Split advanced_features into async_parallel, journal_storage, ask_and_tell, multi_objective
- Each example now requires only its own feature flag
- Trim sampler_comparison winner logic and verbose header
- Update CI workflow and README to match new example names
- Sampler, pruner, storage, parameter, and multi_objective types are no
longer re-exported at the crate root; access via module paths instead
(e.g. optimizer::sampler::TpeSampler, optimizer::parameter::FloatParam)
- Prelude continues to re-export everything for convenience
- Add module-level pub use re-exports in sampler/mod.rs and parameter.rs
- Update derive macro to reference optimizer::parameter::Categorical
- Rename sampler::differential_evolution to sampler::de
- Fix all downstream imports in tests, benches, and doctests
- Fix all rustdoc intra-doc links to use explicit module paths
Extract shared evolutionary algorithm infrastructure (genetic operators,
candidate management, Das-Dennis reference points) from NSGA-II into a
new genetic.rs module, then build two new multi-objective samplers on top:
- NSGA-III: reference-point-based niching for well-distributed fronts
on 3+ objective problems (Das-Dennis structured points, normalization,
perpendicular distance association, niching selection)
- MOEA/D: decomposition-based optimization with three scalarization
methods (Tchebycheff, WeightedSum, PBI), weight-vector neighborhoods,
and neighborhood-based mating selection
Both implement MultiObjectiveSampler with builder pattern, seeded RNG,
and SBX crossover / polynomial mutation via the shared genetic module.
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
Population-based optimizer with mutation + crossover. Supports three
strategies (Rand1, Best1, CurrentToBest1), configurable F and CR,
and auto-sized populations. No extra dependencies needed.
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.
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.
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"]`.
Use cargo hack's --partition flag to split the feature powerset across
4 parallel jobs, reducing wall-clock time for the feature-check step.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.
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).
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.