refactor: move all type re-exports out of crate root into their modules

- 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
This commit is contained in:
Manuel Raimann
2026-02-12 10:28:05 +01:00
parent cc0dce5daf
commit 6a4b27c46f
17 changed files with 82 additions and 105 deletions
+2 -2
View File
@@ -2,10 +2,10 @@
mod test_functions;
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use optimizer::parameter::Parameter;
use optimizer::Study;
use optimizer::parameter::{FloatParam, Parameter};
use optimizer::sampler::random::RandomSampler;
use optimizer::sampler::tpe::TpeSampler;
use optimizer::{FloatParam, Study};
fn make_params(dims: usize) -> Vec<FloatParam> {
(0..dims)
+3 -4
View File
@@ -1,12 +1,11 @@
use std::collections::HashMap;
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use optimizer::parameter::Parameter;
use optimizer::sampler::Sampler;
use optimizer::parameter::{FloatParam, Parameter};
use optimizer::sampler::grid::GridSearchSampler;
use optimizer::sampler::random::RandomSampler;
use optimizer::sampler::tpe::TpeSampler;
use optimizer::{CompletedTrial, FloatParam};
use optimizer::sampler::{CompletedTrial, Sampler};
/// Build a synthetic history of `n` completed trials over `dims` float parameters.
fn build_history(n: usize, dims: usize) -> Vec<CompletedTrial<f64>> {
@@ -33,7 +32,7 @@ fn build_history(n: usize, dims: usize) -> Vec<CompletedTrial<f64>> {
let value: f64 = param_values
.values()
.map(|v| {
let optimizer::ParamValue::Float(f) = v else {
let optimizer::parameter::ParamValue::Float(f) = v else {
unreachable!()
};
f * f
+3 -3
View File
@@ -4,13 +4,13 @@ use syn::{Data, DeriveInput, Fields, parse_macro_input};
/// Derive macro for the `Categorical` trait on fieldless enums.
///
/// Generates an implementation of `optimizer::Categorical` that maps
/// Generates an implementation of `optimizer::parameter::Categorical` that maps
/// enum variants to/from sequential indices.
///
/// # Example
///
/// ```ignore
/// use optimizer::Categorical;
/// use optimizer::parameter::Categorical;
///
/// #[derive(Clone, Categorical)]
/// enum Color {
@@ -49,7 +49,7 @@ pub fn derive_categorical(input: TokenStream) -> TokenStream {
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let expanded = quote! {
impl #impl_generics optimizer::Categorical for #name #ty_generics #where_clause {
impl #impl_generics optimizer::parameter::Categorical for #name #ty_generics #where_clause {
const N_CHOICES: usize = #n_choices;
fn from_index(index: usize) -> Self {
+31 -66
View File
@@ -42,7 +42,7 @@
//! |------|------|
//! | [`Study`] | Drive an optimization loop: create trials, record results, track the best. |
//! | [`Trial`] | A single evaluation of the objective function, carrying suggested parameter values. |
//! | [`Parameter`] | Define the search space — [`FloatParam`], [`IntParam`], [`CategoricalParam`], [`BoolParam`], [`EnumParam`]. |
//! | [`Parameter`](parameter::Parameter) | Define the search space — [`FloatParam`](parameter::FloatParam), [`IntParam`](parameter::IntParam), [`CategoricalParam`](parameter::CategoricalParam), [`BoolParam`](parameter::BoolParam), [`EnumParam`](parameter::EnumParam). |
//! | [`Sampler`](sampler::Sampler) | Strategy for choosing the next point to evaluate (TPE, CMA-ES, random, etc.). |
//! | [`Direction`] | Whether the study minimizes or maximizes the objective value. |
//!
@@ -52,23 +52,23 @@
//!
//! | Sampler | Algorithm | Best for | Feature flag |
//! |---------|-----------|----------|--------------|
//! | [`RandomSampler`] | Uniform random | Baselines, high-dimensional | — |
//! | [`TpeSampler`] | Tree-Parzen Estimator | General-purpose Bayesian | — |
//! | [`GridSearchSampler`] | Exhaustive grid | Small, discrete spaces | — |
//! | [`SobolSampler`] | Sobol quasi-random sequence | Space-filling, low dimensions | `sobol` |
//! | [`CmaEsSampler`] | CMA-ES | Continuous, moderate dimensions | `cma-es` |
//! | [`GpSampler`] | Gaussian Process + EI | Expensive objectives, few trials | `gp` |
//! | [`DifferentialEvolutionSampler`] | Differential Evolution | Non-convex, population-based | — |
//! | [`BohbSampler`] | BOHB (TPE + `HyperBand`) | Budget-aware early stopping | — |
//! | [`RandomSampler`](sampler::RandomSampler) | Uniform random | Baselines, high-dimensional | — |
//! | [`TpeSampler`](sampler::TpeSampler) | Tree-Parzen Estimator | General-purpose Bayesian | — |
//! | [`GridSearchSampler`](sampler::GridSearchSampler) | Exhaustive grid | Small, discrete spaces | — |
//! | [`SobolSampler`](sampler::SobolSampler) | Sobol quasi-random sequence | Space-filling, low dimensions | `sobol` |
//! | [`CmaEsSampler`](sampler::CmaEsSampler) | CMA-ES | Continuous, moderate dimensions | `cma-es` |
//! | [`GpSampler`](sampler::GpSampler) | Gaussian Process + EI | Expensive objectives, few trials | `gp` |
//! | [`DifferentialEvolutionSampler`](sampler::DifferentialEvolutionSampler) | Differential Evolution | Non-convex, population-based | — |
//! | [`BohbSampler`](sampler::BohbSampler) | BOHB (TPE + `HyperBand`) | Budget-aware early stopping | — |
//!
//! ## Multi-objective samplers
//!
//! | Sampler | Algorithm | Best for | Feature flag |
//! |---------|-----------|----------|--------------|
//! | [`Nsga2Sampler`] | NSGA-II | 2-3 objectives | — |
//! | [`Nsga3Sampler`] | NSGA-III (reference-point) | 3+ objectives | — |
//! | [`MoeadSampler`] | MOEA/D (decomposition) | Many objectives, structured fronts | — |
//! | [`MotpeSampler`] | Multi-Objective TPE | Bayesian multi-objective | — |
//! | [`Nsga2Sampler`](sampler::Nsga2Sampler) | NSGA-II | 2-3 objectives | — |
//! | [`Nsga3Sampler`](sampler::Nsga3Sampler) | NSGA-III (reference-point) | 3+ objectives | — |
//! | [`MoeadSampler`](sampler::MoeadSampler) | MOEA/D (decomposition) | Many objectives, structured fronts | — |
//! | [`MotpeSampler`](sampler::MotpeSampler) | Multi-Objective TPE | Bayesian multi-objective | — |
//!
//! # Feature Flags
//!
@@ -77,10 +77,10 @@
//! | `async` | Async/parallel optimization via tokio ([`Study::optimize_async`], [`Study::optimize_parallel`]) | off |
//! | `derive` | `#[derive(Categorical)]` for enum parameters | off |
//! | `serde` | `Serialize`/`Deserialize` on public types, [`Study::save`]/[`Study::load`] | off |
//! | `journal` | [`JournalStorage`] — JSONL persistence with file locking (enables `serde`) | off |
//! | `sobol` | [`SobolSampler`] — quasi-random low-discrepancy sequences | off |
//! | `cma-es` | [`CmaEsSampler`] — Covariance Matrix Adaptation Evolution Strategy | off |
//! | `gp` | [`GpSampler`] — Gaussian Process surrogate with Expected Improvement | off |
//! | `journal` | [`JournalStorage`](storage::JournalStorage) — JSONL persistence with file locking (enables `serde`) | off |
//! | `sobol` | [`SobolSampler`](sampler::SobolSampler) — quasi-random low-discrepancy sequences | off |
//! | `cma-es` | [`CmaEsSampler`](sampler::CmaEsSampler) — Covariance Matrix Adaptation Evolution Strategy | off |
//! | `gp` | [`GpSampler`](sampler::GpSampler) — Gaussian Process surrogate with Expected Improvement | off |
//! | `tracing` | Structured log events via [`tracing`](https://docs.rs/tracing) at key optimization points | off |
/// Emit a `tracing::info!` event when the `tracing` feature is enabled.
@@ -127,38 +127,8 @@ mod visualization;
pub use error::{Error, Result, TrialPruned};
pub use fanova::{FanovaConfig, FanovaResult};
pub use multi_objective::{MultiObjectiveSampler, MultiObjectiveStudy, MultiObjectiveTrial};
#[cfg(feature = "derive")]
pub use optimizer_derive::Categorical;
pub use param::ParamValue;
pub use parameter::{
BoolParam, Categorical, CategoricalParam, EnumParam, FloatParam, IntParam, ParamId, Parameter,
};
pub use pruner::{
HyperbandPruner, MedianPruner, NopPruner, PatientPruner, PercentilePruner, Pruner,
SuccessiveHalvingPruner, ThresholdPruner, WilcoxonPruner,
};
pub use sampler::CompletedTrial;
pub use sampler::bohb::BohbSampler;
#[cfg(feature = "cma-es")]
pub use sampler::cma_es::CmaEsSampler;
pub use sampler::differential_evolution::{
DifferentialEvolutionSampler, DifferentialEvolutionStrategy,
};
#[cfg(feature = "gp")]
pub use sampler::gp::GpSampler;
pub use sampler::grid::GridSearchSampler;
pub use sampler::moead::{Decomposition, MoeadSampler};
pub use sampler::motpe::MotpeSampler;
pub use sampler::nsga2::Nsga2Sampler;
pub use sampler::nsga3::Nsga3Sampler;
pub use sampler::random::RandomSampler;
#[cfg(feature = "sobol")]
pub use sampler::sobol::SobolSampler;
pub use sampler::tpe::TpeSampler;
#[cfg(feature = "journal")]
pub use storage::JournalStorage;
pub use storage::{MemoryStorage, Storage};
#[cfg(feature = "serde")]
pub use study::StudySnapshot;
pub use study::{Study, StudyBuilder};
@@ -177,33 +147,28 @@ pub mod prelude {
pub use crate::error::{Error, Result, TrialPruned};
pub use crate::fanova::{FanovaConfig, FanovaResult};
pub use crate::multi_objective::{MultiObjectiveStudy, MultiObjectiveTrial};
pub use crate::param::ParamValue;
pub use crate::multi_objective::{
MultiObjectiveSampler, MultiObjectiveStudy, MultiObjectiveTrial,
};
pub use crate::parameter::{
BoolParam, Categorical, CategoricalParam, EnumParam, FloatParam, IntParam, Parameter,
BoolParam, Categorical, CategoricalParam, EnumParam, FloatParam, IntParam, ParamValue,
Parameter,
};
pub use crate::pruner::{
HyperbandPruner, MedianPruner, NopPruner, PatientPruner, PercentilePruner, Pruner,
SuccessiveHalvingPruner, ThresholdPruner,
SuccessiveHalvingPruner, ThresholdPruner, WilcoxonPruner,
};
pub use crate::sampler::CompletedTrial;
pub use crate::sampler::bohb::BohbSampler;
#[cfg(feature = "cma-es")]
pub use crate::sampler::cma_es::CmaEsSampler;
pub use crate::sampler::differential_evolution::{
DifferentialEvolutionSampler, DifferentialEvolutionStrategy,
};
pub use crate::sampler::CmaEsSampler;
#[cfg(feature = "gp")]
pub use crate::sampler::gp::GpSampler;
pub use crate::sampler::grid::GridSearchSampler;
pub use crate::sampler::moead::{Decomposition, MoeadSampler};
pub use crate::sampler::motpe::MotpeSampler;
pub use crate::sampler::nsga2::Nsga2Sampler;
pub use crate::sampler::nsga3::Nsga3Sampler;
pub use crate::sampler::random::RandomSampler;
pub use crate::sampler::GpSampler;
#[cfg(feature = "sobol")]
pub use crate::sampler::sobol::SobolSampler;
pub use crate::sampler::tpe::TpeSampler;
pub use crate::sampler::SobolSampler;
pub use crate::sampler::{
BohbSampler, CompletedTrial, Decomposition, DifferentialEvolutionSampler,
DifferentialEvolutionStrategy, GridSearchSampler, MoeadSampler, MotpeSampler, Nsga2Sampler,
Nsga3Sampler, RandomSampler, TpeSampler,
};
#[cfg(feature = "journal")]
pub use crate::storage::JournalStorage;
pub use crate::storage::{MemoryStorage, Storage};
+6 -6
View File
@@ -19,9 +19,9 @@
//! # Samplers
//!
//! By default a random sampler is used. For smarter search, pass a
//! [`MultiObjectiveSampler`] such as [`Nsga2Sampler`](crate::Nsga2Sampler),
//! [`Nsga3Sampler`](crate::Nsga3Sampler), or
//! [`MoeadSampler`](crate::MoeadSampler) via
//! [`MultiObjectiveSampler`] such as [`Nsga2Sampler`](crate::sampler::Nsga2Sampler),
//! [`Nsga3Sampler`](crate::sampler::Nsga3Sampler), or
//! [`MoeadSampler`](crate::sampler::MoeadSampler) via
//! [`MultiObjectiveStudy::with_sampler`].
//!
//! # Examples
@@ -140,9 +140,9 @@ impl MultiObjectiveTrial {
/// (`&[MultiObjectiveTrial]`) and the per-objective directions
/// (`&[Direction]`).
///
/// Implementations include [`Nsga2Sampler`](crate::Nsga2Sampler),
/// [`Nsga3Sampler`](crate::Nsga3Sampler), and
/// [`MoeadSampler`](crate::MoeadSampler).
/// Implementations include [`Nsga2Sampler`](crate::sampler::Nsga2Sampler),
/// [`Nsga3Sampler`](crate::sampler::Nsga3Sampler), and
/// [`MoeadSampler`](crate::sampler::MoeadSampler).
pub trait MultiObjectiveSampler: Send + Sync {
/// Samples a parameter value from the given distribution.
fn sample(
+1 -1
View File
@@ -46,7 +46,7 @@ use crate::distribution::{
CategoricalDistribution, Distribution, FloatDistribution, IntDistribution,
};
use crate::error::{Error, Result};
use crate::param::ParamValue;
pub use crate::param::ParamValue;
use crate::trial::Trial;
static NEXT_PARAM_ID: AtomicU64 = AtomicU64::new(0);
+2 -2
View File
@@ -29,8 +29,8 @@
//!
//! Internally, this module also provides the fast non-dominated sorting
//! algorithm (Deb et al., 2002) used by
//! [`MultiObjectiveStudy::pareto_front()`](crate::MultiObjectiveStudy::pareto_front)
//! and [`Nsga2Sampler`](crate::Nsga2Sampler).
//! [`MultiObjectiveStudy::pareto_front()`](crate::multi_objective::MultiObjectiveStudy::pareto_front)
//! and [`Nsga2Sampler`](crate::sampler::Nsga2Sampler).
//!
//! # Example
//!
+1 -1
View File
@@ -317,7 +317,7 @@ mod tests {
CompletedTrial::with_intermediate_values(
id,
HashMap::<ParamId, crate::ParamValue>::new(),
HashMap::<ParamId, crate::parameter::ParamValue>::new(),
HashMap::new(),
HashMap::new(),
0.0,
+1 -1
View File
@@ -233,7 +233,7 @@ mod tests {
CompletedTrial::with_intermediate_values(
id,
HashMap::<ParamId, crate::ParamValue>::new(),
HashMap::<ParamId, crate::parameter::ParamValue>::new(),
HashMap::new(),
HashMap::new(),
0.0,
+1 -1
View File
@@ -285,7 +285,7 @@ mod tests {
CompletedTrial::with_intermediate_values(
id,
HashMap::<ParamId, crate::ParamValue>::new(),
HashMap::<ParamId, crate::parameter::ParamValue>::new(),
HashMap::new(),
HashMap::new(),
0.0,
@@ -46,9 +46,7 @@
//! # Examples
//!
//! ```
//! use optimizer::sampler::differential_evolution::{
//! DifferentialEvolutionSampler, DifferentialEvolutionStrategy,
//! };
//! use optimizer::sampler::de::{DifferentialEvolutionSampler, DifferentialEvolutionStrategy};
//! use optimizer::{Direction, Study};
//!
//! // Minimize with DE using the Best1 strategy for faster convergence
@@ -101,7 +99,7 @@ pub enum DifferentialEvolutionStrategy {
/// # Examples
///
/// ```
/// use optimizer::sampler::differential_evolution::DifferentialEvolutionSampler;
/// use optimizer::sampler::de::DifferentialEvolutionSampler;
/// use optimizer::{Direction, Study};
///
/// // Default configuration
@@ -115,7 +113,7 @@ pub enum DifferentialEvolutionStrategy {
/// );
///
/// // Custom configuration via builder
/// use optimizer::sampler::differential_evolution::DifferentialEvolutionStrategy;
/// use optimizer::sampler::de::DifferentialEvolutionStrategy;
/// let sampler = DifferentialEvolutionSampler::builder()
/// .mutation_factor(0.8)
/// .crossover_rate(0.9)
@@ -183,7 +181,7 @@ impl Default for DifferentialEvolutionSampler {
/// # Examples
///
/// ```
/// use optimizer::sampler::differential_evolution::{
/// use optimizer::sampler::de::{
/// DifferentialEvolutionSamplerBuilder, DifferentialEvolutionStrategy,
/// };
///
+17 -1
View File
@@ -3,7 +3,7 @@
pub mod bohb;
#[cfg(feature = "cma-es")]
pub mod cma_es;
pub mod differential_evolution;
pub mod de;
pub(crate) mod genetic;
#[cfg(feature = "gp")]
pub mod gp;
@@ -19,6 +19,22 @@ pub mod tpe;
use std::collections::HashMap;
pub use bohb::BohbSampler;
#[cfg(feature = "cma-es")]
pub use cma_es::CmaEsSampler;
pub use de::{DifferentialEvolutionSampler, DifferentialEvolutionStrategy};
#[cfg(feature = "gp")]
pub use gp::GpSampler;
pub use grid::GridSearchSampler;
pub use moead::{Decomposition, MoeadSampler};
pub use motpe::MotpeSampler;
pub use nsga2::Nsga2Sampler;
pub use nsga3::Nsga3Sampler;
pub use random::RandomSampler;
#[cfg(feature = "sobol")]
pub use sobol::SobolSampler;
pub use tpe::TpeSampler;
use crate::distribution::Distribution;
use crate::param::ParamValue;
use crate::parameter::{ParamId, Parameter};
+2 -2
View File
@@ -382,8 +382,8 @@ where
/// ```
/// use std::collections::HashMap;
///
/// use optimizer::parameter::{FloatParam, IntParam, Parameter};
/// use optimizer::{Direction, ParamValue, Study};
/// use optimizer::parameter::{FloatParam, IntParam, ParamValue, Parameter};
/// use optimizer::{Direction, Study};
///
/// let study: Study<f64> = Study::new(Direction::Minimize);
/// let x = FloatParam::new(0.0, 10.0);
+1 -3
View File
@@ -1,7 +1,5 @@
use optimizer::prelude::*;
use optimizer::sampler::differential_evolution::{
DifferentialEvolutionSampler, DifferentialEvolutionStrategy,
};
use optimizer::sampler::de::{DifferentialEvolutionSampler, DifferentialEvolutionStrategy};
#[test]
fn sphere_function() {
+3 -3
View File
@@ -1707,7 +1707,7 @@ fn test_ask_and_tell_with_custom_value_type() {
use std::collections::HashMap;
use optimizer::ParamValue;
use optimizer::parameter::ParamValue;
#[test]
fn test_enqueue_params_evaluated_first() {
@@ -2291,7 +2291,7 @@ fn test_builder_with_sampler() {
#[test]
fn test_builder_with_pruner() {
use optimizer::NopPruner;
use optimizer::pruner::NopPruner;
let study: Study<f64> = Study::builder().pruner(NopPruner).build();
@@ -2303,7 +2303,7 @@ fn test_builder_chaining() {
let study: Study<f64> = Study::builder()
.maximize()
.sampler(RandomSampler::with_seed(42))
.pruner(optimizer::NopPruner)
.pruner(optimizer::pruner::NopPruner)
.build();
assert_eq!(study.direction(), Direction::Maximize);
+2 -1
View File
@@ -1,11 +1,12 @@
//! Integration tests for multi-objective optimization.
use optimizer::Direction;
use optimizer::multi_objective::MultiObjectiveStudy;
use optimizer::parameter::{CategoricalParam, FloatParam, Parameter};
use optimizer::sampler::Decomposition;
use optimizer::sampler::moead::MoeadSampler;
use optimizer::sampler::nsga2::Nsga2Sampler;
use optimizer::sampler::nsga3::Nsga3Sampler;
use optimizer::{Decomposition, Direction};
// ---------------------------------------------------------------------------
// Pareto utility tests (via public MultiObjectiveStudy)
+2 -2
View File
@@ -2,9 +2,9 @@
use std::collections::HashMap;
use optimizer::parameter::{FloatParam, IntParam, Parameter};
use optimizer::parameter::{FloatParam, IntParam, ParamValue, Parameter};
use optimizer::sampler::CompletedTrial;
use optimizer::{Direction, ParamValue, Study, StudySnapshot, TrialState};
use optimizer::{Direction, Study, StudySnapshot, TrialState};
#[test]
fn round_trip_save_load() {