| 1 /*! |
1 /*! |
| 2 Solver for the point source localisation problem using a sliding |
2 Solver for the point source localisation problem using a sliding |
| 3 primal-dual proximal splitting method. |
3 primal-dual proximal splitting method. |
| 4 */ |
4 */ |
| 5 |
5 |
| |
6 use crate::domain::{AdmissibleDomain, FullSpace}; |
| 6 use crate::fb::*; |
7 use crate::fb::*; |
| 7 use crate::forward_model::{BoundedCurvature, BoundedCurvatureGuess}; |
8 use crate::forward_model::{BoundedCurvature, BoundedCurvatureGuess}; |
| 8 use crate::measures::merging::SpikeMerging; |
9 use crate::measures::merging::SpikeMerging; |
| 9 use crate::measures::{DiscreteMeasure, RNDM}; |
10 use crate::measures::{DiscreteMeasure, RNDM}; |
| 10 use crate::plot::Plotter; |
11 use crate::plot::Plotter; |
| 12 use crate::regularisation::SlidingRegTerm; |
13 use crate::regularisation::SlidingRegTerm; |
| 13 use crate::sliding_fb::{SlidingFBConfig, Transport, TransportConfig, TransportProxPenalty}; |
14 use crate::sliding_fb::{SlidingFBConfig, Transport, TransportConfig, TransportProxPenalty}; |
| 14 use crate::types::*; |
15 use crate::types::*; |
| 15 use alg_tools::bounds::MinMaxMapping; |
16 use alg_tools::bounds::MinMaxMapping; |
| 16 use alg_tools::convex::{Conjugable, Prox, Zero}; |
17 use alg_tools::convex::{Conjugable, Prox, Zero}; |
| 17 use alg_tools::norms::L2; |
|
| 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::iterate::AlgIteratorFactory; |
21 use alg_tools::iterate::AlgIteratorFactory; |
| 22 use alg_tools::linops::{ |
22 use alg_tools::linops::{ |
| 23 BoundedLinear, IdOp, SimplyAdjointable, StaticEuclideanOriginGenerator, ZeroOp, AXPY, GEMV, |
23 BoundedLinear, IdOp, SimplyAdjointable, StaticEuclideanOriginGenerator, ZeroOp, AXPY, GEMV, |
| 24 }; |
24 }; |
| 25 use alg_tools::mapping::{DifferentiableMapping, DifferentiableRealMapping, Instance}; |
25 use alg_tools::mapping::{DifferentiableMapping, DifferentiableRealMapping, Instance}; |
| 26 use alg_tools::nalgebra_support::ToNalgebraRealField; |
26 use alg_tools::nalgebra_support::ToNalgebraRealField; |
| |
27 use alg_tools::norms::L2; |
| 27 use anyhow::ensure; |
28 use anyhow::ensure; |
| |
29 use measures::DeltaMeasure; |
| 28 use numeric_literals::replace_float_literals; |
30 use numeric_literals::replace_float_literals; |
| 29 use serde::{Deserialize, Serialize}; |
31 use serde::{Deserialize, Serialize}; |
| 30 |
32 |
| 31 /// Settings for [`pointsource_sliding_pdps_pair`]. |
33 /// Settings for [`pointsource_sliding_pdps_pair`]. |
| 32 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] |
34 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] |
| 94 (μ0, mut z, mut y): (Option<RNDM<N, F>>, Z, Y), |
96 (μ0, mut z, mut y): (Option<RNDM<N, F>>, Z, Y), |
| 95 //opKμ : KOpM, |
97 //opKμ : KOpM, |
| 96 opKz: &KOpZ, |
98 opKz: &KOpZ, |
| 97 fnR: &R, |
99 fnR: &R, |
| 98 fnH: &H, |
100 fnH: &H, |
| 99 domain: Option<&P::Dom>, |
101 domain: &mut impl AdmissibleDomain<Loc<N, F>>, |
| 100 ) -> DynResult<MeasureZ<F, Z, N>> |
102 ) -> DynResult<MeasureZ<F, Z, N>> |
| 101 where |
103 where |
| 102 F: Float + ToNalgebraRealField, |
104 F: Float + ToNalgebraRealField, |
| 103 I: AlgIteratorFactory<IterInfo<F>>, |
105 I: AlgIteratorFactory<IterInfo<F>>, |
| 104 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>> |
106 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>> |
| 304 z = z_new; |
306 z = z_new; |
| 305 |
307 |
| 306 // Merge spikes. |
308 // Merge spikes. |
| 307 // This crucially expects the merge routine to be stable with respect to spike locations, |
309 // This crucially expects the merge routine to be stable with respect to spike locations, |
| 308 // and not to performing any pruning. That is be to done below simultaneously for γ. |
310 // and not to performing any pruning. That is be to done below simultaneously for γ. |
| 309 config.insertion.if_merge_now(&state, |ins| { |
311 let did_merge = config.insertion.if_merge_now(&state, |ins| { |
| 310 let m = prox_penalty.merge_spikes( |
312 stats.merged += prox_penalty.merge_spikes( |
| 311 &mut μ, |
313 &mut μ, |
| 312 &mut τv̆, |
314 &mut τv̆, |
| 313 &μ̆, |
315 &μ̆, |
| 314 τ, |
316 τ, |
| 315 ε, |
317 ε, |
| 316 ins, |
318 ins, |
| 317 ®, |
319 ®, |
| 318 Some(|μ̃: &RNDM<N, F>| f.apply(Pair(μ̃, &z)) + reg.apply(μ̃)), |
320 Some(|μ̃: &RNDM<N, F>| f.apply(Pair(μ̃, &z)) + reg.apply(μ̃)), |
| 319 ); |
321 ); |
| 320 if m > 0 { |
322 γ.prune_compat(&mut μ, &mut stats); |
| 321 stats.merged += m; |
323 |
| |
324 if config.insertion.random_insertions { |
| |
325 if let Some(x) = domain.random_point() { |
| |
326 μ += DeltaMeasure { x, α: 0.0 }; |
| |
327 stats.inserted += 1; |
| |
328 } |
| 322 } |
329 } |
| 323 }); |
330 |
| 324 |
331 for _ in 0..config.insertion.extra_weight_optimisation_steps { |
| 325 γ.prune_compat(&mut μ, &mut stats); |
332 // Do extra weight optimisation step heuristic |
| 326 |
333 let Pair(v, mut _z_tmp) = f.differential(Pair(&μ, &z)); |
| 327 for _ in 0..config.insertion.extra_weight_optimisation_steps { |
334 τv̆ = v * τ; |
| 328 // Do extra weight optimisation step heuristic |
335 prox_penalty.reweigh( |
| 329 let Pair(v, mut _z_tmp) = f.differential(Pair(&μ, &z)); |
336 &mut μ, |
| 330 τv̆ = v * τ; |
337 &mut τv̆, |
| 331 prox_penalty.reweigh( |
338 τ, |
| 332 &mut μ, |
339 ε, |
| 333 &mut τv̆, |
340 &config.insertion, |
| 334 τ, |
341 ®, |
| 335 ε, |
342 &state, |
| 336 &config.insertion, |
343 &mut stats, |
| 337 ®, |
344 )?; |
| 338 &state, |
345 |
| 339 &mut stats, |
346 // opKz_adj.apply_add(&mut z_tmp, &y); |
| 340 )?; |
347 // z_tmp.axpy(1.0, &z, -σ_p); |
| 341 |
348 // let z_new = fnR.prox(σ_p, z_tmp); |
| 342 // opKz_adj.apply_add(&mut z_tmp, &y); |
349 // z.axpy(1.0 + ω, &z_new, -ω); |
| 343 // z_tmp.axpy(1.0, &z, -σ_p); |
350 // //z = (z - &z_new) * (-ω) + &z_new; |
| 344 // let z_new = fnR.prox(σ_p, z_tmp); |
351 // opKz.gemv(&mut y, σ_d, z, 1.0); |
| 345 // z.axpy(1.0 + ω, &z_new, -ω); |
352 // y = starH.prox(σ_d, y); |
| 346 // //z = (z - &z_new) * (-ω) + &z_new; |
353 // z = z_new; |
| 347 // opKz.gemv(&mut y, σ_d, z, 1.0); |
354 } |
| 348 // y = starH.prox(σ_d, y); |
355 Ok(()) |
| 349 // z = z_new; |
356 })?; |
| 350 } |
357 |
| 351 |
358 if did_merge.is_none() { |
| 352 if config.insertion.extra_weight_optimisation_steps > 0 { |
|
| 353 γ.prune_compat(&mut μ, &mut stats); |
359 γ.prune_compat(&mut μ, &mut stats); |
| 354 } |
360 } |
| 355 |
361 |
| 356 // Update step length parameters |
362 // Update step length parameters |
| 357 // let ω = pdpsconfig.acceleration.accelerate(&mut τ, &mut σ, γ); |
363 // let ω = pdpsconfig.acceleration.accelerate(&mut τ, &mut σ, γ); |
| 394 iterator: I, |
400 iterator: I, |
| 395 plotter: Plot, |
401 plotter: Plot, |
| 396 (μ0, z): (Option<RNDM<N, F>>, Z), |
402 (μ0, z): (Option<RNDM<N, F>>, Z), |
| 397 //opKμ : KOpM, |
403 //opKμ : KOpM, |
| 398 fnR: &R, |
404 fnR: &R, |
| 399 domain: Option<&P::Dom> |
405 domain: &mut impl AdmissibleDomain<Loc<N, F>>, |
| 400 ) -> DynResult<MeasureZ<F, Z, N>> |
406 ) -> DynResult<MeasureZ<F, Z, N>> |
| 401 where |
407 where |
| 402 F: Float + ToNalgebraRealField, |
408 F: Float + ToNalgebraRealField, |
| 403 I: AlgIteratorFactory<IterInfo<F>>, |
409 I: AlgIteratorFactory<IterInfo<F>>, |
| 404 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>> |
410 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>> |