Question 1
Question 1 (20 marks)
The supplied legendre_poly generates the Legendre polynomial P_n(x) iteratively.
(a) Test P_0 through P_4 as exact SymPy expressions. [2]
(b) Lambdify P_6 for NumPy arrays and plot it on 200 points of [-1,1]. [3]
(c) Write an efficient recursive version using only one recursive call at each level, and compare it with the iterative function for
n=0,...,8. [5]
(d) Find the four exact roots of P_4 and the corresponding Gauss-Legendre weights 2/((1-xi**2)*P_4'(xi)**2) as floats.
[5]
(e) Use those roots and weights to approximate integral_0^1 exp(-x) dx, and compare with 1-exp(-1). [5]
Answer area
Worked solution and marking guidance
Question 1 (20 marks)
Recognition signal. A three-term polynomial recurrence, exact symbolic roots and a quadrature formula based on those roots.
First key step. Keep the pair (P_{n-1},P_n) together; this is also the key to an efficient one-call recursive version.
Course-method chain. exact recurrence -> lambdify/plot -> pair-return recursion -> roots/derivative/weights -> affine interval
transform and weighted sum.
Marking points. 2+3+5+5+5.
Common errors. Two recursive calls per level; converting to float too early; using P5 derivative with P4 roots; omitting the interval
scaling factor.
Final self-check. The quadrature value should agree with 1-exp(-1) to many digits.
Historical-basis and difficulty audit
- Historical formal-question basis: 2022-23 Assessment 3 Q1(a-f)
- Accessible course-material basis: 2022-23 official marking scheme
- Historical ability gap filled: Legendre recurrence, symbolic-to-numerical conversion, roots and weights, and Gauss quadrature
- Equivalent 2026 difficulty unit: 2026 Q1 (20-mark highly abstract integrated question)
- Why equivalent: the original 35-mark question is compressed to 20 marks, retaining recurrence, lambdify, roots/weights and one integral; approximately 20 minutes.
x=sp.symbols('x')
print([legendre_poly(n,x) for n in range(5)])
p6=legendre_poly(6,x); f6=sp.lambdify(x,p6,'numpy'); xx=np.linspace(-1,1,200)
plt.figure(); plt.plot(xx,f6(xx)); plt.show()
MATH40006_COURSE_METHOD_AUDITED_Mock_4_Solutions Page 1
def legendre_recursive(n,x,pair=False):
if pair:
if n==1:return sp.Integer(1),x
pa,pb=legendre_recursive(n-1,x,True)
return pb,sp.together(sp.expand(((2*n-1)*x*pb-(n-1)*pa)/n))
if n==0:return sp.Integer(1)
return legendre_recursive(n,x,True)[1]
print(all(sp.simplify(legendre_poly(n,x)-legendre_recursive(n,x))==0 for n in range(9)))
p4=legendre_poly(4,x); dp4=sp.diff(p4,x); roots=sp.solve(sp.Eq(p4,0),x)
weights=[float(2/((1-r**2)*dp4.subs(x,r)**2)) for r in roots]
vals=[math.exp(-float((r+1)/2)) for r in roots]
approx=0.5*np.dot(weights,vals); exact=1-math.exp(-1)
print(roots); print(weights); print(approx,exact,abs(approx-exact))
[1, x, (3*x**2 - 1)/2, x*(5*x**2 - 3)/2, (35*x**4 - 30*x**2 + 3)/8]
True
[-sqrt(3/7 - 2*sqrt(30)/35), sqrt(3/7 - 2*sqrt(30)/35), -sqrt(2*sqrt(30)/35 + 3/7), sqrt(2*sqrt(30)/35 +
3/7)]
[0.6521451548625461, 0.6521451548625461, 0.34785484513745385, 0.34785484513745385]
0.6321205584853381 0.6321205588285577 3.4321956388083663e-10