| 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 } |
| 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, |
| 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(®ularisation), |
| |
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 { |
| 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(®ularisation), |
| |
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>>, |