Skip to main content

conspire/math/optimize/nonlinear/step_size/barzilai_borwein/
mod.rs

1use super::StepEstimator;
2use crate::math::Scalar;
3use std::fmt::{self, Display, Formatter};
4
5/// The step sizes of Barzilai and Borwein.
6///
7/// The step along which the change in residual best matches the change in
8/// solution, which stands in for a line search where there is none.
9#[derive(Clone, Debug, Default)]
10pub struct BarzilaiBorwein {
11    pub step: Step,
12}
13
14/// Which of the two step sizes is taken.
15#[derive(Clone, Copy, Debug, Default)]
16pub enum Step {
17    /// The short step $`s^Ty/y^Ty`$.
18    #[default]
19    Short,
20    /// The long step $`s^Ts/s^Ty`$.
21    Long,
22    /// The long step and the short step in turn.
23    Alternating,
24}
25
26impl Display for BarzilaiBorwein {
27    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
28        write!(f, "BarzilaiBorwein")
29    }
30}
31
32impl StepEstimator for BarzilaiBorwein {
33    fn estimate(&self, ss: Scalar, sy: Scalar, yy: Scalar, iteration: usize) -> Scalar {
34        match self.step {
35            Step::Short => sy / yy,
36            Step::Long => ss / sy,
37            Step::Alternating => {
38                if iteration.is_multiple_of(2) {
39                    ss / sy
40                } else {
41                    sy / yy
42                }
43            }
44        }
45    }
46}