# SPDX-FileCopyrightText: 2025-2026 AutoLyap contributors
# SPDX-License-Identifier: GPL-3.0-only
import numpy as np
from typing import Tuple
from .algorithm import Algorithm
[docs]
class AcceleratedProximalPoint(Algorithm):
r"""
Accelerated proximal point method :cite:`kim2021acceleratedproximalpoint`.
See :doc:`3. Algorithm representation </theory/algorithm_representation>`
for mathematical notation and definitions.
Notation-driven assumptions are declared by the user via
:class:`~autolyap.problemclass.InclusionProblem`: when present, terms written with
:math:`\nabla` use differentiable functions, terms written with
:math:`\prox_{\gamma f}` use proper, lower semicontinuous, convex functions,
and terms written with :math:`J_{\gamma G}` use maximally monotone operators.
Standard form
-------------
Let :math:`\lambda_k = k/(k+2)`. For initial points
:math:`x^0,y^0,y^{-1} \in \calH` and :math:`\gamma \in \reals_{++}`,
.. math::
(\forall k \in \naturals)\quad
\left[
\begin{aligned}
x^{k+1} &=
\begin{cases}
J_{\gamma G}(y^k), & \text{if type = operator}, \\
\prox_{\gamma f}(y^k), & \text{if type = function},
\end{cases} \\
y^{k+1} &= x^{k+1} + \lambda_k(x^{k+1} - x^k) - \lambda_k(x^k - y^{k-1}).
\end{aligned}
\right.
State-space representation
--------------------------
The update can be written in the algorithm representation with
.. math::
\bx^k = (x^k, y^k, y^{k-1}), \qquad
\bu^k = \frac{y^k - x^{k+1}}{\gamma}, \qquad
\by^k = y^k.
With :math:`\lambda_k = k/(k+2)`, the system matrices are
.. math::
\begin{aligned}
A_k &=
\begin{bmatrix}
0 & 1 & 0 \\
-2\lambda_k & 1+\lambda_k & \lambda_k \\
0 & 1 & 0
\end{bmatrix}, &
B_k &=
\begin{bmatrix}
-\gamma \\
-\gamma(1+\lambda_k) \\
0
\end{bmatrix}, \\
C_k &= \begin{bmatrix} 0 & 1 & 0 \end{bmatrix}, &
D_k &= \begin{bmatrix} -\gamma \end{bmatrix}.
\end{aligned}
These are the system matrices returned by :meth:`~autolyap.algorithms.Algorithm.get_ABCD`.
Structural parameters
---------------------
.. math::
\text{type}=\text{"operator"}:\quad
n = 3,\quad m = 1,\quad (\bar{m}_i)_{i=1}^{m} = (1),\quad \bar{m} = 1,\quad
I_{\text{func}} = \varnothing,\quad I_{\text{op}} = \{1\}.
.. math::
\text{type}=\text{"function"}:\quad
n = 3,\quad m = 1,\quad (\bar{m}_i)_{i=1}^{m} = (1),\quad \bar{m} = 1,\quad
I_{\text{func}} = \{1\},\quad I_{\text{op}} = \varnothing.
"""
def __init__(
self, gamma:
float,
type:
str = "operator")
-> None:
r"""
Initialize the accelerated proximal point method.
Structural inputs passed to :class:`~autolyap.algorithms.Algorithm` are
case-dependent:
- If `type = operator`:
.. math::
n = 3,\quad m = 1,\quad (\bar m_i)_{i=1}^{m} = (1),\quad \bar m = 1,\quad
I_{\mathrm{func}} = \varnothing,\quad I_{\mathrm{op}} = \{1\}.
- If `type = function`:
.. math::
n = 3,\quad m = 1,\quad (\bar m_i)_{i=1}^{m} = (1),\quad \bar m = 1,\quad
I_{\mathrm{func}} = \{1\},\quad I_{\mathrm{op}} = \varnothing.
"""
if type == "operator":
super()
.__init__(
3,
1, [
1], [], [
1])
elif type == "function":
super()
.__init__(
3,
1, [
1], [
1], [])
else:
raise ValueError(
"type must be either 'operator' or 'function'")
self.gamma
= gamma
[docs]
def set_gamma(
self, gamma:
float)
-> None:
r"""
Set the step-size parameter :math:`\gamma`.
Shared notation follows the class-level reference in
:class:`~autolyap.algorithms.AcceleratedProximalPoint`.
**Parameters**
- `gamma` (:class:`~typing.Union`\[:class:`int`, :class:`float`\]): The value corresponding to :math:`\gamma`.
**Raises**
- `ValueError`: If `gamma` is not a finite real number or if :math:`\gamma \le 0`.
"""
gamma
= self._validate_positive_finite_real(gamma,
"gamma")
self._set_dynamic_parameter(
"gamma", gamma)
[docs]
def get_ABCD(
self, k:
int)
-> Tuple[np
.ndarray, np
.ndarray, np
.ndarray, np
.ndarray]:
lambda_var
= k
/ (k
+ 2)
A
= np
.array([[
0,
1 ,
0],
[
-2*lambda_var,
1+lambda_var, lambda_var],
[
0,
1,
0]])
B
= np
.array([[
-self.gamma],
[
-self.gamma
*(
1+lambda_var)],
[
0]])
C
= np
.array([[
0,
1,
0]])
D
= np
.array([[
-self.gamma]])
return (A, B, C, D)