# How to plot Newton's method

I’m looking at how to plot Newton’s method. I was going to add x values of each itteration, with y=0 to a DataFrame, then run a scatter plot. Is this what I should do, or is there a better way to go about this?

Probably you just need a vector of data. A DataFrame is a unnecessary complication.

6 Likes

You could also plot the tangents, like eg this:

3 Likes

Plotting \log(\| F(x_n) \|) vs n should tell you what you want to know. Semilog plots are the standard way to do this so you can see what is happening in the terminal phase of the iteration.

If you have a scalar equation and want to plot f(x_n) vs x_n, a semilog plot is still the way to go. If you want to plot x_n vs n, a scatter plot makes sense. You can plot your results with the graph of f(x) as an overlay. This is not as fancy was the moving graph that @Tamas_Papp points to, but is easy to do.

As @lmiq says, a DataFrame is overkill for this.

1 Like

That’s what I wanted, I’ll go over how to do this. I always forget the formula for a tangent.

``````(f(x)-b)/f'(x)=x
``````

then I can’t remember how to find b.

That’s interesting. I’m not familiar with semilog plots, and I’m learning linear algebra, so I’m not sure how to write that as code.

As for data frames, I don’t think it’s an issue, but in Maple it creates a crazy large file, so I see where it’s not the best option.

Is a vector a csv? I don’t know how to do data in a matrix.

No, a vector is just a list of numbers. You can crate one with (assuming you are storing numbers):

``````x = Float64[]
``````

And then add data to it with, for instance,

``````push!(x,1.2321)
``````

The resulting `x` is what you need to plot something.

thanks.

1 Like

This could be improved, but Makie offers a nice way to explore Newton’s method and its dependence on the initial value. If you install enough packages to get this to run, dragging the initial points shows the method pretty clearly.

``````using AbstractPlotting
using AbstractPlotting.MakieLayout
using GLMakie

using ForwardDiff
D(f) = x -> ForwardDiff.derivative(f, float(x))

function newton(f=x->x^5 - x - 1, x0=1, a=-1, b=1.5, n = 20)

idx = Ref(0); dragstart = Ref(false); startpos = Base.RefValue(Point2f0(0))
on(events(scene).mousedrag) do drag
if ispressed(scene, Mouse.left)
if drag == Mouse.down
plot, _idx = mouse_selection(scene)
if plot == pplot
idx[] = _idx; dragstart[] = true
startpos[] = to_world(scene, Point2f0(scene.events.mouseposition[]))
end
elseif drag == Mouse.pressed && dragstart[] && checkbounds(Bool, points[], idx[])
pos = to_world(scene, Point2f0(scene.events.mouseposition[]))

# we work with components, not vector
x,y = pos

ptidx = idx[]

x = clamp(x, a, b)
y = zero(y)
points[][idx[]] = [x,y]

points[] = points[]
end
else
dragstart[] = false
end
return
end
end

start_point = Node(Point2f0[(x0, 0)])
points = lift(start_point) do x₀
xs = [x₀[1][1]]
for i in 1:n
xᵢ₋₁ = xs[end]
xᵢ = xᵢ₋₁ - f(xᵢ₋₁) /D(f)(xᵢ₋₁)
push!(xs, xᵢ)
end
xs
end

plt_points = lift(points) do pts
xs = Float64[]
ys = Float64[]
for i in 1:length(pts)-1
pᵢ, pᵢ₊₁ = pts[i], pts[i+1]
append!(xs, [pᵢ, pᵢ, pᵢ₊₁])
append!(ys, [0, f(pᵢ), 0])
end
(xs, ys)
end

scene = Scene()
lines!(scene, a..b, f, linewidth=5, color=:blue)
lines!(scene, a..b, zero, color=:red)
lines!(scene, plt_points, color=:black, linewidth=2)
scatter!(scene, start_point, color=:red)

scene
end
``````
1 Like

I ran it. I get warnings from packages but no errors. Is it supposed to output a plot?

Try: newton()

scatter! not defined.

It might be missing a package, or that could be a syntax error.

That’s from AbstractPlotting, or should be.

Ok, I’m using Jupyter, does it matter if the using commands are in the same code chunk as other code?

I get the scatter not defined error when I run

Try:newton()

I only ran from a terminal. I’m not sure, but WGLMakie might work in place of GLMakie.

1 Like

For an x, given f(x) and f'(x), if you want the tangent as y = a + bx, then just match values and derivatives, ie f(x) = a + bx and f'(x) = b, obtaining a = f(x) - x f'(x).

5 Likes

using Plots
using ForwardDiff
f(x)=((x)^6)-2
fp(x)= ForwardDiff.derivative(f, x)
t(x)=-1*(f(x)-xfp(x)+fp(x))
P1=plot(f,1:.001:1.55,legend=false);hline!([0])
for i in 1:9
root=x
x=BigFloat(x)-BigFloat(f(x)/fp(x))
e=BigFloat(abs((x)-(root)))
push!(df,(x,e,f(x)))
t(x)=-(f(root)-x
fp(root)+fp(root))
plot!(t,1:.001:1.55)
vline!([root])
end

``this gives me lines with the correct slope, but they don't move with root or x, to be tangents.``

Okay, this should work in Jupyter. The `@manipulate` macro from `SimplePlots` allows the interaction with the initial point.

``````using Plots, Interact
using ForwardDiff
D(f) = x -> ForwardDiff.derivative(f, float(x))
f(x)  = x^5 - x - 1
a, b = -1.5, 1.5
nsteps = 20
@manipulate for x0=slider(a:0.1:b, value=1.0, label="x0")
ts = range(a, b, length=251)
plot(ts, f.(ts), xlim=(a,b), ylim=(-5,5), legend=false)
plot!(ts, 0 .* ts)
scatter!([x0],[0])

xs = Float64[]
ys = Float64[]
for i in 1:nsteps
x1 = x0 - f(x0)/D(f)(x0)
append!(xs, [x0, x0, x1])
append!(ys, [0,f(x0), 0])
x0 = x1
end

plot!(xs, ys)

end
``````

[Edited to use Plots+Interact]

I,m getting slider not defined

``````UndefVarError: slider not defined

Stacktrace:
[1] top-level scope at C:\Users\Brett\.julia\packages\SimplePlots\6y94O\src\interact\gui.jl:39