| 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 } |