Source code for fpmlib.typing
#!/usr/bin/env python3
"""
Types appearing in ``fpmlib`` package
-------------------------------------
``fpmlib`` module is provided with object-oriented design using the abstract base classes infrastructure (``abc`` package).
``fpmlib.typing`` module provides the abstract base classes used to express each class provided in ``fpmlib`` package.
The following items are automatically loaded when ``fpmlib`` package is imported.
"""
from __future__ import annotations
import numpy as np
from abc import abstractmethod
from collections.abc import Callable, Container
from typing import Any, Optional
__all__ = ['FixedPointMap', 'NonexpansiveMap', 'FirmlyNonexpansiveMap', 'MetricProjection']
[docs]class FixedPointMap(Callable, Container):
"""
An abstract base class that expresses a mapping :math:`T` from a Hilbert space :math:`H` onto itself.
This is a superclass of all mappings provided from the `fpmlib` package.
"""
@property
@abstractmethod
def ndim(self) -> Optional[int]:
r"""
Number of vector dimensions which this mapping deal with.
If the value is ``None``, this mapping accepts any vector in arbitrary dimension.
"""
raise NotImplementedError()
[docs] @abstractmethod
def __call__(self, x: np.ndarray) -> np.ndarray:
r"""
Map the given point :math:`x\in H` to :math:`T(x)`.
"""
raise NotImplementedError()
[docs] @abstractmethod
def __contains__(self, x: Any) -> bool:
r"""
Return ``True`` if the given point :math:`x` is a fixed point of this mapping :math:`T`, that is, :math:`x\in\mathrm{Fix}(T):=\{u\in H:T(u)=u\}`.
Otherwise, return ``False``.
"""
raise NotImplementedError()
[docs]class NonexpansiveMap(FixedPointMap):
r"""
An abstract base class that expresses a nonexpansive mapping, that is, a mapping :math:`T:H\to H` which satisfies :math:`\|T(x)-T(y)\|\le\|x-y\|` for any :math:`x, y\in H`.
"""
[docs]class FirmlyNonexpansiveMap(NonexpansiveMap):
r"""
An abstract base class that expresses a firmly nonexpansive mapping, that is, a mapping :math:`T:H\to H` which satisfies :math:`\|T(x)-T(y)\|^2+\|(\mathrm{Id}-T)(x)-(\mathrm{Id}-T)(y)\|^2\le\|x-y\|^2` for any :math:`x, y\in H`.
"""
@staticmethod
def from_nonexpansive(T: NonexpansiveMap, alpha: float=0.5) -> FirmlyNonexpansiveMap:
# TODO: Test this method
# return __FirmlyNonexpansiveMap(T, alpha)
return None
class __FirmlyNonexpansiveMap(FirmlyNonexpansiveMap):
def __init__(self, T: NonexpansiveMap, alpha: float=0.5):
assert 0 < alpha <= 0.5, 'Argument alpha must be between 0 and 0.5.'
self.__T = T
self.__alpha = alpha
def __call__(self, x: np.ndarray) -> np.ndarray:
u = self.__T(x)
if u is x:
u = x.copy()
u *= self.__alpha
u += (1 - self.__alpha) * x
return u
def __contains__(self, x: np.ndarray) -> bool:
return x in self.__T
[docs]class MetricProjection(FirmlyNonexpansiveMap):
r"""
An abstract base class that expresses a metric projection onto some nonempty, closed, convex subset of :math:`H`, that is, a mapping :math:`T:H\to H` which satisfies :math:`T(x)\in\mathrm{Fix}(T)` and :math:`\|T(x)-x\|=\inf_{y\in\mathrm{Fix}(T)}\|x-y\|` for any :math:`x\in H`.
"""