src/run.rs

branch
dev
changeset 39
6316d68b58af
parent 37
c5d8bd1a7728
child 41
b6bdb6cb4d44
equal deleted inserted replaced
37:c5d8bd1a7728 39:6316d68b58af
54 use alg_tools::direct_product::Pair; 54 use alg_tools::direct_product::Pair;
55 55
56 use crate::kernels::*; 56 use crate::kernels::*;
57 use crate::types::*; 57 use crate::types::*;
58 use crate::measures::*; 58 use crate::measures::*;
59 use crate::measures::merging::SpikeMerging; 59 use crate::measures::merging::{SpikeMerging,SpikeMergingMethod};
60 use crate::forward_model::*; 60 use crate::forward_model::*;
61 use crate::forward_model::sensor_grid::{ 61 use crate::forward_model::sensor_grid::{
62 SensorGrid, 62 SensorGrid,
63 SensorGridBT, 63 SensorGridBT,
64 //SensorGridBTFN, 64 //SensorGridBTFN,
93 FWConfig, 93 FWConfig,
94 FWVariant, 94 FWVariant,
95 pointsource_fw_reg, 95 pointsource_fw_reg,
96 //WeightOptim, 96 //WeightOptim,
97 }; 97 };
98 //use crate::subproblem::InnerSettings; 98 use crate::subproblem::{InnerSettings, InnerMethod};
99 use crate::seminorms::*; 99 use crate::seminorms::*;
100 use crate::plot::*; 100 use crate::plot::*;
101 use crate::{AlgorithmOverrides, CommandLineArgs}; 101 use crate::{AlgorithmOverrides, CommandLineArgs};
102 use crate::tolerance::Tolerance; 102 use crate::tolerance::Tolerance;
103 use crate::regularisation::{ 103 use crate::regularisation::{
144 } 144 }
145 145
146 impl<F : ClapFloat> AlgorithmConfig<F> { 146 impl<F : ClapFloat> AlgorithmConfig<F> {
147 /// Override supported parameters based on the command line. 147 /// Override supported parameters based on the command line.
148 pub fn cli_override(self, cli : &AlgorithmOverrides<F>) -> Self { 148 pub fn cli_override(self, cli : &AlgorithmOverrides<F>) -> Self {
149 let override_merging = |g : SpikeMergingMethod<F>| {
150 SpikeMergingMethod {
151 enabled : cli.merge.unwrap_or(g.enabled),
152 radius : cli.merge_radius.unwrap_or(g.radius),
153 interp : cli.merge_interp.unwrap_or(g.interp),
154 }
155 };
149 let override_fb_generic = |g : FBGenericConfig<F>| { 156 let override_fb_generic = |g : FBGenericConfig<F>| {
150 FBGenericConfig { 157 FBGenericConfig {
151 bootstrap_insertions : cli.bootstrap_insertions 158 bootstrap_insertions : cli.bootstrap_insertions
152 .as_ref() 159 .as_ref()
153 .map_or(g.bootstrap_insertions, 160 .map_or(g.bootstrap_insertions,
154 |n| Some((n[0], n[1]))), 161 |n| Some((n[0], n[1]))),
155 merge_every : cli.merge_every.unwrap_or(g.merge_every), 162 merge_every : cli.merge_every.unwrap_or(g.merge_every),
156 merging : cli.merging.clone().unwrap_or(g.merging), 163 merging : override_merging(g.merging),
157 final_merging : cli.final_merging.clone().unwrap_or(g.final_merging), 164 final_merging : cli.final_merging.unwrap_or(g.final_merging),
165 fitness_merging : cli.fitness_merging.unwrap_or(g.fitness_merging),
158 tolerance: cli.tolerance.as_ref().map(unpack_tolerance).unwrap_or(g.tolerance), 166 tolerance: cli.tolerance.as_ref().map(unpack_tolerance).unwrap_or(g.tolerance),
159 .. g 167 .. g
160 } 168 }
161 }; 169 };
162 let override_transport = |g : TransportConfig<F>| { 170 let override_transport = |g : TransportConfig<F>| {
163 TransportConfig { 171 TransportConfig {
164 θ0 : cli.theta0.unwrap_or(g.θ0), 172 θ0 : cli.theta0.unwrap_or(g.θ0),
165 tolerance_ω: cli.transport_tolerance_omega.unwrap_or(g.tolerance_ω), 173 tolerance_mult_pos: cli.transport_tolerance_pos.unwrap_or(g.tolerance_mult_pos),
166 tolerance_dv: cli.transport_tolerance_dv.unwrap_or(g.tolerance_dv), 174 tolerance_mult_pri: cli.transport_tolerance_pri.unwrap_or(g.tolerance_mult_pri),
167 adaptation: cli.transport_adaptation.unwrap_or(g.adaptation), 175 adaptation: cli.transport_adaptation.unwrap_or(g.adaptation),
168 .. g 176 .. g
169 } 177 }
170 }; 178 };
171 179
187 acceleration : cli.acceleration.unwrap_or(pdps.acceleration), 195 acceleration : cli.acceleration.unwrap_or(pdps.acceleration),
188 generic : override_fb_generic(pdps.generic), 196 generic : override_fb_generic(pdps.generic),
189 .. pdps 197 .. pdps
190 }, prox), 198 }, prox),
191 FW(fw) => FW(FWConfig { 199 FW(fw) => FW(FWConfig {
192 merging : cli.merging.clone().unwrap_or(fw.merging), 200 merging : override_merging(fw.merging),
193 tolerance : cli.tolerance.as_ref().map(unpack_tolerance).unwrap_or(fw.tolerance), 201 tolerance : cli.tolerance.as_ref().map(unpack_tolerance).unwrap_or(fw.tolerance),
194 .. fw 202 .. fw
195 }), 203 }),
196 SlidingFB(sfb, prox) => SlidingFB(SlidingFBConfig { 204 SlidingFB(sfb, prox) => SlidingFB(SlidingFBConfig {
197 τ0 : cli.tau0.unwrap_or(sfb.τ0), 205 τ0 : cli.tau0.unwrap_or(sfb.τ0),
280 288
281 impl DefaultAlgorithm { 289 impl DefaultAlgorithm {
282 /// Returns the algorithm configuration corresponding to the algorithm shorthand 290 /// Returns the algorithm configuration corresponding to the algorithm shorthand
283 pub fn default_config<F : Float>(&self) -> AlgorithmConfig<F> { 291 pub fn default_config<F : Float>(&self) -> AlgorithmConfig<F> {
284 use DefaultAlgorithm::*; 292 use DefaultAlgorithm::*;
293 let radon_insertion = FBGenericConfig {
294 merging : SpikeMergingMethod{ interp : false, .. Default::default() },
295 inner : InnerSettings {
296 method : InnerMethod::PDPS, // SSN not implemented
297 .. Default::default()
298 },
299 .. Default::default()
300 };
285 match *self { 301 match *self {
286 FB => AlgorithmConfig::FB(Default::default(), ProxTerm::Wave), 302 FB => AlgorithmConfig::FB(Default::default(), ProxTerm::Wave),
287 FISTA => AlgorithmConfig::FISTA(Default::default(), ProxTerm::Wave), 303 FISTA => AlgorithmConfig::FISTA(Default::default(), ProxTerm::Wave),
288 FW => AlgorithmConfig::FW(Default::default()), 304 FW => AlgorithmConfig::FW(Default::default()),
289 FWRelax => AlgorithmConfig::FW(FWConfig{ 305 FWRelax => AlgorithmConfig::FW(FWConfig{
295 SlidingPDPS => AlgorithmConfig::SlidingPDPS(Default::default(), ProxTerm::Wave), 311 SlidingPDPS => AlgorithmConfig::SlidingPDPS(Default::default(), ProxTerm::Wave),
296 ForwardPDPS => AlgorithmConfig::ForwardPDPS(Default::default(), ProxTerm::Wave), 312 ForwardPDPS => AlgorithmConfig::ForwardPDPS(Default::default(), ProxTerm::Wave),
297 313
298 // Radon variants 314 // Radon variants
299 315
300 RadonFB => AlgorithmConfig::FB(Default::default(), ProxTerm::RadonSquared), 316 RadonFB => AlgorithmConfig::FB(
301 RadonFISTA => AlgorithmConfig::FISTA(Default::default(), ProxTerm::RadonSquared), 317 FBConfig{ generic : radon_insertion, ..Default::default() },
302 RadonPDPS => AlgorithmConfig::PDPS(Default::default(), ProxTerm::RadonSquared), 318 ProxTerm::RadonSquared
303 RadonSlidingFB => AlgorithmConfig::SlidingFB(Default::default(), ProxTerm::RadonSquared), 319 ),
304 RadonSlidingPDPS => AlgorithmConfig::SlidingPDPS(Default::default(), ProxTerm::RadonSquared), 320 RadonFISTA => AlgorithmConfig::FISTA(
305 RadonForwardPDPS => AlgorithmConfig::ForwardPDPS(Default::default(), ProxTerm::RadonSquared), 321 FBConfig{ generic : radon_insertion, ..Default::default() },
322 ProxTerm::RadonSquared
323 ),
324 RadonPDPS => AlgorithmConfig::PDPS(
325 PDPSConfig{ generic : radon_insertion, ..Default::default() },
326 ProxTerm::RadonSquared
327 ),
328 RadonSlidingFB => AlgorithmConfig::SlidingFB(
329 SlidingFBConfig{ insertion : radon_insertion, ..Default::default() },
330 ProxTerm::RadonSquared
331 ),
332 RadonSlidingPDPS => AlgorithmConfig::SlidingPDPS(
333 SlidingPDPSConfig{ insertion : radon_insertion, ..Default::default() },
334 ProxTerm::RadonSquared
335 ),
336 RadonForwardPDPS => AlgorithmConfig::ForwardPDPS(
337 ForwardPDPSConfig{ insertion : radon_insertion, ..Default::default() },
338 ProxTerm::RadonSquared
339 ),
306 } 340 }
307 } 341 }
308 342
309 /// Returns the [`Named`] algorithm corresponding to the algorithm shorthand 343 /// Returns the [`Named`] algorithm corresponding to the algorithm shorthand
310 pub fn get_named<F : Float>(&self) -> Named<AlgorithmConfig<F>> { 344 pub fn get_named<F : Float>(&self) -> Named<AlgorithmConfig<F>> {
336 #[clap(name = "data")] 370 #[clap(name = "data")]
337 Data, 371 Data,
338 /// Plot iterationwise state 372 /// Plot iterationwise state
339 #[clap(name = "iter")] 373 #[clap(name = "iter")]
340 Iter, 374 Iter,
375 }
376
377 impl Default for PlotLevel {
378 fn default() -> Self {
379 Self::Data
380 }
341 } 381 }
342 382
343 type DefaultBT<F, const N : usize> = BT< 383 type DefaultBT<F, const N : usize> = BT<
344 DynamicDepth, 384 DynamicDepth,
345 F, 385 F,
416 456
417 457
418 /// Struct for experiment configurations 458 /// Struct for experiment configurations
419 #[derive(Debug, Clone, Serialize)] 459 #[derive(Debug, Clone, Serialize)]
420 pub struct ExperimentV2<F, NoiseDistr, S, K, P, const N : usize> 460 pub struct ExperimentV2<F, NoiseDistr, S, K, P, const N : usize>
421 where F : Float, 461 where F : Float + ClapFloat,
422 [usize; N] : Serialize, 462 [usize; N] : Serialize,
423 NoiseDistr : Distribution<F>, 463 NoiseDistr : Distribution<F>,
424 S : Sensor<F, N>, 464 S : Sensor<F, N>,
425 P : Spread<F, N>, 465 P : Spread<F, N>,
426 K : SimpleConvolutionKernel<F, N>, 466 K : SimpleConvolutionKernel<F, N>,
446 /// For plotting : how wide should the kernels be plotted 486 /// For plotting : how wide should the kernels be plotted
447 pub kernel_plot_width : F, 487 pub kernel_plot_width : F,
448 /// Data term 488 /// Data term
449 pub dataterm : DataTerm, 489 pub dataterm : DataTerm,
450 /// A map of default configurations for algorithms 490 /// A map of default configurations for algorithms
451 #[serde(skip)] 491 pub algorithm_overrides : HashMap<DefaultAlgorithm, AlgorithmOverrides<F>>,
452 pub algorithm_defaults : HashMap<DefaultAlgorithm, AlgorithmConfig<F>>, 492 /// Default merge radius
493 pub default_merge_radius : F,
453 } 494 }
454 495
455 #[derive(Debug, Clone, Serialize)] 496 #[derive(Debug, Clone, Serialize)]
456 pub struct ExperimentBiased<F, NoiseDistr, S, K, P, B, const N : usize> 497 pub struct ExperimentBiased<F, NoiseDistr, S, K, P, B, const N : usize>
457 where F : Float, 498 where F : Float + ClapFloat,
458 [usize; N] : Serialize, 499 [usize; N] : Serialize,
459 NoiseDistr : Distribution<F>, 500 NoiseDistr : Distribution<F>,
460 S : Sensor<F, N>, 501 S : Sensor<F, N>,
461 P : Spread<F, N>, 502 P : Spread<F, N>,
462 K : SimpleConvolutionKernel<F, N>, 503 K : SimpleConvolutionKernel<F, N>,
475 /// Run all algorithms provided, or default algorithms if none provided, on the experiment. 516 /// Run all algorithms provided, or default algorithms if none provided, on the experiment.
476 fn runall(&self, cli : &CommandLineArgs, 517 fn runall(&self, cli : &CommandLineArgs,
477 algs : Option<Vec<Named<AlgorithmConfig<F>>>>) -> DynError; 518 algs : Option<Vec<Named<AlgorithmConfig<F>>>>) -> DynError;
478 519
479 /// Return algorithm default config 520 /// Return algorithm default config
480 fn algorithm_defaults(&self, alg : DefaultAlgorithm) -> Option<AlgorithmConfig<F>>; 521 fn algorithm_overrides(&self, alg : DefaultAlgorithm) -> AlgorithmOverrides<F>;
481 } 522 }
482 523
483 /// Helper function to print experiment start message and save setup. 524 /// Helper function to print experiment start message and save setup.
484 /// Returns saving prefix. 525 /// Returns saving prefix.
485 fn start_experiment<E, S>( 526 fn start_experiment<E, S>(
492 S : Serialize, 533 S : Serialize,
493 { 534 {
494 let Named { name : experiment_name, data } = experiment; 535 let Named { name : experiment_name, data } = experiment;
495 536
496 println!("{}\n{}", 537 println!("{}\n{}",
497 format!("Performing experiment {}…", experiment_name).cyan(), 538 format!("Performing experiment {}…", experiment_name).cyan(),
498 format!("{:?}", data).bright_black()); 539 format!("Experiment settings: {}", serde_json::to_string(&data)?).bright_black());
499 540
500 // Set up output directory 541 // Set up output directory
501 let prefix = format!("{}/{}/", cli.outdir, experiment_name); 542 let prefix = format!("{}/{}/", cli.outdir, experiment_name);
502 543
503 // Save experiment configuration and statistics 544 // Save experiment configuration and statistics
523 Timed<IterInfo<F, N>>, 564 Timed<IterInfo<F, N>>,
524 TimingIteratorFactory<BasicAlgIteratorFactory<IterInfo<F, N>>> 565 TimingIteratorFactory<BasicAlgIteratorFactory<IterInfo<F, N>>>
525 >; 566 >;
526 567
527 /// Helper function to run all algorithms on an experiment. 568 /// Helper function to run all algorithms on an experiment.
528 fn do_runall<F : Float, Z, const N : usize>( 569 fn do_runall<F : Float + for<'b> Deserialize<'b>, Z, const N : usize>(
529 experiment_name : &String, 570 experiment_name : &String,
530 prefix : &String, 571 prefix : &String,
531 cli : &CommandLineArgs, 572 cli : &CommandLineArgs,
532 algorithms : Vec<Named<AlgorithmConfig<F>>>, 573 algorithms : Vec<Named<AlgorithmConfig<F>>>,
533 plotgrid : LinSpace<Loc<F, N>, [usize; N]>, 574 plotgrid : LinSpace<Loc<F, N>, [usize; N]>,
545 let mut logs = Vec::new(); 586 let mut logs = Vec::new();
546 587
547 let iterator_options = AlgIteratorOptions{ 588 let iterator_options = AlgIteratorOptions{
548 max_iter : cli.max_iter, 589 max_iter : cli.max_iter,
549 verbose_iter : cli.verbose_iter 590 verbose_iter : cli.verbose_iter
550 .map_or(Verbose::Logarithmic(10), 591 .map_or(Verbose::LogarithmicCap{base : 10, cap : 2},
551 |n| Verbose::Every(n)), 592 |n| Verbose::Every(n)),
552 quiet : cli.quiet, 593 quiet : cli.quiet,
553 }; 594 };
554 595
555 // Run the algorithm(s) 596 // Run the algorithm(s)
563 .into_log(&mut logger); 604 .into_log(&mut logger);
564 605
565 let running = if !cli.quiet { 606 let running = if !cli.quiet {
566 format!("{}\n{}\n{}\n", 607 format!("{}\n{}\n{}\n",
567 format!("Running {} on experiment {}…", alg_name, experiment_name).cyan(), 608 format!("Running {} on experiment {}…", alg_name, experiment_name).cyan(),
568 format!("{:?}", iterator_options).bright_black(), 609 format!("Iteration settings: {}", serde_json::to_string(&iterator_options)?).bright_black(),
569 format!("{:?}", alg).bright_black()) 610 format!("Algorithm settings: {}", serde_json::to_string(&alg)?).bright_black())
570 } else { 611 } else {
571 "".to_string() 612 "".to_string()
572 }; 613 };
573 // 614 //
574 // The following is for postprocessing, which has been disabled anyway. 615 // The following is for postprocessing, which has been disabled anyway.
612 write_json(mkname("stats.json"), &AlgorithmStats { cpu_time, elapsed })?; 653 write_json(mkname("stats.json"), &AlgorithmStats { cpu_time, elapsed })?;
613 μ.write_csv(mkname("reco.txt"))?; 654 μ.write_csv(mkname("reco.txt"))?;
614 save_extra(mkname(""), z)?; 655 save_extra(mkname(""), z)?;
615 //logger.write_csv(mkname("log.txt"))?; 656 //logger.write_csv(mkname("log.txt"))?;
616 logs.push((mkname("log.txt"), logger)); 657 logs.push((mkname("log.txt"), logger));
617 } 658 }
618 659
619 save_logs(logs) 660 save_logs(logs, format!("{prefix}valuerange.json"), cli.load_valuerange)
620 } 661 }
621 662
622 #[replace_float_literals(F::cast_from(literal))] 663 #[replace_float_literals(F::cast_from(literal))]
623 impl<F, NoiseDistr, S, K, P, /*PreadjointCodomain, */ const N : usize> RunnableExperiment<F> for 664 impl<F, NoiseDistr, S, K, P, /*PreadjointCodomain, */ const N : usize> RunnableExperiment<F> for
624 Named<ExperimentV2<F, NoiseDistr, S, K, P, N>> 665 Named<ExperimentV2<F, NoiseDistr, S, K, P, N>>
625 where 666 where
626 F : ClapFloat + nalgebra::RealField + ToNalgebraRealField<MixedType=F>, 667 F : ClapFloat + nalgebra::RealField + ToNalgebraRealField<MixedType=F>
668 + Default + for<'b> Deserialize<'b>,
627 [usize; N] : Serialize, 669 [usize; N] : Serialize,
628 S : Sensor<F, N> + Copy + Serialize + std::fmt::Debug, 670 S : Sensor<F, N> + Copy + Serialize + std::fmt::Debug,
629 P : Spread<F, N> + Copy + Serialize + std::fmt::Debug, 671 P : Spread<F, N> + Copy + Serialize + std::fmt::Debug,
630 Convolution<S, P>: Spread<F, N> + Bounded<F> + LocalAnalysis<F, Bounds<F>, N> + Copy 672 Convolution<S, P>: Spread<F, N> + Bounded<F> + LocalAnalysis<F, Bounds<F>, N> + Copy
631 // TODO: shold not have differentiability as a requirement, but 673 // TODO: shold not have differentiability as a requirement, but
653 // DefaultSeminormOp<F, K, N> : ProxPenalty<F, PreadjointCodomain, NonnegRadonRegTerm<F>, N>, 695 // DefaultSeminormOp<F, K, N> : ProxPenalty<F, PreadjointCodomain, NonnegRadonRegTerm<F>, N>,
654 // RadonSquared : ProxPenalty<F, PreadjointCodomain, RadonRegTerm<F>, N>, 696 // RadonSquared : ProxPenalty<F, PreadjointCodomain, RadonRegTerm<F>, N>,
655 // RadonSquared : ProxPenalty<F, PreadjointCodomain, NonnegRadonRegTerm<F>, N>, 697 // RadonSquared : ProxPenalty<F, PreadjointCodomain, NonnegRadonRegTerm<F>, N>,
656 { 698 {
657 699
658 fn algorithm_defaults(&self, alg : DefaultAlgorithm) -> Option<AlgorithmConfig<F>> { 700 fn algorithm_overrides(&self, alg : DefaultAlgorithm) -> AlgorithmOverrides<F> {
659 self.data.algorithm_defaults.get(&alg).cloned() 701 AlgorithmOverrides {
702 merge_radius : Some(self.data.default_merge_radius),
703 .. self.data.algorithm_overrides.get(&alg).cloned().unwrap_or(Default::default())
704 }
660 } 705 }
661 706
662 fn runall(&self, cli : &CommandLineArgs, 707 fn runall(&self, cli : &CommandLineArgs,
663 algs : Option<Vec<Named<AlgorithmConfig<F>>>>) -> DynError { 708 algs : Option<Vec<Named<AlgorithmConfig<F>>>>) -> DynError {
664 // Get experiment configuration 709 // Get experiment configuration
885 930
886 #[replace_float_literals(F::cast_from(literal))] 931 #[replace_float_literals(F::cast_from(literal))]
887 impl<F, NoiseDistr, S, K, P, B, /*PreadjointCodomain,*/ const N : usize> RunnableExperiment<F> for 932 impl<F, NoiseDistr, S, K, P, B, /*PreadjointCodomain,*/ const N : usize> RunnableExperiment<F> for
888 Named<ExperimentBiased<F, NoiseDistr, S, K, P, B, N>> 933 Named<ExperimentBiased<F, NoiseDistr, S, K, P, B, N>>
889 where 934 where
890 F : ClapFloat + nalgebra::RealField + ToNalgebraRealField<MixedType=F>, 935 F : ClapFloat + nalgebra::RealField + ToNalgebraRealField<MixedType=F>
936 + Default + for<'b> Deserialize<'b>,
891 [usize; N] : Serialize, 937 [usize; N] : Serialize,
892 S : Sensor<F, N> + Copy + Serialize + std::fmt::Debug, 938 S : Sensor<F, N> + Copy + Serialize + std::fmt::Debug,
893 P : Spread<F, N> + Copy + Serialize + std::fmt::Debug, 939 P : Spread<F, N> + Copy + Serialize + std::fmt::Debug,
894 Convolution<S, P>: Spread<F, N> + Bounded<F> + LocalAnalysis<F, Bounds<F>, N> + Copy 940 Convolution<S, P>: Spread<F, N> + Bounded<F> + LocalAnalysis<F, Bounds<F>, N> + Copy
895 // TODO: shold not have differentiability as a requirement, but 941 // TODO: shold not have differentiability as a requirement, but
918 // DefaultSeminormOp<F, K, N> : ProxPenalty<F, PreadjointCodomain, NonnegRadonRegTerm<F>, N>, 964 // DefaultSeminormOp<F, K, N> : ProxPenalty<F, PreadjointCodomain, NonnegRadonRegTerm<F>, N>,
919 // RadonSquared : ProxPenalty<F, PreadjointCodomain, RadonRegTerm<F>, N>, 965 // RadonSquared : ProxPenalty<F, PreadjointCodomain, RadonRegTerm<F>, N>,
920 // RadonSquared : ProxPenalty<F, PreadjointCodomain, NonnegRadonRegTerm<F>, N>, 966 // RadonSquared : ProxPenalty<F, PreadjointCodomain, NonnegRadonRegTerm<F>, N>,
921 { 967 {
922 968
923 fn algorithm_defaults(&self, alg : DefaultAlgorithm) -> Option<AlgorithmConfig<F>> { 969 fn algorithm_overrides(&self, alg : DefaultAlgorithm) -> AlgorithmOverrides<F> {
924 self.data.base.algorithm_defaults.get(&alg).cloned() 970 AlgorithmOverrides {
971 merge_radius : Some(self.data.base.default_merge_radius),
972 .. self.data.base.algorithm_overrides.get(&alg).cloned().unwrap_or(Default::default())
973 }
925 } 974 }
926 975
927 fn runall(&self, cli : &CommandLineArgs, 976 fn runall(&self, cli : &CommandLineArgs,
928 algs : Option<Vec<Named<AlgorithmConfig<F>>>>) -> DynError { 977 algs : Option<Vec<Named<AlgorithmConfig<F>>>>) -> DynError {
929 // Get experiment configuration 978 // Get experiment configuration
1075 Ok((μ, z)) 1124 Ok((μ, z))
1076 }) 1125 })
1077 } 1126 }
1078 } 1127 }
1079 1128
1129 #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
1130 struct ValueRange<F : Float> {
1131 ini : F,
1132 min : F,
1133 }
1134
1135 impl<F : Float> ValueRange<F> {
1136 fn expand_with(self, other : Self) -> Self {
1137 ValueRange {
1138 ini : self.ini.max(other.ini),
1139 min : self.min.min(other.min),
1140 }
1141 }
1142 }
1080 1143
1081 /// Calculative minimum and maximum values of all the `logs`, and save them into 1144 /// Calculative minimum and maximum values of all the `logs`, and save them into
1082 /// corresponding file names given as the first elements of the tuples in the vectors. 1145 /// corresponding file names given as the first elements of the tuples in the vectors.
1083 fn save_logs<F : Float, const N : usize>( 1146 fn save_logs<F : Float + for<'b> Deserialize<'b>, const N : usize>(
1084 logs : Vec<(String, Logger<Timed<IterInfo<F, N>>>)> 1147 logs : Vec<(String, Logger<Timed<IterInfo<F, N>>>)>,
1148 valuerange_file : String,
1149 load_valuerange : bool,
1085 ) -> DynError { 1150 ) -> DynError {
1086 // Process logs for relative values 1151 // Process logs for relative values
1087 println!("{}", "Processing logs…"); 1152 println!("{}", "Processing logs…");
1088
1089 1153
1090 // Find minimum value and initial value within a single log 1154 // Find minimum value and initial value within a single log
1091 let proc_single_log = |log : &Logger<Timed<IterInfo<F, N>>>| { 1155 let proc_single_log = |log : &Logger<Timed<IterInfo<F, N>>>| {
1092 let d = log.data(); 1156 let d = log.data();
1093 let mi = d.iter() 1157 let mi = d.iter()
1094 .map(|i| i.data.value) 1158 .map(|i| i.data.value)
1095 .reduce(NumTraitsFloat::min); 1159 .reduce(NumTraitsFloat::min);
1096 d.first() 1160 d.first()
1097 .map(|i| i.data.value) 1161 .map(|i| i.data.value)
1098 .zip(mi) 1162 .zip(mi)
1163 .map(|(ini, min)| ValueRange{ ini, min })
1099 }; 1164 };
1100 1165
1101 // Find minimum and maximum value over all logs 1166 // Find minimum and maximum value over all logs
1102 let (v_ini, v_min) = logs.iter() 1167 let mut v = logs.iter()
1103 .filter_map(|&(_, ref log)| proc_single_log(log)) 1168 .filter_map(|&(_, ref log)| proc_single_log(log))
1104 .reduce(|(i1, m1), (i2, m2)| (i1.max(i2), m1.min(m2))) 1169 .reduce(|v1, v2| v1.expand_with(v2))
1105 .ok_or(anyhow!("No algorithms found"))?; 1170 .ok_or(anyhow!("No algorithms found"))?;
1171
1172 // Load existing range
1173 if load_valuerange && std::fs::metadata(&valuerange_file).is_ok() {
1174 let data = std::fs::read_to_string(&valuerange_file)?;
1175 v = v.expand_with(serde_json::from_str(&data)?);
1176 }
1106 1177
1107 let logmap = |Timed { cpu_time, iter, data }| { 1178 let logmap = |Timed { cpu_time, iter, data }| {
1108 let IterInfo { 1179 let IterInfo {
1109 value, 1180 value,
1110 n_spikes, 1181 n_spikes,
1126 // dataterm.value_at_residual(opA.apply(&μ) - &b) 1197 // dataterm.value_at_residual(opA.apply(&μ) - &b)
1127 // + regularisation.apply(&μ) 1198 // + regularisation.apply(&μ)
1128 // }, 1199 // },
1129 // _ => value, 1200 // _ => value,
1130 // }; 1201 // };
1131 let relative_value = (value - v_min)/(v_ini - v_min); 1202 let relative_value = (value - v.min)/(v.ini - v.min);
1132 CSVLog { 1203 CSVLog {
1133 iter, 1204 iter,
1134 value, 1205 value,
1135 relative_value, 1206 relative_value,
1136 //post_value, 1207 //post_value,
1142 this_iters 1213 this_iters
1143 } 1214 }
1144 }; 1215 };
1145 1216
1146 println!("{}", "Saving logs …".green()); 1217 println!("{}", "Saving logs …".green());
1218
1219 serde_json::to_writer_pretty(std::fs::File::create(&valuerange_file)?, &v)?;
1147 1220
1148 for (name, logger) in logs { 1221 for (name, logger) in logs {
1149 logger.map(logmap).write_csv(name)?; 1222 logger.map(logmap).write_csv(name)?;
1150 } 1223 }
1151 1224

mercurial