| 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)] |
| 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>, |
| 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 |
| 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, |