Skip to main content

Lbfgs

Struct Lbfgs 

Source
pub struct Lbfgs<Mode = Bounded, S = MoreThuente, F = f64> { /* private fields */ }
Expand description

Limited-memory BFGS, parameterised over a type-state mode marker.

Lbfgs<Bounded> (aliased as Lbfgsb) is a faithful port of Byrd–Lu–Nocedal 1995 / Zhu–Byrd–Lu–Nocedal 1997 (ACM TOMS Alg. 778), with the Nocedal–Morales 2011 v3.0 directional-derivative + bound- backtracking deviation in subspace minimization. Iteration-wise parity with the Fortran v3.0 reference (references/lbfgsb-v3.0/) is verified by tests/lbfgsb_iter_parity.rs.

Lbfgs<Unbounded> is unconstrained limited-memory BFGS via Nocedal–Wright’s two-loop recursion (Algorithm 7.4). It reuses the same LbfgsState history machinery but skips the Cauchy / freev / subsm phases — those are box-constraint-specific. Construct with Lbfgs::<Unbounded>::new(), or transition from the default Lbfgs::<Bounded>::new() via Lbfgs::unbounded.

§Bounded mode — per-iteration outline

  1. Walks the projected gradient ray, building a piecewise-quadratic model and identifying the generalized Cauchy point xcp — the minimizer along the path (see the cauchy submodule).
  2. Restricts to the free variables at xcp and computes an approximate subspace minimizer via a structured Newton step against the limited-memory compact-form Hessian (see the subsm submodule). If the projected Newton step is infeasible, a uniform-α bound-backtracking branch fires.
  3. Performs a Moré–Thuente line search along d = z − x, safeguarded so the step is feasible.
  4. Accepts the step, updates the limited-memory (s, y) history when the curvature condition holds, and rebuilds the compact-form middle matrix T via Cholesky factorization (see compact::formt).

On a singular middle-matrix or non-positive-definite T, the solver clears the history and retries the iteration (Fortran’s goto 222 reset path). One retry is enough — after clearing, col = 0 falls through to the line-search-only path, which either succeeds with the projected steepest-descent direction or fails the whole solve.

§Unbounded mode — per-iteration outline

  1. Two-loop recursion (Nocedal–Wright Alg. 7.4) over the (s_i, y_i) history with initial Hessian H₀ = (1/θ)·I (θ = (y_last·y_last) / (s_last·y_last) after the first accepted update) to produce d = −H_k · ∇f.
  2. Moré–Thuente line search along d.
  3. Curvature-conditioned limited-memory update (same as bounded).

§Memory parameter

The history capacity m lives on LbfgsState: LbfgsState::new(x0, m). Fortran recommends m ∈ [3, 20]; m = 10 is a reasonable default.

§Termination

No solver-internal optimality test on the unbounded path — pair with the framework-level GradientTolerance. On the bounded path, a built-in projected-gradient check fires when ‖projgr(x, g, l, u)‖_∞ ≤ tol_pg (Fortran-pgtol parity); the framework-level ProjectedGradientTolerance is the canonical companion when external bookkeeping wants the same metric. Pair either mode with MaxIter, MaxCostEvals, and CostTolerance as desired.

§Backends

Generic over any parameter type implementing AsFloatSliceMut<F> + Clone + Dot<F> + ScaledAdd<F>. Built-in impls cover Vec<F>, nalgebra::DVector<F> (feature nalgebra), faer::Col<F> (feature faer), and ndarray::Array1<F> (feature ndarray). Other backends can implement the trait if their storage is contiguous.

§Examples

See Bfgs for the quasi-Newton Executor pattern. L-BFGS iterates an LbfgsState sized to the history length m (LbfgsState::new(x0, m)); construct the solver with Lbfgs::new() (L-BFGS-B, the default) or Lbfgs::<Unbounded>::new().

Implementations§

Source§

impl Lbfgs<Bounded, MoreThuente>

Source

pub fn new() -> Self

L-BFGS-B with Moré–Thuente line search and Fortran v3.0 defaults (ftol = 1e-3, gtol = 0.9, xtol = 0.1). Built-in projected-gradient tolerance is 1e-10; the seed history capacity (used only when the solver constructs the state, e.g. for memetic injection) is 10.

Source§

impl Lbfgs<Unbounded, MoreThuente>

Source

pub fn new() -> Self

Unconstrained L-BFGS with Moré–Thuente line search and the same curvature-skip / history defaults as the bounded path. The tol_pg field is unused in this mode — terminate via the framework-level GradientTolerance.

Source§

impl<S, F: Scalar> Lbfgs<Bounded, S, F>

L-BFGS-B with an explicit line-search strategy. Note: using anything other than MoreThuente forfeits iteration-wise parity with the Fortran reference. The curvature-skip threshold defaults to F::epsilon() (matching f64::EPSILON when F = f64); tol_pg defaults to 1e-10.

Source

pub fn with_tol_pg(self, tol_pg: F) -> Self

Override the built-in projected-gradient convergence tolerance. Default 1e-10; pass 0.0 to disable (Fortran-pgtol=0 semantics, used by the iteration-wise parity test). Bounded mode only — the unbounded path doesn’t compute a projected gradient.

Source

pub fn unbounded(self) -> Lbfgs<Unbounded, S, F>

Switch to the unconstrained Unbounded mode while preserving the configured line search, curvature threshold, and history capacity. Mirrors NelderMead::projected’s type-state transition.

Source§

impl<S, F: Scalar> Lbfgs<Unbounded, S, F>

Source

pub fn with_line_search(line_search: S) -> Self

Unconstrained L-BFGS with an explicit line-search strategy. The curvature-skip threshold defaults to F::epsilon() (matching f64::EPSILON when F = f64).

Source

pub fn bounded(self) -> Lbfgs<Bounded, S, F>

Switch to box-constrained Bounded mode while preserving the configured line search, curvature threshold, and history capacity. The resulting solver requires the problem to implement BoxConstraints.

Source§

impl<Mode, S, F: Scalar> Lbfgs<Mode, S, F>

Source

pub fn with_epsilon(self, epsilon: F) -> Self

Override the curvature-skip threshold. Default F::epsilon() (= f64::EPSILON when F = f64), matching Fortran’s dr ≤ epsmch · ddum test.

Source

pub fn with_m_capacity(self, m_capacity: usize) -> Self

Override the default limited-memory history capacity used when the solver constructs its own LbfgsState (memetic seeding). Standalone usage that hands in a state via LbfgsState::new(x, m) is unaffected. Default 10; Nocedal recommends [3, 20].

§Panics

Panics if m_capacity == 0.

Trait Implementations§

Source§

impl Default for Lbfgs<Bounded, MoreThuente>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Default for Lbfgs<Unbounded, MoreThuente>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<S, V, F> MemeticInner<V, F> for Lbfgs<Bounded, S, F>
where F: Scalar, V: Clone,

Source§

fn seed_scaled(&self, x: &V, _sigma: F) -> Self::State

Build a fresh inner state seeded at CMA-ES candidate x, scaled by the current step-size sigma. Called once per refined candidate per outer generation. Read more
Source§

impl<P, V, S, F> Solver<P, LbfgsState<V, F>> for Lbfgs<Bounded, S, F>
where F: Scalar, P: CostFunction<Param = V, Output = F> + Gradient<Gradient = V> + BoxConstraints, V: AsFloatSliceMut<F> + Clone + Dot<F> + ScaledAdd<F>, S: LineSearch<P, V, F, Error = P::Error>,

Source§

type Error = <P as CostFunction>::Error

Hard-abort error type — mirrors the underlying problem’s type Error. See the trait docs.
Source§

fn init( &mut self, problem: &mut Problem<P>, state: LbfgsState<V, F>, ) -> Result<LbfgsState<V, F>, Self::Error>

One-time setup before the iteration loop. Read more
Source§

fn next_iter( &mut self, problem: &mut Problem<P>, state: LbfgsState<V, F>, ) -> Result<(LbfgsState<V, F>, Option<TerminationReason>), Self::Error>

Advance one iteration. Read more
Source§

fn terminate(&self, _state: &S) -> Option<TerminationReason>

Optional pre-iteration solver-specific termination test. Read more
Source§

impl<P, V, S, F> Solver<P, LbfgsState<V, F>> for Lbfgs<Unbounded, S, F>
where F: Scalar, P: CostFunction<Param = V, Output = F> + Gradient<Gradient = V>, V: AsFloatSliceMut<F> + Clone + Dot<F> + ScaledAdd<F>, S: LineSearch<P, V, F, Error = P::Error>,

Source§

type Error = <P as CostFunction>::Error

Hard-abort error type — mirrors the underlying problem’s type Error. See the trait docs.
Source§

fn init( &mut self, problem: &mut Problem<P>, state: LbfgsState<V, F>, ) -> Result<LbfgsState<V, F>, Self::Error>

One-time setup before the iteration loop. Read more
Source§

fn next_iter( &mut self, problem: &mut Problem<P>, state: LbfgsState<V, F>, ) -> Result<(LbfgsState<V, F>, Option<TerminationReason>), Self::Error>

Advance one iteration. Read more
Source§

fn terminate(&self, _state: &S) -> Option<TerminationReason>

Optional pre-iteration solver-specific termination test. Read more
Source§

impl<Mode, S, V, F> WarmStart<V> for Lbfgs<Mode, S, F>
where F: Scalar, V: Clone,

Source§

type State = LbfgsState<V, F>

State shape this solver iterates against.
Source§

fn seed(&self, x: &V) -> LbfgsState<V, F>

Build a fresh inner state seeded at x using the solver’s natural default scale.

Auto Trait Implementations§

§

impl<Mode, S, F> Freeze for Lbfgs<Mode, S, F>
where S: Freeze, F: Freeze,

§

impl<Mode, S, F> RefUnwindSafe for Lbfgs<Mode, S, F>

§

impl<Mode, S, F> Send for Lbfgs<Mode, S, F>
where S: Send, F: Send,

§

impl<Mode, S, F> Sync for Lbfgs<Mode, S, F>
where S: Sync, F: Sync,

§

impl<Mode, S, F> Unpin for Lbfgs<Mode, S, F>
where S: Unpin, F: Unpin,

§

impl<Mode, S, F> UnsafeUnpin for Lbfgs<Mode, S, F>
where S: UnsafeUnpin, F: UnsafeUnpin,

§

impl<Mode, S, F> UnwindSafe for Lbfgs<Mode, S, F>
where S: UnwindSafe, F: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ByRef<T> for T

Source§

fn by_ref(&self) -> &T

Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Imply<T> for U
where T: ?Sized, U: ?Sized,

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V