optimization_solvers/line_search/
mod.rs

1use super::*;
2pub mod backtracking;
3pub use backtracking::*;
4pub mod morethuente;
5pub use morethuente::*;
6pub mod morethuente_b;
7pub use morethuente_b::*;
8pub mod backtracking_b;
9pub use backtracking_b::*;
10pub mod gll_quadratic;
11pub use gll_quadratic::*;
12pub mod nosearch;
13pub use nosearch::*;
14pub trait LineSearch {
15    fn compute_step_len(
16        &mut self,
17        x_k: &DVector<Floating>,         // current iterate
18        eval_x_k: &FuncEvalMultivariate, // function evaluation at x_k
19        direction_k: &DVector<Floating>, // direction of the ray along which we are going to search
20        oracle: &mut impl FnMut(&DVector<Floating>) -> FuncEvalMultivariate, // oracle
21        max_iter: usize, // maximum number of iterations during line search (if direction update is costly, set this high to perform more exact line search)
22    ) -> Floating; //returns the scalar step size
23}
24
25pub trait SufficientDecreaseCondition {
26    fn c1(&self) -> Floating; // Armijo senstivity
27    fn sufficient_decrease(
28        &self,
29        f_k: &Floating,
30        f_kp1: &Floating,
31        grad_k: &DVector<Floating>,
32        t: &Floating, // step size
33        direction_k: &DVector<Floating>,
34    ) -> bool {
35        f_kp1 - f_k <= self.c1() * t * grad_k.dot(direction_k)
36    }
37}
38
39pub trait CurvatureCondition {
40    fn c2(&self) -> Floating; // curvature senstivity
41    fn curvature_condition(
42        &self,
43        grad_k: &DVector<Floating>,
44        grad_kp1: &DVector<Floating>,
45        direction_k: &DVector<Floating>,
46    ) -> bool {
47        grad_kp1.dot(direction_k) >= self.c2() * grad_k.dot(direction_k)
48    }
49    fn strong_curvature_condition(
50        &self,
51        grad_k: &DVector<Floating>,
52        grad_kp1: &DVector<Floating>,
53        direction_k: &DVector<Floating>,
54    ) -> bool {
55        grad_kp1.dot(direction_k).abs() <= self.c2() * grad_k.dot(direction_k).abs()
56    }
57}
58
59pub trait WolfeConditions: SufficientDecreaseCondition + CurvatureCondition {
60    fn wolfe_conditions_with_directional_derivative(
61        &self,
62        f_k: &Floating,
63        f_kp1: &Floating,
64        grad_k: &DVector<Floating>,
65        grad_kp1: &DVector<Floating>,
66        t: &Floating, // step size
67        direction_k: &DVector<Floating>,
68    ) -> bool {
69        self.sufficient_decrease(f_k, f_kp1, grad_k, t, direction_k)
70            && self.curvature_condition(grad_k, grad_kp1, direction_k)
71    }
72    fn strong_wolfe_conditions_with_directional_derivative(
73        &self,
74        f_k: &Floating,
75        f_kp1: &Floating,
76        grad_k: &DVector<Floating>,
77        grad_kp1: &DVector<Floating>,
78        t: &Floating, // step size
79        direction_k: &DVector<Floating>,
80    ) -> bool {
81        self.sufficient_decrease(f_k, f_kp1, grad_k, t, direction_k)
82            && self.strong_curvature_condition(grad_k, grad_kp1, direction_k)
83    }
84}
85// Blanket implementation for WolfeConditions
86impl<T> WolfeConditions for T where T: SufficientDecreaseCondition + CurvatureCondition {}