Source code for minterpy.schemes.barycentric.operators

"""
This module contains the concrete implementations of the barycentric operators
classes.

The class `BarycentricOperator` implements the abstract base class
:py:class:`OperatorABC <.core.ABC.operator_abstract.OperatorABC>` and
serves as the parent class for several specialized barycentric transformation
operator classes.

These specialized classes differ in how the decomposition of the transformation
matrix is performed and how the transformation is applied:

- `BarycentricDictOperator`
- `BarycentricFactorisedOperator`
- `BarycentricPiecewiseOperator`

----

"""

from abc import abstractmethod
from typing import Optional, Union

import numpy as np
from _warnings import warn

from minterpy.core.ABC import OperatorABC
from minterpy.global_settings import ARRAY, FLOAT_DTYPE

from ..matrix_operator import MatrixOperator
from .conversion import merge_trafo_dict, merge_trafo_factorised, merge_trafo_piecewise
from .transformation_fcts import (
    transform_barycentric_dict,
    transform_barycentric_factorised,
    transform_barycentric_piecewise,
)


[docs] class BarycentricOperator(OperatorABC): """Base class for the barycentric transformation operators. Specialized versions (dict, factorised, and piecewise) are derived from this base class. """ _array_representation: Optional[ARRAY] = None @property def array_representation(self) -> ARRAY: """Reconstructs the global transformation matrix.""" if self._array_representation is None: warn( "building a full transformation matrix from a barycentric transformation. this is inefficient." ) # NOTE: 'self' arg must not be passed to the the merging fcts (@staticmethod) full_array = self.__class__.merging_fct(*self.transformation_data) # type: ignore self._array_representation = full_array return self._array_representation
[docs] @staticmethod @abstractmethod def transformation_fct(coeffs_in, coeffs_out_placeholder, *args): """Abstract method for executing the potentially decomposed linear transformation.""" pass
[docs] @staticmethod @abstractmethod def merging_fct(*args): """Abstract method for reconstructing the global matrix from the decomposition.""" pass
[docs] def __matmul__( self, other: Union[OperatorABC, ARRAY] ) -> Union[MatrixOperator, ARRAY]: """Applies the transformation operator on the input.""" if isinstance(other, OperatorABC): # the input is another transformation # workaround: return matrix operator constructed from the matrix product # TODO support this natively # TODO which transformation object should be passed? return MatrixOperator( self.transformation, self.array_repr_full @ other.array_repr_full ) # TODO support "separate multi index" transformations # assuming the input are coefficients which should be transformed coeffs_in = other # alias # use an output placeholder (for an increases compatibility with Numba JIT compilation) # initialise the placeholder with 0 coeffs_out_placeholder = np.zeros(coeffs_in.shape, dtype=FLOAT_DTYPE) # trafo_dict, leaf_positions = self.data_container # NOTE: 'self' arg must not be passed to the the transformation fcts (@staticmethod) self.__class__.transformation_fct( coeffs_in, coeffs_out_placeholder, *self.transformation_data ) # type: ignore return coeffs_out_placeholder
[docs] def _get_array_repr(self): """Reconstructs the global transformation matrix.""" return self.array_representation
[docs] class BarycentricDictOperator(BarycentricOperator): """Concrete implementation of the BarycentricOperator given by the edge case given by decomposition to the 1D atomic sub-problems. """ transformation_fct = transform_barycentric_dict merging_fct = merge_trafo_dict
[docs] class BarycentricFactorisedOperator(BarycentricOperator): """Concrete implementation of the BarycentricOperator given by the edge case given by realizing the factorised copied of the basic 1D atomic sub-problem. """ transformation_fct = transform_barycentric_factorised merging_fct = merge_trafo_factorised
[docs] class BarycentricPiecewiseOperator(BarycentricOperator): """Concrete implementation of the BarycentricOperator used to make comparisons with the global matrix possible by zooming into corresponding submatrix. """ transformation_fct = transform_barycentric_piecewise merging_fct = merge_trafo_piecewise