src/tolerance.rs

changeset 0
eb3c7813b67a
equal deleted inserted replaced
-1:000000000000 0:eb3c7813b67a
1 //! Tolerance update schemes for subproblem solution quality
2 use serde::{Serialize, Deserialize};
3 use numeric_literals::replace_float_literals;
4 use crate::types::*;
5
6 /// Update style for optimality system solution tolerance
7 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)]
8 #[allow(dead_code)]
9 pub enum Tolerance<F : Float> {
10 /// $ε_k = εθ^k$ for the `factor` $θ$ and initial tolerance $ε$.
11 Exponential{ factor : F, initial : F },
12 /// $ε_k = ε/(1+θk)^p$ for the `factor` $θ$, `exponent` $p$, and initial tolerance $ε$.
13 Power{ factor : F, exponent : F, initial : F},
14 /// $ε_k = εθ^{⌊k^p⌋}$ for the `factor` $θ$, initial tolerance $ε$, and exponent $p$.
15 SlowExp{ factor : F, exponent : F, initial : F }
16 }
17
18 #[replace_float_literals(F::cast_from(literal))]
19 impl<F : Float> Default for Tolerance<F> {
20 fn default() -> Self {
21 Tolerance::Power {
22 initial : 0.5,
23 factor : 0.2,
24 exponent : 1.4 // 1.5 works but is already slower in practise on our examples.
25 }
26 }
27 }
28
29 #[replace_float_literals(F::cast_from(literal))]
30 impl<F : Float> Tolerance<F> {
31 /// Get the initial tolerance
32 pub fn initial(&self) -> F {
33 match self {
34 &Tolerance::Exponential { initial, .. } => initial,
35 &Tolerance::Power { initial, .. } => initial,
36 &Tolerance::SlowExp { initial, .. } => initial,
37 }
38 }
39
40 /// Get mutable reference to the initial tolerance
41 fn initial_mut(&mut self) -> &mut F {
42 match self {
43 Tolerance::Exponential { ref mut initial, .. } => initial,
44 Tolerance::Power { ref mut initial, .. } => initial,
45 Tolerance::SlowExp { ref mut initial, .. } => initial,
46 }
47 }
48
49 /// Set the initial tolerance
50 pub fn set_initial(&mut self, set : F) {
51 *self.initial_mut() = set;
52 }
53
54 /// Update `tolerance` for iteration `iter`.
55 /// `tolerance` may or may not be used depending on the specific
56 /// update scheme.
57 pub fn update(&self, tolerance : F, iter : usize) -> F {
58 match self {
59 &Tolerance::Exponential { factor, .. } => {
60 tolerance * factor
61 },
62 &Tolerance::Power { factor, exponent, initial } => {
63 initial /(1.0 + factor * F::cast_from(iter)).powf(exponent)
64 },
65 &Tolerance::SlowExp { factor, exponent, initial } => {
66 // let m = (speed
67 // * factor.powi(-(iter as i32))
68 // * F::cast_from(iter).powf(-exponent)
69 // ).floor().as_();
70 let m = F::cast_from(iter).powf(exponent).floor().as_();
71 initial * factor.powi(m)
72 },
73 }
74 }
75 }
76
77 impl<F: Float> std::ops::MulAssign<F> for Tolerance<F> {
78 fn mul_assign(&mut self, factor : F) {
79 *self.initial_mut() *= factor;
80 }
81 }
82
83 impl<F: Float> std::ops::Mul<F> for Tolerance<F> {
84 type Output = Tolerance<F>;
85 fn mul(mut self, factor : F) -> Self::Output {
86 *self.initial_mut() *= factor;
87 self
88 }
89 }

mercurial