Skip to main content

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

1use super::{LineSearchError, ResidualMerit, exhausted};
2use crate::math::Scalar;
3use std::fmt::{self, Display, Formatter};
4
5/// The Armijo condition on half the squared norm of the residual.
6#[derive(Clone, Debug)]
7pub struct Residual {
8    pub control: Scalar,
9    pub cut_back: Scalar,
10    pub max_steps: usize,
11}
12
13impl Default for Residual {
14    fn default() -> Self {
15        Self {
16            control: 1e-3,
17            cut_back: 9e-1,
18            max_steps: 100,
19        }
20    }
21}
22
23impl Display for Residual {
24    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
25        write!(f, "Residual")
26    }
27}
28
29impl ResidualMerit for Residual {
30    fn search_residual(
31        &self,
32        mut merit: impl FnMut(Scalar) -> Result<Scalar, String>,
33        value: Scalar,
34        fraction: Scalar,
35    ) -> Result<Scalar, LineSearchError> {
36        let t = self.control * 2.0 * fraction * value;
37        let mut n = 1.0;
38        for _ in 0..self.max_steps {
39            if let Ok(trial) = merit(n)
40                && value - trial >= n * t
41            {
42                return Ok(n);
43            } else {
44                n *= self.cut_back
45            }
46        }
47        Err(exhausted(self, self.max_steps))
48    }
49}