src/sliding_fb.rs

changeset 83
66b8ac0ebe00
parent 82
afb3ce40cff6
child 84
edb5de5d5bd6
equal deleted inserted replaced
82:afb3ce40cff6 83:66b8ac0ebe00
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);
833 }; 842 };
834 843
835 if let Some(τθ) = simple_τθ { 844 if let Some(τθ) = simple_τθ {
836 for ρ in self.iter_mut() { 845 for ρ in self.iter_mut() {
837 if ρ.fail_count <= tconfig.max_fail { 846 if ρ.fail_count <= tconfig.max_fail {
838 ρ.y = ρ.x - v.differential(&ρ.x) * (ρ.α_γ.signum() * τθ); 847 let tmp = ρ.x - v.differential(&ρ.x) * (ρ.α_γ.signum() * τθ);
848 ρ.y = if domain.is_none_or(|d| d.contains(&tmp)) { tmp } else { ρ.x };
839 } 849 }
840 } 850 }
841 } 851 }
842 } 852 }
843 853
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>,
1035 ε, 1047 ε,
1036 τ, 1048 τ,
1037 &mut τθ_or_adaptive, 1049 &mut τθ_or_adaptive,
1038 &v, 1050 &v,
1039 &config.transport, 1051 &config.transport,
1052 domain
1040 ); 1053 );
1041 1054
1042 let mut attempts = 0; 1055 let mut attempts = 0;
1043 1056
1044 // Solve finite-dimensional subproblem several times until the dual variable for the 1057 // Solve finite-dimensional subproblem several times until the dual variable for the
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 }

mercurial