Skip to content

date_wise_multiplication

DateWiseMultiplication

Bases: OneToOneInversableDerivableTransformer

1-to-1 transformation allowing to transform a serie by multiplying it, element-wise, by a vector of coefficients of the same length.

Parameters:

Name Type Description Default
coefficients list[float]

Vector of coefficients of the same length as the time serie. Example: coefficients = [coef_1, coef_2, .., coef_N]

required
power float

power applied to the coefficients vector. Default to 1

1.0
Source code in eki_mmo_equations/one_to_one_transformations/mathematical_functions/date_wise_multiplication.py
class DateWiseMultiplication(OneToOneInversableDerivableTransformer):
    """1-to-1 transformation allowing to transform a serie by multiplying it, element-wise, by a vector of
    coefficients of the same length.

    ```math
        (\\text{coef}_{1}^{power} \\times \\text{serie_val}_{1}),
        \\ldots
        (\\text{coef}_{N}^{power} \\times \\text{serie_val}_N))
    ```

    Args:
        coefficients (list[float]): Vector of coefficients of the same length as the time serie.
            Example: coefficients = [coef_1, coef_2, .., coef_N]
        power (float, optional): power applied to the coefficients vector. Default to 1
    """

    def __init__(
        self,
        coefficients: list[float],
        power: float = 1.0,
    ):
        self.coefficients: list[float] = coefficients
        self.power: float = power

    @property
    def parameters(self) -> dict[str, Any]:
        return self.__dict__

    @property
    def is_linear(self) -> bool:
        return True

    # ------- METHODS -------

    def transform(self, serie: np.ndarray, copy=False) -> np.ndarray:
        serie = super().transform(serie, copy)

        return self._transformer(serie, self.coefficients, self.power)

    def inverse_transform(self, serie: np.ndarray, copy=False) -> np.ndarray:
        serie = super().inverse_transform(serie, copy)

        return self._inverse_transformer(serie, self.coefficients, self.power)

    def derivative_transform(self, serie: np.ndarray, copy=False) -> np.ndarray:
        serie = super().derivative_transform(serie, copy)

        return self._derivative_transformer(serie, self.coefficients, self.power)

    # ------- TRANSFORMERS -------

    @staticmethod
    def _transformer(
        serie: np.ndarray,
        coefficients: list[float],
        power: float,
    ) -> np.ndarray:
        "Returns the multiplication of an input variable by a vector of coefficients."
        return serie * (np.array(coefficients, dtype=float) ** power)

    @staticmethod
    def _inverse_transformer(
        serie: np.ndarray,
        coefficients: list[float],
        power: float,
    ) -> np.ndarray:
        with np.errstate(over="raise", divide="raise"):
            return serie / (np.array(coefficients, dtype=float) ** power)

    @staticmethod
    def _derivative_transformer(
        serie: np.ndarray,
        coefficients: list[float],
        power: float,
    ) -> np.ndarray:
        return np.array(coefficients, dtype=float) ** power

    # ------- CHECKERS -------

    def check_params(self, serie: np.ndarray):
        """Check if parameters respect their application scope."""
        if len(self.coefficients) != len(serie):
            raise ParameterScopeException(
                f"DateWiseMultiplication: the length of the 'coefficients' ({len(self.coefficients)}) should "
                + f"be equal to the length of the serie ({len(serie)})."
            )
        negative_coefficients_by_index: dict = {index: coef for index, coef in enumerate(self.coefficients) if coef < 0}
        if (abs(self.power) < 1) and negative_coefficients_by_index:
            raise ParameterScopeException(
                "DateWiseMultiplication: if '-1 < power < 1', then all coefficients should be non-negative. Found "
                + f"negative values: {list(negative_coefficients_by_index.values())} at indexes "
                + f"{list(negative_coefficients_by_index)}."
            )
        null_coefficients_by_index: dict = {index: coef for index, coef in enumerate(self.coefficients) if coef == 0}
        if (self.power < 0) and null_coefficients_by_index:
            raise ParameterScopeException(
                "DateWiseMultiplication: if 'power < 0', all coefficients should be non-zero. Found zero values: "
                + f"{list(null_coefficients_by_index)} at indexes "
                + f"{list(null_coefficients_by_index.values())}."
            )

check_params(serie)

Check if parameters respect their application scope.

Source code in eki_mmo_equations/one_to_one_transformations/mathematical_functions/date_wise_multiplication.py
def check_params(self, serie: np.ndarray):
    """Check if parameters respect their application scope."""
    if len(self.coefficients) != len(serie):
        raise ParameterScopeException(
            f"DateWiseMultiplication: the length of the 'coefficients' ({len(self.coefficients)}) should "
            + f"be equal to the length of the serie ({len(serie)})."
        )
    negative_coefficients_by_index: dict = {index: coef for index, coef in enumerate(self.coefficients) if coef < 0}
    if (abs(self.power) < 1) and negative_coefficients_by_index:
        raise ParameterScopeException(
            "DateWiseMultiplication: if '-1 < power < 1', then all coefficients should be non-negative. Found "
            + f"negative values: {list(negative_coefficients_by_index.values())} at indexes "
            + f"{list(negative_coefficients_by_index)}."
        )
    null_coefficients_by_index: dict = {index: coef for index, coef in enumerate(self.coefficients) if coef == 0}
    if (self.power < 0) and null_coefficients_by_index:
        raise ParameterScopeException(
            "DateWiseMultiplication: if 'power < 0', all coefficients should be non-zero. Found zero values: "
            + f"{list(null_coefficients_by_index)} at indexes "
            + f"{list(null_coefficients_by_index.values())}."
        )