src/sliding_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
child 34
efa60bc4f743
permissions
-rw-r--r--

Early transport sketches

32
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1 /*!
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
2 Solver for the point source localisation problem using a sliding
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
3 forward-backward splitting method.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
4 */
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
5
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
6 use numeric_literals::replace_float_literals;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
7 use serde::{Serialize, Deserialize};
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
8 //use colored::Colorize;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
9 //use nalgebra::{DVector, DMatrix};
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
10 use itertools::izip;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
11 use std::iter::{Map, Flatten};
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
12
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
13 use alg_tools::iterate::{
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
14 AlgIteratorFactory,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
15 AlgIteratorState
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
16 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
17 use alg_tools::euclidean::{
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
18 Euclidean,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
19 Dot
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
20 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
21 use alg_tools::sets::Cube;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
22 use alg_tools::loc::Loc;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
23 use alg_tools::mapping::{Apply, Differentiable};
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
24 use alg_tools::bisection_tree::{
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
25 BTFN,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
26 PreBTFN,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
27 Bounds,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
28 BTNodeLookup,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
29 BTNode,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
30 BTSearch,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
31 P2Minimise,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
32 SupportGenerator,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
33 LocalAnalysis,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
34 //Bounded,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
35 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
36 use alg_tools::mapping::RealMapping;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
37 use alg_tools::nalgebra_support::ToNalgebraRealField;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
38
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
39 use crate::types::*;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
40 use crate::measures::{
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
41 DiscreteMeasure,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
42 DeltaMeasure,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
43 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
44 use crate::measures::merging::{
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
45 //SpikeMergingMethod,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
46 SpikeMerging,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
47 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
48 use crate::forward_model::ForwardModel;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
49 use crate::seminorms::DiscreteMeasureOp;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
50 //use crate::tolerance::Tolerance;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
51 use crate::plot::{
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
52 SeqPlotter,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
53 Plotting,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
54 PlotLookup
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
55 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
56 use crate::fb::*;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
57 use crate::regularisation::SlidingRegTerm;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
58 use crate::dataterm::{
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
59 L2Squared,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
60 //DataTerm,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
61 calculate_residual,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
62 calculate_residual2,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
63 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
64 use crate::transport::TransportLipschitz;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
65
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
66 /// Settings for [`pointsource_sliding_fb_reg`].
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
67 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)]
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
68 #[serde(default)]
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
69 pub struct SlidingFBConfig<F : Float> {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
70 /// Step length scaling
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
71 pub τ0 : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
72 /// Transport smoothness assumption
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
73 pub ℓ0 : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
74 /// Inverse of the scaling factor $θ$ of the 2-norm-squared transport cost.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
75 /// This means that $τθ$ is the step length for the transport step.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
76 pub inverse_transport_scaling : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
77 /// Factor for deciding transport reduction based on smoothness assumption violation
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
78 pub minimum_goodness_factor : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
79 /// Maximum rays to retain in transports from each source.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
80 pub maximum_rays : usize,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
81 /// Generic parameters
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
82 pub insertion : FBGenericConfig<F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
83 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
84
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
85 #[replace_float_literals(F::cast_from(literal))]
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
86 impl<F : Float> Default for SlidingFBConfig<F> {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
87 fn default() -> Self {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
88 SlidingFBConfig {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
89 τ0 : 0.99,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
90 ℓ0 : 1.5,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
91 inverse_transport_scaling : 1.0,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
92 minimum_goodness_factor : 1.0, // TODO: totally arbitrary choice,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
93 // should be scaled by problem data?
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
94 maximum_rays : 10,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
95 insertion : Default::default()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
96 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
97 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
98 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
99
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
100 /// A transport ray (including various additional computational information).
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
101 #[derive(Clone, Debug)]
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
102 pub struct Ray<Domain, F : Num> {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
103 /// The destination of the ray, and the mass. The source is indicated in a [`RaySet`].
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
104 δ : DeltaMeasure<Domain, F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
105 /// Goodness of the data term for the aray: $v(z)-v(y)-⟨∇v(x), z-y⟩ + ℓ‖z-y‖^2$.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
106 goodness : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
107 /// Goodness of the regularisation term for the ray: $w(z)-w(y)$.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
108 /// Initially zero until $w$ can be constructed.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
109 reg_goodness : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
110 /// Indicates that this ray also forms a component in γ^{k+1} with the mass `to_return`.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
111 to_return : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
112 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
113
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
114 /// A set of transport rays with the same source point.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
115 #[derive(Clone, Debug)]
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
116 pub struct RaySet<Domain, F : Num> {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
117 /// Source of every ray in thset
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
118 source : Domain,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
119 /// Mass of the diagonal ray, with destination the same as the source.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
120 diagonal: F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
121 /// Goodness of the data term for the diagonal ray with $z=x$:
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
122 /// $v(x)-v(y)-⟨∇v(x), x-y⟩ + ℓ‖x-y‖^2$.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
123 diagonal_goodness : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
124 /// Goodness of the data term for the diagonal ray with $z=x$: $w(x)-w(y)$.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
125 diagonal_reg_goodness : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
126 /// The non-diagonal rays.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
127 rays : Vec<Ray<Domain, F>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
128 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
129
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
130 #[replace_float_literals(F::cast_from(literal))]
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
131 impl<Domain, F : Float> RaySet<Domain, F> {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
132 fn non_diagonal_mass(&self) -> F {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
133 self.rays
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
134 .iter()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
135 .map(|Ray{ δ : DeltaMeasure{ α, .. }, .. }| *α)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
136 .sum()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
137 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
138
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
139 fn total_mass(&self) -> F {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
140 self.non_diagonal_mass() + self.diagonal
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
141 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
142
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
143 fn targets<'a>(&'a self)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
144 -> Map<
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
145 std::slice::Iter<'a, Ray<Domain, F>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
146 fn(&'a Ray<Domain, F>) -> &'a DeltaMeasure<Domain, F>
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
147 > {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
148 fn get_δ<'b, Domain, F : Float>(Ray{ δ, .. }: &'b Ray<Domain, F>)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
149 -> &'b DeltaMeasure<Domain, F> {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
150 δ
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
151 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
152 self.rays
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
153 .iter()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
154 .map(get_δ)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
155 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
156
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
157 // fn non_diagonal_goodness(&self) -> F {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
158 // self.rays
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
159 // .iter()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
160 // .map(|&Ray{ δ : DeltaMeasure{ α, .. }, goodness, reg_goodness, .. }| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
161 // α * (goodness + reg_goodness)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
162 // })
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
163 // .sum()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
164 // }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
165
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
166 // fn total_goodness(&self) -> F {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
167 // self.non_diagonal_goodness() + (self.diagonal_goodness + self.diagonal_reg_goodness)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
168 // }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
169
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
170 fn non_diagonal_badness(&self) -> F {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
171 self.rays
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
172 .iter()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
173 .map(|&Ray{ δ : DeltaMeasure{ α, .. }, goodness, reg_goodness, .. }| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
174 0.0.max(- α * (goodness + reg_goodness))
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
175 })
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
176 .sum()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
177 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
178
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
179 fn total_badness(&self) -> F {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
180 self.non_diagonal_badness()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
181 + 0.0.max(- self.diagonal * (self.diagonal_goodness + self.diagonal_reg_goodness))
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
182 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
183
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
184 fn total_return(&self) -> F {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
185 self.rays
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
186 .iter()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
187 .map(|&Ray{ to_return, .. }| to_return)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
188 .sum()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
189 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
190 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
191
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
192 #[replace_float_literals(F::cast_from(literal))]
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
193 impl<Domain : Clone, F : Num> RaySet<Domain, F> {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
194 fn return_targets<'a>(&'a self)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
195 -> Flatten<Map<
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
196 std::slice::Iter<'a, Ray<Domain, F>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
197 fn(&'a Ray<Domain, F>) -> Option<DeltaMeasure<Domain, F>>
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
198 >> {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
199 fn get_return<'b, Domain : Clone, F : Num>(ray: &'b Ray<Domain, F>)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
200 -> Option<DeltaMeasure<Domain, F>> {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
201 (ray.to_return != 0.0).then_some(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
202 DeltaMeasure{x : ray.δ.x.clone(), α : ray.to_return}
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
203 )
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
204 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
205 let tmp : Map<
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
206 std::slice::Iter<'a, Ray<Domain, F>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
207 fn(&'a Ray<Domain, F>) -> Option<DeltaMeasure<Domain, F>>
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
208 > = self.rays
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
209 .iter()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
210 .map(get_return);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
211 tmp.flatten()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
212 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
213 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
214
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
215 /// Iteratively solve the pointsource localisation problem using sliding forward-backward
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
216 /// splitting
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
217 ///
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
218 /// The parametrisatio is as for [`pointsource_fb_reg`].
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
219 /// Inertia is currently not supported.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
220 #[replace_float_literals(F::cast_from(literal))]
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
221 pub fn pointsource_sliding_fb_reg<'a, F, I, A, GA, 𝒟, BTA, G𝒟, S, K, Reg, const N : usize>(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
222 opA : &'a A,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
223 b : &A::Observable,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
224 reg : Reg,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
225 op𝒟 : &'a 𝒟,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
226 sfbconfig : &SlidingFBConfig<F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
227 iterator : I,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
228 mut plotter : SeqPlotter<F, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
229 ) -> DiscreteMeasure<Loc<F, N>, F>
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
230 where F : Float + ToNalgebraRealField,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
231 I : AlgIteratorFactory<IterInfo<F, N>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
232 for<'b> &'b A::Observable : std::ops::Neg<Output=A::Observable>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
233 //+ std::ops::Mul<F, Output=A::Observable>, <-- FIXME: compiler overflow
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
234 A::Observable : std::ops::MulAssign<F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
235 A::PreadjointCodomain : for<'b> Differentiable<&'b Loc<F, N>, Output=Loc<F, N>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
236 GA : SupportGenerator<F, N, SupportType = S, Id = usize> + Clone,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
237 A : ForwardModel<Loc<F, N>, F, PreadjointCodomain = BTFN<F, GA, BTA, N>>
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
238 + Lipschitz<&'a 𝒟, FloatType=F> + TransportLipschitz<L2Squared, FloatType=F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
239 BTA : BTSearch<F, N, Data=usize, Agg=Bounds<F>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
240 G𝒟 : SupportGenerator<F, N, SupportType = K, Id = usize> + Clone,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
241 𝒟 : DiscreteMeasureOp<Loc<F, N>, F, PreCodomain = PreBTFN<F, G𝒟, N>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
242 𝒟::Codomain : RealMapping<F, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
243 S: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
244 + Differentiable<Loc<F, N>, Output=Loc<F,N>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
245 K: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
246 //+ Differentiable<Loc<F, N>, Output=Loc<F,N>>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
247 BTNodeLookup: BTNode<F, usize, Bounds<F>, N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
248 Cube<F, N>: P2Minimise<Loc<F, N>, F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
249 PlotLookup : Plotting<N>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
250 DiscreteMeasure<Loc<F, N>, F> : SpikeMerging<F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
251 Reg : SlidingRegTerm<F, N> {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
252
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
253 assert!(sfbconfig.τ0 > 0.0 &&
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
254 sfbconfig.inverse_transport_scaling > 0.0 &&
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
255 sfbconfig.ℓ0 > 0.0);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
256
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
257 // Set up parameters
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
258 let config = &sfbconfig.insertion;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
259 let op𝒟norm = op𝒟.opnorm_bound();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
260 let θ = sfbconfig.inverse_transport_scaling;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
261 let τ = sfbconfig.τ0/opA.lipschitz_factor(&op𝒟).unwrap()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
262 .max(opA.transport_lipschitz_factor(L2Squared) * θ);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
263 let ℓ = sfbconfig.ℓ0; // TODO: v scaling?
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
264 // We multiply tolerance by τ for FB since our subproblems depending on tolerances are scaled
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
265 // by τ compared to the conditional gradient approach.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
266 let tolerance = config.tolerance * τ * reg.tolerance_scaling();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
267 let mut ε = tolerance.initial();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
268
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
269 // Initialise iterates
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
270 let mut μ : DiscreteMeasure<Loc<F, N>, F> = DiscreteMeasure::new();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
271 let mut μ_transported_base = DiscreteMeasure::new();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
272 let mut γ_hat : Vec<RaySet<Loc<F, N>, F>> = Vec::new(); // γ̂_k and extra info
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
273 let mut residual = -b;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
274 let mut stats = IterInfo::new();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
275
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
276 // Run the algorithm
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
277 iterator.iterate(|state| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
278 // Calculate smooth part of surrogate model.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
279 // Using `std::mem::replace` here is not ideal, and expects that `empty_observable`
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
280 // has no significant overhead. For some reosn Rust doesn't allow us simply moving
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
281 // the residual and replacing it below before the end of this closure.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
282 residual *= -τ;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
283 let r = std::mem::replace(&mut residual, opA.empty_observable());
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
284 let minus_τv = opA.preadjoint().apply(r);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
285
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
286 // Save current base point and shift μ to new positions.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
287 let μ_base = μ.clone();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
288 for δ in μ.iter_spikes_mut() {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
289 δ.x += minus_τv.differential(&δ.x) * θ;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
290 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
291 let mut μ_transported = μ.clone();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
292
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
293 assert_eq!(μ.len(), γ_hat.len());
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
294
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
295 // Calculate the goodness λ formed from γ_hat (≈ γ̂_k) and γ^{k+1}, where the latter
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
296 // transports points x from μ_base to points y in μ as shifted above, or “returns”
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
297 // them “home” to z given by the rays in γ_hat. Returning is necessary if the rays
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
298 // are not “good” for the smoothness assumptions, or if γ_hat has more mass than
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
299 // μ_base.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
300 let mut total_goodness = 0.0; // data term goodness
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
301 let mut total_reg_goodness = 0.0; // regulariser goodness
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
302 let minimum_goodness = - ε * sfbconfig.minimum_goodness_factor;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
303
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
304 for (δ, r) in izip!(μ.iter_spikes(), γ_hat.iter_mut()) {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
305 // Calculate data term goodness for all rays.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
306 let &DeltaMeasure{ x : ref y, α : δ_mass } = δ;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
307 let x = &r.source;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
308 let mvy = minus_τv.apply(y);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
309 let mdvx = minus_τv.differential(x);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
310 let mut r_total_mass = 0.0; // Total mass of all rays with source r.source.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
311 let mut bad_mass = 0.0;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
312 let mut calc_goodness = |goodness : &mut F, reg_goodness : &mut F, α, z : &Loc<F, N>| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
313 *reg_goodness = 0.0; // Initial guess
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
314 *goodness = mvy - minus_τv.apply(z) + mdvx.dot(&(z-y))
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
315 + ℓ * z.dist2_squared(&y);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
316 total_goodness += *goodness * α;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
317 r_total_mass += α; // TODO: should this include to_return from staging? (Probably not)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
318 if *goodness < 0.0 {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
319 bad_mass += α;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
320 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
321 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
322 for ray in r.rays.iter_mut() {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
323 calc_goodness(&mut ray.goodness, &mut ray.reg_goodness, ray.δ.α, &ray.δ.x);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
324 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
325 calc_goodness(&mut r.diagonal_goodness, &mut r.diagonal_reg_goodness, r.diagonal, x);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
326
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
327 // If the total mass of the ray set is less than that of μ at the same source,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
328 // a diagonal component needs to be added to be able to (attempt to) transport
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
329 // all mass of μ. In the opposite case, we need to construct γ_{k+1} to ‘return’
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
330 // the the extra mass of γ̂_k to the target z. We return mass from the oldest “bad”
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
331 // rays in the set.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
332 if δ_mass >= r_total_mass {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
333 r.diagonal += δ_mass - r_total_mass;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
334 } else {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
335 let mut reduce_transport = r_total_mass - δ_mass;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
336 let mut good_needed = (bad_mass - reduce_transport).max(0.0);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
337 // NOTE: reg_goodness is zero at this point, so it is not used in this code.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
338 let mut reduce_ray = |goodness, to_return : Option<&mut F>, α : &mut F| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
339 if reduce_transport > 0.0 {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
340 let return_amount = if goodness < 0.0 {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
341 α.min(reduce_transport)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
342 } else {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
343 let amount = α.min(good_needed);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
344 good_needed -= amount;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
345 amount
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
346 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
347
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
348 if return_amount > 0.0 {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
349 reduce_transport -= return_amount;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
350 // Adjust total goodness by returned amount
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
351 total_goodness -= goodness * return_amount;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
352 to_return.map(|tr| *tr += return_amount);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
353 *α -= return_amount;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
354 *α > 0.0
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
355 } else {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
356 true
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
357 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
358 } else {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
359 true
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
360 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
361 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
362 r.rays.retain_mut(|ray| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
363 reduce_ray(ray.goodness, Some(&mut ray.to_return), &mut ray.δ.α)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
364 });
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
365 // A bad diagonal is simply reduced without any 'return'.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
366 // It was, after all, just added to match μ, but there is no need to match it.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
367 // It's just a heuristic.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
368 // TODO: Maybe a bad diagonal should be the first to go.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
369 reduce_ray(r.diagonal_goodness, None, &mut r.diagonal);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
370 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
371 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
372
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
373 // Solve finite-dimensional subproblem several times until the dual variable for the
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
374 // regularisation term conforms to the assumptions made for the transport above.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
375 let (d, within_tolerances) = 'adapt_transport: loop {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
376 // If transport violates goodness requirements, shift it to ‘return’ mass to z,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
377 // forcing y = z. Based on the badness of each ray set (sum of bad rays' goodness),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
378 // we proportionally distribute the reductions to each ray set, and within each ray
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
379 // set, prioritise reducing the oldest bad rays' weight.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
380 let tg = total_goodness + total_reg_goodness;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
381 let adaptation_needed = minimum_goodness - tg;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
382 if adaptation_needed > 0.0 {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
383 let total_badness = γ_hat.iter().map(|r| r.total_badness()).sum();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
384
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
385 let mut return_ray = |goodness : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
386 reg_goodness : F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
387 to_return : Option<&mut F>,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
388 α : &mut F,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
389 left_to_return : &mut F| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
390 let g = goodness + reg_goodness;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
391 assert!(*α >= 0.0 && *left_to_return >= 0.0);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
392 if *left_to_return > 0.0 && g < 0.0 {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
393 let return_amount = (*left_to_return / (-g)).min(*α);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
394 *left_to_return -= (-g) * return_amount;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
395 total_goodness -= goodness * return_amount;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
396 total_reg_goodness -= reg_goodness * return_amount;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
397 to_return.map(|tr| *tr += return_amount);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
398 *α -= return_amount;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
399 *α > 0.0
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
400 } else {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
401 true
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
402 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
403 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
404
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
405 for r in γ_hat.iter_mut() {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
406 let mut left_to_return = adaptation_needed * r.total_badness() / total_badness;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
407 if left_to_return > 0.0 {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
408 for ray in r.rays.iter_mut() {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
409 return_ray(ray.goodness, ray.reg_goodness,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
410 Some(&mut ray.to_return), &mut ray.δ.α, &mut left_to_return);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
411 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
412 return_ray(r.diagonal_goodness, r.diagonal_reg_goodness,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
413 None, &mut r.diagonal, &mut left_to_return);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
414 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
415 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
416 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
417
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
418 // Construct μ_k + (π_#^1-π_#^0)γ_{k+1}.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
419 // This can be broken down into
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
420 //
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
421 // μ_transported_base = [μ - π_#^0 (γ_shift + γ_return)] + π_#^1 γ_return, and
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
422 // μ_transported = π_#^1 γ_shift
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
423 //
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
424 // where γ_shift is our “true” γ_{k+1}, and γ_return is the return compoennt.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
425 // The former can be constructed from δ.x and δ_new.x for δ in μ_base and δ_new in μ
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
426 // (which has already been shifted), and the mass stored in a γ_hat ray's δ measure
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
427 // The latter can be constructed from γ_hat rays' source and destination with the
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
428 // to_return mass.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
429 //
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
430 // Note that μ_transported is constructed to have the same spike locations as μ, but
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
431 // to have same length as μ_base. This loop does not iterate over the spikes of μ
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
432 // (and corresponding transports of γ_hat) that have been newly added in the current
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
433 // 'adapt_transport loop.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
434 for (δ, δ_transported, r) in izip!(μ_base.iter_spikes(),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
435 μ_transported.iter_spikes_mut(),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
436 γ_hat.iter()) {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
437 let &DeltaMeasure{ref x, α} = δ;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
438 debug_assert_eq!(*x, r.source);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
439 let shifted_mass = r.total_mass();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
440 let ret_mass = r.total_return();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
441 // μ - π_#^0 (γ_shift + γ_return)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
442 μ_transported_base += DeltaMeasure { x : *x, α : α - shifted_mass - ret_mass };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
443 // π_#^1 γ_return
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
444 μ_transported_base.extend(r.return_targets());
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
445 // π_#^1 γ_shift
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
446 δ_transported.set_mass(shifted_mass);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
447 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
448 // Calculate transported_minus_τv = -τA_*(A[μ_transported + μ_transported_base]-b)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
449 let transported_residual = calculate_residual2(&μ_transported,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
450 &μ_transported_base,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
451 opA, b);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
452 let transported_minus_τv = opA.preadjoint()
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
453 .apply(transported_residual);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
454
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
455 // Construct μ^{k+1} by solving finite-dimensional subproblems and insert new spikes.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
456 let (mut d, within_tolerances) = insert_and_reweigh(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
457 &mut μ, &transported_minus_τv, &μ_transported, Some(&μ_transported_base),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
458 op𝒟, op𝒟norm,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
459 τ, ε,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
460 config, &reg, state, &mut stats
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
461 );
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
462
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
463 // We have d = ω0 - τv - 𝒟μ = -𝒟(μ - μ^k) - τv; more precisely
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
464 // d = minus_τv + op𝒟.preapply(μ_diff(μ, μ_transported, config));
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
465 // We “essentially” assume that the subdifferential w of the regularisation term
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
466 // satisfies w'(y)=0, so for a “goodness” estimate τ[w(y)-w(z)-w'(y)(z-y)]
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
467 // that incorporates the assumption, we need to calculate τ[w(z) - w(y)] for
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
468 // some w in the subdifferential of the regularisation term, such that
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
469 // -ε ≤ τw - d ≤ ε. This is done by [`RegTerm::goodness`].
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
470 for r in γ_hat.iter_mut() {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
471 for ray in r.rays.iter_mut() {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
472 ray.reg_goodness = reg.goodness(&mut d, &μ, &r.source, &ray.δ.x, τ, ε, config);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
473 total_reg_goodness += ray.reg_goodness * ray.δ.α;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
474 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
475 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
476
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
477 // If update of regularisation term goodness didn't invalidate minimum goodness
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
478 // requirements, we have found our step. Otherwise we need to keep reducing
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
479 // transport by repeating the loop.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
480 if total_goodness + total_reg_goodness >= minimum_goodness {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
481 break 'adapt_transport (d, within_tolerances)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
482 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
483 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
484
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
485 // Update γ_hat to new location
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
486 for (δ_new, r) in izip!(μ.iter_spikes(), γ_hat.iter_mut()) {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
487 // Prune rays that only had a return component, as the return component becomes
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
488 // a diagonal in γ̂^{k+1}.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
489 r.rays.retain(|ray| ray.δ.α != 0.0);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
490 // Otherwise zero out the return component, or stage rays for pruning
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
491 // to keep memory and computational demands reasonable.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
492 let n_rays = r.rays.len();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
493 for (ray, ir) in izip!(r.rays.iter_mut(), (0..n_rays).rev()) {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
494 if ir >= sfbconfig.maximum_rays {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
495 // Only keep sfbconfig.maximum_rays - 1 previous rays, staging others for
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
496 // pruning in next step.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
497 ray.to_return = ray.δ.α;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
498 ray.δ.α = 0.0;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
499 } else {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
500 ray.to_return = 0.0;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
501 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
502 ray.goodness = 0.0; // TODO: probably not needed
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
503 ray.reg_goodness = 0.0;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
504 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
505 // Add a new ray for the currently diagonal component
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
506 if r.diagonal > 0.0 {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
507 r.rays.push(Ray{
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
508 δ : DeltaMeasure{x : r.source, α : r.diagonal},
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
509 goodness : 0.0,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
510 reg_goodness : 0.0,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
511 to_return : 0.0,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
512 });
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
513 // TODO: Maybe this does not need to be done here, and is sufficent to to do where
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
514 // the goodness is calculated.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
515 r.diagonal = 0.0;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
516 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
517 r.diagonal_goodness = 0.0;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
518
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
519 // Shift source
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
520 r.source = δ_new.x;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
521 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
522 // Extend to new spikes
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
523 γ_hat.extend(μ[γ_hat.len()..].iter().map(|δ_new| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
524 RaySet{
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
525 source : δ_new.x,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
526 rays : [].into(),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
527 diagonal : 0.0,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
528 diagonal_goodness : 0.0,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
529 diagonal_reg_goodness : 0.0
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
530 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
531 }));
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
532
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
533 // Prune spikes with zero weight. This also moves the marginal differences of corresponding
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
534 // transports from γ_hat to γ_pruned_marginal_diff.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
535 // TODO: optimise standard prune with swap_remove.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
536 μ_transported_base.clear();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
537 let mut i = 0;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
538 assert_eq!(μ.len(), γ_hat.len());
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
539 while i < μ.len() {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
540 if μ[i].α == F::ZERO {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
541 μ.swap_remove(i);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
542 let r = γ_hat.swap_remove(i);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
543 μ_transported_base.extend(r.targets().cloned());
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
544 μ_transported_base -= DeltaMeasure{ α : r.non_diagonal_mass(), x : r.source };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
545 } else {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
546 i += 1;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
547 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
548 }
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
549
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
550 // TODO: how to merge?
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
551
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
552 // Update residual
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
553 residual = calculate_residual(&μ, opA, b);
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
554
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
555 // Update main tolerance for next iteration
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
556 let ε_prev = ε;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
557 ε = tolerance.update(ε, state.iteration());
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
558 stats.this_iters += 1;
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
559
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
560 // Give function value if needed
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
561 state.if_verbose(|| {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
562 // Plot if so requested
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
563 plotter.plot_spikes(
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
564 format!("iter {} end; {}", state.iteration(), within_tolerances), &d,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
565 "start".to_string(), Some(&minus_τv),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
566 reg.target_bounds(τ, ε_prev), &μ,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
567 );
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
568 // Calculate mean inner iterations and reset relevant counters.
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
569 // Return the statistics
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
570 let res = IterInfo {
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
571 value : residual.norm2_squared_div2() + reg.apply(&μ),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
572 n_spikes : μ.len(),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
573 ε : ε_prev,
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
574 postprocessing: config.postprocessing.then(|| μ.clone()),
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
575 .. stats
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
576 };
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
577 stats = IterInfo::new();
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
578 res
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
579 })
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
580 });
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
581
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
582 postprocess(μ, config, L2Squared, opA, b)
56c8adc32b09 Early transport sketches
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
583 }

mercurial