Skip to content

polykin.math.derivatives¤

derivative_centered ¤

derivative_centered(
    f: Callable[[float], float],
    x: float,
    *,
    epsf: float | None = None,
    h: float = 0.0
) -> tuple[float, float]

Calculate the numerical derivative of a scalar function using the centered finite-difference scheme.

\[ f'(x) = \frac{f(x + h) - f(x - h)}{2 h} + O(h^2) \]

References

PARAMETER DESCRIPTION
f

Function to be differentiated.

TYPE: Callable[[float], float]

x

Differentiation point.

TYPE: float

epsf

Machine precision of the function values. If None, machine precision of 64-bit floating-point type is assumed. If the number of reliable base-10 digits in the results returned by the function is \(n\), then epsf is approximately \(10^{-n}\).

TYPE: float | None DEFAULT: None

h

Finite-difference step. If 0, it will be set to the theoretical optimum value \(h=\sqrt[3]{3\epsilon_f}\).

TYPE: float DEFAULT: 0.0

RETURNS DESCRIPTION
tuple[float, float]

Tuple with derivative and mean function value, \((f'(x), f(x))\).

Examples:

Evaluate the numerical derivative of f(x)=x**3 at x=1.

>>> from polykin.math import derivative_centered
>>> def f(x): return x**3
>>> derivative_centered(f, 1.0)
(3.0000000003141882, 1.0000000009152836)
Source code in src/polykin/math/derivatives/ndiff.py
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
def derivative_centered(
    f: Callable[[float], float],
    x: float,
    *,
    epsf: float | None = None,
    h: float = 0.0,
) -> tuple[float, float]:
    r"""Calculate the numerical derivative of a scalar function using the
    centered finite-difference scheme.

    $$ f'(x) = \frac{f(x + h) - f(x - h)}{2 h} + O(h^2) $$

    **References**

    *   J. Martins and A. Ning. Engineering Design Optimization. Cambridge University
        Press, 2021.
    *   [boost/math/differentiation/finite_difference.hpp](https://www.boost.org/doc/libs/1_80_0/boost/math/differentiation/finite_difference.hpp).

    Parameters
    ----------
    f : Callable[[float], float]
        Function to be differentiated.
    x : float
        Differentiation point.
    epsf : float | None
        Machine precision of the function values. If `None`, machine precision of 64-bit
        floating-point type is assumed. If the number of reliable base-10 digits in the
        results returned by the function is $n$, then `epsf` is approximately $10^{-n}$.
    h : float
        Finite-difference step. If `0`, it will be set to the theoretical optimum
        value $h=\sqrt[3]{3\epsilon_f}$.

    Returns
    -------
    tuple[float, float]
        Tuple with derivative and mean function value, $(f'(x), f(x))$.

    Examples
    --------
    Evaluate the numerical derivative of f(x)=x**3 at x=1.
    >>> from polykin.math import derivative_centered
    >>> def f(x): return x**3
    >>> derivative_centered(f, 1.0)
    (3.0000000003141882, 1.0000000009152836)
    """
    epsf = max(epsf, eps) if epsf is not None else eps
    _h = math.cbrt(3 * epsf)

    h = max(h, _h) if h != 0 else _h
    h *= max(1.0, abs(x))

    xp = x + h
    xm = x - h
    fp = f(xp)
    fm = f(xm)
    df = (fp - fm) / (xp - xm)
    fx = (fp + fm) / 2.0

    return (df, fx)