+{
+ let λ = λ_.to_nalgebra_mixed();
+ let τ = τ_.to_nalgebra_mixed();
+ let σ = σ_.to_nalgebra_mixed();
+ let θ = θ_.to_nalgebra_mixed();
+ let β = β_.to_nalgebra_mixed();
+ let σθ = σ*θ;
+ let τθ = τ*θ;
+ let mut w = DVector::zeros(x.len());
+ let mut tmp = DVector::zeros(x.len());
+ let mut xprev = x.clone();
+ let mut iters = 0;
+
+ iterator.iterate(|state| {
+ // Primal step: x^{k+1} = soft_τλ(x^k - τ(θ w^k -g))
+ x.axpy(-τθ, &w, 1.0);
+ x.axpy(τ, g, 1.0);
+ x.apply(|x_i| *x_i = soft_thresholding(*x_i, τ*λ));
+
+ // Dual step: with g(x) = (β/(2θ))‖x-y‖₁² and q = w^k + σ(2x^{k+1}-x^k),
+ // we compute w^{k+1} = prox_{σg^*}(q) for
+ // = q - σ prox_{g/σ}(q/σ)
+ // = q - σ prox_{(β/(2θσ))‖.-y‖₁²}(q/σ)
+ // = σ(q/σ - prox_{(β/(2θσ))‖.-y‖₁²}(q/σ))
+ // where q/σ = w^k/σ + (2x^{k+1}-x^k),
+ w /= σ;
+ w.axpy(2.0, x, 1.0);
+ w.axpy(-1.0, &xprev, 1.0);
+ xprev.copy_from(&w); // use xprev as temporary variable
+ l1squared_prox(&mut tmp, &mut xprev, y, β/σθ);
+ w -= &xprev;
+ w *= σ;
+ xprev.copy_from(x);
+
+ iters += 1;
+
+ state.if_verbose(|| {
+ F::from_nalgebra_mixed(min_subdifferential(y, x, g, λ, β))
+ })
+ });
+
+ iters
+}
+
/// This function applies an iterative method for the solution of the problem
/// $$
@@ -182,14 +257,15 @@
where F : Float + ToNalgebraRealField,
I : AlgIteratorFactory
{
- // Estimate of ‖K‖ for K=Id.
- let normest = 1.0;
+ // Estimate of ‖K‖ for K=θ Id.
+ let inner_θ = 1.0;
+ let normest = inner_θ;
let (inner_τ, inner_σ) = (inner.pdps_τσ0.0 / normest, inner.pdps_τσ0.1 / normest);
match inner.method {
InnerMethod::PDPS =>
- l1squared_unconstrained_pdps(y, g, λ, β, x, inner_τ, inner_σ, iterator),
+ l1squared_unconstrained_pdps_alt(y, g, λ, β, x, inner_τ, inner_σ, inner_θ, iterator),
other => unimplemented!("${other:?} is unimplemented"),
}
}