src/sliding_fb.rs

changeset 83
66b8ac0ebe00
parent 82
afb3ce40cff6
child 84
edb5de5d5bd6
--- a/src/sliding_fb.rs	Thu Jul 30 09:27:44 2026 -0500
+++ b/src/sliding_fb.rs	Fri Jul 31 10:41:47 2026 -0500
@@ -28,6 +28,7 @@
 use alg_tools::mapping::{DifferentiableMapping, DifferentiableRealMapping, Mapping, RealMapping};
 use alg_tools::nalgebra_support::ToNalgebraRealField;
 use alg_tools::norms::Norm;
+use alg_tools::sets::{Set, Cube};
 use anyhow::ensure;
 use std::ops::ControlFlow;
 
@@ -230,6 +231,7 @@
     Domain: Space + Clone,
 {
     type TransportStepLength;
+    type Dom : Set<Domain>;
 
     /// Constrution of initial transport `γ1` from initial measure `μ` and `v=F'(μ)`
     /// with step lengh τ and transport step length `θ_or_adaptive`.
@@ -242,6 +244,7 @@
         τθ_or_adaptive: &mut Self::TransportStepLength,
         v: &PreadjointCodomain,
         tconfig: &TransportConfig<F>,
+        domain: Option<&Self::Dom>,
     );
 
     /// A posteriori transport adaptation.
@@ -281,6 +284,7 @@
     RNDM<N, F>: SpikeMerging<F>,
 {
     type TransportStepLength = TransportStepLength<F>;
+    type Dom = Cube<N, F>;
 
     fn get_transport_steplength(
         &self,
@@ -306,8 +310,9 @@
         τθ_or_adaptive: &mut TransportStepLength<F>,
         v: &M,
         tconfig: &TransportConfig<F>,
+        domain: Option<&Cube<N, F>>,
     ) {
-        γ.do_init_transport(v, μ, τθ_or_adaptive, tconfig);
+        γ.do_init_transport(v, μ, τθ_or_adaptive, tconfig, domain);
     }
 
     fn aposteriori_transport(
@@ -387,6 +392,7 @@
     RNDM<N, F>: SpikeMerging<F>,
 {
     type TransportStepLength = TransportStepLength<F>;
+    type Dom = Cube<N, F>;
 
     fn get_transport_steplength(
         &self,
@@ -412,8 +418,9 @@
         τθ_or_adaptive: &mut TransportStepLength<F>,
         v: &M,
         tconfig: &TransportConfig<F>,
+        domain: Option<&Cube<N, F>>,
     ) {
-        γ.do_init_transport(v, μ, τθ_or_adaptive, tconfig);
+        γ.do_init_transport(v, μ, τθ_or_adaptive, tconfig, domain);
     }
 
     fn aposteriori_transport(
@@ -744,6 +751,7 @@
         μ: &RNDM<N, F>,
         τθ_or_adaptive: &mut TransportStepLength<F>,
         tconfig: &TransportConfig<F>,
+        domain: Option<&Cube<N, F>>,
     ) where
         D: DifferentiableRealMapping<N, F>,
     {
@@ -810,7 +818,8 @@
                         if ρ.fail_count < tconfig.max_fail {
                             let dv_x = v.differential(&ρ.x);
                             let g = &dv_x * (ρ.α_γ.signum() * τθ);
-                            ρ.y = ρ.x - g;
+                            let tmp = ρ.x - g;
+                            ρ.y = if domain.is_none_or(|d| d.contains(&tmp)) { tmp } else { ρ.x };
                             let n = g.norm2();
                             if n >= F::EPSILON {
                                 // Estimate Lipschitz factor of ∇v
@@ -835,7 +844,8 @@
         if let Some(τθ) = simple_τθ {
             for ρ in self.iter_mut() {
                 if ρ.fail_count <= tconfig.max_fail {
-                    ρ.y = ρ.x - v.differential(&ρ.x) * (ρ.α_γ.signum() * τθ);
+                    let tmp = ρ.x - v.differential(&ρ.x) * (ρ.α_γ.signum() * τθ);
+                    ρ.y = if domain.is_none_or(|d| d.contains(&tmp)) { tmp } else { ρ.x };
                 }
             }
         }
@@ -964,10 +974,11 @@
 /// Iteratively solve the pointsource localisation problem using sliding forward-backward
 /// splitting
 ///
-/// The parametrisation is as for [`pointsource_fb_reg`].
+/// The parametrisation is as for [`pointsource_fb_reg`], except an additional domain restriction
+/// may be given.
 /// Inertia is currently not supported.
 #[replace_float_literals(F::cast_from(literal))]
-pub fn pointsource_sliding_fb_reg<F, I, Dat, Reg, Plot, P, const N: usize>(
+pub fn pointsource_sliding_fb_dom<F, I, Dat, Reg, Plot, P, const N: usize>(
     f: &Dat,
     reg: &Reg,
     prox_penalty: &P,
@@ -975,6 +986,7 @@
     iterator: I,
     mut plotter: Plot,
     μ0: Option<RNDM<N, F>>,
+    domain: Option<&P::Dom>,
 ) -> DynResult<RNDM<N, F>>
 where
     F: Float + ToNalgebraRealField,
@@ -1037,6 +1049,7 @@
             &mut τθ_or_adaptive,
             &v,
             &config.transport,
+            domain
         );
 
         let mut attempts = 0;
@@ -1148,3 +1161,29 @@
     //postprocess(μ, &config.insertion, f)
     postprocess(μ, &config.insertion, |μ̃| f.apply(μ̃))
 }
+
+#[deprecated]
+/// Version of `pointsource_sliding_fb` without domain restriction
+pub fn pointsource_sliding_fb_reg<F, I, Dat, Reg, Plot, P, const N: usize>(
+    f: &Dat,
+    reg: &Reg,
+    prox_penalty: &P,
+    config: &SlidingFBConfig<F>,
+    iterator: I,
+    plotter: Plot,
+    μ0: Option<RNDM<N, F>>,
+) -> DynResult<RNDM<N, F>>
+where
+    F: Float + ToNalgebraRealField,
+    I: AlgIteratorFactory<IterInfo<F>>,
+    Dat: DifferentiableMapping<RNDM<N, F>, Codomain = F> + BoundedCurvature<F>,
+    Dat::DerivativeDomain:
+        DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>,
+    //for<'a> Dat::Differential<'a>: Lipschitz<&'a P, FloatType = F>,
+    RNDM<N, F>: SpikeMerging<F>,
+    Reg: SlidingRegTerm<Loc<N, F>, F>,
+    P: TransportProxPenalty<Loc<N, F>, Dat::DerivativeDomain, Reg, F> + StepLengthBound<F, Dat>,
+    Plot: Plotter<P::ReturnMapping, Dat::DerivativeDomain, RNDM<N, F>>,
+{
+    pointsource_sliding_fb_dom(f, reg, prox_penalty, config, iterator, plotter, μ0, None)
+}

mercurial