diff -r c5d8bd1a7728 -r 6316d68b58af src/prox_penalty.rs --- a/src/prox_penalty.rs Thu Jan 23 23:35:28 2025 +0100 +++ b/src/prox_penalty.rs Thu Jan 23 23:34:05 2025 +0100 @@ -12,17 +12,12 @@ AlgIteratorIteration, AlgIterator, }; -use crate::measures::{ - RNDM, -}; +use crate::measures::RNDM; use crate::types::{ RefinementSettings, IterInfo, }; -use crate::subproblem::{ - InnerSettings, - InnerMethod, -}; +use crate::subproblem::InnerSettings; use crate::tolerance::Tolerance; use crate::measures::merging::SpikeMergingMethod; use crate::regularisation::RegTerm; @@ -66,8 +61,11 @@ /// Tolerance multiplier for merges pub merge_tolerance_mult : F, - /// Spike merging method after the last step - pub final_merging : SpikeMergingMethod, + /// Merge spikes after last step (even if merging not generally enabled) + pub final_merging : bool, + + /// Use fitness as merging criterion. Implies worse convergence guarantees. + pub fitness_merging : bool, /// Iterations between merging heuristic tries pub merge_every : usize, @@ -86,13 +84,10 @@ max_insertions : 100, //bootstrap_insertions : None, bootstrap_insertions : Some((10, 1)), - inner : InnerSettings { - method : InnerMethod::Default, - .. Default::default() - }, - merging : SpikeMergingMethod::None, - //merging : Default::default(), - final_merging : Default::default(), + inner : Default::default(), + merging : Default::default(), + final_merging : true, + fitness_merging : false, merge_every : 10, merge_tolerance_mult : 2.0, // postprocessing : false, @@ -103,7 +98,12 @@ impl FBGenericConfig { /// Check if merging should be attempted this iteration pub fn merge_now(&self, state : &AlgIteratorIteration) -> bool { - state.iteration() % self.merge_every == 0 + 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} } } @@ -145,14 +145,45 @@ /// Merge spikes, if possible. + /// + /// Either optimality condition merging or objective value (fitness) merging + /// may be used, the latter only if `fitness` is provided and `config.fitness_merging` + /// is set. fn merge_spikes( &self, μ : &mut RNDM, τv : &mut PreadjointCodomain, μ_base : &RNDM, + ν_delta: Option<&RNDM>, τ : 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 + #[inline] + fn merge_spikes_no_fitness( + &self, + μ : &mut RNDM, + τv : &mut PreadjointCodomain, + μ_base : &RNDM, + ν_delta: Option<&RNDM>, + τ : 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{ + None + } + self.merge_spikes(μ, τv, μ_base, ν_delta, τ, ε, config, reg, + into_none(Some(|_ : &RNDM| F::ZERO))) + } }