src/subproblem/l1squared_unconstrained.rs

branch
dev
changeset 42
6a7365d73e4c
parent 39
6316d68b58af
child 54
b3312eee105c
equal deleted inserted replaced
41:b6bdb6cb4d44 42:6a7365d73e4c
159 }); 159 });
160 160
161 iters 161 iters
162 } 162 }
163 163
164 /// Alternative PDPS implementation of [`l1squared_unconstrained`].
165 /// For detailed documentation of the inputs and outputs, refer to there.
166 ///
167 /// By not dualising the 1-norm, this should produce more sparse solutions than
168 /// [`l1squared_unconstrained_pdps`].
169 ///
170 /// The `λ` component of the model is handled in the proximal step instead of the gradient step
171 /// for potential performance improvements.
172 /// The parameter `θ` is used to multiply the rescale the operator (identity) of the PDPS model.
173 /// We rewrite
174 /// <div>$$
175 /// \begin{split}
176 /// & \min_{x ∈ ℝ^n} \frac{β}{2} |x-y|_1^2 - g^⊤ x + λ\|x\|₁ \\
177 /// & = \min_{x ∈ ℝ^n} \max_{w} ⟨θ w, x⟩ - g^⊤ x + λ\|x\|₁
178 /// - \left(x ↦ \frac{β}{2θ} |x-y|_1^2 \right)^*(w).
179 /// \end{split}
180 /// $$</div>
181 #[replace_float_literals(F::cast_from(literal).to_nalgebra_mixed())]
182 pub fn l1squared_unconstrained_pdps_alt<F, I>(
183 y : &DVector<F::MixedType>,
184 g : &DVector<F::MixedType>,
185 λ_ : F,
186 β_ : F,
187 x : &mut DVector<F::MixedType>,
188 τ_ : F,
189 σ_ : F,
190 θ_ : F,
191 iterator : I
192 ) -> usize
193 where F : Float + ToNalgebraRealField,
194 I : AlgIteratorFactory<F>
195 {
196 let λ = λ_.to_nalgebra_mixed();
197 let τ = τ_.to_nalgebra_mixed();
198 let σ = σ_.to_nalgebra_mixed();
199 let θ = θ_.to_nalgebra_mixed();
200 let β = β_.to_nalgebra_mixed();
201 let σθ = σ*θ;
202 let τθ = τ*θ;
203 let mut w = DVector::zeros(x.len());
204 let mut tmp = DVector::zeros(x.len());
205 let mut xprev = x.clone();
206 let mut iters = 0;
207
208 iterator.iterate(|state| {
209 // Primal step: x^{k+1} = soft_τλ(x^k - τ(θ w^k -g))
210 x.axpy(-τθ, &w, 1.0);
211 x.axpy(τ, g, 1.0);
212 x.apply(|x_i| *x_i = soft_thresholding(*x_i, τ*λ));
213
214 // Dual step: with g(x) = (β/(2θ))‖x-y‖₁² and q = w^k + σ(2x^{k+1}-x^k),
215 // we compute w^{k+1} = prox_{σg^*}(q) for
216 // = q - σ prox_{g/σ}(q/σ)
217 // = q - σ prox_{(β/(2θσ))‖.-y‖₁²}(q/σ)
218 // = σ(q/σ - prox_{(β/(2θσ))‖.-y‖₁²}(q/σ))
219 // where q/σ = w^k/σ + (2x^{k+1}-x^k),
220 w /= σ;
221 w.axpy(2.0, x, 1.0);
222 w.axpy(-1.0, &xprev, 1.0);
223 xprev.copy_from(&w); // use xprev as temporary variable
224 l1squared_prox(&mut tmp, &mut xprev, y, β/σθ);
225 w -= &xprev;
226 w *= σ;
227 xprev.copy_from(x);
228
229 iters += 1;
230
231 state.if_verbose(|| {
232 F::from_nalgebra_mixed(min_subdifferential(y, x, g, λ, β))
233 })
234 });
235
236 iters
237 }
238
164 239
165 /// This function applies an iterative method for the solution of the problem 240 /// This function applies an iterative method for the solution of the problem
166 /// <div>$$ 241 /// <div>$$
167 /// \min_{x ∈ ℝ^n} \frac{β}{2} |x-y|_1^2 - g^⊤ x + λ\|x\|₁. 242 /// \min_{x ∈ ℝ^n} \frac{β}{2} |x-y|_1^2 - g^⊤ x + λ\|x\|₁.
168 /// $$</div> 243 /// $$</div>
180 iterator : I 255 iterator : I
181 ) -> usize 256 ) -> usize
182 where F : Float + ToNalgebraRealField, 257 where F : Float + ToNalgebraRealField,
183 I : AlgIteratorFactory<F> 258 I : AlgIteratorFactory<F>
184 { 259 {
185 // Estimate of ‖K‖ for K=Id. 260 // Estimate of ‖K‖ for K=θ Id.
186 let normest = 1.0; 261 let inner_θ = 1.0;
262 let normest = inner_θ;
187 263
188 let (inner_τ, inner_σ) = (inner.pdps_τσ0.0 / normest, inner.pdps_τσ0.1 / normest); 264 let (inner_τ, inner_σ) = (inner.pdps_τσ0.0 / normest, inner.pdps_τσ0.1 / normest);
189 265
190 match inner.method { 266 match inner.method {
191 InnerMethod::PDPS => 267 InnerMethod::PDPS =>
192 l1squared_unconstrained_pdps(y, g, λ, β, x, inner_τ, inner_σ, iterator), 268 l1squared_unconstrained_pdps_alt(y, g, λ, β, x, inner_τ, inner_σ, inner_θ, iterator),
193 other => unimplemented!("${other:?} is unimplemented"), 269 other => unimplemented!("${other:?} is unimplemented"),
194 } 270 }
195 } 271 }

mercurial