pub struct Bobyqa<Mode = Bounded, F = f64> { /* private fields */ }Expand description
BOBYQA (Powell 2009): bound-constrained model-based derivative-free trust-region optimization.
Configure the trust-region radii and interpolation-set size, then drive it
with an Executor over a BobyqaState on a problem
that implements CostFunction + BoxConstraints:
use basin::{BoxConstraints, CostFunction, Executor, Bobyqa, BobyqaState, MaxCostEvals};
struct Booth {
lower: Vec<f64>,
upper: Vec<f64>,
}
impl CostFunction for Booth {
type Param = Vec<f64>;
type Output = f64;
type Error = std::convert::Infallible;
fn cost(&self, x: &Vec<f64>) -> Result<f64, std::convert::Infallible> {
Ok((x[0] + 2.0 * x[1] - 7.0).powi(2) + (2.0 * x[0] + x[1] - 5.0).powi(2))
}
}
impl BoxConstraints for Booth {
fn lower(&self) -> &Vec<f64> { &self.lower }
fn upper(&self) -> &Vec<f64> { &self.upper }
}
let problem = Booth { lower: vec![-5.0, -5.0], upper: vec![5.0, 5.0] };
let solver = Bobyqa::new().with_rho_beg(0.5).with_rho_end(1e-8);
let state = BobyqaState::new(vec![0.0, 0.0]);
let result = Executor::new(problem, solver, state)
.terminate_on(MaxCostEvals(500))
.run()
.unwrap();
assert!(result.best_param()[0].is_finite());§Configuration
with_rho_beg— initial trust-region radiusρ_beg(default1.0). Also the initialΔ. The initial sampling needs roomb_i ≥ a_i + 2ρ_beg(Powell 2009, eq. 2.1); ifρ_begis too large for a narrow box it is reduced tomin(b_i − a_i)/4(withρ_endpulled down to match), mirroring PRIMA rather than rejecting the solve.with_rho_end— final radiusρ_end(default1e-6); must satisfyρ_beg > ρ_end > 0.with_npt— interpolation-set sizenpt, in[2n+1, ½(n+1)(n+2)](default2n+1).
§Panics
Executor::run panics (in init) if the start point
is empty, if npt is outside [2n+1, ½(n+1)(n+2)] (the n+2 ≤ npt ≤ 2n
partial-model regime is not yet implemented), or if after the narrow-box
revision ρ_beg > ρ_end > 0 cannot hold (e.g. a degenerate b_i = a_i).
§RESCUE
The full method of RESCUE (Powell 2009, §5 — restoring the interpolation set when rounding damages the update denominator) is implemented and wired, but it fires only on severely ill-conditioned geometry. As Powell and PRIMA both note, it is essentially never invoked on well-behaved problems without heavy noise on the objective; expect it to stay dormant in normal use.
§Backends
Backend-generic over the parameter vector: Vec<f64>, nalgebra, ndarray, and
faer all work — the parameter type needs only Clone, VectorLen, and
Index/IndexMut element access. The model algebra is internal pure-Rust
Vec<f64> scratch, so no linalg-tier op is required. wasm-clean.
§References
M. J. D. Powell, The BOBYQA algorithm for bound constrained optimization without derivatives, DAMTP report 2009/NA06, University of Cambridge. Cross-validated against PRIMA v0.7.2.
Implementations§
Source§impl<F: Scalar> Bobyqa<Bounded, F>
impl<F: Scalar> Bobyqa<Bounded, F>
Sourcepub fn new() -> Self
pub fn new() -> Self
A BOBYQA solver with the default schedule (ρ_beg = 1, ρ_end = 1e-6,
npt = 2n+1). Tune with the with_* builders.
Sourcepub fn with_rho_beg(self, rho_beg: F) -> Self
pub fn with_rho_beg(self, rho_beg: F) -> Self
Set the initial trust-region radius ρ_beg (also the initial Δ).
Sourcepub fn with_rho_end(self, rho_end: F) -> Self
pub fn with_rho_end(self, rho_end: F) -> Self
Set the final trust-region radius ρ_end. Must satisfy ρ_beg > ρ_end > 0.
Trait Implementations§
Source§impl<V, F> InitialState<V> for Bobyqa<Bounded, F>
impl<V, F> InitialState<V> for Bobyqa<Bounded, F>
Source§impl<P, V, F> Solver<P, BobyqaState<V, F>> for Bobyqa<Bounded, F>where
F: Scalar,
P: CostFunction<Param = V, Output = F> + BoxConstraints,
V: Clone + VectorLen + Index<usize, Output = F> + IndexMut<usize, Output = F>,
impl<P, V, F> Solver<P, BobyqaState<V, F>> for Bobyqa<Bounded, F>where
F: Scalar,
P: CostFunction<Param = V, Output = F> + BoxConstraints,
V: Clone + VectorLen + Index<usize, Output = F> + IndexMut<usize, Output = F>,
Source§type Error = <P as CostFunction>::Error
type Error = <P as CostFunction>::Error
type Error. See the trait docs.Source§fn init(
&mut self,
problem: &mut Problem<P>,
state: BobyqaState<V, F>,
) -> Result<BobyqaState<V, F>, Self::Error>
fn init( &mut self, problem: &mut Problem<P>, state: BobyqaState<V, F>, ) -> Result<BobyqaState<V, F>, Self::Error>
Source§fn next_iter(
&mut self,
problem: &mut Problem<P>,
state: BobyqaState<V, F>,
) -> Result<(BobyqaState<V, F>, Option<TerminationReason>), Self::Error>
fn next_iter( &mut self, problem: &mut Problem<P>, state: BobyqaState<V, F>, ) -> Result<(BobyqaState<V, F>, Option<TerminationReason>), Self::Error>
Auto Trait Implementations§
impl<Mode, F> Freeze for Bobyqa<Mode, F>where
F: Freeze,
impl<Mode, F> RefUnwindSafe for Bobyqa<Mode, F>where
F: RefUnwindSafe,
impl<Mode, F> Send for Bobyqa<Mode, F>where
F: Send,
impl<Mode, F> Sync for Bobyqa<Mode, F>where
F: Sync,
impl<Mode, F> Unpin for Bobyqa<Mode, F>where
F: Unpin,
impl<Mode, F> UnsafeUnpin for Bobyqa<Mode, F>where
F: UnsafeUnpin,
impl<Mode, F> UnwindSafe for Bobyqa<Mode, F>where
F: UnwindSafe,
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.