Ticket #7673: trac_7673.2.patch

File trac_7673.2.patch, 6.2 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 ecef1c315bf372705920f01eb0f82cdc0e3d3dbd
    # Parent  37983ed77183ab4491908430d75239078f310895
    Bidirectional Dijkstra in c_graphs
    
    diff -r 37983ed77183 -r ecef1c315bf3 sage/graphs/base/c_graph.pyx
    a b  
    12201220            out = -out
    12211221
    12221222        return []
     1223
     1224    def bidirectional_dijkstra(self,x,y):
     1225        r"""
     1226        Returns the shortest path between x and y using
     1227        a bidirectional version of Dijkstra
     1228 
     1229        EXAMPLE::
     1230 
     1231            sage: G = Graph(graphs.PetersenGraph(), implementation='c_graph')
     1232            sage: for (u,v) in G.edges(labels=None):
     1233            ...      G.set_edge_label(u,v,1)
     1234            sage: G.shortest_path(0,1,by_weight=True)
     1235            [0, 1]
     1236
     1237        TEST:
     1238
     1239        Bugfix from #7673 ::
     1240
     1241            sage: G = Graph(implementation="networkx")
     1242            sage: G.add_edges([(0,1,9),(0,2,8),(1,2,7)])
     1243            sage: Gc = G.copy(implementation='c_graph')
     1244            sage: sp = G.shortest_path_length(0,1,by_weight=True)
     1245            sage: spc = Gc.shortest_path_length(0,1,by_weight=True)
     1246            sage: sp == spc
     1247            True
     1248        """
     1249
     1250        if x==y:
     1251            return 0
     1252
     1253        # ****************** WARNING **********************
     1254        # Use Python to maintain a heap...
     1255        # Rewrite this in Cython as soon as possible !
     1256        # *************************************************
     1257        from heapq import heappush, heappop
     1258
     1259
     1260        # As for shortest_path, the roles of x and y are symmetric, hence we define
     1261        # dictionaries like pred_current and pred_other, which represent alternatively
     1262        # pred_x or pred_y according to the side studied
     1263        cdef int x_int = get_vertex(x, self.vertex_ints, self.vertex_labels, self._cg)
     1264        cdef int y_int = get_vertex(y, self.vertex_ints, self.vertex_labels, self._cg)
     1265        cdef int u = 0
     1266        cdef int v = 0
     1267        cdef int w = 0
     1268        cdef int pred
     1269        cdef float distance
     1270        cdef float edge_label
     1271        cdef int side
     1272        cdef float f_tmp
     1273
     1274        # Each vertex knows its predecessors in the search, for each side
     1275        cdef dict pred_x = {}
     1276        cdef dict pred_y = {}
     1277        cdef dict pred_current
     1278        cdef dict pred_other
     1279
     1280        # Stores the distances from x and y
     1281        cdef dict dist_x = {}
     1282        cdef dict dist_y = {}
     1283        cdef dict dist_current
     1284        cdef dict dist_other
     1285
     1286        # Lists of vertices who are left to be explored
     1287        # they are represented as 4-uples : (distance, side, predecessor ,name)
     1288        # 1 indicates x's side, -1 indicates y's, the distance being
     1289        # defined relatively
     1290        cdef list queue = [(0,1,x_int,x_int),(0,-1,y_int,y_int)]
     1291
     1292        cdef list shortest_path = []
     1293
     1294        # meeting_vertex is a vertex discovered through x and through y
     1295        # which defines ther shortest path found
     1296        # ( of length shortest_path_length )
     1297        cdef int meeting_vertex = -1
     1298        cdef float shortest_path_length
     1299
     1300        # As long as the current side (x or y) is not totally explored ...
     1301        while queue:
     1302           
     1303            (distance, side, pred, v) = heappop(queue)
     1304            if meeting_vertex != -1 and distance > shortest_path_length:
     1305                break
     1306
     1307            if side == 1:
     1308                dist_current, dist_other = dist_x, dist_y
     1309                pred_current, pred_other = pred_x, pred_y
     1310            else:
     1311                dist_current, dist_other = dist_y, dist_x
     1312                pred_current, pred_other = pred_y, pred_x
     1313           
     1314            if not dist_current.has_key(v):
     1315                pred_current[v] = pred
     1316                dist_current[v] = distance
     1317
     1318                if dist_other.has_key(v):
     1319                    f_tmp = distance + dist_other[v]
     1320                    if meeting_vertex == -1 or f_tmp<shortest_path_length:
     1321                        meeting_vertex = v
     1322                        shortest_path_length = f_tmp
     1323
     1324                for w in (self._cg.out_neighbors(v) if side == 1 else self._cg.in_neighbors(v)):
     1325                    # If the neihgbor is new, adds its non-found neighbors to the queue
     1326                    if not dist_current.has_key(w):
     1327                        edge_label = self.get_edge_label(v,w) if side == 1 else self.get_edge_label(w,v)
     1328                        heappush(queue,(distance + edge_label,side,v,w))
     1329                   
     1330
     1331        # No meeting point has been found
     1332        if meeting_vertex == -1:
     1333            return []
     1334        else:
     1335            # build the shortest path and returns it.
     1336            w = meeting_vertex
     1337
     1338            while w != x_int:
     1339                shortest_path.append(vertex_label(w, self.vertex_ints, self.vertex_labels, self._cg))
     1340                w = pred_x[w]
     1341
     1342            shortest_path.append(x)
     1343            shortest_path.reverse()
     1344
     1345            if meeting_vertex == y_int:
     1346                return shortest_path
     1347
     1348            w=pred_y[meeting_vertex]
     1349            while w != y_int:
     1350                shortest_path.append(vertex_label(w, self.vertex_ints, self.vertex_labels, self._cg))
     1351                w = pred_y[w]
     1352            shortest_path.append(y)
     1353
     1354            return shortest_path
     1355           
     1356       
     1357   
     1358           
     1359
  • sage/graphs/graph.py

    diff -r 37983ed77183 -r ecef1c315bf3 sage/graphs/graph.py
    a b  
    62276227        if by_weight:
    62286228            if bidirectional:
    62296229                try:
    6230                     L = networkx.bidirectional_dijkstra(self.networkx_graph(copy=False), u, v)[1]
    6231                 except:
    6232                     L = False
     6230                    L = self._backend.bidirectional_dijkstra(u,v)
     6231                except AttributeError:
     6232                    try:
     6233                        L = networkx.bidirectional_dijkstra(self.networkx_graph(copy=False), u, v)[1]
     6234                    except:
     6235                        L = False
    62336236            else:
    62346237                L = networkx.dijkstra_path(self.networkx_graph(copy=False), u, v)
    62356238        else: