Simple Derivative

Suppose we want to differentiate the function \(f(x) = x^2\). For this function we can easily state its analytical derivative \(f'(x) = 2x\).

Instead of implementing the analytical derivative by hand, we want to have it computed algorithmically. Let’s say we are interested in the function value \(f(x)\) and its derivative at \(x=0.5\).

First we need to implement a function f which computes \(f(x)\). We are already able to compute \(f(0.5)\).

[1]:
def f(x):
    return x**2

print ("f(0.5) = {}".format(f(0.5)));
f(0.5) = 0.25

To generate a function which computes the derivative, we use the derivative function from the pyADiff package. This returns a function for the derivative which we here call df. Now we are able to compute \(f'(0.5)\)

[2]:
import pyADiff
df = pyADiff.derivative(f)

print("f'(0.5) = {}".format(df(0.5)));
f'(0.5) = 1.0

This result can be verified using the analytical derivative \(f'(0.5) = 2 \times 0.5 = 1\).

It might be more convenient to see the functions \(f\) and \(f'\) as graphs. Therefore the packages numpy and matplotlib.pyplot are included.

[3]:
import numpy as np
import matplotlib.pyplot as plt

Now we initialize x as 100 points between -1 and 1. And calculate the function value \(f\) and its derivative \(f'\) at each of the points in x. Note the wayf and df are called repeatedly. While for f the numpy vectorization would work as expected and would return all of the inputs x squared, pyADiff would interpret f as a function \(f : \mathbb{R}^{100} \to \mathbb{R}^{100}\), where \(f_i(x) = x_i^2\) and would return the jacobian of \(f\).

Therefore we explicitly call f and df for each x_i in a loop here.

[4]:
x = np.linspace(-1, 1, 100)

y = np.array([f(x_i) for x_i in x])
dy = np.array([df(x_i) for x_i in x])

The last step is to plot the function \(f\) and its derivative \(f'\) over x.

[5]:
plt.plot(x, y, label="f(x) = x²")
plt.plot(x, dy, label="f'(x) = 2x")
plt.xlabel('x')
plt.legend();
../../_images/documentation_examples_simple_derivative_9_0.png