Tue, 31 Dec 2024 09:34:24 -0500
Early transport sketches
|
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
1 | /*! |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
2 | Regularisation terms |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
3 | */ |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
4 | |
| 32 | 5 | use numeric_literals::replace_float_literals; |
|
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
6 | use serde::{Serialize, Deserialize}; |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
7 | use alg_tools::norms::Norm; |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
8 | use alg_tools::linops::Apply; |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
9 | use alg_tools::loc::Loc; |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
10 | use crate::types::*; |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
11 | use crate::measures::{ |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
12 | DiscreteMeasure, |
| 32 | 13 | DeltaMeasure, |
|
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
14 | Radon |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
15 | }; |
| 32 | 16 | use crate::fb::FBGenericConfig; |
|
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
17 | #[allow(unused_imports)] // Used by documentation. |
| 32 | 18 | use crate::fb::pointsource_fb_reg; |
| 19 | #[allow(unused_imports)] // Used by documentation. | |
| 20 | use crate::sliding_fb::pointsource_sliding_fb_reg; | |
|
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
21 | |
| 32 | 22 | use nalgebra::{DVector, DMatrix}; |
| 23 | use alg_tools::nalgebra_support::ToNalgebraRealField; | |
| 24 | use alg_tools::mapping::Mapping; | |
| 25 | use alg_tools::bisection_tree::{ | |
| 26 | BTFN, | |
| 27 | Bounds, | |
| 28 | BTSearch, | |
| 29 | P2Minimise, | |
| 30 | SupportGenerator, | |
| 31 | LocalAnalysis, | |
| 32 | Bounded, | |
| 33 | }; | |
| 34 | use crate::subproblem::{ | |
| 35 | nonneg::quadratic_nonneg, | |
| 36 | unconstrained::quadratic_unconstrained, | |
| 37 | }; | |
| 38 | use alg_tools::iterate::AlgIteratorFactory; | |
| 39 | ||
| 40 | /// The regularisation term $α\\|μ\\|\_{ℳ(Ω)} + δ_{≥ 0}(μ)$ for [`pointsource_fb_reg`] and other | |
| 41 | /// algorithms. | |
|
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
42 | /// |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
43 | /// The only member of the struct is the regularisation parameter α. |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
44 | #[derive(Copy, Clone, Debug, Serialize, Deserialize)] |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
45 | pub struct NonnegRadonRegTerm<F : Float>(pub F /* α */); |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
46 | |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
47 | impl<'a, F : Float> NonnegRadonRegTerm<F> { |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
48 | /// Returns the regularisation parameter |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
49 | pub fn α(&self) -> F { |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
50 | let &NonnegRadonRegTerm(α) = self; |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
51 | α |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
52 | } |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
53 | } |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
54 | |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
55 | impl<'a, F : Float, const N : usize> Apply<&'a DiscreteMeasure<Loc<F, N>, F>> |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
56 | for NonnegRadonRegTerm<F> { |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
57 | type Output = F; |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
58 | |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
59 | fn apply(&self, μ : &'a DiscreteMeasure<Loc<F, N>, F>) -> F { |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
60 | self.α() * μ.norm(Radon) |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
61 | } |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
62 | } |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
63 | |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
64 | |
| 32 | 65 | /// The regularisation term $α\|μ\|_{ℳ(Ω)}$ for [`pointsource_fb_reg`]. |
|
24
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
66 | /// |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
67 | /// The only member of the struct is the regularisation parameter α. |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
68 | #[derive(Copy, Clone, Debug, Serialize, Deserialize)] |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
69 | pub struct RadonRegTerm<F : Float>(pub F /* α */); |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
70 | |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
71 | |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
72 | impl<'a, F : Float> RadonRegTerm<F> { |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
73 | /// Returns the regularisation parameter |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
74 | pub fn α(&self) -> F { |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
75 | let &RadonRegTerm(α) = self; |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
76 | α |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
77 | } |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
78 | } |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
79 | |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
80 | impl<'a, F : Float, const N : usize> Apply<&'a DiscreteMeasure<Loc<F, N>, F>> |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
81 | for RadonRegTerm<F> { |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
82 | type Output = F; |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
83 | |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
84 | fn apply(&self, μ : &'a DiscreteMeasure<Loc<F, N>, F>) -> F { |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
85 | self.α() * μ.norm(Radon) |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
86 | } |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
87 | } |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
88 | |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
89 | /// Regularisation term configuration |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
90 | #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
91 | pub enum Regularisation<F : Float> { |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
92 | /// $α \\|μ\\|\_{ℳ(Ω)}$ |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
93 | Radon(F), |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
94 | /// $α\\|μ\\|\_{ℳ(Ω)} + δ_{≥ 0}(μ)$ |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
95 | NonnegRadon(F), |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
96 | } |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
97 | |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
98 | impl<'a, F : Float, const N : usize> Apply<&'a DiscreteMeasure<Loc<F, N>, F>> |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
99 | for Regularisation<F> { |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
100 | type Output = F; |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
101 | |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
102 | fn apply(&self, μ : &'a DiscreteMeasure<Loc<F, N>, F>) -> F { |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
103 | match *self { |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
104 | Self::Radon(α) => RadonRegTerm(α).apply(μ), |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
105 | Self::NonnegRadon(α) => NonnegRadonRegTerm(α).apply(μ), |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
106 | } |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
107 | } |
|
d29d1fcf5423
Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
108 | } |
| 32 | 109 | |
| 110 | /// Abstraction of regularisation terms for [`generic_pointsource_fb_reg`]. | |
| 111 | pub trait RegTerm<F : Float + ToNalgebraRealField, const N : usize> | |
| 112 | : for<'a> Apply<&'a DiscreteMeasure<Loc<F, N>, F>, Output = F> { | |
| 113 | /// Approximately solve the problem | |
| 114 | /// <div>$$ | |
| 115 | /// \min_{x ∈ ℝ^n} \frac{1}{2} x^⊤Ax - g^⊤ x + τ G(x) | |
| 116 | /// $$</div> | |
| 117 | /// for $G$ depending on the trait implementation. | |
| 118 | /// | |
| 119 | /// The parameter `mA` is $A$. An estimate for its opeator norm should be provided in | |
| 120 | /// `mA_normest`. The initial iterate and output is `x`. The current main tolerance is `ε`. | |
| 121 | /// | |
| 122 | /// Returns the number of iterations taken. | |
| 123 | fn solve_findim( | |
| 124 | &self, | |
| 125 | mA : &DMatrix<F::MixedType>, | |
| 126 | g : &DVector<F::MixedType>, | |
| 127 | τ : F, | |
| 128 | x : &mut DVector<F::MixedType>, | |
| 129 | mA_normest : F, | |
| 130 | ε : F, | |
| 131 | config : &FBGenericConfig<F> | |
| 132 | ) -> usize; | |
| 133 | ||
| 134 | /// Find a point where `d` may violate the tolerance `ε`. | |
| 135 | /// | |
| 136 | /// If `skip_by_rough_check` is set, do not find the point if a rough check indicates that we | |
| 137 | /// are in bounds. `ε` is the current main tolerance and `τ` a scaling factor for the | |
| 138 | /// regulariser. | |
| 139 | /// | |
| 140 | /// Returns `None` if `d` is in bounds either based on the rough check, or a more precise check | |
| 141 | /// terminating early. Otherwise returns a possibly violating point, the value of `d` there, | |
| 142 | /// and a boolean indicating whether the found point is in bounds. | |
| 143 | fn find_tolerance_violation<G, BT>( | |
| 144 | &self, | |
| 145 | d : &mut BTFN<F, G, BT, N>, | |
| 146 | τ : F, | |
| 147 | ε : F, | |
| 148 | skip_by_rough_check : bool, | |
| 149 | config : &FBGenericConfig<F>, | |
| 150 | ) -> Option<(Loc<F, N>, F, bool)> | |
| 151 | where BT : BTSearch<F, N, Agg=Bounds<F>>, | |
| 152 | G : SupportGenerator<F, N, Id=BT::Data>, | |
| 153 | G::SupportType : Mapping<Loc<F, N>,Codomain=F> | |
| 154 | + LocalAnalysis<F, Bounds<F>, N>; | |
| 155 | ||
| 156 | /// Verify that `d` is in bounds `ε` for a merge candidate `μ` | |
| 157 | /// | |
| 158 | /// `ε` is the current main tolerance and `τ` a scaling factor for the regulariser. | |
| 159 | fn verify_merge_candidate<G, BT>( | |
| 160 | &self, | |
| 161 | d : &mut BTFN<F, G, BT, N>, | |
| 162 | μ : &DiscreteMeasure<Loc<F, N>, F>, | |
| 163 | τ : F, | |
| 164 | ε : F, | |
| 165 | config : &FBGenericConfig<F>, | |
| 166 | ) -> bool | |
| 167 | where BT : BTSearch<F, N, Agg=Bounds<F>>, | |
| 168 | G : SupportGenerator<F, N, Id=BT::Data>, | |
| 169 | G::SupportType : Mapping<Loc<F, N>,Codomain=F> | |
| 170 | + LocalAnalysis<F, Bounds<F>, N>; | |
| 171 | ||
| 172 | /// TODO: document this | |
| 173 | fn target_bounds(&self, τ : F, ε : F) -> Option<Bounds<F>>; | |
| 174 | ||
| 175 | /// Returns a scaling factor for the tolerance sequence. | |
| 176 | /// | |
| 177 | /// Typically this is the regularisation parameter. | |
| 178 | fn tolerance_scaling(&self) -> F; | |
| 179 | } | |
| 180 | ||
| 181 | /// Abstraction of regularisation terms for [`pointsource_sliding_fb_reg`]. | |
| 182 | pub trait SlidingRegTerm<F : Float + ToNalgebraRealField, const N : usize> | |
| 183 | : RegTerm<F, N> { | |
| 184 | /// Calculate $τ[w(z) - w(y)]$ for some w in the subdifferential of the regularisation | |
| 185 | /// term, such that $-ε ≤ τw - d ≤ ε$. | |
| 186 | fn goodness<G, BT>( | |
| 187 | &self, | |
| 188 | d : &mut BTFN<F, G, BT, N>, | |
| 189 | μ : &DiscreteMeasure<Loc<F, N>, F>, | |
| 190 | y : &Loc<F, N>, | |
| 191 | z : &Loc<F, N>, | |
| 192 | τ : F, | |
| 193 | ε : F, | |
| 194 | config : &FBGenericConfig<F>, | |
| 195 | ) -> F | |
| 196 | where BT : BTSearch<F, N, Agg=Bounds<F>>, | |
| 197 | G : SupportGenerator<F, N, Id=BT::Data>, | |
| 198 | G::SupportType : Mapping<Loc<F, N>,Codomain=F> | |
| 199 | + LocalAnalysis<F, Bounds<F>, N>; | |
| 200 | } | |
| 201 | ||
| 202 | #[replace_float_literals(F::cast_from(literal))] | |
| 203 | impl<F : Float + ToNalgebraRealField, const N : usize> RegTerm<F, N> | |
| 204 | for NonnegRadonRegTerm<F> | |
| 205 | where Cube<F, N> : P2Minimise<Loc<F, N>, F> { | |
| 206 | fn solve_findim( | |
| 207 | &self, | |
| 208 | mA : &DMatrix<F::MixedType>, | |
| 209 | g : &DVector<F::MixedType>, | |
| 210 | τ : F, | |
| 211 | x : &mut DVector<F::MixedType>, | |
| 212 | mA_normest : F, | |
| 213 | ε : F, | |
| 214 | config : &FBGenericConfig<F> | |
| 215 | ) -> usize { | |
| 216 | let inner_tolerance = ε * config.inner.tolerance_mult; | |
| 217 | let inner_it = config.inner.iterator_options.stop_target(inner_tolerance); | |
| 218 | let inner_τ = config.inner.τ0 / mA_normest; | |
| 219 | quadratic_nonneg(config.inner.method, mA, g, τ * self.α(), x, | |
| 220 | inner_τ, inner_it) | |
| 221 | } | |
| 222 | ||
| 223 | #[inline] | |
| 224 | fn find_tolerance_violation<G, BT>( | |
| 225 | &self, | |
| 226 | d : &mut BTFN<F, G, BT, N>, | |
| 227 | τ : F, | |
| 228 | ε : F, | |
| 229 | skip_by_rough_check : bool, | |
| 230 | config : &FBGenericConfig<F>, | |
| 231 | ) -> Option<(Loc<F, N>, F, bool)> | |
| 232 | where BT : BTSearch<F, N, Agg=Bounds<F>>, | |
| 233 | G : SupportGenerator<F, N, Id=BT::Data>, | |
| 234 | G::SupportType : Mapping<Loc<F, N>,Codomain=F> | |
| 235 | + LocalAnalysis<F, Bounds<F>, N> { | |
| 236 | let τα = τ * self.α(); | |
| 237 | let keep_below = τα + ε; | |
| 238 | let maximise_above = τα + ε * config.insertion_cutoff_factor; | |
| 239 | let refinement_tolerance = ε * config.refinement.tolerance_mult; | |
| 240 | ||
| 241 | // If preliminary check indicates that we are in bonds, and if it otherwise matches | |
| 242 | // the insertion strategy, skip insertion. | |
| 243 | if skip_by_rough_check && d.bounds().upper() <= keep_below { | |
| 244 | None | |
| 245 | } else { | |
| 246 | // If the rough check didn't indicate no insertion needed, find maximising point. | |
| 247 | d.maximise_above(maximise_above, refinement_tolerance, config.refinement.max_steps) | |
| 248 | .map(|(ξ, v_ξ)| (ξ, v_ξ, v_ξ <= keep_below)) | |
| 249 | } | |
| 250 | } | |
| 251 | ||
| 252 | fn verify_merge_candidate<G, BT>( | |
| 253 | &self, | |
| 254 | d : &mut BTFN<F, G, BT, N>, | |
| 255 | μ : &DiscreteMeasure<Loc<F, N>, F>, | |
| 256 | τ : F, | |
| 257 | ε : F, | |
| 258 | config : &FBGenericConfig<F>, | |
| 259 | ) -> bool | |
| 260 | where BT : BTSearch<F, N, Agg=Bounds<F>>, | |
| 261 | G : SupportGenerator<F, N, Id=BT::Data>, | |
| 262 | G::SupportType : Mapping<Loc<F, N>,Codomain=F> | |
| 263 | + LocalAnalysis<F, Bounds<F>, N> { | |
| 264 | let τα = τ * self.α(); | |
| 265 | let refinement_tolerance = ε * config.refinement.tolerance_mult; | |
| 266 | let merge_tolerance = config.merge_tolerance_mult * ε; | |
| 267 | let keep_below = τα + merge_tolerance; | |
| 268 | let keep_supp_above = τα - merge_tolerance; | |
| 269 | let bnd = d.bounds(); | |
| 270 | ||
| 271 | return ( | |
| 272 | bnd.lower() >= keep_supp_above | |
| 273 | || | |
| 274 | μ.iter_spikes().map(|&DeltaMeasure{ α : β, ref x }| { | |
| 275 | (β == 0.0) || d.apply(x) >= keep_supp_above | |
| 276 | }).all(std::convert::identity) | |
| 277 | ) && ( | |
| 278 | bnd.upper() <= keep_below | |
| 279 | || | |
| 280 | d.has_upper_bound(keep_below, refinement_tolerance, config.refinement.max_steps) | |
| 281 | ) | |
| 282 | } | |
| 283 | ||
| 284 | fn target_bounds(&self, τ : F, ε : F) -> Option<Bounds<F>> { | |
| 285 | let τα = τ * self.α(); | |
| 286 | Some(Bounds(τα - ε, τα + ε)) | |
| 287 | } | |
| 288 | ||
| 289 | fn tolerance_scaling(&self) -> F { | |
| 290 | self.α() | |
| 291 | } | |
| 292 | } | |
| 293 | ||
| 294 | #[replace_float_literals(F::cast_from(literal))] | |
| 295 | impl<F : Float + ToNalgebraRealField, const N : usize> SlidingRegTerm<F, N> | |
| 296 | for NonnegRadonRegTerm<F> | |
| 297 | where Cube<F, N> : P2Minimise<Loc<F, N>, F> { | |
| 298 | ||
| 299 | fn goodness<G, BT>( | |
| 300 | &self, | |
| 301 | d : &mut BTFN<F, G, BT, N>, | |
| 302 | _μ : &DiscreteMeasure<Loc<F, N>, F>, | |
| 303 | y : &Loc<F, N>, | |
| 304 | z : &Loc<F, N>, | |
| 305 | τ : F, | |
| 306 | ε : F, | |
| 307 | _config : &FBGenericConfig<F>, | |
| 308 | ) -> F | |
| 309 | where BT : BTSearch<F, N, Agg=Bounds<F>>, | |
| 310 | G : SupportGenerator<F, N, Id=BT::Data>, | |
| 311 | G::SupportType : Mapping<Loc<F, N>,Codomain=F> | |
| 312 | + LocalAnalysis<F, Bounds<F>, N> { | |
| 313 | //let w = |x| 1.0.min((ε + d.apply(x))/(τ * self.α())); | |
| 314 | let τw = |x| τ.min((ε + d.apply(x))/self.α()); | |
| 315 | τw(z) - τw(y) | |
| 316 | } | |
| 317 | } | |
| 318 | ||
| 319 | #[replace_float_literals(F::cast_from(literal))] | |
| 320 | impl<F : Float + ToNalgebraRealField, const N : usize> RegTerm<F, N> for RadonRegTerm<F> | |
| 321 | where Cube<F, N> : P2Minimise<Loc<F, N>, F> { | |
| 322 | fn solve_findim( | |
| 323 | &self, | |
| 324 | mA : &DMatrix<F::MixedType>, | |
| 325 | g : &DVector<F::MixedType>, | |
| 326 | τ : F, | |
| 327 | x : &mut DVector<F::MixedType>, | |
| 328 | mA_normest: F, | |
| 329 | ε : F, | |
| 330 | config : &FBGenericConfig<F> | |
| 331 | ) -> usize { | |
| 332 | let inner_tolerance = ε * config.inner.tolerance_mult; | |
| 333 | let inner_it = config.inner.iterator_options.stop_target(inner_tolerance); | |
| 334 | let inner_τ = config.inner.τ0 / mA_normest; | |
| 335 | quadratic_unconstrained(config.inner.method, mA, g, τ * self.α(), x, | |
| 336 | inner_τ, inner_it) | |
| 337 | } | |
| 338 | ||
| 339 | fn find_tolerance_violation<G, BT>( | |
| 340 | &self, | |
| 341 | d : &mut BTFN<F, G, BT, N>, | |
| 342 | τ : F, | |
| 343 | ε : F, | |
| 344 | skip_by_rough_check : bool, | |
| 345 | config : &FBGenericConfig<F>, | |
| 346 | ) -> Option<(Loc<F, N>, F, bool)> | |
| 347 | where BT : BTSearch<F, N, Agg=Bounds<F>>, | |
| 348 | G : SupportGenerator<F, N, Id=BT::Data>, | |
| 349 | G::SupportType : Mapping<Loc<F, N>,Codomain=F> | |
| 350 | + LocalAnalysis<F, Bounds<F>, N> { | |
| 351 | let τα = τ * self.α(); | |
| 352 | let keep_below = τα + ε; | |
| 353 | let keep_above = -τα - ε; | |
| 354 | let maximise_above = τα + ε * config.insertion_cutoff_factor; | |
| 355 | let minimise_below = -τα - ε * config.insertion_cutoff_factor; | |
| 356 | let refinement_tolerance = ε * config.refinement.tolerance_mult; | |
| 357 | ||
| 358 | // If preliminary check indicates that we are in bonds, and if it otherwise matches | |
| 359 | // the insertion strategy, skip insertion. | |
| 360 | if skip_by_rough_check && Bounds(keep_above, keep_below).superset(&d.bounds()) { | |
| 361 | None | |
| 362 | } else { | |
| 363 | // If the rough check didn't indicate no insertion needed, find maximising point. | |
| 364 | let mx = d.maximise_above(maximise_above, refinement_tolerance, | |
| 365 | config.refinement.max_steps); | |
| 366 | let mi = d.minimise_below(minimise_below, refinement_tolerance, | |
| 367 | config.refinement.max_steps); | |
| 368 | ||
| 369 | match (mx, mi) { | |
| 370 | (None, None) => None, | |
| 371 | (Some((ξ, v_ξ)), None) => Some((ξ, v_ξ, keep_below >= v_ξ)), | |
| 372 | (None, Some((ζ, v_ζ))) => Some((ζ, v_ζ, keep_above <= v_ζ)), | |
| 373 | (Some((ξ, v_ξ)), Some((ζ, v_ζ))) => { | |
| 374 | if v_ξ - τα > τα - v_ζ { | |
| 375 | Some((ξ, v_ξ, keep_below >= v_ξ)) | |
| 376 | } else { | |
| 377 | Some((ζ, v_ζ, keep_above <= v_ζ)) | |
| 378 | } | |
| 379 | } | |
| 380 | } | |
| 381 | } | |
| 382 | } | |
| 383 | ||
| 384 | fn verify_merge_candidate<G, BT>( | |
| 385 | &self, | |
| 386 | d : &mut BTFN<F, G, BT, N>, | |
| 387 | μ : &DiscreteMeasure<Loc<F, N>, F>, | |
| 388 | τ : F, | |
| 389 | ε : F, | |
| 390 | config : &FBGenericConfig<F>, | |
| 391 | ) -> bool | |
| 392 | where BT : BTSearch<F, N, Agg=Bounds<F>>, | |
| 393 | G : SupportGenerator<F, N, Id=BT::Data>, | |
| 394 | G::SupportType : Mapping<Loc<F, N>,Codomain=F> | |
| 395 | + LocalAnalysis<F, Bounds<F>, N> { | |
| 396 | let τα = τ * self.α(); | |
| 397 | let refinement_tolerance = ε * config.refinement.tolerance_mult; | |
| 398 | let merge_tolerance = config.merge_tolerance_mult * ε; | |
| 399 | let keep_below = τα + merge_tolerance; | |
| 400 | let keep_above = -τα - merge_tolerance; | |
| 401 | let keep_supp_pos_above = τα - merge_tolerance; | |
| 402 | let keep_supp_neg_below = -τα + merge_tolerance; | |
| 403 | let bnd = d.bounds(); | |
| 404 | ||
| 405 | return ( | |
| 406 | (bnd.lower() >= keep_supp_pos_above && bnd.upper() <= keep_supp_neg_below) | |
| 407 | || | |
| 408 | μ.iter_spikes().map(|&DeltaMeasure{ α : β, ref x }| { | |
| 409 | use std::cmp::Ordering::*; | |
| 410 | match β.partial_cmp(&0.0) { | |
| 411 | Some(Greater) => d.apply(x) >= keep_supp_pos_above, | |
| 412 | Some(Less) => d.apply(x) <= keep_supp_neg_below, | |
| 413 | _ => true, | |
| 414 | } | |
| 415 | }).all(std::convert::identity) | |
| 416 | ) && ( | |
| 417 | bnd.upper() <= keep_below | |
| 418 | || | |
| 419 | d.has_upper_bound(keep_below, refinement_tolerance, | |
| 420 | config.refinement.max_steps) | |
| 421 | ) && ( | |
| 422 | bnd.lower() >= keep_above | |
| 423 | || | |
| 424 | d.has_lower_bound(keep_above, refinement_tolerance, | |
| 425 | config.refinement.max_steps) | |
| 426 | ) | |
| 427 | } | |
| 428 | ||
| 429 | fn target_bounds(&self, τ : F, ε : F) -> Option<Bounds<F>> { | |
| 430 | let τα = τ * self.α(); | |
| 431 | Some(Bounds(-τα - ε, τα + ε)) | |
| 432 | } | |
| 433 | ||
| 434 | fn tolerance_scaling(&self) -> F { | |
| 435 | self.α() | |
| 436 | } | |
| 437 | } | |
| 438 | ||
| 439 | #[replace_float_literals(F::cast_from(literal))] | |
| 440 | impl<F : Float + ToNalgebraRealField, const N : usize> SlidingRegTerm<F, N> | |
| 441 | for RadonRegTerm<F> | |
| 442 | where Cube<F, N> : P2Minimise<Loc<F, N>, F> { | |
| 443 | ||
| 444 | fn goodness<G, BT>( | |
| 445 | &self, | |
| 446 | d : &mut BTFN<F, G, BT, N>, | |
| 447 | _μ : &DiscreteMeasure<Loc<F, N>, F>, | |
| 448 | y : &Loc<F, N>, | |
| 449 | z : &Loc<F, N>, | |
| 450 | τ : F, | |
| 451 | ε : F, | |
| 452 | _config : &FBGenericConfig<F>, | |
| 453 | ) -> F | |
| 454 | where BT : BTSearch<F, N, Agg=Bounds<F>>, | |
| 455 | G : SupportGenerator<F, N, Id=BT::Data>, | |
| 456 | G::SupportType : Mapping<Loc<F, N>,Codomain=F> | |
| 457 | + LocalAnalysis<F, Bounds<F>, N> { | |
| 458 | ||
| 459 | let α = self.α(); | |
| 460 | // let w = |x| { | |
| 461 | // let dx = d.apply(x); | |
| 462 | // ((-ε + dx)/(τ * α)).max(1.0.min(ε + dx)/(τ * α)) | |
| 463 | // }; | |
| 464 | let τw = |x| { | |
| 465 | let dx = d.apply(x); | |
| 466 | ((-ε + dx)/α).max(τ.min(ε + dx)/α) | |
| 467 | }; | |
| 468 | τw(z) - τw(y) | |
| 469 | } | |
| 470 | } |