optimization_solvers/line_search/
backtracking_b.rs1use super::*;
4pub struct BackTrackingB {
5 c1: Floating, beta: Floating, lower_bound: DVector<Floating>,
8 upper_bound: DVector<Floating>,
9}
10impl BackTrackingB {
11 pub fn new(
12 c1: Floating,
13 beta: Floating,
14 lower_bound: DVector<Floating>,
15 upper_bound: DVector<Floating>,
16 ) -> Self {
17 BackTrackingB {
18 c1,
19 beta,
20 lower_bound,
21 upper_bound,
22 }
23 }
24 fn sufficient_decrease_with_bounds(
25 &self,
26 x0: &DVector<Floating>,
27 x: &DVector<Floating>,
28 f0: &Floating,
29 f: &Floating,
30 t: &Floating, ) -> bool {
32 let diff = x - x0;
33 f - f0 <= (-&self.c1 / t) * diff.dot(&diff)
34 }
35}
36
37impl HasBounds for BackTrackingB {
38 fn lower_bound(&self) -> &DVector<Floating> {
39 &self.lower_bound
40 }
41 fn upper_bound(&self) -> &DVector<Floating> {
42 &self.upper_bound
43 }
44 fn set_lower_bound(&mut self, lower_bound: DVector<Floating>) {
45 self.lower_bound = lower_bound;
46 }
47 fn set_upper_bound(&mut self, upper_bound: DVector<Floating>) {
48 self.upper_bound = upper_bound;
49 }
50}
51
52impl LineSearch for BackTrackingB {
53 fn compute_step_len(
54 &mut self,
55 x_k: &DVector<Floating>,
56 eval_x_k: &FuncEvalMultivariate,
57 direction_k: &DVector<Floating>,
58 oracle: & mut impl FnMut(&DVector<Floating>) -> FuncEvalMultivariate,
59 max_iter: usize,
60 ) -> Floating {
61 let mut t = 1.0;
62 let mut i = 0;
63
64 while max_iter > i {
65 let x_kp1 = x_k + t * direction_k;
66 let x_kp1 = x_kp1.box_projection(&self.lower_bound, &self.upper_bound);
68 let eval_kp1 = oracle(&x_kp1);
69 if eval_kp1.f().is_nan() || eval_kp1.f().is_infinite() {
71 trace!(target: "backtracking_b line search", "Step size too big: next iterate is out of domain. Decreasing step by beta ({:?})", x_kp1);
72 t *= self.beta;
73 continue;
74 }
75 if self.sufficient_decrease_with_bounds(x_k, &x_kp1, eval_x_k.f(), eval_kp1.f(), &t) {
76 trace!(target: "backtracking_b line search", "Modified Armijo rule met. Exiting with step size: {:?} at iteration {:?}", t, i);
77 return t;
78 }
79
80 t *= self.beta;
82 i += 1;
83 }
84 trace!(target: "backtracking_b line search", "Max iter reached. Early stopping.");
85 t
86 }
90}