Sliding methods now support domain restrictions

Fri, 31 Jul 2026 10:41:47 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Fri, 31 Jul 2026 10:41:47 -0500
changeset 83
66b8ac0ebe00
parent 82
afb3ce40cff6
child 84
edb5de5d5bd6

Sliding methods now support domain restrictions

Cargo.lock file | annotate | diff | comparison | revisions
Cargo.toml file | annotate | diff | comparison | revisions
src/regularisation.rs file | annotate | diff | comparison | revisions
src/run.rs file | annotate | diff | comparison | revisions
src/sliding_fb.rs file | annotate | diff | comparison | revisions
src/sliding_pdps.rs file | annotate | diff | comparison | revisions
--- a/Cargo.lock	Thu Jul 30 09:27:44 2026 -0500
+++ b/Cargo.lock	Fri Jul 31 10:41:47 2026 -0500
@@ -816,7 +816,7 @@
 
 [[package]]
 name = "pointsource_algs"
-version = "3.1.1"
+version = "3.2.0"
 dependencies = [
  "GSL",
  "alg_tools",
--- a/Cargo.toml	Thu Jul 30 09:27:44 2026 -0500
+++ b/Cargo.toml	Fri Jul 31 10:41:47 2026 -0500
@@ -1,6 +1,6 @@
 [package]
 name = "pointsource_algs"
-version = "3.1.1"
+version = "3.2.0"
 edition = "2021"
 rust-version = "1.85"
 authors = ["Tuomo Valkonen <tuomov@iki.fi>"]
--- a/src/regularisation.rs	Thu Jul 30 09:27:44 2026 -0500
+++ b/src/regularisation.rs	Fri Jul 31 10:41:47 2026 -0500
@@ -7,7 +7,7 @@
 use crate::fb::InsertionConfig;
 use crate::measures::{DeltaMeasure, DiscreteMeasure, Radon, RNDM};
 #[allow(unused_imports)] // Used by documentation.
-use crate::sliding_fb::pointsource_sliding_fb_reg;
+use crate::sliding_fb::pointsource_sliding_fb_dom;
 use crate::types::*;
 use alg_tools::instance::{Instance, Space};
 use alg_tools::linops::Mapping;
@@ -213,7 +213,7 @@
         M: MinMaxMapping<Domain, F>;
 }
 
-/// Abstraction of regularisation terms for [`pointsource_sliding_fb_reg`].
+/// Abstraction of regularisation terms for [`pointsource_sliding_fb_dom`].
 pub trait SlidingRegTerm<Domain, F = f64>: RegTerm<Domain, F>
 where
     Domain: Space + Clone,
--- a/src/run.rs	Thu Jul 30 09:27:44 2026 -0500
+++ b/src/run.rs	Fri Jul 31 10:41:47 2026 -0500
@@ -24,10 +24,10 @@
 use crate::regularisation::{NonnegRadonRegTerm, RadonRegTerm, Regularisation, SlidingRegTerm};
 use crate::seminorms::*;
 use crate::sliding_fb::{
-    pointsource_sliding_fb_reg, SlidingFBConfig, TransportConfig, TransportProxPenalty,
+    pointsource_sliding_fb_dom, SlidingFBConfig, TransportConfig, TransportProxPenalty,
 };
 use crate::sliding_pdps::{
-    pointsource_sliding_fb_pair, pointsource_sliding_pdps_pair, SlidingPDPSConfig,
+    pointsource_sliding_fb_pair_dom, pointsource_sliding_pdps_pair_dom, SlidingPDPSConfig,
 };
 use crate::subproblem::{InnerMethod, InnerSettings};
 use crate::tolerance::Tolerance;
@@ -989,6 +989,38 @@
     f: &Dat,
     reg: &Reg,
     prox_penalty: &P,
+    init: (
+        &AlgorithmConfig<F>,
+        I,
+        Plot,
+        Option<RNDM<N, F>>,
+        String,
+    ),
+    cont: impl FnOnce(
+        (&AlgorithmConfig<F>, I, Plot, Option<RNDM<N, F>>, String),
+    ) -> DynResult<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>,
+    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>>,
+{
+    run_fb_dom(f, reg, prox_penalty, init, None, cont)
+}
+
+/// Runs FB-style algorithms if `alg` so requests and `prox_penalty` matches.
+///
+/// `cont` gives a continuation attempt to find the algorithm matching the description `alg`.
+pub fn run_fb_dom<F, Dat, Reg, P, I, Plot, const N: usize>(
+    f: &Dat,
+    reg: &Reg,
+    prox_penalty: &P,
     (alg, iterator, plotter, μ0, running): (
         &AlgorithmConfig<F>,
         I,
@@ -996,6 +1028,7 @@
         Option<RNDM<N, F>>,
         String,
     ),
+    domain: Option<&P::Dom>,
     cont: impl FnOnce(
         (&AlgorithmConfig<F>, I, Plot, Option<RNDM<N, F>>, String),
     ) -> DynResult<RNDM<N, F>>,
@@ -1024,7 +1057,7 @@
         }
         &AlgorithmConfig::SlidingFB(ref algconfig, prox_type) if prox_type == pt => {
             print!("{running}");
-            pointsource_sliding_fb_reg(f, reg, prox_penalty, algconfig, iterator, plotter, μ0)
+            pointsource_sliding_fb_dom(f, reg, prox_penalty, algconfig, iterator, plotter, μ0, domain)
         }
         _ => cont((alg, iterator, plotter, μ0, running)),
     }
@@ -1261,8 +1294,8 @@
                     save_extra,
                     (μ0, z, y),
                     |p| {
-                        run_pdps_pair(&f, &reg, &RadonSquared, &opKz, &fnR, &fnH, p, |q| {
-                            run_pdps_pair(&f, &reg, &op𝒟, &opKz, &fnR, &fnH, q, |_| {
+                        run_pdps_pair_dom(&f, &reg, &RadonSquared, &opKz, &fnR, &fnH, p, None, |q| {
+                            run_pdps_pair_dom(&f, &reg, &op𝒟, &opKz, &fnR, &fnH, q, None, |_| {
                                 Err(NotImplemented.into())
                             })
                         })
@@ -1281,8 +1314,8 @@
                     save_extra,
                     (μ0, z, y),
                     |p| {
-                        run_pdps_pair(&f, &reg, &RadonSquared, &opKz, &fnR, &fnH, p, |q| {
-                            run_pdps_pair(&f, &reg, &op𝒟, &opKz, &fnR, &fnH, q, |_| {
+                        run_pdps_pair_dom(&f, &reg, &RadonSquared, &opKz, &fnR, &fnH, p, None, |q| {
+                            run_pdps_pair_dom(&f, &reg, &op𝒟, &opKz, &fnR, &fnH, q, None, |_| {
                                 Err(NotImplemented.into())
                             })
                         })
@@ -1297,6 +1330,7 @@
 
 type MeasureZ<F, Z, const N: usize> = Pair<RNDM<N, F>, Z>;
 
+#[deprecated]
 pub fn run_pdps_pair<F, S, Dat, Reg, Z, R, Y, KOpZ, H, P, I, Plot, const N: usize>(
     f: &Dat,
     reg: &Reg,
@@ -1304,6 +1338,57 @@
     opKz: &KOpZ,
     fnR: &R,
     fnH: &H,
+    init: (
+        &AlgorithmConfig<F>,
+        I,
+        Plot,
+        (Option<RNDM<N, F>>, Z, Y),
+        String,
+    ),
+    cont: impl FnOnce(
+        (
+            &AlgorithmConfig<F>,
+            I,
+            Plot,
+            (Option<RNDM<N, F>>, Z, Y),
+            String,
+        ),
+    ) -> DynResult<Pair<RNDM<N, F>, Z>>,
+) -> DynResult<Pair<RNDM<N, F>, Z>>
+where
+    F: Float + ToNalgebraRealField,
+    I: AlgIteratorFactory<IterInfo<F>>,
+    Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>>
+        + BoundedCurvature<F>,
+    S: DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>,
+    for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>,
+    //Pair<S, Z>: ClosedMul<F>,
+    RNDM<N, F>: SpikeMerging<F>,
+    Reg: SlidingRegTerm<Loc<N, F>, F>,
+    P: TransportProxPenalty<Loc<N, F>, S, Reg, F>,
+    KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y>
+        + GEMV<F, Z>
+        + SimplyAdjointable<Z, Y, AdjointCodomain = Z>,
+    KOpZ::SimpleAdjoint: GEMV<F, Y>,
+    Y: ClosedEuclidean<F> + Clone,
+    for<'b> &'b Y: Instance<Y>,
+    Z: ClosedEuclidean<F> + Clone + ClosedMul<F> + AXPY,
+    for<'b> &'b Z: Instance<Z>,
+    R: Prox<Z, Codomain = F>,
+    H: Conjugable<Y, F, Codomain = F>,
+    for<'b> H::Conjugate<'b>: Prox<Y>,
+    Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>,
+{
+    run_pdps_pair_dom(f, reg, prox_penalty, opKz, fnR, fnH, init, None, cont)
+}
+
+pub fn run_pdps_pair_dom<F, S, Dat, Reg, Z, R, Y, KOpZ, H, P, I, Plot, const N: usize>(
+    f: &Dat,
+    reg: &Reg,
+    prox_penalty: &P,
+    opKz: &KOpZ,
+    fnR: &R,
+    fnH: &H,
     (alg, iterator, plotter, μ0zy, running): (
         &AlgorithmConfig<F>,
         I,
@@ -1311,6 +1396,7 @@
         (Option<RNDM<N, F>>, Z, Y),
         String,
     ),
+    domain: Option<&P::Dom>,
     cont: impl FnOnce(
         (
             &AlgorithmConfig<F>,
@@ -1365,7 +1451,7 @@
         }
         &AlgorithmConfig::SlidingPDPS(ref algconfig, prox_type) if prox_type == pt => {
             print!("{running}");
-            pointsource_sliding_pdps_pair(
+            pointsource_sliding_pdps_pair_dom(
                 f,
                 reg,
                 prox_penalty,
@@ -1376,6 +1462,7 @@
                 opKz,
                 fnR,
                 fnH,
+                domain,
             )
         }
         _ => cont((alg, iterator, plotter, μ0zy, running)),
@@ -1387,6 +1474,48 @@
     reg: &Reg,
     prox_penalty: &P,
     fnR: &R,
+    init: (
+        &AlgorithmConfig<F>,
+        I,
+        Plot,
+        (Option<RNDM<N, F>>, Z),
+        String,
+    ),
+    cont: impl FnOnce(
+        (
+            &AlgorithmConfig<F>,
+            I,
+            Plot,
+            (Option<RNDM<N, F>>, Z),
+            String,
+        ),
+    ) -> DynResult<Pair<RNDM<N, F>, Z>>,
+) -> DynResult<Pair<RNDM<N, F>, Z>>
+where
+    F: Float + ToNalgebraRealField,
+    I: AlgIteratorFactory<IterInfo<F>>,
+    Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>>
+        + BoundedCurvature<F>,
+    S: DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>,
+    RNDM<N, F>: SpikeMerging<F>,
+    Reg: SlidingRegTerm<Loc<N, F>, F>,
+    P: TransportProxPenalty<Loc<N, F>, S, Reg, F>,
+    for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>,
+    Z: ClosedEuclidean<F> + AXPY + Clone,
+    for<'b> &'b Z: Instance<Z>,
+    R: Prox<Z, Codomain = F>,
+    Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>,
+    // We should not need to explicitly require this:
+    for<'b> &'b Loc<0, F>: Instance<Loc<0, F>>,
+{
+    run_fb_pair_dom(f, reg, prox_penalty, fnR, init, None, cont)
+}
+
+pub fn run_fb_pair_dom<F, S, Dat, Reg, Z, R, P, I, Plot, const N: usize>(
+    f: &Dat,
+    reg: &Reg,
+    prox_penalty: &P,
+    fnR: &R,
     (alg, iterator, plotter, μ0z, running): (
         &AlgorithmConfig<F>,
         I,
@@ -1394,6 +1523,7 @@
         (Option<RNDM<N, F>>, Z),
         String,
     ),
+    domain: Option<&P::Dom>,
     cont: impl FnOnce(
         (
             &AlgorithmConfig<F>,
@@ -1430,7 +1560,7 @@
         }
         &AlgorithmConfig::SlidingFB(ref algconfig, prox_type) if prox_type == pt => {
             print!("{running}");
-            pointsource_sliding_fb_pair(
+            pointsource_sliding_fb_pair_dom(
                 f,
                 reg,
                 prox_penalty,
@@ -1439,6 +1569,7 @@
                 plotter,
                 μ0z,
                 fnR,
+                domain
             )
         }
         _ => cont((alg, iterator, plotter, μ0z, running)),
--- 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)
+}
--- a/src/sliding_pdps.rs	Thu Jul 30 09:27:44 2026 -0500
+++ b/src/sliding_pdps.rs	Fri Jul 31 10:41:47 2026 -0500
@@ -67,9 +67,10 @@
 /// Iteratively solve the pointsource localisation with an additional variable
 /// using sliding primal-dual proximal splitting
 ///
-/// The parametrisation is as for [`crate::forward_pdps::pointsource_forward_pdps_pair`].
+/// The parametrisation is as for [`crate::forward_pdps::pointsource_forward_pdps_pair`],
+/// except an additional domain restriction may be given.
 #[replace_float_literals(F::cast_from(literal))]
-pub fn pointsource_sliding_pdps_pair<
+pub fn pointsource_sliding_pdps_pair_dom<
     F,
     I,
     S,
@@ -95,6 +96,7 @@
     opKz: &KOpZ,
     fnR: &R,
     fnH: &H,
+    domain: Option<&P::Dom>,
 ) -> DynResult<MeasureZ<F, Z, N>>
 where
     F: Float + ToNalgebraRealField,
@@ -236,6 +238,7 @@
             &mut τθ_or_adaptive,
             &v,
             &config.transport,
+            domain,
         );
 
         let mut attempts = 0;
@@ -382,6 +385,144 @@
 /// The implementation uses [`pointsource_sliding_pdps_pair`] with appropriate dummy
 /// variables, operators, and functions.
 #[replace_float_literals(F::cast_from(literal))]
+pub fn pointsource_sliding_fb_pair_dom<F, I, S, Dat, Reg, P, Z, R, Plot, const N: usize>(
+    f: &Dat,
+    reg: &Reg,
+    prox_penalty: &P,
+    config: &SlidingFBConfig<F>,
+    iterator: I,
+    plotter: Plot,
+    (μ0, z): (Option<RNDM<N, F>>, Z),
+    //opKμ : KOpM,
+    fnR: &R,
+    domain: Option<&P::Dom>
+) -> DynResult<MeasureZ<F, Z, N>>
+where
+    F: Float + ToNalgebraRealField,
+    I: AlgIteratorFactory<IterInfo<F>>,
+    Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>>
+        + BoundedCurvature<F>,
+    S: DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>,
+    RNDM<N, F>: SpikeMerging<F>,
+    Reg: SlidingRegTerm<Loc<N, F>, F>,
+    P: TransportProxPenalty<Loc<N, F>, S, Reg, F>,
+    for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>,
+    Z: ClosedEuclidean<F> + AXPY + Clone,
+    for<'b> &'b Z: Instance<Z>,
+    R: Prox<Z, Codomain = F>,
+    Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>,
+    // We should not need to explicitly require this:
+    for<'b> &'b Loc<0, F>: Instance<Loc<0, F>>,
+    // Loc<0, F>: StaticEuclidean<Field = F, PrincipalE = Loc<0, F>>
+    //     + Instance<Loc<0, F>>
+    //     + VectorSpace<Field = F>,
+{
+    let opKz: ZeroOp<Z, Loc<0, F>, _, _, F> =
+        ZeroOp::new_dualisable(StaticEuclideanOriginGenerator, z.dual_origin());
+    let fnH = Zero::new();
+    // Convert config. We don't implement From (that could be done with the o2o crate), as σd0
+    // needs to be chosen in a general case; for the problem of this fucntion, anything is valid.
+    let &SlidingFBConfig { τ0, σp0, insertion, transport, guess } = config;
+    let pdps_config = SlidingPDPSConfig { τ0, σp0, insertion, transport, guess, σd0: 0.0 };
+
+    pointsource_sliding_pdps_pair_dom(
+        f,
+        reg,
+        prox_penalty,
+        &pdps_config,
+        iterator,
+        plotter,
+        (μ0, z, Loc([])),
+        &opKz,
+        fnR,
+        &fnH,
+        domain
+    )
+}
+
+
+#[deprecated]
+/// Version of [`pointsource_sliding_pdps_pair`] without domain specification.
+#[replace_float_literals(F::cast_from(literal))]
+pub fn pointsource_sliding_pdps_pair<
+    F,
+    I,
+    S,
+    Dat,
+    Reg,
+    P,
+    Z,
+    R,
+    Y,
+    Plot,
+    /*KOpM, */ KOpZ,
+    H,
+    const N: usize,
+>(
+    f: &Dat,
+    reg: &Reg,
+    prox_penalty: &P,
+    config: &SlidingPDPSConfig<F>,
+    iterator: I,
+    plotter: Plot,
+    init: (Option<RNDM<N, F>>, Z, Y),
+    //opKμ : KOpM,
+    opKz: &KOpZ,
+    fnR: &R,
+    fnH: &H,
+) -> DynResult<MeasureZ<F, Z, N>>
+where
+    F: Float + ToNalgebraRealField,
+    I: AlgIteratorFactory<IterInfo<F>>,
+    Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>>
+        + BoundedCurvature<F>,
+    S: DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>,
+    for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>,
+    //Pair<S, Z>: ClosedMul<F>,
+    RNDM<N, F>: SpikeMerging<F>,
+    Reg: SlidingRegTerm<Loc<N, F>, F>,
+    P: TransportProxPenalty<Loc<N, F>, S, Reg, F>,
+    // KOpM : Linear<RNDM<N, F>, Codomain=Y>
+    //     + GEMV<F, RNDM<N, F>>
+    //     + Preadjointable<
+    //         RNDM<N, F>, Y,
+    //         PreadjointCodomain = S,
+    //     >
+    //     + TransportLipschitz<L2Squared, FloatType=F>
+    //     + AdjointProductBoundedBy<RNDM<N, F>, 𝒟, FloatType=F>,
+    // for<'b> KOpM::Preadjoint<'b> : GEMV<F, Y>,
+    // Since Z is Hilbert, we may just as well use adjoints for K_z.
+    KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y>
+        + GEMV<F, Z>
+        + SimplyAdjointable<Z, Y, AdjointCodomain = Z>,
+    KOpZ::SimpleAdjoint: GEMV<F, Y>,
+    Y: ClosedEuclidean<F>,
+    for<'b> &'b Y: Instance<Y>,
+    Z: ClosedEuclidean<F> + AXPY,
+    for<'b> &'b Z: Instance<Z>,
+    R: Prox<Z, Codomain = F>,
+    H: Conjugable<Y, F, Codomain = F>,
+    for<'b> H::Conjugate<'b>: Prox<Y>,
+    Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>,
+{
+    pointsource_sliding_pdps_pair_dom(
+        f,
+        reg,
+        prox_penalty,
+        config,
+        iterator,
+        plotter,
+        init,
+        opKz,
+        fnR,
+        fnH,
+        None,
+    )
+}
+
+#[deprecated]
+/// Version of [`pointsource_sliding_fb_pair_dom`] without domain specification
+#[replace_float_literals(F::cast_from(literal))]
 pub fn pointsource_sliding_fb_pair<F, I, S, Dat, Reg, P, Z, R, Plot, const N: usize>(
     f: &Dat,
     reg: &Reg,
@@ -421,7 +562,7 @@
     let &SlidingFBConfig { τ0, σp0, insertion, transport, guess } = config;
     let pdps_config = SlidingPDPSConfig { τ0, σp0, insertion, transport, guess, σd0: 0.0 };
 
-    pointsource_sliding_pdps_pair(
+    pointsource_sliding_pdps_pair_dom(
         f,
         reg,
         prox_penalty,
@@ -432,5 +573,6 @@
         &opKz,
         fnR,
         &fnH,
+        None
     )
 }

mercurial