--- 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 ) }