src/prox_penalty.rs

branch
dev
changeset 51
0693cc9ba9f0
parent 39
6316d68b58af
equal deleted inserted replaced
50:39c5e6c7759d 51:0693cc9ba9f0
1 /*! 1 /*!
2 Proximal penalty abstraction 2 Proximal penalty abstraction
3 */ 3 */
4 4
5 use alg_tools::types::*;
5 use numeric_literals::replace_float_literals; 6 use numeric_literals::replace_float_literals;
6 use alg_tools::types::*; 7 use serde::{Deserialize, Serialize};
7 use serde::{Serialize, Deserialize};
8 8
9 use crate::measures::merging::SpikeMergingMethod;
10 use crate::measures::RNDM;
11 use crate::regularisation::RegTerm;
12 use crate::subproblem::InnerSettings;
13 use crate::tolerance::Tolerance;
14 use crate::types::{IterInfo, RefinementSettings};
15 use alg_tools::iterate::{AlgIterator, AlgIteratorIteration};
9 use alg_tools::mapping::RealMapping; 16 use alg_tools::mapping::RealMapping;
10 use alg_tools::nalgebra_support::ToNalgebraRealField; 17 use alg_tools::nalgebra_support::ToNalgebraRealField;
11 use alg_tools::iterate::{
12 AlgIteratorIteration,
13 AlgIterator,
14 };
15 use crate::measures::RNDM;
16 use crate::types::{
17 RefinementSettings,
18 IterInfo,
19 };
20 use crate::subproblem::InnerSettings;
21 use crate::tolerance::Tolerance;
22 use crate::measures::merging::SpikeMergingMethod;
23 use crate::regularisation::RegTerm;
24 18
19 pub mod radon_squared;
25 pub mod wave; 20 pub mod wave;
26 pub mod radon_squared;
27 pub use radon_squared::RadonSquared; 21 pub use radon_squared::RadonSquared;
28 22
29 /// Settings for the solution of the stepwise optimality condition. 23 /// Settings for the solution of the stepwise optimality condition.
30 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] 24 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)]
31 #[serde(default)] 25 #[serde(default)]
32 pub struct FBGenericConfig<F : Float> { 26 pub struct FBGenericConfig<F: Float> {
33 /// Tolerance for point insertion. 27 /// Tolerance for point insertion.
34 pub tolerance : Tolerance<F>, 28 pub tolerance: Tolerance<F>,
35 29
36 /// Stop looking for predual maximum (where to isert a new point) below 30 /// Stop looking for predual maximum (where to isert a new point) below
37 /// `tolerance` multiplied by this factor. 31 /// `tolerance` multiplied by this factor.
38 /// 32 ///
39 /// Not used by [`super::radon_fb`]. 33 /// Not used by [`crate::prox_penalty::radon_squared`].
40 pub insertion_cutoff_factor : F, 34 pub insertion_cutoff_factor: F,
41 35
42 /// Settings for branch and bound refinement when looking for predual maxima 36 /// Settings for branch and bound refinement when looking for predual maxima
43 pub refinement : RefinementSettings<F>, 37 pub refinement: RefinementSettings<F>,
44 38
45 /// Maximum insertions within each outer iteration 39 /// Maximum insertions within each outer iteration
46 /// 40 ///
47 /// Not used by [`super::radon_fb`]. 41 /// Not used by [`crate::prox_penalty::radon_squared`].
48 pub max_insertions : usize, 42 pub max_insertions: usize,
49 43
50 /// Pair `(n, m)` for maximum insertions `m` on first `n` iterations. 44 /// Pair `(n, m)` for maximum insertions `m` on first `n` iterations.
51 /// 45 ///
52 /// Not used by [`super::radon_fb`]. 46 /// Not used by [`crate::prox_penalty::radon_squared`].
53 pub bootstrap_insertions : Option<(usize, usize)>, 47 pub bootstrap_insertions: Option<(usize, usize)>,
54 48
55 /// Inner method settings 49 /// Inner method settings
56 pub inner : InnerSettings<F>, 50 pub inner: InnerSettings<F>,
57 51
58 /// Spike merging method 52 /// Spike merging method
59 pub merging : SpikeMergingMethod<F>, 53 pub merging: SpikeMergingMethod<F>,
60 54
61 /// Tolerance multiplier for merges 55 /// Tolerance multiplier for merges
62 pub merge_tolerance_mult : F, 56 pub merge_tolerance_mult: F,
63 57
64 /// Merge spikes after last step (even if merging not generally enabled) 58 /// Merge spikes after last step (even if merging not generally enabled)
65 pub final_merging : bool, 59 pub final_merging: bool,
66 60
67 /// Use fitness as merging criterion. Implies worse convergence guarantees. 61 /// Use fitness as merging criterion. Implies worse convergence guarantees.
68 pub fitness_merging : bool, 62 pub fitness_merging: bool,
69 63
70 /// Iterations between merging heuristic tries 64 /// Iterations between merging heuristic tries
71 pub merge_every : usize, 65 pub merge_every: usize,
72
73 // /// Save $μ$ for postprocessing optimisation 66 // /// Save $μ$ for postprocessing optimisation
74 // pub postprocessing : bool 67 // pub postprocessing : bool
75 } 68 }
76 69
77 #[replace_float_literals(F::cast_from(literal))] 70 #[replace_float_literals(F::cast_from(literal))]
78 impl<F : Float> Default for FBGenericConfig<F> { 71 impl<F: Float> Default for FBGenericConfig<F> {
79 fn default() -> Self { 72 fn default() -> Self {
80 FBGenericConfig { 73 FBGenericConfig {
81 tolerance : Default::default(), 74 tolerance: Default::default(),
82 insertion_cutoff_factor : 1.0, 75 insertion_cutoff_factor: 1.0,
83 refinement : Default::default(), 76 refinement: Default::default(),
84 max_insertions : 100, 77 max_insertions: 100,
85 //bootstrap_insertions : None, 78 //bootstrap_insertions : None,
86 bootstrap_insertions : Some((10, 1)), 79 bootstrap_insertions: Some((10, 1)),
87 inner : Default::default(), 80 inner: Default::default(),
88 merging : Default::default(), 81 merging: Default::default(),
89 final_merging : true, 82 final_merging: true,
90 fitness_merging : false, 83 fitness_merging: false,
91 merge_every : 10, 84 merge_every: 10,
92 merge_tolerance_mult : 2.0, 85 merge_tolerance_mult: 2.0,
93 // postprocessing : false, 86 // postprocessing : false,
94 } 87 }
95 } 88 }
96 } 89 }
97 90
98 impl<F : Float> FBGenericConfig<F> { 91 impl<F: Float> FBGenericConfig<F> {
99 /// Check if merging should be attempted this iteration 92 /// Check if merging should be attempted this iteration
100 pub fn merge_now<I : AlgIterator>(&self, state : &AlgIteratorIteration<I>) -> bool { 93 pub fn merge_now<I: AlgIterator>(&self, state: &AlgIteratorIteration<I>) -> bool {
101 self.merging.enabled && state.iteration() % self.merge_every == 0 94 self.merging.enabled && state.iteration() % self.merge_every == 0
102 } 95 }
103 96
104 /// Returns the final merging method 97 /// Returns the final merging method
105 pub fn final_merging_method(&self) -> SpikeMergingMethod<F> { 98 pub fn final_merging_method(&self) -> SpikeMergingMethod<F> {
106 SpikeMergingMethod{ enabled : self.final_merging, ..self.merging} 99 SpikeMergingMethod {
100 enabled: self.final_merging,
101 ..self.merging
102 }
107 } 103 }
108 } 104 }
109 105
110
111 /// Trait for proximal penalties 106 /// Trait for proximal penalties
112 pub trait ProxPenalty<F, PreadjointCodomain, Reg, const N : usize> 107 pub trait ProxPenalty<F, PreadjointCodomain, Reg, const N: usize>
113 where 108 where
114 F : Float + ToNalgebraRealField, 109 F: Float + ToNalgebraRealField,
115 Reg : RegTerm<F, N>, 110 Reg: RegTerm<F, N>,
116 { 111 {
117 type ReturnMapping : RealMapping<F, N>; 112 type ReturnMapping: RealMapping<F, N>;
118 113
119 /// Insert new spikes into `μ` to approximately satisfy optimality conditions 114 /// Insert new spikes into `μ` to approximately satisfy optimality conditions
120 /// with the forward step term fixed to `τv`. 115 /// with the forward step term fixed to `τv`.
121 /// 116 ///
122 /// May return `τv + w` for `w` a subdifferential of the regularisation term `reg`, 117 /// May return `τv + w` for `w` a subdifferential of the regularisation term `reg`,
123 /// as well as an indication of whether the tolerance bounds `ε` are satisfied. 118 /// as well as an indication of whether the tolerance bounds `ε` are satisfied.
124 /// 119 ///
125 /// `μ_base + ν_delta` is the base point, where `μ` and `μ_base` are assumed to have the same 120 /// `μ_base + ν_delta` is the base point, where `μ` and `μ_base` are assumed to have the same
126 /// spike locations, while `ν_delta` may have different locations. 121 /// spike locations, while `ν_delta` may have different locations.
127 /// 122 ///
128 /// `τv` is mutable to allow [`alg_tools::bisection_tree::btfn::BTFN`] refinement. 123 /// `τv` is mutable to allow [`alg_tools::bisection_tree::BTFN`] refinement.
129 /// Actual values of `τv` are not supposed to be mutated. 124 /// Actual values of `τv` are not supposed to be mutated.
130 fn insert_and_reweigh<I>( 125 fn insert_and_reweigh<I>(
131 &self, 126 &self,
132 μ : &mut RNDM<F, N>, 127 μ: &mut RNDM<F, N>,
133 τv : &mut PreadjointCodomain, 128 τv: &mut PreadjointCodomain,
134 μ_base : &RNDM<F, N>, 129 μ_base: &RNDM<F, N>,
135 ν_delta: Option<&RNDM<F, N>>, 130 ν_delta: Option<&RNDM<F, N>>,
136 τ : F, 131 τ: F,
137 ε : F, 132 ε: F,
138 config : &FBGenericConfig<F>, 133 config: &FBGenericConfig<F>,
139 reg : &Reg, 134 reg: &Reg,
140 state : &AlgIteratorIteration<I>, 135 state: &AlgIteratorIteration<I>,
141 stats : &mut IterInfo<F, N>, 136 stats: &mut IterInfo<F, N>,
142 ) -> (Option<Self::ReturnMapping>, bool) 137 ) -> (Option<Self::ReturnMapping>, bool)
143 where 138 where
144 I : AlgIterator; 139 I: AlgIterator;
145
146 140
147 /// Merge spikes, if possible. 141 /// Merge spikes, if possible.
148 /// 142 ///
149 /// Either optimality condition merging or objective value (fitness) merging 143 /// Either optimality condition merging or objective value (fitness) merging
150 /// may be used, the latter only if `fitness` is provided and `config.fitness_merging` 144 /// may be used, the latter only if `fitness` is provided and `config.fitness_merging`
151 /// is set. 145 /// is set.
152 fn merge_spikes( 146 fn merge_spikes(
153 &self, 147 &self,
154 μ : &mut RNDM<F, N>, 148 μ: &mut RNDM<F, N>,
155 τv : &mut PreadjointCodomain, 149 τv: &mut PreadjointCodomain,
156 μ_base : &RNDM<F, N>, 150 μ_base: &RNDM<F, N>,
157 ν_delta: Option<&RNDM<F, N>>, 151 ν_delta: Option<&RNDM<F, N>>,
158 τ : F, 152 τ: F,
159 ε : F, 153 ε: F,
160 config : &FBGenericConfig<F>, 154 config: &FBGenericConfig<F>,
161 reg : &Reg, 155 reg: &Reg,
162 fitness : Option<impl Fn(&RNDM<F, N>) -> F>, 156 fitness: Option<impl Fn(&RNDM<F, N>) -> F>,
163 ) -> usize; 157 ) -> usize;
164 158
165 /// Merge spikes, if possible. 159 /// Merge spikes, if possible.
166 /// 160 ///
167 /// Unlike [`merge_spikes`], this variant only supports optimality condition based merging 161 /// Unlike [`Self::merge_spikes`], this variant only supports optimality condition based merging
168 #[inline] 162 #[inline]
169 fn merge_spikes_no_fitness( 163 fn merge_spikes_no_fitness(
170 &self, 164 &self,
171 μ : &mut RNDM<F, N>, 165 μ: &mut RNDM<F, N>,
172 τv : &mut PreadjointCodomain, 166 τv: &mut PreadjointCodomain,
173 μ_base : &RNDM<F, N>, 167 μ_base: &RNDM<F, N>,
174 ν_delta: Option<&RNDM<F, N>>, 168 ν_delta: Option<&RNDM<F, N>>,
175 τ : F, 169 τ: F,
176 ε : F, 170 ε: F,
177 config : &FBGenericConfig<F>, 171 config: &FBGenericConfig<F>,
178 reg : &Reg, 172 reg: &Reg,
179 ) -> usize { 173 ) -> usize {
180 /// This is a hack to create a `None` of same type as a `Some` 174 /// This is a hack to create a `None` of same type as a `Some`
181 // for the `impl Fn` parameter of `merge_spikes`. 175 // for the `impl Fn` parameter of `merge_spikes`.
182 #[inline] 176 #[inline]
183 fn into_none<T>(_ : Option<T>) -> Option<T>{ 177 fn into_none<T>(_: Option<T>) -> Option<T> {
184 None 178 None
185 } 179 }
186 self.merge_spikes(μ, τv, μ_base, ν_delta, τ, ε, config, reg, 180 self.merge_spikes(
187 into_none(Some(|_ : &RNDM<F, N>| F::ZERO))) 181 μ,
182 τv,
183 μ_base,
184 ν_delta,
185 τ,
186 ε,
187 config,
188 reg,
189 into_none(Some(|_: &RNDM<F, N>| F::ZERO)),
190 )
188 } 191 }
189 } 192 }

mercurial