diff -r 39c5e6c7759d -r 0693cc9ba9f0 src/prox_penalty.rs --- a/src/prox_penalty.rs Mon Feb 17 13:45:11 2025 -0500 +++ b/src/prox_penalty.rs Mon Feb 17 13:51:50 2025 -0500 @@ -2,119 +2,114 @@ Proximal penalty abstraction */ +use alg_tools::types::*; use numeric_literals::replace_float_literals; -use alg_tools::types::*; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; +use crate::measures::merging::SpikeMergingMethod; +use crate::measures::RNDM; +use crate::regularisation::RegTerm; +use crate::subproblem::InnerSettings; +use crate::tolerance::Tolerance; +use crate::types::{IterInfo, RefinementSettings}; +use alg_tools::iterate::{AlgIterator, AlgIteratorIteration}; use alg_tools::mapping::RealMapping; use alg_tools::nalgebra_support::ToNalgebraRealField; -use alg_tools::iterate::{ - AlgIteratorIteration, - AlgIterator, -}; -use crate::measures::RNDM; -use crate::types::{ - RefinementSettings, - IterInfo, -}; -use crate::subproblem::InnerSettings; -use crate::tolerance::Tolerance; -use crate::measures::merging::SpikeMergingMethod; -use crate::regularisation::RegTerm; +pub mod radon_squared; pub mod wave; -pub mod radon_squared; pub use radon_squared::RadonSquared; /// Settings for the solution of the stepwise optimality condition. #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] #[serde(default)] -pub struct FBGenericConfig { +pub struct FBGenericConfig { /// Tolerance for point insertion. - pub tolerance : Tolerance, + pub tolerance: Tolerance, /// Stop looking for predual maximum (where to isert a new point) below /// `tolerance` multiplied by this factor. /// - /// Not used by [`super::radon_fb`]. - pub insertion_cutoff_factor : F, + /// Not used by [`crate::prox_penalty::radon_squared`]. + pub insertion_cutoff_factor: F, /// Settings for branch and bound refinement when looking for predual maxima - pub refinement : RefinementSettings, + pub refinement: RefinementSettings, /// Maximum insertions within each outer iteration /// - /// Not used by [`super::radon_fb`]. - pub max_insertions : usize, + /// Not used by [`crate::prox_penalty::radon_squared`]. + pub max_insertions: usize, /// Pair `(n, m)` for maximum insertions `m` on first `n` iterations. /// - /// Not used by [`super::radon_fb`]. - pub bootstrap_insertions : Option<(usize, usize)>, + /// Not used by [`crate::prox_penalty::radon_squared`]. + pub bootstrap_insertions: Option<(usize, usize)>, /// Inner method settings - pub inner : InnerSettings, + pub inner: InnerSettings, /// Spike merging method - pub merging : SpikeMergingMethod, + pub merging: SpikeMergingMethod, /// Tolerance multiplier for merges - pub merge_tolerance_mult : F, + pub merge_tolerance_mult: F, /// Merge spikes after last step (even if merging not generally enabled) - pub final_merging : bool, + pub final_merging: bool, /// Use fitness as merging criterion. Implies worse convergence guarantees. - pub fitness_merging : bool, + pub fitness_merging: bool, /// Iterations between merging heuristic tries - pub merge_every : usize, - + pub merge_every: usize, // /// Save $μ$ for postprocessing optimisation // pub postprocessing : bool } #[replace_float_literals(F::cast_from(literal))] -impl Default for FBGenericConfig { +impl Default for FBGenericConfig { fn default() -> Self { FBGenericConfig { - tolerance : Default::default(), - insertion_cutoff_factor : 1.0, - refinement : Default::default(), - max_insertions : 100, + tolerance: Default::default(), + insertion_cutoff_factor: 1.0, + refinement: Default::default(), + max_insertions: 100, //bootstrap_insertions : None, - bootstrap_insertions : Some((10, 1)), - inner : Default::default(), - merging : Default::default(), - final_merging : true, - fitness_merging : false, - merge_every : 10, - merge_tolerance_mult : 2.0, + bootstrap_insertions: Some((10, 1)), + inner: Default::default(), + merging: Default::default(), + final_merging: true, + fitness_merging: false, + merge_every: 10, + merge_tolerance_mult: 2.0, // postprocessing : false, } } } -impl FBGenericConfig { +impl FBGenericConfig { /// Check if merging should be attempted this iteration - pub fn merge_now(&self, state : &AlgIteratorIteration) -> bool { + pub fn merge_now(&self, state: &AlgIteratorIteration) -> bool { self.merging.enabled && state.iteration() % self.merge_every == 0 } /// Returns the final merging method pub fn final_merging_method(&self) -> SpikeMergingMethod { - SpikeMergingMethod{ enabled : self.final_merging, ..self.merging} + SpikeMergingMethod { + enabled: self.final_merging, + ..self.merging + } } } - /// Trait for proximal penalties -pub trait ProxPenalty +pub trait ProxPenalty where - F : Float + ToNalgebraRealField, - Reg : RegTerm, + F: Float + ToNalgebraRealField, + Reg: RegTerm, { - type ReturnMapping : RealMapping; + type ReturnMapping: RealMapping; /// Insert new spikes into `μ` to approximately satisfy optimality conditions /// with the forward step term fixed to `τv`. @@ -125,24 +120,23 @@ /// `μ_base + ν_delta` is the base point, where `μ` and `μ_base` are assumed to have the same /// spike locations, while `ν_delta` may have different locations. /// - /// `τv` is mutable to allow [`alg_tools::bisection_tree::btfn::BTFN`] refinement. + /// `τv` is mutable to allow [`alg_tools::bisection_tree::BTFN`] refinement. /// Actual values of `τv` are not supposed to be mutated. fn insert_and_reweigh( &self, - μ : &mut RNDM, - τv : &mut PreadjointCodomain, - μ_base : &RNDM, + μ: &mut RNDM, + τv: &mut PreadjointCodomain, + μ_base: &RNDM, ν_delta: Option<&RNDM>, - τ : F, - ε : F, - config : &FBGenericConfig, - reg : &Reg, - state : &AlgIteratorIteration, - stats : &mut IterInfo, + τ: F, + ε: F, + config: &FBGenericConfig, + reg: &Reg, + state: &AlgIteratorIteration, + stats: &mut IterInfo, ) -> (Option, bool) where - I : AlgIterator; - + I: AlgIterator; /// Merge spikes, if possible. /// @@ -151,39 +145,48 @@ /// is set. fn merge_spikes( &self, - μ : &mut RNDM, - τv : &mut PreadjointCodomain, - μ_base : &RNDM, + μ: &mut RNDM, + τv: &mut PreadjointCodomain, + μ_base: &RNDM, ν_delta: Option<&RNDM>, - τ : F, - ε : F, - config : &FBGenericConfig, - reg : &Reg, - fitness : Option) -> F>, + τ: F, + ε: F, + config: &FBGenericConfig, + reg: &Reg, + fitness: Option) -> F>, ) -> usize; /// Merge spikes, if possible. /// - /// Unlike [`merge_spikes`], this variant only supports optimality condition based merging + /// Unlike [`Self::merge_spikes`], this variant only supports optimality condition based merging #[inline] fn merge_spikes_no_fitness( &self, - μ : &mut RNDM, - τv : &mut PreadjointCodomain, - μ_base : &RNDM, + μ: &mut RNDM, + τv: &mut PreadjointCodomain, + μ_base: &RNDM, ν_delta: Option<&RNDM>, - τ : F, - ε : F, - config : &FBGenericConfig, - reg : &Reg, + τ: F, + ε: F, + config: &FBGenericConfig, + reg: &Reg, ) -> usize { /// This is a hack to create a `None` of same type as a `Some` // for the `impl Fn` parameter of `merge_spikes`. #[inline] - fn into_none(_ : Option) -> Option{ + fn into_none(_: Option) -> Option { None } - self.merge_spikes(μ, τv, μ_base, ν_delta, τ, ε, config, reg, - into_none(Some(|_ : &RNDM| F::ZERO))) + self.merge_spikes( + μ, + τv, + μ_base, + ν_delta, + τ, + ε, + config, + reg, + into_none(Some(|_: &RNDM| F::ZERO)), + ) } }