Skip to content

Commit 9a9f2c4

Browse files
committed
generalize graph algorithms to AbstractOSMGraph
1 parent 5749a8f commit 9a9f2c4

File tree

2 files changed

+60
-50
lines changed

2 files changed

+60
-50
lines changed

src/graph_utilities.jl

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,67 @@
11
"""
2-
index_to_node_id(g::OSMGraph, x::DEFAULT_OSM_INDEX_TYPE)
3-
index_to_node_id(g::OSMGraph, x::Vector{<:DEFAULT_OSM_INDEX_TYPE})
2+
index_to_node_id(g::AbstractOSMGraph, x::DEFAULT_OSM_INDEX_TYPE)
3+
index_to_node_id(g::AbstractOSMGraph, x::Vector{<:DEFAULT_OSM_INDEX_TYPE})
44
55
Maps node index to node id.
66
"""
7-
index_to_node_id(g::OSMGraph, x::DEFAULT_OSM_INDEX_TYPE) = g.index_to_node[x]
8-
index_to_node_id(g::OSMGraph, x::Vector{<:DEFAULT_OSM_INDEX_TYPE}) = [index_to_node_id(g, i) for i in x]
7+
index_to_node_id(g::AbstractOSMGraph, x::DEFAULT_OSM_INDEX_TYPE) = g.index_to_node[x]
8+
index_to_node_id(g::AbstractOSMGraph, x::Vector{<:DEFAULT_OSM_INDEX_TYPE}) = [index_to_node_id(g, i) for i in x]
99

1010
"""
11-
index_to_node(g::OSMGraph, x::DEFAULT_OSM_INDEX_TYPE)
12-
index_to_node(g::OSMGraph, x::Vector{<:DEFAULT_OSM_INDEX_TYPE})
11+
index_to_node(g::AbstractOSMGraph, x::DEFAULT_OSM_INDEX_TYPE)
12+
index_to_node(g::AbstractOSMGraph, x::Vector{<:DEFAULT_OSM_INDEX_TYPE})
1313
1414
Maps node index to node object.
1515
"""
16-
index_to_node(g::OSMGraph, x::DEFAULT_OSM_INDEX_TYPE) = g.nodes[g.index_to_node[x]]
17-
index_to_node(g::OSMGraph, x::Vector{<:DEFAULT_OSM_INDEX_TYPE}) = [index_to_node(g, i) for i in x]
16+
index_to_node(g::AbstractOSMGraph, x::DEFAULT_OSM_INDEX_TYPE) = g.nodes[g.index_to_node[x]]
17+
index_to_node(g::AbstractOSMGraph, x::Vector{<:DEFAULT_OSM_INDEX_TYPE}) = [index_to_node(g, i) for i in x]
1818

1919
"""
20-
node_id_to_index(g::OSMGraph, x::DEFAULT_OSM_ID_TYPE)
21-
node_id_to_index(g::OSMGraph, x::Vector{<:DEFAULT_OSM_ID_TYPE})
20+
node_id_to_index(g::AbstractOSMGraph, x::DEFAULT_OSM_ID_TYPE)
21+
node_id_to_index(g::AbstractOSMGraph, x::Vector{<:DEFAULT_OSM_ID_TYPE})
2222
2323
Maps node id to index.
2424
"""
25-
node_id_to_index(g::OSMGraph, x::DEFAULT_OSM_ID_TYPE) = g.node_to_index[x]
26-
node_id_to_index(g::OSMGraph, x::Vector{<:DEFAULT_OSM_ID_TYPE}) = [node_id_to_index(g, i) for i in x]
25+
node_id_to_index(g::AbstractOSMGraph, x::DEFAULT_OSM_ID_TYPE) = g.node_to_index[x]
26+
node_id_to_index(g::AbstractOSMGraph, x::Vector{<:DEFAULT_OSM_ID_TYPE}) = [node_id_to_index(g, i) for i in x]
2727
"""
28-
node_to_index(g::OSMGraph, x::Node)
29-
node_to_index(g::OSMGraph, x::Vector{Node})
28+
node_to_index(g::AbstractOSMGraph, x::Node)
29+
node_to_index(g::AbstractOSMGraph, x::Vector{Node})
3030
3131
Maps node object to index.
3232
"""
33-
node_to_index(g::OSMGraph, x::Node) = g.node_to_index[x.id]
34-
node_to_index(g::OSMGraph, x::Vector{Node}) = [node_id_to_index(g, i.id) for i in x]
33+
node_to_index(g::AbstractOSMGraph, x::Node) = g.node_to_index[x.id]
34+
node_to_index(g::AbstractOSMGraph, x::Vector{Node}) = [node_id_to_index(g, i.id) for i in x]
3535

3636
"""
37-
index_to_dijkstra_state(g::OSMGraph, x::DEFAULT_OSM_INDEX_TYPE)
37+
index_to_dijkstra_state(g::AbstractOSMGraph, x::DEFAULT_OSM_INDEX_TYPE)
3838
3939
Maps node index to dijkstra state (parents).
4040
"""
41-
index_to_dijkstra_state(g::OSMGraph, x::DEFAULT_OSM_INDEX_TYPE) = g.dijkstra_states[x]
41+
index_to_dijkstra_state(g::AbstractOSMGraph, x::DEFAULT_OSM_INDEX_TYPE) = g.dijkstra_states[x]
4242
"""
43-
node_id_to_dijkstra_state(g::OSMGraph, x::DEFAULT_OSM_ID_TYPE)
43+
node_id_to_dijkstra_state(g::AbstractOSMGraph, x::DEFAULT_OSM_ID_TYPE)
4444
4545
Maps node id to dijkstra state (parents).
4646
"""
47-
node_id_to_dijkstra_state(g::OSMGraph, x::DEFAULT_OSM_ID_TYPE) = g.dijkstra_states[node_id_to_index(g, x)]
47+
node_id_to_dijkstra_state(g::AbstractOSMGraph, x::DEFAULT_OSM_ID_TYPE) = g.dijkstra_states[node_id_to_index(g, x)]
4848
"""
49-
set_dijkstra_state_with_index!(g::OSMGraph, index::DEFAULT_OSM_INDEX_TYPE, state)
49+
set_dijkstra_state_with_index!(g::AbstractOSMGraph, index::DEFAULT_OSM_INDEX_TYPE, state)
5050
5151
Set dijkstra state (parents) with node index.
5252
"""
53-
set_dijkstra_state_with_index!(g::OSMGraph, index::DEFAULT_OSM_INDEX_TYPE, state) = push!(g.dijkstra_states, index, state)
53+
set_dijkstra_state_with_index!(g::AbstractOSMGraph, index::DEFAULT_OSM_INDEX_TYPE, state) = push!(g.dijkstra_states, index, state)
5454
"""
55-
set_dijkstra_state_with_node_id!(g::OSMGraph, index::DEFAULT_OSM_ID_TYPE, state)
55+
set_dijkstra_state_with_node_id!(g::AbstractOSMGraph, index::DEFAULT_OSM_ID_TYPE, state)
5656
5757
Set dijkstra state (parents) with node id.
5858
"""
59-
set_dijkstra_state_with_node_id!(g::OSMGraph, node_id::DEFAULT_OSM_ID_TYPE, state) = push!(g.dijkstra_states, node_id_to_index(g, node_id), state)
59+
set_dijkstra_state_with_node_id!(g::AbstractOSMGraph, node_id::DEFAULT_OSM_ID_TYPE, state) = push!(g.dijkstra_states, node_id_to_index(g, node_id), state)
6060
"""
6161
maxspeed_from_index(g, x::DEFAULT_OSM_INDEX_TYPE)
6262
maxspeed_from_node_id(g, x::DEFAULT_OSM_ID_TYPE)
6363
6464
Get maxspeed from index id or node id.
6565
"""
66-
maxspeed_from_index(g, x::DEFAULT_OSM_INDEX_TYPE) = index_to_node(g, x).tags["maxspeed"]
67-
maxspeed_from_node_id(g, x::DEFAULT_OSM_ID_TYPE) = g.nodes[x].tags["maxspeed"]
66+
maxspeed_from_index(g::AbstractOSMGraph, x::DEFAULT_OSM_INDEX_TYPE) = index_to_node(g, x).tags["maxspeed"]
67+
maxspeed_from_node_id(g::AbstractOSMGraph, x::DEFAULT_OSM_ID_TYPE) = g.nodes[x].tags["maxspeed"]

src/shortest_path.jl

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""
22
shortest_path([PathAlgorithm,]
3-
g::OSMGraph,
3+
g::AbstractOSMGraph,
44
origin::Union{Integer,Node},
55
destination::Union{Integer,Node},
66
[weights::AbstractMatrix=g.weights;
@@ -21,7 +21,7 @@ Calculates the shortest path between two OpenStreetMap node ids.
2121
Faster for small graphs and/or long paths.
2222
- `AStarDict`: A* algorithm using the `Dict` implementation.
2323
Faster for large graphs and/or short paths.
24-
- `g::OSMGraph{U,T,W}`: Graph container.
24+
- `g::AbstractOSMGraph{U,T,W}`: Graph container.
2525
- `origin::Union{Integer,Node}`: Origin OpenStreetMap node or node id.
2626
- `destination::Union{Integer,Node},`: Destination OpenStreetMap node or node
2727
id.
@@ -45,7 +45,7 @@ Calculates the shortest path between two OpenStreetMap node ids.
4545
the shortest path.
4646
"""
4747
function shortest_path(::Type{A},
48-
g::OSMGraph{U,T,W},
48+
g::AbstractOSMGraph{U,T,W},
4949
origin::DEFAULT_OSM_ID_TYPE,
5050
destination::DEFAULT_OSM_ID_TYPE,
5151
weights::AbstractMatrix{W};
@@ -59,7 +59,7 @@ function shortest_path(::Type{A},
5959
return index_to_node_id(g, path)
6060
end
6161
function shortest_path(::Type{A},
62-
g::OSMGraph{U,T,W},
62+
g::AbstractOSMGraph{U,T,W},
6363
origin::DEFAULT_OSM_ID_TYPE,
6464
destination::DEFAULT_OSM_ID_TYPE,
6565
weights::AbstractMatrix{W};
@@ -73,50 +73,50 @@ function shortest_path(::Type{A},
7373
isnothing(path) && return
7474
return index_to_node_id(g, path)
7575
end
76-
function shortest_path(::Type{A}, g::OSMGraph{U,T,W}, origin::DEFAULT_OSM_ID_TYPE, destination::DEFAULT_OSM_ID_TYPE; kwargs...)::Union{Nothing,Vector{T}} where {A <: PathAlgorithm, U, T, W}
76+
function shortest_path(::Type{A}, g::AbstractOSMGraph{U,T,W}, origin::DEFAULT_OSM_ID_TYPE, destination::DEFAULT_OSM_ID_TYPE; kwargs...)::Union{Nothing,Vector{T}} where {A <: PathAlgorithm, U, T, W}
7777
return shortest_path(A, g, origin, destination, g.weights; kwargs...)
7878
end
79-
function shortest_path(::Type{A}, g::OSMGraph{U,T,W}, origin::Node{<:DEFAULT_OSM_ID_TYPE}, destination::Node{<:DEFAULT_OSM_ID_TYPE}, args...; kwargs...)::Union{Nothing,Vector{T}} where {A <: PathAlgorithm, U, T, W}
79+
function shortest_path(::Type{A}, g::AbstractOSMGraph{U,T,W}, origin::Node{<:DEFAULT_OSM_ID_TYPE}, destination::Node{<:DEFAULT_OSM_ID_TYPE}, args...; kwargs...)::Union{Nothing,Vector{T}} where {A <: PathAlgorithm, U, T, W}
8080
return shortest_path(A, g, origin.id, destination.id, args...; kwargs...)
8181
end
82-
function shortest_path(g::OSMGraph{U,T,W}, args...; kwargs...)::Union{Nothing,Vector{T}} where {U, T, W}
82+
function shortest_path(g::AbstractOSMGraph{U,T,W}, args...; kwargs...)::Union{Nothing,Vector{T}} where {U, T, W}
8383
return shortest_path(Dijkstra, g, args...; kwargs...)
8484
end
8585

8686
"""
87-
set_dijkstra_state!(g::OSMGraph, src::Union{Integer,Vecotr{<:Integer}, weights::AbstractMatrix; cost_adjustment::Function=(u, v, parents) -> 0.0)
87+
set_dijkstra_state!(g::AbstractOSMGraph, src::Union{Integer,Vecotr{<:Integer}, weights::AbstractMatrix; cost_adjustment::Function=(u, v, parents) -> 0.0)
8888
8989
Compute and set the dijkstra parent states for one or multiple src vertices. Threads are used for multiple srcs.
9090
Note, computing dijkstra states for all vertices is a O(V² + ElogV) operation, use on large graphs with caution.
9191
"""
92-
function set_dijkstra_state!(g::OSMGraph, src::Integer, weights::AbstractMatrix; cost_adjustment::Function=(u, v, parents) -> 0.0)
92+
function set_dijkstra_state!(g::AbstractOSMGraph, src::Integer, weights::AbstractMatrix; cost_adjustment::Function=(u, v, parents) -> 0.0)
9393
g.dijkstra_states[src] = dijkstra(g.graph, weights, src; cost_adjustment=cost_adjustment)
9494
end
95-
function set_dijkstra_state!(g::OSMGraph, srcs::Vector{<:Integer}, weights::AbstractMatrix; cost_adjustment::Function=(u, v, parents) -> 0.0)
95+
function set_dijkstra_state!(g::AbstractOSMGraph, srcs::Vector{<:Integer}, weights::AbstractMatrix; cost_adjustment::Function=(u, v, parents) -> 0.0)
9696
Threads.@threads for src in srcs
9797
set_dijkstra_state!(g, src, weights; cost_adjustment=cost_adjustment)
9898
end
9999
return g
100100
end
101-
set_dijkstra_state!(g::OSMGraph, src; kwargs...) = set_dijkstra_state!(g, src, g.weights; kwargs...)
101+
set_dijkstra_state!(g::AbstractOSMGraph, src; kwargs...) = set_dijkstra_state!(g, src, g.weights; kwargs...)
102102

103103
"""
104-
shortest_path_from_dijkstra_state(g::OSMGraph, origin::Integer, destination::Integer)
104+
shortest_path_from_dijkstra_state(g::AbstractOSMGraph, origin::Integer, destination::Integer)
105105
106106
Extract shortest path from precomputed dijkstra state, from `origin` to `detination` node id.
107107
108108
Note, function will raise `UndefRefError: access to undefined reference` if the dijkstra state of the
109109
origin node is not precomputed.
110110
111111
# Arguments
112-
- `g::OSMGraph`: Graph container.
112+
- `g::AbstractOSMGraph`: Graph container.
113113
- `origin::Integer`: Origin OpenStreetMap node or node id.
114114
- `destination::Integer`: Destination OpenStreetMap node or node id.
115115
116116
# Return
117117
- `Union{Nothing,Vector{T}}`: Array of OpenStreetMap node ids making up the shortest path.
118118
"""
119-
function shortest_path_from_dijkstra_state(g::OSMGraph, origin::Integer, destination::Integer)
119+
function shortest_path_from_dijkstra_state(g::AbstractOSMGraph, origin::Integer, destination::Integer)
120120
parents = node_id_to_dijkstra_state(g, origin)
121121
path = path_from_parents(parents, node_id_to_index(g, destination))
122122
isnothing(path) && return
@@ -186,7 +186,7 @@ function restriction_cost(restrictions::AbstractDict{V,Vector{MutableLinkedList{
186186
end
187187

188188
"""
189-
restriction_cost_adjustment(g::OSMGraph)
189+
restriction_cost_adjustment(g::AbstractOSMGraph)
190190
191191
Returns the cost adjustment function (user in dijkstra and astar) for restrictions. The return function
192192
takes 3 arguments, `u` being the current node, `v` being the neighbour node, `parents` being the array
@@ -195,17 +195,27 @@ of parent dijkstra states. By default `g.indexed_restrictions` is used to check
195195
"""
196196
restriction_cost_adjustment(g::OSMGraph) = (u, v, parents) -> restriction_cost(g.indexed_restrictions, u, v, parents)
197197

198+
"""
199+
restriction_cost_adjustment(g::SinplifiedOSMGraph)
200+
201+
Returns the cost adjustment function (user in dijkstra and astar) for restrictions. The return function
202+
takes 3 arguments, `u` being the current node, `v` being the neighbour node, `parents` being the array
203+
of parent dijkstra states. By default `g.indexed_restrictions` is used to check whether the path from
204+
`u` to `v` is restricted given all previous nodes in `parents`.
205+
"""
206+
restriction_cost_adjustment(g::SimplifiedOSMGraph) = (u, v, parents) -> restriction_cost(g.parent.indexed_restrictions, u, v, parents)
207+
198208
"""
199209
distance_heuristic(g::OSMGraph)
200210
201211
Returns the heuristic function used in astar shortest path calculation, should be used with a graph with
202212
`weight_type=:distance`. The heuristic function takes in 2 arguments, `u` being the current node and `v`
203213
being the neighbour node, and returns the haversine distance between them.
204214
"""
205-
distance_heuristic(g::OSMGraph) = (u, v) -> haversine(g.node_coordinates[u], g.node_coordinates[v])
215+
distance_heuristic(g::AbstractOSMGraph) = (u, v) -> haversine(g.node_coordinates[u], g.node_coordinates[v])
206216

207217
"""
208-
time_heuristic(g::OSMGraph)
218+
time_heuristic(g::AbstractOSMGraph)
209219
210220
Returns the heuristic function used in astar shortest path calculation, should be used with a graph with
211221
`weight_type=:time` or `weight_type=:lane_efficiency`. The heuristic function takes in 2 arguments, `u`
@@ -214,40 +224,40 @@ Calculated by dividing the harversine distance by a fixed maxspeed of `100`. Rem
214224
path, it is important to pick an *underestimating* heuristic that best estimates the cost remaining to the `goal`,
215225
hence we pick the largest maxspeed across all ways.
216226
"""
217-
time_heuristic(g::OSMGraph) = (u, v) -> haversine(g.node_coordinates[u], g.node_coordinates[v]) / 100.0
227+
time_heuristic(g::AbstractOSMGraph) = (u, v) -> haversine(g.node_coordinates[u], g.node_coordinates[v]) / 100.0
218228

219229
"""
220-
weights_from_path(g::OSMGraph{U,T,W}, path::Vector{T}; weights=g.weights)::Vector{W} where {U <: DEFAULT_OSM_INDEX_TYPE,T <: DEFAULT_OSM_ID_TYPE,W <: Real}
230+
weights_from_path(g::AbstractOSMGraph{U,T,W}, path::Vector{T}; weights=g.weights)::Vector{W} where {U <: DEFAULT_OSM_INDEX_TYPE,T <: DEFAULT_OSM_ID_TYPE,W <: Real}
221231
222232
Extracts edge weights from a path using the weight matrix stored in `g.weights` unless
223233
a different matrix is passed to the `weights` kwarg.
224234
225235
# Arguments
226-
- `g::OSMGraph`: Graph container.
236+
- `g::AbstractOSMGraph`: Graph container.
227237
- `path::Vector{T}`: Array of OpenStreetMap node ids.
228238
- `weights=g.weights`: the matrix that the edge weights are extracted from. Defaults to `g.weights`.
229239
230240
# Return
231241
- `Vector{W}`: Array of edge weights, distances are in km, time is in hours.
232242
"""
233-
function weights_from_path(g::OSMGraph{U,T,W}, path::Vector{T}; weights=g.weights)::Vector{W} where {U <: DEFAULT_OSM_INDEX_TYPE,T <: DEFAULT_OSM_ID_TYPE,W <: Real}
243+
function weights_from_path(g::AbstractOSMGraph{U,T,W}, path::Vector{T}; weights=g.weights)::Vector{W} where {U <: DEFAULT_OSM_INDEX_TYPE,T <: DEFAULT_OSM_ID_TYPE,W <: Real}
234244
return [weights[g.node_to_index[path[i]], g.node_to_index[path[i + 1]]] for i in 1:length(path) - 1]
235245
end
236246

237247
"""
238-
total_path_weight(g::OSMGraph{U,T,W}, path::Vector{T}; weights=g.weights)::W where {U <: Integer,T <: DEFAULT_OSM_ID_TYPE,W <: Real}
248+
total_path_weight(g::AbstractOSMGraph{U,T,W}, path::Vector{T}; weights=g.weights)::W where {U <: Integer,T <: DEFAULT_OSM_ID_TYPE,W <: Real}
239249
240250
Extract total edge weight along a path.
241251
242252
# Arguments
243-
- `g::OSMGraph`: Graph container.
253+
- `g::AbstractOSMGraph`: Graph container.
244254
- `path::Vector{T}`: Array of OpenStreetMap node ids.
245255
- `weights=g.weights`: the matrix that the edge weights are extracted from. Defaults to `g.weights`.
246256
247257
# Return
248258
- `sum::W`: Total path edge weight, distances are in km, time is in hours.
249259
"""
250-
function total_path_weight(g::OSMGraph{U,T,W}, path::Vector{T}; weights=g.weights)::W where {U <: Integer,T <: DEFAULT_OSM_ID_TYPE,W <: Real}
260+
function total_path_weight(g::AbstractOSMGraph{U,T,W}, path::Vector{T}; weights=g.weights)::W where {U <: Integer,T <: DEFAULT_OSM_ID_TYPE,W <: Real}
251261
sum::W = zero(W)
252262
for i in 1:length(path) - 1
253263
sum += weights[g.node_to_index[path[i]], g.node_to_index[path[i + 1]]]

0 commit comments

Comments
 (0)