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

Commit

Permalink
show_dijkstra_shortest_paths()
Browse files Browse the repository at this point in the history
change Array to Vector

silly test fix

rename per suggestion

updated docs
  • Loading branch information
sbromberger committed Dec 30, 2014
1 parent ab89beb commit 742fdc7
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 41 deletions.
88 changes: 47 additions & 41 deletions doc/source/algorithms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,29 @@ During traveral, each vertex maintains a status (also called *color*), which is
:param source: The source vertex (or vertices). The traversal starts from here.
:param visitor: The visitor which performs certain operations along the traversal.
:param colormap: An integer vector that indicates the status of each vertex. If this is input by the user, the status will be written to the input vector, otherwise an internal color vector will be created.

Here, ``visitor`` must be an instance of a sub-type of ``AbstractGraphVisitor``. A specific graph visitor type can choose to implement some or all of the following methods.

.. py:function:: discover_vertex!(visitor, v)
invoked when a vertex ``v`` is encountered for the first time. This function should return whether to continue traversal.

.. py:function:: open_vertex!(visitor, v)
invoked when a vertex ``v`` is about to examine ``v``'s neighbors.

.. py:function:: examine_neighbor!(visitor, u, v, color, ecolor)
invoked when a neighbor/out-going edge is examined. Here ``color`` is the status of ``v``, and ``ecolor`` is the status of the outgoing edge. Edge statuses are currently only considered by depth-first search.

.. py:function:: close_vertex!(visitor, v)
invoked when all neighbors of ``v`` has been examined.

If a method of these is not implemented, it will automatically fallback to no-op. The package provides some pre-defined visitor types:

* ``TrivialGraphVisitor``: all methods are no-op.
* ``VertexListVisitor``: it has a field ``vertices``, which is a vector comprised of vertices in the order of being discovered.
* ``VertexListVisitor``: it has a field ``vertices``, which is a vector comprised of vertices in the order of being discovered.
* ``LogGraphVisitor``: it prints message to show the progress of the traversal.

Many graph algorithms can be implemented based on graph traversal through certain visitors or by using the colormap in certain ways. For example, in this package, topological sorting, connected components, and cycle detection are all implemented using ``traverse_graph`` with specifically designed visitors.
Expand All @@ -62,12 +62,12 @@ Many graph algorithms can be implemented based on graph traversal through certai
Cycle detection
---------------

In graph theory, a cycle is defined to be a path that starts from some vertex ``v`` and ends up at ``v``.
In graph theory, a cycle is defined to be a path that starts from some vertex ``v`` and ends up at ``v``.

.. py:function:: test_cyclic_by_dfs(g)
Tests whether a graph contains a cycle through depth-first search. It returns ``true`` when it finds a cycle, otherwise ``false``. Here, ``g`` must implement ``vertex_list``, ``vertex_map``, and ``adjacency_list``.


Connected components
--------------------
Expand All @@ -88,17 +88,17 @@ clique is the largest clique containing a given node.
.. py:function:: maximal_cliques(g)
Returns a vector of maximal cliques, where each maximal clique is represented by a vector of vertices. Here, ``g`` must be an undirected graph, and implement ``vertex_list`` and ``adjacency_list``.

Topological Sorting
-------------------

Topological sorting of an acyclic directed graph is a linear ordering of vertices, such that for each directed edge ``(u, v)``, ``u`` always comes before ``v`` in the ordering.
Topological sorting of an acyclic directed graph is a linear ordering of vertices, such that for each directed edge ``(u, v)``, ``u`` always comes before ``v`` in the ordering.

.. py:function:: topological_sort_by_dfs(g)
Returns a topological sorting of the vertices in ``g`` in the form of a vector of vertices. Here, ``g`` may be directed or undirected, and implement ``vertex_list``, ``vertex_map``, and ``adjacency_list``.


Shortest Paths
---------------

Expand All @@ -112,18 +112,18 @@ Dijkstra's Algorithm

.. py:function:: dijkstra_shortest_paths(graph, edge_dists, source[, visitor])
Performs Dijkstra's algorithm to find shortest paths to all vertices from input sources.
Performs Dijkstra's algorithm to find shortest paths to all vertices from input sources.

:param graph: The input graph
:param edge_dists: The vector of edge distances or an edge
property inspector.
:param source: The source vertex (or vertices)
:param visitor: An visitor instance

:returns: An instance of ``DijkstraStates`` that encapsulates the results.

Here, ``graph`` can be directed or undirected. It must implement
``vertex_map``, ``edge_map`` and ``incidence_list``. `edge_dists` is optional; if not specified,
``vertex_map``, ``edge_map`` and ``incidence_list``. `edge_dists` is optional; if not specified,
default distances of `1` are used for each edge.

The following is an example that shows how to use this function:
Expand All @@ -148,11 +148,11 @@ The following is an example that shows how to use this function:
ne = length(g1_wedges)
dists = zeros(ne)
for i = 1 : ne
a = inputs[i]
add_edge!(g1, a[1], a[2]) # add edge
dists[i] = a[3] # set distance
dists[i] = a[3] # set distance
end
r = dijkstra_shortest_paths(g, dists, 1)
Expand All @@ -169,35 +169,41 @@ The user can (optionally) provide a visitor that perform operations along with t
.. py:function:: discover_vertex!(visitor, u, v, d)
Invoked when a new vertex ``v`` is first discovered (from the parent ``u``). ``d`` is the initial distance from ``v`` to source.
.. py:function:: include_vertex!(visitor, u, v, d)
Invoked when a new vertex ``v`` is first discovered (from the parent ``u``). ``d`` is the initial distance from ``v`` to source.
.. py:function:: include_vertex!(visitor, u, v, d)
Invoked when the distance of a vertex is determined (at the point ``v`` is popped from the heap). This function should return whether to continue the procedure. One can use a visitor to terminate the algorithm earlier by letting this function return ``false`` under certain conditions.
.. py:function:: update_vertex!(visitor, u, v, d)
Invoked when the distance to a vertex is updated (relaxed).
.. py:function:: close_vertex!(visitor, u, v, d)
Invoked when a vertex is closed (all its neighbors have been examined).
.. py:function:: dijkstra_shortest_paths_explicit(graph, edge_dists, source[, visitor])
Returns the explicit paths using ``dijkstra_shortest_paths()`` as an array of
vectors of vertices from the source to each target. Empty vectors are used to
indicate vertices that are unreachable from the source. Parameters are the same
as described in ``dijkstra_shortest_paths()``.
Bellman Ford Algorithm
~~~~~~~~~~~~~~~~~~~~

.. py:function:: bellman_ford_shortest_paths(graph, edge_dists, source)
Performs Bellman Ford algorithm to find shortest paths to all vertices from input sources.
Performs Bellman Ford algorithm to find shortest paths to all vertices from input sources.

:param graph: The input graph
:param edge_dists: The vector of edge distances or an edge
property inspector.
:param source: The source vertex (or vertices)

:returns: An instance of ``BellmanFordStates`` that encapsulates the results.

Here, ``graph`` can be directed or undirected. Weights can be negative
for a directed graph. It must implement
``vertex_map``, ``edge_map`` and ``incidence_list``. If there is a
Expand All @@ -222,18 +228,18 @@ Floyd-Warshall's algorithm

.. py:function:: floyd_warshall(dists)
Performs Floyd-Warshall algorithm to compute shortest path lengths between each pair of vertices.
:param dists: The edge distance matrix.
Performs Floyd-Warshall algorithm to compute shortest path lengths between each pair of vertices.

:param dists: The edge distance matrix.
:returns: The matrix of shortest path lengths.

.. py:function:: floyd_warshall!(dists)
Performs Floyd-Warshall algorithm inplace, updating an edge distance matrix into a matrix of shortest path lengths.

.. py:function:: floyd_warshall!(dists, nexts)
Performs Floyd-Warshall algorithm inplace, and writes the next-hop matrix. When this function finishes, ``nexts[i,j]`` is the next hop of ``i`` along the shortest path from ``i`` to ``j``. One can reconstruct the shortest path based on this matrix.
Performs Floyd-Warshall algorithm inplace, and writes the next-hop matrix. When this function finishes, ``nexts[i,j]`` is the next hop of ``i`` along the shortest path from ``i`` to ``j``. One can reconstruct the shortest path based on this matrix.


A*
Expand All @@ -254,22 +260,22 @@ A*
Minimum Spanning Trees
-----------------------

This package implements two algorithm to find a minimum spanning tree of a graph: *Prim's algorithm* and *Kruskal's algorithm*.
This package implements two algorithm to find a minimum spanning tree of a graph: *Prim's algorithm* and *Kruskal's algorithm*.

Prim's algorithm
~~~~~~~~~~~~~~~~~

Prim's algorithm finds a minimum spanning tree by growing from a root vertex, adding one edge at each iteration.
Prim's algorithm finds a minimum spanning tree by growing from a root vertex, adding one edge at each iteration.

.. py:function:: prim_minimum_spantree(graph, eweights, root)
Perform Prim's algorithm to find a minimum spanning tree.
Perform Prim's algorithm to find a minimum spanning tree.

:param graph: the input graph
:param eweights: the edge weights (a vector or an edge property inspector)
:param root: the root vertex
:returns: ``(re, rw)``, where ``re`` is a vector of edges that constitute the resultant tree, and ``rw`` is the vector of corresponding edge weights.

:returns: ``(re, rw)``, where ``re`` is a vector of edges that constitute the resultant tree, and ``rw`` is the vector of corresponding edge weights.


Kruskal's algorithm
Expand All @@ -282,8 +288,8 @@ Kruskal's algorithm finds a minimum spanning tree (or forest) by gradually uniti
:param graph: the input graph
:param eweights: the edge weights (a vector or an edge property inspector)
:param K: the number of trees in the resultant forest. If ``K = 1``, it ends up with a tree. This argument is optional. By default, it is set to ``1``.
:returns: ``(re, rw)``, where ``re`` is a vector of edges that constitute the resultant tree, and ``rw`` is the vector of corresponding edge weights.

:returns: ``(re, rw)``, where ``re`` is a vector of edges that constitute the resultant tree, and ``rw`` is the vector of corresponding edge weights.


Random Graphs
Expand Down
1 change: 1 addition & 0 deletions src/Graphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ module Graphs
DijkstraStates, create_dijkstra_states, AbstractDijkstraVisitor,
dijkstra_shortest_paths!, dijkstra_shortest_paths,
dijkstra_shortest_paths_withlog,
dijkstra_shortest_paths_explicit,

# bellmanford
BellmanFordStates, create_bellman_ford_states, NegativeCycleError,
Expand Down
34 changes: 34 additions & 0 deletions src/dijkstra_spath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,37 @@ end
dijkstra_shortest_paths{V}(
graph::AbstractGraph{V}, s::V
) = dijkstra_shortest_paths(graph, ones(num_vertices(graph)), s)

function dijkstra_shortest_paths_explicit{V}(g::AbstractGraph{V},all...)
state = dijkstra_shortest_paths(g,all...)
allvertices = g.vertices
patharr = Array(Vector{V},0)
parents = state.parents
dists = state.dists
for i in 1:length(parents)
path = V[]
currvertex = allvertices[i]
connected = isdefined(parents,i) && (parents[i] in allvertices)
if connected # that is, the current node has a valid parent
currparent = parents[i]
currvind = i
currpind = vertex_index(currparent, g)
lastparent = nothing
lastparentind = -1
# parent(src) == src and dist=0 when we're at the source
# so check to make sure we still have some path to follow
while (currvertex != currparent) && (dists[currvind] != zero(Float64))
# we do
push!(path, currvertex)
# follow the parent
currvertex = currparent
currparent = parents[currpind]
currvind = vertex_index(currvertex, g)
currpind = vertex_index(currparent, g)
end
push!(path, currvertex)
end
push!(patharr, reverse(path))
end
return patharr
end
6 changes: 6 additions & 0 deletions test/dijkstra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,9 @@ s2 = dijkstra_shortest_paths(g2, eweights2, [1])
@test s2.parents == [1, 1, 1, 3, 6, 3]
@test s2.dists == [0., 7., 9., 20., 20., 11.]
@test s2.colormap == [2, 2, 2, 2, 2, 2]

g3 = simple_graph(4)
add_edge!(g3,1,2); add_edge!(g3,1,3); add_edge!(g3,2,3); add_edge!(g3,3,4)
sps = dijkstra_shortest_paths_explicit(g3,2)
@test length(sps[1]) == 0
@test sps[4][2] == 3

0 comments on commit 742fdc7

Please sign in to comment.