| 9 use crate::measures::DiscreteMeasure; |
9 use crate::measures::DiscreteMeasure; |
| 10 use crate::plot::Plotter; |
10 use crate::plot::Plotter; |
| 11 use crate::prox_penalty::{ProxPenalty, StepLengthBoundPair}; |
11 use crate::prox_penalty::{ProxPenalty, StepLengthBoundPair}; |
| 12 use crate::regularisation::RegTerm; |
12 use crate::regularisation::RegTerm; |
| 13 use crate::types::*; |
13 use crate::types::*; |
| |
14 use alg_tools::bounds::MinMaxMapping; |
| 14 use alg_tools::convex::{Conjugable, Prox, Zero}; |
15 use alg_tools::convex::{Conjugable, Prox, Zero}; |
| 15 use alg_tools::direct_product::Pair; |
16 use alg_tools::direct_product::Pair; |
| 16 use alg_tools::error::DynResult; |
17 use alg_tools::error::DynResult; |
| 17 use alg_tools::euclidean::ClosedEuclidean; |
18 use alg_tools::euclidean::ClosedEuclidean; |
| 18 use alg_tools::iterate::AlgIteratorFactory; |
19 use alg_tools::iterate::AlgIteratorFactory; |
| 20 BoundedLinear, IdOp, SimplyAdjointable, Space, StaticEuclideanOriginGenerator, ZeroOp, AXPY, |
21 BoundedLinear, IdOp, SimplyAdjointable, Space, StaticEuclideanOriginGenerator, ZeroOp, AXPY, |
| 21 GEMV, |
22 GEMV, |
| 22 }; |
23 }; |
| 23 use alg_tools::mapping::{DifferentiableMapping, Instance}; |
24 use alg_tools::mapping::{DifferentiableMapping, Instance}; |
| 24 use alg_tools::nalgebra_support::ToNalgebraRealField; |
25 use alg_tools::nalgebra_support::ToNalgebraRealField; |
| 25 use alg_tools::norms::L2; |
26 use alg_tools::norms::{Norm, L2}; |
| 26 use anyhow::ensure; |
27 use anyhow::ensure; |
| 27 use measures::DeltaMeasure; |
28 use measures::{DeltaMeasure, Radon}; |
| 28 use numeric_literals::replace_float_literals; |
29 use numeric_literals::replace_float_literals; |
| 29 use serde::{Deserialize, Serialize}; |
30 use serde::{Deserialize, Serialize}; |
| |
31 //use std::ops::Mul; |
| 30 |
32 |
| 31 /// Settings for [`pointsource_forward_pdps_pair`]. |
33 /// Settings for [`pointsource_forward_pdps_pair`]. |
| 32 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] |
34 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] |
| 33 #[serde(default)] |
35 #[serde(default)] |
| 34 pub struct ForwardPDPSConfig<F: Float> { |
36 pub struct ForwardPDPSConfig<F: Float> { |
| 121 where |
123 where |
| 122 F: Float + ToNalgebraRealField, |
124 F: Float + ToNalgebraRealField, |
| 123 U: Space + Clone, |
125 U: Space + Clone, |
| 124 I: AlgIteratorFactory<IterInfo<F>>, |
126 I: AlgIteratorFactory<IterInfo<F>>, |
| 125 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
127 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
| 126 S: ClosedMul<F>, |
128 S: ClosedMul<F> + MinMaxMapping<U, F>, |
| 127 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
129 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
| 128 DiscreteMeasure<U, F>: SpikeMerging<F>, |
130 DiscreteMeasure<U, F>: SpikeMerging<F> + Norm<Radon, F>, |
| 129 Reg: RegTerm<U, F>, |
131 Reg: RegTerm<U, F>, |
| 130 P: ProxPenalty<U, S, Reg, F>, |
132 P: ProxPenalty<U, S, Reg, F>, |
| 131 KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y> |
133 KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y> |
| 132 + GEMV<F, Z> |
134 + GEMV<F, Z> |
| 133 + SimplyAdjointable<Z, Y, AdjointCodomain = Z>, |
135 + SimplyAdjointable<Z, Y, AdjointCodomain = Z>, |
| 134 KOpZ::SimpleAdjoint: GEMV<F, Y>, |
136 KOpZ::SimpleAdjoint: GEMV<F, Y>, |
| 135 Y: ClosedEuclidean<F>, |
137 Y: ClosedEuclidean<F>, |
| 136 for<'b> &'b Y: Instance<Y>, |
138 for<'b> &'b Y: Instance<Y>, |
| 137 Z: ClosedEuclidean<F> + AXPY, |
139 Z: ClosedEuclidean<F> + AXPY + Clone, |
| 138 for<'b> &'b Z: Instance<Z>, |
140 for<'b> &'b Z: Instance<Z>, // compiler overflow + Mul<F, Output = Z>, |
| 139 R: Prox<Z, Codomain = F>, |
141 R: Prox<Z, Codomain = F>, |
| 140 H: Conjugable<Y, F, Codomain = F>, |
142 H: Conjugable<Y, F, Codomain = F>, |
| 141 for<'b> H::Conjugate<'b>: Prox<Y>, |
143 for<'b> H::Conjugate<'b>: Prox<Y>, |
| 142 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>, |
144 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>, |
| 143 { |
145 { |
| 156 let nKz = opKz.opnorm_bound(L2, L2)?; |
158 let nKz = opKz.opnorm_bound(L2, L2)?; |
| 157 let is_fb = nKz == 0.0; |
159 let is_fb = nKz == 0.0; |
| 158 let idOpZ = IdOp::new(); |
160 let idOpZ = IdOp::new(); |
| 159 let opKz_adj = opKz.adjoint(); |
161 let opKz_adj = opKz.adjoint(); |
| 160 let (l, l_z) = Pair(prox_penalty, &idOpZ).step_length_bound_pair(&f)?; |
162 let (l, l_z) = Pair(prox_penalty, &idOpZ).step_length_bound_pair(&f)?; |
| |
163 let l_z_prime = if l_z == 0.0 { |
| |
164 1.0 |
| |
165 } else { |
| |
166 ensure!(config.σp0 < 1.0); |
| |
167 l_z |
| |
168 }; |
| |
169 let l_prime = if l == 0.0 { |
| |
170 1.0 |
| |
171 } else { |
| |
172 ensure!(config.τ0 < 1.0); |
| |
173 l |
| |
174 }; |
| 161 |
175 |
| 162 let (τ, σ_p, σ_d) = if is_fb { |
176 let (τ, σ_p, σ_d) = if is_fb { |
| 163 (config.τ0 / l, config.σp0 / l_z, 0.0) |
177 (config.τ0 / l_prime, config.σp0 / l_z_prime, 0.0) |
| 164 } else { |
178 } else { |
| 165 ensure!( |
179 ensure!( |
| 166 //config.τ0 < 1.0 && |
180 //config.τ0 < 1.0 && |
| 167 config.σp0 < 1.0 && config.σd0 > 0.0 && config.σp0 * config.σd0 <= 1.0, |
181 config.σp0 < 1.0 && config.σd0 > 0.0 && config.σp0 * config.σd0 <= 1.0, |
| 168 "Invalid step length parameters" |
182 "Invalid step length parameters" |
| 169 ); |
183 ); |
| 170 let σ_d = config.σd0 / nKz; |
184 let σ_d = config.σd0 / nKz; |
| 171 let σ_p = config.σp0 / (l_z + config.σd0 * nKz); |
185 let σ_p = config.σp0 / (l_z_prime + config.σd0 * nKz); |
| 172 let φ = 1.0 - config.σp0; |
186 let φ = 1.0 - config.σp0; |
| 173 let a = 1.0 - σ_p * l_z; |
187 let a = 1.0 - σ_p * l_z_prime; |
| 174 let τ = config.τ0 * φ / (σ_d * bigM * a + φ * l); |
188 let τ = config.τ0 * φ / (σ_d * bigM * a + φ * l_prime); |
| 175 (τ, σ_p, σ_d) |
189 (τ, σ_p, σ_d) |
| 176 }; |
190 }; |
| 177 |
191 |
| 178 // Acceleration is not currently supported |
192 // Acceleration is not currently supported |
| 179 // let γ = dataterm.factor_of_strong_convexity(); |
193 // let γ = dataterm.factor_of_strong_convexity(); |
| 185 let mut ε = tolerance.initial(); |
199 let mut ε = tolerance.initial(); |
| 186 |
200 |
| 187 let starH = fnH.conjugate(); |
201 let starH = fnH.conjugate(); |
| 188 |
202 |
| 189 // Statistics |
203 // Statistics |
| 190 let full_stats = |μ: &DiscreteMeasure<U, F>, z: &Z, ε, stats| IterInfo { |
204 let full_stats = |μ: &DiscreteMeasure<U, F>, v: &mut S, z: &Z, dz: &Z, ε, stats| { |
| 191 value: f.apply(Pair(μ, z)) |
205 let value = f.apply(Pair(μ, z)) |
| 192 + fnR.apply(z) |
206 + fnR.apply(z) |
| 193 + reg.apply(μ) |
207 + reg.apply(μ) |
| 194 + fnH.apply(/* opKμ.apply(μ) + */ opKz.apply(z)), |
208 + fnH.apply(/* opKμ.apply(μ) + */ opKz.apply(z)); |
| 195 n_spikes: μ.len(), |
209 let discrepancy = reg.discrepancy(v, τ, ε, μ, &config.insertion); |
| 196 ε, |
210 let aux_discrepancy = is_fb.then(|| z.dist2(fnR.prox(σ_p, Z::clone(dz) * (-σ_p) + z))); |
| 197 // postprocessing: config.insertion.postprocessing.then(|| μ.clone()), |
211 let joint_discrepancy = aux_discrepancy |
| 198 ..stats |
212 .map(|d| (discrepancy.powi(2) + τ * (2.0 / σ_p - l_z) * d.powi(2)).sqrt()); |
| |
213 IterInfo { |
| |
214 value, |
| |
215 n_spikes: μ.len(), |
| |
216 discrepancy: Some(discrepancy), |
| |
217 μ_norm: μ.norm(Radon), |
| |
218 // compiler overflow with the necesssary trait bounds: |
| |
219 //aux_discrepancy: is_fb.then(|| z.dist2(fnR.prox(σ_p, dz * (-σ_p) + z))), |
| |
220 aux_discrepancy, |
| |
221 joint_discrepancy, |
| |
222 ε, |
| |
223 // postprocessing: config.insertion.postprocessing.then(|| μ.clone()), |
| |
224 ..stats |
| |
225 } |
| 199 }; |
226 }; |
| 200 let mut stats = IterInfo::new(); |
227 let mut stats = IterInfo::new(); |
| 201 |
228 |
| 202 let zy_step = |mut z, mut y, mut z_tmp| { |
229 let zy_step = |mut z, mut y, mut dz| { |
| 203 // Do z variable primal update |
230 // Do z variable primal update |
| 204 opKz_adj.apply_add(&mut z_tmp, &y); |
231 opKz_adj.apply_add(&mut dz, &y); |
| 205 z_tmp.axpy(1.0, &z, -σ_p); |
232 dz.axpy(1.0, &z, -σ_p); |
| 206 let z_new = fnR.prox(σ_p, z_tmp); |
233 let z_new = fnR.prox(σ_p, dz); |
| 207 //let z_new = fnR.prox(σ_p, z_tmp * (-σ_p) + &z); |
234 //let z_new = fnR.prox(σ_p, dz * (-σ_p) + &z); |
| 208 // Do dual update |
235 // Do dual update |
| 209 z.axpy(1.0 + ω, &z_new, -ω); |
236 z.axpy(1.0 + ω, &z_new, -ω); |
| 210 //z = (z - &z_new) * (-ω) + &z_new; |
237 //z = (z - &z_new) * (-ω) + &z_new; |
| 211 opKz.gemv(&mut y, σ_d, z, 1.0); |
238 opKz.gemv(&mut y, σ_d, z, 1.0); |
| 212 let y = starH.prox(σ_d, y); |
239 let y = starH.prox(σ_d, y); |
| 213 (z_new, y) |
240 (z_new, y) |
| 214 }; |
241 }; |
| 215 |
242 |
| |
243 // Calculate differential of smooth part |
| |
244 let Pair(mut v, mut dz) = f.differential(Pair(&μ, &z)); |
| |
245 let mut τv = v * τ; |
| |
246 |
| 216 // Run the algorithm |
247 // Run the algorithm |
| 217 for state in iterator.iter_init(|| full_stats(&μ, &z, ε, stats.clone())) { |
248 for state in iterator.iter_init(|| full_stats(&μ, &mut τv, &z, &dz, ε, stats.clone())) { |
| 218 // Calculate initial transport |
249 // Calculate initial transport |
| 219 let Pair(v, z_tmp) = f.differential(Pair(&μ, &z)); |
|
| 220 let mut τv = v * τ; |
|
| 221 let μ_base = μ.clone(); |
250 let μ_base = μ.clone(); |
| 222 let μ_base_len = μ_base.len(); |
251 let μ_base_len = μ_base.len(); |
| 223 |
252 |
| 224 // Construct μ^{k+1} by solving finite-dimensional subproblems and insert new spikes. |
253 // Construct μ^{k+1} by solving finite-dimensional subproblems and insert new spikes. |
| 225 prox_penalty.insert_and_reweigh( |
254 prox_penalty.insert_and_reweigh( |
| 274 ®, |
303 ®, |
| 275 &state, |
304 &state, |
| 276 &mut stats, |
305 &mut stats, |
| 277 )?; |
306 )?; |
| 278 |
307 |
| 279 // opKz_adj.apply_add(&mut z_tmp, &y); |
308 // opKz_adj.apply_add(&mut dz, &y); |
| 280 // z_tmp.axpy(1.0, &z, -σ_p); |
309 // dz.axpy(1.0, &z, -σ_p); |
| 281 // let z_new = fnR.prox(σ_p, z_tmp); |
310 // let z_new = fnR.prox(σ_p, dz); |
| 282 // z.axpy(1.0 + ω, &z_new, -ω); |
311 // z.axpy(1.0 + ω, &z_new, -ω); |
| 283 // //z = (z - &z_new) * (-ω) + &z_new; |
312 // //z = (z - &z_new) * (-ω) + &z_new; |
| 284 // opKz.gemv(&mut y, σ_d, z, 1.0); |
313 // opKz.gemv(&mut y, σ_d, z, 1.0); |
| 285 // y = starH.prox(σ_d, y); |
314 // y = starH.prox(σ_d, y); |
| 286 // z = z_new; |
315 // z = z_new; |
| 298 |
327 |
| 299 // Give statistics if requested |
328 // Give statistics if requested |
| 300 let iter = state.iteration(); |
329 let iter = state.iteration(); |
| 301 stats.this_iters += 1; |
330 stats.this_iters += 1; |
| 302 |
331 |
| |
332 // Update differential of smooth part |
| |
333 Pair(v, dz) = f.differential(Pair(&μ, &z)); |
| |
334 τv = v * τ; |
| |
335 |
| 303 state.if_verbose(|| { |
336 state.if_verbose(|| { |
| 304 plotter.plot_spikes(iter, None, Some(&τv), &μ); |
337 plotter.plot_spikes(iter, None, Some(&τv), &μ); |
| 305 full_stats(&μ, &z, ε, std::mem::replace(&mut stats, IterInfo::new())) |
338 full_stats( |
| |
339 &μ, |
| |
340 &mut τv, |
| |
341 &z, |
| |
342 &dz, |
| |
343 ε, |
| |
344 std::mem::replace(&mut stats, IterInfo::new()), |
| |
345 ) |
| 306 }); |
346 }); |
| 307 |
347 |
| 308 // Update main tolerance for next iteration |
348 // Update main tolerance for next iteration |
| 309 ε = tolerance.update(ε, iter); |
349 ε = tolerance.update(ε, iter); |
| 310 } |
350 } |
| 352 F: Float + ToNalgebraRealField, |
392 F: Float + ToNalgebraRealField, |
| 353 U: Space + Clone, |
393 U: Space + Clone, |
| 354 //for<'a> &'a U: Instance<U>, |
394 //for<'a> &'a U: Instance<U>, |
| 355 I: AlgIteratorFactory<IterInfo<F>>, |
395 I: AlgIteratorFactory<IterInfo<F>>, |
| 356 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
396 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
| 357 S: ClosedMul<F>, |
397 S: ClosedMul<F> + MinMaxMapping<U, F>, |
| 358 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
398 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
| 359 //Pair<S, Z>: ClosedMul<F>, |
399 //Pair<S, Z>: ClosedMul<F>, |
| 360 DiscreteMeasure<U, F>: SpikeMerging<F>, |
400 DiscreteMeasure<U, F>: SpikeMerging<F> + Norm<Radon, F>, |
| 361 Reg: RegTerm<U, F>, |
401 Reg: RegTerm<U, F>, |
| 362 P: ProxPenalty<U, S, Reg, F>, |
402 P: ProxPenalty<U, S, Reg, F>, |
| 363 KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y> |
403 KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y> |
| 364 + GEMV<F, Z> |
404 + GEMV<F, Z> |
| 365 + SimplyAdjointable<Z, Y, AdjointCodomain = Z>, |
405 + SimplyAdjointable<Z, Y, AdjointCodomain = Z>, |
| 366 KOpZ::SimpleAdjoint: GEMV<F, Y>, |
406 KOpZ::SimpleAdjoint: GEMV<F, Y>, |
| 367 Y: ClosedEuclidean<F>, |
407 Y: ClosedEuclidean<F>, |
| 368 for<'b> &'b Y: Instance<Y>, |
408 for<'b> &'b Y: Instance<Y>, |
| 369 Z: ClosedEuclidean<F> + AXPY, |
409 Z: ClosedEuclidean<F> + AXPY + Clone, // clone not neede if Mul worked below |
| 370 for<'b> &'b Z: Instance<Z>, |
410 for<'b> &'b Z: Instance<Z>, // compiler overflow + Mul<F, Output = Z>, |
| 371 R: Prox<Z, Codomain = F>, |
411 R: Prox<Z, Codomain = F>, |
| 372 H: Conjugable<Y, F, Codomain = F>, |
412 H: Conjugable<Y, F, Codomain = F>, |
| 373 for<'b> H::Conjugate<'b>: Prox<Y>, |
413 for<'b> H::Conjugate<'b>: Prox<Y>, |
| 374 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>, |
414 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>, |
| 375 { |
415 { |
| 410 F: Float + ToNalgebraRealField, |
450 F: Float + ToNalgebraRealField, |
| 411 U: Space + Clone, |
451 U: Space + Clone, |
| 412 for<'a> &'a U: Instance<U>, |
452 for<'a> &'a U: Instance<U>, |
| 413 I: AlgIteratorFactory<IterInfo<F>>, |
453 I: AlgIteratorFactory<IterInfo<F>>, |
| 414 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
454 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
| 415 S: ClosedMul<F>, |
455 S: ClosedMul<F> + MinMaxMapping<U, F>, |
| 416 DiscreteMeasure<U, F>: SpikeMerging<F>, |
456 DiscreteMeasure<U, F>: SpikeMerging<F> + Norm<Radon, F>, |
| 417 Reg: RegTerm<U, F>, |
457 Reg: RegTerm<U, F>, |
| 418 P: ProxPenalty<U, S, Reg, F>, |
458 P: ProxPenalty<U, S, Reg, F>, |
| 419 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
459 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
| 420 Z: ClosedEuclidean<F> + AXPY + Clone, |
460 Z: ClosedEuclidean<F> + AXPY + Clone, |
| 421 for<'b> &'b Z: Instance<Z>, |
461 for<'b> &'b Z: Instance<Z>, // compiler overflow + Mul<F, Output = Z>, |
| 422 R: Prox<Z, Codomain = F>, |
462 R: Prox<Z, Codomain = F>, |
| 423 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>, |
463 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>, |
| 424 { |
464 { |
| 425 let opKz: ZeroOp<Z, Loc<0, F>, _, _, F> = |
465 let opKz: ZeroOp<Z, Loc<0, F>, _, _, F> = |
| 426 ZeroOp::new_dualisable(StaticEuclideanOriginGenerator, z.dual_origin()); |
466 ZeroOp::new_dualisable(StaticEuclideanOriginGenerator, z.dual_origin()); |
| 462 F: Float + ToNalgebraRealField, |
502 F: Float + ToNalgebraRealField, |
| 463 U: Space + Clone, |
503 U: Space + Clone, |
| 464 for<'a> &'a U: Instance<U>, |
504 for<'a> &'a U: Instance<U>, |
| 465 I: AlgIteratorFactory<IterInfo<F>>, |
505 I: AlgIteratorFactory<IterInfo<F>>, |
| 466 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
506 Dat: DifferentiableMapping<MeasureZ<F, Z, U>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
| 467 S: ClosedMul<F>, |
507 S: ClosedMul<F> + MinMaxMapping<U, F>, |
| 468 DiscreteMeasure<U, F>: SpikeMerging<F>, |
508 DiscreteMeasure<U, F>: SpikeMerging<F> + Norm<Radon, F>, |
| 469 Reg: RegTerm<U, F>, |
509 Reg: RegTerm<U, F>, |
| 470 P: ProxPenalty<U, S, Reg, F>, |
510 P: ProxPenalty<U, S, Reg, F>, |
| 471 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
511 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
| 472 Z: ClosedEuclidean<F> + AXPY + Clone, |
512 Z: ClosedEuclidean<F> + AXPY + Clone, |
| 473 for<'b> &'b Z: Instance<Z>, |
513 for<'b> &'b Z: Instance<Z>, // compiler overflow + Mul<F, Output = Z>, |
| 474 R: Prox<Z, Codomain = F>, |
514 R: Prox<Z, Codomain = F>, |
| 475 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>, |
515 Plot: Plotter<P::ReturnMapping, S, DiscreteMeasure<U, F>>, |
| 476 { |
516 { |
| 477 pointsource_fb_pair_dom( |
517 pointsource_fb_pair_dom( |
| 478 f, |
518 f, |