Skip to main content

conspire/math/optimize/globalization/line_search/goldstein/
mod.rs

1use super::{LineSearchError, ObjectiveMerit, backtrack, backtrack_merit};
2use crate::math::{Erase, Jacobian, Quantity, Scalar, Solution, Tensor};
3use std::{
4    fmt::{self, Display, Formatter},
5    ops::Mul,
6};
7
8/// The Goldstein conditions on the objective.
9#[derive(Clone, Debug)]
10pub struct Goldstein {
11    pub control: Scalar,
12    pub cut_back: Scalar,
13    pub max_steps: usize,
14}
15
16impl Display for Goldstein {
17    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
18        write!(f, "Goldstein")
19    }
20}
21
22impl Goldstein {
23    fn accepts(&self, decrease: Scalar, n: Scalar, slope: Scalar) -> bool {
24        !(n * (1.0 - self.control) * slope < decrease || decrease < n * self.control * slope)
25    }
26}
27
28impl ObjectiveMerit for Goldstein {
29    fn search<X, J, D, W, E>(
30        &self,
31        function: impl FnMut(&X, Scalar) -> Result<Scalar, String>,
32        _jacobian: impl FnMut(&X) -> Result<J, String>,
33        argument: &X,
34        jacobian0: &J,
35        decrement: &D,
36        step_size: Scalar,
37    ) -> Result<Scalar, LineSearchError>
38    where
39        J: Erase<Erased = E> + Jacobian,
40        D: Erase<Erased = E>,
41        E: Tensor,
42        X: Solution,
43        for<'a> &'a D: Mul<Quantity<W>, Output = X>,
44    {
45        backtrack(
46            self,
47            self.cut_back,
48            self.max_steps,
49            function,
50            argument,
51            jacobian0,
52            decrement,
53            step_size,
54            |decrease, n, slope| self.accepts(decrease, n, slope),
55        )
56    }
57    fn search_merit(
58        &self,
59        merit: impl FnMut(Scalar) -> Result<Scalar, String>,
60        value: Scalar,
61        slope: Scalar,
62        step_size: Scalar,
63    ) -> Result<Scalar, LineSearchError> {
64        backtrack_merit(
65            self,
66            self.cut_back,
67            self.max_steps,
68            merit,
69            value,
70            slope,
71            step_size,
72            |decrease, n, slope| self.accepts(decrease, n, slope),
73        )
74    }
75}