src/subproblem/l1squared_nonneg.rs

Tue, 18 Feb 2025 20:19:57 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Tue, 18 Feb 2025 20:19:57 -0500
changeset 57
5c9c5649c35d
parent 42
6a7365d73e4c
permissions
-rw-r--r--

Add arXiv link of second paper to README

34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1 /*!
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
2 Iterative algorithms for solving the finite-dimensional subproblem with constraint.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
3 */
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
4
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
5 use nalgebra::DVector;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
6 use numeric_literals::replace_float_literals;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
7 use itertools::izip;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
8 //use std::iter::zip;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
9 use std::cmp::Ordering::*;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
10
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
11 use alg_tools::iterate::{
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
12 AlgIteratorFactory,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
13 AlgIteratorState,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
14 };
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
15 use alg_tools::nalgebra_support::ToNalgebraRealField;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
16 use alg_tools::norms::{Dist, L1};
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
17 use alg_tools::nanleast::NaNLeast;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
18
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
19 use crate::types::*;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
20 use super::{
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
21 InnerMethod,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
22 InnerSettings
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
23 };
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
24 use super::nonneg::nonneg_soft_thresholding;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
25 use super::l1squared_unconstrained::l1squared_prox;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
26
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
27 /// Return maximum of `dist` and distnce of inteval `[lb, ub]` to zero.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
28 #[replace_float_literals(F::cast_from(literal))]
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
29 pub(super) fn max_interval_dist_to_zero<F : Float>(dist : F, lb : F, ub : F) -> F {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
30 if lb < 0.0 {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
31 if ub > 0.0 {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
32 dist
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
33 } else {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
34 dist.max(-ub)
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
35 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
36 } else /* ub ≥ 0.0*/ {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
37 dist.max(lb)
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
38 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
39 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
40
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
41 /// Returns the ∞-norm minimal subdifferential of $x ↦ (β/2)|x-y|_1^2 - g^⊤ x + λ\|x\|₁ +δ_{≥}(x)$ at $x$.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
42 ///
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
43 /// `v` will be modified and cannot be trusted to contain useful values afterwards.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
44 #[replace_float_literals(F::cast_from(literal))]
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
45 fn min_subdifferential<F : Float + nalgebra::RealField>(
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
46 y : &DVector<F>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
47 x : &DVector<F>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
48 g : &DVector<F>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
49 λ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
50 β : F
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
51 ) -> F {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
52 let mut val = 0.0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
53 let tmp = β*y.dist(x, L1);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
54 for (&g_i, &x_i, y_i) in izip!(g.iter(), x.iter(), y.iter()) {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
55 let (mut lb, mut ub) = (-g_i, -g_i);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
56 match x_i.partial_cmp(y_i) {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
57 Some(Greater) => { lb += tmp; ub += tmp },
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
58 Some(Less) => { lb -= tmp; ub -= tmp },
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
59 Some(Equal) => { lb -= tmp; ub += tmp },
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
60 None => {},
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
61 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
62 match x_i.partial_cmp(&0.0) {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
63 Some(Greater) => { lb += λ; ub += λ },
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
64 // Less should not happen
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
65 Some(Less|Equal) => { lb = F::NEG_INFINITY; ub += λ },
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
66 None => {},
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
67 };
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
68 val = max_interval_dist_to_zero(val, lb, ub);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
69 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
70 val
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
71 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
72
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
73 #[replace_float_literals(F::cast_from(literal))]
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
74 fn lbd_soft_thresholding<F : Float>(v : F, λ : F, b : F) -> F
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
75 {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
76 match (b >= 0.0, v >= b) {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
77 (true, false) => b,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
78 (true, true) => b.max(v - λ), // soft-to-b from above
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
79 (false, true) => super::unconstrained::soft_thresholding(v, λ),
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
80 (false, false) => 0.0.min(b.max(v - λ)), // soft-to-0 with lower bound
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
81 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
82 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
83
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
84 /// Calculate $prox_f(x)$ for $f(x)=\frac{β}{2}\norm{x-y}_1^2 + δ_{≥0}(x)$.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
85 ///
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
86 /// To derive an algorithm for this, we can use
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
87 /// $prox_f(x) = prox_{f_0}(x - y) - y$ for
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
88 /// $f_0(z)=\frac{β}{2}\norm{z}_1^2 + δ_{≥-y}(z)$.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
89 /// Now, the optimality conditions for $w = prox_{f_0}(x)$ are
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
90 /// $$\tag{*}
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
91 /// x ∈ w + β\norm{w}_1\sign w + N_{≥ -y}(w).
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
92 /// $$
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
93 /// If we know $\norm{w}_1$, then this is easily solved by lower-bounded soft-thresholding.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
94 /// We find this by sorting the elements by the distance to the 'locked' lower-bounded
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
95 /// soft-thresholding target ($0$ or $-y_i$).
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
96 /// Then we loop over this sorted vector, increasing our estimate of $\norm{w}_1$ as we decide
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
97 /// that the soft-thresholding parameter `β\norm{w}_1` has to be such that the passed elements
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
98 /// will reach their locked value (after which they cannot change anymore, for a larger
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
99 /// soft-thresholding parameter. This has to be slightly more fine-grained for account
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
100 /// for the case that $-y_i<0$ and $x_i < -y_i$.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
101 ///
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
102 /// Indeed, we denote by x' and w' the subset of elements such that w_i ≠ 0 and w_i > -y_i,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
103 /// we can calculate by applying $⟨\cdot, \sign w'⟩$ to the corresponding lines of (*) that
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
104 /// $$
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
105 /// \norm{x'} = \norm{w'} + β \norm{w}_1 m.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
106 /// $$
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
107 /// Having a value for $t = \norm{w}-\norm{w'}$, we can then calculate
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
108 /// $$
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
109 /// \norm{x'} - t = (1+β m)\norm{w}_1,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
110 /// $$
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
111 /// from where we can calculate the soft-thresholding parameter $λ=β\norm{w}_1$.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
112 /// Since we do not actually know the unlocked elements, but just loop over all the possibilities
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
113 /// for them, we have to check that $λ$ is above the current lower bound for this parameter
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
114 /// (`shift` in the code), and below a value that would cause changes in the locked set
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
115 /// (`max_shift` in the code).
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
116 #[replace_float_literals(F::cast_from(literal))]
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
117 pub(super) fn l1squared_nonneg_prox<F :Float + nalgebra::RealField>(
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
118 sorted : &mut Vec<(F, F, F, Option<(F, F)>)>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
119 x : &mut DVector<F>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
120 y : &DVector<F>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
121 β : F
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
122 ) {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
123 // nalgebra double-definition bullshit workaround
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
124 //let max = alg_tools::NumTraitsFloat::max;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
125 let abs = alg_tools::NumTraitsFloat::abs;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
126
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
127 *x -= y;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
128
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
129 for (az_x_i, &x_i, &y_i) in izip!(sorted.iter_mut(), x.iter(), y.iter()) {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
130 // The first component of each az_x_i contains the distance of x_i to the
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
131 // soft-thresholding limit. If it is negative, it is always reached.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
132 // The second component contains the absolute value of the result for that component
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
133 // w_i of the solution, if the soft-thresholding limit is reached.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
134 // This is stored here due to the sorting, although could otherwise be computed directly.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
135 // Likewise the third component contains the absolute value of x_i.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
136 // The fourth component contains an initial lower bound.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
137 let a_i = abs(x_i);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
138 let b = -y_i;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
139 *az_x_i = match (b >= 0.0, x_i >= b) {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
140 (true, false) => (x_i-b, b, a_i, None), // w_i=b, so sorting element negative!
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
141 (true, true) => (x_i-b, b, a_i, None), // soft-to-b from above
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
142 (false, true) => (a_i, 0.0, a_i, None), // soft-to-0
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
143 (false, false) => (a_i, 0.0, a_i, Some((b, b-x_i))), // soft-to-0 with initial limit
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
144 };
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
145 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
146 sorted.as_mut_slice()
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
147 .sort_unstable_by(|(a, _, _, _), (b, _, _, _)| NaNLeast(*a).cmp(&NaNLeast(*b)));
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
148
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
149 let mut nwlow = 0.0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
150 let mut shift = 0.0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
151 // This main loop is over different combinations of elements of the solution locked
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
152 // to the soft-thresholding lower bound (`0` or `-y_i`), in the sorted order of locking.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
153 for (i, az_x_i) in izip!(0.., sorted.iter()) {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
154 // This 'attempt is over different combinations of elements locked to the
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
155 // lower bound (`-y_i ≤ 0`). It calculates `max_shift` as the maximum shift that
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
156 // can be done until the locking would change (or become non-strictly-complementary).
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
157 // If the main rule (*) gives an estimate of `λ` that stays below `max_shift`, it is
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
158 // accepted. Otherwise `shift` is updated to `max_shift`, and we attempt again,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
159 // with the non-locking set that participates in the calculation of `λ` then including
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
160 // the elements that are no longer locked to the lower bound.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
161 'attempt: loop {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
162 let mut nwthis = 0.0; // contribution to ‖w‖ from elements with locking
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
163 //soft-thresholding parameter = `shift`
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
164 let mut nxmore = 0.0; // ‖x'‖ for those elements through to not be locked to
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
165 // neither the soft-thresholding limit, nor the lower bound
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
166 let mut nwlbd = 0.0; // contribution to ‖w‖ from those elements locked to their
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
167 // lower bound
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
168 let mut m = 0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
169 let mut max_shift = F::INFINITY; // maximal shift for which our estimate of the set of
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
170 // unlocked elements is valid.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
171 let mut max_shift_from_lbd = false; // Whether max_shift comes from the next element
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
172 // or from a lower bound being reached.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
173 for az_x_j in sorted[i as usize..].iter() {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
174 if az_x_j.0 <= shift {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
175 nwthis += az_x_j.1;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
176 } else {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
177 match az_x_j.3 {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
178 Some((l, s)) if shift < s => {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
179 if max_shift > s {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
180 max_shift_from_lbd = true;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
181 max_shift = s;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
182 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
183 nwlbd += -l;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
184 },
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
185 _ => {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
186 nxmore += az_x_j.2;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
187 if m == 0 && max_shift > az_x_j.0 {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
188 max_shift = az_x_j.0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
189 max_shift_from_lbd = false;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
190 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
191 m += 1;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
192 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
193 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
194 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
195 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
196
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
197 // We need ‖x'‖ = ‖w'‖ + β m ‖w‖, i.e. ‖x'‖ - (‖w‖-‖w'‖)= (1 + β m)‖w‖.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
198 let tmp = β*(nxmore - (nwlow + nwthis + nwlbd))/(1.0 + β*F::cast_from(m));
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
199 if tmp > max_shift {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
200 if max_shift_from_lbd {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
201 shift = max_shift;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
202 continue 'attempt;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
203 } else {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
204 break 'attempt
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
205 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
206 } else if tmp < shift {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
207 // TODO: this should probably be an assert!(false)
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
208 break 'attempt;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
209 } else {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
210 // success
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
211 x.zip_apply(y, |x_i, y_i| *x_i = y_i + lbd_soft_thresholding(*x_i, tmp, -y_i));
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
212 return
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
213 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
214 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
215 shift = az_x_i.0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
216 nwlow += az_x_i.1;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
217 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
218 // TODO: this fallback has not been verified to be correct
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
219 x.zip_apply(y, |x_i, y_i| *x_i = y_i + lbd_soft_thresholding(*x_i, shift, -y_i));
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
220 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
221
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
222 /// Proximal point method implementation of [`l1squared_nonneg`].
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
223 /// For detailed documentation of the inputs and outputs, refer to there.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
224 ///
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
225 /// The `λ` component of the model is handled in the proximal step instead of the gradient step
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
226 /// for potential performance improvements.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
227 #[replace_float_literals(F::cast_from(literal).to_nalgebra_mixed())]
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
228 pub fn l1squared_nonneg_pp<F, I>(
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
229 y : &DVector<F::MixedType>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
230 g : &DVector<F::MixedType>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
231 λ_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
232 β_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
233 x : &mut DVector<F::MixedType>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
234 τ_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
235 θ_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
236 iterator : I
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
237 ) -> usize
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
238 where F : Float + ToNalgebraRealField,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
239 I : AlgIteratorFactory<F>
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
240 {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
241 let λ = λ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
242 let β = β_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
243 let mut τ = τ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
244 let θ = θ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
245 let mut tmp = std::iter::repeat((0.0, 0.0, 0.0, None)).take(x.len()).collect();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
246 let mut iters = 0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
247
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
248 iterator.iterate(|state| {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
249 // Primal step: x^{k+1} = prox_{(τβ/2)|.-y|_1^2+δ_{≥0}+}(x^k - τ(λ𝟙^⊤-g))
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
250 x.apply(|x_i| *x_i -= τ*λ);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
251 x.axpy(τ, g, 1.0);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
252 l1squared_nonneg_prox(&mut tmp, x, y, τ*β);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
253
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
254 iters += 1;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
255 // This gives O(1/N^2) rates due to monotonicity of function values.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
256 // Higher acceleration does not seem to be numerically stable.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
257 τ += θ;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
258
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
259 // This gives O(1/N^3) rates due to monotonicity of function values.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
260 // Higher acceleration does not seem to be numerically stable.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
261 //τ + = F::cast_from(iters).to_nalgebra_mixed()*θ;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
262
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
263 state.if_verbose(|| {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
264 F::from_nalgebra_mixed(min_subdifferential(y, x, g, λ, β))
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
265 })
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
266 });
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
267
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
268 iters
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
269 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
270
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
271 /// PDPS implementation of [`l1squared_nonneg`].
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
272 /// For detailed documentation of the inputs and outputs, refer to there.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
273 ///
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
274 /// The `λ` component of the model is handled in the proximal step instead of the gradient step
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
275 /// for potential performance improvements.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
276 /// The parameter `θ` is used to multiply the rescale the operator (identity) of the PDPS model.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
277 #[replace_float_literals(F::cast_from(literal).to_nalgebra_mixed())]
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
278 pub fn l1squared_nonneg_pdps<F, I>(
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
279 y : &DVector<F::MixedType>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
280 g : &DVector<F::MixedType>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
281 λ_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
282 β_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
283 x : &mut DVector<F::MixedType>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
284 τ_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
285 σ_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
286 θ_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
287 iterator : I
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
288 ) -> usize
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
289 where F : Float + ToNalgebraRealField,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
290 I : AlgIteratorFactory<F>
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
291 {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
292 let λ = λ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
293 let β = β_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
294 let τ = τ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
295 let σ = σ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
296 let θ = θ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
297 let mut w = DVector::zeros(x.len());
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
298 let mut tmp = DVector::zeros(x.len());
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
299 let mut xprev = x.clone();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
300 let mut iters = 0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
301
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
302 iterator.iterate(|state| {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
303 // Primal step: x^{k+1} = prox_{(τβ/2)|.-y|_1^2}(x^k - τ (w^k - g))
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
304 x.axpy(-τ*θ, &w, 1.0);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
305 x.axpy(τ, g, 1.0);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
306 l1squared_prox(&mut tmp, x, y, τ*β);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
307
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
308 // Dual step: w^{k+1} = proj_{[-∞,λ]}(w^k + σ(2x^{k+1}-x^k))
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
309 w.axpy(2.0*σ*θ, x, 1.0);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
310 w.axpy(-σ*θ, &xprev, 1.0);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
311 w.apply(|w_i| *w_i = w_i.min(λ));
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
312 xprev.copy_from(x);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
313
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
314 iters +=1;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
315
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
316 state.if_verbose(|| {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
317 F::from_nalgebra_mixed(min_subdifferential(y, x, g, λ, β))
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
318 })
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
319 });
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
320
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
321 iters
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
322 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
323
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
324 /// Alternative PDPS implementation of [`l1squared_nonneg`].
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
325 /// For detailed documentation of the inputs and outputs, refer to there.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
326 ///
42
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
327 /// By not dualising the 1-norm, this should produce more sparse solutions than
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
328 /// [`l1squared_nonneg_pdps`].
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
329 ///
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
330 /// The `λ` component of the model is handled in the proximal step instead of the gradient step
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
331 /// for potential performance improvements.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
332 /// The parameter `θ` is used to multiply the rescale the operator (identity) of the PDPS model.
42
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
333 /// We rewrite
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
334 /// <div>$$
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
335 /// \begin{split}
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
336 /// & \min_{x ∈ ℝ^n} \frac{β}{2} |x-y|_1^2 - g^⊤ x + λ\|x\|₁ + δ_{≥ 0}(x) \\
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
337 /// & = \min_{x ∈ ℝ^n} \max_{w} ⟨θ w, x⟩ - g^⊤ x + λ\|x\|₁ + δ_{≥ 0}(x)
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
338 /// - \left(x ↦ \frac{β}{2θ} |x-y|_1^2 \right)^*(w).
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
339 /// \end{split}
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
340 /// $$</div>
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
341 #[replace_float_literals(F::cast_from(literal).to_nalgebra_mixed())]
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
342 pub fn l1squared_nonneg_pdps_alt<F, I>(
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
343 y : &DVector<F::MixedType>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
344 g : &DVector<F::MixedType>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
345 λ_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
346 β_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
347 x : &mut DVector<F::MixedType>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
348 τ_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
349 σ_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
350 θ_ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
351 iterator : I
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
352 ) -> usize
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
353 where F : Float + ToNalgebraRealField,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
354 I : AlgIteratorFactory<F>
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
355 {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
356 let λ = λ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
357 let τ = τ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
358 let σ = σ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
359 let θ = θ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
360 let β = β_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
361 let σθ = σ*θ;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
362 let τθ = τ*θ;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
363 let mut w = DVector::zeros(x.len());
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
364 let mut tmp = DVector::zeros(x.len());
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
365 let mut xprev = x.clone();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
366 let mut iters = 0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
367
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
368 iterator.iterate(|state| {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
369 // Primal step: x^{k+1} = nonnegsoft_τλ(x^k - τ(θ w^k -g))
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
370 x.axpy(-τθ, &w, 1.0);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
371 x.axpy(τ, g, 1.0);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
372 x.apply(|x_i| *x_i = nonneg_soft_thresholding(*x_i, τ*λ));
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
373
42
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
374 // Dual step: with g(x) = (β/(2θ))‖x-y‖₁² and q = w^k + σ(2x^{k+1}-x^k),
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
375 // we compute w^{k+1} = prox_{σg^*}(q) for
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
376 // = q - σ prox_{g/σ}(q/σ)
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
377 // = q - σ prox_{(β/(2θσ))‖.-y‖₁²}(q/σ)
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
378 // = σ(q/σ - prox_{(β/(2θσ))‖.-y‖₁²}(q/σ))
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
379 // where q/σ = w^k/σ + (2x^{k+1}-x^k),
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
380 w /= σ;
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
381 w.axpy(2.0, x, 1.0);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
382 w.axpy(-1.0, &xprev, 1.0);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
383 xprev.copy_from(&w); // use xprev as temporary variable
42
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
384 l1squared_prox(&mut tmp, &mut xprev, y, β/σθ);
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
385 w -= &xprev;
42
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
386 w *= σ;
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
387 xprev.copy_from(x);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
388
42
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
389 iters += 1;
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
390
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
391 state.if_verbose(|| {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
392 F::from_nalgebra_mixed(min_subdifferential(y, x, g, λ, β))
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
393 })
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
394 });
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
395
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
396 iters
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
397 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
398
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
399
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
400 /// This function applies an iterative method for the solution of the problem
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
401 /// <div>$$
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
402 /// \min_{x ∈ ℝ^n} \frac{β}{2} |x-y|_1^2 - g^⊤ x + λ\|x\|₁ + δ_{≥ 0}(x).
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
403 /// $$</div>
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
404 ///
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
405 /// This function returns the number of iterations taken.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
406 #[replace_float_literals(F::cast_from(literal))]
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
407 pub fn l1squared_nonneg<F, I>(
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
408 y : &DVector<F::MixedType>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
409 g : &DVector<F::MixedType>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
410 λ : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
411 β : F,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
412 x : &mut DVector<F::MixedType>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
413 inner : &InnerSettings<F>,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
414 iterator : I
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
415 ) -> usize
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
416 where F : Float + ToNalgebraRealField,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
417 I : AlgIteratorFactory<F>
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
418 {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
419 match inner.method {
39
6316d68b58af Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents: 34
diff changeset
420 InnerMethod::PDPS => {
42
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
421 let inner_θ = 1.0;
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
422 // Estimate of ‖K‖ for K=θ\Id.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
423 let normest = inner_θ;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
424 let (inner_τ, inner_σ) = (inner.pdps_τσ0.0 / normest, inner.pdps_τσ0.1 / normest);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
425 l1squared_nonneg_pdps_alt(y, g, λ, β, x, inner_τ, inner_σ, inner_θ, iterator)
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
426 },
39
6316d68b58af Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents: 34
diff changeset
427 InnerMethod::FB => {
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
428 // The Lipschitz factor of ∇[x ↦ g^⊤ x + λ∑x]=g - λ𝟙 is FB is just a proximal point
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
429 // method with on constraints on τ. We “accelerate” it by adding to τ the constant θ
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
430 // on each iteration. Exponential growth does not seem stable.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
431 let inner_τ = inner.fb_τ0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
432 let inner_θ = inner_τ;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
433 l1squared_nonneg_pp(y, g, λ, β, x, inner_τ, inner_θ, iterator)
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
434 },
39
6316d68b58af Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents: 34
diff changeset
435 other => unimplemented!("${other:?} is unimplemented"),
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
436 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
437 }

mercurial