Ticket #7724: trac_7724_iterator-rebased.patch
File trac_7724_iterator-rebased.patch, 12.5 KB (added by , 13 years ago) |
---|
-
sage/graphs/base/c_graph.pyx
# HG changeset patch # User Yann Laigle-Chapuy <yannlaiglechapuy@gmail.com> # Date 1261410197 -3600 # Node ID b66143e70dba9437c95d1f33dbfa26959097db54 # Parent 2a0d2c20d545899643823ba6cb346ac9774125c0 #7724 depth_first_search iterator diff -r 2a0d2c20d545 -r b66143e70dba sage/graphs/base/c_graph.pyx
a b 1389 1389 1390 1390 return shortest_path 1391 1391 1392 def depth_first_search(self, v, reverse=False, ignore_direction=False): 1393 r""" 1394 Returns a depth-first search from vertex v. 1395 1396 INPUT: 1397 1398 - ``reverse`` -- considers the reversed graph ( 1399 the out_neighbors become in_neighbors ). 1400 1401 The default value is ``False``. 1402 1403 - ``ignore_direction`` -- consider the undirected graph. 1404 1405 The default value is ``False``. 1406 1407 EXAMPLE:: 1408 1409 sage: G = Graph(graphs.PetersenGraph(), implementation='c_graph') 1410 sage: list(G.depth_first_search(0)) 1411 [0, 5, 8, 6, 9, 7, 2, 3, 4, 1] 1412 """ 1413 return Search_iterator(self, v, direction=-1, reverse=reverse, ignore_direction=ignore_direction) 1414 1415 def breadth_first_search(self, v, reverse=False, ignore_direction=False): 1416 r""" 1417 Returns a breadth-first search from vertex v. 1418 1419 INPUT: 1420 1421 - ``reverse`` -- considers the reversed graph ( 1422 the out_neighbors become in_neighbors ). 1423 1424 The default value is ``False``. 1425 1426 - ``ignore_direction`` -- consider the undirected graph. 1427 1428 The default value is ``False``. 1429 1430 1431 EXAMPLE:: 1432 1433 sage: G = Graph(graphs.PetersenGraph(), implementation='c_graph') 1434 sage: list(G.breadth_first_search(0)) 1435 [0, 1, 4, 5, 2, 6, 3, 9, 7, 8] 1436 """ 1437 return Search_iterator(self, v, direction=0, reverse=reverse, ignore_direction=ignore_direction) 1438 1439 def is_connected(self): 1440 r""" 1441 Returns whether the graph is connected. 1442 1443 EXAMPLE: 1444 1445 Petersen's graph is connected :: 1446 1447 sage: DiGraph(graphs.PetersenGraph(),implementation="c_graph").is_connected() 1448 True 1449 1450 While the disjoint union of two of them is not:: 1451 1452 sage: DiGraph(2*graphs.PetersenGraph(),implementation="c_graph").is_connected() 1453 False 1454 """ 1455 1456 cdef int v_int = 0 1457 v_int = bitset_first((<CGraph>self._cg).active_vertices) 1458 1459 if v_int == -1: 1460 return True 1461 1462 return len(list(self.depth_first_search(get_vertex(v_int, self.vertex_ints, self.vertex_labels, self._cg),\ 1463 ignore_direction=True))\ 1464 ) == (<CGraph>self._cg).num_verts 1465 1466 def is_strongly_connected(self): 1467 r""" 1468 Returns whether the graph is strongly connected. 1469 1470 EXAMPLE: 1471 1472 The circuit on 3 vertices is obviously strongly connected :: 1473 1474 sage: g = DiGraph({ 0 : [1], 1 : [2], 2 : [0]},implementation="c_graph") 1475 sage: g.is_strongly_connected() 1476 True 1477 1478 But a transitive triangle is not:: 1479 1480 sage: g = DiGraph({ 0 : [1,2], 1 : [2]},implementation="c_graph") 1481 sage: g.is_strongly_connected() 1482 False 1483 """ 1484 cdef int v_int = 0 1485 1486 # Pick one vertex 1487 v_int = bitset_first((<CGraph>self._cg).active_vertices) 1488 1489 if v_int == -1: 1490 return True 1491 1492 v = get_vertex(v_int, self.vertex_ints, self.vertex_labels, self._cg) 1493 1494 return (<CGraph>self._cg).num_verts == len(list(self.depth_first_search(v))) and \ 1495 (<CGraph>self._cg).num_verts == len(list(self.depth_first_search(v, reverse=True))) 1496 1497 1498 cdef class Search_iterator: 1499 cdef graph 1500 cdef int direction 1501 cdef list stack 1502 cdef bitset_t seen 1503 cdef bool test_out 1504 cdef bool test_in 1505 1506 def __init__(self, graph, v, direction=0, reverse=False, ignore_direction=False): 1507 self.graph = graph 1508 self.direction = direction 1509 1510 bitset_init(self.seen,(<CGraph>self.graph._cg).active_vertices.size) 1511 bitset_set_first_n(self.seen,0) 1512 1513 self.stack = [get_vertex(v, self.graph.vertex_ints, self.graph.vertex_labels, self.graph._cg)] 1514 1515 if not self.graph.directed: 1516 ignore_direction = False 1517 1518 self.test_out = (not reverse) or ignore_direction 1519 self.test_in = reverse or ignore_direction 1520 1521 def __iter__(self): 1522 return self 1523 1524 def __next__(self): 1525 cdef int v_int 1526 cdef int w_int 1527 1528 while self.stack: 1529 v_int = self.stack.pop(self.direction) 1530 1531 if bitset_not_in(self.seen,v_int): 1532 value = vertex_label(v_int, self.graph.vertex_ints, self.graph.vertex_labels, self.graph._cg) 1533 bitset_add(self.seen,v_int) 1534 1535 if self.test_out: 1536 self.stack.extend(self.graph._cg.out_neighbors(v_int)) 1537 if self.test_in: 1538 self.stack.extend(self.graph._cg.in_neighbors(v_int)) 1539 1540 break 1541 else: 1542 bitset_free(self.seen) 1543 raise StopIteration 1544 1545 return value 1392 1546 1393 1547 1394 1548 -
sage/graphs/graph.py
diff -r 2a0d2c20d545 -r b66143e70dba sage/graphs/graph.py
a b 3200 3200 """ 3201 3201 if self.order() == 0: 3202 3202 return True 3203 v = self.vertex_iterator().next() 3204 conn_verts = list(self.breadth_first_search(v, ignore_direction=True)) 3205 return len(conn_verts) == self.num_verts() 3203 3204 try: 3205 return self._backend.is_connected() 3206 except AttributeError: 3207 v = self.vertex_iterator().next() 3208 conn_verts = list(self.depth_first_search(v, ignore_direction=True)) 3209 return len(conn_verts) == self.num_verts() 3206 3210 3207 3211 def connected_components(self): 3208 3212 """ … … 3276 3280 sage: D.connected_component_containing_vertex(0) 3277 3281 [0, 1, 2, 3] 3278 3282 """ 3279 c = list(self.breadth_first_search(vertex, ignore_direction=True)) 3283 try: 3284 c = list(self._backend.depth_first_search(vertex, ignore_direction=True)) 3285 except AttributeError: 3286 c = list(self.depth_first_search(vertex, ignore_direction=True)) 3287 3280 3288 c.sort() 3281 3289 return c 3282 3290 … … 8141 8149 [0, 1, 2] 8142 8150 8143 8151 """ 8144 if neighbors is None: 8145 if not self._directed or ignore_direction: 8146 neighbors=self.neighbor_iterator 8147 else: 8148 neighbors=self.neighbor_out_iterator 8149 seen=set([]) 8150 if isinstance(start, list): 8151 queue=[(v,0) for v in start] 8152 else: 8153 queue=[(start,0)] 8154 8155 for v,d in queue: 8156 yield v 8157 seen.add(v) 8158 8159 while len(queue)>0: 8160 v,d = queue.pop(0) 8161 if distance is None or d<distance: 8162 for w in neighbors(v): 8163 if w not in seen: 8164 seen.add(w) 8165 queue.append((w, d+1)) 8166 yield w 8152 # Preferably use the Cython implementation 8153 if neighbors is None and not isinstance(start,list) and distance is None and hasattr(self._backend,"breadth_first_search"): 8154 for v in self._backend.breadth_first_search(start, ignore_direction = ignore_direction): 8155 yield v 8156 else: 8157 if neighbors is None: 8158 if not self._directed or ignore_direction: 8159 neighbors=self.neighbor_iterator 8160 else: 8161 neighbors=self.neighbor_out_iterator 8162 seen=set([]) 8163 if isinstance(start, list): 8164 queue=[(v,0) for v in start] 8165 else: 8166 queue=[(start,0)] 8167 8168 for v,d in queue: 8169 yield v 8170 seen.add(v) 8171 8172 while len(queue)>0: 8173 v,d = queue.pop(0) 8174 if distance is None or d<distance: 8175 for w in neighbors(v): 8176 if w not in seen: 8177 seen.add(w) 8178 queue.append((w, d+1)) 8179 yield w 8167 8180 8168 8181 def depth_first_search(self, start, ignore_direction=False, distance=None, neighbors=None): 8169 8182 """ … … 8251 8264 [0, 2, 1] 8252 8265 8253 8266 """ 8254 if neighbors is None: 8255 if not self._directed or ignore_direction: 8256 neighbors=self.neighbor_iterator 8257 else: 8258 neighbors=self.neighbor_out_iterator 8259 seen=set([]) 8260 if isinstance(start, list): 8261 # Reverse the list so that the initial vertices come out in the same order 8262 queue=[(v,0) for v in reversed(start)] 8263 else: 8264 queue=[(start,0)] 8265 8266 while len(queue)>0: 8267 v,d = queue.pop() 8268 if v not in seen: 8269 yield v 8270 seen.add(v) 8271 if distance is None or d<distance: 8272 for w in neighbors(v): 8273 if w not in seen: 8274 queue.append((w, d+1)) 8267 # Preferably use the Cython implementation 8268 if neighbors is None and not isinstance(start,list) and distance is None and hasattr(self._backend,"depth_first_search"): 8269 for v in self._backend.depth_first_search(start, ignore_direction = ignore_direction): 8270 yield v 8271 else: 8272 if neighbors is None: 8273 if not self._directed or ignore_direction: 8274 neighbors=self.neighbor_iterator 8275 else: 8276 neighbors=self.neighbor_out_iterator 8277 seen=set([]) 8278 if isinstance(start, list): 8279 # Reverse the list so that the initial vertices come out in the same order 8280 queue=[(v,0) for v in reversed(start)] 8281 else: 8282 queue=[(start,0)] 8283 8284 while len(queue)>0: 8285 v,d = queue.pop() 8286 if v not in seen: 8287 yield v 8288 seen.add(v) 8289 if distance is None or d<distance: 8290 for w in neighbors(v): 8291 if w not in seen: 8292 queue.append((w, d+1)) 8275 8293 8276 8294 def lex_BFS(self,reverse=False,tree=False): 8277 8295 r""" … … 11724 11742 self._weighted = weighted 11725 11743 self.allow_loops(loops, check=False) 11726 11744 self.allow_multiple_edges(multiedges, check=False) 11745 self._backend.directed = False 11727 11746 else: 11728 11747 raise NotImplementedError("Supported implementations: networkx, c_graph.") 11729 11748 … … 13994 14013 self._weighted = weighted 13995 14014 self.allow_loops(loops, check=False) 13996 14015 self.allow_multiple_edges(multiedges, check=False) 14016 self._backend.directed = True 13997 14017 else: 13998 14018 raise NotImplementedError("Supported implementations: networkx, c_graph.") 13999 14019 … … 14886 14906 import networkx 14887 14907 return networkx.strongly_connected_components(self.networkx_graph(copy=False)) 14888 14908 14909 def is_strongly_connected(self): 14910 r""" 14911 Returns whether the current ``DiGraph`` is strongly connected. 14912 14913 EXAMPLE: 14914 14915 The circuit is obviously strongly connected :: 14916 14917 sage: g = digraphs.Circuit(5) 14918 sage: g.is_strongly_connected() 14919 True 14920 14921 But a transitive triangle is not:: 14922 14923 sage: g = DiGraph({ 0 : [1,2], 1 : [2]}) 14924 sage: g.is_strongly_connected() 14925 False 14926 """ 14927 if self.order()==1: 14928 return True 14929 14930 try: 14931 return self._backend.is_strongly_connected() 14932 14933 except AttributeError: 14934 return len(self.strongly_connected_components()) == 1 14935 14936 14889 14937 def tachyon_vertex_plot(g, bgcolor=(1,1,1), 14890 14938 vertex_colors=None, 14891 14939 vertex_size=0.06,