qml.gradients.finite_diff_coeffs

finite_diff_coeffs(n, approx_order, strategy)[source]

Generate the finite difference shift values and corresponding term coefficients for a given derivative order, approximation accuracy, and strategy.

Parameters
  • n (int) – Positive integer specifying the order of the derivative. For example, n=1 corresponds to the first derivative, n=2 the second derivative, etc.

  • approx_order (int) – Positive integer referring to the approximation order of the returned coefficients, e.g., approx_order=1 corresponds to the first-order approximation to the derivative.

  • strategy (str) – One of "forward", "center", or "backward". For the "forward" strategy, the finite-difference shifts occur at the points \(x_0, x_0+h, x_0+2h,\dots\), where \(h\) is some small step size. The "backwards" strategy is similar, but in reverse: \(x_0, x_0-h, x_0-2h, \dots\). Finally, the "center" strategy results in shifts symmetric around the unshifted point: \(\dots, x_0-2h, x_0-h, x_0, x_0+h, x_0+2h,\dots\).

Returns

A (2, N) array. The first row corresponds to the coefficients, and the second row corresponds to the shifts.

Return type

array[float]

Example

>>> finite_diff_coeffs(n=1, approx_order=1, strategy="forward")
array([[-1.,  1.],
       [ 0.,  1.]])

For example, this results in the linear combination:

\[\frac{-y(x_0) + y(x_0 + h)}{h}\]

where \(h\) is the finite-difference step size.

More examples:

>>> finite_diff_coeffs(n=1, approx_order=2, strategy="center")
array([[-0.5,  0.5],
       [-1. ,  1. ]])
>>> finite_diff_coeffs(n=2, approx_order=2, strategy="center")
array([[-2.,  1.,  1.],
       [ 0., -1.,  1.]])

Details

Consider a function \(y(x)\). We wish to approximate the \(n\)-th derivative at point \(x_0\), \(y^{(n)}(x_0)\), by sampling the function at \(N<n\) distinct points:

\[y^{(n)}(x_0) \approx \sum_{i=1}^N c_i y(x_i)\]

where \(c_i\) are coefficients, and \(x_i=x_0 + s_i\) are the points we sample the function at.

Consider the Taylor expansion of \(y(x_i)\) around the point \(x_0\):

\[\begin{split}y^{(n)}(x_0) \approx \sum_{i=1}^N c_i y(x_i) &= \sum_{i=1}^N c_i \left[ y(x_0) + y'(x_0)(x_i-x_0) + \frac{1}{2} y''(x_0)(x_i-x_0)^2 + \cdots \right]\\ & = \sum_{j=0}^m y^{(j)}(x_0) \left[\sum_{i=1}^N \frac{c_i s_i^j}{j!} + \mathcal{O}(s_i^m) \right],\end{split}\]

where \(s_i = x_i-x_0\). For this approximation to be satisfied, we must therefore have

\[\begin{split}\sum_{i=1}^N s_i^j c_i = \begin{cases} j!, &j=n\\ 0, & j\neq n\end{cases}.\end{split}\]

Thus, to determine the coefficients \(c_i \in \{c_1, \dots, c_N\}\) for particular shift values \(s_i \in \{s_1, \dots, s_N\}\) and derivative order \(n\), we must solve this linear system of equations.