src/sliding_pdps.rs

changeset 93
8f1e57821d76
parent 89
8d1c959432c8
child 95
d9318317ccac
equal deleted inserted replaced
92:759634edb536 93:8f1e57821d76
5 5
6 use crate::domain::{AdmissibleDomain, FullSpace}; 6 use crate::domain::{AdmissibleDomain, FullSpace};
7 use crate::fb::*; 7 use crate::fb::*;
8 use crate::forward_model::{BoundedCurvature, BoundedCurvatureGuess}; 8 use crate::forward_model::{BoundedCurvature, BoundedCurvatureGuess};
9 use crate::measures::merging::SpikeMerging; 9 use crate::measures::merging::SpikeMerging;
10 use crate::measures::{DiscreteMeasure, RNDM}; 10 use crate::measures::DiscreteMeasure;
11 use crate::plot::Plotter; 11 use crate::plot::Plotter;
12 use crate::prox_penalty::StepLengthBoundPair; 12 use crate::prox_penalty::StepLengthBoundPair;
13 use crate::regularisation::SlidingRegTerm; 13 use crate::regularisation::SlidingRegTerm;
14 use crate::sliding_fb::{SlidingFBConfig, Transport, TransportConfig, TransportProxPenalty}; 14 use crate::sliding_fb::{SlidingFBConfig, Transport, TransportConfig, TransportProxPenalty};
15 use crate::types::*; 15 use crate::types::*;
16 use alg_tools::bounds::MinMaxMapping; 16 use alg_tools::bounds::MinMaxMapping;
17 use alg_tools::convex::{Conjugable, Prox, Zero}; 17 use alg_tools::convex::{Conjugable, Prox, Zero};
18 use alg_tools::direct_product::Pair; 18 use alg_tools::direct_product::Pair;
19 use alg_tools::error::DynResult; 19 use alg_tools::error::DynResult;
20 use alg_tools::euclidean::ClosedEuclidean; 20 use alg_tools::euclidean::ClosedEuclidean;
21 use alg_tools::instance::{Instance, Space};
21 use alg_tools::iterate::AlgIteratorFactory; 22 use alg_tools::iterate::AlgIteratorFactory;
22 use alg_tools::linops::{ 23 use alg_tools::linops::{
23 BoundedLinear, IdOp, SimplyAdjointable, StaticEuclideanOriginGenerator, ZeroOp, AXPY, GEMV, 24 BoundedLinear, IdOp, SimplyAdjointable, StaticEuclideanOriginGenerator, ZeroOp, AXPY, GEMV,
24 }; 25 };
25 use alg_tools::mapping::{DifferentiableMapping, DifferentiableRealMapping, Instance}; 26 use alg_tools::mapping::DifferentiableMapping;
26 use alg_tools::nalgebra_support::ToNalgebraRealField; 27 use alg_tools::nalgebra_support::ToNalgebraRealField;
27 use alg_tools::norms::L2; 28 use alg_tools::norms::{Dist, L2};
28 use anyhow::ensure; 29 use anyhow::ensure;
29 use measures::DeltaMeasure; 30 use measures::DeltaMeasure;
30 use numeric_literals::replace_float_literals; 31 use numeric_literals::replace_float_literals;
31 use serde::{Deserialize, Serialize}; 32 use serde::{Deserialize, Serialize};
32 33
62 guess: BoundedCurvatureGuess::BetterThanZero, 63 guess: BoundedCurvatureGuess::BetterThanZero,
63 } 64 }
64 } 65 }
65 } 66 }
66 67
67 type MeasureZ<F, Z, const N: usize> = Pair<RNDM<N, F>, Z>; 68 type MeasureZ<F, Z, U> = Pair<DiscreteMeasure<U, F>, Z>;
68 69
69 /// Iteratively solve the pointsource localisation with an additional variable 70 /// Iteratively solve the pointsource localisation with an additional variable
70 /// using sliding primal-dual proximal splitting 71 /// using sliding primal-dual proximal splitting
71 /// 72 ///
72 /// The parametrisation is as for [`crate::forward_pdps::pointsource_forward_pdps_pair`], 73 /// The parametrisation is as for [`crate::forward_pdps::pointsource_forward_pdps_pair`],
83 R, 84 R,
84 Y, 85 Y,
85 Plot, 86 Plot,
86 /*KOpM, */ KOpZ, 87 /*KOpM, */ KOpZ,
87 H, 88 H,
88 const N: usize, 89 U,
89 >( 90 >(
90 f: &Dat, 91 f: &Dat,
91 reg: &Reg, 92 reg: &Reg,
92 prox_penalty: &P, 93 prox_penalty: &P,
93 config: &SlidingPDPSConfig<F>, 94 config: &SlidingPDPSConfig<F>,
94 iterator: I, 95 iterator: I,
95 mut plotter: Plot, 96 mut plotter: Plot,
96 (μ0, mut z, mut y): (Option<RNDM<N, F>>, Z, Y), 97 (μ0, mut z, mut y): (Option<DiscreteMeasure<U, F>>, Z, Y),
97 //opKμ : KOpM, 98 //opKμ : KOpM,
98 opKz: &KOpZ, 99 opKz: &KOpZ,
99 fnR: &R, 100 fnR: &R,
100 fnH: &H, 101 fnH: &H,
101 domain: &mut impl AdmissibleDomain<Loc<N, F>>, 102 domain: &mut impl AdmissibleDomain<U>,
102 ) -> DynResult<MeasureZ<F, Z, N>> 103 ) -> DynResult<MeasureZ<F, Z, U>>
103 where 104 where
104 F: Float + ToNalgebraRealField, 105 F: Float + ToNalgebraRealField,
106 U: Space + Clone + Dist<L2, F>,
107 for<'a> &'a U: Instance<U>,
105 I: AlgIteratorFactory<IterInfo<F>>, 108 I: AlgIteratorFactory<IterInfo<F>>,
106 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>> 109 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>>
107 + BoundedCurvature<F>, 110 + BoundedCurvature<F>,
108 S: DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>, 111 S: DifferentiableMapping<U, Codomain = F> + ClosedMul<F> + MinMaxMapping<U, F>,
109 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, 112 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>,
110 //Pair<S, Z>: ClosedMul<F>, 113 //Pair<S, Z>: ClosedMul<F>,
111 RNDM<N, F>: SpikeMerging<F>, 114 DiscreteMeasure<U, F>: SpikeMerging<F>,
112 Reg: SlidingRegTerm<Loc<N, F>, F>, 115 Reg: SlidingRegTerm<U, F>,
113 P: TransportProxPenalty<Loc<N, F>, S, Reg, F>, 116 P: TransportProxPenalty<U, S, Reg, F>,
114 // KOpM : Linear<RNDM<N, F>, Codomain=Y> 117 // KOpM : Linear<DiscreteMeasure<U, F>, Codomain=Y>
115 // + GEMV<F, RNDM<N, F>> 118 // + GEMV<F, DiscreteMeasure<U, F>>
116 // + Preadjointable< 119 // + Preadjointable<
117 // RNDM<N, F>, Y, 120 // DiscreteMeasure<U, F>, Y,
118 // PreadjointCodomain = S, 121 // PreadjointCodomain = S,
119 // > 122 // >
120 // + TransportLipschitz<L2Squared, FloatType=F> 123 // + TransportLipschitz<L2Squared, FloatType=F>
121 // + AdjointProductBoundedBy<RNDM<N, F>, 𝒟, FloatType=F>, 124 // + AdjointProductBoundedBy<DiscreteMeasure<U, F>, 𝒟, FloatType=F>,
122 // for<'b> KOpM::Preadjoint<'b> : GEMV<F, Y>, 125 // for<'b> KOpM::Preadjoint<'b> : GEMV<F, Y>,
123 // Since Z is Hilbert, we may just as well use adjoints for K_z. 126 // Since Z is Hilbert, we may just as well use adjoints for K_z.
124 KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y> 127 KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y>
125 + GEMV<F, Z> 128 + GEMV<F, Z>
126 + SimplyAdjointable<Z, Y, AdjointCodomain = Z>, 129 + SimplyAdjointable<Z, Y, AdjointCodomain = Z>,
130 Z: ClosedEuclidean<F> + AXPY, 133 Z: ClosedEuclidean<F> + AXPY,
131 for<'b> &'b Z: Instance<Z>, 134 for<'b> &'b Z: Instance<Z>,
132 R: Prox<Z, Codomain = F>, 135 R: Prox<Z, Codomain = F>,
133 H: Conjugable<Y, F, Codomain = F>, 136 H: Conjugable<Y, F, Codomain = F>,
134 for<'b> H::Conjugate<'b>: Prox<Y>, 137 for<'b> H::Conjugate<'b>: Prox<Y>,
135 Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>, 138 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>,
136 { 139 {
137 // Check parameters 140 // Check parameters
138 /*ensure!( 141 /*ensure!(
139 config.τ0 > 0.0 142 config.τ0 > 0.0
140 && config.τ0 < 1.0 143 && config.τ0 < 1.0
204 let mut ε = tolerance.initial(); 207 let mut ε = tolerance.initial();
205 208
206 let starH = fnH.conjugate(); 209 let starH = fnH.conjugate();
207 210
208 // Statistics 211 // Statistics
209 let full_stats = |μ: &RNDM<N, F>, z: &Z, ε, stats| IterInfo { 212 let full_stats = |μ: &DiscreteMeasure<U, F>, z: &Z, ε, stats| IterInfo {
210 value: f.apply(Pair(μ, z)) 213 value: f.apply(Pair(μ, z))
211 + fnR.apply(z) 214 + fnR.apply(z)
212 + reg.apply(μ) 215 + reg.apply(μ)
213 + fnH.apply(/* opKμ.apply(μ) + */ opKz.apply(z)), 216 + fnH.apply(/* opKμ.apply(μ) + */ opKz.apply(z)),
214 n_spikes: μ.len(), 217 n_spikes: μ.len(),
315 &μ̆, 318 &μ̆,
316 τ, 319 τ,
317 ε, 320 ε,
318 ins, 321 ins,
319 &reg, 322 &reg,
320 Some(|μ̃: &RNDM<N, F>| f.apply(Pair(μ̃, &z)) + reg.apply(μ̃)), 323 Some(|μ̃: &DiscreteMeasure<U, F>| f.apply(Pair(μ̃, &z)) + reg.apply(μ̃)),
321 ); 324 );
322 γ.prune_compat(&mut μ, &mut stats); 325 γ.prune_compat(&mut μ, &mut stats);
323 326
324 if config.insertion.random_insertions { 327 if config.insertion.random_insertions {
325 if let Some(x) = domain.random_point() { 328 if let Some(x) = domain.random_point() {
373 376
374 // Update main tolerance for next iteration 377 // Update main tolerance for next iteration
375 ε = tolerance.update(ε, iter); 378 ε = tolerance.update(ε, iter);
376 } 379 }
377 380
378 let fit = |μ̃: &RNDM<N, F>| { 381 let fit = |μ̃: &DiscreteMeasure<U, F>| {
379 f.apply(Pair(μ̃, &z)) /*+ fnR.apply(z) + reg.apply(μ)*/ 382 f.apply(Pair(μ̃, &z)) /*+ fnR.apply(z) + reg.apply(μ)*/
380 + fnH.apply(/* opKμ.apply(&μ̃) + */ opKz.apply(&z)) 383 + fnH.apply(/* opKμ.apply(&μ̃) + */ opKz.apply(&z))
381 + reg.apply(μ̃) 384 + reg.apply(μ̃)
382 }; 385 };
383 386
390 /// using sliding forward-backward splitting. 393 /// using sliding forward-backward splitting.
391 /// 394 ///
392 /// The implementation uses [`pointsource_sliding_pdps_pair`] with appropriate dummy 395 /// The implementation uses [`pointsource_sliding_pdps_pair`] with appropriate dummy
393 /// variables, operators, and functions. 396 /// variables, operators, and functions.
394 #[replace_float_literals(F::cast_from(literal))] 397 #[replace_float_literals(F::cast_from(literal))]
395 pub fn pointsource_sliding_fb_pair_dom<F, I, S, Dat, Reg, P, Z, R, Plot, const N: usize>( 398 pub fn pointsource_sliding_fb_pair_dom<F, I, S, Dat, Reg, P, Z, R, Plot, U>(
396 f: &Dat, 399 f: &Dat,
397 reg: &Reg, 400 reg: &Reg,
398 prox_penalty: &P, 401 prox_penalty: &P,
399 config: &SlidingFBConfig<F>, 402 config: &SlidingFBConfig<F>,
400 iterator: I, 403 iterator: I,
401 plotter: Plot, 404 plotter: Plot,
402 (μ0, z): (Option<RNDM<N, F>>, Z), 405 (μ0, z): (Option<DiscreteMeasure<U, F>>, Z),
403 //opKμ : KOpM, 406 //opKμ : KOpM,
404 fnR: &R, 407 fnR: &R,
405 domain: &mut impl AdmissibleDomain<Loc<N, F>>, 408 domain: &mut impl AdmissibleDomain<U>,
406 ) -> DynResult<MeasureZ<F, Z, N>> 409 ) -> DynResult<MeasureZ<F, Z, U>>
407 where 410 where
408 F: Float + ToNalgebraRealField, 411 F: Float + ToNalgebraRealField,
412 U: Space + Clone + Dist<L2, F>,
413 for<'a> &'a U: Instance<U>,
409 I: AlgIteratorFactory<IterInfo<F>>, 414 I: AlgIteratorFactory<IterInfo<F>>,
410 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>> 415 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>>
411 + BoundedCurvature<F>, 416 + BoundedCurvature<F>,
412 S: DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>, 417 S: DifferentiableMapping<U, Codomain = F> + ClosedMul<F> + MinMaxMapping<U, F>,
413 RNDM<N, F>: SpikeMerging<F>, 418 DiscreteMeasure<U, F>: SpikeMerging<F>,
414 Reg: SlidingRegTerm<Loc<N, F>, F>, 419 Reg: SlidingRegTerm<U, F>,
415 P: TransportProxPenalty<Loc<N, F>, S, Reg, F>, 420 P: TransportProxPenalty<U, S, Reg, F>,
416 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, 421 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>,
417 Z: ClosedEuclidean<F> + AXPY + Clone, 422 Z: ClosedEuclidean<F> + AXPY + Clone,
418 for<'b> &'b Z: Instance<Z>, 423 for<'b> &'b Z: Instance<Z>,
419 R: Prox<Z, Codomain = F>, 424 R: Prox<Z, Codomain = F>,
420 Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>, 425 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>,
421 // We should not need to explicitly require this: 426 // We should not need to explicitly require this:
422 for<'b> &'b Loc<0, F>: Instance<Loc<0, F>>, 427 for<'b> &'b Loc<0, F>: Instance<Loc<0, F>>,
423 // Loc<0, F>: StaticEuclidean<Field = F, PrincipalE = Loc<0, F>> 428 // Loc<0, F>: StaticEuclidean<Field = F, PrincipalE = Loc<0, F>>
424 // + Instance<Loc<0, F>> 429 // + Instance<Loc<0, F>>
425 // + VectorSpace<Field = F>, 430 // + VectorSpace<Field = F>,
461 R, 466 R,
462 Y, 467 Y,
463 Plot, 468 Plot,
464 /*KOpM, */ KOpZ, 469 /*KOpM, */ KOpZ,
465 H, 470 H,
466 const N: usize, 471 U,
467 >( 472 >(
468 f: &Dat, 473 f: &Dat,
469 reg: &Reg, 474 reg: &Reg,
470 prox_penalty: &P, 475 prox_penalty: &P,
471 config: &SlidingPDPSConfig<F>, 476 config: &SlidingPDPSConfig<F>,
472 iterator: I, 477 iterator: I,
473 plotter: Plot, 478 plotter: Plot,
474 init: (Option<RNDM<N, F>>, Z, Y), 479 init: (Option<DiscreteMeasure<U, F>>, Z, Y),
475 //opKμ : KOpM, 480 //opKμ : KOpM,
476 opKz: &KOpZ, 481 opKz: &KOpZ,
477 fnR: &R, 482 fnR: &R,
478 fnH: &H, 483 fnH: &H,
479 ) -> DynResult<MeasureZ<F, Z, N>> 484 ) -> DynResult<MeasureZ<F, Z, U>>
480 where 485 where
481 F: Float + ToNalgebraRealField, 486 F: Float + ToNalgebraRealField,
487 U: Space + Clone + Dist<L2, F>,
488 for<'a> &'a U: Instance<U>,
482 I: AlgIteratorFactory<IterInfo<F>>, 489 I: AlgIteratorFactory<IterInfo<F>>,
483 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>> 490 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>>
484 + BoundedCurvature<F>, 491 + BoundedCurvature<F>,
485 S: DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>, 492 S: DifferentiableMapping<U, Codomain = F> + ClosedMul<F> + MinMaxMapping<U, F>,
486 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, 493 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>,
487 //Pair<S, Z>: ClosedMul<F>, 494 //Pair<S, Z>: ClosedMul<F>,
488 RNDM<N, F>: SpikeMerging<F>, 495 DiscreteMeasure<U, F>: SpikeMerging<F>,
489 Reg: SlidingRegTerm<Loc<N, F>, F>, 496 Reg: SlidingRegTerm<U, F>,
490 P: TransportProxPenalty<Loc<N, F>, S, Reg, F>, 497 P: TransportProxPenalty<U, S, Reg, F>,
491 // KOpM : Linear<RNDM<N, F>, Codomain=Y> 498 // KOpM : Linear<DiscreteMeasure<U, F>, Codomain=Y>
492 // + GEMV<F, RNDM<N, F>> 499 // + GEMV<F, DiscreteMeasure<U, F>>
493 // + Preadjointable< 500 // + Preadjointable<
494 // RNDM<N, F>, Y, 501 // DiscreteMeasure<U, F>, Y,
495 // PreadjointCodomain = S, 502 // PreadjointCodomain = S,
496 // > 503 // >
497 // + TransportLipschitz<L2Squared, FloatType=F> 504 // + TransportLipschitz<L2Squared, FloatType=F>
498 // + AdjointProductBoundedBy<RNDM<N, F>, 𝒟, FloatType=F>, 505 // + AdjointProductBoundedBy<DiscreteMeasure<U, F>, 𝒟, FloatType=F>,
499 // for<'b> KOpM::Preadjoint<'b> : GEMV<F, Y>, 506 // for<'b> KOpM::Preadjoint<'b> : GEMV<F, Y>,
500 // Since Z is Hilbert, we may just as well use adjoints for K_z. 507 // Since Z is Hilbert, we may just as well use adjoints for K_z.
501 KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y> 508 KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y>
502 + GEMV<F, Z> 509 + GEMV<F, Z>
503 + SimplyAdjointable<Z, Y, AdjointCodomain = Z>, 510 + SimplyAdjointable<Z, Y, AdjointCodomain = Z>,
507 Z: ClosedEuclidean<F> + AXPY, 514 Z: ClosedEuclidean<F> + AXPY,
508 for<'b> &'b Z: Instance<Z>, 515 for<'b> &'b Z: Instance<Z>,
509 R: Prox<Z, Codomain = F>, 516 R: Prox<Z, Codomain = F>,
510 H: Conjugable<Y, F, Codomain = F>, 517 H: Conjugable<Y, F, Codomain = F>,
511 for<'b> H::Conjugate<'b>: Prox<Y>, 518 for<'b> H::Conjugate<'b>: Prox<Y>,
512 Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>, 519 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>,
513 { 520 {
514 pointsource_sliding_pdps_pair_dom( 521 pointsource_sliding_pdps_pair_dom(
515 f, 522 f,
516 reg, 523 reg,
517 prox_penalty, 524 prox_penalty,
527 } 534 }
528 535
529 #[deprecated] 536 #[deprecated]
530 /// Version of [`pointsource_sliding_fb_pair_dom`] without domain specification 537 /// Version of [`pointsource_sliding_fb_pair_dom`] without domain specification
531 #[replace_float_literals(F::cast_from(literal))] 538 #[replace_float_literals(F::cast_from(literal))]
532 pub fn pointsource_sliding_fb_pair<F, I, S, Dat, Reg, P, Z, R, Plot, const N: usize>( 539 pub fn pointsource_sliding_fb_pair<F, I, S, Dat, Reg, P, Z, R, Plot, U>(
533 f: &Dat, 540 f: &Dat,
534 reg: &Reg, 541 reg: &Reg,
535 prox_penalty: &P, 542 prox_penalty: &P,
536 config: &SlidingFBConfig<F>, 543 config: &SlidingFBConfig<F>,
537 iterator: I, 544 iterator: I,
538 plotter: Plot, 545 plotter: Plot,
539 (μ0, z): (Option<RNDM<N, F>>, Z), 546 (μ0, z): (Option<DiscreteMeasure<U, F>>, Z),
540 //opKμ : KOpM, 547 //opKμ : KOpM,
541 fnR: &R, 548 fnR: &R,
542 ) -> DynResult<MeasureZ<F, Z, N>> 549 ) -> DynResult<MeasureZ<F, Z, U>>
543 where 550 where
544 F: Float + ToNalgebraRealField, 551 F: Float + ToNalgebraRealField,
552 U: Space + Clone + Dist<L2, F>,
553 for<'a> &'a U: Instance<U>,
545 I: AlgIteratorFactory<IterInfo<F>>, 554 I: AlgIteratorFactory<IterInfo<F>>,
546 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>> 555 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>>
547 + BoundedCurvature<F>, 556 + BoundedCurvature<F>,
548 S: DifferentiableRealMapping<N, F> + ClosedMul<F> + MinMaxMapping<Loc<N, F>, F>, 557 S: DifferentiableMapping<U, Codomain = F> + ClosedMul<F> + MinMaxMapping<U, F>,
549 RNDM<N, F>: SpikeMerging<F>, 558 DiscreteMeasure<U, F>: SpikeMerging<F>,
550 Reg: SlidingRegTerm<Loc<N, F>, F>, 559 Reg: SlidingRegTerm<U, F>,
551 P: TransportProxPenalty<Loc<N, F>, S, Reg, F>, 560 P: TransportProxPenalty<U, S, Reg, F>,
552 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, 561 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>,
553 Z: ClosedEuclidean<F> + AXPY + Clone, 562 Z: ClosedEuclidean<F> + AXPY + Clone,
554 for<'b> &'b Z: Instance<Z>, 563 for<'b> &'b Z: Instance<Z>,
555 R: Prox<Z, Codomain = F>, 564 R: Prox<Z, Codomain = F>,
556 Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>, 565 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>,
557 // We should not need to explicitly require this: 566 // We should not need to explicitly require this:
558 for<'b> &'b Loc<0, F>: Instance<Loc<0, F>>, 567 for<'b> &'b Loc<0, F>: Instance<Loc<0, F>>,
559 // Loc<0, F>: StaticEuclidean<Field = F, PrincipalE = Loc<0, F>> 568 // Loc<0, F>: StaticEuclidean<Field = F, PrincipalE = Loc<0, F>>
560 // + Instance<Loc<0, F>> 569 // + Instance<Loc<0, F>>
561 // + VectorSpace<Field = F>, 570 // + VectorSpace<Field = F>,

mercurial