pub struct Stepper<P, S, So> { /* private fields */ }Expand description
Drive a solver one iteration at a time.
Owns the problem, state, solver and termination criteria, runs
solver.init exactly once on construction, and exposes
step/run_to_end so callers can
interleave their own work between iterations: recording trajectories,
animating from a UI, pausing on a button press, evaluating a custom
budget, etc.
Executor::run is self.into_stepper().run_to_end(); the stepper
is the building block, the executor is the convenience wrapper.
§Example
let solver = solver.with_absolute_gradient_tolerance(1e-6);
let mut stepper = Executor::new(problem, solver, state)
.max_iter(100)
.into_stepper()?;
let reason = loop {
match stepper.step()? {
StepOutcome::Continue => { /* observe `stepper.state()` */ }
StepOutcome::Stopped(reason) => break reason,
}
};Implementations§
Source§impl<P, S, So> Stepper<P, S, So>
impl<P, S, So> Stepper<P, S, So>
Sourcepub fn counts(&self) -> &EvalCounts
pub fn counts(&self) -> &EvalCounts
Wrapper-side evaluation counters. These are authoritative:
solvers can only call into the user’s problem through the
wrapper, so every cost/gradient/residual/Jacobian /
Hessian call is reflected here. The state mirror under
state is refreshed after every successful
Solver::init /
Solver::next_iter;
on the typed-Err path the state slot is dropped (see
step) but counts is still readable here for
diagnostics.
Sourcepub fn finished(&self) -> Option<&TerminationReason>
pub fn finished(&self) -> Option<&TerminationReason>
Termination reason if the stepper has stopped, else None.
Sourcepub fn step(&mut self) -> Result<StepOutcome, So::Error>
pub fn step(&mut self) -> Result<StepOutcome, So::Error>
Advance one iteration. Once a Stopped outcome has been returned
the stepper is sticky: subsequent calls keep returning the same
Stopped(reason) without touching the state or solver.
Registered observers fire here:
observe_iter on
StepOutcome::Continue, gated by each observer’s
ObserverMode; observe_final once
when this call first returns StepOutcome::Stopped. See the
observer module for the lifecycle.
Returns Err when the underlying problem returns Err from any
cost/gradient/residual/Jacobian/Hessian call during the
step. A hard error consumes the state and may leave solver machinery
partially updated. It does not set finished.
Callers can inspect counts, then drop the stepper or
call into_checkpoint, which returns None.
State access and further stepping are not supported after the error.
Observers and checkpoint sinks do not fire on the failed transition.
Sourcepub fn run_to_end(self) -> Result<OptimizationResult<S>, So::Error>
pub fn run_to_end(self) -> Result<OptimizationResult<S>, So::Error>
Drive step to completion and return an
OptimizationResult.
Use run_to_end_with_solver to retain
the final solver and raw evaluation counters as well.
Sourcepub fn run_to_end_with_solver(
self,
) -> Result<OptimizationResultWithSolver<S, So>, So::Error>
pub fn run_to_end_with_solver( self, ) -> Result<OptimizationResultWithSolver<S, So>, So::Error>
Drive step to completion, retaining the final solver,
state, raw evaluation counters, and termination reason by ownership.
Uses the same lifecycle as run_to_end, including
observer and checkpoint callbacks. An already-stopped stepper returns
its recorded reason without repeating final callbacks. No Clone or
serialization bounds are required.
Returns the solver’s error on a failed transition, without a partial
result or recoverable checkpoint. Calling this after a previous
step error is unsupported, just as with run_to_end.
Sourcepub fn into_checkpoint(self) -> Option<ExactCheckpoint<So, S>>
pub fn into_checkpoint(self) -> Option<ExactCheckpoint<So, S>>
Consume the stepper into a checkpoint at its current boundary.
Returns Some after successful initialization, between completed
steps, or after a clean stop (including cancellation and a mid-step
stop). Returns None after a hard step error consumed
the state; partial solver machinery cannot form an exact checkpoint.
Moves the solver and state and copies the authoritative counters
without requiring Clone or serialization. Extraction performs no
evaluations, convergence checks, or observer/checkpoint callbacks.
The problem, execution policy, and any recorded termination reason
are dropped. Resume through Executor::resume_from_checkpoint,
which describes the requirements for exact continuation.
§Example
use basin::{CostFunction, Executor, NelderMead, State};
struct Sphere;
impl CostFunction for Sphere {
type Param = Vec<f64>;
type Output = f64;
type Error = std::convert::Infallible;
fn cost(&self, x: &Vec<f64>) -> Result<f64, Self::Error> {
Ok(x.iter().map(|v| v * v).sum())
}
}
let mut stepper = Executor::from_start(
Sphere, NelderMead::new(), vec![2.0, 1.0],
).into_stepper()?;
stepper.step()?;
let checkpoint = stepper.into_checkpoint().unwrap();
assert_eq!(checkpoint.state().iter(), 1);
let result = Executor::resume_from_checkpoint(Sphere, checkpoint)
.max_iter(10)
.run()?;
assert_eq!(result.iter(), 10);Sourcepub fn into_state(self) -> S
pub fn into_state(self) -> S
Auto Trait Implementations§
impl<P, S, So> !RefUnwindSafe for Stepper<P, S, So>
impl<P, S, So> !Send for Stepper<P, S, So>
impl<P, S, So> !Sync for Stepper<P, S, So>
impl<P, S, So> !UnwindSafe for Stepper<P, S, So>
impl<P, S, So> Freeze for Stepper<P, S, So>where
Problem<P>: Freeze,
Option<S>: Freeze,
So: Freeze,
RunControl<S>: Freeze,
Vec<(Box<dyn Observe<S>>, ObserverMode)>: Freeze,
Vec<(Box<dyn CheckpointSink<So, S>>, ObserverMode)>: Freeze,
impl<P, S, So> Unpin for Stepper<P, S, So>where
Problem<P>: Unpin,
Option<S>: Unpin,
So: Unpin,
RunControl<S>: Unpin,
Vec<(Box<dyn Observe<S>>, ObserverMode)>: Unpin,
Vec<(Box<dyn CheckpointSink<So, S>>, ObserverMode)>: Unpin,
impl<P, S, So> UnsafeUnpin for Stepper<P, S, So>where
Problem<P>: UnsafeUnpin,
Option<S>: UnsafeUnpin,
So: UnsafeUnpin,
RunControl<S>: UnsafeUnpin,
Vec<(Box<dyn Observe<S>>, ObserverMode)>: UnsafeUnpin,
Vec<(Box<dyn CheckpointSink<So, S>>, ObserverMode)>: UnsafeUnpin,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<T, U> Imply<T> for U
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.