Skip to content
This repository has been archived by the owner on Oct 21, 2021. It is now read-only.

Added vertex property inspectors. #107

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
44 changes: 44 additions & 0 deletions doc/source/vertex_edge.rst
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,50 @@ Both edge types implement the following methods:

A custom edge type ``E{V}`` which is constructible by ``E(index::Int, s::V, t::V)`` and implements the above methods is usable in the ``VectorIncidenceList`` parametric type. Construct such a list with ``inclist(V,E{V})``, where E and V are your vertex and edge types. See test/inclist.jl for an example.

Vertex Properties
---------------

Many algorithms use a property of a vertex such as amount of a
resource provided or required by that vertex as input. As the
algorithms do not mandate any structure for the vertex types, these
vertex properties can be passed through to the algorithm by an
``VertexPropertyInspector``. An ``VertexPropertyInspector`` when
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"An" on these two lines should also be "a".

passed to the ``vertex_property`` method along with a vertex and a
graph, will return that property of a vertex.

All vertex property inspectors should be declared as a subtype of
``AbstractVertexPropertyInspector{T}`` where ``T`` is the type of the
vertex property. The vertex propery inspector should respond to the
following methods.

.. py::function:: vertex_property(i, e, g)

returns the vertex property of vertex ``v`` in graph ``g`` selected by
inspector ``i``.

.. py::function:: vertex_property_requirement(i, g)

checks that graph ``g`` implements the interface(s) necessary for
inspector ``i``

Three vertex property inspectors are provided
``ConstantVertexPropertyInspector``, ``VectorVertexPropertyInspector`` and
``AttributeVertexPropertyInspector``.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FunctionVertexPropertyInspector should also be here, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And AttributeVertexPropertyInspector doesn't seem to be implemented? Or was one replaced with the other?

``ConstantVertexPropertyInspector(c)`` constructs a vertex property
inspector that returns the constant ``c`` for each vertex.

``VectorVertexPropertyInspector(vec)`` constructs a vertex property
inspector that returns ``vec[vertex_index(v, g)]``. It requires that
``g`` implement the ``vertex_map`` interface.

``FunctionVertexPropertyInspector(func)`` constructs a vertex property
inspector that returns the result of ``func(v)`` from an ``ExVertex``.
``AttributeVertexPropertyInspector`` requires that the graph implements
the ``vertex_map`` interface.



Edge Properties
---------------

Expand Down
7 changes: 7 additions & 0 deletions src/Graphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ module Graphs
ConstantEdgePropertyInspector, AttributeEdgePropertyInspector,
edge_property, edge_property_requirement,

AbstractVertexPropertyInspector, ConstantVertexPropertyInspector,
FunctionVertexPropertyInspector, VectorVertexPropertyInspector,
vertex_property_requirement, vertex_property,

AbstractVertexColormap, VectorVertexColormap, HashVertexColormap,
vertex_colormap_requirement, setindex!, getindex,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as setindex! and getindex are imported from base, they don't need to be reexported.

(setindex! does need to be imported above)


# edge_list
GenericEdgeList, EdgeList, simple_edgelist, edgelist,

Expand Down
31 changes: 19 additions & 12 deletions src/a_star_spath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ using Base.Collections

export shortest_path

function a_star_impl!{V,D}(
function a_star_impl!{V,D,DH}(
graph::AbstractGraph{V},# the graph
frontier, # an initialized heap containing the active vertices
colormap::Vector{Int}, # an (initialized) color-map to indicate status of vertices
colormap::AbstractVertexColormap{Int}, # an (initialized) color-map to indicate status of vertices
edge_dists::AbstractEdgePropertyInspector{D}, # cost of each edge
heuristic::Function, # heuristic fn (under)estimating distance to target
heuristic::AbstractVertexPropertyInspector{DH}, # heuristic fn (under)estimating distance to target
t::V) # the end vertex

while !isempty(frontier)
Expand All @@ -33,32 +33,37 @@ function a_star_impl!{V,D}(

for edge in out_edges(u, graph)
v = target(edge)
if colormap[v] < 2
colormap[v] = 1
if colormap[v,graph] < 2
colormap[v,graph] = 1
new_path = cat(1, path, edge)
path_cost = cost_so_far + edge_property(edge_dists, edge, graph)
enqueue!(frontier,
(path_cost, new_path, v),
path_cost + heuristic(v))
path_cost + vertex_property(heuristic,v, graph))
end
end
colormap[u] = 2
colormap[u,graph] = 2
end
nothing
end


function shortest_path{V,E,D}(
function shortest_path{V,E,D,DH}(
graph::AbstractGraph{V,E}, # the graph
edge_dists::AbstractEdgePropertyInspector{D}, # cost of each edge
s::V, # the start vertex
t::V, # the end vertex
heuristic::Function = n -> 0)
heuristic::AbstractVertexPropertyInspector{DH} = ConstantVertexPropertyInspector(0))

# heuristic (under)estimating distance to target
frontier = PriorityQueue{(D,Array{E,1},V),D}()
frontier[(zero(D), E[], s)] = zero(D)
colormap = zeros(Int, num_vertices(graph))
colormap[s] = 1
if implements_vertex_map(graph)
colormap = VectorVertexColormap{Int}(zeros(Int, num_vertices(graph)))
else
colormap = HashVertexColormap{Int}(Dict{V,Int}())
end
colormap[s,graph] = 1
a_star_impl!(graph, frontier, colormap, edge_dists, heuristic, t)
end

Expand All @@ -67,8 +72,10 @@ function shortest_path{V,E,D}(
edge_dists::Vector{D}, # cost of each edge
s::V, # the start vertex
t::V, # the end vertex
heuristic::Function = n -> 0)
fheuristic::Function = n -> 0)
edge_len::AbstractEdgePropertyInspector{D} = VectorEdgePropertyInspector(edge_dists)

heuristic = FunctionVertexPropertyInspector{D}(fheuristic)
shortest_path(graph, edge_len, s, t, heuristic)
end

Expand Down
71 changes: 69 additions & 2 deletions src/common.jl
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,39 @@ next(a::SourceIterator, s::Int) = ((e, s) = next(a.lst, s); (source(e, a.g), s))

#################################################
#
# Edge Length Visitors
# Vertex Property Inspectors
#
################################################

abstract AbstractVertexPropertyInspector{T}

vertex_property_requirement{T, V}(visitor::AbstractVertexPropertyInspector{T}, g::AbstractGraph{V}) = nothing

type ConstantVertexPropertyInspector{T} <: AbstractVertexPropertyInspector{T}
value::T
end

vertex_property{T}(visitor::ConstantVertexPropertyInspector{T}, v, g) = visitor.value

type VectorVertexPropertyInspector{T} <: AbstractVertexPropertyInspector{T}
values::Vector{T}
end

vertex_property{T,V}(visitor::VectorVertexPropertyInspector{T}, v::V,
g::AbstractGraph{V})= visitor.values[vertex_index(v,g)]

vertex_property_requirement{T, V}(visitor::VectorVertexPropertyInspector{T}, g::AbstractGraph{V}) = @graph_requires g vertex_map


type FunctionVertexPropertyInspector{T} <: AbstractVertexPropertyInspector{T}
f::Function
end

vertex_property{T}(visitor::FunctionVertexPropertyInspector{T}, v, g) = visitor.f(v)

#################################################
#
# Edge Property Inspectors
#
################################################

Expand All @@ -164,7 +196,7 @@ end

edge_property{T,V}(visitor::VectorEdgePropertyInspector{T}, e, g::AbstractGraph{V}) = visitor.values[edge_index(e, g)]

edge_property_requirement{T, V}(visitor::AbstractEdgePropertyInspector{T}, g::AbstractGraph{V}) = @graph_requires g edge_map
edge_property_requirement{T, V}(visitor::VectorEdgePropertyInspector{T}, g::AbstractGraph{V}) = @graph_requires g edge_map

type AttributeEdgePropertyInspector{T} <: AbstractEdgePropertyInspector{T}
attribute::UTF8String
Expand All @@ -173,6 +205,41 @@ end
function edge_property{T}(visitor::AttributeEdgePropertyInspector{T},edge::ExEdge, g)
convert(T,edge.attributes[visitor.attribute])
end

#################################################
#
# vertex colormap
#
################################################

abstract AbstractVertexColormap{T}

vertex_colormap_requirement{T, V}(color::AbstractVertexColormap{T},
g::AbstractGraph{V}) = nothing

type VectorVertexColormap{T} <: AbstractVertexColormap{T}
values::Vector{T}
end

vertex_colormap_requirement{T, V}(color::VectorVertexColormap{T},
g::AbstractGraph{V}) = @graph_requires g vertex_map

getindex{T,V}(color::VectorVertexColormap{T},
v::V, g::AbstractGraph{V}) = color.values[vertex_index(v,g)]

setindex!{T,V}(color::VectorVertexColormap{T}, x::T,
v::V, g::AbstractGraph{V}) = color.values[vertex_index(v,g)]=x

type HashVertexColormap{T, V} <: AbstractVertexColormap{T}
values::Dict{V,T}
end

getindex{T,V}(color::HashVertexColormap{T},
v::V, g::AbstractGraph{V}) = color.values[v,g]

setindex!{T,V}(color::HashVertexColormap{T}, x::T,
v::V, g::AbstractGraph{V}) = color.values[v]=x

#################################################
#
# convenient functions
Expand Down
11 changes: 11 additions & 0 deletions test/a_star_spath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,14 @@ end
sp = shortest_path(g1, eweights1, 1, 2, n -> g1_heuristics[n])
edge_numbers = map(e -> edge_index(e, g1), sp)
@test edge_numbers == [2, 7, 15, 16]

g2 = inclist(KeyVertex{Char})
vs = [add_vertex!(g2, 'a'+i) for i = 0:19]
for i = 1 : ne
we = g1_wedges[i]
add_edge!(g2, vs[we[1]], vs[we[2]])
end

sp2 = shortest_path(g2, VectorEdgePropertyInspector(eweights1), vs[1], vs[2],
VectorVertexPropertyInspector(g1_heuristics))
@test map(e -> edge_index(e, g2), sp2) == [2, 7, 15, 16]