CalculusWithJuliaNotes.jl/CwJ/makie-demos/integration.jl
2022-05-24 13:51:49 -04:00

143 lines
3.3 KiB
Julia
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AbstractPlotting
using AbstractPlotting.MakieLayout
using GLMakie
using QuadGK
function riemann(f::Function, a::Real, b::Real, n::Int; method="right")
if method == "right"
meth = f -> (lr -> begin l,r = lr; f(r) * (r-l) end)
elseif method == "left"
meth = f -> (lr -> begin l,r = lr; f(l) * (r-l) end)
elseif method == "trapezoid"
meth = f -> (lr -> begin l,r = lr; (1/2) * (f(l) + f(r)) * (r-l) end)
elseif method == "simpsons"
meth = f -> (lr -> begin l,r=lr; (1/6) * (f(l) + 4*(f((l+r)/2)) + f(r)) * (r-l) end)
end
xs = a .+ (0:n) * (b-a)/n
sum(meth(f), zip(xs[1:end-1], xs[2:end]))
end
"""
integration(f)
Show graphically the left Riemann approximation, the trapezoid approximation, and Simpson's approximation to the integral of `f` over [-1,1].
Assumes `f` is non-negative.
"""
function integration(f=nothing)
if f == nothing
f = x -> x^2*exp(-x/3)
end
a, b = -1, 1
function left_riemann_pts(n)
xs = range(a, b, length=n+1)
pts = Point2f0[(xs[1], 0)]
for i in 1:n
xᵢ, xᵢ₊₁ = xs[i], xs[i+1]
fᵢ = f(xᵢ)
push!(pts, (xᵢ, fᵢ))
push!(pts, (xᵢ₊₁, fᵢ))
end
push!(pts, (xs[end], 0))
pts
end
function trapezoid_pts(n)
xs = range(a, b, length=n+1)
pts = Point2f0[(xs[1], 0)]
for i in 1:n
xᵢ, xᵢ₊₁ = xs[i], xs[i+1]
fᵢ = f(xᵢ)
push!(pts, (xᵢ, f(xᵢ)))
end
push!(pts, (xs[end], f(xs[end])))
push!(pts, (xs[end], 0))
pts
end
function simpsons_pts(n)
xs = range(a, b, length=n+1)
pts = Point2f0[(xs[1], 0), (xs[1], f(xs[1]))]
for i in 1:n
xi, xi1 = xs[i], xs[i+1]
m = xi/2 + xi1/2
p = x -> f(xi)*(x-m)*(x - xi1)/(xi-m)/(xi-xi1) + f(m) * (x-xi)*(x-xi1)/(m-xi)/(m-xi1) + f(xi1) * (x-xi)*(x-m) / (xi1-xi) / (xi1-m)
xs = range(xi, xi1, length=10)
for j in 2:10
x = xs[j]
push!(pts, (x, p(x)))
end
end
push!(pts, (xs[end], 0))
pts
end
# where we lay our scene:
scene, layout = layoutscene()
layout.halign = :left
layout.valign = :top
p1 = layout[1,1] = LScene(scene)
p2 = layout[1,2] = LScene(scene)
p3 = layout[1,3] = LScene(scene)
n = layout[2,1] = LSlider(scene, range=2:25, startvalue=2)
output = layout[2, 2:3] = LText(scene, "...")
lpts = lift(n.value) do n
left_riemann_pts(n)
end
poly!(p1.scene, lpts, color=:gray75)
lines!(p1.scene, a..b, f, color=:black, strokewidth=10)
title(p1.scene, "Left Riemann")
tpts = lift(n.value) do n
trapezoid_pts(n)
end
poly!(p2.scene, tpts, color=:gray75)
lines!(p2.scene, a..b, f, color=:black, strokewidth=10)
title(p2.scene, "Trapezoid")
spts = lift(n.value) do n
simpsons_pts(n)
end
poly!(p3.scene, spts, color=:gray75)
lines!(p3.scene, a..b, f, color=:black, strokewidth=10)
title(p3.scene, "Simpson's")
on(n.value) do n
actual,err = quadgk(f, -1, 1)
lrr = riemann(f, -1, 1, n, method="left")
trap = riemann(f, -1, 1, n, method="trapezoid")
simp = riemann(f, -1, 1, n, method="simpsons")
Δleft = round(abs(lrr - actual), digits=8)
Δtrap = round(abs(trap - actual), digits=8)
Δsimp = round(abs(simp - actual), digits=8)
txt = "Riemann: $Δleft, Trapezoid: $Δtrap, Simpson's: $Δsimp"
output.text[] = txt
end
n.value[] = n.value[]
scene
end