Path: blob/master/src/sage/graphs/base/static_dense_graph.pyx
8815 views
r"""1Static dense graphs23This module gathers everything which is related to static dense graphs, i.e. :45- The vertices are integer from `0` to `n-1`6- No labels on vertices/edges7- No multiple edges8- No addition/removal of vertices910This being said, it is technically possible to add/remove edges. The data11structure does not mind at all.1213It is all based on the binary matrix data structure described in14``misc/binary_matrix.pxi``, which is almost a copy of the bitset data15structure. The only difference is that it differentiates the rows (the vertices)16instead of storing the whole data in a long bitset, and we can use that.1718Index19-----2021**Cython functions**2223.. csv-table::24:class: contentstable25:widths: 30, 7026:delim: |2728``dense_graph_init`` | Fills a binary matrix with the information of a (di)graph.2930**Python functions**3132.. csv-table::33:class: contentstable34:widths: 30, 7035:delim: |3637:meth:`is_strongly_regular` | Tests if a graph is strongly regular3839Functions40---------41"""42include "sage/misc/binary_matrix.pxi"4344cdef dict dense_graph_init(binary_matrix_t m, g, translation = False):45r"""46Initializes the binary matrix from a Sage (di)graph.4748INPUT:4950- ``binary_matrix_t m`` -- the binary matrix to be filled5152- ``g`` -- a graph or digraph5354- ``translation`` (boolean) -- whether to return a dictionary associating to55each vertex its corresponding integer in the binary matrix.56"""57cdef dict d_translation58from sage.graphs.graph import Graph59cdef int is_undirected = isinstance(g, Graph)60cdef int n = g.order()6162binary_matrix_init(m,n,n)63binary_matrix_fill(m,0)6465# If the vertices are 0...n-1, let's avoid an unnecessary dictionary66if g.vertices() == range(n):67if translation:68d_translation = {i:i for i in range(n)}6970for i,j in g.edge_iterator(labels = False):71binary_matrix_set1(m,i,j)72if is_undirected:73binary_matrix_set1(m,j,i)74else:75d_translation = {v:i for i,v in enumerate(g.vertices())}7677for u,v in g.edge_iterator(labels = False):78binary_matrix_set1(m,d_translation[u],d_translation[v])79if is_undirected:80binary_matrix_set1(m,d_translation[v],d_translation[u])8182if translation:83return d_translation8485def is_strongly_regular(g, parameters = False):86r"""87Tests whether ``self`` is strongly regular.8889A graph `G` is said to be strongly regular with parameters `(n, k, \lambda,90\mu)` if and only if:9192* `G` has `n` vertices.9394* `G` is `k`-regular.9596* Any two adjacent vertices of `G` have `\lambda` common neighbors.9798* Any two non-adjacent vertices of `G` have `\mu` common neighbors.99100By convention, the complete graphs, the graphs with no edges101and the empty graph are not strongly regular.102103See :wikipedia:`Strongly regular graph`104105INPUT:106107- ``parameters`` (boolean) -- whether to return the quadruple `(n,108k,\lambda,\mu)`. If ``parameters = False`` (default), this method only109returns ``True`` and ``False`` answers. If ``parameters=True``, the110``True`` answers are replaced by quadruples `(n, k,\lambda,\mu)`. See111definition above.112113EXAMPLES:114115Petersen's graph is strongly regular::116117sage: g = graphs.PetersenGraph()118sage: g.is_strongly_regular()119True120sage: g.is_strongly_regular(parameters = True)121(10, 3, 0, 1)122123And Clebsch's graph is too::124125sage: g = graphs.ClebschGraph()126sage: g.is_strongly_regular()127True128sage: g.is_strongly_regular(parameters = True)129(16, 5, 0, 2)130131But Chvatal's graph is not::132133sage: g = graphs.ChvatalGraph()134sage: g.is_strongly_regular()135False136137Complete graphs are not strongly regular. (:trac:`14297`) ::138139sage: g = graphs.CompleteGraph(5)140sage: g.is_strongly_regular()141False142143Completements of complete graphs are not strongly regular::144145sage: g = graphs.CompleteGraph(5).complement()146sage: g.is_strongly_regular()147False148149The empty graph is not strongly regular::150151sage: g = graphs.EmptyGraph()152sage: g.is_strongly_regular()153False154"""155g._scream_if_not_simple(allow_loops=True)156cdef binary_matrix_t m157cdef int n = g.order()158cdef int inter159cdef int i,j,l, k160161if g.size() == 0: # no vertices or no edges162return False163164if g.is_clique():165return False166167cdef list degree = g.degree()168k = degree[0]169if not all(d == k for d in degree):170return False171172# m i now our copy of the graph173dense_graph_init(m, g)174175cdef int llambda = -1176cdef int mu = -1177178for i in range(n):179for j in range(i+1,n):180181# The intersection of the common neighbors of i and j is a AND of182# their respective rows. A popcount then returns its cardinality.183inter = 0184for l in range(m.width):185inter += __builtin_popcountl(m.rows[i][l] & m.rows[j][l])186187# Check that this cardinality is correct according to the values of lambda and mu188if binary_matrix_get(m,i,j):189if llambda == -1:190llambda = inter191elif llambda != inter:192binary_matrix_free(m)193return False194else:195if mu == -1:196mu = inter197elif mu != inter:198binary_matrix_free(m)199return False200201binary_matrix_free(m)202203if parameters:204return (n,k,llambda,mu)205else:206return True207208209