Root-Finding Algorithm¶
Here, we demonstrate a use case of a root-finding algorithm that requires calculation of the Jacobian.
The test function is \(y = 5x^2+10x-8\).
>>> import autodiff.operations as operations
>>> from autodiff.structures import Number
def func(x):
return 5 * x ** 2 + 10 * x - 8
Newton’s method is implemented to find the root of the test function. The user should be able to find the root and access the Jacobian of each iteration.
How does this implementation work?
- The function and its derivative are evaluated at \(x_0\), then \(x_1\) is calculated as \(x_1 = x_0 - \frac{f(x_0)}{f'(x_0)}\). The Jacobian is stored in the
jacobians
list. - The evaluation of the function at \(x_1\) is compared with the threshhold, in this case \(10^{-7}\). The absolute value of the function’s value at \(x_1\) is larger than the threshold, so \(x_0\)‘s value is updated, i.e., \(x_0 = x_1\).
- The function and its derivative is again evaluated at the new \(x_0\). Derivative is stored in the
jacobians
list. This process is repeated until the threshold is met. - The
Newton()
method returns the root and thejacobians
list. User may access each step’s derivative from this list.
def newtons_method(func, initial_guess):
# Store a list of jacobians from each iteration
jacobians = []
x0 = initial_guess
fxn = func(initial_guess)
fpxn = fxn.jacobian(initial_guess)
x1 = x0 - fxn/fpxn
jacobians.append(fpxn)
while abs(fxn.val) > 1e-7:
x0 = x1
fxn = func(x0)
fpxn = fxn.jacobian(x0)
jacobians.append(fpxn)
x1 = x0- fxn / fpxn
return x1, jacobians
We can instantiate a Number(5)
as the initial guess ($x_0$) of the root.
>>> x0 = Number(5)
The Newton()
method takes the test function and the initial guess.
>>> xstar, jacobians = newtons_method(func, x0)
>>> print(xstar, jacobians[-1])
Number(val=0.6124515496597099) 16.124515496597116