Source code for suppy.feasibility._halfspaces._ams_extrapolations

from typing import List
import numpy as np
import numpy.typing as npt
from scipy import sparse

try:
    import cupy as cp

    NO_GPU = False

except ImportError:
    NO_GPU = True
    cp = np

from suppy.feasibility._halfspaces._ams_algorithms import SimultaneousAMSHalfspace


[docs] class ExtrapolatedLandweberHalfspace(SimultaneousAMSHalfspace): """ Extrapolated Landweber method for solving linear inequalities of the form Ax <= b. Parameters ---------- A : npt.NDArray or sparse.sparray Matrix for linear systems b : npt.NDArray Bound for linear systems weights : None or List[float], optional The weights for the constraints, by default None. relaxation : float, optional The outer relaxation parameter, by default 1.0. proximity_flag : bool, optional A flag indicating whether to use proximity measures, by default True. References ---------- - [1] https://doi.org/10.1007/s11075-025-02163-0 - [2] https://doi.org/10.1007/978-3-642-30901-4 """ def __init__( self, A: npt.NDArray | sparse.sparray, b: npt.NDArray, relaxation: float = 1.0, weights: None | List[float] | npt.NDArray = None, proximity_flag: bool = True, ): super().__init__(A, b, 1.0, relaxation, weights, proximity_flag) self.a_i = self.A.row_norm(2, 2) self.weight_norm = self.weights / self.a_i self.sigmas = [] def _project(self, x: npt.NDArray) -> np.ndarray: xp = cp if self._use_gpu else np p = self.map(x) res = self.b - p res_idx = res < 0 if not xp.any(res_idx): self.sigmas.append(0) return x t = self.weight_norm[res_idx] * res[res_idx] t_2 = t @ self.A[res_idx, :] sig = (res[res_idx] @ t) / (t_2 @ t_2) self.sigmas.append(sig) x += sig * t_2 return x
[docs] class AdaptiveStepLandweberHalfspace(SimultaneousAMSHalfspace): """ Adaptive step-size Landweber algorithm for solving linear inequalities of the form Ax <= b. Parameters ---------- A : npt.NDArray or sparse.sparray Matrix for linear systems b : npt.NDArray Bound for linear systems weights : None or List[float], optional The weights for the constraints, by default None. relaxation : float, optional The outer relaxation parameter, by default 1.0. proximity_flag : bool, optional A flag indicating whether to use proximity measures, by default True. References ---------- - [1] https://doi.org/10.1515/jiip-2015-0082 """ def __init__( self, A: npt.NDArray | sparse.sparray, b: npt.NDArray, relaxation: float = 1.0, weights: None | List[float] | npt.NDArray = None, proximity_flag: bool = True, ): super().__init__(A, b, 1.0, relaxation, weights, proximity_flag) def _project(self, x: npt.NDArray) -> np.ndarray: xp = cp if self._use_gpu else np p = self.map(x) res = self.b - p res_idx = res < 0 if not xp.any(res_idx): return x u_t = (self.weights[res_idx] * res[res_idx]) @ self.A[res_idx, :] Au_t = self.A @ u_t # A*AT*res sig = (u_t @ u_t) / (Au_t @ (self.weights * Au_t)) x += sig * u_t return x