| 18 use alg_tools::linops::{BoundedLinear, IdOp, SimplyAdjointable, ZeroOp, AXPY, GEMV}; |
19 use alg_tools::linops::{BoundedLinear, IdOp, SimplyAdjointable, ZeroOp, AXPY, GEMV}; |
| 19 use alg_tools::mapping::{DifferentiableMapping, DifferentiableRealMapping, Instance}; |
20 use alg_tools::mapping::{DifferentiableMapping, DifferentiableRealMapping, Instance}; |
| 20 use alg_tools::nalgebra_support::ToNalgebraRealField; |
21 use alg_tools::nalgebra_support::ToNalgebraRealField; |
| 21 use alg_tools::norms::L2; |
22 use alg_tools::norms::L2; |
| 22 use anyhow::ensure; |
23 use anyhow::ensure; |
| |
24 use measures::DeltaMeasure; |
| 23 use numeric_literals::replace_float_literals; |
25 use numeric_literals::replace_float_literals; |
| 24 use serde::{Deserialize, Serialize}; |
26 use serde::{Deserialize, Serialize}; |
| 25 |
27 |
| 26 /// Settings for [`pointsource_forward_pdps_pair`]. |
28 /// Settings for [`pointsource_forward_pdps_pair`]. |
| 27 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] |
29 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] |
| 109 (μ0, mut z, mut y): (Option<RNDM<N, F>>, Z, Y), |
111 (μ0, mut z, mut y): (Option<RNDM<N, F>>, Z, Y), |
| 110 //opKμ : KOpM, |
112 //opKμ : KOpM, |
| 111 opKz: &KOpZ, |
113 opKz: &KOpZ, |
| 112 fnR: &R, |
114 fnR: &R, |
| 113 fnH: &H, |
115 fnH: &H, |
| |
116 domain: &mut impl AdmissibleDomain<Loc<N, F>>, |
| 114 ) -> DynResult<MeasureZ<F, Z, N>> |
117 ) -> DynResult<MeasureZ<F, Z, N>> |
| 115 where |
118 where |
| 116 F: Float + ToNalgebraRealField, |
119 F: Float + ToNalgebraRealField, |
| 117 I: AlgIteratorFactory<IterInfo<F>>, |
120 I: AlgIteratorFactory<IterInfo<F>>, |
| 118 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
121 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
| 235 stats.inserted += μ.len() - μ_base.len(); |
238 stats.inserted += μ.len() - μ_base.len(); |
| 236 |
239 |
| 237 // Merge spikes. |
240 // Merge spikes. |
| 238 // This crucially expects the merge routine to be stable with respect to spike locations, |
241 // This crucially expects the merge routine to be stable with respect to spike locations, |
| 239 // and not to performing any pruning. That is be to done below simultaneously for γ. |
242 // and not to performing any pruning. That is be to done below simultaneously for γ. |
| 240 // Merge spikes. |
243 let did_merge = config.insertion.if_merge_now(&state, |ins| { |
| 241 // This crucially expects the merge routine to be stable with respect to spike locations, |
|
| 242 // and not to performing any pruning. That is be to done below simultaneously for γ. |
|
| 243 config.insertion.if_merge_now(&state, |ins| { |
|
| 244 stats.merged += prox_penalty.merge_spikes( |
244 stats.merged += prox_penalty.merge_spikes( |
| 245 &mut μ, |
245 &mut μ, |
| 246 &mut τv, |
246 &mut τv, |
| 247 &μ_base, |
247 &μ_base, |
| 248 τ, |
248 τ, |
| 249 ε, |
249 ε, |
| 250 ins, |
250 ins, |
| 251 ®, |
251 ®, |
| 252 Some(|μ̃: &RNDM<N, F>| f.apply(Pair(μ̃, &z))+ reg.apply(μ̃)), |
252 Some(|μ̃: &RNDM<N, F>| f.apply(Pair(μ̃, &z)) + reg.apply(μ̃)), |
| 253 ); |
253 ); |
| 254 }); |
254 stats.pruned += prune_with_stats(&mut μ); |
| 255 |
255 |
| 256 // Prune spikes with zero weight. |
256 if config.insertion.random_insertions { |
| 257 stats.pruned += prune_with_stats(&mut μ); |
257 if let Some(x) = domain.random_point() { |
| 258 |
258 μ += DeltaMeasure { x, α: 0.0 }; |
| 259 for _ in 0..config.insertion.extra_weight_optimisation_steps { |
259 stats.inserted += 1; |
| 260 // Do extra weight optimisation step heuristic |
260 } |
| 261 let Pair(v, _z_tmp) = f.differential(Pair(&μ, &z)); |
261 } |
| 262 τv = v * τ; |
262 |
| 263 prox_penalty.reweigh( |
263 for _ in 0..config.insertion.extra_weight_optimisation_steps { |
| 264 &mut μ, |
264 // Do extra weight optimisation step heuristic |
| 265 &mut τv, |
265 let Pair(v, mut _z_tmp) = f.differential(Pair(&μ, &z)); |
| 266 τ, |
266 τv = v * τ; |
| 267 ε, |
267 prox_penalty.reweigh( |
| 268 &config.insertion, |
268 &mut μ, |
| 269 ®, |
269 &mut τv, |
| 270 &state, |
270 τ, |
| 271 &mut stats, |
271 ε, |
| 272 )?; |
272 &config.insertion, |
| 273 //(z, y) = zy_step(z, y, z_tmp); |
273 ®, |
| 274 } |
274 &state, |
| 275 |
275 &mut stats, |
| 276 if config.insertion.extra_weight_optimisation_steps > 0 { |
276 )?; |
| 277 // Prune spikes with zero weight. |
277 |
| |
278 // opKz_adj.apply_add(&mut z_tmp, &y); |
| |
279 // z_tmp.axpy(1.0, &z, -σ_p); |
| |
280 // let z_new = fnR.prox(σ_p, z_tmp); |
| |
281 // z.axpy(1.0 + ω, &z_new, -ω); |
| |
282 // //z = (z - &z_new) * (-ω) + &z_new; |
| |
283 // opKz.gemv(&mut y, σ_d, z, 1.0); |
| |
284 // y = starH.prox(σ_d, y); |
| |
285 // z = z_new; |
| |
286 } |
| |
287 Ok(()) |
| |
288 })?; |
| |
289 |
| |
290 if did_merge.is_none() { |
| 278 stats.pruned += prune_with_stats(&mut μ); |
291 stats.pruned += prune_with_stats(&mut μ); |
| 279 } |
292 } |
| 280 |
293 |
| 281 // Update step length parameters |
294 // Update step length parameters |
| 282 // let ω = pdpsconfig.acceleration.accelerate(&mut τ, &mut σ, γ); |
295 // let ω = pdpsconfig.acceleration.accelerate(&mut τ, &mut σ, γ); |
| 301 }; |
314 }; |
| 302 |
315 |
| 303 μ.merge_spikes_fitness(config.insertion.final_merging_method(), fit, |&v| v); |
316 μ.merge_spikes_fitness(config.insertion.final_merging_method(), fit, |&v| v); |
| 304 μ.prune(); |
317 μ.prune(); |
| 305 Ok(Pair(μ, z)) |
318 Ok(Pair(μ, z)) |
| |
319 } |
| |
320 |
| |
321 #[deprecated] |
| |
322 pub fn pointsource_forward_pdps_pair< |
| |
323 F, |
| |
324 I, |
| |
325 S, |
| |
326 Dat, |
| |
327 Reg, |
| |
328 P, |
| |
329 Z, |
| |
330 R, |
| |
331 Y, |
| |
332 /*KOpM, */ KOpZ, |
| |
333 H, |
| |
334 Plot, |
| |
335 const N: usize, |
| |
336 >( |
| |
337 f: &Dat, |
| |
338 reg: &Reg, |
| |
339 prox_penalty: &P, |
| |
340 config: &ForwardPDPSConfig<F>, |
| |
341 iterator: I, |
| |
342 plotter: Plot, |
| |
343 init: (Option<RNDM<N, F>>, Z, Y), |
| |
344 //opKμ : KOpM, |
| |
345 opKz: &KOpZ, |
| |
346 fnR: &R, |
| |
347 fnH: &H, |
| |
348 ) -> DynResult<MeasureZ<F, Z, N>> |
| |
349 where |
| |
350 F: Float + ToNalgebraRealField, |
| |
351 I: AlgIteratorFactory<IterInfo<F>>, |
| |
352 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
| |
353 //Pair<S, Z>: ClosedMul<F>, // Doesn't really need to be closed, if make this signature more complex… |
| |
354 S: DifferentiableRealMapping<N, F> + ClosedMul<F>, |
| |
355 RNDM<N, F>: SpikeMerging<F>, |
| |
356 Reg: RegTerm<Loc<N, F>, F>, |
| |
357 P: ProxPenalty<Loc<N, F>, S, Reg, F>, |
| |
358 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
| |
359 KOpZ: BoundedLinear<Z, L2, L2, F, Codomain = Y> |
| |
360 + GEMV<F, Z, Y> |
| |
361 + SimplyAdjointable<Z, Y, Codomain = Y, AdjointCodomain = Z>, |
| |
362 KOpZ::SimpleAdjoint: GEMV<F, Y, Z>, |
| |
363 Y: ClosedEuclidean<F>, |
| |
364 for<'b> &'b Y: Instance<Y>, |
| |
365 Z: ClosedEuclidean<F> + AXPY, |
| |
366 for<'b> &'b Z: Instance<Z>, |
| |
367 R: Prox<Z, Codomain = F>, |
| |
368 H: Conjugable<Y, F, Codomain = F>, |
| |
369 for<'b> H::Conjugate<'b>: Prox<Y>, |
| |
370 Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>, |
| |
371 { |
| |
372 pointsource_forward_pdps_pair_dom( |
| |
373 f, |
| |
374 reg, |
| |
375 prox_penalty, |
| |
376 config, |
| |
377 iterator, |
| |
378 plotter, |
| |
379 init, |
| |
380 opKz, |
| |
381 fnR, |
| |
382 fnH, |
| |
383 &mut FullSpace, |
| |
384 ) |
| 306 } |
385 } |
| 307 |
386 |
| 308 /// Iteratively solve the pointsource localisation with an additional variable |
387 /// Iteratively solve the pointsource localisation with an additional variable |
| 309 /// using forward-backward splitting. |
388 /// using forward-backward splitting. |
| 310 /// |
389 /// |
| 311 /// The implementation uses [`pointsource_forward_pdps_pair`] with appropriate dummy |
390 /// The implementation uses [`pointsource_forward_pdps_pair`] with appropriate dummy |
| 312 /// variables, operators, and functions. |
391 /// variables, operators, and functions. |
| 313 #[replace_float_literals(F::cast_from(literal))] |
392 #[replace_float_literals(F::cast_from(literal))] |
| 314 pub fn pointsource_fb_pair<F, I, S, Dat, Reg, P, Z, R, Plot, const N: usize>( |
393 pub fn pointsource_fb_pair_dom<F, I, S, Dat, Reg, P, Z, R, Plot, const N: usize>( |
| 315 f: &Dat, |
394 f: &Dat, |
| 316 reg: &Reg, |
395 reg: &Reg, |
| 317 prox_penalty: &P, |
396 prox_penalty: &P, |
| 318 config: &FBConfig<F>, |
397 config: &FBConfig<F>, |
| 319 iterator: I, |
398 iterator: I, |
| 320 plotter: Plot, |
399 plotter: Plot, |
| 321 (μ0, z): (Option<RNDM<N, F>>, Z), |
400 (μ0, z): (Option<RNDM<N, F>>, Z), |
| 322 //opKμ : KOpM, |
401 //opKμ : KOpM, |
| 323 fnR: &R, |
402 fnR: &R, |
| |
403 domain: &mut impl AdmissibleDomain<Loc<N, F>>, |
| 324 ) -> DynResult<MeasureZ<F, Z, N>> |
404 ) -> DynResult<MeasureZ<F, Z, N>> |
| 325 where |
405 where |
| 326 F: Float + ToNalgebraRealField, |
406 F: Float + ToNalgebraRealField, |
| 327 I: AlgIteratorFactory<IterInfo<F>>, |
407 I: AlgIteratorFactory<IterInfo<F>>, |
| 328 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
408 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
| 343 // Convert config. We don't implement From (that could be done with the o2o crate), as σd0 |
423 // Convert config. We don't implement From (that could be done with the o2o crate), as σd0 |
| 344 // needs to be chosen in a general case; for the problem of this fucntion, anything is valid. |
424 // needs to be chosen in a general case; for the problem of this fucntion, anything is valid. |
| 345 let &FBConfig { τ0, σp0, insertion } = config; |
425 let &FBConfig { τ0, σp0, insertion } = config; |
| 346 let pdps_config = ForwardPDPSConfig { τ0, σp0, insertion, σd0: 0.0 }; |
426 let pdps_config = ForwardPDPSConfig { τ0, σp0, insertion, σd0: 0.0 }; |
| 347 |
427 |
| 348 pointsource_forward_pdps_pair( |
428 pointsource_forward_pdps_pair_dom( |
| 349 f, |
429 f, |
| 350 reg, |
430 reg, |
| 351 prox_penalty, |
431 prox_penalty, |
| 352 &pdps_config, |
432 &pdps_config, |
| 353 iterator, |
433 iterator, |
| 354 plotter, |
434 plotter, |
| 355 (μ0, z, Loc([])), |
435 (μ0, z, Loc([])), |
| 356 &opKz, |
436 &opKz, |
| 357 fnR, |
437 fnR, |
| 358 &fnH, |
438 &fnH, |
| |
439 domain, |
| 359 ) |
440 ) |
| 360 } |
441 } |
| |
442 |
| |
443 #[deprecated] |
| |
444 #[replace_float_literals(F::cast_from(literal))] |
| |
445 pub fn pointsource_fb_pair<F, I, S, Dat, Reg, P, Z, R, Plot, const N: usize>( |
| |
446 f: &Dat, |
| |
447 reg: &Reg, |
| |
448 prox_penalty: &P, |
| |
449 config: &FBConfig<F>, |
| |
450 iterator: I, |
| |
451 plotter: Plot, |
| |
452 init: (Option<RNDM<N, F>>, Z), |
| |
453 //opKμ : KOpM, |
| |
454 fnR: &R, |
| |
455 ) -> DynResult<MeasureZ<F, Z, N>> |
| |
456 where |
| |
457 F: Float + ToNalgebraRealField, |
| |
458 I: AlgIteratorFactory<IterInfo<F>>, |
| |
459 Dat: DifferentiableMapping<MeasureZ<F, Z, N>, Codomain = F, DerivativeDomain = Pair<S, Z>>, |
| |
460 S: DifferentiableRealMapping<N, F> + ClosedMul<F>, |
| |
461 RNDM<N, F>: SpikeMerging<F>, |
| |
462 Reg: RegTerm<Loc<N, F>, F>, |
| |
463 P: ProxPenalty<Loc<N, F>, S, Reg, F>, |
| |
464 for<'a> Pair<&'a P, &'a IdOp<Z>>: StepLengthBoundPair<F, Dat>, |
| |
465 Z: ClosedEuclidean<F> + AXPY<Field = F> + Clone, |
| |
466 for<'b> &'b Z: Instance<Z>, |
| |
467 R: Prox<Z, Codomain = F>, |
| |
468 Plot: Plotter<P::ReturnMapping, S, RNDM<N, F>>, |
| |
469 // We should not need to explicitly require this: |
| |
470 for<'b> &'b Loc<0, F>: Instance<Loc<0, F>>, |
| |
471 { |
| |
472 pointsource_fb_pair_dom( |
| |
473 f, |
| |
474 reg, |
| |
475 prox_penalty, |
| |
476 config, |
| |
477 iterator, |
| |
478 plotter, |
| |
479 init, |
| |
480 fnR, |
| |
481 &mut FullSpace, |
| |
482 ) |
| |
483 } |