src/forward_pdps.rs

changeset 98
b9818eb24b47
parent 96
5ba25d740dfc
equal deleted inserted replaced
97:f91f382ba4ae 98:b9818eb24b47
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(
231 &reg, 260 &reg,
232 &state, 261 &state,
233 &mut stats, 262 &mut stats,
234 )?; 263 )?;
235 264
236 (z, y) = zy_step(z, y, z_tmp); 265 (z, y) = zy_step(z, y, dz);
237 266
238 stats.inserted += μ.len() - μ_base.len(); 267 stats.inserted += μ.len() - μ_base.len();
239 268
240 // Merge spikes. 269 // Merge spikes.
241 // This crucially expects the merge routine to be stable with respect to spike locations, 270 // This crucially expects the merge routine to be stable with respect to spike locations,
261 } 290 }
262 } 291 }
263 292
264 for _ in 0..config.insertion.extra_weight_optimisation_steps { 293 for _ in 0..config.insertion.extra_weight_optimisation_steps {
265 // Do extra weight optimisation step heuristic 294 // Do extra weight optimisation step heuristic
266 let Pair(v, mut _z_tmp) = f.differential(Pair(&μ, &z)); 295 let Pair(v, mut _dz) = f.differential(Pair(&μ, &z));
267 τv = v * τ; 296 τv = v * τ;
268 prox_penalty.reweigh( 297 prox_penalty.reweigh(
269 &mut μ, 298 &mut μ,
270 &mut τv, 299 &mut τv,
271 τ, 300 τ,
274 &reg, 303 &reg,
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,

mercurial