src/run.rs

changeset 72
e9a460a0e638
parent 63
7a8a55fd41c0
child 73
9c6432200aba
equal deleted inserted replaced
71:e2953ffd4e0b 72:e9a460a0e638
21 use crate::prox_penalty::{ 21 use crate::prox_penalty::{
22 ProxPenalty, ProxTerm, RadonSquared, StepLengthBound, StepLengthBoundPD, StepLengthBoundPair, 22 ProxPenalty, ProxTerm, RadonSquared, StepLengthBound, StepLengthBoundPD, StepLengthBoundPair,
23 }; 23 };
24 use crate::regularisation::{NonnegRadonRegTerm, RadonRegTerm, Regularisation, SlidingRegTerm}; 24 use crate::regularisation::{NonnegRadonRegTerm, RadonRegTerm, Regularisation, SlidingRegTerm};
25 use crate::seminorms::*; 25 use crate::seminorms::*;
26 use crate::sliding_fb::{pointsource_sliding_fb_reg, SlidingFBConfig, TransportConfig}; 26 use crate::sliding_fb::{
27 pointsource_sliding_fb_reg, SlidingFBConfig, TransportConfig, TransportProxPenalty,
28 };
27 use crate::sliding_pdps::{ 29 use crate::sliding_pdps::{
28 pointsource_sliding_fb_pair, pointsource_sliding_pdps_pair, SlidingPDPSConfig, 30 pointsource_sliding_fb_pair, pointsource_sliding_pdps_pair, SlidingPDPSConfig,
29 }; 31 };
30 use crate::subproblem::{InnerMethod, InnerSettings}; 32 use crate::subproblem::{InnerMethod, InnerSettings};
31 use crate::tolerance::Tolerance; 33 use crate::tolerance::Tolerance;
127 .unwrap_or(g.tolerance), 129 .unwrap_or(g.tolerance),
128 ..g 130 ..g
129 }; 131 };
130 let override_transport = |g: TransportConfig<F>| TransportConfig { 132 let override_transport = |g: TransportConfig<F>| TransportConfig {
131 θ0: cli.theta0.unwrap_or(g.θ0), 133 θ0: cli.theta0.unwrap_or(g.θ0),
132 tolerance_mult_con: cli.transport_tolerance_pos.unwrap_or(g.tolerance_mult_con), 134 τθ: cli.tautheta.or(g.τθ),
135 tolerance_mult: cli.transport_tolerance.unwrap_or(g.tolerance_mult),
136 ℓ_gradv_mult: cli.gradv_lipest_mult.unwrap_or(g.ℓ_gradv_mult),
133 adaptation: cli.transport_adaptation.unwrap_or(g.adaptation), 137 adaptation: cli.transport_adaptation.unwrap_or(g.adaptation),
138 allow_partial_transport: cli
139 .allow_partial_transport
140 .unwrap_or(g.allow_partial_transport),
141 alt_remainder_control: cli.alt_remainder_control.unwrap_or(g.alt_remainder_control),
134 ..g 142 ..g
135 }; 143 };
136 144
137 use AlgorithmConfig::*; 145 use AlgorithmConfig::*;
138 match self { 146 match self {
268 RadonForwardPDPS, 276 RadonForwardPDPS,
269 } 277 }
270 278
271 impl DefaultAlgorithm { 279 impl DefaultAlgorithm {
272 /// Returns the algorithm configuration corresponding to the algorithm shorthand 280 /// Returns the algorithm configuration corresponding to the algorithm shorthand
273 pub fn default_config<F: Float>(&self) -> AlgorithmConfig<F> { 281 pub fn default_config<F: Float>(
282 &self,
283 regularisation_hint: Option<&Regularisation<F>>,
284 ) -> AlgorithmConfig<F> {
274 use DefaultAlgorithm::*; 285 use DefaultAlgorithm::*;
275 let radon_insertion = InsertionConfig { 286 let radon_insertion = InsertionConfig {
276 merging: SpikeMergingMethod { interp: false, ..Default::default() }, 287 merging: SpikeMergingMethod { enabled: true, interp: false, ..Default::default() },
288 fitness_merging: true,
277 inner: InnerSettings { 289 inner: InnerSettings {
278 method: InnerMethod::PDPS, // SSN not implemented 290 method: if let Some(Regularisation::NonnegRadon(_)) = regularisation_hint {
291 InnerMethod::Exact
292 } else {
293 InnerMethod::PDPS // SSN not implemented
294 },
279 ..Default::default() 295 ..Default::default()
280 }, 296 },
281 ..Default::default() 297 ..Default::default()
282 }; 298 };
283 match *self { 299 match *self {
316 RadonForwardPDPS => AlgorithmConfig::ForwardPDPS( 332 RadonForwardPDPS => AlgorithmConfig::ForwardPDPS(
317 ForwardPDPSConfig { insertion: radon_insertion, ..Default::default() }, 333 ForwardPDPSConfig { insertion: radon_insertion, ..Default::default() },
318 ProxTerm::RadonSquared, 334 ProxTerm::RadonSquared,
319 ), 335 ),
320 } 336 }
321 }
322
323 /// Returns the [`Named`] algorithm corresponding to the algorithm shorthand
324 pub fn get_named<F: Float>(&self) -> Named<AlgorithmConfig<F>> {
325 self.to_named(self.default_config())
326 } 337 }
327 338
328 pub fn to_named<F: Float>(self, alg: AlgorithmConfig<F>) -> Named<AlgorithmConfig<F>> { 339 pub fn to_named<F: Float>(self, alg: AlgorithmConfig<F>) -> Named<AlgorithmConfig<F>> {
329 Named { name: self.name(), data: alg } 340 Named { name: self.name(), data: alg }
330 } 341 }
483 pub trait RunnableExperiment<F: ClapFloat> { 494 pub trait RunnableExperiment<F: ClapFloat> {
484 /// Run all algorithms provided, or default algorithms if none provided, on the experiment. 495 /// Run all algorithms provided, or default algorithms if none provided, on the experiment.
485 fn runall( 496 fn runall(
486 &self, 497 &self,
487 cli: &CommandLineArgs, 498 cli: &CommandLineArgs,
488 algs: Option<Vec<Named<AlgorithmConfig<F>>>>, 499 cli_algorithm_overrides: &AlgorithmOverrides<F>,
489 ) -> DynError; 500 ) -> DynError;
490
491 /// Return algorithm default config
492 fn algorithm_overrides(&self, alg: DefaultAlgorithm) -> AlgorithmOverrides<F>;
493 501
494 /// Experiment name 502 /// Experiment name
495 fn name(&self) -> &str; 503 fn name(&self) -> &str;
496 } 504 }
497 505
509 'a, 517 'a,
510 Timed<IterInfo<F>>, 518 Timed<IterInfo<F>>,
511 TimingIteratorFactory<BasicAlgIteratorFactory<IterInfo<F>>>, 519 TimingIteratorFactory<BasicAlgIteratorFactory<IterInfo<F>>>,
512 >; 520 >;
513 521
522 /// Trait for things used by many a [`RunnableExperiment`], but that are not dyn-compatible.
514 pub trait RunnableExperimentExtras<F: ClapFloat>: 523 pub trait RunnableExperimentExtras<F: ClapFloat>:
515 RunnableExperiment<F> + Serialize + Sized 524 RunnableExperiment<F> + Serialize + Sized
516 { 525 {
517 /// Helper function to print experiment start message and save setup. 526 /// Helper function to print experiment start message and save setup.
518 /// Returns saving prefix. 527 /// Returns saving prefix.
541 std::fs::create_dir_all(&prefix)?; 550 std::fs::create_dir_all(&prefix)?;
542 write_json(format!("{prefix}experiment.json"), self)?; 551 write_json(format!("{prefix}experiment.json"), self)?;
543 write_json(format!("{prefix}config.json"), cli)?; 552 write_json(format!("{prefix}config.json"), cli)?;
544 553
545 Ok(prefix) 554 Ok(prefix)
555 }
556
557 /// Collect algorithms to run based on command line args.
558 fn collect_algs(
559 &self,
560 cli: &CommandLineArgs,
561 algorithm_overrides: &AlgorithmOverrides<F>,
562 algorithm_overrides_fn: impl Fn(DefaultAlgorithm) -> Option<AlgorithmOverrides<F>>,
563 regularisation_hint: Option<&Regularisation<F>>,
564 dflt: &[DefaultAlgorithm],
565 ) -> DynResult<Vec<Named<AlgorithmConfig<F>>>>
566 where
567 F: for<'a> Deserialize<'a>,
568 {
569 let proc_alg = |alg: &DefaultAlgorithm| {
570 let default_cfg = alg.default_config(regularisation_hint);
571 let cfg = if let Some(over) = &algorithm_overrides_fn(*alg) {
572 default_cfg.cli_override(over)
573 } else {
574 default_cfg
575 }
576 .cli_override(algorithm_overrides);
577 alg.to_named(cfg)
578 };
579
580 let mut algs: Vec<Named<AlgorithmConfig<F>>> = cli.algorithm.iter().map(proc_alg).collect();
581 for filename in cli.saved_algorithm.iter() {
582 let f = std::fs::File::open(filename)?;
583 let alg = serde_json::from_reader(f)?;
584 algs.push(alg);
585 }
586 if algs.is_empty() {
587 Ok(dflt.iter().map(proc_alg).collect())
588 } else {
589 Ok(algs)
590 }
546 } 591 }
547 592
548 /// Helper function to run all algorithms on an experiment. 593 /// Helper function to run all algorithms on an experiment.
549 fn do_runall<P, Z, Plot, const N: usize>( 594 fn do_runall<P, Z, Plot, const N: usize>(
550 &self, 595 &self,
705 { 750 {
706 fn name(&self) -> &str { 751 fn name(&self) -> &str {
707 self.name.as_ref() 752 self.name.as_ref()
708 } 753 }
709 754
710 fn algorithm_overrides(&self, alg: DefaultAlgorithm) -> AlgorithmOverrides<F> {
711 AlgorithmOverrides {
712 merge_radius: Some(self.data.default_merge_radius),
713 ..self
714 .data
715 .algorithm_overrides
716 .get(&alg)
717 .cloned()
718 .unwrap_or(Default::default())
719 }
720 }
721
722 fn runall( 755 fn runall(
723 &self, 756 &self,
724 cli: &CommandLineArgs, 757 cli: &CommandLineArgs,
725 algs: Option<Vec<Named<AlgorithmConfig<F>>>>, 758 cli_algorithm_overrides: &AlgorithmOverrides<F>,
726 ) -> DynError { 759 ) -> DynError {
727 // Get experiment configuration 760 // Get experiment configuration
728 let &ExperimentV2 { 761 let &ExperimentV2 {
729 domain, 762 domain,
730 sensor_count, 763 sensor_count,
739 noise_seed, 772 noise_seed,
740 .. 773 ..
741 } = &self.data; 774 } = &self.data;
742 775
743 // Set up algorithms 776 // Set up algorithms
744 let algorithms = match (algs, dataterm) { 777 let algorithms = self.collect_algs(
745 (Some(algs), _) => algs, 778 cli,
746 (None, DataTermType::L222) => vec![DefaultAlgorithm::FB.get_named()], 779 cli_algorithm_overrides,
747 (None, DataTermType::L1) => vec![DefaultAlgorithm::PDPS.get_named()], 780 |alg| {
748 }; 781 Some(AlgorithmOverrides {
782 merge_radius: Some(self.data.default_merge_radius),
783 ..self
784 .data
785 .algorithm_overrides
786 .get(&alg)
787 .cloned()
788 .unwrap_or_else(Default::default)
789 })
790 },
791 Some(&regularisation),
792 match dataterm {
793 DataTermType::L222 => &[
794 DefaultAlgorithm::FB,
795 DefaultAlgorithm::RadonFB,
796 DefaultAlgorithm::SlidingFB,
797 DefaultAlgorithm::RadonSlidingFB,
798 DefaultAlgorithm::FW,
799 DefaultAlgorithm::FWRelax,
800 DefaultAlgorithm::PDPS,
801 ],
802 DataTermType::L1 => &[DefaultAlgorithm::PDPS],
803 },
804 )?;
749 805
750 // Set up operators 806 // Set up operators
751 let depth = DynamicDepth(8); 807 let depth = DynamicDepth(8);
752 let opA = DefaultSG::new(domain, sensor_count, sensor, spread, depth); 808 let opA = DefaultSG::new(domain, sensor_count, sensor, spread, depth);
753 let op𝒟 = DefaultSeminormOp::new(depth, domain, kernel); 809 let op𝒟 = DefaultSeminormOp::new(depth, domain, kernel);
942 ) -> DynResult<RNDM<N, F>> 998 ) -> DynResult<RNDM<N, F>>
943 where 999 where
944 F: Float + ToNalgebraRealField, 1000 F: Float + ToNalgebraRealField,
945 I: AlgIteratorFactory<IterInfo<F>>, 1001 I: AlgIteratorFactory<IterInfo<F>>,
946 Dat: DifferentiableMapping<RNDM<N, F>, Codomain = F> + BoundedCurvature<F>, 1002 Dat: DifferentiableMapping<RNDM<N, F>, Codomain = F> + BoundedCurvature<F>,
947 Dat::DerivativeDomain: DifferentiableRealMapping<N, F> + ClosedMul<F>, 1003 Dat::DerivativeDomain:
1004 DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>,
948 RNDM<N, F>: SpikeMerging<F>, 1005 RNDM<N, F>: SpikeMerging<F>,
949 Reg: SlidingRegTerm<Loc<N, F>, F>, 1006 Reg: SlidingRegTerm<Loc<N, F>, F>,
950 P: ProxPenalty<Loc<N, F>, Dat::DerivativeDomain, Reg, F> + StepLengthBound<F, Dat>, 1007 P: TransportProxPenalty<Loc<N, F>, Dat::DerivativeDomain, Reg, F> + StepLengthBound<F, Dat>,
951 Plot: Plotter<P::ReturnMapping, Dat::DerivativeDomain, RNDM<N, F>>, 1008 Plot: Plotter<P::ReturnMapping, Dat::DerivativeDomain, RNDM<N, F>>,
952 { 1009 {
953 let pt = P::prox_type(); 1010 let pt = P::prox_type();
954 1011
955 match alg { 1012 match alg {
1065 { 1122 {
1066 fn name(&self) -> &str { 1123 fn name(&self) -> &str {
1067 self.name.as_ref() 1124 self.name.as_ref()
1068 } 1125 }
1069 1126
1070 fn algorithm_overrides(&self, alg: DefaultAlgorithm) -> AlgorithmOverrides<F> {
1071 AlgorithmOverrides {
1072 merge_radius: Some(self.data.base.default_merge_radius),
1073 ..self
1074 .data
1075 .base
1076 .algorithm_overrides
1077 .get(&alg)
1078 .cloned()
1079 .unwrap_or(Default::default())
1080 }
1081 }
1082
1083 fn runall( 1127 fn runall(
1084 &self, 1128 &self,
1085 cli: &CommandLineArgs, 1129 cli: &CommandLineArgs,
1086 algs: Option<Vec<Named<AlgorithmConfig<F>>>>, 1130 cli_algorithm_overrides: &AlgorithmOverrides<F>,
1087 ) -> DynError { 1131 ) -> DynError {
1088 // Get experiment configuration 1132 // Get experiment configuration
1089 let &ExperimentBiased { 1133 let &ExperimentBiased {
1090 λ, 1134 λ,
1091 ref bias, 1135 ref bias,
1105 .. 1149 ..
1106 }, 1150 },
1107 } = &self.data; 1151 } = &self.data;
1108 1152
1109 // Set up algorithms 1153 // Set up algorithms
1110 let algorithms = match (algs, dataterm) { 1154 let algorithms = self.collect_algs(
1111 (Some(algs), _) => algs, 1155 cli,
1112 _ => vec![DefaultAlgorithm::SlidingPDPS.get_named()], 1156 cli_algorithm_overrides,
1113 }; 1157 |alg| {
1158 Some(AlgorithmOverrides {
1159 merge_radius: Some(self.data.base.default_merge_radius),
1160 ..self
1161 .data
1162 .base
1163 .algorithm_overrides
1164 .get(&alg)
1165 .cloned()
1166 .unwrap_or_else(Default::default)
1167 })
1168 },
1169 Some(&regularisation),
1170 &[
1171 DefaultAlgorithm::SlidingPDPS,
1172 DefaultAlgorithm::ForwardPDPS,
1173 DefaultAlgorithm::RadonSlidingPDPS,
1174 DefaultAlgorithm::RadonForwardPDPS,
1175 ],
1176 )?;
1114 1177
1115 // Set up operators 1178 // Set up operators
1116 let depth = DynamicDepth(8); 1179 let depth = DynamicDepth(8);
1117 let opA = DefaultSG::new(domain, sensor_count, sensor, spread, depth); 1180 let opA = DefaultSG::new(domain, sensor_count, sensor, spread, depth);
1118 let op𝒟 = DefaultSeminormOp::new(depth, domain, kernel); 1181 let op𝒟 = DefaultSeminormOp::new(depth, domain, kernel);
1257 where 1320 where
1258 F: Float + ToNalgebraRealField, 1321 F: Float + ToNalgebraRealField,
1259 I: AlgIteratorFactory<IterInfo<F>>, 1322 I: AlgIteratorFactory<IterInfo<F>>,
1260 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>> 1323 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>>
1261 + BoundedCurvature<F>, 1324 + BoundedCurvature<F>,
1262 S: DifferentiableRealMapping<N, F> + ClosedMul<F>, 1325 S: DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>,
1263 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, 1326 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>,
1264 //Pair<S, Z>: ClosedMul<F>, 1327 //Pair<S, Z>: ClosedMul<F>,
1265 RNDM<N, F>: SpikeMerging<F>, 1328 RNDM<N, F>: SpikeMerging<F>,
1266 Reg: SlidingRegTerm<Loc<N, F>, F>, 1329 Reg: SlidingRegTerm<Loc<N, F>, F>,
1267 P: ProxPenalty<Loc<N, F>, S, Reg, F>, 1330 P: TransportProxPenalty<Loc<N, F>, S, Reg, F>,
1268 KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y> 1331 KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y>
1269 + GEMV<F, Z> 1332 + GEMV<F, Z>
1270 + SimplyAdjointable<Z, Y, AdjointCodomain = Z>, 1333 + SimplyAdjointable<Z, Y, AdjointCodomain = Z>,
1271 KOpZ::SimpleAdjoint: GEMV<F, Y>, 1334 KOpZ::SimpleAdjoint: GEMV<F, Y>,
1272 Y: ClosedEuclidean<F> + Clone, 1335 Y: ClosedEuclidean<F> + Clone,
1273 for<'b> &'b Y: Instance<Y>, 1336 for<'b> &'b Y: Instance<Y>,
1274 Z: ClosedEuclidean<F> + Clone + ClosedMul<F>, 1337 Z: ClosedEuclidean<F> + Clone + ClosedMul<F> + AXPY,
1275 for<'b> &'b Z: Instance<Z>, 1338 for<'b> &'b Z: Instance<Z>,
1276 R: Prox<Z, Codomain = F>, 1339 R: Prox<Z, Codomain = F>,
1277 H: Conjugable<Y, F, Codomain = F>, 1340 H: Conjugable<Y, F, Codomain = F>,
1278 for<'b> H::Conjugate<'b>: Prox<Y>, 1341 for<'b> H::Conjugate<'b>: Prox<Y>,
1279 Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>, 1342 Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>,
1340 where 1403 where
1341 F: Float + ToNalgebraRealField, 1404 F: Float + ToNalgebraRealField,
1342 I: AlgIteratorFactory<IterInfo<F>>, 1405 I: AlgIteratorFactory<IterInfo<F>>,
1343 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>> 1406 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>>
1344 + BoundedCurvature<F>, 1407 + BoundedCurvature<F>,
1345 S: DifferentiableRealMapping<N, F> + ClosedMul<F>, 1408 S: DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>,
1346 RNDM<N, F>: SpikeMerging<F>, 1409 RNDM<N, F>: SpikeMerging<F>,
1347 Reg: SlidingRegTerm<Loc<N, F>, F>, 1410 Reg: SlidingRegTerm<Loc<N, F>, F>,
1348 P: ProxPenalty<Loc<N, F>, S, Reg, F>, 1411 P: TransportProxPenalty<Loc<N, F>, S, Reg, F>,
1349 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, 1412 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>,
1350 Z: ClosedEuclidean<F> + AXPY + Clone, 1413 Z: ClosedEuclidean<F> + AXPY + Clone,
1351 for<'b> &'b Z: Instance<Z>, 1414 for<'b> &'b Z: Instance<Z>,
1352 R: Prox<Z, Codomain = F>, 1415 R: Prox<Z, Codomain = F>,
1353 Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>, 1416 Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>,

mercurial