Tutorial 2
Click the badges above to run this tutorial interactively in your browser without installing anything!
- Binder: Free cloud-based Jupyter environment
- Colab: Google's free Jupyter notebook environment
Topics Covered
This tutorial covers the following topics using Python and SymPy:
- Partial Derivatives: Using limit definition and rules.
- Chain Rule: For composite functions.
- Implicit Differentiation: For multivariable functions.
- Jacobians: For transformations.
Introduction
Sympy: SymPy is a Python library for symbolic mathematics. We will use this library to solve all the tutorials.
import sympy as sy
from sympy.abc import x, y, z, s, t, r, theta, u, v, alpha # variables
from sympy.solvers import solve # Solving equations
from sympy import sqrt,tan,sin,cos,sec,pi,root,ln, E
from sympy import log,exp,atan,asinh,atanh,asin # Import all required math function
from sympy import diff, idiff, Matrix # Solving differentiation
from sympy import simplify, Rational # Simplifying expressions
sy.init_printing(use_latex=True) # Show it in natural display
Question 1
Find the partial derivative and of these functions using the limit definition
a.
f = x**2*y + 2*x + y**3
display(diff(f, x))
display(diff(f, y))
b.
f = x**2 - 4*x*y + y**2
display(diff(f, x))
display(diff(f, y))
c.
f = 2*x**3 + 3*x*y - y**2
display(diff(f, x))
display(diff(f, y))
Question 2
Determine all the first and second order partial derivatives of the function
a.
f = x**2*y**3 + 3*y + x
display(diff(f, x))
display(diff(f, y))
display(diff(f, x, x))
display(diff(f, x, y))
display(diff(f, y, x))
display(diff(f, y, y))
b.
f = x**4*sin(3*y)
display(diff(f, x))
display(diff(f, y))
display(diff(f, x, x))
display(diff(f, x, y))
display(diff(f, y, x))
display(diff(f, y, y))
c.
f = x**2*y + ln(y**2 - x)
display(diff(f, x))
display(diff(f, y))
display(diff(f, x, x))
display(diff(f, x, y))
display(diff(f, y, x))
display(diff(f, y, y))
d.
f = exp(x*y)*(2*x - y)
display(diff(f, x))
display(diff(f, y))
display(diff(f, x, x))
display(diff(f, x, y))
display(diff(f, y, x))
display(diff(f, y, y))
Question 3
Find both partial derivatives for each of the following two variables functions
a.
g = y*exp(x+y)
display(diff(g, x))
display(diff(g, y))
b.
h = x*sin(y) - y*cos(x)
display(diff(h, x))
display(diff(h, y))
c.
p = x**y + y**2
display(diff(p, x))
display(diff(p, y))
d.
U = (9*y**3)/(x-y)
display(diff(U, x))
display(diff(U, y))
Question 4
For , use the implicit function theorem to find and
a.
f = x**2*y**3 + z**2 + x*y*z
dydx = -diff(f, x) / diff(f, y)
dydz = -diff(f, z) / diff(f, y)
display(dydx)
display(dydz)
b.
f = x**3*z**2 + y**3 + 4*x*y*z
dydx = -diff(f, x) / diff(f, y)
dydz = -diff(f, z) / diff(f, y)
display(dydx)
display(dydz)
c.
f = 3*x**2*y**3 + x*z**2*y**2 + y**3*z*x**4 + y**2*z
dydx = -diff(f, x) / diff(f, y)
dydz = -diff(f, z) / diff(f, y)
display(dydx)
display(dydz)
Question 5
Find and , if applicable, for the following composite functions
a. where and
F = sin(x+y)
x_s = 2*s*t
y_s = s**2 + t**2
F_s = F.subs([(x, x_s), (y, y_s)])
display(diff(F_s, s))
display(diff(F_s, t))
b. where and
F = ln(x**2 + y)
x_st = exp(s+t**2)
y_st = s**2 + t
F_st = F.subs([(x, x_st), (y, y_st)])
display(diff(F_st, s))
display(diff(F_st, t))
c. where and
F = x**2*y**2
x_st = s*cos(t)
y_st = s*sin(t)
F_st = F.subs([(x, x_st), (y, y_st)])
display(diff(F_st, s))
display(diff(F_st, t))
d. where and
F = x*y + y*z**2
x_t = E**t
y_t = E**t*sin(t)
z_t = E**t*cos(t)
F_t = F.subs([(x, x_t), (y, y_t), (z, z_t)])
display(diff(F_t, t))
Question 6
Find and (if applicable) for each of the following
a.
f = 7*x**2 + 2*x*y**2 + 9*y**4
dydx = idiff(f, y, x)
display(dydx)
b.
f = x**3*z**2 + y**3 + 4*x*y*z
dydx = idiff(f, y, x)
dydz = idiff(f, y, z)
display(dydx)
display(dydz)
c.
f = 3*x**2*y**3 + x*z**2*y**2 + y**3*z*x**4 + y**2*z
dydx = idiff(f, y, x)
dydz = idiff(f, y, z)
display(dydx)
display(dydz)
d.
f = y**5 + x**2*y**3 - (1 + y*exp(x**2))
dydx = idiff(f, y, x)
display(dydx)
Question 7
a. In polar coordinates, , show that
X = Matrix([r*cos(theta), r*sin(theta)])
Y = Matrix([r, theta])
J = X.jacobian(Y)
display(J)
display(J.det())
b. Obtain the Jacobian of the transformation and determine the inverse of the transformation . Confirm that .
S = Matrix([2*x+y, x-2*y])
X = Matrix([x, y])
J = S.jacobian(X)
display(J)
display(J.det())
# Inverse
sol = solve([s - (2*x+y), t - (x-2*y)], (x, y))
x_st = sol[x]
y_st = sol[y]
X_st = Matrix([x_st, y_st])
S_st = Matrix([s, t])
J1 = X_st.jacobian(S_st)
display(J1)
display(J1.det())
display(J.inv())
c. Show that if and , then .
# x = u - y => x = u - uv
x_uv = u - u*v
y_uv = u*v
X = Matrix([x_uv, y_uv])
Y = Matrix([u, v])
J = X.jacobian(Y)
display(J)
display(J.det())
d. Verify whether the functions and are functionally dependent.
u_xy = (x+y)/(1-x*y)
v_xy = atan(x) + atan(y)
U = Matrix([u_xy, v_xy])
X = Matrix([x, y])
J = U.jacobian(X)
display(J)
display(J.det().simplify())
The Jacobian is 0, so the functions are functionally dependent.
e. If , find .
jacobian = Matrix([[diff(u*v, u), diff(u*v, v)],
[diff((u+v)/(u-v), u), diff((u+v)/(u-v), v)]])
display(simplify(jacobian.det())) # ∂(x,y)/∂(u,v) = 4uv/(u-v)²
display(simplify(1 / jacobian.det())) # ∂(u,v)/∂(x,y) = (u-v)²/(4uv)
The question asks for , which is the reciprocal of the Jacobian we just computed:
Two sign/typo defects in the printed solution are avoided automatically by SymPy:
- Q2d — the printed mixed partial should be .
diff(f, x, y)returns the correct expression, and it agrees withdiff(f, y, x)as Clairaut's theorem requires. - Q7e — , not . With the printed (wrong) sign the Jacobian determinant would be instead of .
Question 8
Error and sensitivity analysis, using the increment (total differential) approximation .
a. How sensitive is to small changes in and near ?
# Q3 above already used `g` and `h` as function names, so rebind them to plain symbols
# here — otherwise `V = pi*r**2*h` would silently contain that earlier expression.
h, l, g = sy.symbols('h l g')
V = pi*r**2*h
V_r, V_h = diff(V, r), diff(V, h)
display(V_r, V_h) # 2*pi*h*r, pi*r**2
display(V_r.subs({r: 1, h: 3}), V_h.subs({r: 1, h: 3})) # 6*pi, pi
A one-unit change in shifts by about ; a one-unit change in shifts it by about . Near the volume is therefore roughly 6 times as sensitive to as it is to .
Now reverse the pair, so that and :
display(V_r.subs({r: 3, h: 1}), V_h.subs({r: 3, h: 1})) # 6*pi, 9*pi
The -sensitivity is unchanged at when the pair is swapped, because it depends only on the product ; only moves, and that is what makes the volume sensitive to instead. So the sensitivity to a change depends not only on the increment but on the relative size of and .
b. If is measured to and to , how accurately can be found?
Taking logarithms, , so .
display(Rational(2, 100) + Rational(1, 200)) # 1/40
display((Rational(2, 100) + Rational(1, 200))*100) # 5/2 -> 2.5 per cent
so the maximum percentage error in is about .
c. , with errors up to in and in .
T = 2*pi*sqrt(l/g)
display(simplify(diff(T, l)*l/T)) # 1/2
display(simplify(diff(T, g)*g/T)) # -1/2
The elasticities are for and for , so
display(Rational(1, 2)*Rational(1, 100) + Rational(1, 2)*Rational(2, 100)) # 3/200
display((Rational(1, 2)*Rational(1, 100) + Rational(1, 2)*Rational(2, 100))*100) # 3/2
The maximum percentage error in is .
d. , with a error in and a error in .
R = v**2*sin(2*alpha)/g
display(simplify(diff(R, v)*v/R)) # 2
display(simplify(diff(R, alpha)*alpha/R)) # 2*alpha/tan(2*alpha)
Since ,
so the percentage error is .
Question 9
Find the tangent plane and the normal line to each surface at the given point.
For a level surface , the gradient evaluated at the point is a normal vector, so the tangent plane is and the normal line has direction ratios .
def grad(f):
return Matrix([diff(f, x), diff(f, y), diff(f, z)])
def tangent_plane(f, pt):
"""Normal vector and tangent plane for the level surface f = 0 at pt."""
n = grad(f).subs(pt)
return n, sy.expand(n[0]*(x - pt[x]) + n[1]*(y - pt[y]) + n[2]*(z - pt[z]))
a. at
n, plane = tangent_plane(x**2 + 2*y**2 + 3*z**2 - 6, {x: 1, y: 1, z: 1})
display(n) # <2, 4, 6>
display(plane) # 2*x + 4*y + 6*z - 12
display(simplify(plane/2)) # x + 2*y + 3*z - 6
Tangent plane ; normal line .
b. at
n, plane = tangent_plane(2*x**2 + y**2 - z**2 + 3, {x: 1, y: 2, z: 3})
display(n) # <4, 4, -6>
display(simplify(plane/2)) # 2*x + 2*y - 3*z + 3
Tangent plane ; normal line .
c. at
n, plane = tangent_plane(x**2 + y**2 - z - 1, {x: 1, y: 2, z: 4})
display(n, plane) # <2, 4, -1>, 2*x + 4*y - z - 6
Tangent plane ; normal line .
d. at
f = ln(x/y) - z**2*(x - 2*y) - 3*z - 3
display(simplify(f.subs({x: 4, y: 2, z: -1}))) # log(2) -> the point is NOT on f = 0
n, plane = tangent_plane(f, {x: 4, y: 2, z: -1})
display(n) # <-3/4, 3/2, -3>
display(plane) # -3*x/4 + 3*y/2 - 3*z - 3
The given point does not satisfy the printed equation: . So no tangent plane exists at for that level surface. The gradient and plane above belong to the surface that actually passes through the point (right-hand side ) — which is what the printed solution intended to compute.
e. at
n, plane = tangent_plane(x**3*z + z**3*x - 2*y*z, {x: 1, y: 1, z: 1})
display(n) # <4, -2, 2>
display(simplify(plane/2)) # 2*x - y + z - 2
Tangent plane ; normal line .
f. at
n, plane = tangent_plane((x - 1)**2 + (y + 2)**2 - z + 5, {x: 2, y: 0, z: 10})
display(n, plane) # <2, 4, -1>, 2*x + 4*y - z + 6
Tangent plane ; normal line .
g. at
n, plane = tangent_plane(x**2/12 + y**2/6 + z**2/4 - 1, {x: 1, y: 2, z: 1})
display(n) # <1/6, 2/3, 1/2>
display(sy.expand(6*plane)) # x + 4*y + 3*z - 12
Tangent plane ; normal line .
h. at
n, plane = tangent_plane(z*exp(x) + exp(z + 1) + x*y + y - 3, {x: 0, y: 3, z: -1})
display(n, plane) # <2, 1, 2>, 2*x + y + 2*z - 1
Tangent plane ; normal line .