Chebyshev polynomials and quadrature
1.1 Question 1 (20 marks)
The Chebyshev polynomials satisfy T0(x)=1, T1(x)=x, and Tn(x)=2xT(n-1)(x)-T(n-2)(x).
(a) Write an iterative chebyshev(n,x) returning a SymPy expression, and test T0,…,T4. [3]
(b) Lambdify T6 for NumPy arrays and plot it at 200 points on [-1,1]. [3]
(c) On one axes plot T1,…,T8. [3]
(d) Write an efficient recursive version that makes only one recursive call at each level; test it
against the iterative version for n=0,…,10. [5]
(e) For n=5, use the exact roots of T5 obtained with SymPy and the Gauss-Chebyshev formula
integral from -1 to 1 of f(x)/sqrt(1-x^2) dx ~= (pi/5) sum f(xi).
Approximate the integral for f(x)=exp(x), and compare with a high-resolution trapezoidal approx-
imation after the substitution x=cos(theta). [6]
[ ]: # YOUR CODE HERE
raise NotImplementedError()
1
Worked solution and marking guidance
1.2 Question 1 (20 marks)
The Chebyshev polynomials satisfy T0(x)=1, T1(x)=x, and Tn(x)=2xT(n-1)(x)-T(n-2)(x).
(a) Write an iterative chebyshev(n,x) returning a SymPy expression, and test T0,…,T4. [3]
(b) Lambdify T6 for NumPy arrays and plot it at 200 points on [-1,1]. [3]
(c) On one axes plot T1,…,T8. [3]
(d) Write an efficient recursive version that makes only one recursive call at each level; test it
against the iterative version for n=0,…,10. [5]
(e) For n=5, use the exact roots of T5 obtained with SymPy and the Gauss-Chebyshev formula
integral from -1 to 1 of f(x)/sqrt(1-x^2) dx ~= (pi/5) sum f(xi).
Approximate the integral for f(x)=exp(x), and compare with a high-resolution trapezoidal approx-
imation after the substitution x=cos(theta). [6]
1
[2]: x=sp.symbols('x')
def chebyshev(n,x):
if n==0: return sp.Integer(1)
if n==1: return x
a,b=sp.Integer(1),x
for _ in range(2,n+1):
a,b=b,sp.expand(2*x*b-a)
return b
print([chebyshev(n,x) for n in range(5)])
T6=chebyshev(6,x)
T6f=sp.lambdify(x,T6,'numpy')
xs=np.linspace(-1,1,200)
plt.figure(); plt .plot(xs,T6f(xs))
plt.figure()
for n in range(1,9):
fn=sp.lambdify(x,chebyshev(n,x),'numpy')
plt.plot(xs,fn(xs))
def chebyshev_rec(n,x,pair=False):
if pair:
if n==1: return sp.Integer(1),x
a,b=chebyshev_rec(n-1,x,True)
return b,sp.expand(2*x*b-a)
if n==0: return sp.Integer(1)
return chebyshev_rec(n,x,True)[1]
assert all(sp.expand(chebyshev(n,x)-chebyshev_rec(n,x))==0 for n in range(11))
T5=chebyshev(5,x)
roots=sp.solve(sp.Eq(T5,0),x)
approx=float(np.pi/5*sum(np.exp(float(r)) for r in roots))
theta=np.linspace(0,np.pi,200001)
reference=float(np.trapezoid(np.exp(np.cos(theta)),theta))
print(roots,approx,reference,abs(approx-reference))
plt.show()
[1, x, 2*x**2 - 1, 4*x**3 - 3*x, 8*x**4 - 8*x**2 + 1]
[0, -sqrt(5/8 - sqrt(5)/8), sqrt(5/8 - sqrt(5)/8), -sqrt(sqrt(5)/8 + 5/8),
sqrt(sqrt(5)/8 + 5/8)] 3.977463258776694 3.977463260506423
1.7297288046336234e-09
2
3
Marking points / verification. 3 marks for the recurrence and tests; 3 for a NumPy-compatible
T6 plot; 3 for the family plot; 5 for genuinely efficient recursion and equality tests; 6 for roots,
weight pi/5, correct transformed reference integral and an accuracy comparison.