src/fb.rs

Tue, 31 Dec 2024 09:34:24 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Tue, 31 Dec 2024 09:34:24 -0500
branch
dev
changeset 32
56c8adc32b09
parent 29
87649ccfa6a8
child 34
efa60bc4f743
permissions
-rw-r--r--

Early transport sketches

0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1 /*!
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
2 Solver for the point source localisation problem using a forward-backward splitting method.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
3
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
4 This corresponds to the manuscript
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
5
13
bdc57366d4f5 arXiv links, README beautification
Tuomo Valkonen <tuomov@iki.fi>
parents: 8
diff changeset
6 * Valkonen T. - _Proximal methods for point source localisation_,
bdc57366d4f5 arXiv links, README beautification
Tuomo Valkonen <tuomov@iki.fi>
parents: 8
diff changeset
7 [arXiv:2212.02991](https://arxiv.org/abs/2212.02991).
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
8
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
9 The main routine is [`pointsource_fb_reg`]. It is based on [`generic_pointsource_fb_reg`], which is
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
10 also used by our [primal-dual proximal splitting][crate::pdps] implementation.
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
11
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
12 FISTA-type inertia can also be enabled through [`FBConfig::meta`].
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
13
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
14 ## Problem
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
15
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
16 <p>
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
17 Our objective is to solve
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
18 $$
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
19 \min_{μ ∈ ℳ(Ω)}~ F_0(Aμ-b) + α \|μ\|_{ℳ(Ω)} + δ_{≥ 0}(μ),
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
20 $$
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
21 where $F_0(y)=\frac{1}{2}\|y\|_2^2$ and the forward operator $A \in 𝕃(ℳ(Ω); ℝ^n)$.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
22 </p>
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
23
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
24 ## Approach
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
25
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
26 <p>
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
27 As documented in more detail in the paper, on each step we approximately solve
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
28 $$
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
29 \min_{μ ∈ ℳ(Ω)}~ F(x) + α \|μ\|_{ℳ(Ω)} + δ_{≥ 0}(x) + \frac{1}{2}\|μ-μ^k|_𝒟^2,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
30 $$
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
31 where $𝒟: 𝕃(ℳ(Ω); C_c(Ω))$ is typically a convolution operator.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
32 </p>
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
33
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
34 ## Finite-dimensional subproblems.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
35
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
36 With $C$ a projection from [`DiscreteMeasure`] to the weights, and $x^k$ such that $x^k=Cμ^k$, we
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
37 form the discretised linearised inner problem
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
38 <p>
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
39 $$
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
40 \min_{x ∈ ℝ^n}~ τ\bigl(F(Cx^k) + [C^*∇F(Cx^k)]^⊤(x-x^k) + α {\vec 1}^⊤ x\bigr)
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
41 + δ_{≥ 0}(x) + \frac{1}{2}\|x-x^k\|_{C^*𝒟C}^2,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
42 $$
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
43 equivalently
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
44 $$
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
45 \begin{aligned}
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
46 \min_x~ & τF(Cx^k) - τ[C^*∇F(Cx^k)]^⊤x^k + \frac{1}{2} (x^k)^⊤ C^*𝒟C x^k
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
47 \\
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
48 &
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
49 - [C^*𝒟C x^k - τC^*∇F(Cx^k)]^⊤ x
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
50 \\
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
51 &
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
52 + \frac{1}{2} x^⊤ C^*𝒟C x
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
53 + τα {\vec 1}^⊤ x + δ_{≥ 0}(x),
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
54 \end{aligned}
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
55 $$
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
56 In other words, we obtain the quadratic non-negativity constrained problem
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
57 $$
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
58 \min_{x ∈ ℝ^n}~ \frac{1}{2} x^⊤ Ã x - b̃^⊤ x + c + τα {\vec 1}^⊤ x + δ_{≥ 0}(x).
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
59 $$
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
60 where
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
61 $$
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
62 \begin{aligned}
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
63 Ã & = C^*𝒟C,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
64 \\
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
65 g̃ & = C^*𝒟C x^k - τ C^*∇F(Cx^k)
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
66 = C^* 𝒟 μ^k - τ C^*A^*(Aμ^k - b)
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
67 \\
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
68 c & = τ F(Cx^k) - τ[C^*∇F(Cx^k)]^⊤x^k + \frac{1}{2} (x^k)^⊤ C^*𝒟C x^k
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
69 \\
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
70 &
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
71 = \frac{τ}{2} \|Aμ^k-b\|^2 - τ[Aμ^k-b]^⊤Aμ^k + \frac{1}{2} \|μ_k\|_{𝒟}^2
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
72 \\
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
73 &
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
74 = -\frac{τ}{2} \|Aμ^k-b\|^2 + τ[Aμ^k-b]^⊤ b + \frac{1}{2} \|μ_k\|_{𝒟}^2.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
75 \end{aligned}
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
76 $$
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
77 </p>
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
78
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
79 We solve this with either SSN or FB via [`quadratic_nonneg`] as determined by
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
80 [`InnerSettings`] in [`FBGenericConfig::inner`].
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
81 */
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
82
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
83 use numeric_literals::replace_float_literals;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
84 use serde::{Serialize, Deserialize};
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
85 use colored::Colorize;
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
86 use nalgebra::DVector;
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
87
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
88 use alg_tools::iterate::{
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
89 AlgIteratorFactory,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
90 AlgIteratorState,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
91 };
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
92 use alg_tools::euclidean::Euclidean;
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
93 use alg_tools::linops::{Apply, GEMV};
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
94 use alg_tools::sets::Cube;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
95 use alg_tools::loc::Loc;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
96 use alg_tools::bisection_tree::{
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
97 BTFN,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
98 PreBTFN,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
99 Bounds,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
100 BTNodeLookup,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
101 BTNode,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
102 BTSearch,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
103 P2Minimise,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
104 SupportGenerator,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
105 LocalAnalysis,
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
106 BothGenerators,
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
107 };
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
108 use alg_tools::mapping::RealMapping;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
109 use alg_tools::nalgebra_support::ToNalgebraRealField;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
110
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
111 use crate::types::*;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
112 use crate::measures::{
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
113 DiscreteMeasure,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
114 DeltaMeasure,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
115 };
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
116 use crate::measures::merging::{
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
117 SpikeMergingMethod,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
118 SpikeMerging,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
119 };
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
120 use crate::forward_model::ForwardModel;
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
121 use crate::seminorms::DiscreteMeasureOp;
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
122 use crate::subproblem::{
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
123 InnerSettings,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
124 InnerMethod,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
125 };
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
126 use crate::tolerance::Tolerance;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
127 use crate::plot::{
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
128 SeqPlotter,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
129 Plotting,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
130 PlotLookup
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
131 };
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
132 use crate::regularisation::RegTerm;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
133 use crate::dataterm::{
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
134 calculate_residual,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
135 L2Squared,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
136 DataTerm,
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
137 };
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
138
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
139 /// Method for constructing $μ$ on each iteration
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
140 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
141 #[allow(dead_code)]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
142 pub enum InsertionStyle {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
143 /// Resuse previous $μ$ from previous iteration, optimising weights
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
144 /// before inserting new spikes.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
145 Reuse,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
146 /// Start each iteration with $μ=0$.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
147 Zero,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
148 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
149
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
150 /// Settings for [`pointsource_fb_reg`].
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
151 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
152 #[serde(default)]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
153 pub struct FBConfig<F : Float> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
154 /// Step length scaling
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
155 pub τ0 : F,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
156 /// Generic parameters
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
157 pub insertion : FBGenericConfig<F>,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
158 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
159
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
160 /// Settings for the solution of the stepwise optimality condition in algorithms based on
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
161 /// [`generic_pointsource_fb_reg`].
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
162 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
163 #[serde(default)]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
164 pub struct FBGenericConfig<F : Float> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
165 /// Method for constructing $μ$ on each iteration; see [`InsertionStyle`].
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
166 pub insertion_style : InsertionStyle,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
167 /// Tolerance for point insertion.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
168 pub tolerance : Tolerance<F>,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
169 /// Stop looking for predual maximum (where to isert a new point) below
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
170 /// `tolerance` multiplied by this factor.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
171 pub insertion_cutoff_factor : F,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
172 /// Settings for branch and bound refinement when looking for predual maxima
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
173 pub refinement : RefinementSettings<F>,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
174 /// Maximum insertions within each outer iteration
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
175 pub max_insertions : usize,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
176 /// Pair `(n, m)` for maximum insertions `m` on first `n` iterations.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
177 pub bootstrap_insertions : Option<(usize, usize)>,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
178 /// Inner method settings
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
179 pub inner : InnerSettings<F>,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
180 /// Spike merging method
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
181 pub merging : SpikeMergingMethod<F>,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
182 /// Tolerance multiplier for merges
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
183 pub merge_tolerance_mult : F,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
184 /// Spike merging method after the last step
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
185 pub final_merging : SpikeMergingMethod<F>,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
186 /// Iterations between merging heuristic tries
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
187 pub merge_every : usize,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
188 /// Save $μ$ for postprocessing optimisation
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
189 pub postprocessing : bool
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
190 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
191
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
192 #[replace_float_literals(F::cast_from(literal))]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
193 impl<F : Float> Default for FBConfig<F> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
194 fn default() -> Self {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
195 FBConfig {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
196 τ0 : 0.99,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
197 insertion : Default::default()
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
198 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
199 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
200 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
201
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
202 #[replace_float_literals(F::cast_from(literal))]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
203 impl<F : Float> Default for FBGenericConfig<F> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
204 fn default() -> Self {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
205 FBGenericConfig {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
206 insertion_style : InsertionStyle::Reuse,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
207 tolerance : Default::default(),
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
208 insertion_cutoff_factor : 1.0,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
209 refinement : Default::default(),
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
210 max_insertions : 100,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
211 //bootstrap_insertions : None,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
212 bootstrap_insertions : Some((10, 1)),
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
213 inner : InnerSettings {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
214 method : InnerMethod::SSN,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
215 .. Default::default()
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
216 },
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
217 merging : SpikeMergingMethod::None,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
218 //merging : Default::default(),
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
219 final_merging : Default::default(),
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
220 merge_every : 10,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
221 merge_tolerance_mult : 2.0,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
222 postprocessing : false,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
223 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
224 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
225 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
226
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
227 #[replace_float_literals(F::cast_from(literal))]
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
228 pub(crate) fn μ_diff<F : Float, const N : usize>(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
229 μ_new : &DiscreteMeasure<Loc<F, N>, F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
230 μ_base : &DiscreteMeasure<Loc<F, N>, F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
231 ν_delta : Option<&DiscreteMeasure<Loc<F, N>, F>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
232 config : &FBGenericConfig<F>
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
233 ) -> DiscreteMeasure<Loc<F, N>, F> {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
234 let mut ν : DiscreteMeasure<Loc<F, N>, F> = match config.insertion_style {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
235 InsertionStyle::Reuse => {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
236 μ_new.iter_spikes()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
237 .zip(μ_base.iter_masses().chain(std::iter::repeat(0.0)))
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
238 .map(|(δ, α_base)| (δ.x, α_base - δ.α))
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
239 .collect()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
240 },
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
241 InsertionStyle::Zero => {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
242 μ_new.iter_spikes()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
243 .map(|δ| -δ)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
244 .chain(μ_base.iter_spikes().copied())
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
245 .collect()
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
246 }
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
247 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
248 ν.prune(); // Potential small performance improvement
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
249 // Add ν_delta if given
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
250 match ν_delta {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
251 None => ν,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
252 Some(ν_d) => ν + ν_d,
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
253 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
254 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
255
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
256 #[replace_float_literals(F::cast_from(literal))]
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
257 pub(crate) fn insert_and_reweigh<
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
258 'a, F, GA, 𝒟, BTA, G𝒟, S, K, Reg, State, const N : usize
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
259 >(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
260 μ : &mut DiscreteMeasure<Loc<F, N>, F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
261 minus_τv : &BTFN<F, GA, BTA, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
262 μ_base : &DiscreteMeasure<Loc<F, N>, F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
263 ν_delta: Option<&DiscreteMeasure<Loc<F, N>, F>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
264 op𝒟 : &'a 𝒟,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
265 op𝒟norm : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
266 τ : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
267 ε : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
268 config : &FBGenericConfig<F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
269 reg : &Reg,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
270 state : &State,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
271 stats : &mut IterInfo<F, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
272 ) -> (BTFN<F, BothGenerators<GA, G𝒟>, BTA, N>, bool)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
273 where F : Float + ToNalgebraRealField,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
274 GA : SupportGenerator<F, N, SupportType = S, Id = usize> + Clone,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
275 BTA : BTSearch<F, N, Data=usize, Agg=Bounds<F>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
276 G𝒟 : SupportGenerator<F, N, SupportType = K, Id = usize> + Clone,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
277 𝒟 : DiscreteMeasureOp<Loc<F, N>, F, PreCodomain = PreBTFN<F, G𝒟, N>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
278 𝒟::Codomain : RealMapping<F, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
279 S: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
280 K: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
281 BTNodeLookup: BTNode<F, usize, Bounds<F>, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
282 DiscreteMeasure<Loc<F, N>, F> : SpikeMerging<F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
283 Reg : RegTerm<F, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
284 State : AlgIteratorState {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
285
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
286 // Maximum insertion count and measure difference calculation depend on insertion style.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
287 let (m, warn_insertions) = match (state.iteration(), config.bootstrap_insertions) {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
288 (i, Some((l, k))) if i <= l => (k, false),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
289 _ => (config.max_insertions, !state.is_quiet()),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
290 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
291 let max_insertions = match config.insertion_style {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
292 InsertionStyle::Zero => {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
293 todo!("InsertionStyle::Zero does not currently work with FISTA, so diabled.");
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
294 // let n = μ.len();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
295 // μ = DiscreteMeasure::new();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
296 // n + m
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
297 },
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
298 InsertionStyle::Reuse => m,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
299 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
300
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
301 // TODO: should avoid a second copy of μ here; μ_base already stores a copy.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
302 let ω0 = op𝒟.apply(match ν_delta {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
303 None => μ.clone(),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
304 Some(ν_d) => &*μ + ν_d,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
305 });
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
306
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
307 // Add points to support until within error tolerance or maximum insertion count reached.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
308 let mut count = 0;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
309 let (within_tolerances, d) = 'insertion: loop {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
310 if μ.len() > 0 {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
311 // Form finite-dimensional subproblem. The subproblem references to the original μ^k
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
312 // from the beginning of the iteration are all contained in the immutable c and g.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
313 let à = op𝒟.findim_matrix(μ.iter_locations());
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
314 let g̃ = DVector::from_iterator(μ.len(),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
315 μ.iter_locations()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
316 .map(|ζ| minus_τv.apply(ζ) + ω0.apply(ζ))
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
317 .map(F::to_nalgebra_mixed));
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
318 let mut x = μ.masses_dvector();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
319
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
320 // The gradient of the forward component of the inner objective is C^*𝒟Cx - g̃.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
321 // We have |C^*𝒟Cx|_2 = sup_{|z|_2 ≤ 1} ⟨z, C^*𝒟Cx⟩ = sup_{|z|_2 ≤ 1} ⟨Cz|𝒟Cx⟩
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
322 // ≤ sup_{|z|_2 ≤ 1} |Cz|_ℳ |𝒟Cx|_∞ ≤ sup_{|z|_2 ≤ 1} |Cz|_ℳ |𝒟| |Cx|_ℳ
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
323 // ≤ sup_{|z|_2 ≤ 1} |z|_1 |𝒟| |x|_1 ≤ sup_{|z|_2 ≤ 1} n |z|_2 |𝒟| |x|_2
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
324 // = n |𝒟| |x|_2, where n is the number of points. Therefore
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
325 let Ã_normest = op𝒟norm * F::cast_from(μ.len());
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
326
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
327 // Solve finite-dimensional subproblem.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
328 stats.inner_iters += reg.solve_findim(&Ã, &g̃, τ, &mut x, Ã_normest, ε, config);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
329
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
330 // Update masses of μ based on solution of finite-dimensional subproblem.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
331 μ.set_masses_dvector(&x);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
332 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
333
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
334 // Form d = ω0 - τv - 𝒟μ = -𝒟(μ - μ^k) - τv for checking the proximate optimality
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
335 // conditions in the predual space, and finding new points for insertion, if necessary.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
336 let mut d = minus_τv + op𝒟.preapply(μ_diff(μ, μ_base, ν_delta, config));
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
337
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
338 // If no merging heuristic is used, let's be more conservative about spike insertion,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
339 // and skip it after first round. If merging is done, being more greedy about spike
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
340 // insertion also seems to improve performance.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
341 let skip_by_rough_check = if let SpikeMergingMethod::None = config.merging {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
342 false
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
343 } else {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
344 count > 0
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
345 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
346
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
347 // Find a spike to insert, if needed
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
348 let (ξ, _v_ξ, in_bounds) = match reg.find_tolerance_violation(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
349 &mut d, τ, ε, skip_by_rough_check, config
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
350 ) {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
351 None => break 'insertion (true, d),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
352 Some(res) => res,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
353 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
354
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
355 // Break if maximum insertion count reached
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
356 if count >= max_insertions {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
357 break 'insertion (in_bounds, d)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
358 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
359
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
360 // No point in optimising the weight here; the finite-dimensional algorithm is fast.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
361 *μ += DeltaMeasure { x : ξ, α : 0.0 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
362 count += 1;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
363 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
364
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
365 // TODO: should redo everything if some transports cause a problem.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
366 // Maybe implementation should call above loop as a closure.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
367
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
368 if !within_tolerances && warn_insertions {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
369 // Complain (but continue) if we failed to get within tolerances
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
370 // by inserting more points.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
371 let err = format!("Maximum insertions reached without achieving \
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
372 subproblem solution tolerance");
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
373 println!("{}", err.red());
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
374 }
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
375
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
376 (d, within_tolerances)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
377 }
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
378
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
379 #[replace_float_literals(F::cast_from(literal))]
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
380 pub(crate) fn prune_and_maybe_simple_merge<
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
381 'a, F, GA, 𝒟, BTA, G𝒟, S, K, Reg, State, const N : usize
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
382 >(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
383 μ : &mut DiscreteMeasure<Loc<F, N>, F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
384 minus_τv : &BTFN<F, GA, BTA, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
385 μ_base : &DiscreteMeasure<Loc<F, N>, F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
386 op𝒟 : &'a 𝒟,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
387 τ : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
388 ε : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
389 config : &FBGenericConfig<F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
390 reg : &Reg,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
391 state : &State,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
392 stats : &mut IterInfo<F, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
393 )
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
394 where F : Float + ToNalgebraRealField,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
395 GA : SupportGenerator<F, N, SupportType = S, Id = usize> + Clone,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
396 BTA : BTSearch<F, N, Data=usize, Agg=Bounds<F>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
397 G𝒟 : SupportGenerator<F, N, SupportType = K, Id = usize> + Clone,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
398 𝒟 : DiscreteMeasureOp<Loc<F, N>, F, PreCodomain = PreBTFN<F, G𝒟, N>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
399 𝒟::Codomain : RealMapping<F, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
400 S: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
401 K: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
402 BTNodeLookup: BTNode<F, usize, Bounds<F>, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
403 DiscreteMeasure<Loc<F, N>, F> : SpikeMerging<F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
404 Reg : RegTerm<F, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
405 State : AlgIteratorState {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
406 if state.iteration() % config.merge_every == 0 {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
407 let n_before_merge = μ.len();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
408 μ.merge_spikes(config.merging, |μ_candidate| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
409 let μd = μ_diff(&μ_candidate, &μ_base, None, config);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
410 let mut d = minus_τv + op𝒟.preapply(μd);
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
411
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
412 reg.verify_merge_candidate(&mut d, μ_candidate, τ, ε, &config)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
413 .then_some(())
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
414 });
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
415 debug_assert!(μ.len() >= n_before_merge);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
416 stats.merged += μ.len() - n_before_merge;
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
417 }
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
418
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
419 let n_before_prune = μ.len();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
420 μ.prune();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
421 debug_assert!(μ.len() <= n_before_prune);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
422 stats.pruned += n_before_prune - μ.len();
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
423 }
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
424
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
425 #[replace_float_literals(F::cast_from(literal))]
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
426 pub(crate) fn postprocess<
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
427 F : Float,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
428 V : Euclidean<F> + Clone,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
429 A : GEMV<F, DiscreteMeasure<Loc<F, N>, F>, Codomain = V>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
430 D : DataTerm<F, V, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
431 const N : usize
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
432 > (
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
433 mut μ : DiscreteMeasure<Loc<F, N>, F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
434 config : &FBGenericConfig<F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
435 dataterm : D,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
436 opA : &A,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
437 b : &V,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
438 ) -> DiscreteMeasure<Loc<F, N>, F>
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
439 where DiscreteMeasure<Loc<F, N>, F> : SpikeMerging<F> {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
440 μ.merge_spikes_fitness(config.merging,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
441 |μ̃| dataterm.calculate_fit_op(μ̃, opA, b),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
442 |&v| v);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
443 μ.prune();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
444 μ
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
445 }
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
446
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
447 /// Iteratively solve the pointsource localisation problem using forward-backward splitting.
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
448 ///
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
449 /// The settings in `config` have their [respective documentation](FBConfig). `opA` is the
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
450 /// forward operator $A$, $b$ the observable, and $\lambda$ the regularisation weight.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
451 /// The operator `op𝒟` is used for forming the proximal term. Typically it is a convolution
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
452 /// operator. Finally, the `iterator` is an outer loop verbosity and iteration count control
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
453 /// as documented in [`alg_tools::iterate`].
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
454 ///
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
455 /// For details on the mathematical formulation, see the [module level](self) documentation.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
456 ///
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
457 /// The implementation relies on [`alg_tools::bisection_tree::BTFN`] presentations of
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
458 /// sums of simple functions usign bisection trees, and the related
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
459 /// [`alg_tools::bisection_tree::Aggregator`]s, to efficiently search for component functions
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
460 /// active at a specific points, and to maximise their sums. Through the implementation of the
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
461 /// [`alg_tools::bisection_tree::BT`] bisection trees, it also relies on the copy-on-write features
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
462 /// of [`std::sync::Arc`] to only update relevant parts of the bisection tree when adding functions.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
463 ///
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
464 /// Returns the final iterate.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
465 #[replace_float_literals(F::cast_from(literal))]
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
466 pub fn pointsource_fb_reg<
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
467 'a, F, I, A, GA, 𝒟, BTA, G𝒟, S, K, Reg, const N : usize
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
468 >(
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
469 opA : &'a A,
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
470 b : &A::Observable,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
471 reg : Reg,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
472 op𝒟 : &'a 𝒟,
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
473 fbconfig : &FBConfig<F>,
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
474 iterator : I,
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
475 mut plotter : SeqPlotter<F, N>,
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
476 ) -> DiscreteMeasure<Loc<F, N>, F>
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
477 where F : Float + ToNalgebraRealField,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
478 I : AlgIteratorFactory<IterInfo<F, N>>,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
479 for<'b> &'b A::Observable : std::ops::Neg<Output=A::Observable>,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
480 //+ std::ops::Mul<F, Output=A::Observable>, <-- FIXME: compiler overflow
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
481 A::Observable : std::ops::MulAssign<F>,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
482 GA : SupportGenerator<F, N, SupportType = S, Id = usize> + Clone,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
483 A : ForwardModel<Loc<F, N>, F, PreadjointCodomain = BTFN<F, GA, BTA, N>>
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
484 + Lipschitz<&'a 𝒟, FloatType=F>,
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
485 BTA : BTSearch<F, N, Data=usize, Agg=Bounds<F>>,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
486 G𝒟 : SupportGenerator<F, N, SupportType = K, Id = usize> + Clone,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
487 𝒟 : DiscreteMeasureOp<Loc<F, N>, F, PreCodomain = PreBTFN<F, G𝒟, N>>,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
488 𝒟::Codomain : RealMapping<F, N>,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
489 S: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
490 K: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
491 BTNodeLookup: BTNode<F, usize, Bounds<F>, N>,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
492 Cube<F, N>: P2Minimise<Loc<F, N>, F>,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
493 PlotLookup : Plotting<N>,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
494 DiscreteMeasure<Loc<F, N>, F> : SpikeMerging<F>,
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
495 Reg : RegTerm<F, N> {
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
496
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
497 // Set up parameters
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
498 let config = &fbconfig.insertion;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
499 let op𝒟norm = op𝒟.opnorm_bound();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
500 let τ = fbconfig.τ0/opA.lipschitz_factor(&op𝒟).unwrap();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
501 // We multiply tolerance by τ for FB since our subproblems depending on tolerances are scaled
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
502 // by τ compared to the conditional gradient approach.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
503 let tolerance = config.tolerance * τ * reg.tolerance_scaling();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
504 let mut ε = tolerance.initial();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
505
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
506 // Initialise iterates
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
507 let mut μ = DiscreteMeasure::new();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
508 let mut residual = -b;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
509 let mut stats = IterInfo::new();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
510
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
511 // Run the algorithm
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
512 iterator.iterate(|state| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
513 // Calculate smooth part of surrogate model.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
514 // Using `std::mem::replace` here is not ideal, and expects that `empty_observable`
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
515 // has no significant overhead. For some reosn Rust doesn't allow us simply moving
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
516 // the residual and replacing it below before the end of this closure.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
517 residual *= -τ;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
518 let r = std::mem::replace(&mut residual, opA.empty_observable());
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
519 let minus_τv = opA.preadjoint().apply(r);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
520
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
521 // Save current base point
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
522 let μ_base = μ.clone();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
523
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
524 // Insert and reweigh
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
525 let (d, within_tolerances) = insert_and_reweigh(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
526 &mut μ, &minus_τv, &μ_base, None,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
527 op𝒟, op𝒟norm,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
528 τ, ε,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
529 config, &reg, state, &mut stats
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
530 );
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
531
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
532 // Prune and possibly merge spikes
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
533 prune_and_maybe_simple_merge(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
534 &mut μ, &minus_τv, &μ_base,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
535 op𝒟,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
536 τ, ε,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
537 config, &reg, state, &mut stats
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
538 );
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
539
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
540 // Update residual
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
541 residual = calculate_residual(&μ, opA, b);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
542
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
543 // Update main tolerance for next iteration
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
544 let ε_prev = ε;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
545 ε = tolerance.update(ε, state.iteration());
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
546 stats.this_iters += 1;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
547
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
548 // Give function value if needed
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
549 state.if_verbose(|| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
550 // Plot if so requested
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
551 plotter.plot_spikes(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
552 format!("iter {} end; {}", state.iteration(), within_tolerances), &d,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
553 "start".to_string(), Some(&minus_τv),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
554 reg.target_bounds(τ, ε_prev), &μ,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
555 );
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
556 // Calculate mean inner iterations and reset relevant counters.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
557 // Return the statistics
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
558 let res = IterInfo {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
559 value : residual.norm2_squared_div2() + reg.apply(&μ),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
560 n_spikes : μ.len(),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
561 ε : ε_prev,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
562 postprocessing: config.postprocessing.then(|| μ.clone()),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
563 .. stats
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
564 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
565 stats = IterInfo::new();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
566 res
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
567 })
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
568 });
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
569
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
570 postprocess(μ, config, L2Squared, opA, b)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
571 }
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
572
32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
573 /// Iteratively solve the pointsource localisation problem using inertial forward-backward splitting.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
574 ///
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
575 /// The settings in `config` have their [respective documentation](FBConfig). `opA` is the
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
576 /// forward operator $A$, $b$ the observable, and $\lambda$ the regularisation weight.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
577 /// The operator `op𝒟` is used for forming the proximal term. Typically it is a convolution
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
578 /// operator. Finally, the `iterator` is an outer loop verbosity and iteration count control
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
579 /// as documented in [`alg_tools::iterate`].
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
580 ///
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
581 /// For details on the mathematical formulation, see the [module level](self) documentation.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
582 ///
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
583 /// The implementation relies on [`alg_tools::bisection_tree::BTFN`] presentations of
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
584 /// sums of simple functions usign bisection trees, and the related
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
585 /// [`alg_tools::bisection_tree::Aggregator`]s, to efficiently search for component functions
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
586 /// active at a specific points, and to maximise their sums. Through the implementation of the
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
587 /// [`alg_tools::bisection_tree::BT`] bisection trees, it also relies on the copy-on-write features
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
588 /// of [`std::sync::Arc`] to only update relevant parts of the bisection tree when adding functions.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
589 ///
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
590 /// Returns the final iterate.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
591 #[replace_float_literals(F::cast_from(literal))]
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
592 pub fn pointsource_fista_reg<
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
593 'a, F, I, A, GA, 𝒟, BTA, G𝒟, S, K, Reg, const N : usize
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
594 >(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
595 opA : &'a A,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
596 b : &A::Observable,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
597 reg : Reg,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
598 op𝒟 : &'a 𝒟,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
599 fbconfig : &FBConfig<F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
600 iterator : I,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
601 mut plotter : SeqPlotter<F, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
602 ) -> DiscreteMeasure<Loc<F, N>, F>
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
603 where F : Float + ToNalgebraRealField,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
604 I : AlgIteratorFactory<IterInfo<F, N>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
605 for<'b> &'b A::Observable : std::ops::Neg<Output=A::Observable>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
606 //+ std::ops::Mul<F, Output=A::Observable>, <-- FIXME: compiler overflow
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
607 A::Observable : std::ops::MulAssign<F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
608 GA : SupportGenerator<F, N, SupportType = S, Id = usize> + Clone,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
609 A : ForwardModel<Loc<F, N>, F, PreadjointCodomain = BTFN<F, GA, BTA, N>>
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
610 + Lipschitz<&'a 𝒟, FloatType=F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
611 BTA : BTSearch<F, N, Data=usize, Agg=Bounds<F>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
612 G𝒟 : SupportGenerator<F, N, SupportType = K, Id = usize> + Clone,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
613 𝒟 : DiscreteMeasureOp<Loc<F, N>, F, PreCodomain = PreBTFN<F, G𝒟, N>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
614 𝒟::Codomain : RealMapping<F, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
615 S: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
616 K: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
617 BTNodeLookup: BTNode<F, usize, Bounds<F>, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
618 Cube<F, N>: P2Minimise<Loc<F, N>, F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
619 PlotLookup : Plotting<N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
620 DiscreteMeasure<Loc<F, N>, F> : SpikeMerging<F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
621 Reg : RegTerm<F, N> {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
622
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
623 // Set up parameters
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
624 let config = &fbconfig.insertion;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
625 let op𝒟norm = op𝒟.opnorm_bound();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
626 let τ = fbconfig.τ0/opA.lipschitz_factor(&op𝒟).unwrap();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
627 let mut λ = 1.0;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
628 // We multiply tolerance by τ for FB since our subproblems depending on tolerances are scaled
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
629 // by τ compared to the conditional gradient approach.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
630 let tolerance = config.tolerance * τ * reg.tolerance_scaling();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
631 let mut ε = tolerance.initial();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
632
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
633 // Initialise iterates
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
634 let mut μ = DiscreteMeasure::new();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
635 let mut μ_prev = DiscreteMeasure::new();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
636 let mut residual = -b;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
637 let mut stats = IterInfo::new();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
638 let mut warned_merging = false;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
639
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
640 // Run the algorithm
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
641 iterator.iterate(|state| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
642 // Calculate smooth part of surrogate model.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
643 // Using `std::mem::replace` here is not ideal, and expects that `empty_observable`
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
644 // has no significant overhead. For some reosn Rust doesn't allow us simply moving
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
645 // the residual and replacing it below before the end of this closure.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
646 residual *= -τ;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
647 let r = std::mem::replace(&mut residual, opA.empty_observable());
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
648 let minus_τv = opA.preadjoint().apply(r);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
649
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
650 // Save current base point
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
651 let μ_base = μ.clone();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
652
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
653 // Insert new spikes and reweigh
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
654 let (d, within_tolerances) = insert_and_reweigh(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
655 &mut μ, &minus_τv, &μ_base, None,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
656 op𝒟, op𝒟norm,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
657 τ, ε,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
658 config, &reg, state, &mut stats
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
659 );
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
660
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
661 // (Do not) merge spikes.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
662 if state.iteration() % config.merge_every == 0 {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
663 match config.merging {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
664 SpikeMergingMethod::None => { },
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
665 _ => if !warned_merging {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
666 let err = format!("Merging not supported for μFISTA");
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
667 println!("{}", err.red());
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
668 warned_merging = true;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
669 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
670 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
671 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
672
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
673 // Update inertial prameters
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
674 let λ_prev = λ;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
675 λ = 2.0 * λ_prev / ( λ_prev + (4.0 + λ_prev * λ_prev).sqrt() );
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
676 let θ = λ / λ_prev - λ;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
677
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
678 // Perform inertial update on μ.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
679 // This computes μ ← (1 + θ) * μ - θ * μ_prev, pruning spikes where both μ
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
680 // and μ_prev have zero weight. Since both have weights from the finite-dimensional
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
681 // subproblem with a proximal projection step, this is likely to happen when the
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
682 // spike is not needed. A copy of the pruned μ without artithmetic performed is
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
683 // stored in μ_prev.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
684 let n_before_prune = μ.len();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
685 μ.pruning_sub(1.0 + θ, θ, &mut μ_prev);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
686 debug_assert!(μ.len() <= n_before_prune);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
687 stats.pruned += n_before_prune - μ.len();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
688
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
689 // Update residual
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
690 residual = calculate_residual(&μ, opA, b);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
691
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
692 // Update main tolerance for next iteration
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
693 let ε_prev = ε;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
694 ε = tolerance.update(ε, state.iteration());
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
695 stats.this_iters += 1;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
696
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
697 // Give function value if needed
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
698 state.if_verbose(|| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
699 // Plot if so requested
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
700 plotter.plot_spikes(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
701 format!("iter {} end; {}", state.iteration(), within_tolerances), &d,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
702 "start".to_string(), Some(&minus_τv),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
703 reg.target_bounds(τ, ε_prev), &μ_prev,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
704 );
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
705 // Calculate mean inner iterations and reset relevant counters.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
706 // Return the statistics
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
707 let res = IterInfo {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
708 value : L2Squared.calculate_fit_op(&μ_prev, opA, b) + reg.apply(&μ_prev),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
709 n_spikes : μ_prev.len(),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
710 ε : ε_prev,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
711 postprocessing: config.postprocessing.then(|| μ_prev.clone()),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
712 .. stats
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
713 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
714 stats = IterInfo::new();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
715 res
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
716 })
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
717 });
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
718
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents: 29
diff changeset
719 postprocess(μ_prev, config, L2Squared, opA, b)
24
d29d1fcf5423 Support arbitrary regularisation terms; implement non-positivity-constrained regularisation.
Tuomo Valkonen <tuomov@iki.fi>
parents: 13
diff changeset
720 }

mercurial