Wed, 22 Mar 2023 20:37:49 +0200
Bump version
0 | 1 | /*! |
2 | This module provides [`RunnableExperiment`] for running chosen algorithms on a chosen experiment. | |
3 | */ | |
4 | ||
5 | use numeric_literals::replace_float_literals; | |
6 | use colored::Colorize; | |
7 | use serde::{Serialize, Deserialize}; | |
8 | use serde_json; | |
9 | use nalgebra::base::DVector; | |
10 | use std::hash::Hash; | |
11 | use chrono::{DateTime, Utc}; | |
12 | use cpu_time::ProcessTime; | |
13 | use clap::ValueEnum; | |
14 | use std::collections::HashMap; | |
15 | use std::time::Instant; | |
16 | ||
17 | use rand::prelude::{ | |
18 | StdRng, | |
19 | SeedableRng | |
20 | }; | |
21 | use rand_distr::Distribution; | |
22 | ||
23 | use alg_tools::bisection_tree::*; | |
24 | use alg_tools::iterate::{ | |
25 | Timed, | |
26 | AlgIteratorOptions, | |
27 | Verbose, | |
28 | AlgIteratorFactory, | |
29 | }; | |
30 | use alg_tools::logger::Logger; | |
31 | use alg_tools::error::DynError; | |
32 | use alg_tools::tabledump::TableDump; | |
33 | use alg_tools::sets::Cube; | |
34 | use alg_tools::mapping::RealMapping; | |
35 | use alg_tools::nalgebra_support::ToNalgebraRealField; | |
36 | use alg_tools::euclidean::Euclidean; | |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
37 | use alg_tools::norms::L1; |
0 | 38 | use alg_tools::lingrid::lingrid; |
39 | use alg_tools::sets::SetOrd; | |
40 | ||
41 | use crate::kernels::*; | |
42 | use crate::types::*; | |
43 | use crate::measures::*; | |
44 | use crate::measures::merging::SpikeMerging; | |
45 | use crate::forward_model::*; | |
46 | use crate::fb::{ | |
47 | FBConfig, | |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
48 | pointsource_fb_reg, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
49 | FBMetaAlgorithm, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
50 | FBGenericConfig, |
0 | 51 | }; |
52 | use crate::pdps::{ | |
53 | PDPSConfig, | |
54 | L2Squared, | |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
55 | pointsource_pdps_reg, |
0 | 56 | }; |
57 | use crate::frank_wolfe::{ | |
58 | FWConfig, | |
59 | FWVariant, | |
25
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
60 | pointsource_fw_reg, |
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
61 | WeightOptim, |
0 | 62 | }; |
63 | use crate::subproblem::InnerSettings; | |
64 | use crate::seminorms::*; | |
65 | use crate::plot::*; | |
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
66 | use crate::{AlgorithmOverrides, CommandLineArgs}; |
20
90f77ad9a98d
Added command line option for (power) tolerance
Tuomo Valkonen <tuomov@iki.fi>
parents:
9
diff
changeset
|
67 | use crate::tolerance::Tolerance; |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
68 | use crate::regularisation::{Regularisation, RadonRegTerm, NonnegRadonRegTerm}; |
0 | 69 | |
70 | /// Available algorithms and their configurations | |
71 | #[derive(Copy, Clone, Debug, Serialize, Deserialize)] | |
72 | pub enum AlgorithmConfig<F : Float> { | |
73 | FB(FBConfig<F>), | |
74 | FW(FWConfig<F>), | |
75 | PDPS(PDPSConfig<F>), | |
76 | } | |
77 | ||
20
90f77ad9a98d
Added command line option for (power) tolerance
Tuomo Valkonen <tuomov@iki.fi>
parents:
9
diff
changeset
|
78 | fn unpack_tolerance<F : Float>(v : &Vec<F>) -> Tolerance<F> { |
90f77ad9a98d
Added command line option for (power) tolerance
Tuomo Valkonen <tuomov@iki.fi>
parents:
9
diff
changeset
|
79 | assert!(v.len() == 3); |
90f77ad9a98d
Added command line option for (power) tolerance
Tuomo Valkonen <tuomov@iki.fi>
parents:
9
diff
changeset
|
80 | Tolerance::Power { initial : v[0], factor : v[1], exponent : v[2] } |
90f77ad9a98d
Added command line option for (power) tolerance
Tuomo Valkonen <tuomov@iki.fi>
parents:
9
diff
changeset
|
81 | } |
90f77ad9a98d
Added command line option for (power) tolerance
Tuomo Valkonen <tuomov@iki.fi>
parents:
9
diff
changeset
|
82 | |
0 | 83 | impl<F : ClapFloat> AlgorithmConfig<F> { |
84 | /// Override supported parameters based on the command line. | |
85 | pub fn cli_override(self, cli : &AlgorithmOverrides<F>) -> Self { | |
86 | let override_fb_generic = |g : FBGenericConfig<F>| { | |
87 | FBGenericConfig { | |
88 | bootstrap_insertions : cli.bootstrap_insertions | |
89 | .as_ref() | |
90 | .map_or(g.bootstrap_insertions, | |
91 | |n| Some((n[0], n[1]))), | |
92 | merge_every : cli.merge_every.unwrap_or(g.merge_every), | |
93 | merging : cli.merging.clone().unwrap_or(g.merging), | |
94 | final_merging : cli.final_merging.clone().unwrap_or(g.final_merging), | |
20
90f77ad9a98d
Added command line option for (power) tolerance
Tuomo Valkonen <tuomov@iki.fi>
parents:
9
diff
changeset
|
95 | tolerance: cli.tolerance.as_ref().map(unpack_tolerance).unwrap_or(g.tolerance), |
0 | 96 | .. g |
97 | } | |
98 | }; | |
99 | ||
100 | use AlgorithmConfig::*; | |
101 | match self { | |
102 | FB(fb) => FB(FBConfig { | |
103 | τ0 : cli.tau0.unwrap_or(fb.τ0), | |
104 | insertion : override_fb_generic(fb.insertion), | |
105 | .. fb | |
106 | }), | |
107 | PDPS(pdps) => PDPS(PDPSConfig { | |
108 | τ0 : cli.tau0.unwrap_or(pdps.τ0), | |
109 | σ0 : cli.sigma0.unwrap_or(pdps.σ0), | |
110 | acceleration : cli.acceleration.unwrap_or(pdps.acceleration), | |
111 | insertion : override_fb_generic(pdps.insertion), | |
112 | .. pdps | |
113 | }), | |
114 | FW(fw) => FW(FWConfig { | |
115 | merging : cli.merging.clone().unwrap_or(fw.merging), | |
20
90f77ad9a98d
Added command line option for (power) tolerance
Tuomo Valkonen <tuomov@iki.fi>
parents:
9
diff
changeset
|
116 | tolerance : cli.tolerance.as_ref().map(unpack_tolerance).unwrap_or(fw.tolerance), |
0 | 117 | .. fw |
118 | }) | |
119 | } | |
120 | } | |
121 | } | |
122 | ||
123 | /// Helper struct for tagging and [`AlgorithmConfig`] or [`Experiment`] with a name. | |
124 | #[derive(Clone, Debug, Serialize, Deserialize)] | |
125 | pub struct Named<Data> { | |
126 | pub name : String, | |
127 | #[serde(flatten)] | |
128 | pub data : Data, | |
129 | } | |
130 | ||
131 | /// Shorthand algorithm configurations, to be used with the command line parser | |
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
132 | #[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] |
0 | 133 | pub enum DefaultAlgorithm { |
134 | /// The μFB forward-backward method | |
135 | #[clap(name = "fb")] | |
136 | FB, | |
137 | /// The μFISTA inertial forward-backward method | |
138 | #[clap(name = "fista")] | |
139 | FISTA, | |
140 | /// The “fully corrective” conditional gradient method | |
141 | #[clap(name = "fw")] | |
142 | FW, | |
143 | /// The “relaxed conditional gradient method | |
144 | #[clap(name = "fwrelax")] | |
145 | FWRelax, | |
146 | /// The μPDPS primal-dual proximal splitting method | |
147 | #[clap(name = "pdps")] | |
148 | PDPS, | |
149 | } | |
150 | ||
151 | impl DefaultAlgorithm { | |
152 | /// Returns the algorithm configuration corresponding to the algorithm shorthand | |
153 | pub fn default_config<F : Float>(&self) -> AlgorithmConfig<F> { | |
154 | use DefaultAlgorithm::*; | |
155 | match *self { | |
156 | FB => AlgorithmConfig::FB(Default::default()), | |
157 | FISTA => AlgorithmConfig::FB(FBConfig{ | |
158 | meta : FBMetaAlgorithm::InertiaFISTA, | |
159 | .. Default::default() | |
160 | }), | |
161 | FW => AlgorithmConfig::FW(Default::default()), | |
162 | FWRelax => AlgorithmConfig::FW(FWConfig{ | |
163 | variant : FWVariant::Relaxed, | |
164 | .. Default::default() | |
165 | }), | |
166 | PDPS => AlgorithmConfig::PDPS(Default::default()), | |
167 | } | |
168 | } | |
169 | ||
170 | /// Returns the [`Named`] algorithm corresponding to the algorithm shorthand | |
171 | pub fn get_named<F : Float>(&self) -> Named<AlgorithmConfig<F>> { | |
172 | self.to_named(self.default_config()) | |
173 | } | |
174 | ||
175 | pub fn to_named<F : Float>(self, alg : AlgorithmConfig<F>) -> Named<AlgorithmConfig<F>> { | |
176 | let name = self.to_possible_value().unwrap().get_name().to_string(); | |
177 | Named{ name , data : alg } | |
178 | } | |
179 | } | |
180 | ||
181 | ||
182 | // // Floats cannot be hashed directly, so just hash the debug formatting | |
183 | // // for use as file identifier. | |
184 | // impl<F : Float> Hash for AlgorithmConfig<F> { | |
185 | // fn hash<H: Hasher>(&self, state: &mut H) { | |
186 | // format!("{:?}", self).hash(state); | |
187 | // } | |
188 | // } | |
189 | ||
190 | /// Plotting level configuration | |
191 | #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, ValueEnum, Debug)] | |
192 | pub enum PlotLevel { | |
193 | /// Plot nothing | |
194 | #[clap(name = "none")] | |
195 | None, | |
196 | /// Plot problem data | |
197 | #[clap(name = "data")] | |
198 | Data, | |
199 | /// Plot iterationwise state | |
200 | #[clap(name = "iter")] | |
201 | Iter, | |
202 | } | |
203 | ||
204 | type DefaultBT<F, const N : usize> = BT< | |
205 | DynamicDepth, | |
206 | F, | |
207 | usize, | |
208 | Bounds<F>, | |
209 | N | |
210 | >; | |
211 | type DefaultSeminormOp<F, K, const N : usize> = ConvolutionOp<F, K, DefaultBT<F, N>, N>; | |
212 | type DefaultSG<F, Sensor, Spread, const N : usize> = SensorGrid::< | |
213 | F, | |
214 | Sensor, | |
215 | Spread, | |
216 | DefaultBT<F, N>, | |
217 | N | |
218 | >; | |
219 | ||
220 | /// This is a dirty workaround to rust-csv not supporting struct flattening etc. | |
221 | #[derive(Serialize)] | |
222 | struct CSVLog<F> { | |
223 | iter : usize, | |
224 | cpu_time : f64, | |
225 | value : F, | |
226 | post_value : F, | |
227 | n_spikes : usize, | |
228 | inner_iters : usize, | |
229 | merged : usize, | |
230 | pruned : usize, | |
231 | this_iters : usize, | |
232 | } | |
233 | ||
234 | /// Collected experiment statistics | |
235 | #[derive(Clone, Debug, Serialize)] | |
236 | struct ExperimentStats<F : Float> { | |
237 | /// Signal-to-noise ratio in decibels | |
238 | ssnr : F, | |
239 | /// Proportion of noise in the signal as a number in $[0, 1]$. | |
240 | noise_ratio : F, | |
241 | /// When the experiment was run (UTC) | |
242 | when : DateTime<Utc>, | |
243 | } | |
244 | ||
245 | #[replace_float_literals(F::cast_from(literal))] | |
246 | impl<F : Float> ExperimentStats<F> { | |
247 | /// Calculate [`ExperimentStats`] based on a noisy `signal` and the separated `noise` signal. | |
248 | fn new<E : Euclidean<F>>(signal : &E, noise : &E) -> Self { | |
249 | let s = signal.norm2_squared(); | |
250 | let n = noise.norm2_squared(); | |
251 | let noise_ratio = (n / s).sqrt(); | |
252 | let ssnr = 10.0 * (s / n).log10(); | |
253 | ExperimentStats { | |
254 | ssnr, | |
255 | noise_ratio, | |
256 | when : Utc::now(), | |
257 | } | |
258 | } | |
259 | } | |
260 | /// Collected algorithm statistics | |
261 | #[derive(Clone, Debug, Serialize)] | |
262 | struct AlgorithmStats<F : Float> { | |
263 | /// Overall CPU time spent | |
264 | cpu_time : F, | |
265 | /// Real time spent | |
266 | elapsed : F | |
267 | } | |
268 | ||
269 | ||
270 | /// A wrapper for [`serde_json::to_writer_pretty`] that takes a filename as input | |
271 | /// and outputs a [`DynError`]. | |
272 | fn write_json<T : Serialize>(filename : String, data : &T) -> DynError { | |
273 | serde_json::to_writer_pretty(std::fs::File::create(filename)?, data)?; | |
274 | Ok(()) | |
275 | } | |
276 | ||
277 | ||
278 | /// Struct for experiment configurations | |
279 | #[derive(Debug, Clone, Serialize)] | |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
280 | pub struct ExperimentV2<F, NoiseDistr, S, K, P, const N : usize> |
0 | 281 | where F : Float, |
282 | [usize; N] : Serialize, | |
283 | NoiseDistr : Distribution<F>, | |
284 | S : Sensor<F, N>, | |
285 | P : Spread<F, N>, | |
286 | K : SimpleConvolutionKernel<F, N>, | |
287 | { | |
288 | /// Domain $Ω$. | |
289 | pub domain : Cube<F, N>, | |
290 | /// Number of sensors along each dimension | |
291 | pub sensor_count : [usize; N], | |
292 | /// Noise distribution | |
293 | pub noise_distr : NoiseDistr, | |
294 | /// Seed for random noise generation (for repeatable experiments) | |
295 | pub noise_seed : u64, | |
296 | /// Sensor $θ$; $θ * ψ$ forms the forward operator $𝒜$. | |
297 | pub sensor : S, | |
298 | /// Spread $ψ$; $θ * ψ$ forms the forward operator $𝒜$. | |
299 | pub spread : P, | |
300 | /// Kernel $ρ$ of $𝒟$. | |
301 | pub kernel : K, | |
302 | /// True point sources | |
303 | pub μ_hat : DiscreteMeasure<Loc<F, N>, F>, | |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
304 | /// Regularisation term and parameter |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
305 | pub regularisation : Regularisation<F>, |
0 | 306 | /// For plotting : how wide should the kernels be plotted |
307 | pub kernel_plot_width : F, | |
308 | /// Data term | |
309 | pub dataterm : DataTerm, | |
310 | /// A map of default configurations for algorithms | |
311 | #[serde(skip)] | |
312 | pub algorithm_defaults : HashMap<DefaultAlgorithm, AlgorithmConfig<F>>, | |
313 | } | |
314 | ||
315 | /// Trait for runnable experiments | |
316 | pub trait RunnableExperiment<F : ClapFloat> { | |
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
317 | /// Run all algorithms provided, or default algorithms if none provided, on the experiment. |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
318 | fn runall(&self, cli : &CommandLineArgs, |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
319 | algs : Option<Vec<Named<AlgorithmConfig<F>>>>) -> DynError; |
0 | 320 | |
321 | /// Return algorithm default config | |
322 | fn algorithm_defaults(&self, alg : DefaultAlgorithm, cli : &AlgorithmOverrides<F>) | |
323 | -> Named<AlgorithmConfig<F>>; | |
324 | } | |
325 | ||
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
326 | // *** macro boilerplate *** |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
327 | macro_rules! impl_experiment { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
328 | ($type:ident, $reg_field:ident, $reg_convert:path) => { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
329 | // *** macro *** |
0 | 330 | impl<F, NoiseDistr, S, K, P, const N : usize> RunnableExperiment<F> for |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
331 | Named<$type<F, NoiseDistr, S, K, P, N>> |
0 | 332 | where F : ClapFloat + nalgebra::RealField + ToNalgebraRealField<MixedType=F>, |
333 | [usize; N] : Serialize, | |
23
9869fa1e0ccd
Print out experiment information when running it
Tuomo Valkonen <tuomov@iki.fi>
parents:
20
diff
changeset
|
334 | S : Sensor<F, N> + Copy + Serialize + std::fmt::Debug, |
9869fa1e0ccd
Print out experiment information when running it
Tuomo Valkonen <tuomov@iki.fi>
parents:
20
diff
changeset
|
335 | P : Spread<F, N> + Copy + Serialize + std::fmt::Debug, |
0 | 336 | Convolution<S, P>: Spread<F, N> + Bounded<F> + LocalAnalysis<F, Bounds<F>, N> + Copy, |
337 | AutoConvolution<P> : BoundedBy<F, K>, | |
23
9869fa1e0ccd
Print out experiment information when running it
Tuomo Valkonen <tuomov@iki.fi>
parents:
20
diff
changeset
|
338 | K : SimpleConvolutionKernel<F, N> + LocalAnalysis<F, Bounds<F>, N> |
9869fa1e0ccd
Print out experiment information when running it
Tuomo Valkonen <tuomov@iki.fi>
parents:
20
diff
changeset
|
339 | + Copy + Serialize + std::fmt::Debug, |
0 | 340 | Cube<F, N>: P2Minimise<Loc<F, N>, F> + SetOrd, |
341 | PlotLookup : Plotting<N>, | |
342 | DefaultBT<F, N> : SensorGridBT<F, S, P, N, Depth=DynamicDepth> + BTSearch<F, N>, | |
343 | BTNodeLookup: BTNode<F, usize, Bounds<F>, N>, | |
344 | DiscreteMeasure<Loc<F, N>, F> : SpikeMerging<F>, | |
23
9869fa1e0ccd
Print out experiment information when running it
Tuomo Valkonen <tuomov@iki.fi>
parents:
20
diff
changeset
|
345 | NoiseDistr : Distribution<F> + Serialize + std::fmt::Debug { |
0 | 346 | |
347 | fn algorithm_defaults(&self, alg : DefaultAlgorithm, cli : &AlgorithmOverrides<F>) | |
348 | -> Named<AlgorithmConfig<F>> { | |
349 | alg.to_named( | |
350 | self.data | |
351 | .algorithm_defaults | |
352 | .get(&alg) | |
353 | .map_or_else(|| alg.default_config(), | |
354 | |config| config.clone()) | |
355 | .cli_override(cli) | |
356 | ) | |
357 | } | |
358 | ||
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
359 | fn runall(&self, cli : &CommandLineArgs, |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
360 | algs : Option<Vec<Named<AlgorithmConfig<F>>>>) -> DynError { |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
361 | // Get experiment configuration |
0 | 362 | let &Named { |
363 | name : ref experiment_name, | |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
364 | data : $type { |
0 | 365 | domain, sensor_count, ref noise_distr, sensor, spread, kernel, |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
366 | ref μ_hat, /*regularisation,*/ kernel_plot_width, dataterm, noise_seed, |
0 | 367 | .. |
368 | } | |
369 | } = self; | |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
370 | #[allow(deprecated)] |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
371 | let regularisation = $reg_convert(self.data.$reg_field); |
0 | 372 | |
23
9869fa1e0ccd
Print out experiment information when running it
Tuomo Valkonen <tuomov@iki.fi>
parents:
20
diff
changeset
|
373 | println!("{}\n{}", |
9869fa1e0ccd
Print out experiment information when running it
Tuomo Valkonen <tuomov@iki.fi>
parents:
20
diff
changeset
|
374 | format!("Performing experiment {}…", experiment_name).cyan(), |
9869fa1e0ccd
Print out experiment information when running it
Tuomo Valkonen <tuomov@iki.fi>
parents:
20
diff
changeset
|
375 | format!("{:?}", &self.data).bright_black()); |
9869fa1e0ccd
Print out experiment information when running it
Tuomo Valkonen <tuomov@iki.fi>
parents:
20
diff
changeset
|
376 | |
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
377 | // Set up output directory |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
378 | let prefix = format!("{}/{}/", cli.outdir, self.name); |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
379 | |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
380 | // Set up algorithms |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
381 | let iterator_options = AlgIteratorOptions{ |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
382 | max_iter : cli.max_iter, |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
383 | verbose_iter : cli.verbose_iter |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
384 | .map_or(Verbose::Logarithmic(10), |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
385 | |n| Verbose::Every(n)), |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
386 | quiet : cli.quiet, |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
387 | }; |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
388 | let algorithms = match (algs, self.data.dataterm) { |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
389 | (Some(algs), _) => algs, |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
390 | (None, DataTerm::L2Squared) => vec![DefaultAlgorithm::FB.get_named()], |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
391 | (None, DataTerm::L1) => vec![DefaultAlgorithm::PDPS.get_named()], |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
392 | }; |
0 | 393 | |
394 | // Set up operators | |
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
395 | let depth = DynamicDepth(8); |
0 | 396 | let opA = DefaultSG::new(domain, sensor_count, sensor, spread, depth); |
397 | let op𝒟 = DefaultSeminormOp::new(depth, domain, kernel); | |
398 | ||
399 | // Set up random number generator. | |
400 | let mut rng = StdRng::seed_from_u64(noise_seed); | |
401 | ||
402 | // Generate the data and calculate SSNR statistic | |
403 | let b_hat = opA.apply(μ_hat); | |
404 | let noise = DVector::from_distribution(b_hat.len(), &noise_distr, &mut rng); | |
405 | let b = &b_hat + &noise; | |
406 | // Need to wrap calc_ssnr into a function to hide ultra-lame nalgebra::RealField | |
407 | // overloading log10 and conflicting with standard NumTraits one. | |
408 | let stats = ExperimentStats::new(&b, &noise); | |
409 | ||
410 | // Save experiment configuration and statistics | |
411 | let mkname_e = |t| format!("{prefix}{t}.json", prefix = prefix, t = t); | |
412 | std::fs::create_dir_all(&prefix)?; | |
413 | write_json(mkname_e("experiment"), self)?; | |
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
414 | write_json(mkname_e("config"), cli)?; |
0 | 415 | write_json(mkname_e("stats"), &stats)?; |
416 | ||
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
417 | plotall(cli, &prefix, &domain, &sensor, &kernel, &spread, |
0 | 418 | &μ_hat, &op𝒟, &opA, &b_hat, &b, kernel_plot_width)?; |
419 | ||
420 | // Run the algorithm(s) | |
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
421 | for named @ Named { name : alg_name, data : alg } in algorithms.iter() { |
0 | 422 | let this_prefix = format!("{}{}/", prefix, alg_name); |
423 | ||
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
424 | let running = || if !cli.quiet { |
0 | 425 | println!("{}\n{}\n{}", |
426 | format!("Running {} on experiment {}…", alg_name, experiment_name).cyan(), | |
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
427 | format!("{:?}", iterator_options).bright_black(), |
0 | 428 | format!("{:?}", alg).bright_black()); |
429 | }; | |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
430 | let not_implemented = || { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
431 | let msg = format!("Algorithm “{alg_name}” not implemented for \ |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
432 | dataterm {dataterm:?} and regularisation {regularisation:?}. \ |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
433 | Skipping.").red(); |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
434 | eprintln!("{}", msg); |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
435 | }; |
0 | 436 | // Create Logger and IteratorFactory |
437 | let mut logger = Logger::new(); | |
25
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
438 | let reg : Box<dyn WeightOptim<_, _, _, N>> = match regularisation { |
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
439 | Regularisation::Radon(α) => Box::new(RadonRegTerm(α)), |
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
440 | Regularisation::NonnegRadon(α) => Box::new(NonnegRadonRegTerm(α)), |
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
441 | }; |
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
442 | let findim_data = reg.prepare_optimise_weights(&opA, &b); |
0 | 443 | let inner_config : InnerSettings<F> = Default::default(); |
444 | let inner_it = inner_config.iterator_options; | |
445 | let logmap = |iter, Timed { cpu_time, data }| { | |
446 | let IterInfo { | |
447 | value, | |
448 | n_spikes, | |
449 | inner_iters, | |
450 | merged, | |
451 | pruned, | |
452 | postprocessing, | |
453 | this_iters, | |
454 | .. | |
455 | } = data; | |
25
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
456 | let post_value = match (postprocessing, dataterm) { |
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
457 | (Some(mut μ), DataTerm::L2Squared) => { |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
458 | // Comparison postprocessing is only implemented for the case handled |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
459 | // by the FW variants. |
25
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
460 | reg.optimise_weights( |
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
461 | &mut μ, &opA, &b, &findim_data, &inner_config, |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
462 | inner_it |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
463 | ); |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
464 | dataterm.value_at_residual(opA.apply(&μ) - &b) |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
465 | + regularisation.apply(&μ) |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
466 | }, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
467 | _ => value, |
0 | 468 | }; |
469 | CSVLog { | |
470 | iter, | |
471 | value, | |
472 | post_value, | |
473 | n_spikes, | |
474 | cpu_time : cpu_time.as_secs_f64(), | |
475 | inner_iters, | |
476 | merged, | |
477 | pruned, | |
478 | this_iters | |
479 | } | |
480 | }; | |
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
481 | let iterator = iterator_options.instantiate() |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
482 | .timed() |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
483 | .mapped(logmap) |
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
484 | .into_log(&mut logger); |
0 | 485 | let plotgrid = lingrid(&domain, &[if N==1 { 1000 } else { 100 }; N]); |
486 | ||
487 | // Create plotter and directory if needed. | |
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
488 | let plot_count = if cli.plot >= PlotLevel::Iter { 2000 } else { 0 }; |
0 | 489 | let plotter = SeqPlotter::new(this_prefix, plot_count, plotgrid); |
490 | ||
491 | // Run the algorithm | |
492 | let start = Instant::now(); | |
493 | let start_cpu = ProcessTime::now(); | |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
494 | let μ = match alg { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
495 | AlgorithmConfig::FB(ref algconfig) => { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
496 | match (regularisation, dataterm) { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
497 | (Regularisation::NonnegRadon(α), DataTerm::L2Squared) => { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
498 | running(); |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
499 | pointsource_fb_reg( |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
500 | &opA, &b, NonnegRadonRegTerm(α), &op𝒟, algconfig, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
501 | iterator, plotter |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
502 | ) |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
503 | }, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
504 | (Regularisation::Radon(α), DataTerm::L2Squared) => { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
505 | running(); |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
506 | pointsource_fb_reg( |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
507 | &opA, &b, RadonRegTerm(α), &op𝒟, algconfig, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
508 | iterator, plotter |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
509 | ) |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
510 | }, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
511 | _ => { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
512 | not_implemented(); |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
513 | continue |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
514 | } |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
515 | } |
0 | 516 | }, |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
517 | AlgorithmConfig::PDPS(ref algconfig) => { |
0 | 518 | running(); |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
519 | match (regularisation, dataterm) { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
520 | (Regularisation::NonnegRadon(α), DataTerm::L2Squared) => { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
521 | pointsource_pdps_reg( |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
522 | &opA, &b, NonnegRadonRegTerm(α), &op𝒟, algconfig, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
523 | iterator, plotter, L2Squared |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
524 | ) |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
525 | }, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
526 | (Regularisation::Radon(α),DataTerm::L2Squared) => { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
527 | pointsource_pdps_reg( |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
528 | &opA, &b, RadonRegTerm(α), &op𝒟, algconfig, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
529 | iterator, plotter, L2Squared |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
530 | ) |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
531 | }, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
532 | (Regularisation::NonnegRadon(α), DataTerm::L1) => { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
533 | pointsource_pdps_reg( |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
534 | &opA, &b, NonnegRadonRegTerm(α), &op𝒟, algconfig, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
535 | iterator, plotter, L1 |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
536 | ) |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
537 | }, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
538 | (Regularisation::Radon(α), DataTerm::L1) => { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
539 | pointsource_pdps_reg( |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
540 | &opA, &b, RadonRegTerm(α), &op𝒟, algconfig, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
541 | iterator, plotter, L1 |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
542 | ) |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
543 | }, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
544 | } |
0 | 545 | }, |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
546 | AlgorithmConfig::FW(ref algconfig) => { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
547 | match (regularisation, dataterm) { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
548 | (Regularisation::Radon(α), DataTerm::L2Squared) => { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
549 | running(); |
25
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
550 | pointsource_fw_reg(&opA, &b, RadonRegTerm(α), |
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
551 | algconfig, iterator, plotter) |
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
552 | }, |
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
553 | (Regularisation::NonnegRadon(α), DataTerm::L2Squared) => { |
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
554 | running(); |
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
555 | pointsource_fw_reg(&opA, &b, NonnegRadonRegTerm(α), |
79943be70720
Implement non-negativity constraints for the conditional gradient methods
Tuomo Valkonen <tuomov@iki.fi>
parents:
24
diff
changeset
|
556 | algconfig, iterator, plotter) |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
557 | }, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
558 | _ => { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
559 | not_implemented(); |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
560 | continue |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
561 | } |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
562 | } |
0 | 563 | } |
564 | }; | |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
565 | |
0 | 566 | let elapsed = start.elapsed().as_secs_f64(); |
567 | let cpu_time = start_cpu.elapsed().as_secs_f64(); | |
568 | ||
569 | println!("{}", format!("Elapsed {elapsed}s (CPU time {cpu_time}s)… ").yellow()); | |
570 | ||
571 | // Save results | |
572 | println!("{}", "Saving results…".green()); | |
573 | ||
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
574 | let mkname = |t| format!("{prefix}{alg_name}_{t}"); |
0 | 575 | |
576 | write_json(mkname("config.json"), &named)?; | |
577 | write_json(mkname("stats.json"), &AlgorithmStats { cpu_time, elapsed })?; | |
578 | μ.write_csv(mkname("reco.txt"))?; | |
579 | logger.write_csv(mkname("log.txt"))?; | |
580 | } | |
581 | ||
582 | Ok(()) | |
583 | } | |
584 | } | |
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
585 | // *** macro end boiler plate *** |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
586 | }} |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
587 | // *** actual code *** |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
588 | |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
589 | impl_experiment!(ExperimentV2, regularisation, std::convert::identity); |
0 | 590 | |
591 | /// Plot experiment setup | |
592 | #[replace_float_literals(F::cast_from(literal))] | |
593 | fn plotall<F, Sensor, Kernel, Spread, 𝒟, A, const N : usize>( | |
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
594 | cli : &CommandLineArgs, |
0 | 595 | prefix : &String, |
596 | domain : &Cube<F, N>, | |
597 | sensor : &Sensor, | |
598 | kernel : &Kernel, | |
599 | spread : &Spread, | |
600 | μ_hat : &DiscreteMeasure<Loc<F, N>, F>, | |
601 | op𝒟 : &𝒟, | |
602 | opA : &A, | |
603 | b_hat : &A::Observable, | |
604 | b : &A::Observable, | |
605 | kernel_plot_width : F, | |
606 | ) -> DynError | |
607 | where F : Float + ToNalgebraRealField, | |
608 | Sensor : RealMapping<F, N> + Support<F, N> + Clone, | |
609 | Spread : RealMapping<F, N> + Support<F, N> + Clone, | |
610 | Kernel : RealMapping<F, N> + Support<F, N>, | |
611 | Convolution<Sensor, Spread> : RealMapping<F, N> + Support<F, N>, | |
612 | 𝒟 : DiscreteMeasureOp<Loc<F, N>, F>, | |
613 | 𝒟::Codomain : RealMapping<F, N>, | |
614 | A : ForwardModel<Loc<F, N>, F>, | |
615 | A::PreadjointCodomain : RealMapping<F, N> + Bounded<F>, | |
616 | PlotLookup : Plotting<N>, | |
617 | Cube<F, N> : SetOrd { | |
618 | ||
9
21b0e537ac0e
Command line parameter passing simplifications and make `-o` required.
Tuomo Valkonen <tuomov@iki.fi>
parents:
0
diff
changeset
|
619 | if cli.plot < PlotLevel::Data { |
0 | 620 | return Ok(()) |
621 | } | |
622 | ||
623 | let base = Convolution(sensor.clone(), spread.clone()); | |
624 | ||
625 | let resolution = if N==1 { 100 } else { 40 }; | |
626 | let pfx = |n| format!("{}{}", prefix, n); | |
627 | let plotgrid = lingrid(&[[-kernel_plot_width, kernel_plot_width]; N].into(), &[resolution; N]); | |
628 | ||
629 | PlotLookup::plot_into_file(sensor, plotgrid, pfx("sensor"), "sensor".to_string()); | |
630 | PlotLookup::plot_into_file(kernel, plotgrid, pfx("kernel"), "kernel".to_string()); | |
631 | PlotLookup::plot_into_file(spread, plotgrid, pfx("spread"), "spread".to_string()); | |
632 | PlotLookup::plot_into_file(&base, plotgrid, pfx("base_sensor"), "base_sensor".to_string()); | |
633 | ||
634 | let plotgrid2 = lingrid(&domain, &[resolution; N]); | |
635 | ||
636 | let ω_hat = op𝒟.apply(μ_hat); | |
637 | let noise = opA.preadjoint().apply(opA.apply(μ_hat) - b); | |
638 | PlotLookup::plot_into_file(&ω_hat, plotgrid2, pfx("omega_hat"), "ω̂".to_string()); | |
639 | PlotLookup::plot_into_file(&noise, plotgrid2, pfx("omega_noise"), | |
640 | "noise Aᵀ(Aμ̂ - b)".to_string()); | |
641 | ||
642 | let preadj_b = opA.preadjoint().apply(b); | |
643 | let preadj_b_hat = opA.preadjoint().apply(b_hat); | |
644 | //let bounds = preadj_b.bounds().common(&preadj_b_hat.bounds()); | |
645 | PlotLookup::plot_into_file_spikes( | |
646 | "Aᵀb".to_string(), &preadj_b, | |
647 | "Aᵀb̂".to_string(), Some(&preadj_b_hat), | |
648 | plotgrid2, None, &μ_hat, | |
649 | pfx("omega_b") | |
650 | ); | |
651 | ||
652 | // Save true solution and observables | |
653 | let pfx = |n| format!("{}{}", prefix, n); | |
654 | μ_hat.write_csv(pfx("orig.txt"))?; | |
655 | opA.write_observable(&b_hat, pfx("b_hat"))?; | |
656 | opA.write_observable(&b, pfx("b_noisy")) | |
657 | } | |
658 | ||
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
659 | // |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
660 | // Deprecated interface |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
661 | // |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
662 | |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
663 | /// Struct for experiment configurations |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
664 | #[derive(Debug, Clone, Serialize)] |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
665 | pub struct Experiment<F, NoiseDistr, S, K, P, const N : usize> |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
666 | where F : Float, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
667 | [usize; N] : Serialize, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
668 | NoiseDistr : Distribution<F>, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
669 | S : Sensor<F, N>, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
670 | P : Spread<F, N>, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
671 | K : SimpleConvolutionKernel<F, N>, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
672 | { |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
673 | /// Domain $Ω$. |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
674 | pub domain : Cube<F, N>, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
675 | /// Number of sensors along each dimension |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
676 | pub sensor_count : [usize; N], |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
677 | /// Noise distribution |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
678 | pub noise_distr : NoiseDistr, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
679 | /// Seed for random noise generation (for repeatable experiments) |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
680 | pub noise_seed : u64, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
681 | /// Sensor $θ$; $θ * ψ$ forms the forward operator $𝒜$. |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
682 | pub sensor : S, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
683 | /// Spread $ψ$; $θ * ψ$ forms the forward operator $𝒜$. |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
684 | pub spread : P, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
685 | /// Kernel $ρ$ of $𝒟$. |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
686 | pub kernel : K, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
687 | /// True point sources |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
688 | pub μ_hat : DiscreteMeasure<Loc<F, N>, F>, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
689 | /// Regularisation parameter |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
690 | #[deprecated(note = "Use [`ExperimentV2`], which replaces `α` by more generic `regularisation`")] |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
691 | pub α : F, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
692 | /// For plotting : how wide should the kernels be plotted |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
693 | pub kernel_plot_width : F, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
694 | /// Data term |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
695 | pub dataterm : DataTerm, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
696 | /// A map of default configurations for algorithms |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
697 | #[serde(skip)] |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
698 | pub algorithm_defaults : HashMap<DefaultAlgorithm, AlgorithmConfig<F>>, |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
699 | } |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
700 | |
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
23
diff
changeset
|
701 | impl_experiment!(Experiment, α, Regularisation::NonnegRadon); |