src/sliding_fb.rs

changeset 93
8f1e57821d76
parent 91
47d495348e38
child 98
b9818eb24b47
equal deleted inserted replaced
92:759634edb536 93:8f1e57821d76
22 use crate::seminorms::DiscreteMeasureOp; 22 use crate::seminorms::DiscreteMeasureOp;
23 use crate::types::*; 23 use crate::types::*;
24 use alg_tools::bounds::{Bounds, MinMaxMapping}; 24 use alg_tools::bounds::{Bounds, MinMaxMapping};
25 use alg_tools::error::DynResult; 25 use alg_tools::error::DynResult;
26 use alg_tools::euclidean::Euclidean; 26 use alg_tools::euclidean::Euclidean;
27 use alg_tools::instance::Space; 27 use alg_tools::instance::{Instance, Space};
28 use alg_tools::iterate::AlgIteratorFactory; 28 use alg_tools::iterate::AlgIteratorFactory;
29 use alg_tools::mapping::{DifferentiableMapping, DifferentiableRealMapping, Mapping, RealMapping}; 29 use alg_tools::mapping::{DifferentiableMapping, DifferentiableRealMapping, Mapping, RealMapping};
30 use alg_tools::nalgebra_support::ToNalgebraRealField; 30 use alg_tools::nalgebra_support::ToNalgebraRealField;
31 use alg_tools::norms::Norm; 31 use alg_tools::norms::{Dist, Norm, L2};
32 use anyhow::ensure; 32 use anyhow::ensure;
33 use std::ops::ControlFlow; 33 use std::ops::ControlFlow;
34 34
35 /// Transport settings for [`pointsource_sliding_fb_reg`]. 35 /// Transport settings for [`pointsource_sliding_fb_reg`].
36 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] 36 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)]
191 } 191 }
192 } 192 }
193 } 193 }
194 194
195 #[derive(Clone, Debug, Serialize)] 195 #[derive(Clone, Debug, Serialize)]
196 pub struct SingleTransport<Domain, F: Float> { 196 pub struct SingleTransport<U, F: Float> {
197 /// Source point 197 /// Source point
198 x: Domain, 198 x: U,
199 /// Target point 199 /// Target point
200 y: Domain, 200 y: U,
201 /// Original mass 201 /// Original mass
202 α_μ_orig: F, 202 α_μ_orig: F,
203 /// Transported mass 203 /// Transported mass
204 α_γ: F, 204 α_γ: F,
205 /// Helper for pruning 205 /// Helper for pruning
209 /// Contribution to remainder (temporary variable) 209 /// Contribution to remainder (temporary variable)
210 excess: F, 210 excess: F,
211 } 211 }
212 212
213 #[derive(Clone, Debug, Serialize)] 213 #[derive(Clone, Debug, Serialize)]
214 pub struct Transport<Domain, F: Float> { 214 pub struct Transport<U, F: Float> {
215 vec: Vec<SingleTransport<Domain, F>>, 215 vec: Vec<SingleTransport<U, F>>,
216 } 216 }
217 217
218 /// Whether partially transported points are allowed. 218 /// Whether partially transported points are allowed.
219 /// 219 ///
220 /// Partial transport can cause spike count explosion, so full or zero 220 /// Partial transport can cause spike count explosion, so full or zero
221 /// transport is generally preferred. If this is set to `true`, different 221 /// transport is generally preferred. If this is set to `true`, different
222 /// transport adaptation heuristics will be used. 222 /// transport adaptation heuristics will be used.
223 const MINIMAL_PARTIAL_TRANSPORT: bool = true; 223 const MINIMAL_PARTIAL_TRANSPORT: bool = true;
224 const NEW_APPROACH: bool = true; 224 const NEW_APPROACH: bool = true;
225 225
226 pub trait TransportProxPenalty<Point, PreadjointCodomain, Reg, F = f64>: 226 pub trait TransportProxPenalty<U, PreadjointCodomain, Reg, F = f64>:
227 ProxPenalty<Point, PreadjointCodomain, Reg, F> 227 ProxPenalty<U, PreadjointCodomain, Reg, F>
228 where 228 where
229 F: Float + ToNalgebraRealField, 229 F: Float + ToNalgebraRealField,
230 Reg: SlidingRegTerm<Point, F>, 230 Reg: SlidingRegTerm<U, F>,
231 Point: Space + Clone, 231 U: Space + Clone,
232 { 232 {
233 type TransportStepLength; 233 type TransportStepLength;
234 234
235 /// Constrution of initial transport `γ1` from initial measure `μ` and `v=F'(μ)` 235 /// Constrution of initial transport `γ1` from initial measure `μ` and `v=F'(μ)`
236 /// with step lengh τ and transport step length `θ_or_adaptive`. 236 /// with step lengh τ and transport step length `θ_or_adaptive`.
237 fn initial_transport<Dom: AdmissibleDomain<Point>>( 237 fn initial_transport<Dom: AdmissibleDomain<U>>(
238 &self, 238 &self,
239 γ: &mut Transport<Point, F>, 239 γ: &mut Transport<U, F>,
240 μ: &DiscreteMeasure<Point, F>, 240 μ: &DiscreteMeasure<U, F>,
241 ε: F, 241 ε: F,
242 τ: F, 242 τ: F,
243 τθ_or_adaptive: &mut Self::TransportStepLength, 243 τθ_or_adaptive: &mut Self::TransportStepLength,
244 v: &PreadjointCodomain, 244 v: &PreadjointCodomain,
245 tconfig: &TransportConfig<F>, 245 tconfig: &TransportConfig<F>,
247 ); 247 );
248 248
249 /// A posteriori transport adaptation. 249 /// A posteriori transport adaptation.
250 fn aposteriori_transport( 250 fn aposteriori_transport(
251 &self, 251 &self,
252 γ: &mut Transport<Point, F>, 252 γ: &mut Transport<U, F>,
253 μ: &DiscreteMeasure<Point, F>, 253 μ: &DiscreteMeasure<U, F>,
254 μ̆: &DiscreteMeasure<Point, F>, 254 μ̆: &DiscreteMeasure<U, F>,
255 τv̆: &mut PreadjointCodomain, 255 τv̆: &mut PreadjointCodomain,
256 v: &mut PreadjointCodomain, 256 v: &mut PreadjointCodomain,
257 extra: Option<F>, 257 extra: Option<F>,
258 ε: F, 258 ε: F,
259 τ: F, 259 τ: F,
375 all_ok 375 all_ok
376 } 376 }
377 } 377 }
378 378
379 #[replace_float_literals(F::cast_from(literal))] 379 #[replace_float_literals(F::cast_from(literal))]
380 impl<F, M, Reg, 𝒟, O, const N: usize> TransportProxPenalty<Loc<N, F>, M, Reg, F> for 𝒟 380 impl<F, M, Reg, 𝒟, const N: usize> TransportProxPenalty<Loc<N, F>, M, Reg, F> for 𝒟
381 where 381 where
382 F: Float + ToNalgebraRealField, 382 F: Float + ToNalgebraRealField,
383 𝒟: DiscreteMeasureOp<Loc<N, F>, F>, 383 𝒟: DiscreteMeasureOp<Loc<N, F>, F>,
384 𝒟::Codomain: RealMapping<N, F>, 384 𝒟::Codomain: RealMapping<N, F>,
385 M: MinMaxMapping<Loc<N, F>, F> + DifferentiableRealMapping<N, F>, 385 M: MinMaxMapping<Loc<N, F>, F> + DifferentiableRealMapping<N, F>,
386 for<'a> &'a M: std::ops::Add<𝒟::PreCodomain, Output = O>,
387 O: MinMaxMapping<Loc<N, F>, F>,
388 Reg: SlidingRegTerm<Loc<N, F>, F>, 386 Reg: SlidingRegTerm<Loc<N, F>, F>,
389 Self: ProxPenalty<Loc<N, F>, M, Reg, F>, 387 Self: ProxPenalty<Loc<N, F>, M, Reg, F>,
390 RNDM<N, F>: SpikeMerging<F>, 388 RNDM<N, F>: SpikeMerging<F>,
391 { 389 {
392 type TransportStepLength = TransportStepLength<F>; 390 type TransportStepLength = TransportStepLength<F>;
606 } 604 }
607 all_ok 605 all_ok
608 } 606 }
609 } 607 }
610 608
609 impl<U, F: Float> Norm<Radon, F> for Transport<U, F> {
610 fn norm(&self, _: Radon) -> F {
611 self.iter().map(|ρ| ρ.α_γ.abs()).sum()
612 }
613 }
614
615 impl<U, F: Float> MulAssign<F> for Transport<U, F> {
616 fn mul_assign(&mut self, factor: F) {
617 for ρ in self.iter_mut() {
618 ρ.α_γ *= factor;
619 }
620 }
621 }
622
611 #[replace_float_literals(F::cast_from(literal))] 623 #[replace_float_literals(F::cast_from(literal))]
612 impl<const N: usize, F: Float> Transport<Loc<N, F>, F> { 624 impl<U, F: Float> Transport<U, F> {
613 pub(crate) fn new() -> Self { 625 pub(crate) fn new() -> Self {
614 Transport { vec: Vec::new() } 626 Transport { vec: Vec::new() }
615 } 627 }
616 628
617 pub(crate) fn iter(&self) -> impl Iterator<Item = &'_ SingleTransport<Loc<N, F>, F>> { 629 pub(crate) fn iter(&self) -> impl Iterator<Item = &'_ SingleTransport<U, F>> {
618 self.vec.iter() 630 self.vec.iter()
619 } 631 }
620 632
621 pub(crate) fn iter_mut( 633 pub(crate) fn iter_mut(&mut self) -> impl Iterator<Item = &'_ mut SingleTransport<U, F>> {
622 &mut self,
623 ) -> impl Iterator<Item = &'_ mut SingleTransport<Loc<N, F>, F>> {
624 self.vec.iter_mut() 634 self.vec.iter_mut()
625 } 635 }
626 636
627 pub(crate) fn extend<I>(&mut self, it: I) 637 pub(crate) fn extend<I>(&mut self, it: I)
628 where 638 where
629 I: IntoIterator<Item = SingleTransport<Loc<N, F>, F>>, 639 I: IntoIterator<Item = SingleTransport<U, F>>,
630 { 640 {
631 self.vec.extend(it) 641 self.vec.extend(it)
632 } 642 }
633 643
634 pub(crate) fn len(&self) -> usize { 644 pub(crate) fn len(&self) -> usize {
635 self.vec.len() 645 self.vec.len()
636 }
637
638 // pub(crate) fn dist_matching(&self, μ: &RNDM<N, F>) -> F {
639 // self.iter()
640 // .zip(μ.iter_spikes())
641 // .map(|(ρ, δ)| (ρ.α_γ - δ.α).abs())
642 // .sum()
643 // }
644
645 /// Construct `μ̆`, replacing the contents of `μ`.
646 pub(crate) fn μ̆_into(&self, μ: &mut RNDM<N, F>) {
647 assert!(self.len() <= μ.len());
648
649 // First transported points
650 for (δ, ρ) in izip!(μ.iter_spikes_mut(), self.iter()) {
651 if ρ.α_γ.abs() > 0.0 {
652 // Transport – transported point
653 δ.α = ρ.α_γ;
654 δ.x = ρ.y;
655 } else {
656 // No transport – original point
657 δ.α = ρ.α_μ_orig;
658 δ.x = ρ.x;
659 }
660 }
661
662 // Then source points with partial transport
663 let mut i = self.len();
664 // This can cause the number of points to explode, so cannot have partial transport.
665 for ρ in self.iter() {
666 let α = ρ.α_μ_orig - ρ.α_γ;
667 if ρ.α_γ.abs() > F::EPSILON && α.abs() > F::EPSILON {
668 let δ = DeltaMeasure { α, x: ρ.x };
669 if i < μ.len() {
670 μ[i] = δ;
671 } else {
672 μ.push(δ)
673 }
674 i += 1;
675 }
676 }
677 μ.truncate(i);
678 } 646 }
679 647
680 /// Returns $‖μ\^k - π\_♯\^0γ\^{k+1}‖$ 648 /// Returns $‖μ\^k - π\_♯\^0γ\^{k+1}‖$
681 pub(crate) fn μ0_minus_γ0_radon(&self) -> F { 649 pub(crate) fn μ0_minus_γ0_radon(&self) -> F {
682 self.vec.iter().map(|ρ| (ρ.α_μ_orig - ρ.α_γ).abs()).sum() 650 self.vec.iter().map(|ρ| (ρ.α_μ_orig - ρ.α_γ).abs()).sum()
683 } 651 }
684 652
653 /// Prune spikes with zero weight. To maintain correct ordering between μ and γ, also the
654 /// latter needs to be pruned when μ is.
655 pub(crate) fn prune_compat(&mut self, μ: &mut DiscreteMeasure<U, F>, stats: &mut IterInfo<F>) {
656 assert!(self.vec.len() <= μ.len());
657 let old_len = μ.len();
658 for (ρ, δ) in self.vec.iter_mut().zip(μ.iter_spikes()) {
659 ρ.retain = δ.α != F::ZERO;
660 }
661 // Do not prune new insertions on first round.
662 μ.prune_until(self.vec.len());
663 stats.pruned += old_len - μ.len();
664 self.vec.retain(|ρ| ρ.retain);
665 assert!(self.vec.len() <= μ.len());
666 }
667 }
668
669 #[replace_float_literals(F::cast_from(literal))]
670 impl<U, F> Transport<U, F>
671 where
672 U: Dist<L2, F>,
673 F: Float,
674 for<'a> &'a U: Instance<U>,
675 {
685 /// Returns $∫ c_2 d|γ|$ 676 /// Returns $∫ c_2 d|γ|$
686 pub(crate) fn c2integral(&self) -> F { 677 pub(crate) fn c2integral(&self) -> F {
678 let sq2 = |x| (x * x) / 2.0;
687 self.vec 679 self.vec
688 .iter() 680 .iter()
689 .map(|ρ| ρ.y.dist2_squared(&ρ.x) / 2.0 * ρ.α_γ.abs()) 681 .map(|ρ| sq2(ρ.y.dist(&ρ.x, L2)) * ρ.α_γ.abs())
690 .sum() 682 .sum()
691 } 683 }
692 684
693 pub(crate) fn get_transport_stats(&self, stats: &mut IterInfo<F>, μ: &RNDM<N, F>) { 685 pub(crate) fn get_transport_stats(&self, stats: &mut IterInfo<F>, μ: &DiscreteMeasure<U, F>) {
694 // TODO: This doesn't take into account μ[i].α becoming zero in the latest tranport 686 // TODO: This doesn't take into account μ[i].α becoming zero in the latest tranport
695 // attempt, for i < self.len(), when a corresponding source term also exists with index 687 // attempt, for i < self.len(), when a corresponding source term also exists with index
696 // j ≥ self.len(). For now, we let that be reflected in the prune count. 688 // j ≥ self.len(). For now, we let that be reflected in the prune count.
697 stats.inserted += μ.len() - self.len(); 689 stats.inserted += μ.len() - self.len();
698 690
724 (a, b) 716 (a, b)
725 } 717 }
726 }) 718 })
727 }; 719 };
728 } 720 }
729 721 }
730 /// Prune spikes with zero weight. To maintain correct ordering between μ and γ, also the 722
731 /// latter needs to be pruned when μ is. 723 #[replace_float_literals(F::cast_from(literal))]
732 pub(crate) fn prune_compat(&mut self, μ: &mut RNDM<N, F>, stats: &mut IterInfo<F>) { 724 impl<U: Clone, F: Float> Transport<U, F> {
733 assert!(self.vec.len() <= μ.len()); 725 // pub(crate) fn dist_matching(&self, μ: &RNDM<N, F>) -> F {
734 let old_len = μ.len(); 726 // self.iter()
735 for (ρ, δ) in self.vec.iter_mut().zip(μ.iter_spikes()) { 727 // .zip(μ.iter_spikes())
736 ρ.retain = δ.α != F::ZERO; 728 // .map(|(ρ, δ)| (ρ.α_γ - δ.α).abs())
737 } 729 // .sum()
738 // Do not prune new insertions on first round. 730 // }
739 μ.prune_until(self.vec.len()); 731
740 stats.pruned += old_len - μ.len(); 732 /// Construct `μ̆`, replacing the contents of `μ`.
741 self.vec.retain(|ρ| ρ.retain); 733 pub(crate) fn μ̆_into(&self, μ: &mut DiscreteMeasure<U, F>) {
742 assert!(self.vec.len() <= μ.len()); 734 assert!(self.len() <= μ.len());
743 } 735
744 736 // First transported points
737 for (δ, ρ) in izip!(μ.iter_spikes_mut(), self.iter()) {
738 if ρ.α_γ.abs() > 0.0 {
739 // Transport – transported point
740 δ.α = ρ.α_γ;
741 δ.x = ρ.y.clone();
742 } else {
743 // No transport – original point
744 δ.α = ρ.α_μ_orig;
745 δ.x = ρ.x.clone();
746 }
747 }
748
749 // Then source points with partial transport
750 let mut i = self.len();
751 // This can cause the number of points to explode, so cannot have partial transport.
752 for ρ in self.iter() {
753 let α = ρ.α_μ_orig - ρ.α_γ;
754 if ρ.α_γ.abs() > F::EPSILON && α.abs() > F::EPSILON {
755 let δ = DeltaMeasure { α, x: ρ.x.clone() };
756 if i < μ.len() {
757 μ[i] = δ;
758 } else {
759 μ.push(δ)
760 }
761 i += 1;
762 }
763 }
764 μ.truncate(i);
765 }
766 }
767
768 #[replace_float_literals(F::cast_from(literal))]
769 impl<const N: usize, F: Float> Transport<Loc<N, F>, F> {
745 /// Helper for initial transport. Called from [`TransportProxPenalty::initial_transport`]. 770 /// Helper for initial transport. Called from [`TransportProxPenalty::initial_transport`].
746 pub(super) fn do_init_transport<D, Dom: AdmissibleDomain<Loc<N, F>>>( 771 pub(super) fn do_init_transport<D, Dom: AdmissibleDomain<Loc<N, F>>>(
747 &mut self, 772 &mut self,
748 v: &D, 773 v: &D,
749 μ: &RNDM<N, F>, 774 μ: &RNDM<N, F>,
953 all_ok 978 all_ok
954 } 979 }
955 } 980 }
956 } 981 }
957 982
958 impl<const N: usize, F: Float> Norm<Radon, F> for Transport<Loc<N, F>, F> {
959 fn norm(&self, _: Radon) -> F {
960 self.iter().map(|ρ| ρ.α_γ.abs()).sum()
961 }
962 }
963
964 impl<const N: usize, F: Float> MulAssign<F> for Transport<Loc<N, F>, F> {
965 fn mul_assign(&mut self, factor: F) {
966 for ρ in self.iter_mut() {
967 ρ.α_γ *= factor;
968 }
969 }
970 }
971
972 /// Iteratively solve the pointsource localisation problem using sliding forward-backward 983 /// Iteratively solve the pointsource localisation problem using sliding forward-backward
973 /// splitting 984 /// splitting
974 /// 985 ///
975 /// The parametrisation is as for [`pointsource_fb_reg`], except an additional domain restriction 986 /// The parametrisation is as for [`pointsource_fb_reg`], except an additional domain restriction
976 /// may be given. 987 /// may be given.
977 /// Inertia is currently not supported. 988 /// Inertia is currently not supported.
978 #[replace_float_literals(F::cast_from(literal))] 989 #[replace_float_literals(F::cast_from(literal))]
979 pub fn pointsource_sliding_fb<F, I, Dat, Reg, Plot, P, const N: usize>( 990 pub fn pointsource_sliding_fb<F, U, I, Dat, Reg, Plot, P>(
980 f: &Dat, 991 f: &Dat,
981 reg: &Reg, 992 reg: &Reg,
982 prox_penalty: &P, 993 prox_penalty: &P,
983 config: &SlidingFBConfig<F>, 994 config: &SlidingFBConfig<F>,
984 iterator: I, 995 iterator: I,
985 mut plotter: Plot, 996 mut plotter: Plot,
986 μ0: Option<RNDM<N, F>>, 997 μ0: Option<DiscreteMeasure<U, F>>,
987 domain: &mut impl AdmissibleDomain<Loc<N, F>>, 998 domain: &mut impl AdmissibleDomain<U>,
988 ) -> DynResult<RNDM<N, F>> 999 ) -> DynResult<DiscreteMeasure<U, F>>
989 where 1000 where
990 F: Float + ToNalgebraRealField, 1001 F: Float + ToNalgebraRealField,
1002 U: Space + Clone + Dist<L2, F>,
1003 for<'a> &'a U: Instance<U>,
991 I: AlgIteratorFactory<IterInfo<F>>, 1004 I: AlgIteratorFactory<IterInfo<F>>,
992 Dat: DifferentiableMapping<RNDM<N, F>, Codomain = F> + BoundedCurvature<F>, 1005 Dat: DifferentiableMapping<DiscreteMeasure<U, F>, Codomain = F> + BoundedCurvature<F>,
993 Dat::DerivativeDomain: 1006 Dat::DerivativeDomain:
994 DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>, 1007 DifferentiableMapping<U, Codomain = F> + ClosedMul<F> + MinMaxMapping<U, F>,
995 //for<'a> Dat::Differential<'a>: Lipschitz<&'a P, FloatType = F>, 1008 //for<'a> Dat::Differential<'a>: Lipschitz<&'a P, FloatType = F>,
996 RNDM<N, F>: SpikeMerging<F>, 1009 DiscreteMeasure<U, F>: SpikeMerging<F>,
997 Reg: SlidingRegTerm<Loc<N, F>, F>, 1010 Reg: SlidingRegTerm<U, F>,
998 P: TransportProxPenalty<Loc<N, F>, Dat::DerivativeDomain, Reg, F> + StepLengthBound<F, Dat>, 1011 P: TransportProxPenalty<U, Dat::DerivativeDomain, Reg, F> + StepLengthBound<F, Dat>,
999 Plot: Plotter<P::ReturnMapping, Dat::DerivativeDomain, RNDM<N, F>>, 1012 Plot: Plotter<P::ReturnMapping, Dat::DerivativeDomain, DiscreteMeasure<U, F>>,
1000 { 1013 {
1001 // Check parameters 1014 // Check parameters
1002 ensure!(config.τ0 > 0.0, "Invalid step length parameter"); 1015 ensure!(config.τ0 > 0.0, "Invalid step length parameter");
1003 config.transport.check()?; 1016 config.transport.check()?;
1004 1017
1023 // by τ compared to the conditional gradient approach. 1036 // by τ compared to the conditional gradient approach.
1024 let tolerance = config.insertion.tolerance * τ * reg.tolerance_scaling(); 1037 let tolerance = config.insertion.tolerance * τ * reg.tolerance_scaling();
1025 let mut ε = tolerance.initial(); 1038 let mut ε = tolerance.initial();
1026 1039
1027 // Statistics 1040 // Statistics
1028 let full_stats = |μ: &RNDM<N, F>, ε, stats| IterInfo { 1041 let full_stats = |μ: &DiscreteMeasure<U, F>, ε, stats| IterInfo {
1029 value: f.apply(μ) + reg.apply(μ), 1042 value: f.apply(μ) + reg.apply(μ),
1030 n_spikes: μ.len(), 1043 n_spikes: μ.len(),
1031 ε, 1044 ε,
1032 // postprocessing: config.insertion.postprocessing.then(|| μ.clone()), 1045 // postprocessing: config.insertion.postprocessing.then(|| μ.clone()),
1033 ..stats 1046 ..stats
1112 &μ̆, 1125 &μ̆,
1113 τ, 1126 τ,
1114 ε, 1127 ε,
1115 ins, 1128 ins,
1116 &reg, 1129 &reg,
1117 Some(|μ̃: &RNDM<N, F>| f.apply(μ̃) + reg.apply(μ̃)), 1130 Some(|μ̃: &DiscreteMeasure<U, F>| f.apply(μ̃) + reg.apply(μ̃)),
1118 ); 1131 );
1119 // Prune. Do not prune new insertions on first round. 1132 // Prune. Do not prune new insertions on first round.
1120 γ.prune_compat(&mut μ, &mut stats); 1133 γ.prune_compat(&mut μ, &mut stats);
1121 1134
1122 if config.insertion.random_insertions { 1135 if config.insertion.random_insertions {
1165 postprocess(μ, &config.insertion, |μ̃| f.apply(μ̃) + reg.apply(μ̃)) 1178 postprocess(μ, &config.insertion, |μ̃| f.apply(μ̃) + reg.apply(μ̃))
1166 } 1179 }
1167 1180
1168 #[deprecated] 1181 #[deprecated]
1169 /// Version of `pointsource_sliding_fb` without domain restriction 1182 /// Version of `pointsource_sliding_fb` without domain restriction
1170 pub fn pointsource_sliding_fb_reg<F, I, Dat, Reg, Plot, P, const N: usize>( 1183 pub fn pointsource_sliding_fb_reg<F, U, I, Dat, Reg, Plot, P>(
1171 f: &Dat, 1184 f: &Dat,
1172 reg: &Reg, 1185 reg: &Reg,
1173 prox_penalty: &P, 1186 prox_penalty: &P,
1174 config: &SlidingFBConfig<F>, 1187 config: &SlidingFBConfig<F>,
1175 iterator: I, 1188 iterator: I,
1176 plotter: Plot, 1189 plotter: Plot,
1177 μ0: Option<RNDM<N, F>>, 1190 μ0: Option<DiscreteMeasure<U, F>>,
1178 ) -> DynResult<RNDM<N, F>> 1191 ) -> DynResult<DiscreteMeasure<U, F>>
1179 where 1192 where
1180 F: Float + ToNalgebraRealField, 1193 F: Float + ToNalgebraRealField,
1194 U: Space + Clone + Dist<L2, F>,
1195 for<'a> &'a U: Instance<U>,
1181 I: AlgIteratorFactory<IterInfo<F>>, 1196 I: AlgIteratorFactory<IterInfo<F>>,
1182 Dat: DifferentiableMapping<RNDM<N, F>, Codomain = F> + BoundedCurvature<F>, 1197 Dat: DifferentiableMapping<DiscreteMeasure<U, F>, Codomain = F> + BoundedCurvature<F>,
1183 Dat::DerivativeDomain: 1198 Dat::DerivativeDomain:
1184 DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>, 1199 DifferentiableMapping<U, Codomain = F> + ClosedMul<F> + MinMaxMapping<U, F>,
1185 //for<'a> Dat::Differential<'a>: Lipschitz<&'a P, FloatType = F>, 1200 //for<'a> Dat::Differential<'a>: Lipschitz<&'a P, FloatType = F>,
1186 RNDM<N, F>: SpikeMerging<F>, 1201 DiscreteMeasure<U, F>: SpikeMerging<F>,
1187 Reg: SlidingRegTerm<Loc<N, F>, F>, 1202 Reg: SlidingRegTerm<U, F>,
1188 P: TransportProxPenalty<Loc<N, F>, Dat::DerivativeDomain, Reg, F> + StepLengthBound<F, Dat>, 1203 P: TransportProxPenalty<U, Dat::DerivativeDomain, Reg, F> + StepLengthBound<F, Dat>,
1189 Plot: Plotter<P::ReturnMapping, Dat::DerivativeDomain, RNDM<N, F>>, 1204 Plot: Plotter<P::ReturnMapping, Dat::DerivativeDomain, DiscreteMeasure<U, F>>,
1190 { 1205 {
1191 pointsource_sliding_fb( 1206 pointsource_sliding_fb(
1192 f, 1207 f,
1193 reg, 1208 reg,
1194 prox_penalty, 1209 prox_penalty,

mercurial