Struct Dehb
pub struct Dehb { /* private fields */ }Expand description
Differential-Evolution Hyperband: a stateful DE sampler over a Hyperband fidelity schedule.
Construct with Dehb::new (min/max fidelity, default η = 3 and the
reference F = CR = 0.5) and hand it to a study through
StudyBuilder::sampler, ideally paired
with a HyperbandPruner over the same
(min, max, η). See the module documentation for the algorithm.
use atune_core::sampler::Dehb;
// Fidelities 1, 3, 9, 27 (η = 3) — four DE subpopulations.
let dehb = Dehb::new(1, 27)?;
assert_eq!(dehb.fidelities(), [1, 3, 9, 27]);
assert_eq!(dehb.reduction_factor(), 3);Implementations§
§impl Dehb
impl Dehb
pub fn new(min_fidelity: u64, max_fidelity: u64) -> Result<Self>
pub fn new(min_fidelity: u64, max_fidelity: u64) -> Result<Self>
Builds a DEHB sampler over [min_fidelity, max_fidelity] with the default
reduction factor
η = 3 and the reference
F = CR = 0.5.
§Errors
Error::InvalidSpace for a nonsense ladder — see RungLadder::new —
and for min_fidelity == max_fidelity, which is not a ladder at all
(see with_eta).
pub fn with_eta(min_fidelity: u64, max_fidelity: u64, eta: u32) -> Result<Self>
pub fn with_eta(min_fidelity: u64, max_fidelity: u64, eta: u32) -> Result<Self>
Builds a DEHB sampler with an explicit reduction factor η.
§Errors
Error::InvalidSpace for a nonsense ladder (RungLadder::new) or for
a single-budget one (min_fidelity == max_fidelity). The latter is
refused rather than degenerated into “plain DE”: with one fidelity the
sole subpopulation is also always the target, the donor pool empties, and
every rand/1 donor is a fresh uniform vector — random search wearing a DE
hat. DEHB is a multi-fidelity method; a caller who wants one budget wants
a different sampler.
pub fn with_mutation_factor(self, f: f64) -> Self
pub fn with_mutation_factor(self, f: f64) -> Self
Sets the DE scale factor F (default DEFAULT_MUTATION_FACTOR).
Clamped to be non-negative; a runaway factor is still made safe by the boundary fix.
pub fn with_crossover_prob(self, cr: f64) -> Self
pub fn with_crossover_prob(self, cr: f64) -> Self
Sets the DE crossover rate CR (default DEFAULT_CROSSOVER_PROB),
clamped into [0, 1].
pub const fn with_boundary_fix(self, boundary: BoundaryFix) -> Self
pub const fn with_boundary_fix(self, boundary: BoundaryFix) -> Self
Sets how out-of-range mutant coordinates are repaired (default
BoundaryFix::Clamp).
pub fn fidelities(&self) -> &[u64]
pub fn fidelities(&self) -> &[u64]
The geometric fidelity ladder [min·η⁰, …, max].
pub const fn reduction_factor(&self) -> u32
pub const fn reduction_factor(&self) -> u32
The reduction factor η.
pub fn min_fidelity(&self) -> u64
pub fn min_fidelity(&self) -> u64
The lowest fidelity.
pub fn max_fidelity(&self) -> u64
pub fn max_fidelity(&self) -> u64
The highest fidelity (the finish line).
pub const fn mutation_factor(&self) -> f64
pub const fn mutation_factor(&self) -> f64
The DE scale factor F.
pub const fn crossover_prob(&self) -> f64
pub const fn crossover_prob(&self) -> f64
The DE crossover rate CR.
pub fn target_fidelity(&self, trial_number: u64) -> Option<u64>
pub fn target_fidelity(&self, trial_number: u64) -> Option<u64>
The fidelity a still-in-flight trial’s configuration was bred for, if the trial has been sampled and not yet told back.
This is how an executor learns what budget to run a job to (and, on a
promotion, whether to warm-continue). It reads the pending job map, so a
finished trial (whose job has been consumed by
after_trial) returns None.
Trait Implementations§
§impl Sampler for Dehb
impl Sampler for Dehb
§fn infer_relative_space(&self, study: &StudyView) -> Result<SpaceSchema>
fn infer_relative_space(&self, study: &StudyView) -> Result<SpaceSchema>
The study’s declared space, verbatim.
DEHB evolves a fixed-dimension unit vector, so it wants a declared
SpaceSchema. A define-by-run study (no declared space) yields an
empty relative space here, which routes every
parameter through sample_independent’s
uniform fallback — DEHB’s DE engine is a static-space method.
§Errors
Never.
§fn sample_relative(
&self,
_study: &StudyView,
trial: &TrialMeta,
space: &SpaceSchema,
) -> Result<Assignment>
fn sample_relative( &self, _study: &StudyView, trial: &TrialMeta, space: &SpaceSchema, ) -> Result<Assignment>
Breeds this trial’s configuration with one DEHB job.
Every returned value lies in its declared support — it is produced through
Distribution::from_unit of a
unit coordinate in [0, 1], so contains holds for every kind (log,
stepped, categorical, boolean).
§Errors
Error::InvalidSpace if a declared distribution is malformed;
Error::Sampler if the state lock is poisoned or the restored state’s
shape does not fit the live schedule (which
restore_state already refuses to create — this
is the belt-and-braces path that keeps a shape drift an error rather than
an out-of-bounds panic).
§fn sample_independent(
&self,
_study: &StudyView,
trial: &TrialMeta,
name: &str,
dist: &Distribution,
) -> Result<ParamValue>
fn sample_independent( &self, _study: &StudyView, trial: &TrialMeta, name: &str, dist: &Distribution, ) -> Result<ParamValue>
The uniform draw for a parameter the relative space did not cover — the
same fallback Tpe uses, keyed on
(sampler seed, name).
§Errors
Error::InvalidSpace if dist is malformed.
§fn after_trial(&self, study: &StudyView, trial: &FrozenTrial) -> Result<()>
fn after_trial(&self, study: &StudyView, trial: &FrozenTrial) -> Result<()>
DE selection: the finished trial’s config competes for its target slot.
The trial’s pending job is taken unconditionally and first — a job is
pending exactly while its trial is in flight, so every path out of this
method consumes it. That is what keeps trial_jobs (and therefore the
persisted state blob, which the loop re-serializes after every trial end)
from growing without bound on the paths that do not select: a failed
trial has no value, and a multi-objective study has no single loss.
The job then feeds selection only if all of the following hold; otherwise it is simply dropped, which is never an error:
- the trial has one objective value and the study one direction;
- the evaluated point is the bred point. The study loop samples every
trial, including one created from a
TrialTemplate(enqueued, retried or forked) whose fixed values then override the bred draw. Selection re-derives the evaluated configuration from the trial’s recorded parameters and compares it to the job’s vector, so a template’s loss can never be recorded as the fitness of a configuration nobody ran.
The objective is normalised to a loss (smaller is better) by the study direction; if it is at least as good as the slot’s current fitness — and finite — the slot adopts the child.
§Errors
Never — a failure here must not fail the trial, so a poisoned lock is swallowed (the update is simply skipped).
§fn state(&self) -> Result<Option<SamplerState>>
fn state(&self) -> Result<Option<SamplerState>>
The whole DEHB machine as a versioned blob — populations, counters, the bracket cursor and the pending-job map.
§Errors
Error::Sampler if the state lock is poisoned or the state cannot be
serialized.
§fn restore_state(&self, blob: &SamplerState) -> Result<()>
fn restore_state(&self, blob: &SamplerState) -> Result<()>
Rebuilds the DEHB machine from a persisted blob so a reopened study continues identically.
The blob’s ladder identity must match this sampler’s: the
subpopulations, the parent counters and the promotion queues are all
sized n_fid, so adopting a state saved under Dehb::new(1, 9)
(3 fidelities) into a Dehb::new(1, 27) (4) would leave every later job
indexing past the end of a vector. Such a resume is rejected rather than
silently reinitialised, because the two ladders are two different searches
and quietly discarding the saved populations would throw away the study’s
whole history without telling anyone.
§Errors
Error::Sampler if the blob is not a DEHB blob of the expected
version, was saved for a different fidelity ladder, cannot be decoded, or
the lock is poisoned.
§fn reseed(&self, _seed: u64)
fn reseed(&self, _seed: u64)
A no-op: DEHB’s randomness is keyed on
TrialMeta::sampler_seed and the
study seed, so there is no auxiliary stream for a reseed to move — the
same argument Tpe documents.