pub mod backtracking;
pub mod hager_zhang;
pub mod more_thuente;
pub mod wolfe;
pub use backtracking::Backtracking;
pub use hager_zhang::HagerZhang;
pub use more_thuente::MoreThuente;
pub use wolfe::Wolfe;
use crate::core::math::Scalar;
use crate::core::problem::Problem;
#[derive(Debug, Clone, Copy, PartialEq)]
#[non_exhaustive]
pub enum LineSearchOutcome<F> {
Step(F),
Failed,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub struct LineSearchEvaluation<V, F> {
pub param: V,
pub cost: F,
pub gradient: V,
}
impl<V, F> LineSearchEvaluation<V, F> {
pub fn new(param: V, cost: F, gradient: V) -> Self {
Self {
param,
cost,
gradient,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub struct LineSearchResult<V, F> {
pub outcome: LineSearchOutcome<F>,
pub evaluation: Option<LineSearchEvaluation<V, F>>,
}
impl<V, F> LineSearchResult<V, F> {
pub fn new(outcome: LineSearchOutcome<F>) -> Self {
Self {
outcome,
evaluation: None,
}
}
pub fn with_evaluation(step: F, param: V, cost: F, gradient: V) -> Self {
Self {
outcome: LineSearchOutcome::Step(step),
evaluation: Some(LineSearchEvaluation::new(param, cost, gradient)),
}
}
}
pub trait LineSearch<P, V, F = f64> {
type Error;
fn next(
&mut self,
problem: &mut Problem<P>,
param: &V,
cost: F,
gradient: &V,
direction: &V,
) -> Result<F, Self::Error>;
fn next_with_outcome(
&mut self,
problem: &mut Problem<P>,
param: &V,
cost: F,
gradient: &V,
direction: &V,
) -> Result<LineSearchOutcome<F>, Self::Error> {
self.next(problem, param, cost, gradient, direction)
.map(LineSearchOutcome::Step)
}
fn next_with_evaluation(
&mut self,
problem: &mut Problem<P>,
param: &V,
cost: F,
gradient: &V,
direction: &V,
) -> Result<LineSearchResult<V, F>, Self::Error> {
self.next_with_outcome(problem, param, cost, gradient, direction)
.map(LineSearchResult::new)
}
}
pub struct Constant<F = f64>(pub F);
impl<F: Scalar> Constant<F> {
pub fn new(alpha: F) -> Self {
Self(alpha)
}
}
impl<P, V, F> LineSearch<P, V, F> for Constant<F>
where
P: crate::core::problem::CostFunction,
F: Scalar,
{
type Error = P::Error;
fn next(
&mut self,
_problem: &mut Problem<P>,
_param: &V,
_cost: F,
_gradient: &V,
_direction: &V,
) -> Result<F, Self::Error> {
Ok(self.0)
}
}