Ticket #7640: trac_7640.patch

File trac_7640.patch, 5.7 KB (added by ncohen, 11 years ago)
  • sage/graphs/base/c_graph.pyx

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # 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 b  
    11101110        self.vertex_labels = new_vx_labels
    11111111       
    11121112
     1113    def shortest_path(self,x,y):
     1114        r"""
     1115        Returns the shortest path between x and y
    11131116
     1117        EXAMPLE::
    11141118
     1119            sage: G = Graph(graphs.PetersenGraph(), implementation='c_graph')
     1120            sage: G.shortest_path(0,1)
     1121            [0, 1]
     1122        """
     1123
     1124        if x==y:
     1125            return 0
     1126
     1127        # The function being mostly symmetric in x and y
     1128        # their roles are reversed at the end of each loop
     1129        # For this reason is defined, for example,
     1130        # two dictionaries dist_y and dist_x containing the
     1131        # distances to x and y, and a dictionary
     1132        # dist_current and dist_other, pointing toward the
     1133        # previous two, alternatively.
     1134        #
     1135        # Besides, there is another difference in the fact
     1136        # that for directed graphs we are interested in paths
     1137        # leaving x toward y, so we are considering the out_neighbors
     1138        # on x's side, and in_neighbors on y's side
     1139
     1140        cdef int x_int = get_vertex(x, self.vertex_ints, self.vertex_labels, self._cg)
     1141        cdef int y_int = get_vertex(y, self.vertex_ints, self.vertex_labels, self._cg)
     1142        cdef int u = 0
     1143        cdef int v = 0
     1144        cdef int w = 0
     1145
     1146        # Each vertex knows its predecessors in the search, for each side
     1147        cdef dict pred_x = {}
     1148        cdef dict pred_y = {}
     1149        cdef dict pred_current = pred_x
     1150        cdef dict pred_other = pred_y
     1151
     1152        # Stores the distances from x and y
     1153        cdef dict dist_x = {}
     1154        cdef dict dist_y = {}
     1155        cdef dict dist_current = dist_x
     1156        cdef dict dist_other = dist_y
     1157        dist_x[x_int] = 0
     1158        dist_y[y_int] = 0
     1159
     1160        # Lists of vertices whose neighbors have not been explored yet
     1161        cdef list next_x = [x_int]
     1162        cdef list next_y = [y_int]
     1163        cdef list next_current = next_x
     1164        cdef list next_other = next_y
     1165        cdef list next_temporary = []
     1166
     1167        cdef list shortest_path = []
     1168
     1169        # We are interested in edges leaving x and entering y, so we
     1170        # are dealing with two different "neighbors" functions
     1171        cdef int out = 1
     1172
     1173        # As long as the current side (x or y) is not totally explored ...
     1174        while next_current:
     1175            next_temporary = []
     1176
     1177            # Take the next vertex in the list, and study all of its neighbors
     1178            # When a new neighbor is found, it is added into a temporary list
     1179            # When all the vertices in the list are tested
     1180            # and next_current is replaced by the temporary list
     1181            #
     1182            # After this, current and other are reversed, and the loop restarts
     1183            for u in next_current:
     1184                for v in (self._cg.out_neighbors(u) if out == 1 else self._cg.in_neighbors(u)):
     1185                    # If the neihgbor is new, updates the distances and adds to the list
     1186                    if not dist_current.has_key(v):
     1187                        dist_current[v] = dist_current[u] + 1
     1188                        pred_current[v] = u
     1189                        next_current.append(v)
     1190   
     1191                        # If the new neighbor is already known by the other side ...
     1192       
     1193                        if dist_other.has_key(v):
     1194                            # build the shortest path and returns in.
     1195       
     1196                            w = v
     1197       
     1198                            while w != x_int:
     1199                                shortest_path.append(vertex_label(w, self.vertex_ints, self.vertex_labels, self._cg))
     1200                                w = pred_x[w]
     1201       
     1202                            shortest_path.append(x)
     1203                            shortest_path.reverse()
     1204       
     1205                            if v == y_int:
     1206                                return shortest_path
     1207       
     1208                            w=pred_y[v]
     1209                            while w != y_int:
     1210                                shortest_path.append(vertex_label(w, self.vertex_ints, self.vertex_labels, self._cg))
     1211                                w = pred_y[w]
     1212                            shortest_path.append(y)
     1213       
     1214                            return shortest_path
     1215
     1216            next_current = next_temporary
     1217            pred_current, pred_other = pred_other, pred_current
     1218            dist_current, dist_other = dist_other, dist_current
     1219            next_current, next_other = next_other, next_current
     1220            out = -out
     1221
     1222        return []
  • sage/graphs/graph.py

    diff -r 2e4cf9d12539 -r 3ec89745ecdd sage/graphs/graph.py
    a b  
    62406240                L = networkx.dijkstra_path(self.networkx_graph(copy=False), u, v)
    62416241        else:
    62426242            if bidirectional:
    6243                 L = networkx.shortest_path(self.networkx_graph(copy=False), u, v)
     6243                # If the graph is a C_graph, use shortest_path from its backend !
     6244                try:
     6245                    L = self._backend.shortest_path(u,v)
     6246                except AttributeError:
     6247                    L = networkx.shortest_path(self.networkx_graph(copy=False), u, v)
    62446248            else:
    62456249                try:
    62466250                    L = networkx.single_source_shortest_path(self.networkx_graph(copy=False), u)[v]