Source code for poisson_approval.utils.ComputationEngineNumeric

import math
import numpy as np
import sympy as sp
from fractions import Fraction
from poisson_approval.utils.ComputationEngine import ComputationEngine

[docs]class ComputationEngineNumeric(ComputationEngine):
"""Computation engine: numeric computation.

This engine performs numeric computation, using floats when necessary:

>>> ce = ComputationEngineNumeric
>>> ce.inf
inf
>>> ce.nan
nan
>>> ce.exp(3)
20.085536923187668
>>> ce.log(3)
1.0986122886681098
>>> ce.Rational(1, 3)
Fraction(1, 3)
>>> ce.S(1) / 3
0.3333333333333333
>>> ce.simplify(- ce.Rational(1, 10) - (- ce.sqrt(15) / 5 + ce.sqrt(30) / 10)**2)
-0.151471862576143
>>> ce.sqrt(3)
1.7320508075688772

Usage of :meth:look_equal:

>>> ce.look_equal(1, 0.999999999999)
True
>>> ce.look_equal(1, np.float(0.999999999999))
True
>>> ce.look_equal(1, sp.Float(0.999999999999))
False
>>> ce.look_equal(1, Fraction(999999999999, 1000000000000))
False
>>> ce.look_equal(ce.sqrt(2), ce.Rational(14142135623730951, 10000000000000000))
True
"""

# Constants

inf = np.inf
nan = np.nan
pi = math.pi

# Functions

[docs]    @classmethod
def barycenter(cls, a, b, ratio_b):
"""Barycenter.

Parameters
----------
a : Number
b : Number or iterable
ratio_b : Number or iterable
The ratio of b in the result. If an iterable, must be the same size as b.

Returns
-------
Number
The result of (1 - ratio_b) * a + ratio_b * b. The added value of this function is to preserve the type
of a (resp. b) when ratio_b is 0 (resp. 1). If b and ratio_b are iterable, return
(1 - sum(ratio_b)) * a + sum(ratio_b * b).

Examples
--------
In this first example, barycenter preserves the type Fraction, whereas a naive computation returns a float:

>>> from fractions import Fraction
>>> a, b = Fraction(1, 10), 0.7
>>> ratio_b = 0
>>> ComputationEngineNumeric.barycenter(a, b, ratio_b)
Fraction(1, 10)
>>> (1 - ratio_b) * a + ratio_b * b
0.1

The second example is symmetric of the first one, in the sense that it preserves the type of b:

>>> a, b = 0.7, 42
>>> ratio_b = 1
>>> ComputationEngineNumeric.barycenter(a, b, ratio_b)
42
>>> (1 - ratio_b) * a + ratio_b * b
42.0

In the following example, b and ratio_b are iterables:

>>> a = 0
>>> b = [-1 , 1]
>>> ComputationEngineNumeric.barycenter(0, [-1, 1], [Fraction(2, 10), Fraction(3, 10)])
Fraction(1, 10)
"""
return super().barycenter(a, b, ratio_b)

[docs]    @classmethod
def exp(cls, x):
return math.exp(x)

[docs]    @classmethod
def factorial(cls, x):
return math.factorial(x)

[docs]    @classmethod
def log(cls, x):
return math.log(x)

[docs]    @classmethod
def Rational(cls, x, y):
return Fraction(x, y)

[docs]    @classmethod
def S(cls, x):
return x

[docs]    @classmethod
def simplify(cls, x):
if isinstance(x, Fraction) and x.denominator == 1:
return x.numerator
else:
return x

[docs]    @classmethod
def sqrt(cls, x):
return math.sqrt(x)