| 26 use alg_tools::instance::Space; |
26 use alg_tools::instance::Space; |
| 27 use alg_tools::iterate::AlgIteratorFactory; |
27 use alg_tools::iterate::AlgIteratorFactory; |
| 28 use alg_tools::mapping::{DifferentiableMapping, DifferentiableRealMapping, Mapping, RealMapping}; |
28 use alg_tools::mapping::{DifferentiableMapping, DifferentiableRealMapping, Mapping, RealMapping}; |
| 29 use alg_tools::nalgebra_support::ToNalgebraRealField; |
29 use alg_tools::nalgebra_support::ToNalgebraRealField; |
| 30 use alg_tools::norms::Norm; |
30 use alg_tools::norms::Norm; |
| |
31 use alg_tools::sets::{Set, Cube}; |
| 31 use anyhow::ensure; |
32 use anyhow::ensure; |
| 32 use std::ops::ControlFlow; |
33 use std::ops::ControlFlow; |
| 33 |
34 |
| 34 /// Transport settings for [`pointsource_sliding_fb_reg`]. |
35 /// Transport settings for [`pointsource_sliding_fb_reg`]. |
| 35 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] |
36 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] |
| 228 F: Float + ToNalgebraRealField, |
229 F: Float + ToNalgebraRealField, |
| 229 Reg: SlidingRegTerm<Domain, F>, |
230 Reg: SlidingRegTerm<Domain, F>, |
| 230 Domain: Space + Clone, |
231 Domain: Space + Clone, |
| 231 { |
232 { |
| 232 type TransportStepLength; |
233 type TransportStepLength; |
| |
234 type Dom : Set<Domain>; |
| 233 |
235 |
| 234 /// Constrution of initial transport `γ1` from initial measure `μ` and `v=F'(μ)` |
236 /// Constrution of initial transport `γ1` from initial measure `μ` and `v=F'(μ)` |
| 235 /// with step lengh τ and transport step length `θ_or_adaptive`. |
237 /// with step lengh τ and transport step length `θ_or_adaptive`. |
| 236 fn initial_transport( |
238 fn initial_transport( |
| 237 &self, |
239 &self, |
| 240 ε: F, |
242 ε: F, |
| 241 τ: F, |
243 τ: F, |
| 242 τθ_or_adaptive: &mut Self::TransportStepLength, |
244 τθ_or_adaptive: &mut Self::TransportStepLength, |
| 243 v: &PreadjointCodomain, |
245 v: &PreadjointCodomain, |
| 244 tconfig: &TransportConfig<F>, |
246 tconfig: &TransportConfig<F>, |
| |
247 domain: Option<&Self::Dom>, |
| 245 ); |
248 ); |
| 246 |
249 |
| 247 /// A posteriori transport adaptation. |
250 /// A posteriori transport adaptation. |
| 248 fn aposteriori_transport( |
251 fn aposteriori_transport( |
| 249 &self, |
252 &self, |
| 279 M: MinMaxMapping<Loc<N, F>, F> + DifferentiableRealMapping<N, F>, |
282 M: MinMaxMapping<Loc<N, F>, F> + DifferentiableRealMapping<N, F>, |
| 280 Reg: SlidingRegTerm<Loc<N, F>, F>, |
283 Reg: SlidingRegTerm<Loc<N, F>, F>, |
| 281 RNDM<N, F>: SpikeMerging<F>, |
284 RNDM<N, F>: SpikeMerging<F>, |
| 282 { |
285 { |
| 283 type TransportStepLength = TransportStepLength<F>; |
286 type TransportStepLength = TransportStepLength<F>; |
| |
287 type Dom = Cube<N, F>; |
| 284 |
288 |
| 285 fn get_transport_steplength( |
289 fn get_transport_steplength( |
| 286 &self, |
290 &self, |
| 287 (ℓ_F, maybe_ℓ_gradv, _maybe_transport_lip): (DynResult<F>, DynResult<F>, DynResult<F>), |
291 (ℓ_F, maybe_ℓ_gradv, _maybe_transport_lip): (DynResult<F>, DynResult<F>, DynResult<F>), |
| 288 tconfig: &TransportConfig<F>, |
292 tconfig: &TransportConfig<F>, |
| 304 _ε: F, |
308 _ε: F, |
| 305 _τ: F, |
309 _τ: F, |
| 306 τθ_or_adaptive: &mut TransportStepLength<F>, |
310 τθ_or_adaptive: &mut TransportStepLength<F>, |
| 307 v: &M, |
311 v: &M, |
| 308 tconfig: &TransportConfig<F>, |
312 tconfig: &TransportConfig<F>, |
| |
313 domain: Option<&Cube<N, F>>, |
| 309 ) { |
314 ) { |
| 310 γ.do_init_transport(v, μ, τθ_or_adaptive, tconfig); |
315 γ.do_init_transport(v, μ, τθ_or_adaptive, tconfig, domain); |
| 311 } |
316 } |
| 312 |
317 |
| 313 fn aposteriori_transport( |
318 fn aposteriori_transport( |
| 314 &self, |
319 &self, |
| 315 γ: &mut Transport<Loc<N, F>, F>, |
320 γ: &mut Transport<Loc<N, F>, F>, |
| 385 Reg: SlidingRegTerm<Loc<N, F>, F>, |
390 Reg: SlidingRegTerm<Loc<N, F>, F>, |
| 386 Self: ProxPenalty<Loc<N, F>, M, Reg, F>, |
391 Self: ProxPenalty<Loc<N, F>, M, Reg, F>, |
| 387 RNDM<N, F>: SpikeMerging<F>, |
392 RNDM<N, F>: SpikeMerging<F>, |
| 388 { |
393 { |
| 389 type TransportStepLength = TransportStepLength<F>; |
394 type TransportStepLength = TransportStepLength<F>; |
| |
395 type Dom = Cube<N, F>; |
| 390 |
396 |
| 391 fn get_transport_steplength( |
397 fn get_transport_steplength( |
| 392 &self, |
398 &self, |
| 393 (ℓ_F, maybe_ℓ_gradv, _maybe_transport_lip): (DynResult<F>, DynResult<F>, DynResult<F>), |
399 (ℓ_F, maybe_ℓ_gradv, _maybe_transport_lip): (DynResult<F>, DynResult<F>, DynResult<F>), |
| 394 tconfig: &TransportConfig<F>, |
400 tconfig: &TransportConfig<F>, |
| 410 _ε: F, |
416 _ε: F, |
| 411 _τ: F, |
417 _τ: F, |
| 412 τθ_or_adaptive: &mut TransportStepLength<F>, |
418 τθ_or_adaptive: &mut TransportStepLength<F>, |
| 413 v: &M, |
419 v: &M, |
| 414 tconfig: &TransportConfig<F>, |
420 tconfig: &TransportConfig<F>, |
| |
421 domain: Option<&Cube<N, F>>, |
| 415 ) { |
422 ) { |
| 416 γ.do_init_transport(v, μ, τθ_or_adaptive, tconfig); |
423 γ.do_init_transport(v, μ, τθ_or_adaptive, tconfig, domain); |
| 417 } |
424 } |
| 418 |
425 |
| 419 fn aposteriori_transport( |
426 fn aposteriori_transport( |
| 420 &self, |
427 &self, |
| 421 γ: &mut Transport<Loc<N, F>, F>, |
428 γ: &mut Transport<Loc<N, F>, F>, |
| 742 &mut self, |
749 &mut self, |
| 743 v: &D, |
750 v: &D, |
| 744 μ: &RNDM<N, F>, |
751 μ: &RNDM<N, F>, |
| 745 τθ_or_adaptive: &mut TransportStepLength<F>, |
752 τθ_or_adaptive: &mut TransportStepLength<F>, |
| 746 tconfig: &TransportConfig<F>, |
753 tconfig: &TransportConfig<F>, |
| |
754 domain: Option<&Cube<N, F>>, |
| 747 ) where |
755 ) where |
| 748 D: DifferentiableRealMapping<N, F>, |
756 D: DifferentiableRealMapping<N, F>, |
| 749 { |
757 { |
| 750 use TransportStepLength::*; |
758 use TransportStepLength::*; |
| 751 |
759 |
| 808 let mut changes = false; |
816 let mut changes = false; |
| 809 for ρ in self.iter_mut() { |
817 for ρ in self.iter_mut() { |
| 810 if ρ.fail_count < tconfig.max_fail { |
818 if ρ.fail_count < tconfig.max_fail { |
| 811 let dv_x = v.differential(&ρ.x); |
819 let dv_x = v.differential(&ρ.x); |
| 812 let g = &dv_x * (ρ.α_γ.signum() * τθ); |
820 let g = &dv_x * (ρ.α_γ.signum() * τθ); |
| 813 ρ.y = ρ.x - g; |
821 let tmp = ρ.x - g; |
| |
822 ρ.y = if domain.is_none_or(|d| d.contains(&tmp)) { tmp } else { ρ.x }; |
| 814 let n = g.norm2(); |
823 let n = g.norm2(); |
| 815 if n >= F::EPSILON { |
824 if n >= F::EPSILON { |
| 816 // Estimate Lipschitz factor of ∇v |
825 // Estimate Lipschitz factor of ∇v |
| 817 let this_ℓ_gradv = (dv_x - v.differential(&ρ.y)).norm2() / n; |
826 let this_ℓ_gradv = (dv_x - v.differential(&ρ.y)).norm2() / n; |
| 818 *adaptive_ℓ_gradv = adaptive_ℓ_gradv.max(this_ℓ_gradv); |
827 *adaptive_ℓ_gradv = adaptive_ℓ_gradv.max(this_ℓ_gradv); |
| 962 } |
972 } |
| 963 |
973 |
| 964 /// Iteratively solve the pointsource localisation problem using sliding forward-backward |
974 /// Iteratively solve the pointsource localisation problem using sliding forward-backward |
| 965 /// splitting |
975 /// splitting |
| 966 /// |
976 /// |
| 967 /// The parametrisation is as for [`pointsource_fb_reg`]. |
977 /// The parametrisation is as for [`pointsource_fb_reg`], except an additional domain restriction |
| |
978 /// may be given. |
| 968 /// Inertia is currently not supported. |
979 /// Inertia is currently not supported. |
| 969 #[replace_float_literals(F::cast_from(literal))] |
980 #[replace_float_literals(F::cast_from(literal))] |
| 970 pub fn pointsource_sliding_fb_reg<F, I, Dat, Reg, Plot, P, const N: usize>( |
981 pub fn pointsource_sliding_fb_dom<F, I, Dat, Reg, Plot, P, const N: usize>( |
| 971 f: &Dat, |
982 f: &Dat, |
| 972 reg: &Reg, |
983 reg: &Reg, |
| 973 prox_penalty: &P, |
984 prox_penalty: &P, |
| 974 config: &SlidingFBConfig<F>, |
985 config: &SlidingFBConfig<F>, |
| 975 iterator: I, |
986 iterator: I, |
| 976 mut plotter: Plot, |
987 mut plotter: Plot, |
| 977 μ0: Option<RNDM<N, F>>, |
988 μ0: Option<RNDM<N, F>>, |
| |
989 domain: Option<&P::Dom>, |
| 978 ) -> DynResult<RNDM<N, F>> |
990 ) -> DynResult<RNDM<N, F>> |
| 979 where |
991 where |
| 980 F: Float + ToNalgebraRealField, |
992 F: Float + ToNalgebraRealField, |
| 981 I: AlgIteratorFactory<IterInfo<F>>, |
993 I: AlgIteratorFactory<IterInfo<F>>, |
| 982 Dat: DifferentiableMapping<RNDM<N, F>, Codomain = F> + BoundedCurvature<F>, |
994 Dat: DifferentiableMapping<RNDM<N, F>, Codomain = F> + BoundedCurvature<F>, |
| 1146 } |
1159 } |
| 1147 |
1160 |
| 1148 //postprocess(μ, &config.insertion, f) |
1161 //postprocess(μ, &config.insertion, f) |
| 1149 postprocess(μ, &config.insertion, |μ̃| f.apply(μ̃)) |
1162 postprocess(μ, &config.insertion, |μ̃| f.apply(μ̃)) |
| 1150 } |
1163 } |
| |
1164 |
| |
1165 #[deprecated] |
| |
1166 /// Version of `pointsource_sliding_fb` without domain restriction |
| |
1167 pub fn pointsource_sliding_fb_reg<F, I, Dat, Reg, Plot, P, const N: usize>( |
| |
1168 f: &Dat, |
| |
1169 reg: &Reg, |
| |
1170 prox_penalty: &P, |
| |
1171 config: &SlidingFBConfig<F>, |
| |
1172 iterator: I, |
| |
1173 plotter: Plot, |
| |
1174 μ0: Option<RNDM<N, F>>, |
| |
1175 ) -> DynResult<RNDM<N, F>> |
| |
1176 where |
| |
1177 F: Float + ToNalgebraRealField, |
| |
1178 I: AlgIteratorFactory<IterInfo<F>>, |
| |
1179 Dat: DifferentiableMapping<RNDM<N, F>, Codomain = F> + BoundedCurvature<F>, |
| |
1180 Dat::DerivativeDomain: |
| |
1181 DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>, |
| |
1182 //for<'a> Dat::Differential<'a>: Lipschitz<&'a P, FloatType = F>, |
| |
1183 RNDM<N, F>: SpikeMerging<F>, |
| |
1184 Reg: SlidingRegTerm<Loc<N, F>, F>, |
| |
1185 P: TransportProxPenalty<Loc<N, F>, Dat::DerivativeDomain, Reg, F> + StepLengthBound<F, Dat>, |
| |
1186 Plot: Plotter<P::ReturnMapping, Dat::DerivativeDomain, RNDM<N, F>>, |
| |
1187 { |
| |
1188 pointsource_sliding_fb_dom(f, reg, prox_penalty, config, iterator, plotter, μ0, None) |
| |
1189 } |