Source code for poisson_approval.utils.ComputationEngine

import math
import numpy as np
from abc import ABC, abstractmethod


# noinspection PyPropertyDefinition,PyNestedDecorators
[docs]class ComputationEngine(ABC): """Computation engine. Define how some mathematical operations are performed. Cf. :class:`ComputationEngineSymbolic` and :class:`ComputationEngineNumeric` for some examples. """ # Constants inf = None """Positive infinity.""" nan = None """Not a Number.""" pi = None """Pi.""" # Functions
[docs] @classmethod def barycenter(cls, a, b, ratio_b): """Barycenter. Cf. :meth:`ComputationEngineNumeric.barycenter` for specifications and examples. """ try: # b and ratio_b are numbers return cls.multiply_with_absorbing_zero(1 - ratio_b, a) + cls.multiply_with_absorbing_zero(ratio_b, b) except TypeError: # b and ratio_b are iterables ratio_a = 1 - sum(ratio_b) return cls.multiply_with_absorbing_zero(ratio_a, a) + sum([ cls.multiply_with_absorbing_zero(r, x) for r, x in zip(b, ratio_b)])
[docs] @classmethod @abstractmethod def exp(cls, x): """Exponential. """ raise NotImplementedError
[docs] @classmethod @abstractmethod def factorial(cls, x): """Factorial. """ raise NotImplementedError
[docs] @classmethod @abstractmethod def log(cls, x): """Logarithm. """ raise NotImplementedError
[docs] @classmethod def look_equal(cls, x, y, *args, **kwargs): """Test if two numbers can reasonably be considered as equal. Parameters ---------- x, y : Number *args Cf. :func:`math.isclose`. **kwargs Cf. :func:`math.isclose`. Returns ------- bool If `x` or `y` is a float or numpy float (but not a sympy float), then return ``math.isclose(x, y, *args, **kwargs)``. In all other cases, return True iff `x` is equal to `y`. """ if isinstance(x, float) or isinstance(y, float): return math.isclose(x, y, *args, **kwargs) else: return cls.simplify(x - y) == 0
[docs] @classmethod def multiply_with_absorbing_zero(cls, x, y): """Multiplication with absorbing zero. Parameters ---------- x, y : Number Returns ------- Number If `x` or `y` is 0, then 0 (even if the other input is ``nan``). Otherwise, the product of `x` and `y`. """ x = cls.simplify(x) y = cls.simplify(y) return cls.S(0) if x == 0 or y == 0 else x * y
[docs] @classmethod def ones(cls, *args, **kwargs): """Array of ones. """ return np.ones(*args, **kwargs, dtype=int)
# noinspection PyPep8Naming
[docs] @classmethod @abstractmethod def Rational(cls, x, y): """Rational number. Should return a fraction, even in a numeric engine. """ raise NotImplementedError
# noinspection PyPep8Naming
[docs] @classmethod @abstractmethod def S(cls, x): """Convert the number if necessary. Return a number that has the same value as `x`. Cf. function ``S`` of the package `sympy`. """ raise NotImplementedError
[docs] @classmethod @abstractmethod def simplify(cls, x): """Simplify the number if necessary. Return a number that has the same value as `x`. Cf. function ``simplify`` of the package `sympy`. """ raise NotImplementedError
[docs] @classmethod def simplify_vector(cls, x): """Simplify the coefficients if necessary. """ return np.array([cls.simplify(value) for value in x])
[docs] @classmethod @abstractmethod def sqrt(cls, x): """Square root. """ raise NotImplementedError
[docs] @classmethod def zeros(cls, *args, **kwargs): """Array of zeros. """ return np.zeros(*args, **kwargs, dtype=int)