Skip to main content

hyperopt_core/
lib.rs

1//! # hyperopt-core
2//!
3//! Core abstractions for `hyperopt-rs`, an Optuna-shaped hyperparameter
4//! optimization framework for Rust. This crate defines the foundational types
5//! and the three extension traits everything else plugs into:
6//!
7//! - [`Sampler`] — a pluggable search algorithm (random, grid, TPE, …).
8//! - [`Pruner`] — a pluggable early-stopping policy.
9//! - [`Storage`] — where trial history lives (in-memory, SQLite, …).
10//!
11//! Third parties can depend on just `hyperopt-core` to implement a new sampler
12//! or pruner without pulling in SQLite or `rayon`.
13//!
14//! ## Define-by-run
15//!
16//! The search space is **not** declared up front. Instead the user's objective
17//! closure receives a [`TrialContext`] and *calls* `suggest_*` methods on it;
18//! each call records a [`Distribution`] and asks the active [`Sampler`] for a
19//! [`Value`]. This allows conditional/dynamic search spaces — a later
20//! suggestion can depend on an earlier one — which is the design this framework
21//! is built around.
22//!
23//! ```no_run
24//! # use hyperopt_core::*;
25//! # fn run(study: &Study) -> Result<(), HyperoptError> {
26//! study.optimize(|trial| {
27//!     let x = trial.suggest_float("x", -10.0, 10.0);
28//!     let y = trial.suggest_float("y", -10.0, 10.0);
29//!     Ok((x - 2.0).powi(2) + (y + 3.0).powi(2)) // minimize
30//! }, 100)?;
31//! # Ok(()) }
32//! ```
33
34mod context;
35mod distribution;
36mod error;
37mod storage;
38mod study;
39mod study_state;
40mod suggest;
41mod traits;
42mod trial;
43mod value;
44
45pub use context::TrialContext;
46pub use distribution::Distribution;
47pub use error::{HyperoptError, ObjectiveError, ObjectiveResult};
48pub use storage::{Storage, StorageError, StudyMetadata};
49pub use study::Study;
50pub use study_state::StudyState;
51pub use suggest::Suggest;
52pub use traits::{Pruner, Sampler};
53pub use trial::{ParamRecord, Trial, TrialState};
54pub use value::Value;
55
56use serde::{Deserialize, Serialize};
57
58/// Optimization direction: whether the objective should be minimized or
59/// maximized. Samplers and pruners read this from [`StudyState::direction`] and
60/// adjust accordingly (e.g. TPE always minimizes internally, negating values
61/// under `Maximize`).
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
63pub enum Direction {
64    Minimize,
65    Maximize,
66}
67
68impl Direction {
69    /// `true` if `a` is a better objective value than `b` under this direction.
70    pub fn is_better(self, a: f64, b: f64) -> bool {
71        match self {
72            Direction::Minimize => a < b,
73            Direction::Maximize => a > b,
74        }
75    }
76}