Sun, 11 Dec 2022 23:25:53 +0200
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
* Fixes the conditional gradient methods that were incorrectly solving
positivity constrained subproblems although the infinite-dimensional
versions do not include such constraints.
* Introduces the `ExperimentV2` struct that has `regularisation` in place
of `α`. The `Experiment` struct is now deprecated.
* The L^2-squared experiments were switch to be unconstrained, as the
Franke-Wolfe implementations do not support constraints. (This would
be easy to add for the “fully corrective” variant, but is not
immediate for the “relaxed” variant.)
/*! Regularisation terms */ use serde::{Serialize, Deserialize}; use alg_tools::norms::Norm; use alg_tools::linops::Apply; use alg_tools::loc::Loc; use crate::types::*; use crate::measures::{ DiscreteMeasure, Radon }; #[allow(unused_imports)] // Used by documentation. use crate::fb::generic_pointsource_fb_reg; /// The regularisation term $α\\|μ\\|\_{ℳ(Ω)} + δ_{≥ 0}(μ)$ for [`generic_pointsource_fb_reg`]. /// /// The only member of the struct is the regularisation parameter α. #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct NonnegRadonRegTerm<F : Float>(pub F /* α */); impl<'a, F : Float> NonnegRadonRegTerm<F> { /// Returns the regularisation parameter pub fn α(&self) -> F { let &NonnegRadonRegTerm(α) = self; α } } impl<'a, F : Float, const N : usize> Apply<&'a DiscreteMeasure<Loc<F, N>, F>> for NonnegRadonRegTerm<F> { type Output = F; fn apply(&self, μ : &'a DiscreteMeasure<Loc<F, N>, F>) -> F { self.α() * μ.norm(Radon) } } /// The regularisation term $α\|μ\|_{ℳ(Ω)}$ for [`generic_pointsource_fb_reg`]. /// /// The only member of the struct is the regularisation parameter α. #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct RadonRegTerm<F : Float>(pub F /* α */); impl<'a, F : Float> RadonRegTerm<F> { /// Returns the regularisation parameter pub fn α(&self) -> F { let &RadonRegTerm(α) = self; α } } impl<'a, F : Float, const N : usize> Apply<&'a DiscreteMeasure<Loc<F, N>, F>> for RadonRegTerm<F> { type Output = F; fn apply(&self, μ : &'a DiscreteMeasure<Loc<F, N>, F>) -> F { self.α() * μ.norm(Radon) } } /// Regularisation term configuration #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] pub enum Regularisation<F : Float> { /// $α \\|μ\\|\_{ℳ(Ω)}$ Radon(F), /// $α\\|μ\\|\_{ℳ(Ω)} + δ_{≥ 0}(μ)$ NonnegRadon(F), } impl<'a, F : Float, const N : usize> Apply<&'a DiscreteMeasure<Loc<F, N>, F>> for Regularisation<F> { type Output = F; fn apply(&self, μ : &'a DiscreteMeasure<Loc<F, N>, F>) -> F { match *self { Self::Radon(α) => RadonRegTerm(α).apply(μ), Self::NonnegRadon(α) => NonnegRadonRegTerm(α).apply(μ), } } }