# HG changeset patch
# User Nathann Cohen
# Date 1260639709 -3600
# Node ID 3ec89745ecddf37560738c9bdf6dda103b85dc16
# Parent 2e4cf9d12539d2e3acc4e4b82e794f86b8918345
Shortest path in c_graphs
diff -r 2e4cf9d12539 -r 3ec89745ecdd sage/graphs/base/c_graph.pyx
--- a/sage/graphs/base/c_graph.pyx Sat Dec 12 19:38:56 2009 +0100
+++ b/sage/graphs/base/c_graph.pyx Sat Dec 12 18:41:49 2009 +0100
@@ -1110,5 +1110,113 @@
self.vertex_labels = new_vx_labels
+ def shortest_path(self,x,y):
+ r"""
+ Returns the shortest path between x and y
+ EXAMPLE::
+ sage: G = Graph(graphs.PetersenGraph(), implementation='c_graph')
+ sage: G.shortest_path(0,1)
+ [0, 1]
+ """
+
+ if x==y:
+ return 0
+
+ # The function being mostly symmetric in x and y
+ # their roles are reversed at the end of each loop
+ # For this reason is defined, for example,
+ # two dictionaries dist_y and dist_x containing the
+ # distances to x and y, and a dictionary
+ # dist_current and dist_other, pointing toward the
+ # previous two, alternatively.
+ #
+ # Besides, there is another difference in the fact
+ # that for directed graphs we are interested in paths
+ # leaving x toward y, so we are considering the out_neighbors
+ # on x's side, and in_neighbors on y's side
+
+ cdef int x_int = get_vertex(x, self.vertex_ints, self.vertex_labels, self._cg)
+ cdef int y_int = get_vertex(y, self.vertex_ints, self.vertex_labels, self._cg)
+ cdef int u = 0
+ cdef int v = 0
+ cdef int w = 0
+
+ # Each vertex knows its predecessors in the search, for each side
+ cdef dict pred_x = {}
+ cdef dict pred_y = {}
+ cdef dict pred_current = pred_x
+ cdef dict pred_other = pred_y
+
+ # Stores the distances from x and y
+ cdef dict dist_x = {}
+ cdef dict dist_y = {}
+ cdef dict dist_current = dist_x
+ cdef dict dist_other = dist_y
+ dist_x[x_int] = 0
+ dist_y[y_int] = 0
+
+ # Lists of vertices whose neighbors have not been explored yet
+ cdef list next_x = [x_int]
+ cdef list next_y = [y_int]
+ cdef list next_current = next_x
+ cdef list next_other = next_y
+ cdef list next_temporary = []
+
+ cdef list shortest_path = []
+
+ # We are interested in edges leaving x and entering y, so we
+ # are dealing with two different "neighbors" functions
+ cdef int out = 1
+
+ # As long as the current side (x or y) is not totally explored ...
+ while next_current:
+ next_temporary = []
+
+ # Take the next vertex in the list, and study all of its neighbors
+ # When a new neighbor is found, it is added into a temporary list
+ # When all the vertices in the list are tested
+ # and next_current is replaced by the temporary list
+ #
+ # After this, current and other are reversed, and the loop restarts
+ for u in next_current:
+ for v in (self._cg.out_neighbors(u) if out == 1 else self._cg.in_neighbors(u)):
+ # If the neihgbor is new, updates the distances and adds to the list
+ if not dist_current.has_key(v):
+ dist_current[v] = dist_current[u] + 1
+ pred_current[v] = u
+ next_current.append(v)
+
+ # If the new neighbor is already known by the other side ...
+
+ if dist_other.has_key(v):
+ # build the shortest path and returns in.
+
+ w = v
+
+ while w != x_int:
+ shortest_path.append(vertex_label(w, self.vertex_ints, self.vertex_labels, self._cg))
+ w = pred_x[w]
+
+ shortest_path.append(x)
+ shortest_path.reverse()
+
+ if v == y_int:
+ return shortest_path
+
+ w=pred_y[v]
+ while w != y_int:
+ shortest_path.append(vertex_label(w, self.vertex_ints, self.vertex_labels, self._cg))
+ w = pred_y[w]
+ shortest_path.append(y)
+
+ return shortest_path
+
+ next_current = next_temporary
+ pred_current, pred_other = pred_other, pred_current
+ dist_current, dist_other = dist_other, dist_current
+ next_current, next_other = next_other, next_current
+ out = -out
+
+ return []
diff -r 2e4cf9d12539 -r 3ec89745ecdd sage/graphs/graph.py
--- a/sage/graphs/graph.py Sat Dec 12 19:38:56 2009 +0100
+++ b/sage/graphs/graph.py Sat Dec 12 18:41:49 2009 +0100
@@ -6240,7 +6240,11 @@
L = networkx.dijkstra_path(self.networkx_graph(copy=False), u, v)
else:
if bidirectional:
- L = networkx.shortest_path(self.networkx_graph(copy=False), u, v)
+ # If the graph is a C_graph, use shortest_path from its backend !
+ try:
+ L = self._backend.shortest_path(u,v)
+ except AttributeError:
+ L = networkx.shortest_path(self.networkx_graph(copy=False), u, v)
else:
try:
L = networkx.single_source_shortest_path(self.networkx_graph(copy=False), u)[v]