Ticket #13917: trac_13917-v2.patch

File trac_13917-v2.patch, 24.6 KB (added by ncohen, 8 years ago)
  • doc/en/reference/graphs/index.rst

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1357313418 -3600
    # Node ID 52e82e90eadfed80e12ab5ad7ab904fea9fc4480
    # Parent  e70ee5cb77af0044d07b4e9d39ecf5200ffae9a6
    IndependentSets class
    
    diff --git a/doc/en/reference/graphs/index.rst b/doc/en/reference/graphs/index.rst
    a b  
    4848
    4949   sage/graphs/graph_coloring
    5050   sage/graphs/cliquer
     51   sage/graphs/independent_sets
    5152   sage/graphs/comparability
    5253   sage/graphs/line_graph
    5354   sage/graphs/spanning_tree
  • module_list.py

    diff --git a/module_list.py b/module_list.py
    a b  
    354354              sources = ['sage/graphs/cliquer.pyx'],
    355355              libraries = ['cliquer']),
    356356
     357    Extension('sage.graphs.independent_sets',
     358              sources = ['sage/graphs/independent_sets.pyx']),
    357359
    358360    Extension('sage.graphs.graph_decompositions.vertex_separation',
    359361              sources = ['sage/graphs/graph_decompositions/vertex_separation.pyx']),
  • new file sage/graphs/base/static_dense_graph.pxd

    diff --git a/sage/graphs/base/static_dense_graph.pxd b/sage/graphs/base/static_dense_graph.pxd
    new file mode 100644
    - +  
     1include "sage/misc/binary_matrix.pxi"
     2
     3cdef dict dense_graph_init(binary_matrix_t m, g, translation = ?)
  • sage/graphs/base/static_dense_graph.pyx

    diff --git a/sage/graphs/base/static_dense_graph.pyx b/sage/graphs/base/static_dense_graph.pyx
    a b  
    4040Functions
    4141---------
    4242"""
    43 include "sage/misc/binary_matrix.pxi"
    4443
    4544cdef dict dense_graph_init(binary_matrix_t m, g, translation = False):
    4645    r"""
  • sage/graphs/graph.py

    diff --git a/sage/graphs/graph.py b/sage/graphs/graph.py
    a b  
    45494549        # intensity of 1.
    45504550
    45514551        for g1,g2 in G.edges(labels = None):
    4552            
     4552
    45534553            p.add_constraint(   p.sum( flow[C][(g1,g2)] for C in H.edges(labels = False) )
    45544554                              + p.sum( flow[C][(g2,g1)] for C in H.edges(labels = False) ),
    45554555                                max = 1)
     
    45704570        v_repr = p.get_values(v_repr)
    45714571        flow = p.get_values(flow)
    45724572
    4573        
    45744573        for u,v in minor.edges(labels = False):
    45754574            used = False
    45764575            for C in H.edges(labels = False):
     
    45824581            if not used:
    45834582                minor.delete_edge(u,v)
    45844583
    4585         minor.delete_vertices( [v for v in minor 
     4584        minor.delete_vertices( [v for v in minor
    45864585                                if minor.degree(v) == 0 ] )
    45874586
    45884587        for g in minor:
     
    45964595
    45974596
    45984597    ### Cliques
    4599    
    4600     def cliques_maximal(self):
     4598
     4599    def cliques_maximal(self, algorithm = "native"):
    46014600        """
    46024601        Returns the list of all maximal cliques, with each clique represented
    46034602        by a list of vertices. A clique is an induced complete subgraph, and a
    46044603        maximal clique is one not contained in a larger one.
    4605        
     4604
     4605        INPUT:
     4606
     4607        - ``algorithm`` -- can be set to ``"native"`` (default) to use Sage's
     4608          own implementation, or to ``"NetworkX"`` to use NetworkX'
     4609          implementation of the Bron and Kerbosch Algorithm [BroKer1973]_.
     4610
    46064611        .. NOTE::
    4607        
    4608             Currently only implemented for undirected graphs. Use to_undirected
    4609             to convert a digraph to an undirected graph.
    4610        
    4611         ALGORITHM:
    4612        
    4613         This function is based on NetworkX's implementation of the Bron and
    4614         Kerbosch Algorithm [BroKer1973]_.
    4615            
     4612
     4613            This method sorts its output before returning it. If you prefer to
     4614            save the extra time, you can call
     4615            :class:`sage.graphs.independent_sets.IndependentSets` directly.
     4616
     4617        .. NOTE::
     4618
     4619            Sage's implementation of the enumeration of *maximal* independent
     4620            sets is not much faster than NetworkX' (expect a 2x speedup), which
     4621            is surprising as it is written in Cython. This being said, the
     4622            algorithm from NetworkX appears to be sligthly different from this
     4623            one, and that would be a good thing to explore if one wants to
     4624            improve the implementation.
     4625
    46164626        REFERENCE:
    46174627
    46184628        .. [BroKer1973] Coen Bron and Joep Kerbosch. (1973). Algorithm 457:
    46194629          Finding All Cliques of an Undirected Graph. Commun. ACM. v
    46204630          16. n 9.  pages 575-577. ACM Press. [Online] Available:
    46214631          http://www.ram.org/computing/rambin/rambin.html
    4622        
     4632
    46234633        EXAMPLES::
    4624        
     4634
    46254635            sage: graphs.ChvatalGraph().cliques_maximal()
    4626             [[0, 1], [0, 4], [0, 6], [0, 9], [2, 1], [2, 3], [2, 6], [2, 8], [3, 4], [3, 7], [3, 9], [5, 1], [5, 4], [5, 10], [5, 11], [7, 1], [7, 8], [7, 11], [8, 4], [8, 10], [10, 6], [10, 9], [11, 6], [11, 9]]
     4636            [[0, 1], [0, 4], [0, 6], [0, 9], [1, 2], [1, 5], [1, 7], [2, 3],
     4637             [2, 6], [2, 8], [3, 4], [3, 7], [3, 9], [4, 5], [4, 8], [5, 10],
     4638             [5, 11], [6, 10], [6, 11], [7, 8], [7, 11], [8, 10], [9, 10], [9, 11]]
    46274639            sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]})
    46284640            sage: G.show(figsize=[2,2])
    46294641            sage: G.cliques_maximal()
    46304642            [[0, 1, 2], [0, 1, 3]]
    46314643            sage: C=graphs.PetersenGraph()
    46324644            sage: C.cliques_maximal()
    4633             [[0, 1], [0, 4], [0, 5], [2, 1], [2, 3], [2, 7], [3, 4], [3, 8], [6, 1], [6, 8], [6, 9], [7, 5], [7, 9], [8, 5], [9, 4]]
     4645            [[0, 1], [0, 4], [0, 5], [1, 2], [1, 6], [2, 3], [2, 7], [3, 4],
     4646             [3, 8], [4, 9], [5, 7], [5, 8], [6, 8], [6, 9], [7, 9]]
    46344647            sage: C = Graph('DJ{')
    46354648            sage: C.cliques_maximal()
    4636             [[4, 0], [4, 1, 2, 3]]
     4649            [[0, 4], [1, 2, 3, 4]]
     4650
     4651        Comparing the two implementations::
     4652
     4653            sage: g = graphs.RandomGNP(20,.7)
     4654            sage: s1 = Set(map(Set, g.cliques_maximal(algorithm="NetworkX")))
     4655            sage: s2 = Set(map(Set, g.cliques_maximal(algorithm="native")))
     4656            sage: s1 == s2
     4657            True
    46374658
    46384659        """
    4639         import networkx
    4640         return sorted(networkx.find_cliques(self.networkx_graph(copy=False)))
     4660        if algorithm == "native":
     4661            from sage.graphs.independent_sets import IndependentSets
     4662            return sorted(IndependentSets(self, maximal = True, complement = True))
     4663        elif algorithm == "NetworkX":
     4664            import networkx
     4665            return sorted(networkx.find_cliques(self.networkx_graph(copy=False)))
     4666        else:
     4667            raise ValueError("Algorithm must be equal to 'native' or to 'NetworkX'.")
    46414668
    46424669    cliques = deprecated_function_alias(5739, cliques_maximal)
    46434670
     
    47994826            {0: 1, 1: 1, 2: 1, 3: 1, 4: 2}
    48004827            sage: E = C.cliques_maximal()
    48014828            sage: E
    4802             [[4, 0], [4, 1, 2, 3]]
     4829            [[0, 4], [1, 2, 3, 4]]
    48034830            sage: C.cliques_number_of(cliques=E)
    48044831            {0: 1, 1: 1, 2: 1, 3: 1, 4: 2}
    48054832            sage: F = graphs.Grid2dGraph(2,3)
     
    48274854        Returns a graph constructed with maximal cliques as vertices, and
    48284855        edges between maximal cliques with common members in the original
    48294856        graph.
    4830        
     4857
     4858        For more information, see the :wikipedia:`Clique_graph`.
     4859
    48314860        .. NOTE::
    4832        
     4861
    48334862            Currently only implemented for undirected graphs. Use to_undirected
    48344863            to convert a digraph to an undirected graph.
    4835        
     4864
    48364865        INPUT:
    4837        
     4866
    48384867        -  ``name`` - The name of the new graph.
    4839        
     4868
    48404869        EXAMPLES::
    4841        
     4870
    48424871            sage: (graphs.ChvatalGraph()).cliques_get_max_clique_graph()
    48434872            Graph on 24 vertices
    48444873            sage: ((graphs.ChvatalGraph()).cliques_get_max_clique_graph()).show(figsize=[2,2], vertex_size=20, vertex_labels=False)
     
    48894918        Equivalently, an independent set is defined as the complement of a
    48904919        vertex cover.
    48914920
     4921        For more information, see the
     4922        :wikipedia:`Independent_set_(graph_theory)` and the
     4923        :wikipedia:`Vertex_cover`.
     4924
    48924925        INPUT:
    48934926
    48944927        - ``algorithm`` -- the algorithm to be used
     
    49014934            * If ``algorithm = "MILP"``, the problem is solved through a Mixed
    49024935              Integer Linear Program.
    49034936
    4904               (see :class:`MixedIntegerLinearProgram <sage.numerical.mip>`)
     4937              (see :class:`MixedIntegerLinearProgram`)
    49054938
    49064939        - ``value_only`` -- boolean (default: ``False``). If set to ``True``,
    49074940          only the size of a maximum independent set is returned. Otherwise,
     
    52625295            {0: 2, 1: 4, 2: 4, 3: 4, 4: 4}
    52635296            sage: E = C.cliques_maximal()
    52645297            sage: E
    5265             [[4, 0], [4, 1, 2, 3]]
     5298            [[0, 4], [1, 2, 3, 4]]
    52665299            sage: C.cliques_vertex_clique_number(cliques=E,algorithm="networkx")
    52675300            {0: 2, 1: 4, 2: 4, 3: 4, 4: 4}
    52685301            sage: F = graphs.Grid2dGraph(2,3)
     
    53255358            {0: [[4, 0]], 1: [[4, 1, 2, 3]], 2: [[4, 1, 2, 3]], 3: [[4, 1, 2, 3]], 4: [[4, 0], [4, 1, 2, 3]]}
    53265359            sage: E = C.cliques_maximal()
    53275360            sage: E
    5328             [[4, 0], [4, 1, 2, 3]]
     5361            [[0, 4], [1, 2, 3, 4]]
    53295362            sage: C.cliques_containing_vertex(cliques=E)
    5330             {0: [[4, 0]], 1: [[4, 1, 2, 3]], 2: [[4, 1, 2, 3]], 3: [[4, 1, 2, 3]], 4: [[4, 0], [4, 1, 2, 3]]}
     5363            {0: [[0, 4]], 1: [[1, 2, 3, 4]], 2: [[1, 2, 3, 4]], 3: [[1, 2, 3, 4]], 4: [[0, 4], [1, 2, 3, 4]]}
    53315364            sage: F = graphs.Grid2dGraph(2,3)
    53325365            sage: X = F.cliques_containing_vertex()
    53335366            sage: for v in sorted(X.iterkeys()):
     
    53535386        """
    53545387        Returns the clique complex of self. This is the largest simplicial complex on
    53555388        the vertices of self whose 1-skeleton is self.
    5356        
     5389
    53575390        This is only makes sense for undirected simple graphs.
    53585391
    53595392        EXAMPLES::
     
    53615394            sage: g = Graph({0:[1,2],1:[2],4:[]})
    53625395            sage: g.clique_complex()
    53635396            Simplicial complex with vertex set (0, 1, 2, 4) and facets {(4,), (0, 1, 2)}
    5364            
     5397
    53655398            sage: h = Graph({0:[1,2,3,4],1:[2,3,4],2:[3]})
    53665399            sage: x = h.clique_complex()
    53675400            sage: x
  • new file sage/graphs/independent_sets.pxd

    diff --git a/sage/graphs/independent_sets.pxd b/sage/graphs/independent_sets.pxd
    new file mode 100644
    - +  
     1from libc.stdint cimport uint32_t, uint64_t
     2include "sage/misc/binary_matrix.pxi"
     3include "sage/misc/bitset_pxd.pxi"
     4#include "sage/misc/bitset_pxd.pxi"
     5
     6cdef class IndependentSets:
     7    cdef binary_matrix_t g
     8    cdef list vertices
     9    cdef dict vertex_to_int
     10    cdef int n
     11    cdef int i
     12    cdef int count_only
     13    cdef int maximal
     14
  • new file sage/graphs/independent_sets.pyx

    diff --git a/sage/graphs/independent_sets.pyx b/sage/graphs/independent_sets.pyx
    new file mode 100644
    - +  
     1r"""
     2Independent sets
     3
     4This module implements the :class:`IndependentSets` class which can be used to :
     5
     6- List the independent sets (or cliques) of a graph
     7- Count them (which is obviously faster)
     8- Test whether a set of vertices is an independent set
     9
     10It can also be restricted to focus on (inclusionwise) maximal independent
     11sets. See the documentation of :class:`IndependentSets` for actual examples.
     12
     13Classes and methods
     14-------------------
     15
     16"""
     17
     18include "sage/misc/bitset.pxi"
     19from sage.misc.cachefunc import cached_method
     20from sage.graphs.base.static_dense_graph cimport dense_graph_init
     21
     22cdef inline int bitset_are_disjoint(unsigned long * b1, unsigned long * b2, int width):
     23    r"""
     24    Tests whether two bitsets of length width*sizeof(unsigned int) have an empty
     25    intersection.
     26    """
     27    cdef int i
     28    for i in range(width):
     29        if b1[i]&b2[i]:
     30            return False
     31    return True
     32
     33cdef inline int ismaximal(binary_matrix_t g, int n, bitset_t s):
     34    cdef int i
     35    for i in range(n):
     36        if (not bitset_in(s,i)) and bitset_are_disjoint(g.rows[i],s.bits,g.width):
     37            return False
     38
     39    return True
     40
     41cdef class IndependentSets:
     42    r"""
     43    An instance of this class represents the set of independent sets of a graph.
     44
     45    For more information on independent sets, see the
     46    :wikipedia:`Independent_set_(graph_theory)`.
     47
     48    INPUT:
     49
     50    - ``G`` -- a graph
     51
     52    - ``maximal`` (boolean) -- whether to only consider (inclusionwise) maximal
     53      independent sets. Set to ``False`` by default.
     54
     55    - ``complement`` (boolean) -- whether to consider the graph's complement
     56      (i.e. cliques instead of independent sets). Set to ``False`` by default.
     57
     58    ALGORITHM:
     59
     60    The enumeration of independent sets is done naively : given an independent
     61    sets, this implementation considers all ways to add a new vertex to it
     62    (while keeping it an independent sets), and then creates new independent
     63    sets from all those that were created this way.
     64
     65    The implementation, however, is not recursive.
     66
     67    .. NOTE::
     68
     69        This implementation of the enumeration of *maximal* independent sets is
     70        not much faster than NetworkX', which is surprising as it is written in
     71        Cython. This being said, the algorithm from NetworkX appears to be
     72        sligthly different from this one, and that would be a good thing to
     73        explore if one wants to improve the implementation.
     74
     75    EXAMPLES:
     76
     77    Listing all independent sets of the Claw graph::
     78
     79        sage: from sage.graphs.independent_sets import IndependentSets
     80        sage: g = graphs.ClawGraph()
     81        sage: list(IndependentSets(g))
     82        [[0], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3], []]
     83
     84    Count them::
     85
     86        sage: IndependentSets(g).cardinality()
     87        9
     88
     89    List only the maximal independent sets::
     90
     91        sage: list(IndependentSets(g, maximal = True))
     92        [[0], [1, 2, 3]]
     93
     94    And count them::
     95
     96        sage: IndependentSets(g, maximal = True).cardinality()
     97        2
     98
     99    One can easily obtain an iterator over all independent sets of given
     100    cardinality::
     101
     102        sage: g = graphs.PetersenGraph()
     103        sage: is4 = (x for x in IndependentSets(g) if len(x) == 4)
     104        sage: list(is4)
     105        [[0, 2, 8, 9], [0, 3, 6, 7], [1, 3, 5, 9], [1, 4, 7, 8], [2, 4, 5, 6]]
     106
     107    Similarly, one can easily count the number of independent sets of each
     108    cardinality::
     109
     110        sage: number_of_is = [0] * g.order()
     111        sage: for x in IndependentSets(g):
     112        ...      number_of_is[len(x)] += 1
     113        sage: print number_of_is
     114        [1, 10, 30, 30, 5, 0, 0, 0, 0, 0]
     115    """
     116    def __init__(self, G, maximal = False, complement = False):
     117        r"""
     118        Constructor for this class
     119
     120        TESTS::
     121
     122            sage: from sage.graphs.independent_sets import IndependentSets
     123            sage: IndependentSets(graphs.PetersenGraph())
     124            <sage.graphs.independent_sets.IndependentSets object...
     125
     126        Compute the number of matchings, and check with Sage's implementation::
     127
     128            sage: from sage.graphs.independent_sets import IndependentSets
     129            sage: from sage.graphs.matchpoly import matching_polynomial
     130            sage: def check_matching(G):
     131            ...       number_of_matchings = sum(map(abs,matching_polynomial(G).coeffs()))
     132            ...       if number_of_matchings != IndependentSets(G.line_graph()).cardinality():
     133            ...           print "Ooooch !"
     134            sage: for i in range(30):
     135            ...       check_matching(graphs.RandomGNP(11,.3))
     136
     137        Compare the result with the output of subgraph_search::
     138
     139            sage: from sage.sets.set import Set
     140            sage: def check_matching(G):
     141            ...       IS = set(map(Set,list(IndependentSets(G))))
     142            ...       if not all(G.subgraph(l).is_independent_set() for l in IS):
     143            ...          print "Gloops"
     144            ...       omega = max(map(len,IS))
     145            ...       IS2 = [Set([x]) for x in range(G.order())] + [Set([])]
     146            ...       for n in range(2,omega+1):
     147            ...           IS2.extend(map(Set,list(G.subgraph_search_iterator(G.__class__(n), induced = True))))
     148            ...       if len(IS) != len(set(IS2)):
     149            ...          print "Oops"
     150            ...          print len(IS), len(set(IS2))
     151            sage: for i in range(5):
     152            ...       check_matching(graphs.RandomGNP(11,.3))
     153        """
     154        cdef int i
     155        if G.order() == 0:
     156            raise ValueError("This class can only handle non-empty graphs")
     157
     158        # Map from Vertex to Integer, and from Integer to Vertex
     159        self.vertices = G.vertices()
     160        self.n = G.order()
     161        self.maximal = maximal
     162        self.vertex_to_int = dense_graph_init(self.g, G, translation = True)
     163
     164        # If we must consider the graph's complement instead
     165        if complement:
     166            binary_matrix_complement(self.g)
     167            for i in range(self.n):
     168                binary_matrix_set0(self.g,i,i)
     169
     170        self.count_only = 0
     171
     172    def __iter__(self):
     173        r"""
     174        Returns self, as it has a __next__ method.
     175
     176        TESTS::
     177
     178            sage: from sage.graphs.independent_sets import IndependentSets
     179            sage: list(IndependentSets(graphs.PetersenGraph()))
     180            [[0], [0, 2], [0, 2, 6], [0, 2, 8], [0, 2, 8, 9], [0, 2, 9],
     181             [0, 3], [0, 3, 6], [0, 3, 6, 7], [0, 3, 7], [0, 3, 9],
     182             [0, 6], [0, 6, 7], [0, 7], [0, 7, 8], [0, 8], [0, 8, 9],
     183             [0, 9], [1], [1, 3], [1, 3, 5], [1, 3, 5, 9], [1, 3, 7],
     184             [1, 3, 9], [1, 4], [1, 4, 5], [1, 4, 7], [1, 4, 7, 8],
     185             [1, 4, 8], [1, 5], [1, 5, 9], [1, 7], [1, 7, 8], [1, 8],
     186             [1, 8, 9], [1, 9], [2], [2, 4], [2, 4, 5], [2, 4, 5, 6],
     187             [2, 4, 6], [2, 4, 8], [2, 5], [2, 5, 6], [2, 5, 9],
     188             [2, 6], [2, 8], [2, 8, 9], [2, 9], [3], [3, 5],
     189             [3, 5, 6], [3, 5, 9], [3, 6], [3, 6, 7], [3, 7],
     190             [3, 9], [4], [4, 5], [4, 5, 6], [4, 6], [4, 6, 7], [4, 7],
     191             [4, 7, 8], [4, 8], [5], [5, 6], [5, 9], [6], [6, 7], [7],
     192             [7, 8], [8], [8, 9], [9], []]
     193        """
     194        cdef int i = 0
     195
     196        cdef bitset_t current_set
     197        cdef bitset_t tmp
     198        bitset_init(current_set,self.n)
     199        bitset_set_first_n(current_set,0)
     200        bitset_add(current_set,0)
     201        bitset_init(tmp,self.n)
     202
     203        cdef uint64_t count = 0
     204        cdef list ans
     205        cdef int j
     206
     207        # At every moment of the algorithm current_set represents an independent
     208        # set, except for the ith bit. All bits >i are zero.
     209
     210        while True:
     211
     212            # If i is in current_set
     213            if bitset_in(current_set,i):
     214
     215                # We have found an independent set !
     216                if bitset_are_disjoint(self.g.rows[i],current_set.bits,self.g.width):
     217
     218                    # Saving that set
     219                    bitset_copy(tmp, current_set)
     220
     221                    # Preparing for the next set, except if we set the last bit.
     222                    if i < self.n-1:
     223
     224                        # Adding (i+1)th bit
     225                        bitset_add(current_set,i+1)
     226                        i += 1
     227                    else:
     228                        bitset_discard(current_set,i)
     229
     230                    # Returning the result if necessary ...
     231
     232                    if self.maximal and not ismaximal(self.g,self.n, tmp):
     233                        continue
     234
     235                    count += 1
     236
     237                    if not self.count_only:
     238                        yield [self.vertices[j] for j in range(i+1) if bitset_in(tmp,j)]
     239                        continue
     240
     241                else:
     242                    # Removing the ith bit
     243                    bitset_discard(current_set, i)
     244
     245                    # Preparing for the next set !
     246                    if i < self.n-1:
     247                        bitset_add(current_set, i+1)
     248                        i += 1
     249
     250            # Not already included in the set
     251            else:
     252                if i == 0:
     253                    if not self.maximal:
     254                        count+=1
     255                        yield []
     256
     257                    break
     258
     259                # Going backward, we explored all we could there !
     260                if bitset_in(current_set,i-1):
     261                    bitset_discard(current_set, i-1)
     262                    bitset_add(current_set,i)
     263                else:
     264                    i -= 1
     265                    if i == -1:
     266                        break
     267
     268
     269        if self.count_only:
     270            yield count
     271
     272        bitset_free(current_set)
     273        bitset_free(tmp)
     274
     275
     276    def __dealloc__(self):
     277        r"""
     278        Frees everything we ever allocated
     279        """
     280        binary_matrix_free(self.g)
     281
     282    @cached_method
     283    def cardinality(self):
     284        r"""
     285        Computes and returns the number of independent sets
     286
     287        TESTS::
     288
     289            sage: from sage.graphs.independent_sets import IndependentSets
     290            sage: IndependentSets(graphs.PetersenGraph()).cardinality()
     291            76
     292
     293        Only maximal ones::
     294
     295            sage: from sage.graphs.independent_sets import IndependentSets
     296            sage: IndependentSets(graphs.PetersenGraph(), maximal = True).cardinality()
     297            15
     298        """
     299        self.count_only = 1
     300
     301        for i in self:
     302            pass
     303
     304        self.count_only = 0
     305
     306        from sage.rings.integer import Integer
     307        return Integer(i)
     308
     309    def __contains__(self, S):
     310        r"""
     311        Checks whether the set is an independent set (possibly maximal)
     312
     313        - ``S`` -- a set of vertices to be tested.
     314
     315        EXAMPLE::
     316
     317        All independent sets of PetersenGraph are ... independent sets ::
     318
     319            sage: from sage.graphs.independent_sets import IndependentSets
     320            sage: IS = IndependentSets(graphs.PetersenGraph())
     321            sage: all( s in IS for s in IS)
     322            True
     323
     324        Same with maximal independent sets::
     325
     326            sage: IS = IndependentSets(graphs.PetersenGraph(), maximal = True)
     327            sage: all( s in IS for s in IS)
     328            True
     329        """
     330        # Set of vertices as a bitset
     331        cdef bitset_t s
     332
     333        bitset_init(s,self.n)
     334        bitset_set_first_n(s,0)
     335
     336        cdef int i
     337        for I in S:
     338            try:
     339                i = self.vertex_to_int[I]
     340            except KeyError:
     341                raise ValueError("An element of the set being tested does not belong to ")
     342
     343            # Adding the new vertex to s
     344            bitset_add(s, i)
     345
     346            # Checking that the set s is independent
     347            if not bitset_are_disjoint(self.g.rows[i],s.bits,self.g.width):
     348                return False
     349
     350        if self.maximal and not ismaximal(self.g, self.n,s):
     351            return False
     352
     353        return True
  • sage/misc/binary_matrix.pxi

    diff --git a/sage/misc/binary_matrix.pxi b/sage/misc/binary_matrix.pxi
    a b  
    2222    width``.
    2323"""
    2424include "binary_matrix_pxd.pxi"
     25include "sage/ext/stdsage.pxi"
    2526
    2627cdef inline binary_matrix_init(binary_matrix_t m, long n_rows, long n_cols):
    2728    r"""
     
    5657    r"""
    5758    Fill the whole matrix with a bit
    5859    """
    59     memset(m.rows[0],-(<char> bit),m.width * m.n_rows * sizeof(unsigned long))
     60    memset(m.rows[0],-(<unsigned char> bit),m.width * m.n_rows * sizeof(unsigned long))
     61
     62cdef inline binary_matrix_complement(binary_matrix_t m):
     63    r"""
     64    Complements all of the matrix' bits.
     65    """
     66    cdef int i,j
     67    for i in range(m.n_rows):
     68        for j in range(m.width):
     69            m.rows[i][j] = ~m.rows[i][j]
     70
     71        # Set the "useless" bits to 0 too.
     72        if ((m.n_cols)  & offset_mask):
     73            m.rows[i][m.width-1] &= (<unsigned long> 1<<((m.n_cols)  & offset_mask))-1
    6074
    6175cdef inline binary_matrix_set1(binary_matrix_t m, long row, long col):
    6276    r"""
     
    90104    cdef int i,j
    91105    import sys
    92106    for i in range(m.n_rows):
     107        # If you want to print the *whole* matrix, including the useless bits,
     108        # use the following line instead
     109        #
     110        # for j in (m.width*8*sizeof(unsigned long)):
    93111        for j in range(m.n_cols):
    94112            sys.stdout.write("1" if binary_matrix_get(m, i, j) else ".",)
    95113        print ""
  • sage/misc/binary_matrix_pxd.pxi

    diff --git a/sage/misc/binary_matrix_pxd.pxi b/sage/misc/binary_matrix_pxd.pxi
    a b  
    1 include "bitset_pxd.pxi"
    2 include "bitset.pxi"
    3 
    41cdef extern from *:
    52    int __builtin_popcountl(unsigned long)
     3    void *memset(void *, int, size_t)
     4    # constant literals
     5    int index_shift "(sizeof(unsigned long)==8 ? 6 : 5)"
     6    unsigned long offset_mask "(sizeof(unsigned long)==8 ? 0x3F : 0x1F)"
    67
    78cdef struct binary_matrix_s:
    89    long n_cols