<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Symbolic Differentiation vs Automatic Differentiation
Consider the function below that, at least computationally, is very simple.
Step1:  We can compute a derivative symbolically, but it is of course horrendous (see below).  Think of how much worse it would be if we chose a function with products, more dimensions, or iterated more than 20 times.
Step2:  We can now evaluate the expression.
Step3:  Let's compare with automatic differentiation using operator overloading
Step4:  Let's also compare to AD using a source code transformation method (I used Tapenade in Fortran)
<ASSISTANT_TASK:>
Python Code:
from math import sin, cos
def func(x):
    y = x
    for i in range(30):
        y = sin(x + y)
    return y
Explanation: Symbolic Differentiation vs Automatic Differentiation
Consider the function below that, at least computationally, is very simple.
End of explanation
from sympy import diff, Symbol, sin
from __future__ import print_function
x = Symbol('x')
dexp = diff(func(x), x)
print(dexp)
Explanation: We can compute a derivative symbolically, but it is of course horrendous (see below).  Think of how much worse it would be if we chose a function with products, more dimensions, or iterated more than 20 times.
End of explanation
xpt = 0.1
dfdx = dexp.subs(x, xpt)
print('dfdx =', dfdx)
Explanation: We can now evaluate the expression.
End of explanation
from algopy import UTPM, sin
x_algopy = UTPM.init_jacobian(xpt)
y_algopy = func(x_algopy)
dfdx = UTPM.extract_jacobian(y_algopy)
    
print('dfdx =', dfdx)
Explanation: Let's compare with automatic differentiation using operator overloading:
End of explanation
def funcad(x):
    xd = 1.0
    yd = xd
    y = x
    for i in range(30):
        yd = (xd + yd)*cos(x + y)
        y = sin(x + y)
    return yd
dfdx = funcad(xpt)
print('dfdx =', dfdx)
Explanation: Let's also compare to AD using a source code transformation method (I used Tapenade in Fortran)
End of explanation
<END_TASK>