Skip to content

Instantly share code, notes, and snippets.

@asinghvi17
Last active February 4, 2019 16:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save asinghvi17/2d192f7379c6abb1f5536be4f8f457b5 to your computer and use it in GitHub Desktop.
Save asinghvi17/2d192f7379c6abb1f5536be4f8f457b5 to your computer and use it in GitHub Desktop.
Julia interactive gradient ascent on a contour map (2D or 3D), can be changed to a heatmap (which is nice) or a surface (which has some bugs).
##setup
# using Pkg
# pkg"add Makie ForwardDiff"
## begin program
using Makie,
ForwardDiff
# using MakieThemes
using AbstractPlotting: textslider
# AbstractPlotting.set_theme!(ggthemr(:flat_dark))
f(x::Real, y::Real) = 2/(x^2 - 4*x + y^2 + 5) + 3/(x^2 - 4*y + y^2 + 6)
f(x::Array{T, 1} where T <: Real) = f(x[1], x[2])
∇f(x::Real, y::Real) = ForwardDiff.gradient(f, [x, y])
∇f(x::Array{Float64, 1}) = ForwardDiff.gradient(f, x)
xa = LinRange(-5, 5, 500)
ya = LinRange(-5, 5, 500)
za = [f(x, y) for x xa, y ya]
# ∇za = [∇f(x, y) for x ∈ xa, y ∈ ya]
# different plots you can see of f and grad f
# remove semicolon to display
fsurf = surface(xa, ya, za, shading = false);
# ∇fsurf = surface(xa, ya, ∇za, shading = false);
fcont = contour(xa, ya, za, levels = 20, linewidth = 3);
# ∇fcont = contour(xa, ya, ∇za, levels = 20, linewidth = 3);
fheat = heatmap(xa, ya, za);
# ∇fheat = heatmap(xa, ya, ∇za);
fcont3 = contour3d(xa, ya, za, levels = 20, linewidth = 3);
# ∇fcont3 = contour3d(xa, ya, ∇za, levels = 20, linewidth = 3);
p = fcont3;
function ascend(
Δ::Real,
x0::Real,
y0::Real;
numsteps = 10
)::Array{Float64, 2}
coords = zeros(numsteps, 2)
coords[1, 1] = x0
coords[1, 2] = y0
for i 2:numsteps
coords[i, :] = coords[i-1, :] + Δ*∇f(coords[i-1, :])
end
coords
end
p # show the plot
# setup slider
sd, delta = textslider(0.01:0.01:4, "Δ", start = 0.1)
x0 = Node(0f0)
y0 = Node(0f0)
coords = Makie.lift(ascend, delta, x0, y0)
xs = lift(x -> x[:, 1], coords)
ys = lift(x -> x[:, 2], coords)
# lines!(p, xs, ys, color = :black, linewidth = 10) # for two dimensional plots
zs = lift((x, y) -> f.(x, y), xs, ys) # for three dimensional plots
lines!(p, xs, ys, zs, color = :black, linewidth = 10)
parenta = hbox(vbox(sd), p)
# setup mouse interactiomn, kind of works but it's buggy.
# on(parenta.events.mousebuttons) do buttons
# if ispressed(parenta, Mouse.left)
# pos = to_world(parenta, Point2f0(parenta.events.mouseposition[]))
# push!(x0, pos[1])
# push!(y0, pos[2])
# end
# return
# end
parenta
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment