argmin/solver/conjugategradient/
beta.rs

1// Copyright 2018-2020 argmin developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! # Beta update methods
9//!
10//! TODO: Proper documentation.
11//!
12//! # References:
13//!
14//! [0] Jorge Nocedal and Stephen J. Wright (2006). Numerical Optimization.
15//! Springer. ISBN 0-387-30303-0.
16
17use crate::prelude::*;
18use serde::{Deserialize, Serialize};
19
20/// Fletcher and Reeves (FR) method
21/// TODO: Reference
22#[derive(
23    Default, Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug,
24)]
25pub struct FletcherReeves {}
26
27impl FletcherReeves {
28    /// Constructor
29    pub fn new() -> Self {
30        FletcherReeves {}
31    }
32}
33
34impl<T, F> ArgminNLCGBetaUpdate<T, F> for FletcherReeves
35where
36    T: Clone + ArgminDot<T, F>,
37    F: ArgminFloat,
38{
39    fn update(&self, dfk: &T, dfk1: &T, _pk: &T) -> F {
40        dfk1.dot(&dfk1) / dfk.dot(&dfk)
41    }
42}
43
44/// Polak and Ribiere (PR) method
45/// TODO: Reference
46#[derive(
47    Default, Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug,
48)]
49pub struct PolakRibiere {}
50
51impl PolakRibiere {
52    /// Constructor
53    pub fn new() -> Self {
54        PolakRibiere {}
55    }
56}
57
58impl<T, F> ArgminNLCGBetaUpdate<T, F> for PolakRibiere
59where
60    T: Clone + ArgminDot<T, F> + ArgminSub<T, T> + ArgminNorm<F>,
61    F: ArgminFloat,
62{
63    fn update(&self, dfk: &T, dfk1: &T, _pk: &T) -> F {
64        let dfk_norm_sq = dfk.norm().powi(2);
65        dfk1.dot(&dfk1.sub(&dfk)) / dfk_norm_sq
66    }
67}
68
69/// Polak and Ribiere Plus (PR+) method
70/// TODO: Reference
71#[derive(
72    Default, Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug,
73)]
74pub struct PolakRibierePlus {}
75
76impl PolakRibierePlus {
77    /// Constructor
78    pub fn new() -> Self {
79        PolakRibierePlus {}
80    }
81}
82
83impl<T, F> ArgminNLCGBetaUpdate<T, F> for PolakRibierePlus
84where
85    T: Clone + ArgminDot<T, F> + ArgminSub<T, T> + ArgminNorm<F>,
86    F: ArgminFloat,
87{
88    fn update(&self, dfk: &T, dfk1: &T, _pk: &T) -> F {
89        let dfk_norm_sq = dfk.norm().powi(2);
90        let beta = dfk1.dot(&dfk1.sub(&dfk)) / dfk_norm_sq;
91        F::from_f64(0.0).unwrap().max(beta)
92    }
93}
94
95/// Hestenes and Stiefel (HS) method
96/// TODO: Reference
97#[derive(
98    Default, Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug,
99)]
100pub struct HestenesStiefel {}
101
102impl HestenesStiefel {
103    /// Constructor
104    pub fn new() -> Self {
105        HestenesStiefel {}
106    }
107}
108
109impl<T, F> ArgminNLCGBetaUpdate<T, F> for HestenesStiefel
110where
111    T: Clone + ArgminDot<T, F> + ArgminSub<T, T> + ArgminNorm<F>,
112    F: ArgminFloat,
113{
114    fn update(&self, dfk: &T, dfk1: &T, pk: &T) -> F {
115        let d = dfk1.sub(&dfk);
116        dfk1.dot(&d) / d.dot(&pk)
117    }
118}
119
120#[cfg(test)]
121mod tests {
122    use super::*;
123    use crate::test_trait_impl;
124
125    test_trait_impl!(fletcher_reeves, FletcherReeves);
126    test_trait_impl!(polak_ribiere, PolakRibiere);
127    test_trait_impl!(polak_ribiere_plus, PolakRibierePlus);
128    test_trait_impl!(hestenes_stiefel, HestenesStiefel);
129}