Skip to content

Commit

Permalink
Merge pull request #8 from bartoszpankratz/master
Browse files Browse the repository at this point in the history
Added A* search algorithm implementation
  • Loading branch information
pszufe committed Mar 10, 2019
2 parents 3f0b7d4 + bf05295 commit 31fb4e1
Show file tree
Hide file tree
Showing 9 changed files with 269 additions and 68 deletions.
26 changes: 13 additions & 13 deletions Manifest.toml
Expand Up @@ -15,15 +15,15 @@ version = "0.5.3"

[[CodecZlib]]
deps = ["BinaryProvider", "Libdl", "Test", "TranscodingStreams"]
git-tree-sha1 = "e3df104c84dfc108f0ca203fd7f5bbdc98641ae9"
git-tree-sha1 = "36bbf5374c661054d41410dc53ff752972583b9b"
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
version = "0.5.1"
version = "0.5.2"

[[Compat]]
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
git-tree-sha1 = "49269e311ffe11ac5b334681d212329002a9832a"
git-tree-sha1 = "195a3ffcb8b0762684b6821de18f83a16455c6ea"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "1.5.1"
version = "2.0.0"

[[DataStructures]]
deps = ["InteractiveUtils", "OrderedCollections", "Random", "Serialization", "Test"]
Expand Down Expand Up @@ -92,19 +92,19 @@ uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[MacroTools]]
deps = ["Compat"]
git-tree-sha1 = "c443e1c8d58a4e9f61b708ad0a88286c7042145b"
git-tree-sha1 = "3fd1a3022952128935b449c33552eb65895380c1"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.4.4"
version = "0.4.5"

[[Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[MbedTLS]]
deps = ["BinaryProvider", "Dates", "Libdl", "Random", "Sockets", "Test"]
git-tree-sha1 = "40b4a9149f0967714991328b8155c9ff5f91e755"
deps = ["BinaryProvider", "Dates", "Distributed", "Libdl", "Random", "Sockets", "Test"]
git-tree-sha1 = "2d94286a9c2f52c63a16146bb86fd6cdfbf677c6"
uuid = "739be429-bea8-5141-9913-cc70e7f3736d"
version = "0.6.7"
version = "0.6.8"

[[Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"
Expand Down Expand Up @@ -156,9 +156,9 @@ uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[[StaticArrays]]
deps = ["InteractiveUtils", "LinearAlgebra", "Random", "Statistics", "Test"]
git-tree-sha1 = "1eb114d6e23a817cd3e99abc3226190876d7c898"
git-tree-sha1 = "3841b39ed5f047db1162627bf5f80a9cd3e39ae2"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "0.10.2"
version = "0.10.3"

[[Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
Expand All @@ -170,9 +170,9 @@ uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[[TranscodingStreams]]
deps = ["Pkg", "Random", "Test"]
git-tree-sha1 = "a34a2d588e2d2825602bf14a24216d5c8b0921ec"
git-tree-sha1 = "8a032ceb5cf7a28bf1bdb77746b250b9e9fda565"
uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa"
version = "0.8.1"
version = "0.9.0"

[[UUIDs]]
deps = ["Random"]
Expand Down
2 changes: 2 additions & 0 deletions Project.toml
Expand Up @@ -4,6 +4,8 @@ authors = ["Przemyslaw Szufel <pszufe@gmail.com>", "Bartosz Pankratz <bartosz.pa
version = "0.1.5"

[deps]
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
LibExpat = "522f3ed2-3f36-55e3-b6df-e94fee9b0c07"
Expand Down
4 changes: 4 additions & 0 deletions src/OpenStreetMapX.jl
Expand Up @@ -3,7 +3,9 @@ module OpenStreetMapX
using LibExpat
using LightGraphs
using SparseArrays
using DataStructures
using Serialization
using Statistics
using JSON
using HTTP

Expand All @@ -12,6 +14,7 @@ export distance, getX, getY, getZ # Auxiliary functions to calculate distances
export center, inbounds, onbounds, boundary_point #Functions for map bounds
export ECEF, LLA, ENU #Conversion functions
export MapData
export get_distance, a_star_algorithm #A* search algorithm implementation

export extract_highways, filter_highways #Highways extraction
export filter_roadways, classify_roadways, filter_walkways, classify_walkways, filter_cycleways, classify_cycleways #Filtering and classification of cars, cycles and pedestrian Highways
Expand All @@ -33,6 +36,7 @@ include("types.jl") #types used in the package
include("classes.jl") #grouping highways into classes for routing and plotting
include("speeds.jl") # speed limits in kilometers per hour
include("polyline.jl")
include("a_star.jl")
include("points.jl") # points coordinates and constants
include("bounds.jl") #bounds of the map
include("conversion.jl") #conversion of geographical coordinates
Expand Down
114 changes: 114 additions & 0 deletions src/a_star.jl
@@ -0,0 +1,114 @@
"""
get_distance(A::Int, B::Int,
nodes::Dict{Int,T} ,
vertices_to_nodes::Dict{Int,Int}) where T<:Union{OpenStreetMapX.ENU,OpenStreetMapX.ECEF}
Auxiliary function - takes two vertices of graph and return the distance between them.
Used to compute straight line distance heuristic for A* algorithm.
**Arguments**
* `A` : start vertex
* `B` : end vertex
* `nodes` : dictionary of .osm nodes ID's and correspoding points coordinates
* `vertices_to_nodes` : dictionary mapping graph vertices to .osm file nodes
"""
function get_distance(A::Int, B::Int,
nodes::Dict{Int,T},
vertices_to_nodes::Dict{Int,Int}) where T<:Union{OpenStreetMapX.ENU,OpenStreetMapX.ECEF}
A,B = vertices_to_nodes[A], vertices_to_nodes[B]
OpenStreetMapX.distance(nodes[A],nodes[B])
end


function extract_a_star_route(parents::Vector{Int},s::Int, u::Int)
route = Int[]
index = u
push!(route,index)
while index != s
index = parents[index]
push!(route, index)
end
reverse!(route)
end

"""
a_star_algorithm(g::AbstractGraph{U},
s::Integer,
t::Integer,
distmx::AbstractMatrix{T}=LightGraphs.weights(g),
heuristic::Function = n -> zero(T)) where {T, U}
High level function - implementation of A star search algorithm:
(https://en.wikipedia.org/wiki/A*_search_algorithm).
Based on the implementation in LightGraphs library,
however significantly improved in terms of performance.
**Arguments**
* `g` : graph object
* `S` : start vertex
* `t` : end vertex
* `distmx` : distance matrix
* `heuristic` : search heuristic function; by default returns zero
"""
function a_star_algorithm(g::LightGraphs.AbstractGraph{U}, # the g
s::Integer, # the start vertex
t::Integer, # the end vertex
distmx::AbstractMatrix{T}=LightGraphs.weights(g),
heuristic::Function = n -> zero(T)) where {T, U}
checkbounds(distmx, Base.OneTo(nv(g)), Base.OneTo(nv(g)))
frontier = DataStructures.PriorityQueue{Tuple{T, U},T}()
frontier[(zero(T), U(s))] = zero(T)
nvg = nv(g)
visited = zeros(Bool, nvg)
dists = fill(typemax(T), nvg)
parents = zeros(U, nvg)
colormap = zeros(UInt8, nvg)
colormap[s] = 1
@inbounds while !isempty(frontier)
(cost_so_far, u) = dequeue!(frontier)
u == t && (return OpenStreetMapX.extract_a_star_route(parents,s,u), cost_so_far)
for v in LightGraphs.outneighbors(g, u)
if get(colormap, v, 0) < 2
dist = distmx[u, v]
colormap[v] = 1
path_cost = cost_so_far + dist
if !visited[v]
visited[v] = true
parents[v] = u
dists[v] = path_cost
enqueue!(frontier,
(path_cost, v),
path_cost + heuristic(v,t))
elseif path_cost < dists[v]
parents[v] = u
dists[v] = path_cost
frontier[path_cost, v] = path_cost + heuristic(v,t)
end
end
end
colormap[u] = 2
end
Vector{U}(), Inf
end

"""
a_star_algorithm(m::OpenStreetMapX.MapData,
s::Integer,
t::Integer)
A star search algorithm with straight line distance heuristic
**Arguments**
* `m` : MapData object
* `S` : start vertex
* `t` : end vertex
* `distmx` : distance matrix
"""
function a_star_algorithm(m::OpenStreetMapX.MapData,
s::Integer,
t::Integer)
heuristic(u,v) = OpenStreetMapX.get_distance(u, v, m.nodes, m.n)
OpenStreetMapX.a_star_algorithm(m.g,s,t,m.w,heuristic)
end
4 changes: 2 additions & 2 deletions src/google_routing.jl
Expand Up @@ -158,7 +158,7 @@ function get_google_route(origin::Int,destination::Int,waypoint::Int,
return OpenStreetMapX.get_google_route(origin,destination,waypoint,map_data,googleapi_key,googleapi_parameters = googleapi_parameters)
else
#get route based on OSM routing
warn("Google Distances API cannot get a proper results - route will be calculated with OSMSim Routing module")
@warn "Google Distances API cannot get a proper results - route will be calculated with OSMSim Routing module"
if rand() < 0.5
route_nodes, distance, route_time = OpenStreetMapX.shortest_route(map_data, origin, waypoint, destination)
return route_nodes, "shortest"
Expand Down Expand Up @@ -194,7 +194,7 @@ function get_google_route(origin::Int,destination::Int,
return OpenStreetMapX.get_google_route(origin,destination,map_data,googleapi_key,googleapi_parameters = googleapi_parameters)
else
#get route based on OSM routing
warn("Google Distances API cannot get a proper results - route will be calculated with OSMSim Routing module")
@warn "Google Distances API cannot get a proper results - route will be calculated with OSMSim Routing module"
if rand() < 0.5
route_nodes, distance, route_time = OpenStreetMapX.shortest_route(map_data, origin, destination)
return route_nodes, "shortest"
Expand Down
3 changes: 2 additions & 1 deletion src/parseMap.jl
Expand Up @@ -125,14 +125,15 @@ function get_map_data(filepath::String,filename::Union{String,Nothing}=nothing;
end
# (node id) => (graph vertex)
v = OpenStreetMapX.get_vertices(e)
n = Dict(reverse.(collect(v)))
edges = [v[id] for id in reinterpret(Int, e)]
I = edges[1:2:end]
J = edges[2:2:end]
# w - Edge weights, indexed by graph id
w = SparseArrays.sparse(I, J, weights, length(v), length(v))
g = LightGraphs.DiGraph(w)

res = OpenStreetMapX.MapData(bounds,nodes,roadways,intersections,g,v,e,w,class)
res = OpenStreetMapX.MapData(bounds,nodes,roadways,intersections,g,v,n,e,w,class)
if use_cache
f=open(cachefile,"w");
Serialization.serialize(f,res);
Expand Down

0 comments on commit 31fb4e1

Please sign in to comment.