pyerrors.roots

 1import numpy as np
 2import scipy.optimize
 3from autograd import jacobian
 4
 5from .obs import derived_observable
 6
 7
 8def find_root(d, func, guess=1.0, **kwargs):
 9    r'''Finds the root of the function func(x, d) where d is an `Obs`.
10
11    Parameters
12    -----------------
13    d : Obs
14        Obs passed to the function.
15    func : object
16        Function to be minimized. Any numpy functions have to use the autograd.numpy wrapper.
17        Example:
18        ```python
19        import autograd.numpy as anp
20        def root_func(x, d):
21            return anp.exp(-x ** 2) - d
22        ```
23    guess : float
24        Initial guess for the minimization.
25
26    Returns
27    -------
28    res : Obs
29        `Obs` valued root of the function.
30    '''
31    d_val = np.vectorize(lambda x: x.value)(np.array(d))
32
33    root = scipy.optimize.fsolve(func, guess, d_val)
34
35    # Error propagation as detailed in arXiv:1809.01289
36    try:
37        dx = jacobian(func)(root[0], d_val)
38        da = jacobian(lambda u, v: func(v, u))(d_val, root[0])
39    except (TypeError, ValueError, np.linalg.LinAlgError):
40        raise Exception("It is required to use autograd.numpy instead of numpy within root functions, see the documentation for details.") from None
41    deriv = - da / dx
42    res = derived_observable(lambda x, **kwargs: (x[0] + np.finfo(np.float64).eps) / (np.array(d).reshape(-1)[0].value + np.finfo(np.float64).eps) * root[0],
43                             np.array(d).reshape(-1), man_grad=np.array(deriv).reshape(-1))
44    return res
def find_root(d, func, guess=1.0, **kwargs):
 9def find_root(d, func, guess=1.0, **kwargs):
10    r'''Finds the root of the function func(x, d) where d is an `Obs`.
11
12    Parameters
13    -----------------
14    d : Obs
15        Obs passed to the function.
16    func : object
17        Function to be minimized. Any numpy functions have to use the autograd.numpy wrapper.
18        Example:
19        ```python
20        import autograd.numpy as anp
21        def root_func(x, d):
22            return anp.exp(-x ** 2) - d
23        ```
24    guess : float
25        Initial guess for the minimization.
26
27    Returns
28    -------
29    res : Obs
30        `Obs` valued root of the function.
31    '''
32    d_val = np.vectorize(lambda x: x.value)(np.array(d))
33
34    root = scipy.optimize.fsolve(func, guess, d_val)
35
36    # Error propagation as detailed in arXiv:1809.01289
37    try:
38        dx = jacobian(func)(root[0], d_val)
39        da = jacobian(lambda u, v: func(v, u))(d_val, root[0])
40    except (TypeError, ValueError, np.linalg.LinAlgError):
41        raise Exception("It is required to use autograd.numpy instead of numpy within root functions, see the documentation for details.") from None
42    deriv = - da / dx
43    res = derived_observable(lambda x, **kwargs: (x[0] + np.finfo(np.float64).eps) / (np.array(d).reshape(-1)[0].value + np.finfo(np.float64).eps) * root[0],
44                             np.array(d).reshape(-1), man_grad=np.array(deriv).reshape(-1))
45    return res

Finds the root of the function func(x, d) where d is an Obs.

Parameters
  • d (Obs): Obs passed to the function.
  • func (object): Function to be minimized. Any numpy functions have to use the autograd.numpy wrapper. Example:

    import autograd.numpy as anp
    def root_func(x, d):
        return anp.exp(-x ** 2) - d
    
  • guess (float): Initial guess for the minimization.

Returns
  • res (Obs): Obs valued root of the function.