src/subproblem/l1squared_nonneg.rs

Mon, 23 Feb 2026 18:18:02 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Mon, 23 Feb 2026 18:18:02 -0500
branch
dev
changeset 64
d3be4f7ffd60
parent 63
7a8a55fd41c0
permissions
-rw-r--r--

ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable

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
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
5 use itertools::izip;
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
6 use nalgebra::DVector;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
7 use numeric_literals::replace_float_literals;
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
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
11 use alg_tools::iterate::{AlgIteratorFactory, AlgIteratorState};
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
12 use alg_tools::nalgebra_support::ToNalgebraRealField;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
13 use alg_tools::norms::{Dist, L1};
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
14
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
15 use super::l1squared_unconstrained::l1squared_prox;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
16 use super::nonneg::nonneg_soft_thresholding;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
17 use super::{InnerMethod, InnerSettings};
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
18 use crate::types::*;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
19
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
20 /// 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
21 #[replace_float_literals(F::cast_from(literal))]
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
22 pub(super) fn max_interval_dist_to_zero<F: Float>(dist: F, lb: F, ub: F) -> F {
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
23 if lb < 0.0 {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
24 if ub > 0.0 {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
25 dist
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
26 } else {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
27 dist.max(-ub)
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
28 }
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
29 } else
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
30 /* ub ≥ 0.0*/
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
31 {
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
32 dist.max(lb)
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
33 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
34 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
35
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
36 /// Returns the ∞-norm minimal subdifferential of $x ↦ (β/2)|x-y|_1^2 - g^⊤ x + λ\|x\|₁ +δ_{≥0}(x)$ at $x$.
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
37 ///
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
38 /// `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
39 #[replace_float_literals(F::cast_from(literal))]
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
40 fn min_subdifferential<F: Float + nalgebra::RealField>(
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
41 y: &DVector<F>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
42 x: &DVector<F>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
43 g: &DVector<F>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
44 λ: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
45 β: F,
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
46 ) -> F {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
47 let mut val = 0.0;
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
48 let tmp = β * y.dist(x, L1);
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
49 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
50 let (mut lb, mut ub) = (-g_i, -g_i);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
51 match x_i.partial_cmp(y_i) {
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
52 Some(Greater) => {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
53 lb += tmp;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
54 ub += tmp
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
55 }
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
56 Some(Less) => {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
57 lb -= tmp;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
58 ub -= tmp
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
59 }
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
60 Some(Equal) => {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
61 lb -= tmp;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
62 ub += tmp
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
63 }
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
64 None => {}
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
65 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
66 match x_i.partial_cmp(&0.0) {
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
67 Some(Greater) => {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
68 lb += λ;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
69 ub += λ
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
70 }
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
71 // Less should not happen
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
72 Some(Less | Equal) => {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
73 lb = F::NEG_INFINITY;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
74 ub += λ
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
75 }
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
76 None => {}
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
77 };
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
78 val = max_interval_dist_to_zero(val, lb, ub);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
79 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
80 val
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
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
83 // #[replace_float_literals(F::cast_from(literal))]
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
84 // fn lbd_soft_thresholding<F: Float>(v: F, λ: F, b: F) -> F {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
85 // match (b >= 0.0, v >= b) {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
86 // (true, false) => b,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
87 // (true, true) => b.max(v - λ), // soft-to-b from above
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
88 // (false, true) => super::unconstrained::soft_thresholding(v, λ),
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
89 // (false, false) => 0.0.min(b.max(v + λ)), // soft-to-0 with lower bound
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
90 // }
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
91 // }
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
92
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
93 /// Calculates $\prox\_f(x)$ for $f(x)=λ\abs{x-y} + δ\_{≥0}(x)$.
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
94 /// This is the first output. The second output is the first output $-y$, i..e, the prox
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
95 /// of $f\_0$ for the shift function $f\_0(z) = f(z+y) = λ\abs{z} + δ\_{≥-y}(z)$
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
96 /// satisfying
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
97 /// $$
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
98 /// \prox_f(x) = \prox\_{f\_0}(x - y) + y,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
99 /// $$
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
100 /// which is also used internally.
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
101 /// The third output indicates whether the output is “locked” to either $0$ (resp. $-y$ in
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
102 /// the reformulation), or $y$ ($0$ in the reformulation).
64
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
103 /// The fourth output indicates $λ$ where such locking to y would happen. It may be negative,
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
104 /// in which case the prox is always locked to y.
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
105 #[replace_float_literals(F::cast_from(literal))]
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
106 #[inline]
64
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
107 fn shifted_nonneg_soft_thresholding<F: Float>(x: F, y: F, λ: F) -> (F, F, bool, F) {
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
108 // The OC is
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
109 // x ∈ w + λsign(w-y) + N_{≥ 0}(w)
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
110 // x-y ∈ w' + λsign(w') + N_{≥ -y}(w')
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
111 // if w' > -y, then soft-thresholding. So if soft-thresholding stays above -y.
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
112 // If w' = -y, and w'≠0, then x ≤ λsign(-y)
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
113 // If w' = -y and w'=0, then x ≤ λ.
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
114 // w_i=max{sign(x-y)*max(|x-y| - λ, 0), -y} + y = max{sign(x-y)*max(|x-y| - λ, 0)+y, 0}
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
115 let (w, locked, lock) = if x >= y {
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
116 // w_i=max{max(x-y - λ, 0)+y, 0}=max{max(x - λ, y), 0} = max{x-λ, max(y, 0)}
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
117 let l = 0.0.max(y);
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
118 // x - l = x + min(0.0, y) = min(x, x + y)
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
119 if x - λ >= l {
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
120 (x - λ, false, x - l)
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
121 } else {
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
122 (l, true, F::NEG_INFINITY) // λ is increasing, so NEG_INFINITY is ok. So is x-l < λ
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
123 }
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
124 } else {
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
125 // w_i=max{-max(-(x-y) - λ, 0)+y, 0}=max{min((x-y) + λ, 0)+y, 0}=max{min(x + λ, y), 0}
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
126 if x + λ <= y {
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
127 // = max(x+λ, 0)
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
128 if x >= -λ {
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
129 (x + λ, false, y - x)
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
130 } else {
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
131 (0.0, true, 0.0.min(y) - x)
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
132 }
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
133 } else {
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
134 (0.0.max(y), true, F::NEG_INFINITY)
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
135 }
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
136 };
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
137 return (w, w - y, locked, lock);
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
138
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
139 /*
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
140 let z = x - y; // The shift to f_0
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
141 if -y >= 0.0 {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
142 if x > λ {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
143 (x - λ, z - λ, false, Some(x))
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
144 } else {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
145 (0.0, -y, true, None)
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
146 }
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
147 } else if z < 0.0 {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
148 if λ < -x {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
149 (0.0, -y, true, Some(-x))
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
150 } else if z + λ < 0.0 {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
151 (x + λ, z + λ, false, Some(-z))
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
152 } else {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
153 (y, 0.0, true, None)
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
154 }
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
155 } else if z > λ {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
156 (x - λ, z - λ, false, Some(z))
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
157 } else {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
158 (y, 0.0, true, None)
64
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
159 }*/
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
160 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
161
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
162 /// Calculate $\prox\_f(x)$ for $f(x)=\frac{β}{2}\norm{x-y}\_1\^2 + δ\_{≥0}(x)$.
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
163 ///
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
164 /// To derive an algorithm for this, we can use
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
165 /// $$
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
166 /// \prox_f(x) = \prox\_{f\_0}(x - y) + y
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
167 /// \quad\text{for}\quad
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
168 /// f\_0(z)=\frac{β}{2}\norm{z}\_1\^2 + δ\_{≥-y}(z).
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
169 /// $$
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
170 /// Now, the optimality conditions for $w = \prox\_{f\_0}(x)$ are
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
171 /// $$\tag{*}
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
172 /// x ∈ w + β\norm{w}\_1\sign w + N\_{≥ -y}(w).
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
173 /// $$
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
174 /// If we know $\norm{w}\_1$, then this is easily solved by lower-bounded soft-thresholding.
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
175 /// 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
176 /// soft-thresholding target ($0$ or $-y_i$).
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
177 /// Then we loop over this sorted vector, increasing our estimate of $\norm{w}\_1$ as we decide
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
178 /// that the soft-thresholding parameter $β\norm{w}\_1$ has to be such that the passed elements
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
179 /// 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
180 /// soft-thresholding parameter. This has to be slightly more fine-grained for account
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
181 /// for the case that $-y\_i<0$ and $x\_i < -y\_i$.
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
182 ///
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
183 /// Indeed, denoting by $x'$ and $w'$ the subset of elements such that $w\_i ≠ 0$ and
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
184 /// $w\_i > -y\_i$, we can calculate by applying $⟨\cdot, \sign w'⟩$ to the corresponding
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
185 /// lines of (*) that
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
186 /// $$
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
187 /// \norm{x'} = \norm{w'} + β \norm{w}\_1 m,
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
188 /// $$
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
189 /// where $m$ is the number of unlocked components.
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
190 /// We can now calculate the mass $t = \norm{w}-\norm{w'}$ of locked components, and so obtain
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
191 /// $$
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
192 /// \norm{x'} + t = (1+β m)\norm{w}\_1,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
193 /// $$
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
194 /// from where we can calculate the soft-thresholding parameter $λ=β\norm{w}\_1$.
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
195 /// 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
196 /// 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
197 /// (`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
198 /// (`max_shift` in the code).
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
199 #[replace_float_literals(F::cast_from(literal))]
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
200 pub fn l1squared_nonneg_prox<F: Float + nalgebra::RealField>(
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
201 x: &mut DVector<F>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
202 y: &DVector<F>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
203 β: F,
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
204 ) {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
205 // nalgebra double-definition bullshit workaround
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
206 let abs = alg_tools::NumTraitsFloat::abs;
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
207 let min = alg_tools::NumTraitsFloat::min;
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
208
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
209 let mut λ = 0.0;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
210 loop {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
211 let mut w_locked = 0.0;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
212 let mut n_unlocked = 0; // m
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
213 let mut x_prime = 0.0;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
214 let mut max_shift = F::INFINITY;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
215 for (&x_i, &y_i) in izip!(x.iter(), y.iter()) {
64
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
216 let (_, w_i, locked, lock) = shifted_nonneg_soft_thresholding(x_i, y_i, λ);
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
217
64
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
218 // If not already locked (lock <= y), consider this coordinate in next level for λ.
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
219 if lock > λ {
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
220 max_shift = min(max_shift, lock);
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
221 }
64
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
222
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
223 if locked {
64
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
224 w_locked += abs(w_i);
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
225 } else {
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
226 n_unlocked += 1;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
227 x_prime += abs(x_i - y_i);
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
228 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
229 }
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
230
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
231 // We need ‖x'‖ = ‖w'‖ + β m ‖w‖, i.e. ‖x'‖ + (‖w‖-‖w'‖)= (1 + β m)‖w‖.
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
232 let λ_new = (x_prime + w_locked) / (1.0 / β + F::cast_from(n_unlocked));
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
233
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
234 if λ_new > max_shift {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
235 λ = max_shift;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
236 } else {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
237 assert!(λ_new >= λ);
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
238 // success
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
239 x.zip_apply(y, |x_i, y_i| {
64
d3be4f7ffd60 ATTEMPT, HAS BUGS: Make shifted_nonneg_soft_thresholding more readable
Tuomo Valkonen <tuomov@iki.fi>
parents: 63
diff changeset
240 (*x_i, _, _, _) = shifted_nonneg_soft_thresholding(*x_i, y_i, λ_new);
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
241 });
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
242 return;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
243 }
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
244 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
245 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
246
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
247 /// Proximal point method implementation of [`l1squared_nonneg`].
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
248 /// For detailed documentation of the inputs and outputs, refer to there.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
249 ///
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
250 /// 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
251 /// for potential performance improvements.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
252 #[replace_float_literals(F::cast_from(literal).to_nalgebra_mixed())]
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
253 pub fn l1squared_nonneg_pp<F, I>(
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
254 y: &DVector<F::MixedType>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
255 g: &DVector<F::MixedType>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
256 λ_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
257 β_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
258 x: &mut DVector<F::MixedType>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
259 τ_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
260 θ_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
261 iterator: I,
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
262 ) -> usize
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
263 where
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
264 F: Float + ToNalgebraRealField,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
265 I: AlgIteratorFactory<F>,
34
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 let λ = λ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
268 let β = β_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
269 let mut τ = τ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
270 let θ = θ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
271 let mut iters = 0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
272
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
273 iterator.iterate(|state| {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
274 // Primal step: x^{k+1} = prox_{(τβ/2)|.-y|_1^2+δ_{≥0}+}(x^k - τ(λ𝟙^⊤-g))
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
275 x.apply(|x_i| *x_i -= τ * λ);
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
276 x.axpy(τ, g, 1.0);
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
277 l1squared_nonneg_prox(x, y, τ * β);
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
278
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
279 iters += 1;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
280 // 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
281 // Higher acceleration does not seem to be numerically stable.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
282 τ += θ;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
283
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
284 // 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
285 // Higher acceleration does not seem to be numerically stable.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
286 //τ + = F::cast_from(iters).to_nalgebra_mixed()*θ;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
287
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
288 state.if_verbose(|| F::from_nalgebra_mixed(min_subdifferential(y, x, g, λ, β)))
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
289 });
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
290
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
291 iters
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
292 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
293
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
294 /// PDPS implementation of [`l1squared_nonneg`].
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
295 /// For detailed documentation of the inputs and outputs, refer to there.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
296 ///
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
297 /// 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
298 /// for potential performance improvements.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
299 /// 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
300 #[replace_float_literals(F::cast_from(literal).to_nalgebra_mixed())]
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
301 pub fn l1squared_nonneg_pdps<F, I>(
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
302 y: &DVector<F::MixedType>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
303 g: &DVector<F::MixedType>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
304 λ_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
305 β_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
306 x: &mut DVector<F::MixedType>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
307 τ_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
308 σ_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
309 θ_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
310 iterator: I,
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
311 ) -> usize
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
312 where
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
313 F: Float + ToNalgebraRealField,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
314 I: AlgIteratorFactory<F>,
34
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 let λ = λ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
317 let β = β_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
318 let τ = τ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
319 let σ = σ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
320 let θ = θ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
321 let mut w = DVector::zeros(x.len());
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
322 let mut tmp = DVector::zeros(x.len());
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
323 let mut xprev = x.clone();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
324 let mut iters = 0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
325
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
326 iterator.iterate(|state| {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
327 // Primal step: x^{k+1} = prox_{(τβ/2)|.-y|_1^2}(x^k - τ (w^k - g))
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
328 x.axpy(-τ * θ, &w, 1.0);
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
329 x.axpy(τ, g, 1.0);
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
330 l1squared_prox(&mut tmp, x, y, τ * β);
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
331
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
332 // Dual step: w^{k+1} = proj_{[-∞,λ]}(w^k + σ(2x^{k+1}-x^k))
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
333 w.axpy(2.0 * σ * θ, x, 1.0);
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
334 w.axpy(-σ * θ, &xprev, 1.0);
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
335 w.apply(|w_i| *w_i = w_i.min(λ));
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
336 xprev.copy_from(x);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
337
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
338 iters += 1;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
339
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
340 state.if_verbose(|| F::from_nalgebra_mixed(min_subdifferential(y, x, g, λ, β)))
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
341 });
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
342
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
343 iters
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
344 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
345
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
346 /// Alternative PDPS implementation of [`l1squared_nonneg`].
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
347 /// For detailed documentation of the inputs and outputs, refer to there.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
348 ///
42
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
349 /// 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
350 /// [`l1squared_nonneg_pdps`].
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
351 ///
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
352 /// 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
353 /// for potential performance improvements.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
354 /// 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
355 /// We rewrite
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
356 /// <div>$$
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
357 /// \begin{split}
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
358 /// & \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
359 /// & = \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
360 /// - \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
361 /// \end{split}
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
362 /// $$</div>
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
363 #[replace_float_literals(F::cast_from(literal).to_nalgebra_mixed())]
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
364 pub fn l1squared_nonneg_pdps_alt<F, I>(
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
365 y: &DVector<F::MixedType>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
366 g: &DVector<F::MixedType>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
367 λ_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
368 β_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
369 x: &mut DVector<F::MixedType>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
370 τ_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
371 σ_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
372 θ_: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
373 iterator: I,
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
374 ) -> usize
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
375 where
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
376 F: Float + ToNalgebraRealField,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
377 I: AlgIteratorFactory<F>,
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
378 {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
379 let λ = λ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
380 let τ = τ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
381 let σ = σ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
382 let θ = θ_.to_nalgebra_mixed();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
383 let β = β_.to_nalgebra_mixed();
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
384 let σθ = σ * θ;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
385 let τθ = τ * θ;
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
386 let mut w = DVector::zeros(x.len());
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
387 let mut tmp = DVector::zeros(x.len());
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
388 let mut xprev = x.clone();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
389 let mut iters = 0;
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 iterator.iterate(|state| {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
392 // Primal step: x^{k+1} = nonnegsoft_τλ(x^k - τ(θ w^k -g))
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
393 x.axpy(-τθ, &w, 1.0);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
394 x.axpy(τ, g, 1.0);
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
395 x.apply(|x_i| *x_i = nonneg_soft_thresholding(*x_i, τ * λ));
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
396
42
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
397 // 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
398 // 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
399 // = q - σ prox_{g/σ}(q/σ)
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
400 // = q - σ prox_{(β/(2θσ))‖.-y‖₁²}(q/σ)
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
401 // = σ(q/σ - prox_{(β/(2θσ))‖.-y‖₁²}(q/σ))
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
402 // 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
403 w /= σ;
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
404 w.axpy(2.0, x, 1.0);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
405 w.axpy(-1.0, &xprev, 1.0);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
406 xprev.copy_from(&w); // use xprev as temporary variable
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
407 l1squared_prox(&mut tmp, &mut xprev, y, β / σθ);
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
408 w -= &xprev;
42
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
409 w *= σ;
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
410 xprev.copy_from(x);
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
411
42
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
412 iters += 1;
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
413
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
414 state.if_verbose(|| F::from_nalgebra_mixed(min_subdifferential(y, x, g, λ, β)))
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
415 });
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
416
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
417 iters
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
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
420 /// 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
421 /// <div>$$
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
422 /// \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
423 /// $$</div>
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
424 ///
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
425 /// This function returns the number of iterations taken.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
426 #[replace_float_literals(F::cast_from(literal))]
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
427 pub fn l1squared_nonneg<F, I>(
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
428 y: &DVector<F::MixedType>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
429 g: &DVector<F::MixedType>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
430 λ: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
431 β: F,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
432 x: &mut DVector<F::MixedType>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
433 inner: &InnerSettings<F>,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
434 iterator: I,
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
435 ) -> usize
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
436 where
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
437 F: Float + ToNalgebraRealField,
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
438 I: AlgIteratorFactory<F>,
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
439 {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
440 match inner.method {
39
6316d68b58af Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents: 34
diff changeset
441 InnerMethod::PDPS => {
42
6a7365d73e4c Fixes to Radon norm prox term inner algorithm
Tuomo Valkonen <tuomov@iki.fi>
parents: 39
diff changeset
442 let inner_θ = 1.0;
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
443 // Estimate of ‖K‖ for K=θ\Id.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
444 let normest = inner_θ;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
445 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
446 l1squared_nonneg_pdps_alt(y, g, λ, β, x, inner_τ, inner_σ, inner_θ, iterator)
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
447 }
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
448 InnerMethod::PP | InnerMethod::FB => {
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
449 let inner_τ = inner.pp_τ.0;
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
450 let inner_θ = inner.pp_τ.1;
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
451 l1squared_nonneg_pp(y, g, λ, β, x, inner_τ, inner_θ, iterator)
63
7a8a55fd41c0 Subproblem solver and sliding adjustments/improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 42
diff changeset
452 }
39
6316d68b58af Merging adjustments, parameter tuning, etc.
Tuomo Valkonen <tuomov@iki.fi>
parents: 34
diff changeset
453 other => unimplemented!("${other:?} is unimplemented"),
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
454 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
455 }

mercurial