Ticket #8922: trac_8922-reviewer.patch
File trac_8922-reviewer.patch, 31.5 KB (added by , 11 years ago) |
---|
-
sage/graphs/base/c_graph.pxd
# HG changeset patch # User Minh Van Nguyen <nguyenminh2@gmail.com> # Date 1275581569 25200 # Node ID 3166b00d898d9ff25ec2e3ba9062fa1d933ad4c6 # Parent 34e31a8c91d4dba1960a1012750538d18479a904 #8922: reviewer patch: induced subgraph search; unit tests for cdef functions and methods diff --git a/sage/graphs/base/c_graph.pxd b/sage/graphs/base/c_graph.pxd
a b 28 28 cpdef add_arc(self, int u, int v) 29 29 cpdef bint has_arc(self, int u, int v) 30 30 cpdef del_all_arcs(self, int u, int v) 31 cdef int *adjacency_sequence(self, int n, int *vertices, int v) 31 32 cpdef list all_arcs(self, int u, int v) 32 33 cpdef list in_neighbors(self, int v) 33 34 cpdef list out_neighbors(self, int u) -
sage/graphs/base/c_graph.pyx
diff --git a/sage/graphs/base/c_graph.pyx b/sage/graphs/base/c_graph.pyx
a b 840 840 """ 841 841 raise NotImplementedError() 842 842 843 cdef int *adjacency_sequence(self, int n, int *vertices, int v): 844 r""" 845 Returns the adjacency sequence corresponding to a list of vertices 846 and a vertex. See the function ``_test_adjacency_sequence()`` of 847 ``dense_graph.pyx`` and ``sparse_graph.pyx`` for unit tests. 848 849 INPUT: 850 851 - ``n`` -- nonnegative integer; the maximum index in ``vertices`` up 852 to which we want to consider. If ``n = 0``, we only want to know if 853 ``v`` is adjacent to ``vertices[0]``. If ``n = 1``, we want to know 854 if ``v`` is adjacent to both ``vertices[0]`` and ``vertices[1]``. 855 Let ``k`` be the length of ``vertices``. If ``0 <= n < k``, then we 856 want to know if ``v`` is adjacent to each of 857 ``vertices[0], vertices[1], ..., vertices[n]``. Where ``n = k - 1``, 858 then we consider all elements in the list ``vertices``. 859 860 - ``vertices`` -- list of vertices. 861 862 - ``v`` -- a vertex. 863 864 OUTPUT: 865 866 Returns a list of ``n`` integers, whose i-th element 867 is set to 1 iff ``v`` is adjacent to ``vertices[i]``. 868 """ 869 cdef int i = 0 870 cdef int *seq = <int *>sage_malloc(n * sizeof(int)) 871 for 0 <= i < n: 872 seq[i] = 1 if self.has_arc_unsafe(v, vertices[i]) else 0 873 return seq 874 843 875 cpdef list all_arcs(self, int u, int v): 844 876 """ 845 877 Return the labels of all arcs from ``u`` to ``v``. -
sage/graphs/base/dense_graph.pxd
diff --git a/sage/graphs/base/dense_graph.pxd b/sage/graphs/base/dense_graph.pxd
a b 21 21 cdef int radix_mod_mask 22 22 cdef int num_longs 23 23 cdef unsigned long *edges 24 cdef int * adjacency_sequence(self, int n, int * vertices, int vertex)25 24 26 25 # Method declarations inherited from CGraph: 27 26 # cdef int add_arc_unsafe(self, int, int) -
sage/graphs/base/dense_graph.pyx
diff --git a/sage/graphs/base/dense_graph.pyx b/sage/graphs/base/dense_graph.pyx
a b 456 456 self.check_vertex(u) 457 457 self.check_vertex(v) 458 458 self.del_arc_unsafe(u,v) 459 460 cdef int * adjacency_sequence(self, int n, int * vertices, int vertex):461 r"""462 Returns the adjacency sequence corresponding to a list of463 vertices, and a vertex464 465 INPUT:466 467 - ``n`` -- number of elements in ``vertices``468 - ``vertices`` -- list of vertices469 - ``vertex``470 471 OUTPUT:472 473 Returns a list of ``n`` integers, whose i th element474 is set to 1 iif vertex is adjacent to vertices[i]475 """476 477 cdef int i = 0478 cdef int * line479 line = <int *> sage_malloc(n*sizeof(int))480 for 0 <= i < n:481 line[i] = 1 if self.has_arc_unsafe(vertices[i],vertex) else 0482 483 return line484 459 485 460 ################################### 486 461 # Neighbor functions … … 609 584 sage_free(neighbors) 610 585 return output 611 586 587 ############################## 588 # Further tests. Unit tests for methods, functions, classes defined with cdef. 589 ############################## 612 590 613 591 def random_stress(): 614 592 """ … … 647 625 if Gnew.in_degrees[i] != Gold.in_degree(i): 648 626 raise RuntimeError( "NO" ) 649 627 628 def _test_adjacency_sequence(): 629 """ 630 Randomly test the method ``DenseGraph.adjacency_sequence()``. No output 631 indicates that no errors were found. 632 633 TESTS:: 634 635 sage: from sage.graphs.base.dense_graph import _test_adjacency_sequence 636 sage: _test_adjacency_sequence() # long time 637 """ 638 from sage.graphs.digraph import DiGraph 639 from sage.graphs.graph_generators import GraphGenerators 640 from sage.misc.prandom import randint, random 641 low = 0 642 high = 500 643 randg = DiGraph(GraphGenerators().RandomGNP(randint(low, high), random())) 644 n = randg.order() 645 cdef DenseGraph g = DenseGraph(n, 646 verts=randg.vertices(), 647 arcs=randg.edges(labels=False)) 648 assert g._num_verts() == randg.order(), ( 649 "Graph order mismatch: %s vs. %s" % (g._num_verts(), randg.order())) 650 assert g._num_arcs() == randg.size(), ( 651 "Graph size mismatch: %s vs. %s" % (g._num_arcs(), randg.size())) 652 M = randg.adjacency_matrix() 653 cdef int *V = <int *>sage_malloc(n * sizeof(int)) 654 cdef int i = 0 655 for v in randg.vertex_iterator(): 656 V[i] = v 657 i += 1 658 cdef int *seq 659 for 0 <= i < randint(50, 101): 660 u = randint(low, n - 1) 661 seq = g.adjacency_sequence(n, V, u) 662 A = [seq[k] for k in range(n)] 663 try: 664 assert A == list(M[u]) 665 except AssertionError: 666 sage_free(V) 667 sage_free(seq) 668 raise AssertionError("Graph adjacency mismatch") 669 sage_free(seq) 670 sage_free(V) 671 650 672 ########################################### 651 673 # Dense Graph Backend 652 674 ########################################### … … 1043 1065 NotImplementedError: Dense graphs do not support edge labels. 1044 1066 """ 1045 1067 raise NotImplementedError("Dense graphs do not support edge labels.") 1046 1047 -
sage/graphs/base/sparse_graph.pyx
diff --git a/sage/graphs/base/sparse_graph.pyx b/sage/graphs/base/sparse_graph.pyx
a b 1189 1189 raise RuntimeError("Label (%d) must be a nonnegative integer."%l) 1190 1190 return self.has_arc_label_unsafe(u,v,l) == 1 1191 1191 1192 ############################## 1193 # Further tests. Unit tests for methods, functions, classes defined with cdef. 1194 ############################## 1195 1192 1196 def random_stress(): 1193 1197 """ 1194 1198 Randomly search for mistakes in the code. … … 1302 1306 if Gnew.has_arc_unsafe(i,j) != Gold.has_edge(i,j): 1303 1307 raise RuntimeError( "NO" ) 1304 1308 1309 def _test_adjacency_sequence(): 1310 """ 1311 Randomly test the method ``SparseGraph.adjacency_sequence()``. No output 1312 indicates that no errors were found. 1313 1314 TESTS:: 1315 1316 sage: from sage.graphs.base.sparse_graph import _test_adjacency_sequence 1317 sage: _test_adjacency_sequence() # long time 1318 """ 1319 from sage.graphs.digraph import DiGraph 1320 from sage.graphs.graph_generators import GraphGenerators 1321 from sage.misc.prandom import randint, random 1322 low = 0 1323 high = 1000 1324 randg = DiGraph(GraphGenerators().RandomGNP(randint(low, high), random())) 1325 n = randg.order() 1326 # set all labels to 0 1327 E = [(u, v, 0) for u, v in randg.edges(labels=False)] 1328 cdef SparseGraph g = SparseGraph(n, 1329 verts=randg.vertices(), 1330 arcs=E) 1331 assert g._num_verts() == randg.order(), ( 1332 "Graph order mismatch: %s vs. %s" % (g._num_verts(), randg.order())) 1333 assert g._num_arcs() == randg.size(), ( 1334 "Graph size mismatch: %s vs. %s" % (g._num_arcs(), randg.size())) 1335 M = randg.adjacency_matrix() 1336 cdef int *V = <int *>sage_malloc(n * sizeof(int)) 1337 cdef int i = 0 1338 for v in randg.vertex_iterator(): 1339 V[i] = v 1340 i += 1 1341 cdef int *seq 1342 for 0 <= i < randint(50, 101): 1343 u = randint(low, n - 1) 1344 seq = g.adjacency_sequence(n, V, u) 1345 A = [seq[k] for k in range(n)] 1346 try: 1347 assert A == list(M[u]) 1348 except AssertionError: 1349 sage_free(V) 1350 sage_free(seq) 1351 raise AssertionError("Graph adjacency mismatch") 1352 sage_free(seq) 1353 sage_free(V) 1354 1305 1355 ########################################### 1306 1356 # Sparse Graph Backend 1307 1357 ########################################### … … 1798 1848 self._cg.del_arc_label(v_int, u_int, ll_int) 1799 1849 self._cg.add_arc_label(u_int, v_int, l_int) 1800 1850 self._cg.add_arc_label(v_int, u_int, l_int) 1801 1802 -
sage/graphs/generic_graph.py
diff --git a/sage/graphs/generic_graph.py b/sage/graphs/generic_graph.py
a b 6912 6912 if not inplace: 6913 6913 return G 6914 6914 6915 def induced_subgraph_search(self, G): 6916 r""" 6917 Returns an induced copy of `G` in self. 6918 6919 INPUT: 6920 6921 - ``G`` -- the graph whose copy we are looking for in ``self`` 6915 def subgraph_search(self, G, induced=False): 6916 r""" 6917 Returns a copy of ``G`` in ``self``. 6918 6919 INPUT: 6920 6921 - ``G`` -- the graph whose copy we are looking for in ``self``. 6922 6923 - ``induced`` -- boolean (default: ``False``). Whether or not to 6924 search for an induced copy of ``G`` in ``self``. 6925 6926 OUTPUT: 6927 6928 - If ``induced=False``, return a copy of ``G`` in this graph. 6929 Otherwise, return an induced copy of ``G`` in ``self``. If ``G`` 6930 is the empty graph, return the empty graph since it is a subgraph 6931 of every graph. Now suppose ``G`` is not the empty graph. If there 6932 is no copy (induced or otherwise) of ``G`` in ``self``, we return 6933 ``None``. 6922 6934 6923 6935 ALGORITHM: 6924 6936 6925 Brute-force 6926 6927 EXAMPLES: 6928 6929 A Petersen Graph contains a `P_5`::6930 6937 Brute-force search. 6938 6939 EXAMPLES: 6940 6941 The Petersen graph contains the path graph `P_5`:: 6942 6931 6943 sage: g = graphs.PetersenGraph() 6932 sage: h1 = g.induced_subgraph_search(graphs.PathGraph(5)) 6933 sage: h1 6944 sage: h1 = g.subgraph_search(graphs.PathGraph(5)); h1 6934 6945 Subgraph of (Petersen graph): Graph on 5 vertices 6935 6946 sage: h1.vertices() 6947 [0, 1, 2, 3, 4] 6948 sage: I1 = g.subgraph_search(graphs.PathGraph(5), induced=True); I1 6949 Subgraph of (Petersen graph): Graph on 5 vertices 6950 sage: I1.vertices() 6936 6951 [0, 1, 2, 3, 8] 6937 6938 It also contains a Claw (`K_{1,3}`):: 6939 6940 sage: h2 = g.induced_subgraph_search(graphs.ClawGraph()) 6941 sage: h2 6952 6953 It also contains the claw `K_{1,3}`:: 6954 6955 sage: h2 = g.subgraph_search(graphs.ClawGraph()); h2 6942 6956 Subgraph of (Petersen graph): Graph on 4 vertices 6943 6957 sage: h2.vertices() 6944 6958 [0, 1, 4, 5] 6945 6946 Of course both copies are isomorphic to the graphs we were looking 6947 for :: 6948 6949 sage: h1.is_isomorphic(graphs.PathGraph(5)) 6959 sage: I2 = g.subgraph_search(graphs.ClawGraph(), induced=True); I2 6960 Subgraph of (Petersen graph): Graph on 4 vertices 6961 sage: I2.vertices() 6962 [0, 1, 4, 5] 6963 6964 Of course the induced copies are isomorphic to the graphs we were 6965 looking for:: 6966 6967 sage: I1.is_isomorphic(graphs.PathGraph(5)) 6950 6968 True 6951 sage: h2.is_isomorphic(graphs.ClawGraph())6969 sage: I2.is_isomorphic(graphs.ClawGraph()) 6952 6970 True 6953 6971 6954 However, as it contains no induced subgraphs isomorphic to 6955 `P_6`, an exception is raised in this case :: 6956 6957 sage: g.induced_subgraph_search(graphs.PathGraph(6)) 6958 Traceback (most recent call last): 6959 ... 6960 ValueError: No induced copy of the graph exists 6972 However, the Petersen graph does not contain a subgraph isomorphic to 6973 `K_3`:: 6974 6975 sage: g.subgraph_search(graphs.CompleteGraph(3)) is None 6976 True 6977 6978 Nor does it contain a nonempty induced subgraph isomorphic to `P_6`:: 6979 6980 sage: g.subgraph_search(graphs.PathGraph(6), induced=True) is None 6981 True 6982 6983 The empty graph is a subgraph of every graph:: 6984 6985 sage: g.subgraph_search(graphs.EmptyGraph()) 6986 Graph on 0 vertices 6987 sage: g.subgraph_search(graphs.EmptyGraph(), induced=True) 6988 Graph on 0 vertices 6961 6989 """ 6962 6990 from sage.graphs.generic_graph_pyx import subgraph_search 6963 6964 H = subgraph_search(self, G, induced = True) 6965 6991 from sage.graphs.graph_generators import GraphGenerators 6992 if G.order() == 0: 6993 return GraphGenerators().EmptyGraph() 6994 H = subgraph_search(self, G, induced=induced) 6966 6995 if H == []: 6967 raise ValueError('No induced copy of the graph exists') 6968 6969 return self.subgraph(H) 6970 6971 def subgraph_search(self, G): 6972 r""" 6973 Returns an of `G` included in self. 6974 6975 INPUT: 6976 6977 - ``G`` -- the graph whose copy we are looking for in ``self`` 6978 6979 ALGORITHM: 6980 6981 Brute-force 6982 6983 EXAMPLES: 6984 6985 A Petersen Graph contains a `P_5` :: 6986 6987 sage: g = graphs.PetersenGraph() 6988 sage: h1 = g.subgraph_search(graphs.PathGraph(5)) 6989 sage: h1 6990 Subgraph of (Petersen graph): Graph on 5 vertices 6991 sage: h1.vertices() 6992 [0, 1, 2, 3, 4] 6993 6994 It also contains a Claw (`K_{1,3}`):: 6995 6996 sage: h2 = g.subgraph_search(graphs.ClawGraph()) 6997 sage: h2 6998 Subgraph of (Petersen graph): Graph on 4 vertices 6999 sage: h2.vertices() 7000 [0, 1, 4, 5] 7001 7002 However, as it contains no subgraph isomorphic to 7003 `K_3`, an exception is raised in this case :: 7004 7005 sage: g.subgraph_search(graphs.CompleteGraph(3)) 7006 Traceback (most recent call last): 7007 ... 7008 ValueError: No copy of the graph exists 7009 """ 7010 from sage.graphs.generic_graph_pyx import subgraph_search 7011 7012 H = subgraph_search(self, G) 7013 7014 if H == []: 7015 raise ValueError('No copy of the graph exists') 7016 6996 return None 7017 6997 return self.subgraph(H) 7018 6998 7019 6999 def random_subgraph(self, p, inplace=False): -
sage/graphs/generic_graph_pyx.pxd
diff --git a/sage/graphs/generic_graph_pyx.pxd b/sage/graphs/generic_graph_pyx.pxd
a b 6 6 cdef class GenericGraph_pyx(SageObject): 7 7 pass 8 8 9 9 cdef inline bint vectors_equal(int n, int *a, int *b) 10 cdef inline bint vectors_inferior(int n, int *a, int *b) -
sage/graphs/generic_graph_pyx.pyx
diff --git a/sage/graphs/generic_graph_pyx.pyx b/sage/graphs/generic_graph_pyx.pyx
a b 19 19 include '../ext/cdefs.pxi' 20 20 include '../ext/stdsage.pxi' 21 21 22 # import from Python standard library 23 from random import random 24 25 # import from third-party library 22 26 from sage.graphs.base.dense_graph cimport DenseGraph 23 from random import random24 27 25 28 cdef extern from *: 26 29 double sqrt(double) … … 455 458 456 459 # Exhaustive search in graphs 457 460 458 cpdef subgraph_search(G,H, induced =False):461 cpdef list subgraph_search(G, H, bint induced=False): 459 462 r""" 460 Returns a set of vertices in G representing a copy of H463 Returns a set of vertices in ``G`` representing a copy of ``H``. 461 464 462 465 ALGORITHM: 463 466 464 467 This algorithm is a brute-force search. 465 Let `V(H) =\{h_1,\dots,h_k\}`. It first tries468 Let `V(H) = \{h_1,\dots,h_k\}`. It first tries 466 469 to find in `G` a possible representant of `h_1`, then a 467 470 representant of `h_2` compatible with `h_1`, then 468 471 a representant of `h_3` compatible with the first 469 two, etc ...472 two, etc. 470 473 471 This way, most of the time swe need to test far less than472 ` \binom k!{|V(G)|}{k}` subsets, and hope this brute-force474 This way, most of the time we need to test far less than 475 `k! \binom{|V(G)|}{k}` subsets, and hope this brute-force 473 476 technique can sometimes be useful. 474 477 475 478 INPUT: 476 479 477 - ``G``, ``H`` -- graphs480 - ``G``, ``H`` -- two graphs such that ``H`` is a subgraph of ``G``. 478 481 479 - ``induced`` (boolean) -- whether to require that the subgraph480 is an induced subgraph482 - ``induced`` -- boolean (default: ``False``); whether to require that 483 the subgraph is an induced subgraph. 481 484 482 485 OUTPUT: 483 486 484 A list of vertices inducing a copy of ``H`` . If none is found,487 A list of vertices inducing a copy of ``H`` in ``G``. If none is found, 485 488 an empty list is returned. 486 489 487 EXAMPLE :490 EXAMPLES: 488 491 489 A Petersen Graph contains an induced `P_5`::492 A Petersen graph contains an induced path graph `P_5`:: 490 493 491 494 sage: from sage.graphs.generic_graph_pyx import subgraph_search 492 495 sage: g = graphs.PetersenGraph() 493 sage: subgraph_search(g, graphs.PathGraph(5), induced =True)496 sage: subgraph_search(g, graphs.PathGraph(5), induced=True) 494 497 [0, 1, 2, 3, 8] 495 498 496 It also contains a Claw (`K_{1,3}`)::499 It also contains a the claw `K_{1,3}`:: 497 500 498 501 sage: subgraph_search(g, graphs.ClawGraph()) 499 502 [0, 1, 4, 5] 500 503 501 Though it contains no induced `P_6` 504 Though it contains no induced `P_6`:: 502 505 503 sage: subgraph_search(g, graphs.PathGraph(6), induced = True) 506 sage: subgraph_search(g, graphs.PathGraph(6), induced=True) 507 [] 508 509 TESTS: 510 511 Let `G` and `H` be graphs having orders `m` and `n`, respectively. If 512 `m < n`, then there are no copies of `H` in `G`:: 513 514 sage: from sage.graphs.generic_graph_pyx import subgraph_search 515 sage: m = randint(100, 200) 516 sage: n = randint(m + 1, 300) 517 sage: G = graphs.RandomGNP(m, random()) 518 sage: H = graphs.RandomGNP(n, random()) 519 sage: G.order() < H.order() 520 True 521 sage: subgraph_search(G, H) 504 522 [] 505 523 """ 506 524 # TODO: This is a brute-force search and can be very inefficient. Write 525 # a more efficient subgraph search implementation. 507 526 cdef int ng = G.order() 508 527 cdef int nh = H.order() 528 if ng < nh: 529 return [] 509 530 cdef int i, j, k 510 cdef int * tmp_array 511 512 cdef (int) (*is_admissible) (int, int *, int *) 513 531 cdef int *tmp_array 532 cdef (bint) (*is_admissible) (int, int *, int *) 514 533 if induced: 515 534 is_admissible = vectors_equal 516 535 else: 517 536 is_admissible = vectors_inferior 518 519 # Static copies of the two graphs for 520 # more efficient operations 521 537 # static copies of the two graphs for more efficient operations 522 538 cdef DenseGraph g = DenseGraph(ng) 523 539 cdef DenseGraph h = DenseGraph(nh) 524 525 # Copying the matrices 526 540 # copying the adjacency relations in both G and H 527 541 i = 0 528 for lin G.adjacency_matrix():542 for row in G.adjacency_matrix(): 529 543 j = 0 530 for k in l:544 for k in row: 531 545 if k: 532 g.add_arc(i,j) 533 j=j+1 534 i=i+1 535 546 g.add_arc(i, j) 547 j += 1 548 i += 1 536 549 i = 0 537 for lin H.adjacency_matrix():550 for row in H.adjacency_matrix(): 538 551 j = 0 539 for k in l:552 for k in row: 540 553 if k: 541 h.add_arc(i,j) 542 j=j+1 543 i=i+1 544 545 # A vertex is said to be busy if it is already part 546 # of the partial copy of H in G 547 cdef int * busy 548 busy = <int *> sage_malloc(ng*sizeof(int)) 549 memset(busy, 0, ng*sizeof(int)) 550 551 # 0 is the first vertex we use, so it is at first 552 # busy 554 h.add_arc(i, j) 555 j += 1 556 i += 1 557 # A vertex is said to be busy if it is already part of the partial copy 558 # of H in G. 559 cdef int *busy = <int *>sage_malloc(ng * sizeof(int)) 560 memset(busy, 0, ng * sizeof(int)) 561 # 0 is the first vertex we use, so it is at first busy 553 562 busy[0] = 1 554 555 # stack563 # stack -- list of the vertices which are part of the partial copy of H 564 # in G. 556 565 # 557 # List of the vertices which are part of the 558 # partial copy of H in G 559 # 560 # stack[i] is the integer corresponding 561 # to the vertex of G representing 562 # the i th vertex of H 566 # stack[i] -- the integer corresponding to the vertex of G representing 567 # the i-th vertex of H. 563 568 # 564 569 # stack[i] = -1 means that i is not represented 565 # ... yet ! 566 567 cdef int * stack 568 stack = <int *> sage_malloc(nh*sizeof(int)) 570 # ... yet! 571 cdef int *stack = <int *>sage_malloc(nh * sizeof(int)) 569 572 stack[0] = 0 570 573 stack[1] = -1 571 572 # number of representants we have already 573 # found 574 575 # set to 1 as vertex 0 is already part of the partial 576 # copy of H ... 574 # Number of representants we have already found. Set to 1 as vertex 0 575 # is already part of the partial copy of H in G. 577 576 cdef int active = 1 578 579 # vertices is equal to range(nh), as an int * variable 580 cdef int * vertices 581 vertices = <int *> sage_malloc(nh*sizeof(int)) 582 for 0<= i < nh: 577 # vertices is equal to range(nh), as an int *variable 578 cdef int *vertices = <int *>sage_malloc(nh * sizeof(int)) 579 for 0 <= i < nh: 583 580 vertices[i] = i 584 585 581 # line_h[i] represents the adjacency sequence of vertex i 586 # in h relatively to vertices 0...i-1 587 cdef int ** line_h 588 line_h = <int **> sage_malloc(nh * sizeof(int *)) 589 for 0<= i < nh: 590 line_h[i] = <int *> h.adjacency_sequence( i, vertices, i) 591 582 # in h relative to vertices 0, 1, ..., i-1 583 cdef int **line_h = <int **>sage_malloc(nh * sizeof(int *)) 584 for 0 <= i < nh: 585 line_h[i] = <int *>h.adjacency_sequence(i, vertices, i) 592 586 # the sequence of vertices to be returned 593 value = []587 cdef list value = [] 594 588 595 589 _sig_on 596 590 597 591 # as long as there is a non-void partial copy of H in G 598 592 while active: 599 600 # If we are here and found nothing yet 601 # we try the next possible vertex 602 # as a representant of the active th 603 # vertex of H 604 i = stack[active] +1 605 606 # Looking for a vertex which is not busy 607 # and compatible with the partial copy we have of H 593 # If we are here and found nothing yet, we try the next possible 594 # vertex as a representant of the active i-th vertex of H. 595 i = stack[active] + 1 596 # Looking for a vertex that is not busy and compatible with the 597 # partial copy we have of H. 608 598 while i < ng: 609 if busy[i] == 1:610 i = i +1599 if busy[i]: 600 i += 1 611 601 else: 612 tmp_array = g.adjacency_sequence(active, stack, i) 613 602 tmp_array = g.adjacency_sequence(active, stack, i) 614 603 if is_admissible(active, tmp_array, line_h[active]): 615 free(tmp_array)604 sage_free(tmp_array) 616 605 break 617 606 else: 618 free(tmp_array) 619 i = i + 1 620 621 # if we found none, it means that we can not extend the current copy of H 622 # so we update the status of stack[active] 623 # and prepare to change the previous vertex 607 sage_free(tmp_array) 608 i += 1 609 # If we found none, it means that we cannot extend the current copy 610 # of H so we update the status of stack[active] and prepare to change 611 # the previous vertex. 624 612 if i >= ng: 625 613 if stack[active] != -1: 626 614 busy[stack[active]] = 0 627 615 stack[active] = -1 628 active=active-1 629 630 631 # If we have found a good representant of H's i^{th} vertex in G 616 active -= 1 617 # If we have found a good representant of H's i-th vertex in G 632 618 else: 633 634 619 if stack[active] != -1: 635 busy[stack[active]] =0620 busy[stack[active]] = 0 636 621 stack[active] = i 637 busy[stack[active]]=1 638 639 active = active + 1 640 641 # We have found our copy !!! 622 busy[stack[active]] = 1 623 active += 1 624 # We have found our copy!!! 642 625 if active == nh: 643 626 g_vertices = G.vertices() 644 627 value = [g_vertices[stack[i]] for i in xrange(nh)] 645 628 break 646 647 629 else: 648 630 # we begin the search of the next vertex at 0 649 631 stack[active] = -1 … … 654 636 sage_free(busy) 655 637 sage_free(stack) 656 638 sage_free(vertices) 657 for 0 <= i < nh:639 for 0 <= i < nh: 658 640 sage_free(line_h[i]) 659 641 sage_free(line_h) 660 642 661 643 return value 662 644 663 664 cdef int vectors_equal(int n, int * a, int * b): 645 cdef inline bint vectors_equal(int n, int *a, int *b): 665 646 r""" 666 Tests whether two vectors given in argument are equal 647 Tests whether the two given vectors are equal. Two integer vectors 648 `a = (a_1, a_2, \dots, a_n)` and `b = (b_1, b_2, \dots, b_n)` are equal 649 iff `a_i = b_i` for all `i = 1, 2, \dots, n`. See the function 650 ``_test_vectors_equal_inferior()`` for unit tests. 667 651 668 652 INPUT: 669 653 670 - ``n`` -- length of the vectors 671 - ``a``,``b`` -- the two vectors 654 - ``n`` -- positive integer; length of the vectors. 655 656 - ``a``, ``b`` -- two vectors of integers. 657 658 OUTPUT: 659 660 - ``True`` if ``a`` and ``b`` are the same vector; ``False`` otherwise. 672 661 """ 673 674 cdef int i =0 675 for 0<= i < n: 662 cdef int i = 0 663 for 0 <= i < n: 676 664 if a[i] != b[i]: 677 665 return False 678 666 return True 679 667 680 cdef in t vectors_inferior(int n, int * a, int *b):668 cdef inline bint vectors_inferior(int n, int *a, int *b): 681 669 r""" 682 Tests whether the second vector of integer is larger than the first 670 Tests whether the second vector of integers is inferior to the first. Let 671 `u = (u_1, u_2, \dots, u_k)` and `v = (v_1, v_2, \dots, v_k)` be two 672 integer vectors of equal length. Then `u` is said to be less than 673 (or inferior to) `v` if `u_i \leq v_i` for all `i = 1, 2, \dots, k`. See 674 the function ``_test_vectors_equal_inferior()`` for unit tests. Given two 675 equal integer vectors `u` and `v`, `u` is inferior to `v` and vice versa. 676 We could also define two vectors `a` and `b` to be equal if `a` is 677 inferior to `b` and `b` is inferior to `a`. 683 678 684 679 INPUT: 685 680 686 - ``n`` -- length of the vectors 687 - ``a``,``b`` -- the two vectors 681 - ``n`` -- positive integer; length of the vectors. 682 683 - ``a``, ``b`` -- two vectors of integers. 684 685 OUTPUT: 686 687 - ``True`` if ``b`` is inferior to (or less than) ``a``; ``False`` 688 otherwise. 688 689 """ 689 690 cdef int i =0 691 for 0<= i < n: 690 cdef int i = 0 691 for 0 <= i < n: 692 692 if a[i] < b[i]: 693 693 return False 694 694 return True 695 695 696 ############################## 697 # Further tests. Unit tests for methods, functions, classes defined with cdef. 698 ############################## 699 700 def _test_vectors_equal_inferior(): 701 """ 702 Unit testing the function ``vectors_equal()``. No output means that no 703 errors were found in the random tests. 704 705 TESTS:: 706 707 sage: from sage.graphs.generic_graph_pyx import _test_vectors_equal_inferior 708 sage: _test_vectors_equal_inferior() 709 """ 710 from sage.misc.prandom import randint 711 n = randint(500, 10**3) 712 cdef int *u = <int *>sage_malloc(n * sizeof(int)) 713 cdef int *v = <int *>sage_malloc(n * sizeof(int)) 714 cdef int i 715 # equal vectors: u = v 716 for 0 <= i < n: 717 u[i] = randint(-10**6, 10**6) 718 v[i] = u[i] 719 try: 720 assert vectors_equal(n, u, v) 721 assert vectors_equal(n, v, u) 722 # Since u and v are equal vectors, then u is inferior to v and v is 723 # inferior to u. One could also define u and v as being equal if 724 # u is inferior to v and vice versa. 725 assert vectors_inferior(n, u, v) 726 assert vectors_inferior(n, v, u) 727 except AssertionError: 728 sage_free(u) 729 sage_free(v) 730 raise AssertionError("Vectors u and v should be equal.") 731 # Different vectors: u != v because we have u_j > v_j for some j. Thus, 732 # u_i = v_i for 0 <= i < j and u_j > v_j. For j < k < n - 2, we could have: 733 # (1) u_k = v_k, 734 # (2) u_k < v_k, or 735 # (3) u_k > v_k. 736 # And finally, u_{n-1} < v_{n-1}. 737 cdef int j = randint(1, n//2) 738 cdef int k 739 for 0 <= i < j: 740 u[i] = randint(-10**6, 10**6) 741 v[i] = u[i] 742 u[j] = randint(-10**6, 10**6) 743 v[j] = u[j] - randint(1, 10**6) 744 for j < k < n: 745 u[k] = randint(-10**6, 10**6) 746 v[k] = randint(-10**6, 10**6) 747 u[n - 1] = v[n - 1] - randint(1, 10**6) 748 try: 749 assert not vectors_equal(n, u, v) 750 assert not vectors_equal(n, v, u) 751 # u is not inferior to v because at least u_j > v_j 752 assert u[j] > v[j] 753 assert not vectors_inferior(n, v, u) 754 # v is not inferior to u because at least v_{n-1} > u_{n-1} 755 assert v[n - 1] > u[n - 1] 756 assert not vectors_inferior(n, u, v) 757 except AssertionError: 758 sage_free(u) 759 sage_free(v) 760 raise AssertionError("".join([ 761 "Vectors u and v should not be equal. ", 762 "u should not be inferior to v, and vice versa."])) 763 # Different vectors: u != v because we have u_j < v_j for some j. Thus, 764 # u_i = v_i for 0 <= i < j and u_j < v_j. For j < k < n - 2, we could have: 765 # (1) u_k = v_k, 766 # (2) u_k < v_k, or 767 # (3) u_k > v_k. 768 # And finally, u_{n-1} > v_{n-1}. 769 j = randint(1, n//2) 770 for 0 <= i < j: 771 u[i] = randint(-10**6, 10**6) 772 v[i] = u[i] 773 u[j] = randint(-10**6, 10**6) 774 v[j] = u[j] + randint(1, 10**6) 775 for j < k < n: 776 u[k] = randint(-10**6, 10**6) 777 v[k] = randint(-10**6, 10**6) 778 u[n - 1] = v[n - 1] + randint(1, 10**6) 779 try: 780 assert not vectors_equal(n, u, v) 781 assert not vectors_equal(n, v, u) 782 # u is not inferior to v because at least u_{n-1} > v_{n-1} 783 assert u[n - 1] > v[n - 1] 784 assert not vectors_inferior(n, v, u) 785 # v is not inferior to u because at least u_j < v_j 786 assert u[j] < v[j] 787 assert not vectors_inferior(n, u, v) 788 except AssertionError: 789 sage_free(u) 790 sage_free(v) 791 raise AssertionError("".join([ 792 "Vectors u and v should not be equal. ", 793 "u should not be inferior to v, and vice versa."])) 794 # different vectors u != v 795 # What's the probability of two random vectors being equal? 796 for 0 <= i < n: 797 u[i] = randint(-10**6, 10**6) 798 v[i] = randint(-10**6, 10**6) 799 try: 800 assert not vectors_equal(n, u, v) 801 assert not vectors_equal(n, v, u) 802 except AssertionError: 803 sage_free(u) 804 sage_free(v) 805 raise AssertionError("Vectors u and v should not be equal.") 806 # u is inferior to v, but v is not inferior to u 807 for 0 <= i < n: 808 v[i] = randint(-10**6, 10**6) 809 u[i] = randint(-10**6, 10**6) 810 while u[i] > v[i]: 811 u[i] = randint(-10**6, 10**6) 812 try: 813 assert not vectors_equal(n, u, v) 814 assert not vectors_equal(n, v, u) 815 assert vectors_inferior(n, v, u) 816 assert not vectors_inferior(n, u, v) 817 except AssertionError: 818 raise AssertionError( 819 "u should be inferior to v, but v is not inferior to u.") 820 finally: 821 sage_free(u) 822 sage_free(v)