Abstract base classes
NonExact
The main purpose of the class NonExact is to add tolerance
attributes atol and rtol to a class, which can then be used internally in
numerical calculations. A simple example:
>>> from ddg.abc import NonExact
>>> class MyNonExactClass(NonExact):
... pass
...
>>> A = MyNonExactClass(atol=1e-8, rtol=0.)
>>> A.atol
1e-08
>>> A.rtol
0.0
There are global default values for atol and rtol, which are used
everywhere if atol or rtol are set to None (the default). These defaults
are stored as class attributes of NonExact.
>>> NonExact.atol_default
1e-07
>>> NonExact.rtol_default
0.0
>>> A = MyNonExactClass()
>>> A.atol
1e-07
>>> NonExact.atol_default = 1e-13
>>> A.atol
1e-13
>>> A.atol = 1e-5
>>> A.atol
1e-05
>>> A.atol = None
>>> A.atol
1e-13
Since these class attributes are not in a particularly accessible place, they
can also be read and changed via the top-level functions
ddg.get_tol_defaults() and ddg.set_tol_defaults() and reset
to their original values with ddg.reset_tol_defaults():
>>> import ddg
>>> ddg.get_tol_defaults()
{'atol': 1e-13, 'rtol': 0.0}
>>> ddg.set_tol_defaults(rtol=1e-3)
>>> ddg.get_tol_defaults()
{'atol': 1e-13, 'rtol': 0.001}
For simple utility functions which are not members of a class, we can use the
decorator ddg.abc.NonExact.nonexact_function(), which is realized as a
class method. If a function decorated with this method receives None as atol
or rtol, it will be replaced by the global default. The function can still
set its own defaults.
>>> import numpy as np
>>> @NonExact.nonexact_function
... def is_almost_zero(a, atol=None, rtol=0.0):
... return np.isclose(a, 0, atol=atol, rtol=rtol)
...
>>> is_almost_zero(1e-14)
True
>>> is_almost_zero(1e-12)
False
>>> is_almost_zero(1e-14, atol=1e-15)
False
>>> ddg.set_tol_defaults(atol=1e-15)
>>> is_almost_zero(1e-14)
False