src/experiments.rs

branch
dev
changeset 61
4f468d35fa29
parent 45
5200e7090e06
equal deleted inserted replaced
60:9738b51d90d7 61:4f468d35fa29
1 /*! 1 /*!
2 Experimental setups. 2 Experimental setups.
3 */ 3 */
4 4
5 //use numeric_literals::replace_float_literals; 5 //use numeric_literals::replace_float_literals;
6 use serde::{Serialize, Deserialize}; 6 use crate::kernels::SupportProductFirst as Prod;
7 use clap::ValueEnum; 7 use crate::kernels::*;
8 use std::collections::HashMap; 8 use crate::run::{DefaultAlgorithm, ExperimentBiased, ExperimentV2, Named, RunnableExperiment};
9 use std::hash::{Hash, Hasher}; 9 use crate::types::*;
10 use std::collections::hash_map::DefaultHasher; 10 use crate::{AlgorithmOverrides, ExperimentSetup};
11
12 use alg_tools::bisection_tree::*; 11 use alg_tools::bisection_tree::*;
13 use alg_tools::error::DynResult; 12 use alg_tools::error::DynResult;
14 use alg_tools::norms::Linfinity; 13 use alg_tools::norms::Linfinity;
15 14 use clap::{Parser, ValueEnum};
16 use crate::{ExperimentOverrides, AlgorithmOverrides}; 15 use serde::{Deserialize, Serialize};
17 use crate::kernels::*; 16 use std::collections::hash_map::DefaultHasher;
18 use crate::kernels::SupportProductFirst as Prod; 17 use std::collections::HashMap;
19 use crate::types::*; 18 use std::hash::{Hash, Hasher};
20 use crate::run::{ 19 //use crate::fb::InsertionConfig;
21 RunnableExperiment, 20 use crate::rand_distr::{SaltAndPepper, SerializableNormal};
22 ExperimentV2,
23 ExperimentBiased,
24 Named,
25 DefaultAlgorithm,
26 };
27 //use crate::fb::FBGenericConfig;
28 use crate::rand_distr::{SerializableNormal, SaltAndPepper};
29 use crate::regularisation::Regularisation; 21 use crate::regularisation::Regularisation;
30 use alg_tools::euclidean::Euclidean; 22 use alg_tools::euclidean::Euclidean;
31 use alg_tools::instance::Instance; 23 use alg_tools::instance::Instance;
32 use alg_tools::mapping::Mapping; 24 use alg_tools::mapping::Mapping;
33 use alg_tools::operator_arithmetic::{MappingSum, Weighted}; 25 use alg_tools::operator_arithmetic::{MappingSum, Weighted};
26 use itertools::Itertools;
27 use serde_with::skip_serializing_none;
34 28
35 /// Experiments shorthands, to be used with the command line parser 29 /// Experiments shorthands, to be used with the command line parser
36
37 #[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] 30 #[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
38 #[allow(non_camel_case_types)] 31 #[allow(non_camel_case_types)]
39 pub enum DefaultExperiment { 32 pub enum DefaultExperiment {
40 /// One dimension, cut gaussian spread, 2-norm-squared data fidelity 33 /// One dimension, cut gaussian spread, 2-norm-squared data fidelity
41 #[clap(name = "1d")] 34 #[clap(name = "1d")]
67 /// Two dimensions, “fast” spread, 2-norm-squared data fidelity with extra TV-regularised bias 60 /// Two dimensions, “fast” spread, 2-norm-squared data fidelity with extra TV-regularised bias
68 #[clap(name = "2d_tv_fast")] 61 #[clap(name = "2d_tv_fast")]
69 Experiment2D_TV_Fast, 62 Experiment2D_TV_Fast,
70 } 63 }
71 64
65 /// Command line experiment setup overrides
66 #[skip_serializing_none]
67 #[derive(Parser, Debug, Serialize, Deserialize, Default, Clone, Hash)]
68 pub struct DefaultExperimentSetup<F: ClapFloat> {
69 /// List of experiments to perform
70 #[arg(value_name = "EXPERIMENT")]
71 experiments: Vec<DefaultExperiment>,
72
73 #[arg(long)]
74 /// Regularisation parameter override.
75 ///
76 /// Only use if running just a single experiment, as different experiments have different
77 /// regularisation parameters.
78 alpha: Option<F>,
79
80 #[arg(long)]
81 /// Gaussian noise variance override
82 variance: Option<F>,
83
84 #[arg(long, value_names = &["MAGNITUDE", "PROBABILITY"])]
85 /// Salt and pepper noise override.
86 salt_and_pepper: Option<Vec<F>>,
87
88 #[arg(long)]
89 /// Noise seed
90 noise_seed: Option<u64>,
91 }
92
72 macro_rules! make_float_constant { 93 macro_rules! make_float_constant {
73 ($name:ident = $value:expr) => { 94 ($name:ident = $value:expr) => {
74 #[derive(Debug, Copy, Eq, PartialEq, Clone, Serialize, Deserialize)] 95 #[derive(Debug, Copy, Eq, PartialEq, Clone, Serialize, Deserialize)]
75 #[serde(into = "float")] 96 #[serde(into = "float")]
76 struct $name; 97 struct $name;
77 impl Into<float> for $name { 98 impl Into<f64> for $name {
78 #[inline] 99 #[inline]
79 fn into(self) -> float { $value } 100 fn into(self) -> float {
101 $value
102 }
80 } 103 }
81 impl Constant for $name { 104 impl Constant for $name {
82 type Type = float; 105 type Type = float;
83 fn value(&self) -> float { $value } 106 fn value(&self) -> float {
107 $value
108 }
84 } 109 }
85 } 110 };
86 } 111 }
87 112
88 /// Ground-truth measure spike locations and magnitudes for 1D experiments 113 /// Ground-truth measure spike locations and magnitudes for 1D experiments
89 static MU_TRUE_1D_BASIC : [(float, float); 4] = [ 114 static MU_TRUE_1D_BASIC: [(float, float); 4] =
90 (0.10, 10.0), 115 [(0.10, 10.0), (0.30, 2.0), (0.70, 3.0), (0.80, 5.0)];
91 (0.30, 2.0),
92 (0.70, 3.0),
93 (0.80, 5.0)
94 ];
95 116
96 /// Ground-truth measure spike locations and magnitudes for 2D experiments 117 /// Ground-truth measure spike locations and magnitudes for 2D experiments
97 static MU_TRUE_2D_BASIC : [([float; 2], float); 4] = [ 118 static MU_TRUE_2D_BASIC: [([float; 2], float); 4] = [
98 ([0.15, 0.15], 10.0), 119 ([0.15, 0.15], 10.0),
99 ([0.75, 0.45], 2.0), 120 ([0.75, 0.45], 2.0),
100 ([0.80, 0.50], 4.0), 121 ([0.80, 0.50], 4.0),
101 ([0.30, 0.70], 5.0) 122 ([0.30, 0.70], 5.0),
102 ]; 123 ];
103 124
104 /// The $\{0,1\}$-valued characteristic function of a ball as a [`Mapping`]. 125 /// The $\{0,1\}$-valued characteristic function of a ball as a [`Mapping`].
105 #[derive(Debug,Copy,Clone,Serialize,PartialEq)] 126 #[derive(Debug, Copy, Clone, Serialize, PartialEq)]
106 struct BallCharacteristic<F : Float, const N : usize> { 127 struct BallCharacteristic<F: Float, const N: usize> {
107 pub center : Loc<F, N>, 128 pub center: Loc<N, F>,
108 pub radius : F, 129 pub radius: F,
109 } 130 }
110 131
111 impl<F : Float, const N : usize> Mapping<Loc<F, N>> for BallCharacteristic<F, N> { 132 impl<F: Float, const N: usize> Mapping<Loc<N, F>> for BallCharacteristic<F, N> {
112 type Codomain =F; 133 type Codomain = F;
113 134
114 fn apply<I : Instance<Loc<F, N>>>(&self, i : I) -> F { 135 fn apply<I: Instance<Loc<N, F>>>(&self, i: I) -> F {
115 if self.center.dist2(i) <= self.radius { 136 if self.center.dist2(i) <= self.radius {
116 F::ONE 137 F::ONE
117 } else { 138 } else {
118 F::ZERO 139 F::ZERO
119 } 140 }
120 } 141 }
121 } 142 }
122 143
144 /// Trait for customising the experiments available from the command line
145 impl ExperimentSetup for DefaultExperimentSetup<f64> {
146 type FloatType = f64;
147
148 fn runnables(&self) -> DynResult<Vec<Box<dyn RunnableExperiment<Self::FloatType>>>> {
149 self.experiments
150 .iter()
151 .unique()
152 .map(|e| e.get_experiment(self))
153 .try_collect()
154 }
155 }
156
123 //#[replace_float_literals(F::cast_from(literal))] 157 //#[replace_float_literals(F::cast_from(literal))]
124 impl DefaultExperiment { 158 impl DefaultExperiment {
159 // fn default_list() -> Vec<Self> {
160 // use DefaultExperiment::*;
161 // [
162 // Experiment1D,
163 // Experiment1DFast,
164 // Experiment2D,
165 // Experiment2DFast,
166 // Experiment1D_L1,
167 // ]
168 // .into()
169 // }
170
125 /// Convert the experiment shorthand into a runnable experiment configuration. 171 /// Convert the experiment shorthand into a runnable experiment configuration.
126 pub fn get_experiment(&self, cli : &ExperimentOverrides<float>) -> DynResult<Box<dyn RunnableExperiment<float>>> { 172 fn get_experiment(
127 let name = "pointsource".to_string() 173 &self,
128 + self.to_possible_value().unwrap().get_name(); 174 cli: &DefaultExperimentSetup<f64>,
175 ) -> DynResult<Box<dyn RunnableExperiment<f64>>> {
176 let name = "pointsource".to_string() + self.to_possible_value().unwrap().get_name();
129 177
130 let kernel_plot_width = 0.2; 178 let kernel_plot_width = 0.2;
131 179
132 const BASE_SEED : u64 = 915373234; 180 const BASE_SEED: u64 = 915373234;
133 181
134 const N_SENSORS_1D : usize = 100; 182 const N_SENSORS_1D: usize = 100;
135 make_float_constant!(SensorWidth1D = 0.4/(N_SENSORS_1D as float)); 183 make_float_constant!(SensorWidth1D = 0.4 / (N_SENSORS_1D as float));
136 184
137 const N_SENSORS_2D : usize = 16; 185 const N_SENSORS_2D: usize = 16;
138 make_float_constant!(SensorWidth2D = 0.4/(N_SENSORS_2D as float)); 186 make_float_constant!(SensorWidth2D = 0.4 / (N_SENSORS_2D as float));
139 187
140 const N_SENSORS_2D_MORE : usize = 32; 188 //const N_SENSORS_2D_MORE: usize = 32;
141 make_float_constant!(SensorWidth2DMore = 0.4/(N_SENSORS_2D_MORE as float)); 189 //make_float_constant!(SensorWidth2DMore = 0.4 / (N_SENSORS_2D_MORE as float));
142 190
143 make_float_constant!(Variance1 = 0.05.powi(2)); 191 make_float_constant!(Variance1 = 0.05.powi(2));
144 make_float_constant!(CutOff1 = 0.15); 192 make_float_constant!(CutOff1 = 0.15);
145 make_float_constant!(Hat1 = 0.16); 193 make_float_constant!(Hat1 = 0.16);
146 make_float_constant!(HatBias = 0.05); 194 make_float_constant!(HatBias = 0.05);
158 // tau0 : Some(3.0), 206 // tau0 : Some(3.0),
159 // sigma0 : Some(0.99 / 3.0), 207 // sigma0 : Some(0.99 / 3.0),
160 // .. Default::default() 208 // .. Default::default()
161 // } 209 // }
162 // ); 210 // );
163 let sliding_fb_cut_gaussian = (DefaultAlgorithm::SlidingFB, 211 let sliding_fb_cut_gaussian = (DefaultAlgorithm::SlidingFB, AlgorithmOverrides {
164 AlgorithmOverrides { 212 theta0: Some(0.3),
165 theta0 : Some(0.3), 213 ..Default::default()
166 .. Default::default() 214 });
167 }
168 );
169 // let higher_cpos = |alg| (alg, 215 // let higher_cpos = |alg| (alg,
170 // AlgorithmOverrides { 216 // AlgorithmOverrides {
171 // transport_tolerance_pos : Some(1000.0), 217 // transport_tolerance_pos : Some(1000.0),
172 // .. Default::default() 218 // .. Default::default()
173 // } 219 // }
174 // ); 220 // );
175 let higher_cpos_merging = |alg| (alg, 221 let higher_cpos_merging = |alg| {
176 AlgorithmOverrides { 222 (alg, AlgorithmOverrides {
177 transport_tolerance_pos : Some(1000.0), 223 transport_tolerance_pos: Some(1000.0),
178 merge : Some(true), 224 merge: Some(true),
179 fitness_merging : Some(true), 225 fitness_merging: Some(true),
180 .. Default::default() 226 ..Default::default()
181 } 227 })
182 ); 228 };
183 let higher_cpos_merging_steptune = |alg| (alg, 229 let higher_cpos_merging_steptune = |alg| {
184 AlgorithmOverrides { 230 (alg, AlgorithmOverrides {
185 transport_tolerance_pos : Some(1000.0), 231 transport_tolerance_pos: Some(1000.0),
186 theta0 : Some(0.3), 232 theta0: Some(0.3),
187 merge : Some(true), 233 merge: Some(true),
188 fitness_merging : Some(true), 234 fitness_merging: Some(true),
189 .. Default::default() 235 ..Default::default()
190 } 236 })
191 ); 237 };
192 let much_higher_cpos_merging_steptune = |alg| (alg, 238 let much_higher_cpos_merging_steptune = |alg| {
193 AlgorithmOverrides { 239 (alg, AlgorithmOverrides {
194 transport_tolerance_pos : Some(10000.0), 240 transport_tolerance_pos: Some(10000.0),
195 sigma0 : Some(0.15), 241 sigma0: Some(0.15),
196 theta0 : Some(0.3), 242 theta0: Some(0.3),
197 merge : Some(true), 243 merge: Some(true),
198 fitness_merging : Some(true), 244 fitness_merging: Some(true),
199 .. Default::default() 245 ..Default::default()
200 } 246 })
201 ); 247 };
202 // We add a hash of the experiment name to the configured 248 // We add a hash of the experiment name to the configured
203 // noise seed to not use the same noise for different experiments. 249 // noise seed to not use the same noise for different experiments.
204 let mut h = DefaultHasher::new(); 250 let mut h = DefaultHasher::new();
205 name.hash(&mut h); 251 name.hash(&mut h);
206 let noise_seed = cli.noise_seed.unwrap_or(BASE_SEED) + h.finish(); 252 let noise_seed = cli.noise_seed.unwrap_or(BASE_SEED) + h.finish();
208 let default_merge_radius = 0.01; 254 let default_merge_radius = 0.01;
209 255
210 use DefaultExperiment::*; 256 use DefaultExperiment::*;
211 Ok(match self { 257 Ok(match self {
212 Experiment1D => { 258 Experiment1D => {
213 let base_spread = Gaussian { variance : Variance1 }; 259 let base_spread = Gaussian { variance: Variance1 };
214 let spread_cutoff = BallIndicator { r : CutOff1, exponent : Linfinity }; 260 let spread_cutoff = BallIndicator { r: CutOff1, exponent: Linfinity };
215 Box::new(Named { name, data : ExperimentV2 { 261 Box::new(Named {
216 domain : [[0.0, 1.0]].into(), 262 name,
217 sensor_count : [N_SENSORS_1D], 263 data: ExperimentV2 {
218 regularisation : Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.08)), 264 domain: [[0.0, 1.0]].into(),
219 noise_distr : SerializableNormal::new(0.0, cli.variance.unwrap_or(0.2))?, 265 sensor_count: [N_SENSORS_1D],
220 dataterm : DataTerm::L2Squared, 266 regularisation: Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.08)),
221 μ_hat : MU_TRUE_1D_BASIC.into(), 267 noise_distr: SerializableNormal::new(0.0, cli.variance.unwrap_or(0.2))?,
222 sensor : BallIndicator { r : SensorWidth1D, exponent : Linfinity }, 268 dataterm: DataTermType::L222,
223 spread : Prod(spread_cutoff, base_spread), 269 μ_hat: MU_TRUE_1D_BASIC.into(),
224 kernel : Prod(AutoConvolution(spread_cutoff), base_spread), 270 sensor: BallIndicator { r: SensorWidth1D, exponent: Linfinity },
225 kernel_plot_width, 271 spread: Prod(spread_cutoff, base_spread),
226 noise_seed, 272 kernel: Prod(AutoConvolution(spread_cutoff), base_spread),
227 default_merge_radius, 273 kernel_plot_width,
228 algorithm_overrides: HashMap::from([ 274 noise_seed,
229 sliding_fb_cut_gaussian, 275 default_merge_radius,
230 higher_cpos_merging(DefaultAlgorithm::RadonFB), 276 algorithm_overrides: HashMap::from([
231 higher_cpos_merging(DefaultAlgorithm::RadonSlidingFB), 277 sliding_fb_cut_gaussian,
232 ]), 278 higher_cpos_merging(DefaultAlgorithm::RadonFB),
233 }}) 279 higher_cpos_merging(DefaultAlgorithm::RadonSlidingFB),
234 }, 280 ]),
281 },
282 })
283 }
235 Experiment1DFast => { 284 Experiment1DFast => {
236 let base_spread = HatConv { radius : Hat1 }; 285 let base_spread = HatConv { radius: Hat1 };
237 Box::new(Named { name, data : ExperimentV2 { 286 Box::new(Named {
238 domain : [[0.0, 1.0]].into(), 287 name,
239 sensor_count : [N_SENSORS_1D], 288 data: ExperimentV2 {
240 regularisation : Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.06)), 289 domain: [[0.0, 1.0]].into(),
241 noise_distr : SerializableNormal::new(0.0, cli.variance.unwrap_or(0.2))?, 290 sensor_count: [N_SENSORS_1D],
242 dataterm : DataTerm::L2Squared, 291 regularisation: Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.06)),
243 μ_hat : MU_TRUE_1D_BASIC.into(), 292 noise_distr: SerializableNormal::new(0.0, cli.variance.unwrap_or(0.2))?,
244 sensor : BallIndicator { r : SensorWidth1D, exponent : Linfinity }, 293 dataterm: DataTermType::L222,
245 spread : base_spread, 294 μ_hat: MU_TRUE_1D_BASIC.into(),
246 kernel : base_spread, 295 sensor: BallIndicator { r: SensorWidth1D, exponent: Linfinity },
247 kernel_plot_width, 296 spread: base_spread,
248 noise_seed, 297 kernel: base_spread,
249 default_merge_radius, 298 kernel_plot_width,
250 algorithm_overrides: HashMap::from([ 299 noise_seed,
251 higher_cpos_merging(DefaultAlgorithm::RadonFB), 300 default_merge_radius,
252 higher_cpos_merging(DefaultAlgorithm::RadonSlidingFB), 301 algorithm_overrides: HashMap::from([
253 ]), 302 higher_cpos_merging(DefaultAlgorithm::RadonFB),
254 }}) 303 higher_cpos_merging(DefaultAlgorithm::RadonSlidingFB),
255 }, 304 ]),
305 },
306 })
307 }
256 Experiment2D => { 308 Experiment2D => {
257 let base_spread = Gaussian { variance : Variance1 }; 309 let base_spread = Gaussian { variance: Variance1 };
258 let spread_cutoff = BallIndicator { r : CutOff1, exponent : Linfinity }; 310 let spread_cutoff = BallIndicator { r: CutOff1, exponent: Linfinity };
259 Box::new(Named { name, data : ExperimentV2 { 311 Box::new(Named {
260 domain : [[0.0, 1.0]; 2].into(), 312 name,
261 sensor_count : [N_SENSORS_2D; 2], 313 data: ExperimentV2 {
262 regularisation : Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.19)), 314 domain: [[0.0, 1.0]; 2].into(),
263 noise_distr : SerializableNormal::new(0.0, cli.variance.unwrap_or(0.25))?, 315 sensor_count: [N_SENSORS_2D; 2],
264 dataterm : DataTerm::L2Squared, 316 regularisation: Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.19)),
265 μ_hat : MU_TRUE_2D_BASIC.into(), 317 noise_distr: SerializableNormal::new(0.0, cli.variance.unwrap_or(0.25))?,
266 sensor : BallIndicator { r : SensorWidth2D, exponent : Linfinity }, 318 dataterm: DataTermType::L222,
267 spread : Prod(spread_cutoff, base_spread), 319 μ_hat: MU_TRUE_2D_BASIC.into(),
268 kernel : Prod(AutoConvolution(spread_cutoff), base_spread), 320 sensor: BallIndicator { r: SensorWidth2D, exponent: Linfinity },
269 kernel_plot_width, 321 spread: Prod(spread_cutoff, base_spread),
270 noise_seed, 322 kernel: Prod(AutoConvolution(spread_cutoff), base_spread),
271 default_merge_radius, 323 kernel_plot_width,
272 algorithm_overrides: HashMap::from([ 324 noise_seed,
273 sliding_fb_cut_gaussian, 325 default_merge_radius,
274 higher_cpos_merging(DefaultAlgorithm::RadonFB), 326 algorithm_overrides: HashMap::from([
275 higher_cpos_merging(DefaultAlgorithm::RadonSlidingFB), 327 sliding_fb_cut_gaussian,
276 ]), 328 higher_cpos_merging(DefaultAlgorithm::RadonFB),
277 }}) 329 higher_cpos_merging(DefaultAlgorithm::RadonSlidingFB),
278 }, 330 ]),
331 },
332 })
333 }
279 Experiment2DFast => { 334 Experiment2DFast => {
280 let base_spread = HatConv { radius : Hat1 }; 335 let base_spread = HatConv { radius: Hat1 };
281 Box::new(Named { name, data : ExperimentV2 { 336 Box::new(Named {
282 domain : [[0.0, 1.0]; 2].into(), 337 name,
283 sensor_count : [N_SENSORS_2D; 2], 338 data: ExperimentV2 {
284 regularisation : Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.12)), 339 domain: [[0.0, 1.0]; 2].into(),
285 noise_distr : SerializableNormal::new(0.0, cli.variance.unwrap_or(0.15))?, //0.25 340 sensor_count: [N_SENSORS_2D; 2],
286 dataterm : DataTerm::L2Squared, 341 regularisation: Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.12)),
287 μ_hat : MU_TRUE_2D_BASIC.into(), 342 noise_distr: SerializableNormal::new(0.0, cli.variance.unwrap_or(0.15))?, //0.25
288 sensor : BallIndicator { r : SensorWidth2D, exponent : Linfinity }, 343 dataterm: DataTermType::L222,
289 spread : base_spread, 344 μ_hat: MU_TRUE_2D_BASIC.into(),
290 kernel : base_spread, 345 sensor: BallIndicator { r: SensorWidth2D, exponent: Linfinity },
291 kernel_plot_width, 346 spread: base_spread,
292 noise_seed, 347 kernel: base_spread,
293 default_merge_radius, 348 kernel_plot_width,
294 algorithm_overrides: HashMap::from([ 349 noise_seed,
295 higher_cpos_merging(DefaultAlgorithm::RadonFB), 350 default_merge_radius,
296 higher_cpos_merging(DefaultAlgorithm::RadonSlidingFB), 351 algorithm_overrides: HashMap::from([
297 ]), 352 higher_cpos_merging(DefaultAlgorithm::RadonFB),
298 }}) 353 higher_cpos_merging(DefaultAlgorithm::RadonSlidingFB),
299 }, 354 ]),
355 },
356 })
357 }
300 Experiment1D_L1 => { 358 Experiment1D_L1 => {
301 let base_spread = Gaussian { variance : Variance1 }; 359 let base_spread = Gaussian { variance: Variance1 };
302 let spread_cutoff = BallIndicator { r : CutOff1, exponent : Linfinity }; 360 let spread_cutoff = BallIndicator { r: CutOff1, exponent: Linfinity };
303 Box::new(Named { name, data : ExperimentV2 { 361 Box::new(Named {
304 domain : [[0.0, 1.0]].into(), 362 name,
305 sensor_count : [N_SENSORS_1D], 363 data: ExperimentV2 {
306 regularisation : Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.1)), 364 domain: [[0.0, 1.0]].into(),
307 noise_distr : SaltAndPepper::new( 365 sensor_count: [N_SENSORS_1D],
308 cli.salt_and_pepper.as_ref().map_or(0.6, |v| v[0]), 366 regularisation: Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.1)),
309 cli.salt_and_pepper.as_ref().map_or(0.4, |v| v[1]) 367 noise_distr: SaltAndPepper::new(
310 )?, 368 cli.salt_and_pepper.as_ref().map_or(0.6, |v| v[0]),
311 dataterm : DataTerm::L1, 369 cli.salt_and_pepper.as_ref().map_or(0.4, |v| v[1]),
312 μ_hat : MU_TRUE_1D_BASIC.into(), 370 )?,
313 sensor : BallIndicator { r : SensorWidth1D, exponent : Linfinity }, 371 dataterm: DataTermType::L1,
314 spread : Prod(spread_cutoff, base_spread), 372 μ_hat: MU_TRUE_1D_BASIC.into(),
315 kernel : Prod(AutoConvolution(spread_cutoff), base_spread), 373 sensor: BallIndicator { r: SensorWidth1D, exponent: Linfinity },
316 kernel_plot_width, 374 spread: Prod(spread_cutoff, base_spread),
317 noise_seed, 375 kernel: Prod(AutoConvolution(spread_cutoff), base_spread),
318 default_merge_radius, 376 kernel_plot_width,
319 algorithm_overrides: HashMap::new(), 377 noise_seed,
320 }}) 378 default_merge_radius,
321 }, 379 algorithm_overrides: HashMap::new(),
380 },
381 })
382 }
322 Experiment1D_L1_Fast => { 383 Experiment1D_L1_Fast => {
323 let base_spread = HatConv { radius : Hat1 }; 384 let base_spread = HatConv { radius: Hat1 };
324 Box::new(Named { name, data : ExperimentV2 { 385 Box::new(Named {
325 domain : [[0.0, 1.0]].into(), 386 name,
326 sensor_count : [N_SENSORS_1D], 387 data: ExperimentV2 {
327 regularisation : Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.12)), 388 domain: [[0.0, 1.0]].into(),
328 noise_distr : SaltAndPepper::new( 389 sensor_count: [N_SENSORS_1D],
329 cli.salt_and_pepper.as_ref().map_or(0.6, |v| v[0]), 390 regularisation: Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.12)),
330 cli.salt_and_pepper.as_ref().map_or(0.4, |v| v[1]) 391 noise_distr: SaltAndPepper::new(
331 )?, 392 cli.salt_and_pepper.as_ref().map_or(0.6, |v| v[0]),
332 dataterm : DataTerm::L1, 393 cli.salt_and_pepper.as_ref().map_or(0.4, |v| v[1]),
333 μ_hat : MU_TRUE_1D_BASIC.into(), 394 )?,
334 sensor : BallIndicator { r : SensorWidth1D, exponent : Linfinity }, 395 dataterm: DataTermType::L1,
335 spread : base_spread, 396 μ_hat: MU_TRUE_1D_BASIC.into(),
336 kernel : base_spread, 397 sensor: BallIndicator { r: SensorWidth1D, exponent: Linfinity },
337 kernel_plot_width, 398 spread: base_spread,
338 noise_seed, 399 kernel: base_spread,
339 default_merge_radius, 400 kernel_plot_width,
340 algorithm_overrides: HashMap::new(), 401 noise_seed,
341 }}) 402 default_merge_radius,
342 }, 403 algorithm_overrides: HashMap::new(),
404 },
405 })
406 }
343 Experiment2D_L1 => { 407 Experiment2D_L1 => {
344 let base_spread = Gaussian { variance : Variance1 }; 408 let base_spread = Gaussian { variance: Variance1 };
345 let spread_cutoff = BallIndicator { r : CutOff1, exponent : Linfinity }; 409 let spread_cutoff = BallIndicator { r: CutOff1, exponent: Linfinity };
346 Box::new(Named { name, data : ExperimentV2 { 410 Box::new(Named {
347 domain : [[0.0, 1.0]; 2].into(), 411 name,
348 sensor_count : [N_SENSORS_2D; 2], 412 data: ExperimentV2 {
349 regularisation : Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.35)), 413 domain: [[0.0, 1.0]; 2].into(),
350 noise_distr : SaltAndPepper::new( 414 sensor_count: [N_SENSORS_2D; 2],
351 cli.salt_and_pepper.as_ref().map_or(0.8, |v| v[0]), 415 regularisation: Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.35)),
352 cli.salt_and_pepper.as_ref().map_or(0.2, |v| v[1]) 416 noise_distr: SaltAndPepper::new(
353 )?, 417 cli.salt_and_pepper.as_ref().map_or(0.8, |v| v[0]),
354 dataterm : DataTerm::L1, 418 cli.salt_and_pepper.as_ref().map_or(0.2, |v| v[1]),
355 μ_hat : MU_TRUE_2D_BASIC.into(), 419 )?,
356 sensor : BallIndicator { r : SensorWidth2D, exponent : Linfinity }, 420 dataterm: DataTermType::L1,
357 spread : Prod(spread_cutoff, base_spread), 421 μ_hat: MU_TRUE_2D_BASIC.into(),
358 kernel : Prod(AutoConvolution(spread_cutoff), base_spread), 422 sensor: BallIndicator { r: SensorWidth2D, exponent: Linfinity },
359 kernel_plot_width, 423 spread: Prod(spread_cutoff, base_spread),
360 noise_seed, 424 kernel: Prod(AutoConvolution(spread_cutoff), base_spread),
361 default_merge_radius, 425 kernel_plot_width,
362 algorithm_overrides: HashMap::from([ 426 noise_seed,
363 ]), 427 default_merge_radius,
364 }}) 428 algorithm_overrides: HashMap::from([]),
365 }, 429 },
430 })
431 }
366 Experiment2D_L1_Fast => { 432 Experiment2D_L1_Fast => {
367 let base_spread = HatConv { radius : Hat1 }; 433 let base_spread = HatConv { radius: Hat1 };
368 Box::new(Named { name, data : ExperimentV2 { 434 Box::new(Named {
369 domain : [[0.0, 1.0]; 2].into(), 435 name,
370 sensor_count : [N_SENSORS_2D; 2], 436 data: ExperimentV2 {
371 regularisation : Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.40)), 437 domain: [[0.0, 1.0]; 2].into(),
372 noise_distr : SaltAndPepper::new( 438 sensor_count: [N_SENSORS_2D; 2],
373 cli.salt_and_pepper.as_ref().map_or(0.8, |v| v[0]), 439 regularisation: Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.40)),
374 cli.salt_and_pepper.as_ref().map_or(0.2, |v| v[1]) 440 noise_distr: SaltAndPepper::new(
375 )?, 441 cli.salt_and_pepper.as_ref().map_or(0.8, |v| v[0]),
376 dataterm : DataTerm::L1, 442 cli.salt_and_pepper.as_ref().map_or(0.2, |v| v[1]),
377 μ_hat : MU_TRUE_2D_BASIC.into(), 443 )?,
378 sensor : BallIndicator { r : SensorWidth2D, exponent : Linfinity }, 444 dataterm: DataTermType::L1,
379 spread : base_spread, 445 μ_hat: MU_TRUE_2D_BASIC.into(),
380 kernel : base_spread, 446 sensor: BallIndicator { r: SensorWidth2D, exponent: Linfinity },
381 kernel_plot_width, 447 spread: base_spread,
382 noise_seed, 448 kernel: base_spread,
383 default_merge_radius, 449 kernel_plot_width,
384 algorithm_overrides: HashMap::from([ 450 noise_seed,
385 ]), 451 default_merge_radius,
386 }}) 452 algorithm_overrides: HashMap::from([]),
387 }, 453 },
454 })
455 }
388 Experiment1D_TV_Fast => { 456 Experiment1D_TV_Fast => {
389 let base_spread = HatConv { radius : HatBias }; 457 let base_spread = HatConv { radius: HatBias };
390 Box::new(Named { name, data : ExperimentBiased { 458 Box::new(Named {
391 λ : 0.02, 459 name,
392 bias : MappingSum::new([ 460 data: ExperimentBiased {
393 Weighted::new(1.0, BallCharacteristic{ center : 0.3.into(), radius : 0.2 }), 461 λ: 0.02,
394 Weighted::new(0.5, BallCharacteristic{ center : 0.6.into(), radius : 0.3 }), 462 bias: MappingSum::new([
395 ]), 463 Weighted::new(1.0, BallCharacteristic {
396 base : ExperimentV2 { 464 center: 0.3.into(),
397 domain : [[0.0, 1.0]].into(), 465 radius: 0.2,
398 sensor_count : [N_SENSORS_1D], 466 }),
399 regularisation : Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.2)), 467 Weighted::new(0.5, BallCharacteristic {
400 noise_distr : SerializableNormal::new(0.0, cli.variance.unwrap_or(0.1))?, 468 center: 0.6.into(),
401 dataterm : DataTerm::L2Squared, 469 radius: 0.3,
402 μ_hat : MU_TRUE_1D_BASIC.into(), 470 }),
403 sensor : BallIndicator { r : SensorWidth1D, exponent : Linfinity },
404 spread : base_spread,
405 kernel : base_spread,
406 kernel_plot_width,
407 noise_seed,
408 default_merge_radius,
409 algorithm_overrides: HashMap::from([
410 higher_cpos_merging_steptune(DefaultAlgorithm::RadonForwardPDPS),
411 higher_cpos_merging_steptune(DefaultAlgorithm::RadonSlidingPDPS),
412 ]), 471 ]),
413 }, 472 base: ExperimentV2 {
414 }}) 473 domain: [[0.0, 1.0]].into(),
415 }, 474 sensor_count: [N_SENSORS_1D],
475 regularisation: Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.2)),
476 noise_distr: SerializableNormal::new(0.0, cli.variance.unwrap_or(0.1))?,
477 dataterm: DataTermType::L222,
478 μ_hat: MU_TRUE_1D_BASIC.into(),
479 sensor: BallIndicator { r: SensorWidth1D, exponent: Linfinity },
480 spread: base_spread,
481 kernel: base_spread,
482 kernel_plot_width,
483 noise_seed,
484 default_merge_radius,
485 algorithm_overrides: HashMap::from([
486 higher_cpos_merging_steptune(DefaultAlgorithm::RadonForwardPDPS),
487 higher_cpos_merging_steptune(DefaultAlgorithm::RadonSlidingPDPS),
488 ]),
489 },
490 },
491 })
492 }
416 Experiment2D_TV_Fast => { 493 Experiment2D_TV_Fast => {
417 let base_spread = HatConv { radius : Hat1 }; 494 let base_spread = HatConv { radius: Hat1 };
418 Box::new(Named { name, data : ExperimentBiased { 495 Box::new(Named {
419 λ : 0.005, 496 name,
420 bias : MappingSum::new([ 497 data: ExperimentBiased {
421 Weighted::new(1.0, BallCharacteristic{ center : [0.3, 0.3].into(), radius : 0.2 }), 498 λ: 0.005,
422 Weighted::new(0.5, BallCharacteristic{ center : [0.6, 0.6].into(), radius : 0.3 }), 499 bias: MappingSum::new([
423 ]), 500 Weighted::new(1.0, BallCharacteristic {
424 base : ExperimentV2 { 501 center: [0.3, 0.3].into(),
425 domain : [[0.0, 1.0]; 2].into(), 502 radius: 0.2,
426 sensor_count : [N_SENSORS_2D; 2], 503 }),
427 regularisation : Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.06)), 504 Weighted::new(0.5, BallCharacteristic {
428 noise_distr : SerializableNormal::new(0.0, cli.variance.unwrap_or(0.15))?, //0.25 505 center: [0.6, 0.6].into(),
429 dataterm : DataTerm::L2Squared, 506 radius: 0.3,
430 μ_hat : MU_TRUE_2D_BASIC.into(), 507 }),
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 ]), 508 ]),
441 }, 509 base: ExperimentV2 {
442 }}) 510 domain: [[0.0, 1.0]; 2].into(),
443 }, 511 sensor_count: [N_SENSORS_2D; 2],
512 regularisation: Regularisation::NonnegRadon(cli.alpha.unwrap_or(0.06)),
513 noise_distr: SerializableNormal::new(
514 0.0,
515 cli.variance.unwrap_or(0.15),
516 )?, //0.25
517 dataterm: DataTermType::L222,
518 μ_hat: MU_TRUE_2D_BASIC.into(),
519 sensor: BallIndicator { r: SensorWidth2D, exponent: Linfinity },
520 spread: base_spread,
521 kernel: base_spread,
522 kernel_plot_width,
523 noise_seed,
524 default_merge_radius,
525 algorithm_overrides: HashMap::from([
526 much_higher_cpos_merging_steptune(
527 DefaultAlgorithm::RadonForwardPDPS,
528 ),
529 much_higher_cpos_merging_steptune(
530 DefaultAlgorithm::RadonSlidingPDPS,
531 ),
532 ]),
533 },
534 },
535 })
536 }
444 }) 537 })
445 } 538 }
446 } 539 }
447

mercurial