Skip to content
Snippets Groups Projects
Commit b82a9fab authored by Fredrik Bagge Carlson's avatar Fredrik Bagge Carlson
Browse files

update astar

parent ff23bf0d
Branches
Tags
No related merge requests found
...@@ -8,3 +8,4 @@ jump_lin_id/build ...@@ -8,3 +8,4 @@ jump_lin_id/build
*.jld *.jld
*.mat *.mat
*.m *.m
Fit/*
import Base.Collections: heappop!, heappush!, isheap, heapify! using DataStructures: heappop!, heappush!, isheap, heapify!
import Base: ==, .==, show, isequal, isless import Base: ==, .==, show, isequal, isless
using Base.Test using Base.Test
typealias Coord Tuple{Int,Int} const Coord = Tuple{Int,Int}
abstract AbstractNode abstract type AbstractNode end
type StartNode <: AbstractNode end struct StartNode <: AbstractNode end
type GoalNode <: AbstractNode end struct GoalNode <: AbstractNode end
type UnknownNode <: AbstractNode end struct UnknownNode <: AbstractNode end
type MatrixNode <: AbstractNode mutable struct MatrixNode <: AbstractNode
c::Coord c::Coord
f::Float64 f::Float64
g::Float64 g::Float64
...@@ -20,7 +20,6 @@ show(io::IO,n::MatrixNode) = print(io,"MatrixNode(c=",n.c,", f,g=",round(n.f,3), ...@@ -20,7 +20,6 @@ show(io::IO,n::MatrixNode) = print(io,"MatrixNode(c=",n.c,", f,g=",round(n.f,3),
.==(a::MatrixNode,b::MatrixNode) = a.c == b.c .==(a::MatrixNode,b::MatrixNode) = a.c == b.c
isless(a::MatrixNode,b::MatrixNode) = isless(a.f, b.f) isless(a::MatrixNode,b::MatrixNode) = isless(a.f, b.f)
distance(a,b) = b.cost + ((a.c[1]-b.c[1])^2 + (a.c[2]-b.c[2])^2) distance(a,b) = b.cost + ((a.c[1]-b.c[1])^2 + (a.c[2]-b.c[2])^2)
heuristic(a,b)::Float64 = ((a[1]-b[1])^2 + (a[2]-b[2])^2) # TODO, this does not accept MatrixNode due to recursive data structure..
function neighbors(current::MatrixNode,G)::Vector{MatrixNode} function neighbors(current::MatrixNode,G)::Vector{MatrixNode}
N = size(G,1) N = size(G,1)
i,j = current.c i,j = current.c
...@@ -41,7 +40,7 @@ end ...@@ -41,7 +40,7 @@ end
reconstruct_path(current) = reconstruct_path(current, typeof(current)[]) reconstruct_path(current) = reconstruct_path(current, typeof(current)[])
# Generate graph (matrix) # Generate graph (matrix)
i == 0 #
function astar{T}(G::Matrix{T},startc,goalc) function astar{T}(G::Matrix{T},startc,goalc)
time0 = tic() time0 = tic()
...@@ -101,7 +100,7 @@ end ...@@ -101,7 +100,7 @@ end
function run_astar(N) function run_astar(N)
G = MatrixNode[MatrixNode((i,j),Inf,Inf,rand(1:50), UnknownNode()) for i = 1:N, j=1:N] G = MatrixNode[MatrixNode((i,j),Inf,Inf,rand(1:50), UnknownNode()) for i = 1:N, j=1:N]
nf = 5 nf = 5
costs = conv2(Float64.(abs(randn(N,N))), ones(nf,nf)/nf^2)[nf÷2:end-nf÷2,nf÷2:end-nf÷2] costs = conv2(Float64.(abs.(randn(N,N))), ones(nf,nf)/nf^2)[nf÷2:end-nf÷2,nf÷2:end-nf÷2]
costs = costs[1:N,1:N] costs = costs[1:N,1:N]
# costs[20:22,10:40] = 50 # costs[20:22,10:40] = 50
...@@ -112,40 +111,49 @@ function run_astar(N) ...@@ -112,40 +111,49 @@ function run_astar(N)
# costs[i,i+10] *= 0.8 # costs[i,i+10] *= 0.8
# end # end
assign_costs!(G,costs) assign_costs!(G,costs)
G2 = deepcopy(G)
startc = (1,1) startc = (1,1)
goalc = (N-1,N) goalc = (N-1,N)
path1 = astar(G,startc,goalc) t = @elapsed path = astar(G,startc,goalc)
@assert all(n.f == Inf for n in G2)
gc()
path2 = similar(path1)
t = @elapsed begin
path2 = astar(G2,startc,goalc)
end
@assert all(path1 .== path2)
@assert all(G .== G2)
t t
end end
t = run_astar(100)
Nvec = round(Int, logspace(log10(5), log10(400), 30) ) function test_and_plot(label)
t = run_astar(100)
Nvec = round.(Int, logspace(1, log10(400), 20) )
Nmat = Nvec Nmat = Nvec
# Nmat = repmat(Nvec',10) |> vec
times = map(run_astar,Nmat) times = map(run_astar,Nmat)
# average_times = [mean(times[Nmat .== N]) for N in Nvec]
# median_times = [median(times[Nmat .== N]) for N in Nvec]
# std_times = [std(times[Nmat .== N]) for N in Nvec]
Alog = Float64.(Nmat.^(0:1)') Alog = Float64.(Nmat.^(0:1)')
Alog[:,2:end] = log(Alog[:,2:end]) Alog[:,2:end] = log.(Alog[:,2:end])
xlog = Alog\log(times) xlog = Alog\log.(times)
# plot(Nvec, average_times, yerror=std_times, lab="Average time")
# plot!(Nvec, median_times, yerror=std_times, lab="Median time") scatter!(Nmat,times, lab=label, yscale=:log10, xscale=:log10,
scatter(Nmat,times, lab="Times") xlabel="Problem size", ylabel="Execution time [s]")
plot!(Nmat, A*x, lab="Model fit", yscale=:log10, xscale=:log10) # plot!(Nmat, exp.(Alog*xlog), lab="Log-Model fit")
plot!(Nmat, exp(Alog*xlog), lab="Log-Model fit", yscale=:log10, xscale=:log10) gui()
end
plot()
heuristic(a,b)::Float64 = ((a[1]-b[1])^2 + (a[2]-b[2])^2)
test_and_plot("L2")
heuristic(a,b)::Float64 = 0.5*((a[1]-b[1])^2 + (a[2]-b[2])^2)
test_and_plot("0.5 L2")
heuristic(a,b)::Float64 = 0.1*((a[1]-b[1])^2 + (a[2]-b[2])^2)
test_and_plot("0.1 L2")
heuristic(a,b)::Float64 = ((a[1]-b[1])^2 + (a[2]-b[2])^2)^(1/4)
test_and_plot("sqrt(L2)")
heuristic(a,b)::Float64 = log(abs(a[1]-b[1])) + log(abs(a[2]-b[2]))
test_and_plot("log-manhattan")
# costs = [n.cost for n in G] # costs = [n.cost for n in G]
... ...
......
...@@ -69,7 +69,7 @@ function astar{T}(G::Matrix{T},startc,goalc) ...@@ -69,7 +69,7 @@ function astar{T}(G::Matrix{T},startc,goalc)
return path return path
end end
push!(closed, current) push!(closed, current)
for neighbor in neighbors(current,G) for neighbor neighbors(current,G)
if neighbor ∈ closed if neighbor ∈ closed
continue continue
end end
...@@ -95,7 +95,7 @@ end ...@@ -95,7 +95,7 @@ end
```julia; echo=false ```julia; echo=false
function assign_costs!{T<:AbstractNode}(G::AbstractMatrix{T},costs) function assign_costs!{T<:AbstractNode}(G::AbstractMatrix{T},costs)
for (g,c) in zip(G,costs) for (g,c) zip(G,costs)
g.cost = c g.cost = c
end end
end end
...@@ -164,12 +164,9 @@ test_and_plot("sqrt(L2)") ...@@ -164,12 +164,9 @@ test_and_plot("sqrt(L2)")
plot!(show=true) plot!(show=true)
``` ```
# Comments
It seems convergence is faster for heuristics which underestimate the cost to go.
The L2 heuristic, which is the true cost to go, performs worst in terms of execution time.
$\pagebreak$
# Cost landscape # Cost landscape
```julia ```julia
heuristic(a,b)::Float64 = √((a[1]-b[1])^2 + (a[2]-b[2])^2) heuristic(a,b)::Float64 = √((a[1]-b[1])^2 + (a[2]-b[2])^2)
...@@ -195,5 +192,21 @@ pathx = [n.c[1] for n in path] ...@@ -195,5 +192,21 @@ pathx = [n.c[1] for n in path]
pathy = [n.c[2] for n in path] pathy = [n.c[2] for n in path]
heatmap(log.(costs)) heatmap(log.(costs))
scatter!(pathy,pathx, c=:red, show=true) scatter!(pathy,pathx, c=:red, show=true, title="L2")
```
```julia
heuristic(a,b)::Float64 = 0.5*√((a[1]-b[1])^2 + (a[2]-b[2])^2)
G = MatrixNode[MatrixNode((i,j),Inf,Inf,rand(1:50), UnknownNode()) for i = 1:N, j=1:N]
assign_costs!(G,costs)
path = astar(G,startc,goalc)
pathx = [n.c[1] for n in path]
pathy = [n.c[2] for n in path]
heatmap(log.(costs))
scatter!(pathy,pathx, c=:red, show=true, title="0.5 L2")
``` ```
# Comments
It seems convergence is faster for heuristics which underestimate the cost to go.
The L2 heuristic, which is the true cost to go, performs worst in terms of execution time.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment