| 23 use alg_tools::linops::{ |
23 use alg_tools::linops::{ |
| 24 BoundedLinear, IdOp, SimplyAdjointable, StaticEuclideanOriginGenerator, ZeroOp, AXPY, GEMV, |
24 BoundedLinear, IdOp, SimplyAdjointable, StaticEuclideanOriginGenerator, ZeroOp, AXPY, GEMV, |
| 25 }; |
25 }; |
| 26 use alg_tools::mapping::DifferentiableMapping; |
26 use alg_tools::mapping::DifferentiableMapping; |
| 27 use alg_tools::nalgebra_support::ToNalgebraRealField; |
27 use alg_tools::nalgebra_support::ToNalgebraRealField; |
| 28 use alg_tools::norms::{Dist, L2}; |
28 use alg_tools::norms::{Dist, Norm, L2}; |
| 29 use anyhow::ensure; |
29 use anyhow::ensure; |
| 30 use measures::DeltaMeasure; |
30 use measures::{DeltaMeasure, Radon}; |
| 31 use numeric_literals::replace_float_literals; |
31 use numeric_literals::replace_float_literals; |
| 32 use serde::{Deserialize, Serialize}; |
32 use serde::{Deserialize, Serialize}; |
| 33 |
33 |
| 34 /// Settings for [`pointsource_sliding_pdps_pair`]. |
34 /// Settings for [`pointsource_sliding_pdps_pair`]. |
| 35 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] |
35 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] |
| 106 U: Space + Clone + Dist<L2, F>, |
106 U: Space + Clone + Dist<L2, F>, |
| 107 for<'a> &'a U: Instance<U>, |
107 for<'a> &'a U: Instance<U>, |
| 108 I: AlgIteratorFactory<IterInfo<F>>, |
108 I: AlgIteratorFactory<IterInfo<F>>, |
| 109 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>> |
109 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>> |
| 110 + BoundedCurvature<F>, |
110 + BoundedCurvature<F>, |
| 111 S: ClosedMul<F>, |
111 S: ClosedMul<F> + MinMaxMapping<U, F>, |
| 112 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
112 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
| 113 DiscreteMeasure<U, F>: SpikeMerging<F>, |
113 DiscreteMeasure<U, F>: SpikeMerging<F> + Norm<Radon, F>, |
| 114 Reg: SlidingRegTerm<U, F>, |
114 Reg: SlidingRegTerm<U, F>, |
| 115 P: TransportProxPenalty<U, S, Reg, F>, |
115 P: TransportProxPenalty<U, S, Reg, F>, |
| 116 // KOpM : Linear<DiscreteMeasure<U, F>, Codomain=Y> |
116 // KOpM : Linear<DiscreteMeasure<U, F>, Codomain=Y> |
| 117 // + GEMV<F, DiscreteMeasure<U, F>> |
117 // + GEMV<F, DiscreteMeasure<U, F>> |
| 118 // + Preadjointable< |
118 // + Preadjointable< |
| 157 let nKz = opKz.opnorm_bound(L2, L2)?; |
157 let nKz = opKz.opnorm_bound(L2, L2)?; |
| 158 let is_fb = nKz == 0.0; |
158 let is_fb = nKz == 0.0; |
| 159 let idOpZ = IdOp::new(); |
159 let idOpZ = IdOp::new(); |
| 160 let opKz_adj = opKz.adjoint(); |
160 let opKz_adj = opKz.adjoint(); |
| 161 let (l, l_z) = Pair(prox_penalty, &idOpZ).step_length_bound_pair(&f)?; |
161 let (l, l_z) = Pair(prox_penalty, &idOpZ).step_length_bound_pair(&f)?; |
| |
162 let l_z_prime = if l_z == 0.0 { |
| |
163 1.0 |
| |
164 } else { |
| |
165 ensure!(config.σp0 < 1.0); |
| |
166 l_z |
| |
167 }; |
| |
168 let l_prime = if l == 0.0 { |
| |
169 1.0 |
| |
170 } else { |
| |
171 ensure!(config.τ0 < 1.0); |
| |
172 l |
| |
173 }; |
| 162 |
174 |
| 163 let (τ, σ_p, σ_d, κ) = if is_fb { |
175 let (τ, σ_p, σ_d, κ) = if is_fb { |
| 164 (config.τ0 / l, config.σp0 / l_z, 0.0, 0.0) |
176 (config.τ0 / l_prime, config.σp0 / l_z_prime, 0.0, 0.0) |
| 165 } else { |
177 } else { |
| 166 ensure!( |
178 ensure!( |
| 167 //config.τ0 < 1.0 && |
179 //config.τ0 < 1.0 && |
| 168 config.σp0 < 1.0 && config.σd0 > 0.0 && config.σp0 * config.σd0 <= 1.0, |
180 config.σp0 < 1.0 && config.σd0 > 0.0 && config.σp0 * config.σd0 <= 1.0, |
| 169 "Invalid step length parameters" |
181 "Invalid step length parameters" |
| 176 // |
188 // |
| 177 // To do so, we first solve σ_p and σ_d from standard PDPS step length condition |
189 // To do so, we first solve σ_p and σ_d from standard PDPS step length condition |
| 178 // ^^^^^ < 1. then we solve τ from the rest. |
190 // ^^^^^ < 1. then we solve τ from the rest. |
| 179 // If opKZ is the zero operator, then we set σ_d = 0 for τ to be calculated correctly below. |
191 // If opKZ is the zero operator, then we set σ_d = 0 for τ to be calculated correctly below. |
| 180 let σ_d = config.σd0 / nKz; |
192 let σ_d = config.σd0 / nKz; |
| 181 let σ_p = config.σp0 / (l_z + config.σd0 * nKz); |
193 let σ_p = config.σp0 / (l_z_prime + config.σd0 * nKz); |
| 182 // Observe that = 1 - ^^^^^^^^^^^^^^^^^^^^^ = 1 - σ_{p,0} |
194 // Observe that = 1 - ^^^^^^^^^^^^^^^^^^^^^ = 1 - σ_{p,0} |
| 183 // We get the condition τσ_d M (1-σ_p L_z) < (1-σ_{p,0})*(1-τ L) |
195 // We get the condition τσ_d M (1-σ_p L_z) < (1-σ_{p,0})*(1-τ L) |
| 184 // ⟺ τ [ σ_d M (1-σ_p L_z) + (1-σ_{p,0}) L ] < (1-σ_{p,0}) |
196 // ⟺ τ [ σ_d M (1-σ_p L_z) + (1-σ_{p,0}) L ] < (1-σ_{p,0}) |
| 185 let φ = 1.0 - config.σp0; |
197 let φ = 1.0 - config.σp0; |
| 186 let a = 1.0 - σ_p * l_z; |
198 let a = 1.0 - σ_p * l_z_prime; |
| 187 let τ = config.τ0 * φ / (σ_d * bigM * a + φ * l); |
199 let τ = config.τ0 * φ / (σ_d * bigM * a + φ * l); |
| 188 let ψ = 1.0 - τ * l; |
200 let ψ = 1.0 - τ * l_prime; |
| 189 let β = σ_p * config.σd0 * nKz / a; // σ_p * σ_d * (nKz * nK_z) / a; |
201 let β = σ_p * config.σd0 * nKz / a; // σ_p * σ_d * (nKz * nK_z) / a; |
| 190 ensure!(β < 1.0); |
202 ensure!(β < 1.0); |
| 191 // Now we need κ‖K_μ(π_♯^1 - π_♯^0)γ‖^2 ≤ (1/θ - τ[ℓ_F + ℓ]) ∫ c_2 dγ for κ defined as: |
203 // Now we need κ‖K_μ(π_♯^1 - π_♯^0)γ‖^2 ≤ (1/θ - τ[ℓ_F + ℓ]) ∫ c_2 dγ for κ defined as: |
| 192 // The factor two in the manuscript disappears due to the definition of 𝚹 being |
204 // The factor two in the manuscript disappears due to the definition of 𝚹 being |
| 193 // for ‖x-y‖₂² instead of c_2(x, y)=‖x-y‖₂²/2. |
205 // for ‖x-y‖₂² instead of c_2(x, y)=‖x-y‖₂²/2. |
| 212 let mut ε = tolerance.initial(); |
224 let mut ε = tolerance.initial(); |
| 213 |
225 |
| 214 let starH = fnH.conjugate(); |
226 let starH = fnH.conjugate(); |
| 215 |
227 |
| 216 // Statistics |
228 // Statistics |
| 217 let full_stats = |μ: &DiscreteMeasure<U, F>, z: &Z, ε, stats| IterInfo { |
229 let full_stats = |μ: &DiscreteMeasure<U, F>, v: &mut S, z: &Z, dz: Z, ε, stats| { |
| 218 value: f.apply(Pair(μ, z)) |
230 let discrepancy = reg.discrepancy(v, τ, ε, μ, &config.insertion); |
| 219 + fnR.apply(z) |
231 let aux_discrepancy = is_fb.then(|| z.dist2(fnR.prox(σ_p, dz * (-σ_p) + z))); |
| 220 + reg.apply(μ) |
232 let joint_discrepancy = aux_discrepancy |
| 221 + fnH.apply(/* opKμ.apply(μ) + */ opKz.apply(z)), |
233 .map(|d| (discrepancy.powi(2) + τ * (2.0 / σ_p - l_z) * d.powi(2)).sqrt()); |
| 222 n_spikes: μ.len(), |
234 IterInfo { |
| 223 ε, |
235 value: f.apply(Pair(μ, z)) |
| 224 // postprocessing: config.insertion.postprocessing.then(|| μ.clone()), |
236 + fnR.apply(z) |
| 225 ..stats |
237 + reg.apply(μ) |
| |
238 + fnH.apply(/* opKμ.apply(μ) + */ opKz.apply(z)), |
| |
239 n_spikes: μ.len(), |
| |
240 discrepancy: Some(discrepancy), |
| |
241 μ_norm: μ.norm(Radon), |
| |
242 aux_discrepancy, |
| |
243 joint_discrepancy, |
| |
244 ε, |
| |
245 // postprocessing: config.insertion.postprocessing.then(|| μ.clone()), |
| |
246 ..stats |
| |
247 } |
| 226 }; |
248 }; |
| 227 let mut stats = IterInfo::new(); |
249 let mut stats = IterInfo::new(); |
| 228 |
250 |
| |
251 let Pair(mut v, mut dz) = f.differential(Pair(&μ, &z)); |
| |
252 |
| 229 // Run the algorithm |
253 // Run the algorithm |
| 230 for state in iterator.iter_init(|| full_stats(&μ, &z, ε, stats.clone())) { |
254 for state in iterator.iter_init(|| full_stats(&μ, &mut v, &z, dz, ε, stats.clone())) { |
| 231 let Pair(mut v, _) = f.differential(Pair(&μ, &z)); |
|
| 232 |
|
| 233 //opKμ.preadjoint().apply_add(&mut v, y); |
255 //opKμ.preadjoint().apply_add(&mut v, y); |
| 234 // We want to proceed as in Example 4.12 but with v and v̆ as in §5. |
256 // We want to proceed as in Example 4.12 but with v and v̆ as in §5. |
| 235 // With A(ν, z) = A_μ ν + A_z z, following Example 5.1, we have |
257 // With A(ν, z) = A_μ ν + A_z z, following Example 5.1, we have |
| 236 // P_ℳ[F'(ν, z) + Ξ(ν, z, y)]= A_ν^*[A_ν ν + A_z z] + K_μ ν = A_ν^*A(ν, z) + K_μ ν, |
258 // P_ℳ[F'(ν, z) + Ξ(ν, z, y)]= A_ν^*[A_ν ν + A_z z] + K_μ ν = A_ν^*A(ν, z) + K_μ ν, |
| 237 // where A_ν^* becomes a multiplier. |
259 // where A_ν^* becomes a multiplier. |
| 371 |
393 |
| 372 // Give statistics if requested |
394 // Give statistics if requested |
| 373 let iter = state.iteration(); |
395 let iter = state.iteration(); |
| 374 stats.this_iters += 1; |
396 stats.this_iters += 1; |
| 375 |
397 |
| |
398 Pair(v, dz) = f.differential(Pair(&μ, &z)); |
| |
399 |
| 376 state.if_verbose(|| { |
400 state.if_verbose(|| { |
| 377 plotter.plot_spikes(iter, None, Some(&τv̆), &μ); |
401 plotter.plot_spikes(iter, None, Some(&τv̆), &μ); |
| 378 full_stats(&μ, &z, ε, std::mem::replace(&mut stats, IterInfo::new())) |
402 full_stats( |
| |
403 &μ, |
| |
404 &mut v, |
| |
405 &z, |
| |
406 dz, |
| |
407 ε, |
| |
408 std::mem::replace(&mut stats, IterInfo::new()), |
| |
409 ) |
| 379 }); |
410 }); |
| 380 |
411 |
| 381 // Update main tolerance for next iteration |
412 // Update main tolerance for next iteration |
| 382 ε = tolerance.update(ε, iter); |
413 ε = tolerance.update(ε, iter); |
| 383 } |
414 } |
| 416 U: Space + Clone + Dist<L2, F>, |
447 U: Space + Clone + Dist<L2, F>, |
| 417 for<'a> &'a U: Instance<U>, |
448 for<'a> &'a U: Instance<U>, |
| 418 I: AlgIteratorFactory<IterInfo<F>>, |
449 I: AlgIteratorFactory<IterInfo<F>>, |
| 419 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>> |
450 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>> |
| 420 + BoundedCurvature<F>, |
451 + BoundedCurvature<F>, |
| 421 S: ClosedMul<F>, |
452 S: ClosedMul<F> + MinMaxMapping<U, F>, |
| 422 DiscreteMeasure<U, F>: SpikeMerging<F>, |
453 DiscreteMeasure<U, F>: SpikeMerging<F> + Norm<Radon, F>, |
| 423 Reg: SlidingRegTerm<U, F>, |
454 Reg: SlidingRegTerm<U, F>, |
| 424 P: TransportProxPenalty<U, S, Reg, F>, |
455 P: TransportProxPenalty<U, S, Reg, F>, |
| 425 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
456 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
| 426 Z: ClosedEuclidean<F> + AXPY + Clone, |
457 Z: ClosedEuclidean<F> + AXPY + Clone, |
| 427 for<'b> &'b Z: Instance<Z>, |
458 for<'b> &'b Z: Instance<Z>, |
| 486 U: Space + Clone + Dist<L2, F>, |
517 U: Space + Clone + Dist<L2, F>, |
| 487 for<'a> &'a U: Instance<U>, |
518 for<'a> &'a U: Instance<U>, |
| 488 I: AlgIteratorFactory<IterInfo<F>>, |
519 I: AlgIteratorFactory<IterInfo<F>>, |
| 489 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>> |
520 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>> |
| 490 + BoundedCurvature<F>, |
521 + BoundedCurvature<F>, |
| 491 S: ClosedMul<F>, |
522 S: ClosedMul<F> + MinMaxMapping<U, F>, |
| 492 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
523 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
| 493 DiscreteMeasure<U, F>: SpikeMerging<F>, |
524 DiscreteMeasure<U, F>: SpikeMerging<F> + Norm<Radon, F>, |
| 494 Reg: SlidingRegTerm<U, F>, |
525 Reg: SlidingRegTerm<U, F>, |
| 495 P: TransportProxPenalty<U, S, Reg, F>, |
526 P: TransportProxPenalty<U, S, Reg, F>, |
| 496 KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y> |
527 KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y> |
| 497 + GEMV<F, Z> |
528 + GEMV<F, Z> |
| 498 + SimplyAdjointable<Z, Y, AdjointCodomain = Z>, |
529 + SimplyAdjointable<Z, Y, AdjointCodomain = Z>, |
| 541 for<'a> &'a U: Instance<U>, |
572 for<'a> &'a U: Instance<U>, |
| 542 I: AlgIteratorFactory<IterInfo<F>>, |
573 I: AlgIteratorFactory<IterInfo<F>>, |
| 543 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>> |
574 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>> |
| 544 + BoundedCurvature<F>, |
575 + BoundedCurvature<F>, |
| 545 S: DifferentiableMapping<U, Codomain = F> + ClosedMul<F> + MinMaxMapping<U, F>, |
576 S: DifferentiableMapping<U, Codomain = F> + ClosedMul<F> + MinMaxMapping<U, F>, |
| 546 DiscreteMeasure<U, F>: SpikeMerging<F>, |
577 DiscreteMeasure<U, F>: SpikeMerging<F> + Norm<Radon, F>, |
| 547 Reg: SlidingRegTerm<U, F>, |
578 Reg: SlidingRegTerm<U, F>, |
| 548 P: TransportProxPenalty<U, S, Reg, F>, |
579 P: TransportProxPenalty<U, S, Reg, F>, |
| 549 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
580 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
| 550 Z: ClosedEuclidean<F> + AXPY + Clone, |
581 Z: ClosedEuclidean<F> + AXPY + Clone, |
| 551 for<'b> &'b Z: Instance<Z>, |
582 for<'b> &'b Z: Instance<Z>, |