src/subproblem.rs

Wed, 22 Apr 2026 23:43:00 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Wed, 22 Apr 2026 23:43:00 -0500
branch
dev
changeset 69
3ad8879ee6e1
parent 63
7a8a55fd41c0
permissions
-rw-r--r--

Bump versions

/*!
Iterative algorithms for solving the finite-dimensional subproblem.
*/

use alg_tools::iterate::{AlgIteratorOptions, Verbose};
use clap::ValueEnum;
use numeric_literals::replace_float_literals;
use serde::{Deserialize, Serialize};

use crate::types::*;

pub mod l1squared_nonneg;
pub mod l1squared_unconstrained;
pub mod nonneg;
pub mod unconstrained;

/// Method for solving finite-dimensional subproblems.
/// Not all outer methods necessarily support all options.
#[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug, ValueEnum)]
#[allow(dead_code)]
pub enum InnerMethod {
    /// Forward-backward
    FB,
    /// Semismooth Newton
    SSN,
    /// PDPS
    PDPS,
    /// Proximal point method
    PP,
}

/// Settings for the solution of finite-dimensional subproblems
#[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct InnerSettings<F: Float> {
    /// Method
    pub method: InnerMethod,
    /// Proportional step length ∈ [0, 1) for `InnerMethod::FB`.
    pub fb_τ0: F,
    /// Proportional primal and dual step lengths for `InnerMethod::PDPS`.
    pub pdps_τσ0: (F, F),
    /// Proximal point step length parameter and its growth
    pub pp_τ: (F, F),
    /// Fraction of `tolerance` given to inner algorithm
    pub tolerance_mult: F,
    /// Iterator options
    #[serde(flatten)]
    pub iterator_options: AlgIteratorOptions,
}

#[replace_float_literals(F::cast_from(literal))]
impl<F: Float> Default for InnerSettings<F> {
    fn default() -> Self {
        InnerSettings {
            fb_τ0: 0.99,
            pdps_τσ0: (1.98, 0.5),
            pp_τ: (100.0, 100.0),
            iterator_options: AlgIteratorOptions {
                // max_iter cannot be very small, as initially FB needs many iterations, although
                // on later invocations even one or two tends to be enough
                max_iter: 2000,
                // verbose_iter affects testing of sufficient convergence, so we set it to
                // a small value…
                verbose_iter: Verbose::Every(1),
                // … but don't print out anything
                quiet: true,
                ..Default::default()
            },
            method: InnerMethod::SSN,
            tolerance_mult: 0.01,
        }
    }
}

mercurial