Ticket #8922: trac_8922-reviewer.patch

File trac_8922-reviewer.patch, 31.5 KB (added by mvngu, 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  
    2828    cpdef add_arc(self, int u, int v)
    2929    cpdef bint has_arc(self, int u, int v)
    3030    cpdef del_all_arcs(self, int u, int v)
     31    cdef int *adjacency_sequence(self, int n, int *vertices, int v)
    3132    cpdef list all_arcs(self, int u, int v)
    3233    cpdef list in_neighbors(self, int v)
    3334    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  
    840840        """
    841841        raise NotImplementedError()
    842842
     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
    843875    cpdef list all_arcs(self, int u, int v):
    844876        """
    845877        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  
    2121    cdef int radix_mod_mask
    2222    cdef int num_longs
    2323    cdef unsigned long *edges
    24     cdef int * adjacency_sequence(self, int n, int * vertices, int vertex)
    2524
    2625    # Method declarations inherited from CGraph:
    2726    # 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  
    456456        self.check_vertex(u)
    457457        self.check_vertex(v)
    458458        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 of
    463         vertices, and a vertex
    464        
    465         INPUT:
    466 
    467         - ``n`` -- number of elements in ``vertices``
    468         - ``vertices`` -- list of vertices
    469         - ``vertex``
    470 
    471         OUTPUT:
    472 
    473         Returns a list of ``n`` integers, whose i th element
    474         is set to 1 iif vertex is adjacent to vertices[i]
    475         """
    476 
    477         cdef int i = 0
    478         cdef int * line
    479         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 0
    482 
    483         return line
    484459   
    485460    ###################################
    486461    # Neighbor functions
     
    609584        sage_free(neighbors)
    610585        return output
    611586
     587##############################
     588# Further tests. Unit tests for methods, functions, classes defined with cdef.
     589##############################
    612590
    613591def random_stress():
    614592    """
     
    647625        if Gnew.in_degrees[i] != Gold.in_degree(i):
    648626            raise RuntimeError( "NO" )
    649627
     628def _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
    650672###########################################
    651673# Dense Graph Backend
    652674###########################################
     
    10431065            NotImplementedError: Dense graphs do not support edge labels.
    10441066        """       
    10451067        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  
    11891189            raise RuntimeError("Label (%d) must be a nonnegative integer."%l)
    11901190        return self.has_arc_label_unsafe(u,v,l) == 1
    11911191
     1192##############################
     1193# Further tests. Unit tests for methods, functions, classes defined with cdef.
     1194##############################
     1195
    11921196def random_stress():
    11931197    """
    11941198    Randomly search for mistakes in the code.
     
    13021306            if Gnew.has_arc_unsafe(i,j) != Gold.has_edge(i,j):
    13031307                raise RuntimeError( "NO" )
    13041308
     1309def _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
    13051355###########################################
    13061356# Sparse Graph Backend
    13071357###########################################
     
    17981848            self._cg.del_arc_label(v_int, u_int, ll_int)
    17991849            self._cg.add_arc_label(u_int, v_int, l_int)
    18001850            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  
    69126912        if not inplace:
    69136913            return G
    69146914
    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``.
    69226934
    69236935        ALGORITHM:
    69246936
    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
    69316943             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
    69346945             Subgraph of (Petersen graph): Graph on 5 vertices
    69356946             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()
    69366951             [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
    69426956             Subgraph of (Petersen graph): Graph on 4 vertices
    69436957             sage: h2.vertices()
    69446958             [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))
    69506968             True
    6951              sage: h2.is_isomorphic(graphs.ClawGraph())
     6969             sage: I2.is_isomorphic(graphs.ClawGraph())
    69526970             True
    69536971
    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
    69616989        """
    69626990        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)
    69666995        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
    70176997        return self.subgraph(H)
    70186998   
    70196999    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  
    66cdef class GenericGraph_pyx(SageObject):
    77    pass
    88
    9 
     9cdef inline bint vectors_equal(int n, int *a, int *b)
     10cdef 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  
    1919include '../ext/cdefs.pxi'           
    2020include '../ext/stdsage.pxi'
    2121
     22# import from Python standard library
     23from random import random
     24
     25# import from third-party library
    2226from sage.graphs.base.dense_graph cimport DenseGraph
    23 from random import random
    2427
    2528cdef extern from *:
    2629    double sqrt(double)
     
    455458
    456459# Exhaustive search in graphs
    457460
    458 cpdef subgraph_search(G,H, induced = False):
     461cpdef list subgraph_search(G, H, bint induced=False):
    459462    r"""
    460     Returns a set of vertices in G representing a copy of H
     463    Returns a set of vertices in ``G`` representing a copy of ``H``.
    461464
    462465    ALGORITHM:
    463466
    464467    This algorithm is a brute-force search.
    465     Let `V(H)=\{h_1,\dots,h_k\}`.  It first tries
     468    Let `V(H) = \{h_1,\dots,h_k\}`.  It first tries
    466469    to find in `G` a possible representant of `h_1`, then a
    467470    representant of `h_2` compatible with `h_1`, then
    468471    a representant of `h_3` compatible with the first
    469     two, etc ...
     472    two, etc.
    470473
    471     This way, most of the times we need to test far less than
    472     `\binom k!{|V(G)|}{k}` subsets, and hope this brute-force
     474    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
    473476    technique can sometimes be useful.
    474477
    475478    INPUT:
    476479
    477     - ``G``, ``H`` -- graphs
     480    - ``G``, ``H`` -- two graphs such that ``H`` is a subgraph of ``G``.
    478481
    479     - ``induced`` (boolean) -- whether to require that the subgraph
    480       is an induced subgraph
     482    - ``induced`` -- boolean (default: ``False``); whether to require that
     483      the subgraph is an induced subgraph.
    481484
    482485    OUTPUT:
    483486
    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,
    485488    an empty list is returned.
    486489
    487     EXAMPLE:
     490    EXAMPLES:
    488491
    489     A Petersen Graph contains an induced `P_5` ::
     492    A Petersen graph contains an induced path graph `P_5`::
    490493
    491494        sage: from sage.graphs.generic_graph_pyx import subgraph_search
    492495        sage: g = graphs.PetersenGraph()
    493         sage: subgraph_search(g, graphs.PathGraph(5), induced = True)
     496        sage: subgraph_search(g, graphs.PathGraph(5), induced=True)
    494497        [0, 1, 2, 3, 8]
    495498
    496     It also contains a Claw (`K_{1,3}`)::
     499    It also contains a the claw `K_{1,3}`::
    497500
    498501        sage: subgraph_search(g, graphs.ClawGraph())
    499502        [0, 1, 4, 5]
    500503
    501     Though it contains no induced `P_6` ::
     504    Though it contains no induced `P_6`::
    502505
    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)
    504522        []
    505523    """
    506 
     524    # TODO: This is a brute-force search and can be very inefficient. Write
     525    # a more efficient subgraph search implementation.
    507526    cdef int ng = G.order()
    508527    cdef int nh = H.order()
     528    if ng < nh:
     529        return []
    509530    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 *)
    514533    if induced:
    515534        is_admissible = vectors_equal
    516535    else:
    517536        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
    522538    cdef DenseGraph g = DenseGraph(ng)
    523539    cdef DenseGraph h = DenseGraph(nh)
    524 
    525     # Copying the matrices
    526 
     540    # copying the adjacency relations in both G and H
    527541    i = 0
    528     for l in G.adjacency_matrix():
     542    for row in G.adjacency_matrix():
    529543        j = 0
    530         for k in l:
     544        for k in row:
    531545            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
    536549    i = 0
    537     for l in H.adjacency_matrix():
     550    for row in H.adjacency_matrix():
    538551        j = 0
    539         for k in l:
     552        for k in row:
    540553            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
    553562    busy[0] = 1
    554 
    555     # stack
     563    # stack -- list of the vertices which are part of the partial copy of H
     564    # in G.
    556565    #
    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.
    563568    #
    564569    # 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))
    569572    stack[0] = 0
    570573    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.
    577576    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:
    583580        vertices[i] = i
    584 
    585581    # 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)
    592586    # the sequence of vertices to be returned
    593     value = []
     587    cdef list value = []
    594588   
    595589    _sig_on
    596590
    597591    # as long as there is a non-void partial copy of H in G
    598592    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.
    608598        while i < ng:
    609             if busy[i] == 1:
    610                 i = i + 1
     599            if busy[i]:
     600                i += 1
    611601            else:
    612                 tmp_array =  g.adjacency_sequence(active, stack, i)
    613 
     602                tmp_array = g.adjacency_sequence(active, stack, i)
    614603                if is_admissible(active, tmp_array, line_h[active]):
    615                     free(tmp_array)
     604                    sage_free(tmp_array)
    616605                    break
    617606                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.
    624612        if i >= ng:
    625613            if stack[active] != -1:
    626614                busy[stack[active]] = 0
    627615            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
    632618        else:
    633 
    634619            if stack[active] != -1:
    635                 busy[stack[active]]=0
     620                busy[stack[active]] = 0
    636621            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!!!
    642625            if active == nh:
    643626                g_vertices = G.vertices()
    644627                value = [g_vertices[stack[i]] for i in xrange(nh)]
    645628                break
    646 
    647629            else:
    648630                # we begin the search of the next vertex at 0
    649631                stack[active] = -1
     
    654636    sage_free(busy)
    655637    sage_free(stack)
    656638    sage_free(vertices)
    657     for 0<= i < nh:
     639    for 0 <= i < nh:
    658640        sage_free(line_h[i])
    659641    sage_free(line_h)
    660642
    661643    return value
    662644
    663 
    664 cdef int vectors_equal(int n, int * a, int * b):
     645cdef inline bint vectors_equal(int n, int *a, int *b):
    665646    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.
    667651
    668652    INPUT:
    669653
    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.
    672661    """
    673 
    674     cdef int i =0
    675     for 0<= i < n:
     662    cdef int i = 0
     663    for 0 <= i < n:
    676664        if a[i] != b[i]:
    677665            return False
    678666    return True
    679667
    680 cdef int vectors_inferior(int n, int * a, int * b):
     668cdef inline bint vectors_inferior(int n, int *a, int *b):
    681669    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`.
    683678
    684679    INPUT:
    685680
    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.
    688689    """
    689 
    690     cdef int i =0
    691     for 0<= i < n:
     690    cdef int i = 0
     691    for 0 <= i < n:
    692692        if a[i] < b[i]:
    693693            return False
    694694    return True
    695695
     696##############################
     697# Further tests. Unit tests for methods, functions, classes defined with cdef.
     698##############################
     699
     700def _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)