Code
Name = "YOUR NAME HERE"Assignment 3: Solving nonlinear equations in 1d and polynomial interpolation
Published: Wed 7 Oct
The assignment is worth 100 pts. The symbols ✍️, 💻 indicate theory (\(\LaTeX\)), practice (code), respectively.
Name = "YOUR NAME HERE"The following cell contains code that you should use throughout the assignment (you do not need to implement Newton’s method or the secant method yourself): Newton(f, f_prime, x1) and secant(f, x1, x2) are the functions from Lecture 5 (each returns the vector of iterates \(x_1, x_2, \dots\)) and order_table(x, ξ; α) (from A2) prints the errors \(e_n := |x_n - \xi|\) together with \(\frac{e_{n}}{e_{n-1}^\alpha}\) (approximating \(\mu\) if the order is \(\alpha\)) and \(\frac{\log e_{n}}{\log e_{n-1}}\) (approximating \(\alpha\)).
using Plots, LaTeXStrings, Printf
# Newton's method x_{n+1} = x_n - f(x_n)/f'(x_n) (from Lecture 5)
function Newton(f, f_prime, x1; N=100, tol=1e-10)
x = [x1]
for n ∈ 2:N
push!(x, x[n-1] - f(x[n-1])/f_prime(x[n-1]))
if abs(f(x[end])) < tol
return x
end
end
@warn "Newton did not converge within $N iterations."
return x
end
# secant method x_{n+1} = x_n - f(x_n)/f[x_n, x_{n-1}] (from Lecture 5)
function secant(f, x1, x2; N=100, tol=1e-10)
x = [x1, x2]
for n ∈ 3:N
push!(x, x[n-1] - (x[n-1] - x[n-2])/(f(x[n-1]) - f(x[n-2])) * f(x[n-1]))
if abs(f(x[end])) < tol
return x
end
end
@warn "secant did not converge within $N iterations."
return x
end
# prints the errors e_n = |x_n - ξ| together with
# e_n / e_{n-1}^α (\to μ if the order of convergence is α)
# log(e_n) / log(e_{n-1}) (\to order of convergence)
function order_table(x, ξ; α=1)
e = @. abs(x - ξ)
@printf("%4s %22s %12s %16s %20s\n", "n", "x_n", "e_n", "e_n/e_{n-1}^α", "log e_n/log e_{n-1}")
@printf("%4d %22.16f %12.3e\n", 1, x[1], e[1])
for n ∈ 2:length(x)
@printf("%4d %22.16f %12.3e %16.6f %20.6f\n", n, x[n], e[n], e[n]/e[n-1]^α, log(e[n])/log(e[n-1]))
end
endorder_table (generic function with 1 method)
The following theorem from lectures may be useful:
Theorem (Newton).
Suppose \(f: [a,b] \to \mathbb R\) is twice continuously differentiable with \(f(\xi) = 0\) and \(f'(\xi) \not= 0\) and that \(\left|\frac{f''(x)}{f'(y)}\right| \leq A\) for all \(x,y \in [a,b]\). Then, \(x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)}\) converges at least quadratically to \(\xi\) for all \(x_1 \in [a,b]\) with \(|x_1 - \xi| \leq A^{-1}\), and the asymptotic error constant is \(\mu = \frac12 \left| \frac{f''(\xi)}{f'(\xi)} \right|\).
Exercise 1. (Newton’s method in practice) Consider the following functions:
\[\begin{align} f_1(x) &= x^3 - 3x - 5, \nonumber\\ f_2(x) &= x - \log(1+x), \nonumber\\ f_3(x) &= \arctan x, \nonumber\\ f_4(x) &= \mathrm{sign}(x) \sqrt{|x|}. \nonumber \end{align}\]
Here’s a plot of these functions:
f1(x) = x^3 - 3x - 5
f2(x) = x - log(1 + x)
f3(x) = atan(x)
f4(x) = sign(x) * sqrt(abs(x))
plot( f1, -1, 3; ylims=(-1,2), label=L"f_1", lw=3, color=:blue )
plot!( f2, -0.99, 3; label=L"f_2", lw=3, color=:red )
plot!( f3, -1, 3; label=L"f_3", lw=3, color=:green )
plot!( f4, -1, 3; label=L"f_4", lw=3, color=:orange )
hline!( [0], linestyle=:dash, primary=false )Answer.
💻 Run Newton’s method for \(f_1\) with \(x_1 = 2\) using Newton and order_table from the code cell at the start of the assignment. If the iteration converges, estimate the order of convergence \(\alpha\) and the asymptotic error constant \(\mu\) numerically.
✍️ Find \(A\) such that \(\left|\frac{f_1''(x)}{f_1'(y)}\right| \leq A\) for all \(x, y \in [2,3]\) and compare your numerical estimate of \(\mu\) with the theoretical value \(\frac12 \left| \frac{f_1''(\xi)}{f_1'(\xi)} \right|\).
# your code hereAnswer.
💻 Run Newton’s method for \(f_2\) with \(x_1 = 0.5\) using Newton and order_table from the code cell at the start of the assignment. If the iteration converges, estimate the order of convergence \(\alpha\) and the asymptotic error constant \(\mu\) numerically.
✍️ Why does the convergence behaviour for \(f_2\) not contradict Theorem (Newton) above?
# your code hereAnswer.
💻 Run Newton’s method for \(f_3\) with \(x_1 = 0.5\) using Newton and order_table from the code cell at the start of the assignment. If the iteration converges, estimate the order of convergence \(\alpha\) and the asymptotic error constant \(\mu\) numerically.
✍️ For \(f_3\), the convergence (from \(x_1 = 0.5\)) is faster than quadratic. Explain why. What happens if you instead start at \(x_1 = 2\)? Explain.
Hint: see the discussion of Kepler’s equation (Example 5.5).
# your code hereAnswer.
💻 Run Newton’s method for \(f_4\) with \(x_1 = 0.5\) using Newton and order_table from the code cell at the start of the assignment. If the iteration converges, estimate the order of convergence \(\alpha\) and the asymptotic error constant \(\mu\) numerically.
✍️ Compute \(x_{n+1}\) explicitly in terms of \(x_n\). Hence show that Newton’s method does not converge for any \(x_1 \not= 0\). Why does this not contradict Theorem (Newton) above?
# your code hereAnswer.
The efficiency index of a method with order of convergence \(\alpha\) requiring \(\theta\) function evaluations per iteration is \(E := \alpha^{1/\theta}\). (Here, evaluating \(f\) or \(f'\) each counts as one function evaluation.)
Exercise 2. (Newton vs. secant) Let \(f_1(x) = x^3 - 3x - 5\) and \(\xi \in [2,3]\) be as in Exercise 1.
Answer.
secant from the code cell at the start of the assignment) to \(f_1\) with \(x_1 = 2, x_2 = 3\). Estimate the order of convergence and compare with the theoretical values \(\alpha = \frac{1 + \sqrt5}{2}\) and \(\mu = \left| \frac12 \frac{f_1''(\xi)}{f_1'(\xi)} \right|^{\alpha/(1+\alpha)}\) from Lecture 5.# your code hereAnswer.
Hint: use Newton and secant from the code cell at the start of the assignment. Both stop once \(|f(x_n)| <\) tol (default \(10^{-10}\)), so you may need to pass a smaller tolerance, e.g. Newton(f, f_prime, x1; tol=1e-14).
# your code hereAnswer.
Recall from Lecture 8 that, for distinct nodes \(X = \{x_0, \dots, x_n\}\), the divided differences satisfy the recursion
\[\begin{align} f[x_0, \dots, x_n] = \frac{f[x_1, \dots, x_n] - f[x_0, \dots, x_{n-1}]}{x_n - x_0}, \nonumber \end{align}\]
the polynomial interpolant can be written in Newton form
\[\begin{align} I_Xf(x) &= \sum_{k=0}^n f[x_0, \dots, x_k] \, \pi_k(x), \nonumber\\ \pi_k(x) &:= (x - x_0) \cdots (x - x_{k-1}), \nonumber \end{align}\]
and in Barycentric form
\[\begin{align} I_Xf(x) &= \left. \sum_{j=0}^n \frac{\lambda_j f(x_j)}{x - x_j} \middle/ \sum_{j=0}^n \frac{\lambda_j}{x - x_j} \right., \nonumber\\ % \lambda_j &:= \frac{1}{\prod_{k\not=j} (x_j - x_k)}. \nonumber \end{align}\]
Exercise 3. (Divided differences) Let \(f(x) = \frac1x\).
Answer.
\[\begin{align} f[x_0, \dots, x_n] = \frac{(-1)^n}{x_0 x_1 \cdots x_n}. \nonumber \end{align}\]
Check that this agrees with your table in (i).
Answer.
\[\begin{align} f(x) - I_Xf(x) = f[x_0, \dots, x_n, x] \, \ell_X(x) \nonumber \end{align}\]
where \(\ell_X(x) = (x - x_0) \cdots (x - x_n)\) is the node polynomial. Hence, using (ii), write down an exact formula for the error \(\frac1x - I_Xf(x)\) when \(f(x) = \frac1x\) (and \(x, x_0, \dots, x_n \not= 0\)).
Answer.
Exercise 4. (Newton form vs. Barycentric formula)
Answer.
divided_differences(x, y), which, given the nodes x \(= (x_0, \dots, x_n)\) and the data values y \(= \big( f(x_0), \dots, f(x_n) \big)\), returns the vector of Newton coefficients \(\big( f[x_0], f[x_0,x_1], \dots, f[x_0,\dots,x_n] \big)\) by computing the divided difference table column by column (using \(O(n^2)\) operations), and newton_eval(c, x, t), which evaluates the Newton form at \(t\) using \(O(n)\) operations by nested multiplication: \(c_0 + (t - x_0)\Big( c_1 + (t - x_1)\big( c_2 + \cdots \big) \Big)\).Run it, and use it to check your answer to Exercise 3 (i).
# Newton coefficients (f[x_0], f[x_0,x_1], ..., f[x_0,...,x_n]): the divided difference
# table is computed column by column, overwriting c in place. Here y[j] = f(x[j]) are the data values
function divided_differences(x, y)
c = float.(copy(y))
n = length(x)
for k ∈ 1:n-1 # column k of the table
for j ∈ n:-1:k+1 # bottom to top, so that c[j-1] still holds column k-1
c[j] = (c[j] - c[j-1]) / (x[j] - x[j-k])
end
end
return c
end
# evaluates the Newton form c_0 + (t - x_0)(c_1 + (t - x_1)(c_2 + ...)) by nested multiplication
function newton_eval(c, x, t)
p = c[end]
for k ∈ length(c)-1:-1:1
p = c[k] + (t - x[k]) * p
end
return p
end
# test: g(x) = x^3 on 4 nodes has divided differences g[x_0,...,x_3] = 1 and is reproduced exactly
g(x) = x^3
X = [1, 2, 4, 1/2]
c = divided_differences(X, g.(X))
println("Newton coefficients of x^3 on X: ", c)
println("p(3) = ", newton_eval(c, X, 3), ", g(3) = ", g(3))ChebyshevInterpolant from Lecture 8). Run it.# Barycentric formula for Chebyshev nodes of the second kind (from Lecture 8)
function ChebyshevInterpolant( f, n )
x = @. cos( π*(0:n)/n )
y = @. f( x )
λ = @. (-1.0)^(0:n)
λ[1] /= 2
λ[end] /= 2
return function ( t )
num = 0.0
den = 0.0
for j ∈ 1:(n+1)
if t == x[j]
return y[j]
end
num += λ[j] * y[j] / (t - x[j])
den += λ[j] / (t - x[j])
end
return num / den
end
end
Runge(x) = 1/(1 + 25x^2)
egrid = range(-1, 1, length=2001)
for (name, f) ∈ [("1/(1 + 25x^2)", Runge), ("exp(x)", exp)]
println("f(x) = ", name)
@printf("%5s %16s %16s\n", "n", "error (Newton)", "error (Bary)")
for n ∈ [10, 20, 40, 80, 160]
x = @. cos( π*(0:n)/n )
coeffs = divided_differences(x, f.(x))
p = ChebyshevInterpolant(f, n)
err_newton = maximum( abs(newton_eval(coeffs, x, t) - f(t)) for t ∈ egrid )
err_bary = maximum( abs(p(t) - f(t)) for t ∈ egrid )
@printf("%5d %16.2e %16.2e\n", n, err_newton, err_bary)
end
println()
endAnswer.
Hint: In the Newton form, the coefficient \(f[x_0, \dots, x_k]\) is multiplied by \(\omega_k(t) := \prod_{i<k} (t - x_i)\). How large is \(|\omega_k(t)|\) for \(t\) near \(-1\) when the nodes are in their original order \(1 = x_0 > x_1 > \cdots\)? What about with the Leja ordering?
# Leja ordering: start at a node of largest |x|, then repeatedly choose the remaining node that
# maximises the product of distances to the nodes already chosen (sums of logs avoid overflow)
function leja_order(x)
x = float.(collect(x))
i = argmax(abs.(x))
order = [i]
s = zeros(length(x)) # s[j] = sum of log|x[j] - x[i]| over chosen nodes i
for k ∈ 2:length(x)
s .+= log.(abs.(x .- x[i]))
s[order] .= -Inf
i = argmax(s)
push!(order, i)
end
return x[order]
end
for (name, f) ∈ [("1/(1 + 25x^2)", Runge), ("exp(x)", exp)]
println("f(x) = ", name)
@printf("%5s %16s %16s %16s\n", "n", "error (Newton)", "error (Leja)", "error (Bary)")
for n ∈ [10, 20, 40, 80, 160]
x = @. cos( π*(0:n)/n )
coeffs = divided_differences(x, f.(x))
xL = leja_order(x)
coeffsL = divided_differences(xL, f.(xL))
p = ChebyshevInterpolant(f, n)
err_newton = maximum( abs(newton_eval(coeffs, x, t) - f(t)) for t ∈ egrid )
err_leja = maximum( abs(newton_eval(coeffsL, xL, t) - f(t)) for t ∈ egrid )
err_bary = maximum( abs(p(t) - f(t)) for t ∈ egrid )
@printf("%5d %16.2e %16.2e %16.2e\n", n, err_newton, err_leja, err_bary)
end
println()
endAnswer.
Goal: Reflect on your learning strategies, track your workload, and help us improve future course material.
Time: take 5-10 mins (this shouldn’t take too long)
Estimate the approximate hours you spent:
* Assignment: ____
* Reading notes/materials: ____
* Exercises: ____
(Reminder: you should be spending around 8 hours per week on this course outside of the 4 hours of lectures)
Any other comments:
Take a moment to reflect on your learning over the past two weeks:
What was the easiest topic or task and why? Where did you struggle, and how did you overcome those challenges? Which resources (e.g. lecture notes, practice exercises, peer discussions, …) helped you the most? How did you manage your time and workload (e.g., all at once, spread out over several days, or working with peers)? Looking back, what would you do differently if you were starting these two weeks over today?
Comments:
(Optional) Any changes that would improve the lectures, exercises, or assignments for the future? You can also suggest things anonymously here (opens in a new tab)
Comments: