src/sliding_fb.rs

changeset 89
8d1c959432c8
parent 84
edb5de5d5bd6
child 91
47d495348e38
--- a/src/sliding_fb.rs	Tue Aug 04 13:46:29 2026 -0500
+++ b/src/sliding_fb.rs	Tue Aug 04 14:12:18 2026 -0500
@@ -11,6 +11,7 @@
 use std::iter::Iterator;
 use std::ops::MulAssign;
 
+use crate::domain::{AdmissibleDomain, FullSpace};
 use crate::fb::*;
 use crate::forward_model::{BoundedCurvature, BoundedCurvatureGuess};
 use crate::measures::merging::SpikeMerging;
@@ -28,7 +29,6 @@
 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;
 
@@ -223,36 +223,35 @@
 const MINIMAL_PARTIAL_TRANSPORT: bool = true;
 const NEW_APPROACH: bool = true;
 
-pub trait TransportProxPenalty<Domain, PreadjointCodomain, Reg, F = f64>:
-    ProxPenalty<Domain, PreadjointCodomain, Reg, F>
+pub trait TransportProxPenalty<Point, PreadjointCodomain, Reg, F = f64>:
+    ProxPenalty<Point, PreadjointCodomain, Reg, F>
 where
     F: Float + ToNalgebraRealField,
-    Reg: SlidingRegTerm<Domain, F>,
-    Domain: Space + Clone,
+    Reg: SlidingRegTerm<Point, F>,
+    Point: 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`.
-    fn initial_transport(
+    fn initial_transport<Dom: AdmissibleDomain<Point>>(
         &self,
-        γ: &mut Transport<Domain, F>,
-        μ: &DiscreteMeasure<Domain, F>,
+        γ: &mut Transport<Point, F>,
+        μ: &DiscreteMeasure<Point, F>,
         ε: F,
         τ: F,
         τθ_or_adaptive: &mut Self::TransportStepLength,
         v: &PreadjointCodomain,
         tconfig: &TransportConfig<F>,
-        domain: Option<&Self::Dom>,
+        domain: &Dom,
     );
 
     /// A posteriori transport adaptation.
     fn aposteriori_transport(
         &self,
-        γ: &mut Transport<Domain, F>,
-        μ: &DiscreteMeasure<Domain, F>,
-        μ̆: &DiscreteMeasure<Domain, F>,
+        γ: &mut Transport<Point, F>,
+        μ: &DiscreteMeasure<Point, F>,
+        μ̆: &DiscreteMeasure<Point, F>,
         τv̆: &mut PreadjointCodomain,
         v: &mut PreadjointCodomain,
         extra: Option<F>,
@@ -284,7 +283,6 @@
     RNDM<N, F>: SpikeMerging<F>,
 {
     type TransportStepLength = TransportStepLength<F>;
-    type Dom = Cube<N, F>;
 
     fn get_transport_steplength(
         &self,
@@ -301,7 +299,7 @@
         )
     }
 
-    fn initial_transport(
+    fn initial_transport<Dom: AdmissibleDomain<Loc<N, F>>>(
         &self,
         γ: &mut Transport<Loc<N, F>, F>,
         μ: &RNDM<N, F>,
@@ -310,7 +308,7 @@
         τθ_or_adaptive: &mut TransportStepLength<F>,
         v: &M,
         tconfig: &TransportConfig<F>,
-        domain: Option<&Cube<N, F>>,
+        domain: &Dom,
     ) {
         γ.do_init_transport(v, μ, τθ_or_adaptive, tconfig, domain);
     }
@@ -392,7 +390,6 @@
     RNDM<N, F>: SpikeMerging<F>,
 {
     type TransportStepLength = TransportStepLength<F>;
-    type Dom = Cube<N, F>;
 
     fn get_transport_steplength(
         &self,
@@ -409,7 +406,7 @@
         )
     }
 
-    fn initial_transport(
+    fn initial_transport<Dom: AdmissibleDomain<Loc<N, F>>>(
         &self,
         γ: &mut Transport<Loc<N, F>, F>,
         μ: &RNDM<N, F>,
@@ -418,7 +415,7 @@
         τθ_or_adaptive: &mut TransportStepLength<F>,
         v: &M,
         tconfig: &TransportConfig<F>,
-        domain: Option<&Cube<N, F>>,
+        domain: &Dom,
     ) {
         γ.do_init_transport(v, μ, τθ_or_adaptive, tconfig, domain);
     }
@@ -745,13 +742,13 @@
     }
 
     /// Helper for initial transport. Called from [`TransportProxPenalty::initial_transport`].
-    pub(super) fn do_init_transport<D>(
+    pub(super) fn do_init_transport<D, Dom: AdmissibleDomain<Loc<N, F>>>(
         &mut self,
         v: &D,
         μ: &RNDM<N, F>,
         τθ_or_adaptive: &mut TransportStepLength<F>,
         tconfig: &TransportConfig<F>,
-        domain: Option<&Cube<N, F>>,
+        domain: &Dom,
     ) where
         D: DifferentiableRealMapping<N, F>,
     {
@@ -819,7 +816,7 @@
                             let dv_x = v.differential(&ρ.x);
                             let g = &dv_x * (ρ.α_γ.signum() * τθ);
                             let tmp = ρ.x - g;
-                            ρ.y = if domain.is_none_or(|d| d.contains(&tmp)) { tmp } else { ρ.x };
+                            ρ.y = if domain.contains(&tmp) { tmp } else { ρ.x };
                             let n = g.norm2();
                             if n >= F::EPSILON {
                                 // Estimate Lipschitz factor of ∇v
@@ -845,7 +842,7 @@
             for ρ in self.iter_mut() {
                 if ρ.fail_count <= tconfig.max_fail {
                     let tmp = ρ.x - v.differential(&ρ.x) * (ρ.α_γ.signum() * τθ);
-                    ρ.y = if domain.is_none_or(|d| d.contains(&tmp)) { tmp } else { ρ.x };
+                    ρ.y = if domain.contains(&tmp) { tmp } else { ρ.x };
                 }
             }
         }
@@ -978,7 +975,7 @@
 /// may be given.
 /// Inertia is currently not supported.
 #[replace_float_literals(F::cast_from(literal))]
-pub fn pointsource_sliding_fb_dom<F, I, Dat, Reg, Plot, P, const N: usize>(
+pub fn pointsource_sliding_fb<F, I, Dat, Reg, Plot, P, const N: usize>(
     f: &Dat,
     reg: &Reg,
     prox_penalty: &P,
@@ -986,7 +983,7 @@
     iterator: I,
     mut plotter: Plot,
     μ0: Option<RNDM<N, F>>,
-    domain: Option<&P::Dom>,
+    domain: &mut impl AdmissibleDomain<Loc<N, F>>,
 ) -> DynResult<RNDM<N, F>>
 where
     F: Float + ToNalgebraRealField,
@@ -1049,7 +1046,7 @@
             &mut τθ_or_adaptive,
             &v,
             &config.transport,
-            domain
+            domain,
         );
 
         let mut attempts = 0;
@@ -1107,8 +1104,8 @@
         // Merge spikes.
         // This crucially expects the merge routine to be stable with respect to spike locations,
         // and not to performing any pruning. That is be to done below simultaneously for γ.
-        config.insertion.if_merge_now(&state, |ins| {
-            let m = prox_penalty.merge_spikes(
+        let did_merge = config.insertion.if_merge_now(&state, |ins| {
+            stats.merged += prox_penalty.merge_spikes(
                 &mut μ,
                 &mut τv̆,
                 &μ̆,
@@ -1116,32 +1113,35 @@
                 ε,
                 ins,
                 &reg,
-                Some(|μ̃: &RNDM<N, F>| f.apply(μ̃) + reg.apply(μ̃) ),
+                Some(|μ̃: &RNDM<N, F>| f.apply(μ̃) + reg.apply(μ̃)),
             );
-            //if m > 0 {
-            stats.merged += m;
-            //v = f.differential(&μ);
-            //}
-        });
+            γ.prune_compat(&mut μ, &mut stats);
 
-        γ.prune_compat(&mut μ, &mut stats);
+            if config.insertion.random_insertions {
+                if let Some(x) = domain.random_point() {
+                    μ += DeltaMeasure { x, α: 0.0 };
+                    stats.inserted += 1;
+                }
+            }
 
-        // Do extra weight optimisation step heuristic
-        for _ in 1..config.insertion.extra_weight_optimisation_steps {
-            τv̆ = f.differential(&μ) * τ;
-            prox_penalty.reweigh(
-                &mut μ,
-                &mut τv̆,
-                τ,
-                ε,
-                &config.insertion,
-                &reg,
-                &state,
-                &mut stats,
-            )?;
-        }
+            // Do extra weight optimisation step heuristic
+            for _ in 1..config.insertion.extra_weight_optimisation_steps {
+                τv̆ = f.differential(&μ) * τ;
+                prox_penalty.reweigh(
+                    &mut μ,
+                    &mut τv̆,
+                    τ,
+                    ε,
+                    &config.insertion,
+                    &reg,
+                    &state,
+                    &mut stats,
+                )?;
+            }
+            Ok(())
+        })?;
 
-        if config.insertion.extra_weight_optimisation_steps > 0 {
+        if did_merge.is_none() {
             γ.prune_compat(&mut μ, &mut stats);
         }
 
@@ -1185,5 +1185,14 @@
     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)
+    pointsource_sliding_fb(
+        f,
+        reg,
+        prox_penalty,
+        config,
+        iterator,
+        plotter,
+        μ0,
+        &mut FullSpace,
+    )
 }

mercurial