11 |
11 |
12 use alg_tools::bisection_tree::*; |
12 use alg_tools::bisection_tree::*; |
13 use alg_tools::error::DynResult; |
13 use alg_tools::error::DynResult; |
14 use alg_tools::norms::Linfinity; |
14 use alg_tools::norms::Linfinity; |
15 |
15 |
16 use crate::ExperimentOverrides; |
16 use crate::{ExperimentOverrides, AlgorithmOverrides}; |
17 use crate::kernels::*; |
17 use crate::kernels::*; |
18 use crate::kernels::SupportProductFirst as Prod; |
18 use crate::kernels::SupportProductFirst as Prod; |
19 use crate::pdps::PDPSConfig; |
|
20 use crate::types::*; |
19 use crate::types::*; |
21 use crate::run::{ |
20 use crate::run::{ |
22 RunnableExperiment, |
21 RunnableExperiment, |
23 ExperimentV2, |
22 ExperimentV2, |
24 ExperimentBiased, |
23 ExperimentBiased, |
25 Named, |
24 Named, |
26 DefaultAlgorithm, |
25 DefaultAlgorithm, |
27 AlgorithmConfig, |
|
28 ProxTerm |
|
29 }; |
26 }; |
30 //use crate::fb::FBGenericConfig; |
27 //use crate::fb::FBGenericConfig; |
31 use crate::rand_distr::{SerializableNormal, SaltAndPepper}; |
28 use crate::rand_distr::{SerializableNormal, SaltAndPepper}; |
32 use crate::regularisation::Regularisation; |
29 use crate::regularisation::Regularisation; |
33 use alg_tools::euclidean::Euclidean; |
30 use alg_tools::euclidean::Euclidean; |
62 #[clap(name = "2d_l1")] |
59 #[clap(name = "2d_l1")] |
63 Experiment2D_L1, |
60 Experiment2D_L1, |
64 /// Two dimensions, “fast” spread, 1-norm data fidelity |
61 /// Two dimensions, “fast” spread, 1-norm data fidelity |
65 #[clap(name = "2d_l1_fast")] |
62 #[clap(name = "2d_l1_fast")] |
66 Experiment2D_L1_Fast, |
63 Experiment2D_L1_Fast, |
67 /// One dimension, “fast” spread, 2-norm-squared data fidelity with extra TV-regularised bias |
64 /// One dimension, “fast” spread, 2-norm-squared data fidelity with extra TV-regularised bias |
68 #[clap(name = "1d_tv_fast")] |
65 #[clap(name = "1d_tv_fast")] |
69 Experiment1D_TV_Fast, |
66 Experiment1D_TV_Fast, |
|
67 /// Two dimensions, “fast” spread, 2-norm-squared data fidelity with extra TV-regularised bias |
|
68 #[clap(name = "2d_tv_fast")] |
|
69 Experiment2D_TV_Fast, |
70 } |
70 } |
71 |
71 |
72 macro_rules! make_float_constant { |
72 macro_rules! make_float_constant { |
73 ($name:ident = $value:expr) => { |
73 ($name:ident = $value:expr) => { |
74 #[derive(Debug, Copy, Eq, PartialEq, Clone, Serialize, Deserialize)] |
74 #[derive(Debug, Copy, Eq, PartialEq, Clone, Serialize, Deserialize)] |
144 make_float_constant!(CutOff1 = 0.15); |
144 make_float_constant!(CutOff1 = 0.15); |
145 make_float_constant!(Hat1 = 0.16); |
145 make_float_constant!(Hat1 = 0.16); |
146 make_float_constant!(HatBias = 0.05); |
146 make_float_constant!(HatBias = 0.05); |
147 |
147 |
148 // We use a different step length for PDPS in 2D experiments |
148 // We use a different step length for PDPS in 2D experiments |
149 let pdps_2d = || { |
149 // let pdps_2d = (DefaultAlgorithm::PDPS, |
150 let τ0 = 3.0; |
150 // AlgorithmOverrides { |
151 PDPSConfig { |
151 // tau0 : Some(3.0), |
152 τ0, |
152 // sigma0 : Some(0.99 / 3.0), |
153 σ0 : 0.99 / τ0, |
153 // .. Default::default() |
|
154 // } |
|
155 // ); |
|
156 // let radon_pdps_2d = (DefaultAlgorithm::RadonPDPS, |
|
157 // AlgorithmOverrides { |
|
158 // tau0 : Some(3.0), |
|
159 // sigma0 : Some(0.99 / 3.0), |
|
160 // .. Default::default() |
|
161 // } |
|
162 // ); |
|
163 let sliding_fb_cut_gaussian = (DefaultAlgorithm::SlidingFB, |
|
164 AlgorithmOverrides { |
|
165 theta0 : Some(0.3), |
154 .. Default::default() |
166 .. Default::default() |
155 } |
167 } |
156 }; |
168 ); |
157 let defaults_2d = HashMap::from([ |
169 // let higher_cpos = |alg| (alg, |
158 (DefaultAlgorithm::PDPS, AlgorithmConfig::PDPS(pdps_2d(), ProxTerm::Wave)), |
170 // AlgorithmOverrides { |
159 (DefaultAlgorithm::RadonPDPS, AlgorithmConfig::PDPS(pdps_2d(), ProxTerm::RadonSquared)) |
171 // transport_tolerance_pos : Some(1000.0), |
160 ]); |
172 // .. Default::default() |
161 |
173 // } |
|
174 // ); |
|
175 let higher_cpos_merging = |alg| (alg, |
|
176 AlgorithmOverrides { |
|
177 transport_tolerance_pos : Some(1000.0), |
|
178 merge : Some(true), |
|
179 fitness_merging : Some(true), |
|
180 .. Default::default() |
|
181 } |
|
182 ); |
|
183 let much_higher_cpos_merging_steptune = |alg| (alg, |
|
184 AlgorithmOverrides { |
|
185 transport_tolerance_pri : Some(1000.0), |
|
186 transport_tolerance_pos : Some(10000.0), |
|
187 sigma0 : Some(0.15), |
|
188 theta0 : Some(0.3), |
|
189 merge : Some(true), |
|
190 fitness_merging : Some(true), |
|
191 .. Default::default() |
|
192 } |
|
193 ); |
162 // We add a hash of the experiment name to the configured |
194 // We add a hash of the experiment name to the configured |
163 // noise seed to not use the same noise for different experiments. |
195 // noise seed to not use the same noise for different experiments. |
164 let mut h = DefaultHasher::new(); |
196 let mut h = DefaultHasher::new(); |
165 name.hash(&mut h); |
197 name.hash(&mut h); |
166 let noise_seed = cli.noise_seed.unwrap_or(BASE_SEED) + h.finish(); |
198 let noise_seed = cli.noise_seed.unwrap_or(BASE_SEED) + h.finish(); |
167 |
199 |
|
200 let default_merge_radius = 0.01; |
|
201 |
168 use DefaultExperiment::*; |
202 use DefaultExperiment::*; |
169 Ok(match self { |
203 Ok(match self { |
170 Experiment1D => { |
204 Experiment1D => { |
171 let base_spread = Gaussian { variance : Variance1 }; |
205 let base_spread = Gaussian { variance : Variance1 }; |
172 let spread_cutoff = BallIndicator { r : CutOff1, exponent : Linfinity }; |
206 let spread_cutoff = BallIndicator { r : CutOff1, exponent : Linfinity }; |
173 Box::new(Named { name, data : ExperimentV2 { |
207 Box::new(Named { name, data : ExperimentV2 { |
174 domain : [[0.0, 1.0]].into(), |
208 domain : [[0.0, 1.0]].into(), |
175 sensor_count : [N_SENSORS_1D], |
209 sensor_count : [N_SENSORS_1D], |
176 regularisation : Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.09)), |
210 regularisation : Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.08)), |
177 noise_distr : SerializableNormal::new(0.0, cli.variance.unwrap_or(0.2))?, |
211 noise_distr : SerializableNormal::new(0.0, cli.variance.unwrap_or(0.2))?, |
178 dataterm : DataTerm::L2Squared, |
212 dataterm : DataTerm::L2Squared, |
179 μ_hat : MU_TRUE_1D_BASIC.into(), |
213 μ_hat : MU_TRUE_1D_BASIC.into(), |
180 sensor : BallIndicator { r : SensorWidth1D, exponent : Linfinity }, |
214 sensor : BallIndicator { r : SensorWidth1D, exponent : Linfinity }, |
181 spread : Prod(spread_cutoff, base_spread), |
215 spread : Prod(spread_cutoff, base_spread), |
182 kernel : Prod(AutoConvolution(spread_cutoff), base_spread), |
216 kernel : Prod(AutoConvolution(spread_cutoff), base_spread), |
183 kernel_plot_width, |
217 kernel_plot_width, |
184 noise_seed, |
218 noise_seed, |
185 algorithm_defaults: HashMap::new(), |
219 default_merge_radius, |
|
220 algorithm_overrides: HashMap::from([ |
|
221 sliding_fb_cut_gaussian, |
|
222 higher_cpos_merging(DefaultAlgorithm::RadonFB), |
|
223 higher_cpos_merging(DefaultAlgorithm::RadonSlidingFB), |
|
224 ]), |
186 }}) |
225 }}) |
187 }, |
226 }, |
188 Experiment1DFast => { |
227 Experiment1DFast => { |
189 let base_spread = HatConv { radius : Hat1 }; |
228 let base_spread = HatConv { radius : Hat1 }; |
190 Box::new(Named { name, data : ExperimentV2 { |
229 Box::new(Named { name, data : ExperimentV2 { |
215 sensor : BallIndicator { r : SensorWidth2D, exponent : Linfinity }, |
258 sensor : BallIndicator { r : SensorWidth2D, exponent : Linfinity }, |
216 spread : Prod(spread_cutoff, base_spread), |
259 spread : Prod(spread_cutoff, base_spread), |
217 kernel : Prod(AutoConvolution(spread_cutoff), base_spread), |
260 kernel : Prod(AutoConvolution(spread_cutoff), base_spread), |
218 kernel_plot_width, |
261 kernel_plot_width, |
219 noise_seed, |
262 noise_seed, |
220 algorithm_defaults: defaults_2d, |
263 default_merge_radius, |
|
264 algorithm_overrides: HashMap::from([ |
|
265 sliding_fb_cut_gaussian, |
|
266 higher_cpos_merging(DefaultAlgorithm::RadonFB), |
|
267 higher_cpos_merging(DefaultAlgorithm::RadonSlidingFB), |
|
268 // pdps_2d, |
|
269 // radon_pdps_2d |
|
270 ]), |
221 }}) |
271 }}) |
222 }, |
272 }, |
223 Experiment2DFast => { |
273 Experiment2DFast => { |
224 let base_spread = HatConv { radius : Hat1 }; |
274 let base_spread = HatConv { radius : Hat1 }; |
225 Box::new(Named { name, data : ExperimentV2 { |
275 Box::new(Named { name, data : ExperimentV2 { |
253 sensor : BallIndicator { r : SensorWidth1D, exponent : Linfinity }, |
309 sensor : BallIndicator { r : SensorWidth1D, exponent : Linfinity }, |
254 spread : Prod(spread_cutoff, base_spread), |
310 spread : Prod(spread_cutoff, base_spread), |
255 kernel : Prod(AutoConvolution(spread_cutoff), base_spread), |
311 kernel : Prod(AutoConvolution(spread_cutoff), base_spread), |
256 kernel_plot_width, |
312 kernel_plot_width, |
257 noise_seed, |
313 noise_seed, |
258 algorithm_defaults: HashMap::new(), |
314 default_merge_radius, |
|
315 algorithm_overrides: HashMap::new(), |
259 }}) |
316 }}) |
260 }, |
317 }, |
261 Experiment1D_L1_Fast => { |
318 Experiment1D_L1_Fast => { |
262 let base_spread = HatConv { radius : Hat1 }; |
319 let base_spread = HatConv { radius : Hat1 }; |
263 Box::new(Named { name, data : ExperimentV2 { |
320 Box::new(Named { name, data : ExperimentV2 { |
294 sensor : BallIndicator { r : SensorWidth2D, exponent : Linfinity }, |
352 sensor : BallIndicator { r : SensorWidth2D, exponent : Linfinity }, |
295 spread : Prod(spread_cutoff, base_spread), |
353 spread : Prod(spread_cutoff, base_spread), |
296 kernel : Prod(AutoConvolution(spread_cutoff), base_spread), |
354 kernel : Prod(AutoConvolution(spread_cutoff), base_spread), |
297 kernel_plot_width, |
355 kernel_plot_width, |
298 noise_seed, |
356 noise_seed, |
299 algorithm_defaults: defaults_2d, |
357 default_merge_radius, |
|
358 algorithm_overrides: HashMap::from([ |
|
359 // pdps_2d, |
|
360 // radon_pdps_2d |
|
361 ]), |
300 }}) |
362 }}) |
301 }, |
363 }, |
302 Experiment2D_L1_Fast => { |
364 Experiment2D_L1_Fast => { |
303 let base_spread = HatConv { radius : Hat1 }; |
365 let base_spread = HatConv { radius : Hat1 }; |
304 Box::new(Named { name, data : ExperimentV2 { |
366 Box::new(Named { name, data : ExperimentV2 { |
337 sensor : BallIndicator { r : SensorWidth1D, exponent : Linfinity }, |
403 sensor : BallIndicator { r : SensorWidth1D, exponent : Linfinity }, |
338 spread : base_spread, |
404 spread : base_spread, |
339 kernel : base_spread, |
405 kernel : base_spread, |
340 kernel_plot_width, |
406 kernel_plot_width, |
341 noise_seed, |
407 noise_seed, |
342 algorithm_defaults: HashMap::new(), |
408 default_merge_radius, |
|
409 algorithm_overrides: HashMap::from([ |
|
410 higher_cpos_merging(DefaultAlgorithm::RadonForwardPDPS), |
|
411 higher_cpos_merging(DefaultAlgorithm::RadonSlidingPDPS), |
|
412 ]), |
|
413 }, |
|
414 }}) |
|
415 }, |
|
416 Experiment2D_TV_Fast => { |
|
417 let base_spread = HatConv { radius : Hat1 }; |
|
418 Box::new(Named { name, data : ExperimentBiased { |
|
419 λ : 0.005, |
|
420 bias : MappingSum::new([ |
|
421 Weighted::new(1.0, BallCharacteristic{ center : [0.3, 0.3].into(), radius : 0.2 }), |
|
422 Weighted::new(0.5, BallCharacteristic{ center : [0.6, 0.6].into(), radius : 0.3 }), |
|
423 ]), |
|
424 base : ExperimentV2 { |
|
425 domain : [[0.0, 1.0]; 2].into(), |
|
426 sensor_count : [N_SENSORS_2D; 2], |
|
427 regularisation : Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.06)), |
|
428 noise_distr : SerializableNormal::new(0.0, cli.variance.unwrap_or(0.15))?, //0.25 |
|
429 dataterm : DataTerm::L2Squared, |
|
430 μ_hat : MU_TRUE_2D_BASIC.into(), |
|
431 sensor : BallIndicator { r : SensorWidth2D, exponent : Linfinity }, |
|
432 spread : base_spread, |
|
433 kernel : base_spread, |
|
434 kernel_plot_width, |
|
435 noise_seed, |
|
436 default_merge_radius, |
|
437 algorithm_overrides: HashMap::from([ |
|
438 much_higher_cpos_merging_steptune(DefaultAlgorithm::RadonForwardPDPS), |
|
439 much_higher_cpos_merging_steptune(DefaultAlgorithm::RadonSlidingPDPS), |
|
440 ]), |
343 }, |
441 }, |
344 }}) |
442 }}) |
345 }, |
443 }, |
346 }) |
444 }) |
347 } |
445 } |