diff --git a/src/sage/graphs/all.py b/src/sage/graphs/all.py index edb920f6897..2cbc65d0e23 100644 --- a/src/sage/graphs/all.py +++ b/src/sage/graphs/all.py @@ -4,7 +4,7 @@ lazy_import("sage.graphs.graph_generators", "graphs") lazy_import("sage.graphs.digraph_generators", "digraphs") lazy_import("sage.graphs.hypergraph_generators", "hypergraphs") -from .graph_database import GraphDatabase, GenericGraphQuery, GraphQuery +lazy_import("sage.graphs.graph_database", ["GraphDatabase", "GenericGraphQuery", "GraphQuery"]) from .graph import Graph from .digraph import DiGraph from .bipartite_graph import BipartiteGraph @@ -13,7 +13,7 @@ import sage.graphs.partial_cube from . import graph_list as graphs_list lazy_import("sage.graphs", "graph_coloring") -from .graph_database import graph_db_info +lazy_import("sage.graphs.graph_database", "graph_db_info") lazy_import("sage.graphs.graph_editor", "graph_editor") from sage.graphs.isgci import graph_classes diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index 22a6f4e5ba4..d6508f172f8 100644 --- a/src/sage/graphs/base/boost_graph.pyx +++ b/src/sage/graphs/base/boost_graph.pyx @@ -572,7 +572,7 @@ cpdef bandwidth_heuristics(g, algorithm='cuthill_mckee'): from sage.graphs.base.boost_graph import bandwidth_heuristics sage: bandwidth_heuristics(Graph()) (0, []) - sage: bandwidth_heuristics(graphs.RandomGNM(10,0)) + sage: bandwidth_heuristics(graphs.RandomGNM(10,0)) # optional - networkx (0, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) """ @@ -1964,8 +1964,8 @@ cpdef diameter_DHV(g, weight_function=None, check_weight=True): TESTS:: - sage: G = graphs.RandomBarabasiAlbert(17,6) - sage: diameter_DHV(G) == G.diameter(algorithm = 'Dijkstra_Boost') + sage: G = graphs.RandomBarabasiAlbert(17,6) # optional - networkx + sage: diameter_DHV(G) == G.diameter(algorithm = 'Dijkstra_Boost') # optional - networkx True sage: G = Graph([(0,1,-1)], weighted=True) sage: diameter_DHV(G) diff --git a/src/sage/graphs/base/c_graph.pyx b/src/sage/graphs/base/c_graph.pyx index 83a01eb4f9b..d6fb119d3cf 100644 --- a/src/sage/graphs/base/c_graph.pyx +++ b/src/sage/graphs/base/c_graph.pyx @@ -1577,11 +1577,11 @@ cdef class CGraphBackend(GenericGraphBackend): We check that the bug described in :trac:`8406` is gone:: sage: G = Graph() - sage: R. = GF(3**3) - sage: S. = R[] - sage: G.add_vertex(a**2) - sage: G.add_vertex(x) - sage: G.vertices(sort=True) + sage: R. = GF(3**3) # optional - sage.rings.finite_rings + sage: S. = R[] # optional - sage.rings.finite_rings + sage: G.add_vertex(a**2) # optional - sage.rings.finite_rings + sage: G.add_vertex(x) # optional - sage.rings.finite_rings + sage: G.vertices(sort=True) # optional - sage.rings.finite_rings [a^2, x] And that the bug described in :trac:`9610` is gone:: @@ -2107,9 +2107,9 @@ cdef class CGraphBackend(GenericGraphBackend): Ensure that :trac:`13664` is fixed :: - sage: W = WeylGroup(["A",1]) - sage: G = W.cayley_graph() - sage: Graph(G).degree() + sage: W = WeylGroup(["A",1]) # optional - sage.combinat sage.groups + sage: G = W.cayley_graph() # optional - sage.combinat sage.groups + sage: Graph(G).degree() # optional - sage.combinat sage.groups [1, 1] sage: h = Graph() sage: h.add_edge(1,2,"a") @@ -4406,9 +4406,9 @@ cdef class CGraphBackend(GenericGraphBackend): TESTS:: - sage: P = posets.PentagonPoset() - sage: H = P._hasse_diagram - sage: H._backend.is_connected() + sage: P = posets.PentagonPoset() # optional - sage.modules + sage: H = P._hasse_diagram # optional - sage.modules + sage: H._backend.is_connected() # optional - sage.modules True """ cdef int v_int @@ -4589,9 +4589,9 @@ cdef class CGraphBackend(GenericGraphBackend): TESTS:: - sage: m = Matrix(3,[0, 1, 1, 0, 0, 0, 0, 1, 0]) - sage: g = DiGraph(m) - sage: g.is_directed_acyclic(certificate=True) + sage: m = Matrix(3,[0, 1, 1, 0, 0, 0, 0, 1, 0]) # optional - sage.modules + sage: g = DiGraph(m) # optional - sage.modules + sage: g.is_directed_acyclic(certificate=True) # optional - sage.modules (True, [0, 2, 1]) """ if not self._directed: diff --git a/src/sage/graphs/base/static_sparse_backend.pyx b/src/sage/graphs/base/static_sparse_backend.pyx index c380777c0e7..a8de583d4db 100644 --- a/src/sage/graphs/base/static_sparse_backend.pyx +++ b/src/sage/graphs/base/static_sparse_backend.pyx @@ -446,17 +446,17 @@ cdef class StaticSparseBackend(CGraphBackend): :: - sage: g = DiGraph(digraphs.DeBruijn(4, 3), data_structure="static_sparse") - sage: gi = DiGraph(g, data_structure="static_sparse") - sage: gi.edges(sort=True)[0] + sage: g = DiGraph(digraphs.DeBruijn(4, 3), data_structure="static_sparse") # optional - sage.combinat + sage: gi = DiGraph(g, data_structure="static_sparse") # optional - sage.combinat + sage: gi.edges(sort=True)[0] # optional - sage.combinat ('000', '000', '0') - sage: sorted(gi.edges_incident('111')) + sage: sorted(gi.edges_incident('111')) # optional - sage.combinat [('111', '110', '0'), ('111', '111', '1'), ('111', '112', '2'), ('111', '113', '3')] - sage: set(g.edges(sort=False)) == set(gi.edges(sort=False)) + sage: set(g.edges(sort=False)) == set(gi.edges(sort=False)) # optional - sage.combinat True :: @@ -671,10 +671,10 @@ cdef class StaticSparseBackend(CGraphBackend): :: sage: from sage.graphs.base.static_sparse_backend import StaticSparseBackend - sage: g = StaticSparseBackend(digraphs.DeBruijn(3, 2)) - sage: g.has_edge('00', '01', '1') + sage: g = StaticSparseBackend(digraphs.DeBruijn(3, 2)) # optional - sage.combinat + sage: g.has_edge('00', '01', '1') # optional - sage.combinat True - sage: g.has_edge('00', '01', '0') + sage: g.has_edge('00', '01', '0') # optional - sage.combinat False """ try: diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index 9b843ca965e..aa5c411f3f0 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -47,6 +47,9 @@ from sage.rings.integer import Integer from sage.misc.decorators import rename_keyword from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import + +lazy_import('networkx', ['MultiGraph', 'Graph'], as_=['networkx_MultiGraph', 'networkx_Graph']) class BipartiteGraph(Graph): @@ -195,16 +198,16 @@ class BipartiteGraph(Graph): #. From a reduced adjacency matrix:: - sage: M = Matrix([(1,1,1,0,0,0,0), (1,0,0,1,1,0,0), + sage: M = Matrix([(1,1,1,0,0,0,0), (1,0,0,1,1,0,0), # optional - sage.modules ....: (0,1,0,1,0,1,0), (1,1,0,1,0,0,1)]) - sage: M + sage: M # optional - sage.modules [1 1 1 0 0 0 0] [1 0 0 1 1 0 0] [0 1 0 1 0 1 0] [1 1 0 1 0 0 1] - sage: H = BipartiteGraph(M); H + sage: H = BipartiteGraph(M); H # optional - sage.modules Bipartite graph on 11 vertices - sage: H.edges(sort=True) + sage: H.edges(sort=True) # optional - sage.modules [(0, 7, None), (0, 8, None), (0, 10, None), @@ -221,9 +224,9 @@ class BipartiteGraph(Graph): :: - sage: M = Matrix([(1, 1, 2, 0, 0), (0, 2, 1, 1, 1), (0, 1, 2, 1, 1)]) - sage: B = BipartiteGraph(M, multiedges=True, sparse=True) - sage: B.edges(sort=True) + sage: M = Matrix([(1, 1, 2, 0, 0), (0, 2, 1, 1, 1), (0, 1, 2, 1, 1)]) # optional - sage.modules + sage: B = BipartiteGraph(M, multiedges=True, sparse=True) # optional - sage.modules + sage: B.edges(sort=True) # optional - sage.modules [(0, 5, None), (1, 5, None), (1, 6, None), @@ -241,13 +244,13 @@ class BipartiteGraph(Graph): :: - sage: F. = GF(4) - sage: MS = MatrixSpace(F, 2, 3) - sage: M = MS.matrix([[0, 1, a + 1], [a, 1, 1]]) - sage: B = BipartiteGraph(M, weighted=True, sparse=True) - sage: B.edges(sort=True) + sage: F. = GF(4) # optional - sage.modules sage.rings.finite_rings + sage: MS = MatrixSpace(F, 2, 3) # optional - sage.modules sage.rings.finite_rings + sage: M = MS.matrix([[0, 1, a + 1], [a, 1, 1]]) # optional - sage.modules sage.rings.finite_rings + sage: B = BipartiteGraph(M, weighted=True, sparse=True) # optional - sage.modules sage.rings.finite_rings + sage: B.edges(sort=True) # optional - sage.modules sage.rings.finite_rings [(0, 4, a), (1, 3, 1), (1, 4, 1), (2, 3, a + 1), (2, 4, 1)] - sage: B.weighted() + sage: B.weighted() # optional - sage.modules sage.rings.finite_rings True #. From an alist file:: @@ -261,7 +264,7 @@ class BipartiteGraph(Graph): ....: 1 2 4 7 \n") ....: f.flush() ....: B = BipartiteGraph(f.name) - sage: B.is_isomorphic(H) + sage: B.is_isomorphic(H) # optional - sage.modules True #. From a ``graph6`` string:: @@ -325,15 +328,15 @@ class BipartiteGraph(Graph): Ensure that we can construct a ``BipartiteGraph`` with isolated vertices via the reduced adjacency matrix (:trac:`10356`):: - sage: a = BipartiteGraph(matrix(2, 2, [1, 0, 1, 0])) - sage: a + sage: a = BipartiteGraph(matrix(2, 2, [1, 0, 1, 0])) # optional - sage.modules + sage: a # optional - sage.modules Bipartite graph on 4 vertices - sage: a.vertices(sort=True) + sage: a.vertices(sort=True) # optional - sage.modules [0, 1, 2, 3] - sage: g = BipartiteGraph(matrix(4, 4, [1] * 4 + [0] * 12)) - sage: g.vertices(sort=True) + sage: g = BipartiteGraph(matrix(4, 4, [1] * 4 + [0] * 12)) # optional - sage.modules + sage: g.vertices(sort=True) # optional - sage.modules [0, 1, 2, 3, 4, 5, 6, 7] - sage: sorted(g.left.union(g.right)) + sage: sorted(g.left.union(g.right)) # optional - sage.modules [0, 1, 2, 3, 4, 5, 6, 7] Make sure that loops are not allowed (:trac:`23275`):: @@ -504,8 +507,7 @@ def __init__(self, data=None, partition=None, check=True, hash_labels=None, *arg if len(left) + len(right) != self.num_verts(): raise ValueError("not all vertices appear in partition") - import networkx - if isinstance(data, (networkx.MultiGraph, networkx.Graph)): + if isinstance(data, (networkx_MultiGraph, networkx_Graph)): if hasattr(data, "node_type"): # Assume the graph is bipartite self.left = set() @@ -1289,10 +1291,10 @@ def is_bipartite(self, certificate=False): EXAMPLES:: - sage: g = BipartiteGraph(graphs.RandomBipartite(3, 3, .5)) - sage: g.is_bipartite() + sage: g = BipartiteGraph(graphs.RandomBipartite(3, 3, .5)) # optional - numpy + sage: g.is_bipartite() # optional - numpy True - sage: g.is_bipartite(certificate=True) # random + sage: g.is_bipartite(certificate=True) # random # optional - numpy (True, {(0, 0): 0, (0, 1): 0, (0, 2): 0, (1, 0): 1, (1, 1): 1, (1, 2): 1}) TESTS:: @@ -1625,7 +1627,7 @@ def perfect_matchings(self, labels=False): sage: B = BipartiteGraph(graphs.CompleteBipartiteGraph(4, 4)) sage: len(list(B.perfect_matchings())) 24 - sage: B.matching_polynomial(algorithm='rook')(0) + sage: B.matching_polynomial(algorithm='rook')(0) # optional - sage.modules 24 TESTS:: @@ -1803,26 +1805,26 @@ def save_afile(self, fname): EXAMPLES:: - sage: M = Matrix([(1,1,1,0,0,0,0), (1,0,0,1,1,0,0), + sage: M = Matrix([(1,1,1,0,0,0,0), (1,0,0,1,1,0,0), # optional - sage.modules ....: (0,1,0,1,0,1,0), (1,1,0,1,0,0,1)]) - sage: M + sage: M # optional - sage.modules [1 1 1 0 0 0 0] [1 0 0 1 1 0 0] [0 1 0 1 0 1 0] [1 1 0 1 0 0 1] - sage: b = BipartiteGraph(M) - sage: import tempfile - sage: with tempfile.NamedTemporaryFile() as f: + sage: b = BipartiteGraph(M) # optional - sage.modules + sage: import tempfile # optional - sage.modules + sage: with tempfile.NamedTemporaryFile() as f: # optional - sage.modules ....: b.save_afile(f.name) ....: b2 = BipartiteGraph(f.name) - sage: b.is_isomorphic(b2) + sage: b.is_isomorphic(b2) # optional - sage.modules True TESTS:: sage: import tempfile sage: f = tempfile.NamedTemporaryFile() - sage: for order in range(3, 13, 3): + sage: for order in range(3, 13, 3): # optional - sage.combinat ....: num_chks = int(order / 3) ....: num_vars = order - num_chks ....: partition = (list(range(num_vars)), list(range(num_vars, num_vars+num_chks))) @@ -1920,78 +1922,78 @@ def reduced_adjacency_matrix(self, sparse=True, *, base_ring=None, **kwds): Bipartite graphs that are not weighted will return a matrix over ZZ, unless a base ring is specified:: - sage: M = Matrix([(1,1,1,0,0,0,0), (1,0,0,1,1,0,0), + sage: M = Matrix([(1,1,1,0,0,0,0), (1,0,0,1,1,0,0), # optional - sage.modules ....: (0,1,0,1,0,1,0), (1,1,0,1,0,0,1)]) - sage: B = BipartiteGraph(M) - sage: N = B.reduced_adjacency_matrix() - sage: N + sage: B = BipartiteGraph(M) # optional - sage.modules + sage: N = B.reduced_adjacency_matrix() # optional - sage.modules + sage: N # optional - sage.modules [1 1 1 0 0 0 0] [1 0 0 1 1 0 0] [0 1 0 1 0 1 0] [1 1 0 1 0 0 1] - sage: N == M + sage: N == M # optional - sage.modules True - sage: N[0,0].parent() + sage: N[0,0].parent() # optional - sage.modules Integer Ring - sage: N2 = B.reduced_adjacency_matrix(base_ring=RDF); N2 + sage: N2 = B.reduced_adjacency_matrix(base_ring=RDF); N2 # optional - sage.modules [1.0 1.0 1.0 0.0 0.0 0.0 0.0] [1.0 0.0 0.0 1.0 1.0 0.0 0.0] [0.0 1.0 0.0 1.0 0.0 1.0 0.0] [1.0 1.0 0.0 1.0 0.0 0.0 1.0] - sage: N2[0, 0].parent() + sage: N2[0, 0].parent() # optional - sage.modules Real Double Field Multi-edge graphs also return a matrix over ZZ, unless a base ring is specified:: - sage: M = Matrix([(1,1,2,0,0), (0,2,1,1,1), (0,1,2,1,1)]) - sage: B = BipartiteGraph(M, multiedges=True, sparse=True) - sage: N = B.reduced_adjacency_matrix() - sage: N == M + sage: M = Matrix([(1,1,2,0,0), (0,2,1,1,1), (0,1,2,1,1)]) # optional - sage.modules + sage: B = BipartiteGraph(M, multiedges=True, sparse=True) # optional - sage.modules + sage: N = B.reduced_adjacency_matrix() # optional - sage.modules + sage: N == M # optional - sage.modules True - sage: N[0,0].parent() + sage: N[0,0].parent() # optional - sage.modules Integer Ring - sage: N2 = B.reduced_adjacency_matrix(base_ring=RDF) - sage: N2[0, 0].parent() + sage: N2 = B.reduced_adjacency_matrix(base_ring=RDF) # optional - sage.modules + sage: N2[0, 0].parent() # optional - sage.modules Real Double Field Weighted graphs will return a matrix over the ring given by their (first) weights, unless a base ring is specified:: - sage: F. = GF(4) - sage: MS = MatrixSpace(F, 2, 3) - sage: M = MS.matrix([[0, 1, a+1], [a, 1, 1]]) - sage: B = BipartiteGraph(M, weighted=True, sparse=True) - sage: N = B.reduced_adjacency_matrix(sparse=False) - sage: N == M + sage: F. = GF(4) # optional - sage.modules sage.rings.finite_rings + sage: MS = MatrixSpace(F, 2, 3) # optional - sage.modules sage.rings.finite_rings + sage: M = MS.matrix([[0, 1, a+1], [a, 1, 1]]) # optional - sage.modules sage.rings.finite_rings + sage: B = BipartiteGraph(M, weighted=True, sparse=True) # optional - sage.modules sage.rings.finite_rings + sage: N = B.reduced_adjacency_matrix(sparse=False) # optional - sage.modules sage.rings.finite_rings + sage: N == M # optional - sage.modules sage.rings.finite_rings True - sage: N[0,0].parent() + sage: N[0,0].parent() # optional - sage.modules sage.rings.finite_rings Finite Field in a of size 2^2 - sage: N2 = B.reduced_adjacency_matrix(base_ring=F) - sage: N2[0, 0].parent() + sage: N2 = B.reduced_adjacency_matrix(base_ring=F) # optional - sage.modules sage.rings.finite_rings + sage: N2[0, 0].parent() # optional - sage.modules sage.rings.finite_rings Finite Field in a of size 2^2 TESTS:: sage: B = BipartiteGraph() - sage: B.reduced_adjacency_matrix() + sage: B.reduced_adjacency_matrix() # optional - sage.modules [] - sage: M = Matrix([[0,0], [0,0]]) - sage: BipartiteGraph(M).reduced_adjacency_matrix() == M + sage: M = Matrix([[0,0], [0,0]]) # optional - sage.modules + sage: BipartiteGraph(M).reduced_adjacency_matrix() == M # optional - sage.modules True - sage: M = Matrix([[10,2/3], [0,0]]) - sage: B = BipartiteGraph(M, weighted=True, sparse=True) - sage: M == B.reduced_adjacency_matrix() + sage: M = Matrix([[10,2/3], [0,0]]) # optional - sage.modules + sage: B = BipartiteGraph(M, weighted=True, sparse=True) # optional - sage.modules + sage: M == B.reduced_adjacency_matrix() # optional - sage.modules True An error is raised if the specified base ring is not compatible with the type of the weights of the bipartite graph:: - sage: F. = GF(4) - sage: MS = MatrixSpace(F, 2, 3) - sage: M = MS.matrix([[0, 1, a+1], [a, 1, 1]]) - sage: B = BipartiteGraph(M, weighted=True, sparse=True) - sage: B.reduced_adjacency_matrix(base_ring=RDF) + sage: F. = GF(4) # optional - sage.modules sage.rings.finite_rings + sage: MS = MatrixSpace(F, 2, 3) # optional - sage.modules sage.rings.finite_rings + sage: M = MS.matrix([[0, 1, a+1], [a, 1, 1]]) # optional - sage.modules sage.rings.finite_rings + sage: B = BipartiteGraph(M, weighted=True, sparse=True) # optional - sage.modules sage.rings.finite_rings + sage: B.reduced_adjacency_matrix(base_ring=RDF) # optional - sage.modules sage.rings.finite_rings Traceback (most recent call last): ... TypeError: float() argument must be a string or a ...number, not 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement' @@ -2097,7 +2099,7 @@ class :class:`MixedIntegerLinearProgram Maximum matching in a cycle graph:: sage: G = BipartiteGraph(graphs.CycleGraph(10)) - sage: G.matching() + sage: G.matching() # optional - networkx [(0, 1, None), (2, 3, None), (4, 5, None), (6, 7, None), (8, 9, None)] The size of a maximum matching in a complete bipartite graph using @@ -2124,7 +2126,7 @@ class :class:`MixedIntegerLinearProgram sage: B = BipartiteGraph([(u,v,2) for u,v in G.edges(sort=True, labels=0)]) sage: sorted(B.matching(use_edge_labels=True)) [(0, 3, 2), (1, 2, 2)] - sage: B.matching(use_edge_labels=True, value_only=True) + sage: B.matching(use_edge_labels=True, value_only=True) # optional - networkx 4 sage: B.matching(use_edge_labels=True, value_only=True, algorithm='Edmonds') 4 @@ -2138,9 +2140,9 @@ class :class:`MixedIntegerLinearProgram Traceback (most recent call last): ... ValueError: use_edge_labels cannot be used with "Hopcroft-Karp" or "Eppstein" - sage: B.matching(use_edge_labels=False, value_only=True, algorithm='Hopcroft-Karp') + sage: B.matching(use_edge_labels=False, value_only=True, algorithm='Hopcroft-Karp') # optional - networkx 2 - sage: B.matching(use_edge_labels=False, value_only=True, algorithm='Eppstein') + sage: B.matching(use_edge_labels=False, value_only=True, algorithm='Eppstein') # optional - networkx 2 sage: B.matching(use_edge_labels=False, value_only=True, algorithm='Edmonds') 2 @@ -2284,9 +2286,9 @@ def vertex_cover(self, algorithm="Konig", value_only=False, On the Cycle Graph:: sage: B = BipartiteGraph(graphs.CycleGraph(6)) - sage: len(B.vertex_cover()) + sage: len(B.vertex_cover()) # optional - networkx 3 - sage: B.vertex_cover(value_only=True) + sage: B.vertex_cover(value_only=True) # optional - networkx 3 The two algorithms should return the same result:: diff --git a/src/sage/graphs/bliss.pyx b/src/sage/graphs/bliss.pyx index 86af7ea988e..24e32c35a7c 100644 --- a/src/sage/graphs/bliss.pyx +++ b/src/sage/graphs/bliss.pyx @@ -479,11 +479,11 @@ cpdef canonical_form(G, partition=None, return_graph=False, use_edge_labels=True Check that it works with non hashable non sortable edge labels (relying on string representations of the labels):: - sage: g1 = Graph([(0, 1, matrix(ZZ, 2)), (0, 2, RDF.pi()), (1, 2, 'a')]) - sage: g2 = Graph([(1, 2, matrix(ZZ, 2)), (2, 0, RDF.pi()), (0, 1, 'a')]) - sage: g1can = canonical_form(g1, use_edge_labels=True) # optional - bliss - sage: g2can = canonical_form(g2, use_edge_labels=True) # optional - bliss - sage: g1can == g2can # optional - bliss + sage: g1 = Graph([(0, 1, matrix(ZZ, 2)), (0, 2, RDF.pi()), (1, 2, 'a')]) # optional - sage.modules + sage: g2 = Graph([(1, 2, matrix(ZZ, 2)), (2, 0, RDF.pi()), (0, 1, 'a')]) # optional - sage.modules + sage: g1can = canonical_form(g1, use_edge_labels=True) # optional - bliss sage.modules + sage: g2can = canonical_form(g2, use_edge_labels=True) # optional - bliss sage.modules + sage: g1can == g2can # optional - bliss sage.modules True Check that :trac:`32395` is fixed:: diff --git a/src/sage/graphs/centrality.pyx b/src/sage/graphs/centrality.pyx index 91f0fc21a52..9de214115f9 100755 --- a/src/sage/graphs/centrality.pyx +++ b/src/sage/graphs/centrality.pyx @@ -99,11 +99,11 @@ def centrality_betweenness(G, bint exact=False, bint normalize=True): Compare with NetworkX:: - sage: import networkx # optional - networkx - sage: g = graphs.RandomGNP(100, .2) # optional - networkx - sage: nw = networkx.betweenness_centrality(g.networkx_graph()) # optional - networkx - sage: sg = centrality_betweenness(g) # optional - networkx - sage: max(abs(nw[x] - sg[x]) for x in g) # abs tol 1e-10 # optional - networkx + sage: import networkx # optional - networkx + sage: g = graphs.RandomGNP(100, .2) # optional - networkx + sage: nw = networkx.betweenness_centrality(g.networkx_graph()) # optional - networkx + sage: sg = centrality_betweenness(g) # optional - networkx + sage: max(abs(nw[x] - sg[x]) for x in g) # abs tol 1e-10 # optional - networkx 0 Stupid cases:: @@ -642,13 +642,13 @@ def centrality_closeness_top_k(G, int k=1, int verbose=0): sage: n = 20 sage: m = random.randint(1, n * (n - 1) / 2) sage: k = random.randint(1, n) - sage: g = graphs.RandomGNM(n, m) - sage: topk = centrality_closeness_top_k(g, k) - sage: centr = g.centrality_closeness(algorithm='BFS') - sage: sorted_centr = sorted(centr.values(), reverse=True) - sage: len(topk) == min(k, len(sorted_centr)) + sage: g = graphs.RandomGNM(n, m) # optional - networkx + sage: topk = centrality_closeness_top_k(g, k) # optional - networkx + sage: centr = g.centrality_closeness(algorithm='BFS') # optional - networkx + sage: sorted_centr = sorted(centr.values(), reverse=True) # optional - networkx + sage: len(topk) == min(k, len(sorted_centr)) # optional - networkx True - sage: all(abs(topk[i][0] - sorted_centr[i]) < 1e-12 for i in range(len(topk))) + sage: all(abs(topk[i][0] - sorted_centr[i]) < 1e-12 for i in range(len(topk))) # optional - networkx True Directed case:: @@ -658,13 +658,13 @@ def centrality_closeness_top_k(G, int k=1, int verbose=0): sage: n = 20 sage: m = random.randint(1, n * (n - 1)) sage: k = random.randint(1, n) - sage: g = digraphs.RandomDirectedGNM(n, m) - sage: topk = centrality_closeness_top_k(g, k) - sage: centr = g.centrality_closeness(algorithm='BFS') - sage: sorted_centr = sorted(centr.values(), reverse=True) - sage: len(topk) == min(k, len(sorted_centr)) + sage: g = digraphs.RandomDirectedGNM(n, m) # optional - networkx + sage: topk = centrality_closeness_top_k(g, k) # optional - networkx + sage: centr = g.centrality_closeness(algorithm='BFS') # optional - networkx + sage: sorted_centr = sorted(centr.values(), reverse=True) # optional - networkx + sage: len(topk) == min(k, len(sorted_centr)) # optional - networkx True - sage: all(abs(topk[i][0] - sorted_centr[i]) < 1e-12 for i in range(len(topk))) + sage: all(abs(topk[i][0] - sorted_centr[i]) < 1e-12 for i in range(len(topk))) # optional - networkx True """ cdef list res diff --git a/src/sage/graphs/comparability.pyx b/src/sage/graphs/comparability.pyx index 0585473a75d..0271f43d9d8 100644 --- a/src/sage/graphs/comparability.pyx +++ b/src/sage/graphs/comparability.pyx @@ -745,15 +745,15 @@ def is_transitive(g, certificate=False): (0, 2) sage: digraphs.RandomDirectedGNP(30,.2).is_transitive() False - sage: D = digraphs.DeBruijn(5, 2) - sage: D.is_transitive() + sage: D = digraphs.DeBruijn(5, 2) # optional - sage.combinat + sage: D.is_transitive() # optional - sage.combinat False - sage: cert = D.is_transitive(certificate=True) - sage: D.has_edge(*cert) + sage: cert = D.is_transitive(certificate=True) # optional - sage.combinat + sage: D.has_edge(*cert) # optional - sage.combinat False - sage: bool(D.shortest_path(*cert)) + sage: bool(D.shortest_path(*cert)) # optional - sage.combinat True - sage: digraphs.RandomDirectedGNP(20,.2).transitive_closure().is_transitive() + sage: digraphs.RandomDirectedGNP(20,.2).transitive_closure().is_transitive() # optional - networkx True """ cdef int n = g.order() diff --git a/src/sage/graphs/connectivity.pyx b/src/sage/graphs/connectivity.pyx index 2837f63201d..0cbcb87dd8d 100644 --- a/src/sage/graphs/connectivity.pyx +++ b/src/sage/graphs/connectivity.pyx @@ -4246,8 +4246,8 @@ def is_triconnected(G): Comparing different methods on random graphs that are not always triconnected:: - sage: G = graphs.RandomBarabasiAlbert(50, 3) - sage: G.is_triconnected() == G.vertex_connectivity(k=3) + sage: G = graphs.RandomBarabasiAlbert(50, 3) # optional - networkx + sage: G.is_triconnected() == G.vertex_connectivity(k=3) # optional - networkx True .. SEEALSO:: diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index 203a6a4f299..b1d046ee25d 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -357,7 +357,7 @@ class DiGraph(GenericGraph): sage: g = DiGraph([[1..12], lambda i,j: i != j and i.divides(j)]) sage: g.vertices(sort=True) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] - sage: g.adjacency_matrix() + sage: g.adjacency_matrix() # optional - sage.modules [0 1 1 1 1 1 1 1 1 1 1 1] [0 0 0 1 0 1 0 1 0 1 0 1] [0 0 0 0 0 1 0 0 1 0 0 1] @@ -377,34 +377,36 @@ class DiGraph(GenericGraph): - an adjacency matrix:: - sage: M = Matrix([[0, 1, 1, 1, 0],[0, 0, 0, 0, 0],[0, 0, 0, 0, 1],[0, 0, 0, 0, 0],[0, 0, 0, 0, 0]]); M + sage: M = Matrix([[0, 1, 1, 1, 0], [0, 0, 0, 0, 0], # optional - sage.modules + ....: [0, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]); M [0 1 1 1 0] [0 0 0 0 0] [0 0 0 0 1] [0 0 0 0 0] [0 0 0 0 0] - sage: DiGraph(M) + sage: DiGraph(M) # optional - sage.modules Digraph on 5 vertices - sage: M = Matrix([[0,1,-1],[-1,0,-1/2],[1,1/2,0]]); M + sage: M = Matrix([[0,1,-1], [-1,0,-1/2], [1,1/2,0]]); M # optional - sage.modules [ 0 1 -1] [ -1 0 -1/2] [ 1 1/2 0] - sage: G = DiGraph(M,sparse=True,weighted=True); G + sage: G = DiGraph(M, sparse=True, weighted=True); G # optional - sage.modules Digraph on 3 vertices - sage: G.weighted() + sage: G.weighted() # optional - sage.modules True - an incidence matrix:: - sage: M = Matrix(6, [-1,0,0,0,1, 1,-1,0,0,0, 0,1,-1,0,0, 0,0,1,-1,0, 0,0,0,1,-1, 0,0,0,0,0]); M + sage: M = Matrix(6, [-1,0,0,0,1, 1,-1,0,0,0, 0,1,-1,0,0, # optional - sage.modules + ....: 0,0,1,-1,0, 0,0,0,1,-1, 0,0,0,0,0]); M [-1 0 0 0 1] [ 1 -1 0 0 0] [ 0 1 -1 0 0] [ 0 0 1 -1 0] [ 0 0 0 1 -1] [ 0 0 0 0 0] - sage: DiGraph(M) + sage: DiGraph(M) # optional - sage.modules Digraph on 6 vertices #. A ``dig6`` string: Sage automatically recognizes whether a string is in @@ -530,12 +532,12 @@ def __init__(self, data=None, pos=None, loops=None, format=None, sage: loads(dumps(D)) == D True - sage: a = matrix(2,2,[1,2,0,1]) - sage: DiGraph(a,sparse=True).adjacency_matrix() == a + sage: a = matrix(2,2,[1,2,0,1]) # optional - sage.modules + sage: DiGraph(a, sparse=True).adjacency_matrix() == a # optional - sage.modules True - sage: a = matrix(2,2,[3,2,0,1]) - sage: DiGraph(a,sparse=True).adjacency_matrix() == a + sage: a = matrix(2,2,[3,2,0,1]) # optional - sage.modules + sage: DiGraph(a, sparse=True).adjacency_matrix() == a # optional - sage.modules True The positions are copied when the DiGraph is built from another DiGraph @@ -575,11 +577,12 @@ def __init__(self, data=None, pos=None, loops=None, format=None, Problem with weighted adjacency matrix (:trac:`13919`):: - sage: B = {0:{1:2,2:5,3:4},1:{2:2,4:7},2:{3:1,4:4,5:3},3:{5:4},4:{5:1,6:5},5:{4:1,6:7,5:1}} + sage: B = {0:{1:2,2:5,3:4},1:{2:2,4:7},2:{3:1,4:4,5:3}, + ....: 3:{5:4},4:{5:1,6:5},5:{4:1,6:7,5:1}} sage: grafo3 = DiGraph(B, weighted=True) - sage: matad = grafo3.weighted_adjacency_matrix() - sage: grafo4 = DiGraph(matad, format="adjacency_matrix", weighted=True) - sage: grafo4.shortest_path(0, 6, by_weight=True) + sage: matad = grafo3.weighted_adjacency_matrix() # optional - sage.modules + sage: grafo4 = DiGraph(matad, format="adjacency_matrix", weighted=True) # optional - sage.modules + sage: grafo4.shortest_path(0, 6, by_weight=True) # optional - sage.modules [0, 1, 2, 5, 4, 6] Building a DiGraph with ``immutable=False`` returns a mutable graph:: @@ -1454,8 +1457,8 @@ def degree_polynomial(self): EXAMPLES:: - sage: G = posets.PentagonPoset().hasse_diagram() - sage: G.degree_polynomial() + sage: G = posets.PentagonPoset().hasse_diagram() # optional - sage.matrix + sage: G.degree_polynomial() # optional - sage.matrix x^2 + 3*x*y + y^2 sage: G = posets.BooleanLattice(4).hasse_diagram() @@ -2068,9 +2071,10 @@ def reverse_edges(self, edges, inplace=True, multiedges=None): [(0, 5, None), (1, 0, None), (2, 1, None), (3, 2, None), (4, 3, None), (5, 4, None)] - sage: D = digraphs.Kautz(2, 3) - sage: Dr = D.reverse_edges(D.edges(sort=True), inplace=False, multiedges=True) - sage: Dr.edges(sort=True) == D.reverse().edges(sort=True) + sage: D = digraphs.Kautz(2, 3) # optional - sage.combinat + sage: Dr = D.reverse_edges(D.edges(sort=True), inplace=False, # optional - sage.combinat + ....: multiedges=True) + sage: Dr.edges(sort=True) == D.reverse().edges(sort=True) # optional - sage.combinat True """ tempG = self if inplace else copy(self) @@ -2173,37 +2177,37 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, sage: G.eccentricity(with_labels=True) {0: 0} sage: G = DiGraph([(0,1,2), (1,2,3), (2,0,2)]) - sage: G.eccentricity(algorithm = 'BFS') + sage: G.eccentricity(algorithm='BFS') [2, 2, 2] - sage: G.eccentricity(algorithm = 'Floyd-Warshall-Cython') + sage: G.eccentricity(algorithm='Floyd-Warshall-Cython') [2, 2, 2] - sage: G.eccentricity(by_weight = True, algorithm = 'Dijkstra_NetworkX') + sage: G.eccentricity(by_weight=True, algorithm='Dijkstra_NetworkX') # optional - networkx [5, 5, 4] - sage: G.eccentricity(by_weight = True, algorithm = 'Dijkstra_Boost') + sage: G.eccentricity(by_weight=True, algorithm='Dijkstra_Boost') [5, 5, 4] - sage: G.eccentricity(by_weight = True, algorithm = 'Johnson_Boost') + sage: G.eccentricity(by_weight=True, algorithm='Johnson_Boost') [5, 5, 4] - sage: G.eccentricity(by_weight = True, algorithm = 'Floyd-Warshall-Python') + sage: G.eccentricity(by_weight=True, algorithm='Floyd-Warshall-Python') [5, 5, 4] - sage: G.eccentricity(dist_dict = G.shortest_path_all_pairs(by_weight = True)[0]) + sage: G.eccentricity(dist_dict=G.shortest_path_all_pairs(by_weight=True)[0]) [5, 5, 4] TESTS: A non-implemented algorithm:: - sage: G.eccentricity(algorithm = 'boh') + sage: G.eccentricity(algorithm='boh') Traceback (most recent call last): ... ValueError: unknown algorithm "boh" An algorithm that does not work with edge weights:: - sage: G.eccentricity(by_weight = True, algorithm = 'BFS') + sage: G.eccentricity(by_weight=True, algorithm='BFS') Traceback (most recent call last): ... ValueError: algorithm 'BFS' does not work with weights - sage: G.eccentricity(by_weight = True, algorithm = 'Floyd-Warshall-Cython') + sage: G.eccentricity(by_weight=True, algorithm='Floyd-Warshall-Cython') Traceback (most recent call last): ... ValueError: algorithm 'Floyd-Warshall-Cython' does not work with weights @@ -2211,15 +2215,15 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, An algorithm that computes the all-pair-shortest-paths when not all vertices are needed:: - sage: G.eccentricity(0, algorithm = 'Floyd-Warshall-Cython') + sage: G.eccentricity(0, algorithm='Floyd-Warshall-Cython') Traceback (most recent call last): ... ValueError: algorithm 'Floyd-Warshall-Cython' works only if all eccentricities are needed - sage: G.eccentricity(0, algorithm = 'Floyd-Warshall-Python') + sage: G.eccentricity(0, algorithm='Floyd-Warshall-Python') Traceback (most recent call last): ... ValueError: algorithm 'Floyd-Warshall-Python' works only if all eccentricities are needed - sage: G.eccentricity(0, algorithm = 'Johnson_Boost') + sage: G.eccentricity(0, algorithm='Johnson_Boost') Traceback (most recent call last): ... ValueError: algorithm 'Johnson_Boost' works only if all eccentricities are needed @@ -2442,11 +2446,11 @@ def diameter(self, by_weight=False, algorithm=None, weight_function=None, EXAMPLES:: - sage: G = digraphs.DeBruijn(5,4) - sage: G.diameter() + sage: G = digraphs.DeBruijn(5,4) # optional - sage.combinat + sage: G.diameter() # optional - sage.combinat 4 - sage: G = digraphs.GeneralizedDeBruijn(9, 3) - sage: G.diameter() + sage: G = digraphs.GeneralizedDeBruijn(9, 3) # optional - sage.combinat + sage: G.diameter() # optional - sage.combinat 2 TESTS:: @@ -3152,9 +3156,10 @@ def topological_sort(self, implementation="default"): Using the NetworkX implementation :: - sage: s = list(D.topological_sort(implementation="NetworkX")); s # random + sage: s = list(D.topological_sort(implementation="NetworkX")); s # random # optional - networkx [0, 4, 1, 3, 2, 5, 6, 9, 7, 8, 10] - sage: all(s.index(u) < s.index(v) for u, v in D.edges(sort=False, labels=False)) + sage: all(s.index(u) < s.index(v) # optional - networkx + ....: for u, v in D.edges(sort=False, labels=False)) True :: @@ -3221,8 +3226,9 @@ def topological_sort_generator(self): sage: D = DiGraph({0: [1, 2], 1: [3], 2: [3, 4]}) sage: D.plot(layout='circular').show() # optional - sage.plot - sage: list(D.topological_sort_generator()) - [[0, 1, 2, 3, 4], [0, 2, 1, 3, 4], [0, 2, 1, 4, 3], [0, 2, 4, 1, 3], [0, 1, 2, 4, 3]] + sage: list(D.topological_sort_generator()) # optional - sage.modules sage.rings.finite_rings + [[0, 1, 2, 3, 4], [0, 2, 1, 3, 4], [0, 2, 1, 4, 3], + [0, 2, 4, 1, 3], [0, 1, 2, 4, 3]] :: @@ -3586,7 +3592,7 @@ def flow_polytope(self, edges=None, ends=None, backend=None): Flow polytopes can also be built through the ``polytopes.`` object:: - sage: polytopes.flow_polytope(digraphs.Path(5)) + sage: polytopes.flow_polytope(digraphs.Path(5)) # optional - sage.geometry.polyhedron A 0-dimensional polyhedron in QQ^4 defined as the convex hull of 1 vertex EXAMPLES: @@ -3594,26 +3600,26 @@ def flow_polytope(self, edges=None, ends=None, backend=None): A commutative square:: sage: G = DiGraph({1: [2, 3], 2: [4], 3: [4]}) - sage: fl = G.flow_polytope(); fl + sage: fl = G.flow_polytope(); fl # optional - sage.geometry.polyhedron A 1-dimensional polyhedron in QQ^4 defined as the convex hull of 2 vertices - sage: fl.vertices() + sage: fl.vertices() # optional - sage.geometry.polyhedron (A vertex at (0, 1, 0, 1), A vertex at (1, 0, 1, 0)) Using a different order for the edges of the graph:: - sage: fl = G.flow_polytope(edges=G.edges(key=lambda x: x[0] - x[1])); fl + sage: fl = G.flow_polytope(edges=G.edges(key=lambda x: x[0] - x[1])); fl # optional - sage.geometry.polyhedron A 1-dimensional polyhedron in QQ^4 defined as the convex hull of 2 vertices - sage: fl.vertices() + sage: fl.vertices() # optional - sage.geometry.polyhedron (A vertex at (0, 1, 1, 0), A vertex at (1, 0, 0, 1)) A tournament on 4 vertices:: sage: H = digraphs.TransitiveTournament(4) - sage: fl = H.flow_polytope(); fl + sage: fl = H.flow_polytope(); fl # optional - sage.geometry.polyhedron A 3-dimensional polyhedron in QQ^6 defined as the convex hull of 4 vertices - sage: fl.vertices() + sage: fl.vertices() # optional - sage.geometry.polyhedron (A vertex at (0, 0, 1, 0, 0, 0), A vertex at (0, 1, 0, 0, 0, 1), A vertex at (1, 0, 0, 0, 1, 0), @@ -3621,41 +3627,40 @@ def flow_polytope(self, edges=None, ends=None, backend=None): Restricting to a subset of the edges:: - sage: fl = H.flow_polytope(edges=[(0, 1, None), (1, 2, None), - ....: (2, 3, None), (0, 3, None)]) - sage: fl + sage: fl = H.flow_polytope(edges=[(0, 1, None), (1, 2, None), # optional - sage.geometry.polyhedron + ....: (2, 3, None), (0, 3, None)]); fl A 1-dimensional polyhedron in QQ^4 defined as the convex hull of 2 vertices - sage: fl.vertices() + sage: fl.vertices() # optional - sage.geometry.polyhedron (A vertex at (0, 0, 0, 1), A vertex at (1, 1, 1, 0)) Using a different choice of sources and sinks:: - sage: fl = H.flow_polytope(ends=([1], [3])); fl + sage: fl = H.flow_polytope(ends=([1], [3])); fl # optional - sage.geometry.polyhedron A 1-dimensional polyhedron in QQ^6 defined as the convex hull of 2 vertices - sage: fl.vertices() + sage: fl.vertices() # optional - sage.geometry.polyhedron (A vertex at (0, 0, 0, 1, 0, 1), A vertex at (0, 0, 0, 0, 1, 0)) - sage: fl = H.flow_polytope(ends=([0, 1], [3])); fl + sage: fl = H.flow_polytope(ends=([0, 1], [3])); fl # optional - sage.geometry.polyhedron The empty polyhedron in QQ^6 - sage: fl = H.flow_polytope(ends=([3], [0])); fl + sage: fl = H.flow_polytope(ends=([3], [0])); fl # optional - sage.geometry.polyhedron The empty polyhedron in QQ^6 - sage: fl = H.flow_polytope(ends=([0, 1], [2, 3])); fl + sage: fl = H.flow_polytope(ends=([0, 1], [2, 3])); fl # optional - sage.geometry.polyhedron A 3-dimensional polyhedron in QQ^6 defined as the convex hull of 5 vertices - sage: fl.vertices() + sage: fl.vertices() # optional - sage.geometry.polyhedron (A vertex at (0, 0, 1, 1, 0, 0), A vertex at (0, 1, 0, 0, 1, 0), A vertex at (1, 0, 0, 2, 0, 1), A vertex at (1, 0, 0, 1, 1, 0), A vertex at (0, 1, 0, 1, 0, 1)) - sage: fl = H.flow_polytope(edges=[(0, 1, None), (1, 2, None), + sage: fl = H.flow_polytope(edges=[(0, 1, None), (1, 2, None), # optional - sage.geometry.polyhedron ....: (2, 3, None), (0, 2, None), ....: (1, 3, None)], ....: ends=([0, 1], [2, 3])); fl A 2-dimensional polyhedron in QQ^5 defined as the convex hull of 4 vertices - sage: fl.vertices() + sage: fl.vertices() # optional - sage.geometry.polyhedron (A vertex at (0, 0, 0, 1, 1), A vertex at (1, 2, 1, 0, 0), A vertex at (1, 1, 0, 0, 1), @@ -3664,27 +3669,25 @@ def flow_polytope(self, edges=None, ends=None, backend=None): A digraph with one source and two sinks:: sage: Y = DiGraph({1: [2], 2: [3, 4]}) - sage: Y.flow_polytope() + sage: Y.flow_polytope() # optional - sage.geometry.polyhedron The empty polyhedron in QQ^3 A digraph with one vertex and no edge:: sage: Z = DiGraph({1: []}) - sage: Z.flow_polytope() + sage: Z.flow_polytope() # optional - sage.geometry.polyhedron A 0-dimensional polyhedron in QQ^0 defined as the convex hull of 1 vertex A digraph with multiple edges (:trac:`28837`):: - sage: G = DiGraph([(0, 1), (0,1)], multiedges=True) - sage: G + sage: G = DiGraph([(0, 1), (0,1)], multiedges=True); G Multi-digraph on 2 vertices - sage: P = G.flow_polytope() - sage: P + sage: P = G.flow_polytope(); P # optional - sage.geometry.polyhedron A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices - sage: P.vertices() + sage: P.vertices() # optional - sage.geometry.polyhedron (A vertex at (1, 0), A vertex at (0, 1)) - sage: P.lines() + sage: P.lines() # optional - sage.geometry.polyhedron () """ from sage.geometry.polyhedron.constructor import Polyhedron diff --git a/src/sage/graphs/distances_all_pairs.pyx b/src/sage/graphs/distances_all_pairs.pyx index 87e83b4f5ce..2451de506fd 100644 --- a/src/sage/graphs/distances_all_pairs.pyx +++ b/src/sage/graphs/distances_all_pairs.pyx @@ -545,7 +545,7 @@ def is_distance_regular(G, parameters=False): sage: graphs.PathGraph(2).is_distance_regular(parameters=True) ([1, None], [None, 1]) - sage: graphs.Tutte12Cage().is_distance_regular(parameters=True) + sage: graphs.Tutte12Cage().is_distance_regular(parameters=True) # optional - networkx ([3, 2, 2, 2, 2, 2, None], [None, 1, 1, 1, 1, 1, 3]) """ @@ -843,8 +843,8 @@ cdef uint32_t * c_eccentricity_DHV(short_digraph sd) except NULL: TESTS: - sage: G = graphs.RandomBarabasiAlbert(50, 2) - sage: eccentricity(G, algorithm='bounds') == eccentricity(G, algorithm='DHV') + sage: G = graphs.RandomBarabasiAlbert(50, 2) # optional - networkx + sage: eccentricity(G, algorithm='bounds') == eccentricity(G, algorithm='DHV') # optional - networkx True """ cdef uint32_t n = sd.n @@ -1777,26 +1777,26 @@ def diameter(G, algorithm=None, source=None): Comparison of exact algorithms for graphs:: - sage: G = graphs.RandomBarabasiAlbert(100, 2) - sage: d1 = diameter(G, algorithm='standard') - sage: d2 = diameter(G, algorithm='iFUB') - sage: d3 = diameter(G, algorithm='iFUB', source=G.random_vertex()) - sage: d4 = diameter(G, algorithm='DHV') - sage: if d1 != d2 or d1 != d3 or d1 != d4: print("Something goes wrong!") + sage: G = graphs.RandomBarabasiAlbert(100, 2) # optional - networkx + sage: d1 = diameter(G, algorithm='standard') # optional - networkx + sage: d2 = diameter(G, algorithm='iFUB') # optional - networkx + sage: d3 = diameter(G, algorithm='iFUB', source=G.random_vertex()) # optional - networkx + sage: d4 = diameter(G, algorithm='DHV') # optional - networkx + sage: if d1 != d2 or d1 != d3 or d1 != d4: print("Something goes wrong!") # optional - networkx Comparison of lower bound algorithms:: - sage: lb2 = diameter(G, algorithm='2sweep') - sage: lbm = diameter(G, algorithm='multi-sweep') - sage: if not (lb2 <= lbm and lbm <= d3): print("Something goes wrong!") + sage: lb2 = diameter(G, algorithm='2sweep') # optional - networkx + sage: lbm = diameter(G, algorithm='multi-sweep') # optional - networkx + sage: if not (lb2 <= lbm and lbm <= d3): print("Something goes wrong!") # optional - networkx Comparison of exact algorithms for digraphs:: - sage: D = DiGraph(graphs.RandomBarabasiAlbert(50, 2)) - sage: d1 = diameter(D, algorithm='standard') - sage: d2 = diameter(D, algorithm='DiFUB') - sage: d3 = diameter(D, algorithm='DiFUB', source=D.random_vertex()) - sage: d1 == d2 and d1 == d3 + sage: D = DiGraph(graphs.RandomBarabasiAlbert(50, 2)) # optional - networkx + sage: d1 = diameter(D, algorithm='standard') # optional - networkx + sage: d2 = diameter(D, algorithm='DiFUB') # optional - networkx + sage: d3 = diameter(D, algorithm='DiFUB', source=D.random_vertex()) # optional - networkx + sage: d1 == d2 and d1 == d3 # optional - networkx True TESTS: @@ -2438,8 +2438,8 @@ def distances_distribution(G): The de Bruijn digraph dB(2,3):: - sage: D = digraphs.DeBruijn(2,3) - sage: D.distances_distribution() + sage: D = digraphs.DeBruijn(2,3) # optional - sage.combinat + sage: D.distances_distribution() # optional - sage.combinat {1: 1/4, 2: 11/28, 3: 5/14} """ cdef size_t n = G.order() diff --git a/src/sage/graphs/dot2tex_utils.py b/src/sage/graphs/dot2tex_utils.py index cfa4613fdf9..95850012885 100644 --- a/src/sage/graphs/dot2tex_utils.py +++ b/src/sage/graphs/dot2tex_utils.py @@ -74,7 +74,7 @@ def quoted_latex(x): EXAMPLES:: - sage: sage.graphs.dot2tex_utils.quoted_latex(matrix([[1,1],[0,1],[0,0]])) + sage: sage.graphs.dot2tex_utils.quoted_latex(matrix([[1,1],[0,1],[0,0]])) # optional - sage.modules '\\left(\\begin{array}{rr}1 & 1 \\\\0 & 1 \\\\0 & 0\\end{array}\\right)' """ return re.sub("\"|\r|(%[^\n]*)?\n", "", latex(x)) @@ -89,9 +89,9 @@ def quoted_str(x): EXAMPLES:: - sage: sage.graphs.dot2tex_utils.quoted_str(matrix([[1,1],[0,1],[0,0]])) + sage: sage.graphs.dot2tex_utils.quoted_str(matrix([[1,1],[0,1],[0,0]])) # optional - sage.modules '[1 1]\\n\\\n[0 1]\\n\\\n[0 0]' - sage: print(sage.graphs.dot2tex_utils.quoted_str(matrix([[1,1],[0,1],[0,0]]))) + sage: print(sage.graphs.dot2tex_utils.quoted_str(matrix([[1,1],[0,1],[0,0]]))) # optional - sage.modules [1 1]\n\ [0 1]\n\ [0 0] diff --git a/src/sage/graphs/edge_connectivity.pyx b/src/sage/graphs/edge_connectivity.pyx index 5263e712db5..c4cf6a4f81b 100644 --- a/src/sage/graphs/edge_connectivity.pyx +++ b/src/sage/graphs/edge_connectivity.pyx @@ -56,28 +56,31 @@ cdef class GabowEdgeConnectivity: A random `d`-regular digraph is `d`-edge-connected:: sage: from sage.graphs.edge_connectivity import GabowEdgeConnectivity - sage: D = DiGraph(graphs.RandomRegular(6, 50)) - sage: while not D.is_strongly_connected(): + sage: D = DiGraph(graphs.RandomRegular(6, 50)) # optional - networkx + sage: while not D.is_strongly_connected(): # optional - networkx ....: D = DiGraph(graphs.RandomRegular(6, 50)) - sage: GabowEdgeConnectivity(D).edge_connectivity() + sage: GabowEdgeConnectivity(D).edge_connectivity() # optional - networkx 6 A complete digraph with `n` vertices is `n-1`-edge-connected:: sage: from sage.graphs.edge_connectivity import GabowEdgeConnectivity sage: D = DiGraph(digraphs.Complete(10)) - sage: GabowEdgeConnectivity(D, use_rec = True).edge_connectivity() + sage: GabowEdgeConnectivity(D, use_rec=True).edge_connectivity() 9 Check that we get the same result when with and without the DFS-based speed-up initialization proposed in [GKLP2021]_:: - sage: G = graphs.RandomBarabasiAlbert(100, 2) - sage: D = DiGraph(G) - sage: ec1 = GabowEdgeConnectivity(D, dfs_preprocessing=False).edge_connectivity() - sage: ec2 = GabowEdgeConnectivity(D, dfs_preprocessing=True).edge_connectivity() - sage: ec3 = GabowEdgeConnectivity(D, dfs_preprocessing=True, use_rec=True).edge_connectivity() - sage: ec1 == ec2 and ec2 == ec3 + sage: G = graphs.RandomBarabasiAlbert(100, 2) # optional - networkx + sage: D = DiGraph(G) # optional - networkx + sage: ec1 = GabowEdgeConnectivity(D, # optional - networkx + ....: dfs_preprocessing=False).edge_connectivity() + sage: ec2 = GabowEdgeConnectivity(D, # optional - networkx + ....: dfs_preprocessing=True).edge_connectivity() + sage: ec3 = GabowEdgeConnectivity(D, dfs_preprocessing=True, # optional - networkx + ....: use_rec=True).edge_connectivity() + sage: ec1 == ec2 and ec2 == ec3 # optional - networkx True TESTS: diff --git a/src/sage/graphs/generators/basic.py b/src/sage/graphs/generators/basic.py index 27578e76e4b..43e0b683703 100644 --- a/src/sage/graphs/generators/basic.py +++ b/src/sage/graphs/generators/basic.py @@ -20,8 +20,6 @@ # import from Sage library from sage.graphs.graph import Graph from math import sin, cos, pi -from numpy import corrcoef -from sage.matrix.constructor import Matrix def BullGraph(): @@ -406,18 +404,20 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation): EXAMPLES: sage: from sage.graphs.generators.basic import CorrelationGraph - sage: data=[[1,2,3],[4,5,6],[7,8,9999]] - sage: CG1 = CorrelationGraph(data, 0.9, False) - sage: CG2 = CorrelationGraph(data, 0.9, True) - sage: CG3 = CorrelationGraph(data, 0.1, True) - sage: CG1.edges(sort=False) + sage: data = [[1,2,3], [4,5,6], [7,8,9999]] + sage: CG1 = CorrelationGraph(data, 0.9, False) # optional - numpy + sage: CG2 = CorrelationGraph(data, 0.9, True) # optional - numpy + sage: CG3 = CorrelationGraph(data, 0.1, True) # optional - numpy + sage: CG1.edges(sort=False) # optional - numpy [(0, 0, None), (0, 1, None), (1, 1, None), (2, 2, None)] - sage: CG2.edges(sort=False) + sage: CG2.edges(sort=False) # optional - numpy [(0, 0, None), (0, 1, None), (1, 1, None), (2, 2, None)] - sage: CG3.edges(sort=False) + sage: CG3.edges(sort=False) # optional - numpy [(0, 0, None), (0, 1, None), (0, 2, None), (1, 1, None), (1, 2, None), (2, 2, None)] """ + from numpy import corrcoef + from sage.matrix.constructor import Matrix # compute pairwise correlation coeffecients corrs = corrcoef(seqs) @@ -825,11 +825,11 @@ def Toroidal6RegularGrid2dGraph(p, q): sage: g = graphs.Toroidal6RegularGrid2dGraph(5,5) sage: g.is_regular(k=6) True - sage: g.is_vertex_transitive() + sage: g.is_vertex_transitive() # optional - sage.groups True - sage: g.line_graph().is_vertex_transitive() + sage: g.line_graph().is_vertex_transitive() # optional - sage.groups True - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - sage.groups 300 sage: g.is_hamiltonian() True diff --git a/src/sage/graphs/generators/classical_geometries.py b/src/sage/graphs/generators/classical_geometries.py index 059d46d0c7f..680402dc476 100644 --- a/src/sage/graphs/generators/classical_geometries.py +++ b/src/sage/graphs/generators/classical_geometries.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: optional - sage.modules r""" Families of graphs derived from classical geometries over finite fields @@ -39,7 +39,7 @@ def SymplecticPolarGraph(d, q, algorithm=None): - ``d,q`` -- integers; note that only even values of `d` are accepted by the function. - - ``algorithm`` -- string (default: ``None``); if set to 'gap' then the + - ``algorithm`` -- string (default: ``None``); if set to ``'gap'``, then the computation is carried via GAP library interface, computing totally singular subspaces, which is faster for `q>3`. Otherwise it is done directly. @@ -60,17 +60,18 @@ def SymplecticPolarGraph(d, q, algorithm=None): sage: G = graphs.SymplecticPolarGraph(4,3) sage: G.is_strongly_regular(parameters=True) (40, 12, 2, 4) - sage: O=graphs.OrthogonalPolarGraph(5,3) + sage: O = graphs.OrthogonalPolarGraph(5,3) sage: O.is_strongly_regular(parameters=True) (40, 12, 2, 4) sage: O.is_isomorphic(G) False - sage: graphs.SymplecticPolarGraph(6,4,algorithm="gap").is_strongly_regular(parameters=True) # not tested (long time) + sage: S = graphs.SymplecticPolarGraph(6,4,algorithm="gap") # not tested (long time) # optional - sage.libs.gap + sage: S.is_strongly_regular(parameters=True) # not tested (long time) # optional - sage.libs.gap (1365, 340, 83, 85) TESTS:: - sage: graphs.SymplecticPolarGraph(4,4,algorithm="gap").is_strongly_regular(parameters=True) + sage: graphs.SymplecticPolarGraph(4,4,algorithm="gap").is_strongly_regular(parameters=True) # optional - sage.libs.gap (85, 20, 3, 5) sage: graphs.SymplecticPolarGraph(4,4).is_strongly_regular(parameters=True) (85, 20, 3, 5) @@ -223,61 +224,61 @@ def _orthogonal_polar_graph(m, q, sign="+", point_type=[0]): Petersen graph:: sage: from sage.graphs.generators.classical_geometries import _orthogonal_polar_graph - sage: g=_orthogonal_polar_graph(3,5,point_type=[2,3]) - sage: g.is_strongly_regular(parameters=True) + sage: g = _orthogonal_polar_graph(3,5,point_type=[2,3]) # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (10, 3, 0, 1) A locally Petersen graph (a.k.a. Doro graph, a.k.a. Hall graph):: - sage: g=_orthogonal_polar_graph(4,5,'-',point_type=[2,3]) - sage: g.is_distance_regular(parameters=True) + sage: g = _orthogonal_polar_graph(4,5,'-',point_type=[2,3]) # optional - sage.libs.gap + sage: g.is_distance_regular(parameters=True) # optional - sage.libs.gap ([10, 6, 4, None], [None, 1, 2, 5]) Various big and slow to build graphs: `NO^+(7,3)`:: - sage: g=_orthogonal_polar_graph(7,3,point_type=[1]) # not tested (long time) - sage: g.is_strongly_regular(parameters=True) # not tested (long time) + sage: g = _orthogonal_polar_graph(7,3,point_type=[1]) # not tested (long time) + sage: g.is_strongly_regular(parameters=True) # not tested (long time) (378, 117, 36, 36) `NO^-(7,3)`:: - sage: g=_orthogonal_polar_graph(7,3,point_type=[-1]) # not tested (long time) - sage: g.is_strongly_regular(parameters=True) # not tested (long time) + sage: g = _orthogonal_polar_graph(7,3,point_type=[-1]) # not tested (long time) + sage: g.is_strongly_regular(parameters=True) # not tested (long time) (351, 126, 45, 45) `NO^+(6,3)`:: - sage: g=_orthogonal_polar_graph(6,3,point_type=[1]) - sage: g.is_strongly_regular(parameters=True) + sage: g = _orthogonal_polar_graph(6,3,point_type=[1]) # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (117, 36, 15, 9) `NO^-(6,3)`:: - sage: g=_orthogonal_polar_graph(6,3,'-',point_type=[1]) - sage: g.is_strongly_regular(parameters=True) + sage: g = _orthogonal_polar_graph(6,3,'-',point_type=[1]) # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (126, 45, 12, 18) `NO^{-,\perp}(5,5)`:: - sage: g=_orthogonal_polar_graph(5,5,point_type=[2,3]) # long time - sage: g.is_strongly_regular(parameters=True) # long time + sage: g = _orthogonal_polar_graph(5,5,point_type=[2,3]) # long time, optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time, optional - sage.libs.gap (300, 65, 10, 15) `NO^{+,\perp}(5,5)`:: - sage: g=_orthogonal_polar_graph(5,5,point_type=[1,-1]) # not tested (long time) - sage: g.is_strongly_regular(parameters=True) # not tested (long time) + sage: g = _orthogonal_polar_graph(5,5,point_type=[1,-1]) # not tested (long time) + sage: g.is_strongly_regular(parameters=True) # not tested (long time) (325, 60, 15, 10) TESTS:: - sage: g=_orthogonal_polar_graph(5,3,point_type=[-1]) - sage: g.is_strongly_regular(parameters=True) + sage: g = _orthogonal_polar_graph(5,3,point_type=[-1]) # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (45, 12, 3, 3) - sage: g=_orthogonal_polar_graph(5,3,point_type=[1]) - sage: g.is_strongly_regular(parameters=True) + sage: g = _orthogonal_polar_graph(5,3,point_type=[1]) # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (36, 15, 6, 6) """ @@ -341,34 +342,34 @@ def OrthogonalPolarGraph(m, q, sign="+"): EXAMPLES:: - sage: G = graphs.OrthogonalPolarGraph(6,3,"+"); G + sage: G = graphs.OrthogonalPolarGraph(6,3,"+"); G # optional - sage.libs.gap Orthogonal Polar Graph O^+(6, 3): Graph on 130 vertices - sage: G.is_strongly_regular(parameters=True) + sage: G.is_strongly_regular(parameters=True) # optional - sage.libs.gap (130, 48, 20, 16) - sage: G = graphs.OrthogonalPolarGraph(6,3,"-"); G + sage: G = graphs.OrthogonalPolarGraph(6,3,"-"); G # optional - sage.libs.gap Orthogonal Polar Graph O^-(6, 3): Graph on 112 vertices - sage: G.is_strongly_regular(parameters=True) + sage: G.is_strongly_regular(parameters=True) # optional - sage.libs.gap (112, 30, 2, 10) - sage: G = graphs.OrthogonalPolarGraph(5,3); G + sage: G = graphs.OrthogonalPolarGraph(5,3); G # optional - sage.libs.gap Orthogonal Polar Graph O(5, 3): Graph on 40 vertices - sage: G.is_strongly_regular(parameters=True) + sage: G.is_strongly_regular(parameters=True) # optional - sage.libs.gap (40, 12, 2, 4) - sage: G = graphs.OrthogonalPolarGraph(8,2,"+"); G + sage: G = graphs.OrthogonalPolarGraph(8,2,"+"); G # optional - sage.libs.gap Orthogonal Polar Graph O^+(8, 2): Graph on 135 vertices - sage: G.is_strongly_regular(parameters=True) + sage: G.is_strongly_regular(parameters=True) # optional - sage.libs.gap (135, 70, 37, 35) - sage: G = graphs.OrthogonalPolarGraph(8,2,"-"); G + sage: G = graphs.OrthogonalPolarGraph(8,2,"-"); G # optional - sage.libs.gap Orthogonal Polar Graph O^-(8, 2): Graph on 119 vertices - sage: G.is_strongly_regular(parameters=True) + sage: G.is_strongly_regular(parameters=True) # optional - sage.libs.gap (119, 54, 21, 27) TESTS:: - sage: G = graphs.OrthogonalPolarGraph(4,3,"") + sage: G = graphs.OrthogonalPolarGraph(4,3,"") # optional - sage.libs.gap Traceback (most recent call last): ... ValueError: sign must be equal to either '-' or '+' when m is even - sage: G = graphs.OrthogonalPolarGraph(5,3,"-") + sage: G = graphs.OrthogonalPolarGraph(5,3,"-") # optional - sage.libs.gap Traceback (most recent call last): ... ValueError: sign must be equal to either '' or '+' when m is odd @@ -416,71 +417,74 @@ def NonisotropicOrthogonalPolarGraph(m, q, sign="+", perp=None): `NO^-(4,2)` is isomorphic to Petersen graph:: - sage: g=graphs.NonisotropicOrthogonalPolarGraph(4,2,'-'); g + sage: g = graphs.NonisotropicOrthogonalPolarGraph(4,2,'-'); g # optional - sage.libs.gap NO^-(4, 2): Graph on 10 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (10, 3, 0, 1) `NO^-(6,2)` and `NO^+(6,2)`:: - sage: g=graphs.NonisotropicOrthogonalPolarGraph(6,2,'-') - sage: g.is_strongly_regular(parameters=True) + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,2,'-') # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (36, 15, 6, 6) - sage: g=graphs.NonisotropicOrthogonalPolarGraph(6,2,'+'); g + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,2,'+'); g # optional - sage.libs.gap NO^+(6, 2): Graph on 28 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (28, 15, 6, 10) `NO^+(8,2)`:: - sage: g=graphs.NonisotropicOrthogonalPolarGraph(8,2,'+') - sage: g.is_strongly_regular(parameters=True) + sage: g = graphs.NonisotropicOrthogonalPolarGraph(8,2,'+') # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (120, 63, 30, 36) Wilbrink's graphs for `q=5`:: - sage: graphs.NonisotropicOrthogonalPolarGraph(5,5,perp=1).is_strongly_regular(parameters=True) # long time + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,perp=1) # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time, optional - sage.libs.gap (325, 60, 15, 10) - sage: graphs.NonisotropicOrthogonalPolarGraph(5,5,'-',perp=1).is_strongly_regular(parameters=True) # long time + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'-',perp=1) # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time, optional - sage.libs.gap (300, 65, 10, 15) Wilbrink's graphs:: - sage: g=graphs.NonisotropicOrthogonalPolarGraph(5,4,'+') - sage: g.is_strongly_regular(parameters=True) + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,4,'+') # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (136, 75, 42, 40) - sage: g=graphs.NonisotropicOrthogonalPolarGraph(5,4,'-') - sage: g.is_strongly_regular(parameters=True) + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,4,'-') # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (120, 51, 18, 24) - sage: g=graphs.NonisotropicOrthogonalPolarGraph(7,4,'+'); g # not tested (long time) + sage: g = graphs.NonisotropicOrthogonalPolarGraph(7,4,'+'); g # not tested (long time) NO^+(7, 4): Graph on 2080 vertices - sage: g.is_strongly_regular(parameters=True) # not tested (long time) + sage: g.is_strongly_regular(parameters=True) # not tested (long time) (2080, 1071, 558, 544) TESTS:: - sage: g=graphs.NonisotropicOrthogonalPolarGraph(4,2); g + sage: g = graphs.NonisotropicOrthogonalPolarGraph(4,2); g # optional - sage.libs.gap NO^+(4, 2): Graph on 6 vertices - sage: graphs.NonisotropicOrthogonalPolarGraph(4,3,'-').is_strongly_regular(parameters=True) + sage: g = graphs.NonisotropicOrthogonalPolarGraph(4,3,'-') # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (15, 6, 1, 3) - sage: g=graphs.NonisotropicOrthogonalPolarGraph(3,5,'-',perp=1); g + sage: g = graphs.NonisotropicOrthogonalPolarGraph(3,5,'-',perp=1); g # optional - sage.libs.gap NO^-,perp(3, 5): Graph on 10 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (10, 3, 0, 1) - sage: g=graphs.NonisotropicOrthogonalPolarGraph(6,3,'+') # long time - sage: g.is_strongly_regular(parameters=True) # long time + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'+') # long time, optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time, optional - sage.libs.gap (117, 36, 15, 9) - sage: g=graphs.NonisotropicOrthogonalPolarGraph(6,3,'-'); g # long time + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'-'); g # long time, optional - sage.libs.gap NO^-(6, 3): Graph on 126 vertices - sage: g.is_strongly_regular(parameters=True) # long time + sage: g.is_strongly_regular(parameters=True) # long time, optional - sage.libs.gap (126, 45, 12, 18) - sage: g=graphs.NonisotropicOrthogonalPolarGraph(5,5,'-') # long time - sage: g.is_strongly_regular(parameters=True) # long time + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'-') # long time, optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time, optional - sage.libs.gap (300, 104, 28, 40) - sage: g=graphs.NonisotropicOrthogonalPolarGraph(5,5,'+') # long time - sage: g.is_strongly_regular(parameters=True) # long time + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'+') # long time, optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time, optional - sage.libs.gap (325, 144, 68, 60) - sage: g=graphs.NonisotropicOrthogonalPolarGraph(6,4,'+') + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,4,'+') # optional - sage.libs.gap Traceback (most recent call last): ... ValueError: for m even q must be 2 or 3 @@ -561,9 +565,9 @@ def _polar_graph(m, q, g, intersection_size=None): TESTS:: sage: from sage.graphs.generators.classical_geometries import _polar_graph - sage: _polar_graph(4, 4, libgap.GeneralUnitaryGroup(4, 2)) + sage: _polar_graph(4, 4, libgap.GeneralUnitaryGroup(4, 2)) # optional - sage.libs.gap Graph on 45 vertices - sage: _polar_graph(4, 4, libgap.GeneralUnitaryGroup(4, 2), intersection_size=1) + sage: _polar_graph(4, 4, libgap.GeneralUnitaryGroup(4, 2), intersection_size=1) # optional - sage.libs.gap Graph on 27 vertices """ from sage.libs.gap.libgap import libgap @@ -605,20 +609,20 @@ def UnitaryPolarGraph(m, q, algorithm="gap"): EXAMPLES:: - sage: G = graphs.UnitaryPolarGraph(4,2); G + sage: G = graphs.UnitaryPolarGraph(4,2); G # optional - sage.libs.gap Unitary Polar Graph U(4, 2); GQ(4, 2): Graph on 45 vertices - sage: G.is_strongly_regular(parameters=True) + sage: G.is_strongly_regular(parameters=True) # optional - sage.libs.gap (45, 12, 3, 3) - sage: graphs.UnitaryPolarGraph(5,2).is_strongly_regular(parameters=True) + sage: graphs.UnitaryPolarGraph(5,2).is_strongly_regular(parameters=True) # optional - sage.libs.gap (165, 36, 3, 9) - sage: graphs.UnitaryPolarGraph(6,2) # not tested (long time) + sage: graphs.UnitaryPolarGraph(6,2) # not tested (long time) # optional - sage.libs.gap Unitary Polar Graph U(6, 2): Graph on 693 vertices TESTS:: - sage: graphs.UnitaryPolarGraph(4,3, algorithm="gap").is_strongly_regular(parameters=True) + sage: graphs.UnitaryPolarGraph(4,3, algorithm="gap").is_strongly_regular(parameters=True) # optional - sage.libs.gap (280, 36, 8, 4) - sage: graphs.UnitaryPolarGraph(4,3).is_strongly_regular(parameters=True) + sage: graphs.UnitaryPolarGraph(4,3).is_strongly_regular(parameters=True) # optional - sage.libs.gap (280, 36, 8, 4) sage: graphs.UnitaryPolarGraph(4,3, algorithm="foo") Traceback (most recent call last): @@ -672,18 +676,18 @@ def NonisotropicUnitaryPolarGraph(m, q): EXAMPLES:: - sage: g=graphs.NonisotropicUnitaryPolarGraph(5,2); g + sage: g = graphs.NonisotropicUnitaryPolarGraph(5,2); g # optional - sage.libs.gap NU(5, 2): Graph on 176 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap (176, 135, 102, 108) TESTS:: - sage: graphs.NonisotropicUnitaryPolarGraph(4,2).is_strongly_regular(parameters=True) + sage: graphs.NonisotropicUnitaryPolarGraph(4,2).is_strongly_regular(parameters=True) # optional - sage.libs.gap (40, 27, 18, 18) - sage: graphs.NonisotropicUnitaryPolarGraph(4,3).is_strongly_regular(parameters=True) # long time + sage: graphs.NonisotropicUnitaryPolarGraph(4,3).is_strongly_regular(parameters=True) # long time, optional - sage.libs.gap (540, 224, 88, 96) - sage: graphs.NonisotropicUnitaryPolarGraph(6,6) + sage: graphs.NonisotropicUnitaryPolarGraph(6,6) # optional - sage.libs.gap Traceback (most recent call last): ... ValueError: q must be a prime power @@ -738,16 +742,16 @@ def UnitaryDualPolarGraph(m, q): The point graph of a generalized quadrangle (see :wikipedia:`Generalized_quadrangle`, [PT2009]_) of order (8,4):: - sage: G = graphs.UnitaryDualPolarGraph(5,2); G # long time + sage: G = graphs.UnitaryDualPolarGraph(5,2); G # long time # optional - sage.libs.gap Unitary Dual Polar Graph DU(5, 2); GQ(8, 4): Graph on 297 vertices - sage: G.is_strongly_regular(parameters=True) # long time + sage: G.is_strongly_regular(parameters=True) # long time # optional - sage.libs.gap (297, 40, 7, 5) Another way to get the generalized quadrangle of order (2,4):: - sage: G = graphs.UnitaryDualPolarGraph(4,2); G + sage: G = graphs.UnitaryDualPolarGraph(4,2); G # optional - sage.libs.gap Unitary Dual Polar Graph DU(4, 2); GQ(2, 4): Graph on 27 vertices - sage: G.is_isomorphic(graphs.OrthogonalPolarGraph(6,2,'-')) + sage: G.is_isomorphic(graphs.OrthogonalPolarGraph(6,2,'-')) # optional - sage.libs.gap True A bigger graph:: @@ -759,7 +763,7 @@ def UnitaryDualPolarGraph(m, q): TESTS:: - sage: graphs.UnitaryDualPolarGraph(6,6) + sage: graphs.UnitaryDualPolarGraph(6,6) # optional - sage.libs.gap Traceback (most recent call last): ... GAPError: Error, must be a prime or a finite field @@ -796,11 +800,11 @@ def SymplecticDualPolarGraph(m, q): TESTS:: - sage: G = graphs.SymplecticDualPolarGraph(6,2); G + sage: G = graphs.SymplecticDualPolarGraph(6,2); G # optional - sage.libs.gap Symplectic Dual Polar Graph DSp(6, 2): Graph on 135 vertices - sage: G.is_distance_regular(parameters=True) + sage: G.is_distance_regular(parameters=True) # optional - sage.libs.gap ([14, 12, 8, None], [None, 1, 3, 7]) - sage: graphs.SymplecticDualPolarGraph(6,6) + sage: graphs.SymplecticDualPolarGraph(6,6) # optional - sage.libs.gap Traceback (most recent call last): ... GAPError: Error, must be a prime or a finite field @@ -844,28 +848,28 @@ def TaylorTwographDescendantSRG(q, clique_partition=False): EXAMPLES:: - sage: g=graphs.TaylorTwographDescendantSRG(3); g + sage: g = graphs.TaylorTwographDescendantSRG(3); g # optional - sage.rings.finite_rings Taylor two-graph descendant SRG: Graph on 27 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings (27, 10, 1, 5) sage: from sage.combinat.designs.twographs import taylor_twograph - sage: T = taylor_twograph(3) # long time - sage: g.is_isomorphic(T.descendant(T.ground_set()[1])) # long time + sage: T = taylor_twograph(3) # long time, optional - sage.rings.finite_rings + sage: g.is_isomorphic(T.descendant(T.ground_set()[1])) # long time, optional - sage.rings.finite_rings True - sage: g=graphs.TaylorTwographDescendantSRG(5) # not tested (long time) - sage: g.is_strongly_regular(parameters=True) # not tested (long time) + sage: g = graphs.TaylorTwographDescendantSRG(5) # not tested (long time) + sage: g.is_strongly_regular(parameters=True) # not tested (long time) (125, 52, 15, 26) TESTS:: - sage: g,l,_=graphs.TaylorTwographDescendantSRG(3,clique_partition=True) - sage: all(g.is_clique(x) for x in l) + sage: g,l,_ = graphs.TaylorTwographDescendantSRG(3, clique_partition=True) # optional - sage.rings.finite_rings + sage: all(g.is_clique(x) for x in l) # optional - sage.rings.finite_rings True - sage: graphs.TaylorTwographDescendantSRG(4) + sage: graphs.TaylorTwographDescendantSRG(4) # optional - sage.rings.finite_rings Traceback (most recent call last): ... ValueError: q must be an odd prime power - sage: graphs.TaylorTwographDescendantSRG(6) + sage: graphs.TaylorTwographDescendantSRG(6) # optional - sage.rings.finite_rings Traceback (most recent call last): ... ValueError: q must be an odd prime power @@ -918,9 +922,9 @@ def TaylorTwographSRG(q): EXAMPLES:: - sage: t=graphs.TaylorTwographSRG(3); t + sage: t = graphs.TaylorTwographSRG(3); t # optional - sage.rings.finite_rings Taylor two-graph SRG: Graph on 28 vertices - sage: t.is_strongly_regular(parameters=True) + sage: t.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings (28, 15, 6, 10) """ G, l, v0 = TaylorTwographDescendantSRG(q, clique_partition=True) @@ -955,13 +959,13 @@ def AhrensSzekeresGeneralizedQuadrangleGraph(q, dual=False): EXAMPLES:: - sage: g=graphs.AhrensSzekeresGeneralizedQuadrangleGraph(5); g + sage: g = graphs.AhrensSzekeresGeneralizedQuadrangleGraph(5); g # optional - sage.rings.finite_rings AS(5); GQ(4, 6): Graph on 125 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings (125, 28, 3, 7) - sage: g=graphs.AhrensSzekeresGeneralizedQuadrangleGraph(5,dual=True); g + sage: g = graphs.AhrensSzekeresGeneralizedQuadrangleGraph(5, dual=True); g # optional - sage.rings.finite_rings AS(5)*; GQ(6, 4): Graph on 175 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings (175, 30, 5, 5) """ from sage.combinat.designs.incidence_structures import IncidenceStructure @@ -1025,34 +1029,35 @@ def T2starGeneralizedQuadrangleGraph(q, dual=False, hyperoval=None, field=None, using the built-in construction:: - sage: g=graphs.T2starGeneralizedQuadrangleGraph(4); g + sage: g = graphs.T2starGeneralizedQuadrangleGraph(4); g # optional - sage.rings.finite_rings T2*(O,4); GQ(3, 5): Graph on 64 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings (64, 18, 2, 6) - sage: g=graphs.T2starGeneralizedQuadrangleGraph(4,dual=True); g + sage: g = graphs.T2starGeneralizedQuadrangleGraph(4, dual=True); g # optional - sage.rings.finite_rings T2*(O,4)*; GQ(5, 3): Graph on 96 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings (96, 20, 4, 4) supplying your own hyperoval:: - sage: F=GF(4,'b') - sage: O=[vector(F,(0,0,0,1)),vector(F,(0,0,1,0))]+[vector(F, (0,1,x^2,x)) for x in F] - sage: g=graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F); g + sage: F = GF(4,'b') # optional - sage.rings.finite_rings + sage: O = [vector(F,(0,0,0,1)),vector(F,(0,0,1,0))] + [vector(F, (0,1,x^2,x)) # optional - sage.rings.finite_rings + ....: for x in F] + sage: g = graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F); g # optional - sage.rings.finite_rings T2*(O,4); GQ(3, 5): Graph on 64 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings (64, 18, 2, 6) TESTS:: - sage: F=GF(4,'b') # repeating a point... - sage: O=[vector(F,(0,1,0,0)),vector(F,(0,0,1,0))]+[vector(F, (0,1,x^2,x)) for x in F] - sage: graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F) + sage: F = GF(4,'b') # repeating a point... + sage: O = [vector(F,(0,1,0,0)),vector(F,(0,0,1,0))]+[vector(F, (0,1,x^2,x)) for x in F] # optional - sage.rings.finite_rings + sage: graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F) # optional - sage.rings.finite_rings Traceback (most recent call last): ... RuntimeError: incorrect hyperoval size - sage: O=[vector(F,(0,1,1,0)),vector(F,(0,0,1,0))]+[vector(F, (0,1,x^2,x)) for x in F] - sage: graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F) + sage: O = [vector(F,(0,1,1,0)),vector(F,(0,0,1,0))]+[vector(F, (0,1,x^2,x)) for x in F] # optional - sage.rings.finite_rings + sage: graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F) # optional - sage.rings.finite_rings Traceback (most recent call last): ... RuntimeError: incorrect hyperoval @@ -1144,35 +1149,35 @@ def HaemersGraph(q, hyperoval=None, hyperoval_matching=None, field=None, check_h using the built-in constructions:: - sage: g=graphs.HaemersGraph(4); g + sage: g = graphs.HaemersGraph(4); g # optional - sage.rings.finite_rings Haemers(4): Graph on 96 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings (96, 19, 2, 4) supplying your own hyperoval_matching:: - sage: g=graphs.HaemersGraph(4,hyperoval_matching=((0,5),(1,4),(2,3))); g + sage: g = graphs.HaemersGraph(4, hyperoval_matching=((0,5),(1,4),(2,3))); g # optional - sage.rings.finite_rings Haemers(4): Graph on 96 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings (96, 19, 2, 4) TESTS:: - sage: F=GF(4,'b') # repeating a point... - sage: O=[vector(F,(0,1,0,0)),vector(F,(0,0,1,0))]+[vector(F, (0,1,x^2,x)) for x in F] - sage: graphs.HaemersGraph(4, hyperoval=O, field=F) + sage: F=GF(4,'b') # repeating a point... # optional - sage.rings.finite_rings + sage: O=[vector(F,(0,1,0,0)),vector(F,(0,0,1,0))]+[vector(F, (0,1,x^2,x)) for x in F] # optional - sage.rings.finite_rings + sage: graphs.HaemersGraph(4, hyperoval=O, field=F) # optional - sage.rings.finite_rings Traceback (most recent call last): ... RuntimeError: incorrect hyperoval size - sage: O=[vector(F,(0,1,1,0)),vector(F,(0,0,1,0))]+[vector(F, (0,1,x^2,x)) for x in F] - sage: graphs.HaemersGraph(4, hyperoval=O, field=F) + sage: O=[vector(F,(0,1,1,0)),vector(F,(0,0,1,0))]+[vector(F, (0,1,x^2,x)) for x in F] # optional - sage.rings.finite_rings + sage: graphs.HaemersGraph(4, hyperoval=O, field=F) # optional - sage.rings.finite_rings Traceback (most recent call last): ... RuntimeError: incorrect hyperoval - sage: g=graphs.HaemersGraph(8); g # not tested (long time) + sage: g = graphs.HaemersGraph(8); g # not tested (long time) # optional - sage.rings.finite_rings Haemers(8): Graph on 640 vertices - sage: g.is_strongly_regular(parameters=True) # not tested (long time) + sage: g.is_strongly_regular(parameters=True) # not tested (long time) # optional - sage.rings.finite_rings (640, 71, 6, 8) """ @@ -1259,20 +1264,20 @@ def CossidentePenttilaGraph(q): For `q=3` one gets Sims-Gewirtz graph. :: - sage: G=graphs.CossidentePenttilaGraph(3) # optional - gap_packages (grape) - sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape) + sage: g = graphs.CossidentePenttilaGraph(3) # optional - gap_packages (grape) + sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape) (56, 10, 0, 2) For `q>3` one gets new graphs. :: - sage: G=graphs.CossidentePenttilaGraph(5) # optional - gap_packages (grape) - sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape) + sage: g = graphs.CossidentePenttilaGraph(5) # optional - gap_packages (grape) + sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape) (378, 52, 1, 8) TESTS:: - sage: G=graphs.CossidentePenttilaGraph(7) # optional - gap_packages (grape) # long time - sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape) # long time + sage: g = graphs.CossidentePenttilaGraph(7) # optional - gap_packages (grape) # long time + sage: G.is_strongly_regular(parameters=True) # optional - gap_packages (grape) # long time (1376, 150, 2, 18) sage: graphs.CossidentePenttilaGraph(2) Traceback (most recent call last): @@ -1367,32 +1372,33 @@ def Nowhere0WordsTwoWeightCodeGraph(q, hyperoval=None, field=None, check_hyperov using the built-in construction:: - sage: g=graphs.Nowhere0WordsTwoWeightCodeGraph(8); g + sage: g = graphs.Nowhere0WordsTwoWeightCodeGraph(8); g # optional - sage.rings.finite_rings Nowhere0WordsTwoWeightCodeGraph(8): Graph on 196 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings (196, 60, 14, 20) - sage: g=graphs.Nowhere0WordsTwoWeightCodeGraph(16) # not tested (long time) - sage: g.is_strongly_regular(parameters=True) # not tested (long time) + sage: g = graphs.Nowhere0WordsTwoWeightCodeGraph(16) # not tested (long time) + sage: g.is_strongly_regular(parameters=True) # not tested (long time) (1800, 728, 268, 312) supplying your own hyperoval:: - sage: F=GF(8) - sage: O=[vector(F,(0,0,1)),vector(F,(0,1,0))]+[vector(F, (1,x^2,x)) for x in F] - sage: g=graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F); g + sage: F = GF(8) + sage: O = [vector(F,(0,0,1)),vector(F,(0,1,0))] + [vector(F, (1,x^2,x)) # optional - sage.rings.finite_rings + ....: for x in F] + sage: g = graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F); g # optional - sage.rings.finite_rings Nowhere0WordsTwoWeightCodeGraph(8): Graph on 196 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings (196, 60, 14, 20) TESTS:: - sage: F=GF(8) # repeating a point... - sage: O=[vector(F,(1,0,0)),vector(F,(0,1,0))]+[vector(F, (1,x^2,x)) for x in F] - sage: graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F) + sage: F = GF(8) # repeating a point... # optional - sage.rings.finite_rings + sage: O = [vector(F,(1,0,0)),vector(F,(0,1,0))]+[vector(F, (1,x^2,x)) for x in F] # optional - sage.rings.finite_rings + sage: graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F) # optional - sage.rings.finite_rings Traceback (most recent call last): ... RuntimeError: incorrect hyperoval size - sage: O=[vector(F,(1,1,0)),vector(F,(0,1,0))]+[vector(F, (1,x^2,x)) for x in F] + sage: O = [vector(F,(1,1,0)),vector(F,(0,1,0))]+[vector(F, (1,x^2,x)) for x in F] # optional - sage.rings.finite_rings sage: graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F) Traceback (most recent call last): ... @@ -1461,13 +1467,13 @@ def OrthogonalDualPolarGraph(e, d, q): EXAMPLES:: - sage: G = graphs.OrthogonalDualPolarGraph(1,3,2) - sage: G.is_distance_regular(True) + sage: G = graphs.OrthogonalDualPolarGraph(1,3,2) # optional - sage.libs.gap + sage: G.is_distance_regular(True) # optional - sage.libs.gap ([7, 6, 4, None], [None, 1, 3, 7]) - sage: G = graphs.OrthogonalDualPolarGraph(0,3,3) # long time - sage: G.is_distance_regular(True) # long time + sage: G = graphs.OrthogonalDualPolarGraph(0,3,3) # long time # optional - sage.libs.gap + sage: G.is_distance_regular(True) # long time # optional - sage.libs.gap ([39, 36, 27, None], [None, 1, 4, 13]) - sage: G.order() # long time + sage: G.order() # long time # optional - sage.libs.gap 1120 REFERENCES: @@ -1476,17 +1482,17 @@ def OrthogonalDualPolarGraph(e, d, q): TESTS:: - sage: G = graphs.OrthogonalDualPolarGraph(0,3,2) - sage: G.is_distance_regular(True) + sage: G = graphs.OrthogonalDualPolarGraph(0,3,2) # optional - sage.libs.gap + sage: G.is_distance_regular(True) # optional - sage.libs.gap ([14, 12, 8, None], [None, 1, 3, 7]) - sage: G = graphs.OrthogonalDualPolarGraph(-1,3,2) # long time - sage: G.is_distance_regular(True) # long time + sage: G = graphs.OrthogonalDualPolarGraph(-1,3,2) # long time # optional - sage.libs.gap + sage: G.is_distance_regular(True) # long time # optional - sage.libs.gap ([28, 24, 16, None], [None, 1, 3, 7]) - sage: G = graphs.OrthogonalDualPolarGraph(1,3,4) - sage: G.is_distance_regular(True) + sage: G = graphs.OrthogonalDualPolarGraph(1,3,4) # optional - sage.libs.gap + sage: G.is_distance_regular(True) # optional - sage.libs.gap ([21, 20, 16, None], [None, 1, 5, 21]) - sage: G = graphs.OrthogonalDualPolarGraph(1,4,2) - sage: G.is_distance_regular(True) + sage: G = graphs.OrthogonalDualPolarGraph(1,4,2) # optional - sage.libs.gap + sage: G.is_distance_regular(True) # optional - sage.libs.gap ([15, 14, 12, 8, None], [None, 1, 3, 7, 15]) """ from sage.libs.gap.libgap import libgap diff --git a/src/sage/graphs/generators/degree_sequence.py b/src/sage/graphs/generators/degree_sequence.py index 606f96fb3fd..071878d124e 100644 --- a/src/sage/graphs/generators/degree_sequence.py +++ b/src/sage/graphs/generators/degree_sequence.py @@ -41,25 +41,25 @@ def DegreeSequence(deg_sequence): EXAMPLES:: - sage: G = graphs.DegreeSequence([3,3,3,3]) - sage: G.edges(sort=True, labels=False) + sage: G = graphs.DegreeSequence([3,3,3,3]) # optional - networkx + sage: G.edges(sort=True, labels=False) # optional - networkx [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] - sage: G.show() # long time + sage: G.show() # long time # optional - networkx sage.plot :: - sage: G = graphs.DegreeSequence([3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]) - sage: G.show() # long time + sage: G = graphs.DegreeSequence([3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]) # optional - networkx + sage: G.show() # long time # optional - networkx sage.plot :: - sage: G = graphs.DegreeSequence([4,4,4,4,4,4,4,4]) - sage: G.show() # long time + sage: G = graphs.DegreeSequence([4,4,4,4,4,4,4,4]) # optional - networkx + sage: G.show() # long time # optional - networkx sage.plot :: - sage: G = graphs.DegreeSequence([1,2,3,4,3,4,3,2,3,2,1]) - sage: G.show() # long time + sage: G = graphs.DegreeSequence([1,2,3,4,3,4,3,2,3,2,1]) # optional - networkx + sage: G.show() # long time # optional - networkx sage.plot """ import networkx return Graph(networkx.havel_hakimi_graph([int(i) for i in deg_sequence])) @@ -93,15 +93,15 @@ def DegreeSequenceBipartite(s1, s2): If we are given as sequences ``[2,2,2,2,2]`` and ``[5,5]`` we are given as expected the complete bipartite graph `K_{2,5}`:: - sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]) - sage: g.is_isomorphic(graphs.CompleteBipartiteGraph(5,2)) + sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]) # optional - sage.modules + sage: g.is_isomorphic(graphs.CompleteBipartiteGraph(5,2)) # optional - sage.modules True Some sequences being incompatible if, for example, their sums are different, the functions raises a ``ValueError`` when no graph corresponding to the degree sequences exists:: - sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,1],[5,5]) + sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,1],[5,5]) # optional - sage.modules Traceback (most recent call last): ... ValueError: there exists no bipartite graph corresponding to the given degree sequences @@ -110,7 +110,7 @@ def DegreeSequenceBipartite(s1, s2): :trac:`12155`:: - sage: graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]).complement() + sage: graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]).complement() # optional - sage.modules Graph on 7 vertices """ from sage.combinat.integer_vector import gale_ryser_theorem @@ -147,20 +147,20 @@ def DegreeSequenceConfigurationModel(deg_sequence, seed=None): EXAMPLES:: - sage: G = graphs.DegreeSequenceConfigurationModel([1,1]) - sage: G.adjacency_matrix() + sage: G = graphs.DegreeSequenceConfigurationModel([1,1]) # optional - networkx + sage: G.adjacency_matrix() # optional - networkx sage.modules [0 1] [1 0] The output is allowed to contain both loops and multiple edges:: - sage: deg_sequence = [3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3] - sage: G = graphs.DegreeSequenceConfigurationModel(deg_sequence) - sage: G.order(), G.size() + sage: deg_sequence = [3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3] # optional - networkx + sage: G = graphs.DegreeSequenceConfigurationModel(deg_sequence) # optional - networkx + sage: G.order(), G.size() # optional - networkx (20, 30) - sage: G.has_loops() or G.has_multiple_edges() # random + sage: G.has_loops() or G.has_multiple_edges() # random # optional - networkx True - sage: G.show() # long time + sage: G.show() # long time # optional - networkx sage.plot REFERENCE: @@ -191,10 +191,9 @@ def DegreeSequenceTree(deg_sequence): EXAMPLES:: - sage: G = graphs.DegreeSequenceTree([3,1,3,3,1,1,1,2,1]) - sage: G + sage: G = graphs.DegreeSequenceTree([3,1,3,3,1,1,1,2,1]); G # optional - networkx Graph on 9 vertices - sage: G.show() # long time + sage: G.show() # long time # optional - networkx sage.plot """ import networkx return Graph(networkx.degree_sequence_tree([int(i) for i in deg_sequence])) @@ -220,10 +219,9 @@ def DegreeSequenceExpected(deg_sequence, seed=None): EXAMPLES:: - sage: G = graphs.DegreeSequenceExpected([1,2,3,2,3]) - sage: G + sage: G = graphs.DegreeSequenceExpected([1,2,3,2,3]); G # optional - networkx Looped graph on 5 vertices - sage: G.show() # long time + sage: G.show() # long time # optional - networkx sage.plot REFERENCE: diff --git a/src/sage/graphs/generators/distance_regular.pyx b/src/sage/graphs/generators/distance_regular.pyx index 0df5f3e66b5..dd809a835af 100644 --- a/src/sage/graphs/generators/distance_regular.pyx +++ b/src/sage/graphs/generators/distance_regular.pyx @@ -35,15 +35,12 @@ AUTHORS: # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.coding import codes_catalog as codes -from sage.graphs.graph import Graph -from sage.libs.gap.libgap import libgap -from sage.modules.free_module import VectorSpace -from sage.modules.free_module_element import vector -from sage.rings.finite_rings.finite_field_constructor import GF -from sage.matrix.constructor import Matrix import itertools + from cysignals.signals cimport sig_check + +from sage.graphs.graph import Graph +from sage.misc.lazy_import import LazyImport from sage.graphs.generators.smallgraphs import (FosterGraph, BiggsSmithGraph, CoxeterGraph, LivingstoneGraph, WellsGraph, GossetGraph, @@ -53,6 +50,13 @@ from sage.graphs.generators.smallgraphs import (FosterGraph, BiggsSmithGraph, from sage.graphs.generators.platonic_solids import DodecahedralGraph from sage.graphs.strongly_regular_db import strongly_regular_graph +codes = LazyImport('sage.coding', 'codes_catalog', as_name='codes') +libgap = LazyImport('sage.libs.gap.libgap', 'libgap') +Matrix = LazyImport('sage.matrix.constructor', 'Matrix') +VectorSpace = LazyImport('sage.modules.free_module', 'VectorSpace') +vector = LazyImport('sage.modules.free_module_element', 'vector') +GF = LazyImport('sage.rings.finite_rings.finite_field_constructor', 'GF') + def cocliques_HoffmannSingleton(): r""" diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index f6c7b89bca7..30396e1ab9e 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -452,7 +452,7 @@ def HammingGraph(n, q, X=None): True sage: g.is_regular() True - sage: g.is_vertex_transitive() + sage: g.is_vertex_transitive() # optional - sage.groups True A Hamming graph with parameters (1,q) is isomorphic to the @@ -526,9 +526,9 @@ def BalancedTree(r, h): A balanced tree whose root node has degree `r = 2`, and of height `h = 1`, has order 3 and size 2:: - sage: G = graphs.BalancedTree(2, 1); G + sage: G = graphs.BalancedTree(2, 1); G # optional - networkx Balanced tree: Graph on 3 vertices - sage: G.order(); G.size() + sage: G.order(); G.size() # optional - networkx 3 2 sage: r = 2; h = 1 @@ -539,21 +539,21 @@ def BalancedTree(r, h): Plot a balanced tree of height 5, whose root node has degree `r = 3`:: - sage: G = graphs.BalancedTree(3, 5) - sage: G.show() # long time + sage: G = graphs.BalancedTree(3, 5) # optional - networkx + sage: G.show() # long time # optional - networkx sage.plot A tree is bipartite. If its vertex set is finite, then it is planar. :: sage: r = randint(2, 5); h = randint(1, 7) - sage: T = graphs.BalancedTree(r, h) - sage: T.is_bipartite() + sage: T = graphs.BalancedTree(r, h) # optional - networkx + sage: T.is_bipartite() # optional - networkx True - sage: T.is_planar() + sage: T.is_planar() # optional - networkx True - sage: v = (r^(h + 1) - 1) / (r - 1) - sage: T.order() == v + sage: v = (r^(h + 1) - 1) / (r - 1) # optional - networkx + sage: T.order() == v # optional - networkx True - sage: T.size() == v - 1 + sage: T.size() == v - 1 # optional - networkx True TESTS: @@ -562,13 +562,13 @@ def BalancedTree(r, h): has degree `r \geq 2`, but the construction degenerates gracefully:: - sage: graphs.BalancedTree(1, 10) + sage: graphs.BalancedTree(1, 10) # optional - networkx Balanced tree: Graph on 11 vertices Similarly, we usually want the tree must have height `h \geq 1` but the algorithm also degenerates gracefully here:: - sage: graphs.BalancedTree(3, 0) + sage: graphs.BalancedTree(3, 0) # optional - networkx Balanced tree: Graph on 1 vertex """ import networkx @@ -627,11 +627,11 @@ def BarbellGraph(n1, n2): True sage: K_n1 = graphs.CompleteGraph(n1) sage: P_n2 = graphs.PathGraph(n2) - sage: s_K = g.subgraph_search(K_n1, induced=True) - sage: s_P = g.subgraph_search(P_n2, induced=True) - sage: K_n1.is_isomorphic(s_K) + sage: s_K = g.subgraph_search(K_n1, induced=True) # optional - sage.modules + sage: s_P = g.subgraph_search(P_n2, induced=True) # optional - sage.modules + sage: K_n1.is_isomorphic(s_K) # optional - sage.modules True - sage: P_n2.is_isomorphic(s_P) + sage: P_n2.is_isomorphic(s_P) # optional - sage.modules True TESTS:: @@ -1025,13 +1025,13 @@ def chang_graphs(): Construct the Chang graphs by Seidel switching:: - sage: c3c5=graphs.CycleGraph(3).disjoint_union(graphs.CycleGraph(5)) - sage: c8=graphs.CycleGraph(8) - sage: s=[K8.subgraph_search(c8).edges(sort=False), - ....: [(0,1,None),(2,3,None),(4,5,None),(6,7,None)], - ....: K8.subgraph_search(c3c5).edges(sort=False)] - sage: list(map(lambda x,G: T8.seidel_switching(x, inplace=False).is_isomorphic(G), - ....: s, chang_graphs)) + sage: c3c5 = graphs.CycleGraph(3).disjoint_union(graphs.CycleGraph(5)) + sage: c8 = graphs.CycleGraph(8) + sage: s = [K8.subgraph_search(c8).edges(sort=False), # optional - sage.modules + ....: [(0,1,None),(2,3,None),(4,5,None),(6,7,None)], + ....: K8.subgraph_search(c3c5).edges(sort=False)] + sage: [T8.seidel_switching(x, inplace=False).is_isomorphic(G) # optional - sage.modules + ....: for x, G in zip(s, chang_graphs)] [True, True, True] """ @@ -1353,8 +1353,8 @@ def DorogovtsevGoltsevMendesGraph(n): EXAMPLES:: - sage: G = graphs.DorogovtsevGoltsevMendesGraph(8) - sage: G.size() + sage: G = graphs.DorogovtsevGoltsevMendesGraph(8) # optional - networkx + sage: G.size() # optional - networkx 6561 REFERENCE: @@ -1538,7 +1538,7 @@ def FuzzyBallGraph(partition, q): EXAMPLES:: sage: F = graphs.FuzzyBallGraph([3,1],2) - sage: F.adjacency_matrix(vertices=list(F)) + sage: F.adjacency_matrix(vertices=list(F)) # optional - sage.modules [0 0 1 1 1 0 0 0] [0 0 0 0 0 1 0 0] [1 0 0 1 1 1 1 1] @@ -1553,10 +1553,14 @@ def FuzzyBallGraph(partition, q): `k` parts should be cospectral with respect to the normalized Laplacian:: - sage: m=4; q=2; k=2 - sage: g_list=[graphs.FuzzyBallGraph(p,q) for p in Partitions(m, length=k)] - sage: set([g.laplacian_matrix(normalized=True, vertices=list(g)).charpoly() for g in g_list]) # long time (7s on sage.math, 2011) - {x^8 - 8*x^7 + 4079/150*x^6 - 68689/1350*x^5 + 610783/10800*x^4 - 120877/3240*x^3 + 1351/100*x^2 - 931/450*x} + sage: m = 4; q = 2; k = 2 + sage: g_list = [graphs.FuzzyBallGraph(p,q) # optional - sage.combinat sage.modules + ....: for p in Partitions(m, length=k)] + sage: set(g.laplacian_matrix(normalized=True, # long time (7s on sage.math, 2011), optional - sage.combinat sage.modules + ....: vertices=list(g)).charpoly() + ....: for g in g_list) + {x^8 - 8*x^7 + 4079/150*x^6 - 68689/1350*x^5 + 610783/10800*x^4 + - 120877/3240*x^3 + 1351/100*x^2 - 931/450*x} """ from sage.graphs.generators.basic import CompleteGraph if len(partition) < 1: @@ -2203,30 +2207,31 @@ def LCFGraph(n, shift_list, repeats): EXAMPLES:: - sage: G = graphs.LCFGraph(4, [2,-2], 2) - sage: G.is_isomorphic(graphs.TetrahedralGraph()) + sage: G = graphs.LCFGraph(4, [2,-2], 2) # optional - networkx + sage: G.is_isomorphic(graphs.TetrahedralGraph()) # optional - networkx True :: - sage: G = graphs.LCFGraph(20, [10,7,4,-4,-7,10,-4,7,-7,4], 2) - sage: G.is_isomorphic(graphs.DodecahedralGraph()) + sage: G = graphs.LCFGraph(20, [10,7,4,-4,-7,10,-4,7,-7,4], 2) # optional - networkx + sage: G.is_isomorphic(graphs.DodecahedralGraph()) # optional - networkx True :: - sage: G = graphs.LCFGraph(14, [5,-5], 7) - sage: G.is_isomorphic(graphs.HeawoodGraph()) + sage: G = graphs.LCFGraph(14, [5,-5], 7) # optional - networkx + sage: G.is_isomorphic(graphs.HeawoodGraph()) # optional - networkx True The largest cubic nonplanar graph of diameter three:: - sage: G = graphs.LCFGraph(20, [-10,-7,-5,4,7,-10,-7,-4,5,7,-10,-7,6,-5,7,-10,-7,5,-6,7], 1) - sage: G.degree() + sage: G = graphs.LCFGraph(20, [-10,-7,-5,4,7,-10,-7,-4,5,7, # optional - networkx + ....: -10,-7,6,-5,7,-10,-7,5,-6,7], 1) + sage: G.degree() # optional - networkx [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3] - sage: G.diameter() + sage: G.diameter() # optional - networkx 3 - sage: G.show() # long time + sage: G.show() # long time # optional - networkx sage.plot PLOTTING: LCF Graphs are plotted as an n-cycle with edges in the middle, as described above. @@ -2583,9 +2588,9 @@ def PasechnikGraph(n): EXAMPLES:: - sage: graphs.PasechnikGraph(4).is_strongly_regular(parameters=True) + sage: graphs.PasechnikGraph(4).is_strongly_regular(parameters=True) # optional - sage.combinat sage.modules (225, 98, 43, 42) - sage: graphs.PasechnikGraph(5).is_strongly_regular(parameters=True) # long time + sage: graphs.PasechnikGraph(5).is_strongly_regular(parameters=True) # long time, optional - sage.combinat sage.modules (361, 162, 73, 72) sage: graphs.PasechnikGraph(9).is_strongly_regular(parameters=True) # not tested (1225, 578, 273, 272) diff --git a/src/sage/graphs/generators/random.py b/src/sage/graphs/generators/random.py index a947f4488c9..288515ac397 100644 --- a/src/sage/graphs/generators/random.py +++ b/src/sage/graphs/generators/random.py @@ -97,7 +97,7 @@ def RandomGNP(n, p, seed=None, fast=True, algorithm='Sage'): sage: set_random_seed(0) sage: graphs.RandomGNP(50,.2, algorithm="Sage").size() 243 - sage: graphs.RandomGNP(50,.2, algorithm="networkx").size() + sage: graphs.RandomGNP(50,.2, algorithm="networkx").size() # optional - networkx 279 # 32-bit 209 # 64-bit """ @@ -149,35 +149,35 @@ def RandomBarabasiAlbert(n, m, seed=None): We show the edge list of a random graph on 6 nodes with `m = 2`:: - sage: G = graphs.RandomBarabasiAlbert(6,2) - sage: G.order(), G.size() + sage: G = graphs.RandomBarabasiAlbert(6,2) # optional - networkx + sage: G.order(), G.size() # optional - networkx (6, 8) - sage: G.degree_sequence() # random + sage: G.degree_sequence() # random # optional - networkx [4, 3, 3, 2, 2, 2] We plot a random graph on 12 nodes with `m = 3`:: - sage: ba = graphs.RandomBarabasiAlbert(12,3) - sage: ba.show() # long time + sage: ba = graphs.RandomBarabasiAlbert(12,3) # optional - networkx + sage: ba.show() # long time # optional - networkx sage.plot We view many random graphs using a graphics array:: sage: g = [] sage: j = [] - sage: for i in range(1,10): + sage: for i in range(1,10): # optional - networkx ....: k = graphs.RandomBarabasiAlbert(i+3, 3) ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # optional - networkx sage.plot ....: n = [] ....: for m in range(3): ....: n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False)) ....: j.append(n) - sage: G = graphics_array(j) # optional - sage.plot - sage: G.show() # long time # optional - sage.plot + sage: G = graphics_array(j) # optional - networkx sage.plot + sage: G.show() # long time # optional - networkx sage.plot When `m = 1`, the generated graph is a tree:: - sage: graphs.RandomBarabasiAlbert(6, 1).is_tree() + sage: graphs.RandomBarabasiAlbert(6, 1).is_tree() # optional - networkx True """ if seed is None: @@ -206,35 +206,35 @@ def RandomBipartite(n1, n2, p, set_position=False, seed=None): EXAMPLES:: - sage: g = graphs.RandomBipartite(5, 2, 0.5) - sage: g.vertices(sort=True) + sage: g = graphs.RandomBipartite(5, 2, 0.5) # optional - numpy + sage: g.vertices(sort=True) # optional - numpy [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1)] TESTS:: - sage: g = graphs.RandomBipartite(5, -3, 0.5) + sage: g = graphs.RandomBipartite(5, -3, 0.5) # optional - numpy Traceback (most recent call last): ... ValueError: n1 and n2 should be integers strictly greater than 0 - sage: g = graphs.RandomBipartite(5, 3, 1.5) + sage: g = graphs.RandomBipartite(5, 3, 1.5) # optional - numpy Traceback (most recent call last): ... ValueError: parameter p is a probability, and so should be a real value between 0 and 1 :trac:`12155`:: - sage: graphs.RandomBipartite(5, 6, .2).complement() + sage: graphs.RandomBipartite(5, 6, .2).complement() # optional - numpy complement(Random bipartite graph of order 5+6 with edge probability 0.200000000000000): Graph on 11 vertices Test assigned positions:: - sage: graphs.RandomBipartite(1, 2, .1, set_position=True).get_pos() + sage: graphs.RandomBipartite(1, 2, .1, set_position=True).get_pos() # optional - numpy {(0, 0): (1, 1.0), (1, 0): (0, 0), (1, 1): (2.0, 0.0)} - sage: graphs.RandomBipartite(2, 1, .1, set_position=True).get_pos() + sage: graphs.RandomBipartite(2, 1, .1, set_position=True).get_pos() # optional - numpy {(0, 0): (0, 1), (0, 1): (2.0, 1.0), (1, 0): (1, 0.0)} - sage: graphs.RandomBipartite(2, 2, .1, set_position=True).get_pos() + sage: graphs.RandomBipartite(2, 2, .1, set_position=True).get_pos() # optional - numpy {(0, 0): (0, 1), (0, 1): (2.0, 1.0), (1, 0): (0, 0), (1, 1): (2.0, 0.0)} - sage: graphs.RandomBipartite(2, 2, .1, set_position=False).get_pos() + sage: graphs.RandomBipartite(2, 2, .1, set_position=False).get_pos() # optional - numpy """ if not (p >= 0 and p <= 1): @@ -665,12 +665,12 @@ def RandomGNM(n, m, dense=False, seed=None): INPUT: - - ``n`` - number of vertices. + - ``n`` -- number of vertices. - - ``m`` - number of edges. + - ``m`` -- number of edges. - - ``dense`` - whether to use NetworkX's - dense_gnm_random_graph or gnm_random_graph + - ``dense`` -- whether to use NetworkX's + :func:`dense_gnm_random_graph` or :func:`gnm_random_graph` - ``seed`` -- a ``random.Random`` seed or a Python ``int`` for the random number generator (default: ``None``) @@ -679,28 +679,28 @@ def RandomGNM(n, m, dense=False, seed=None): We show the edge list of a random graph on 5 nodes with 10 edges:: - sage: graphs.RandomGNM(5, 10).edges(sort=True, labels=False) + sage: graphs.RandomGNM(5, 10).edges(sort=True, labels=False) # optional - networkx [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)] We plot a random graph on 12 nodes with m = 12:: - sage: gnm = graphs.RandomGNM(12, 12) - sage: gnm.show() # long time + sage: gnm = graphs.RandomGNM(12, 12) # optional - networkx + sage: gnm.show() # long time # optional - networkx sage.plot We view many random graphs using a graphics array:: sage: g = [] sage: j = [] - sage: for i in range(9): + sage: for i in range(9): # optional - networkx ....: k = graphs.RandomGNM(i+3, i^2-i) ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # optional - networkx sage.plot ....: n = [] ....: for m in range(3): ....: n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False)) ....: j.append(n) - sage: G = graphics_array(j) # optional - sage.plot - sage: G.show() # long time # optional - sage.plot + sage: G = graphics_array(j) # optional - networkx sage.plot + sage: G.show() # long time # optional - networkx sage.plot """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) @@ -737,33 +737,33 @@ def RandomNewmanWattsStrogatz(n, k, p, seed=None): We check that the generated graph contains a cycle of order `n`:: - sage: G = graphs.RandomNewmanWattsStrogatz(7, 2, 0.2) - sage: G.order() + sage: G = graphs.RandomNewmanWattsStrogatz(7, 2, 0.2) # optional - networkx + sage: G.order() # optional - networkx 7 - sage: C7 = graphs.CycleGraph(7) - sage: G.subgraph_search(C7) + sage: C7 = graphs.CycleGraph(7) # optional - networkx + sage: G.subgraph_search(C7) # optional - networkx Subgraph of (): Graph on 7 vertices - sage: G.diameter() <= C7.diameter() + sage: G.diameter() <= C7.diameter() # optional - networkx True :: - sage: G = graphs.RandomNewmanWattsStrogatz(12, 2, .3) - sage: G.show() # long time + sage: G = graphs.RandomNewmanWattsStrogatz(12, 2, .3) # optional - networkx + sage: G.show() # long time # optional - networkx sage.plot TESTS: We check that when `k = 2` and `p = 0`, the generated graph is a cycle:: - sage: G = graphs.RandomNewmanWattsStrogatz(7, 2, 0) - sage: G.is_cycle() + sage: G = graphs.RandomNewmanWattsStrogatz(7, 2, 0) # optional - networkx + sage: G.is_cycle() # optional - networkx True We check that when `k = 4` and `p = 0`, the generated graph is a circulant graph of parameters ``[1, 2]``:: - sage: G = graphs.RandomNewmanWattsStrogatz(7, 4, 0) - sage: G.is_isomorphic(graphs.CirculantGraph(7, [1, 2])) + sage: G = graphs.RandomNewmanWattsStrogatz(7, 4, 0) # optional - networkx + sage: G.is_isomorphic(graphs.CirculantGraph(7, [1, 2])) # optional - networkx True REFERENCE: @@ -807,8 +807,8 @@ def RandomHolmeKim(n, m, p, seed=None): EXAMPLES:: - sage: G = graphs.RandomHolmeKim(12, 3, .3) - sage: G.show() # long time + sage: G = graphs.RandomHolmeKim(12, 3, .3) # optional - networkx + sage: G.show() # long time # optional - networkx sage.plot REFERENCE: @@ -952,8 +952,8 @@ def connecting_nodes(T, l): sage: from sage.graphs.generators.random import connecting_nodes sage: T = graphs.RandomTree(10) - sage: S = connecting_nodes(T, 5) - sage: len(S) + sage: S = connecting_nodes(T, 5) # optional - numpy + sage: len(S) # optional - numpy 10 """ from sage.combinat.permutation import Permutations @@ -1178,8 +1178,8 @@ def RandomChordalGraph(n, algorithm="growing", k=None, l=None, f=None, s=None, s sage: T = RandomChordalGraph(20, algorithm="growing", k=5) sage: T.is_chordal() True - sage: T = RandomChordalGraph(20, algorithm="connecting", l=3) - sage: T.is_chordal() + sage: T = RandomChordalGraph(20, algorithm="connecting", l=3) # optional - numpy + sage: T.is_chordal() # optional - numpy True sage: T = RandomChordalGraph(20, algorithm="pruned", f=1/3, s=.5) sage: T.is_chordal() @@ -1303,13 +1303,13 @@ def RandomLobster(n, p, q, seed=None): We check a random graph with 12 backbone nodes and probabilities `p = 0.7` and `q = 0.3`:: - sage: G = graphs.RandomLobster(12, 0.7, 0.3) - sage: leaves = [v for v in G.vertices(sort=False) if G.degree(v) == 1] - sage: G.delete_vertices(leaves) # caterpillar - sage: leaves = [v for v in G.vertices(sort=False) if G.degree(v) == 1] - sage: G.delete_vertices(leaves) # path - sage: s = G.degree_sequence() - sage: if G: + sage: G = graphs.RandomLobster(12, 0.7, 0.3) # optional - networkx + sage: leaves = [v for v in G.vertices(sort=False) if G.degree(v) == 1] # optional - networkx + sage: G.delete_vertices(leaves) # caterpillar # optional - networkx + sage: leaves = [v for v in G.vertices(sort=False) if G.degree(v) == 1] # optional - networkx + sage: G.delete_vertices(leaves) # path # optional - networkx + sage: s = G.degree_sequence() # optional - networkx + sage: if G: # optional - networkx ....: if G.num_verts() == 1: ....: assert s == [0] ....: else: @@ -1318,8 +1318,8 @@ def RandomLobster(n, p, q, seed=None): :: - sage: G = graphs.RandomLobster(9, .6, .3) - sage: G.show() # long time + sage: G = graphs.RandomLobster(9, .6, .3) # optional - networkx + sage: G.show() # long time # optional - networkx sage.plot """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) @@ -1434,16 +1434,16 @@ def RandomTreePowerlaw(n, gamma=3, tries=1000, seed=None): We check that the generated graph is a tree:: - sage: G = graphs.RandomTreePowerlaw(10, 3) - sage: G.is_tree() + sage: G = graphs.RandomTreePowerlaw(10, 3) # optional - networkx + sage: G.is_tree() # optional - networkx True - sage: G.order(), G.size() + sage: G.order(), G.size() # optional - networkx (10, 9) :: - sage: G = graphs.RandomTreePowerlaw(15, 2) - sage: if G: # random output, long time + sage: G = graphs.RandomTreePowerlaw(15, 2) # optional - networkx + sage: if G: # random output, long time # optional - networkx sage.plot ....: G.show() """ if seed is None: @@ -1474,16 +1474,16 @@ def RandomRegular(d, n, seed=None): We check that a random graph with 8 nodes each of degree 3 is 3-regular:: - sage: G = graphs.RandomRegular(3, 8) - sage: G.is_regular(k=3) + sage: G = graphs.RandomRegular(3, 8) # optional - networkx + sage: G.is_regular(k=3) # optional - networkx True - sage: G.degree_histogram() + sage: G.degree_histogram() # optional - networkx [0, 0, 0, 8] :: - sage: G = graphs.RandomRegular(3, 20) - sage: if G: # random output, long time + sage: G = graphs.RandomRegular(3, 20) # optional - networkx + sage: if G: # random output, long time # optional - networkx sage.plot ....: G.show() REFERENCES: @@ -1524,10 +1524,10 @@ def RandomShell(constructor, seed=None): EXAMPLES:: - sage: G = graphs.RandomShell([(10,20,0.8),(20,40,0.8)]) - sage: G.order(), G.size() + sage: G = graphs.RandomShell([(10,20,0.8),(20,40,0.8)]) # optional - networkx + sage: G.order(), G.size() # optional - networkx (30, 52) - sage: G.show() # long time + sage: G.show() # long time # optional - networkx sage.plot """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) @@ -2005,16 +2005,16 @@ def blossoming_contour(t, shift=0, seed=None): sage: print(blossoming_contour(BinaryTrees(1).an_element())) [('i', 0), ('xb',), ('i', 0), ('xb',), ('i', 0)] - sage: t = BinaryTrees(2).random_element() - sage: print(blossoming_contour(t)) # random + sage: t = BinaryTrees(2).random_element() # optional - sage.combinat + sage: print(blossoming_contour(t)) # random # optional - sage.combinat [('i', 0), ('xb',), ('i', 0), ('n', 2), ('i', 1), ('xb',), ('i', 1), ('xb',), ('i', 1), ('n', 2), ('x',), ('n', 2), ('i', 0)] - sage: w = blossoming_contour(BinaryTrees(3).random_element()); len(w) + sage: w = blossoming_contour(BinaryTrees(3).random_element()); len(w) # optional - sage.combinat 21 - sage: w.count(('xb',)) + sage: w.count(('xb',)) # optional - sage.combinat 4 - sage: w.count(('x',)) + sage: w.count(('x',)) # optional - sage.combinat 2 TESTS:: @@ -2099,16 +2099,16 @@ def RandomBicubicPlanar(n, seed=None): EXAMPLES:: sage: n = randint(200, 300) - sage: G = graphs.RandomBicubicPlanar(n) - sage: G.order() == 2*n + sage: G = graphs.RandomBicubicPlanar(n) # optional - sage.combinat + sage: G.order() == 2*n # optional - sage.combinat True - sage: G.size() == 3*n + sage: G.size() == 3*n # optional - sage.combinat True - sage: G.is_bipartite() and G.is_planar() and G.is_regular(3) + sage: G.is_bipartite() and G.is_planar() and G.is_regular(3) # optional - sage.combinat True - sage: dic = {'red': [v for v in G.vertices(sort=False) if v[0] == 'n'], + sage: dic = {'red': [v for v in G.vertices(sort=False) if v[0] == 'n'], # optional - sage.combinat ....: 'blue': [v for v in G.vertices(sort=False) if v[0] != 'n']} - sage: G.plot(vertex_labels=False, vertex_size=20, vertex_colors=dic) # optional - sage.plot + sage: G.plot(vertex_labels=False, vertex_size=20, vertex_colors=dic) # optional - sage.combinat sage.plot Graphics object consisting of ... graphics primitives .. PLOT:: @@ -2212,21 +2212,21 @@ def RandomUnitDiskGraph(n, radius=.1, side=1, seed=None): sage: from sage.misc.randstate import current_randstate sage: seed = current_randstate().seed() - sage: G = graphs.RandomUnitDiskGraph(20, radius=.5, side=1, seed=seed) - sage: H = graphs.RandomUnitDiskGraph(20, radius=.2, side=1, seed=seed) - sage: H.is_subgraph(G, induced=False) + sage: G = graphs.RandomUnitDiskGraph(20, radius=.5, side=1, seed=seed) # optional - scipy + sage: H = graphs.RandomUnitDiskGraph(20, radius=.2, side=1, seed=seed) # optional - scipy + sage: H.is_subgraph(G, induced=False) # optional - scipy True - sage: H.size() <= G.size() + sage: H.size() <= G.size() # optional - scipy True - sage: Gpos = G.get_pos() - sage: Hpos = H.get_pos() - sage: all(Gpos[u] == Hpos[u] for u in G) + sage: Gpos = G.get_pos() # optional - scipy + sage: Hpos = H.get_pos() # optional - scipy + sage: all(Gpos[u] == Hpos[u] for u in G) # optional - scipy True When the radius is more than `\sqrt{2 \text{side}}`, the graph is a clique:: - sage: G = graphs.RandomUnitDiskGraph(10, radius=2, side=1) - sage: G.is_clique() + sage: G = graphs.RandomUnitDiskGraph(10, radius=2, side=1) # optional - scipy + sage: G.is_clique() # optional - scipy True """ if seed is not None: diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index f25d5b4e561..36275b2ce57 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -139,21 +139,21 @@ def HarriesGraph(embedding=1): EXAMPLES:: - sage: g = graphs.HarriesGraph() - sage: g.order() + sage: g = graphs.HarriesGraph() # optional - networkx + sage: g.order() # optional - networkx 70 - sage: g.size() + sage: g.size() # optional - networkx 105 - sage: g.girth() + sage: g.girth() # optional - networkx 10 - sage: g.diameter() + sage: g.diameter() # optional - networkx 6 - sage: g.show(figsize=[10, 10]) # long time - sage: graphs.HarriesGraph(embedding=2).show(figsize=[10, 10]) # long time + sage: g.show(figsize=[10, 10]) # long time # optional - networkx sage.plot + sage: graphs.HarriesGraph(embedding=2).show(figsize=[10, 10]) # long time # optional - networkx sage.plot TESTS:: - sage: graphs.HarriesGraph(embedding=3) + sage: graphs.HarriesGraph(embedding=3) # optional - networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -257,25 +257,25 @@ def HarriesWongGraph(embedding=1): EXAMPLES:: - sage: g = graphs.HarriesWongGraph() - sage: g.order() + sage: g = graphs.HarriesWongGraph() # optional - networkx + sage: g.order() # optional - networkx 70 - sage: g.size() + sage: g.size() # optional - networkx 105 - sage: g.girth() + sage: g.girth() # optional - networkx 10 - sage: g.diameter() + sage: g.diameter() # optional - networkx 6 - sage: orbits = g.automorphism_group(orbits=True)[-1] # long time - sage: g.show(figsize=[15, 15], partition=orbits) # long time + sage: orbits = g.automorphism_group(orbits=True)[-1] # long time # optional - networkx sage.groups + sage: g.show(figsize=[15, 15], partition=orbits) # long time # optional - networkx sage.groups sage.plot Alternative embedding:: - sage: graphs.HarriesWongGraph(embedding=2).show() # long time + sage: graphs.HarriesWongGraph(embedding=2).show() # long time # optional - networkx sage.plot TESTS:: - sage: graphs.HarriesWongGraph(embedding=3) + sage: graphs.HarriesWongGraph(embedding=3) # optional - networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -679,7 +679,7 @@ def HallJankoGraph(from_string=True): sage: g = graphs.HallJankoGraph() sage: g.is_regular(36) True - sage: g.is_vertex_transitive() + sage: g.is_vertex_transitive() # optional - sage.groups True Is it really strongly regular with parameters 14, 12? :: @@ -804,20 +804,20 @@ def Balaban10Cage(embedding=1): EXAMPLES:: - sage: g = graphs.Balaban10Cage() - sage: g.girth() + sage: g = graphs.Balaban10Cage() # optional - networkx + sage: g.girth() # optional - networkx 10 - sage: g.chromatic_number() + sage: g.chromatic_number() # optional - networkx 2 - sage: g.diameter() + sage: g.diameter() # optional - networkx 6 - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # optional - networkx True - sage: g.show(figsize=[10,10]) # long time + sage: g.show(figsize=[10,10]) # long time # optional - networkx sage.plot TESTS:: - sage: graphs.Balaban10Cage(embedding='foo') + sage: graphs.Balaban10Cage(embedding='foo') # optional - networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -897,7 +897,7 @@ def Balaban11Cage(embedding=1): 11 sage: g.diameter() 8 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - sage.groups 64 Our many embeddings:: @@ -905,9 +905,9 @@ def Balaban11Cage(embedding=1): sage: g1 = graphs.Balaban11Cage(embedding=1) sage: g2 = graphs.Balaban11Cage(embedding=2) sage: g3 = graphs.Balaban11Cage(embedding=3) - sage: g1.show(figsize=[10,10]) # long time - sage: g2.show(figsize=[10,10]) # long time - sage: g3.show(figsize=[10,10]) # long time + sage: g1.show(figsize=[10,10]) # long time # optional - sage.plot + sage: g2.show(figsize=[10,10]) # long time # optional - sage.plot + sage: g3.show(figsize=[10,10]) # long time # optional - sage.plot Proof that the embeddings are the same graph:: @@ -1114,26 +1114,26 @@ def BiggsSmithGraph(embedding=1): Basic properties:: - sage: g = graphs.BiggsSmithGraph() - sage: g.order() + sage: g = graphs.BiggsSmithGraph() # optional - networkx + sage: g.order() # optional - networkx 102 - sage: g.size() + sage: g.size() # optional - networkx 153 - sage: g.girth() + sage: g.girth() # optional - networkx 9 - sage: g.diameter() + sage: g.diameter() # optional - networkx 7 - sage: g.automorphism_group().cardinality() # long time + sage: g.automorphism_group().cardinality() # long time # optional - networkx 2448 - sage: g.show(figsize=[10, 10]) # long time + sage: g.show(figsize=[10, 10]) # long time # optional - networkx sage.plot The other embedding:: - sage: graphs.BiggsSmithGraph(embedding=2).show() # long time + sage: graphs.BiggsSmithGraph(embedding=2).show() # long time # optional - networkx TESTS:: - sage: graphs.BiggsSmithGraph(embedding='xyzzy') + sage: graphs.BiggsSmithGraph(embedding='xyzzy') # optional - networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -1199,16 +1199,16 @@ def BlanusaFirstSnarkGraph(): EXAMPLES:: - sage: g = graphs.BlanusaFirstSnarkGraph() - sage: g.order() + sage: g = graphs.BlanusaFirstSnarkGraph() # optional - sage.groups + sage: g.order() # optional - sage.groups 18 - sage: g.size() + sage: g.size() # optional - sage.groups 27 - sage: g.diameter() + sage: g.diameter() # optional - sage.groups 4 - sage: g.girth() + sage: g.girth() # optional - sage.groups 5 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - sage.groups 8 """ g = Graph({17: [4, 7, 1], 0: [5], 3: [8], 13: [9], 12: [16], @@ -1234,16 +1234,16 @@ def BlanusaSecondSnarkGraph(): EXAMPLES:: - sage: g = graphs.BlanusaSecondSnarkGraph() - sage: g.order() + sage: g = graphs.BlanusaSecondSnarkGraph() # optional - sage.groups + sage: g.order() # optional - sage.groups 18 - sage: g.size() + sage: g.size() # optional - sage.groups 27 - sage: g.diameter() + sage: g.diameter() # optional - sage.groups 4 - sage: g.girth() + sage: g.girth() # optional - sage.groups 5 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - sage.groups 4 """ c0 = (-1, 0) @@ -1361,18 +1361,18 @@ def BrouwerHaemersGraph(): EXAMPLES:: - sage: g = graphs.BrouwerHaemersGraph() - sage: g + sage: g = graphs.BrouwerHaemersGraph() # optional - sage.modules + sage: g # optional - sage.modules Brouwer-Haemers: Graph on 81 vertices It is indeed strongly regular with parameters `(81,20,1,6)`:: - sage: g.is_strongly_regular(parameters=True) # long time + sage: g.is_strongly_regular(parameters=True) # long time # optional - sage.modules (81, 20, 1, 6) Its has as eigenvalues `20,2` and `-7`:: - sage: set(g.spectrum()) == {20,2,-7} + sage: set(g.spectrum()) == {20,2,-7} # optional - sage.modules True """ from sage.rings.finite_rings.finite_field_constructor import FiniteField @@ -1419,16 +1419,16 @@ def BuckyBall(): The Bucky Ball can also be created by extracting the 1-skeleton of the Bucky Ball polyhedron, but this is much slower:: - sage: g = polytopes.buckyball().vertex_graph() - sage: g.remove_loops() + sage: g = polytopes.buckyball().vertex_graph() # optional - sage.geometry.polyhedron + sage: g.remove_loops() # optional - sage.geometry.polyhedron sage: h = graphs.BuckyBall() - sage: g.is_isomorphic(h) + sage: g.is_isomorphic(h) # optional - sage.geometry.polyhedron True The graph is returned along with an attractive embedding:: sage: g = graphs.BuckyBall() # long time - sage: g.plot(vertex_labels=False, vertex_size=10).show() # long time + sage: g.plot(vertex_labels=False, vertex_size=10).show() # long time # optional - sage.plot """ edges = [(0, 2), (0, 48), (0, 59), (1, 3), (1, 9), (1, 58), (2, 3), (2, 36), (3, 17), (4, 6), (4, 8), (4, 12), @@ -1735,12 +1735,12 @@ def CameronGraph(): EXAMPLES:: - sage: g = graphs.CameronGraph() - sage: g.order() + sage: g = graphs.CameronGraph() # optional - sage.groups + sage: g.order() # optional - sage.groups 231 - sage: g.size() + sage: g.size() # optional - sage.groups 3465 - sage: g.is_strongly_regular(parameters = True) # long time + sage: g.is_strongly_regular(parameters=True) # long time # optional - sage.groups (231, 30, 9, 3) """ from sage.groups.perm_gps.permgroup_named import MathieuGroup @@ -1828,7 +1828,7 @@ def ClebschGraph(): EXAMPLES:: sage: g = graphs.ClebschGraph() - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - sage.groups 1920 sage: g.girth() 4 @@ -1836,7 +1836,7 @@ def ClebschGraph(): 4 sage: g.diameter() 2 - sage: g.show(figsize=[10, 10]) # long time + sage: g.show(figsize=[10, 10]) # long time # optional - sage.plot """ g = Graph(pos={}) x = 0 @@ -1865,7 +1865,7 @@ def CoxeterGraph(): EXAMPLES:: sage: g = graphs.CoxeterGraph() - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - sage.groups 336 sage: g.girth() 7 @@ -1873,7 +1873,7 @@ def CoxeterGraph(): 3 sage: g.diameter() 4 - sage: g.show(figsize=[10, 10]) # long time + sage: g.show(figsize=[10, 10]) # long time # optional - sage.plot """ g = Graph({ 27: [6, 22, 14], @@ -1931,10 +1931,10 @@ def DesarguesGraph(): EXAMPLES:: sage: D = graphs.DesarguesGraph() - sage: L = graphs.LCFGraph(20,[5,-5,9,-9],5) - sage: D.is_isomorphic(L) + sage: L = graphs.LCFGraph(20,[5,-5,9,-9],5) # optional - networkx + sage: D.is_isomorphic(L) # optional - networkx True - sage: D.show() # long time + sage: D.show() # long time # optional - sage.plot """ from sage.graphs.generators.families import GeneralizedPetersenGraph G = GeneralizedPetersenGraph(10, 3) @@ -2085,22 +2085,22 @@ def HortonGraph(): EXAMPLES:: - sage: g = graphs.HortonGraph() - sage: g.order() + sage: g = graphs.HortonGraph() # optional - networkx + sage: g.order() # optional - networkx 96 - sage: g.size() + sage: g.size() # optional - networkx 144 - sage: g.radius() + sage: g.radius() # optional - networkx 10 - sage: g.diameter() + sage: g.diameter() # optional - networkx 10 - sage: g.girth() + sage: g.girth() # optional - networkx 6 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - networkx 96 - sage: g.chromatic_number() + sage: g.chromatic_number() # optional - networkx 2 - sage: g.is_hamiltonian() # not tested -- veeeery long + sage: g.is_hamiltonian() # not tested -- veeeery long # optional - networkx False """ g = Graph(name="Horton Graph") @@ -2374,17 +2374,17 @@ def F26AGraph(): EXAMPLES:: - sage: g = graphs.F26AGraph(); g + sage: g = graphs.F26AGraph(); g # optional - networkx F26A Graph: Graph on 26 vertices - sage: g.order(),g.size() + sage: g.order(), g.size() # optional - networkx (26, 39) - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - networkx 78 - sage: g.girth() + sage: g.girth() # optional - networkx 6 - sage: g.is_bipartite() + sage: g.is_bipartite() # optional - networkx True - sage: g.characteristic_polynomial().factor() + sage: g.characteristic_polynomial().factor() # optional - networkx (x - 3) * (x + 3) * (x^4 - 5*x^2 + 3)^6 """ from sage.graphs.generators.families import LCFGraph @@ -2435,26 +2435,26 @@ def FolkmanGraph(): EXAMPLES:: - sage: g = graphs.FolkmanGraph() - sage: g.order() + sage: g = graphs.FolkmanGraph() # optional - networkx + sage: g.order() # optional - networkx 20 - sage: g.size() + sage: g.size() # optional - networkx 40 - sage: g.diameter() + sage: g.diameter() # optional - networkx 4 - sage: g.girth() + sage: g.girth() # optional - networkx 4 - sage: g.charpoly().factor() + sage: g.charpoly().factor() # optional - networkx (x - 4) * (x + 4) * x^10 * (x^2 - 6)^4 - sage: g.chromatic_number() + sage: g.chromatic_number() # optional - networkx 2 - sage: g.is_eulerian() + sage: g.is_eulerian() # optional - networkx True - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # optional - networkx True - sage: g.is_vertex_transitive() + sage: g.is_vertex_transitive() # optional - networkx False - sage: g.is_bipartite() + sage: g.is_bipartite() # optional - networkx True """ from sage.graphs.generators.families import LCFGraph @@ -2471,18 +2471,18 @@ def FosterGraph(): EXAMPLES:: - sage: g = graphs.FosterGraph() - sage: g.order() + sage: g = graphs.FosterGraph() # optional - networkx + sage: g.order() # optional - networkx 90 - sage: g.size() + sage: g.size() # optional - networkx 135 - sage: g.diameter() + sage: g.diameter() # optional - networkx 8 - sage: g.girth() + sage: g.girth() # optional - networkx 10 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - networkx 4320 - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # optional - networkx True """ from sage.graphs.generators.families import LCFGraph @@ -2565,18 +2565,18 @@ def FruchtGraph(): EXAMPLES:: - sage: FRUCHT = graphs.FruchtGraph() - sage: FRUCHT + sage: FRUCHT = graphs.FruchtGraph() # optional - networkx + sage: FRUCHT # optional - networkx Frucht graph: Graph on 12 vertices - sage: FRUCHT.graph6_string() + sage: FRUCHT.graph6_string() # optional - networkx 'KhCKM?_EGK?L' - sage: (graphs.FruchtGraph()).show() # long time + sage: (graphs.FruchtGraph()).show() # long time # optional - networkx TESTS:: - sage: import networkx - sage: G = graphs.FruchtGraph() - sage: G.is_isomorphic(Graph(networkx.frucht_graph())) + sage: import networkx # optional - networkx + sage: G = graphs.FruchtGraph() # optional - networkx + sage: G.is_isomorphic(Graph(networkx.frucht_graph())) # optional - networkx True """ edges = {0: [1, 6, 7], 1: [2, 7], 2: [3, 8], 3: [4, 9], 4: [5, 9], @@ -2888,8 +2888,8 @@ def HerschelGraph(): sage: G.chromatic_number() 2 - sage: ag = G.automorphism_group() - sage: ag.is_isomorphic(DihedralGroup(6)) + sage: ag = G.automorphism_group() # optional - sage.groups + sage: ag.is_isomorphic(DihedralGroup(6)) # optional - sage.groups True """ edge_dict = { @@ -2919,9 +2919,9 @@ def GritsenkoGraph(): EXAMPLES:: - sage: H = graphs.GritsenkoGraph(); H + sage: H = graphs.GritsenkoGraph(); H # optional - sage.groups Gritsenko strongly regular graph: Graph on 65 vertices - sage: H.is_strongly_regular(parameters=True) + sage: H.is_strongly_regular(parameters=True) # optional - sage.groups (65, 32, 15, 16) """ from sage.groups.perm_gps.permgroup import PermutationGroup @@ -3000,13 +3000,13 @@ def HigmanSimsGraph(relabel=True): which is of index 2 and is simple. It is known as the Higman-Sims group:: sage: H = graphs.HigmanSimsGraph() - sage: G = H.automorphism_group() - sage: g=G.order(); g + sage: G = H.automorphism_group() # optional - sage.groups + sage: g = G.order(); g # optional - sage.groups 88704000 - sage: K = G.normal_subgroups()[1] - sage: K.is_simple() + sage: K = G.normal_subgroups()[1] # optional - sage.groups + sage: K.is_simple() # optional - sage.groups True - sage: g//K.order() + sage: g//K.order() # optional - sage.groups 2 AUTHOR: @@ -3192,7 +3192,7 @@ def HoffmanGraph(): 3 sage: g.diameter() 4 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - sage.groups 48 """ g = Graph({ @@ -3231,7 +3231,7 @@ def HoltGraph(): Holt graph: Graph on 27 vertices sage: g.is_regular() True - sage: g.is_vertex_transitive() + sage: g.is_vertex_transitive() # optional - sage.groups True sage: g.chromatic_number() 3 @@ -3243,7 +3243,7 @@ def HoltGraph(): 3 sage: g.girth() 5 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - sage.groups 54 """ g = Graph(loops=False, name="Holt graph", pos={}) @@ -3324,7 +3324,7 @@ def Klein3RegularGraph(): (56, 84) sage: g.girth() 7 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - sage.groups 336 sage: g.chromatic_number() 3 @@ -3357,7 +3357,7 @@ def Klein7RegularGraph(): (24, 84) sage: g.girth() 3 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - sage.groups 336 sage: g.chromatic_number() 4 @@ -3413,21 +3413,21 @@ def LjubljanaGraph(embedding=1): EXAMPLES:: - sage: g = graphs.LjubljanaGraph() - sage: g.order() + sage: g = graphs.LjubljanaGraph() # optional - networkx + sage: g.order() # optional - networkx 112 - sage: g.size() + sage: g.size() # optional - networkx 168 - sage: g.girth() + sage: g.girth() # optional - networkx 10 - sage: g.diameter() + sage: g.diameter() # optional - networkx 8 - sage: g.show(figsize=[10, 10]) # long time - sage: graphs.LjubljanaGraph(embedding=2).show(figsize=[10, 10]) # long time + sage: g.show(figsize=[10, 10]) # long time # optional - networkx sage.plot + sage: graphs.LjubljanaGraph(embedding=2).show(figsize=[10, 10]) # long time # optional - networkx sage.plot TESTS:: - sage: graphs.LjubljanaGraph(embedding=3) + sage: graphs.LjubljanaGraph(embedding=3) # optional - networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -3518,12 +3518,12 @@ def M22Graph(): EXAMPLES:: - sage: g = graphs.M22Graph() - sage: g.order() + sage: g = graphs.M22Graph() # optional - sage.groups + sage: g.order() # optional - sage.groups 77 - sage: g.size() + sage: g.size() # optional - sage.groups 616 - sage: g.is_strongly_regular(parameters = True) + sage: g.is_strongly_regular(parameters=True) # optional - sage.groups (77, 16, 0, 4) """ from sage.groups.perm_gps.permgroup_named import MathieuGroup @@ -3561,11 +3561,11 @@ def MarkstroemGraph(): True sage: g.is_regular(3) True - sage: g.subgraph_search(graphs.CycleGraph(4)) is None + sage: g.subgraph_search(graphs.CycleGraph(4)) is None # optional - sage.modules True - sage: g.subgraph_search(graphs.CycleGraph(8)) is None + sage: g.subgraph_search(graphs.CycleGraph(8)) is None # optional - sage.modules True - sage: g.subgraph_search(graphs.CycleGraph(16)) + sage: g.subgraph_search(graphs.CycleGraph(16)) # optional - sage.modules Subgraph of (Markstroem Graph): Graph on 16 vertices """ g = Graph(name="Markstroem Graph") @@ -3602,21 +3602,21 @@ def McGeeGraph(embedding=2): EXAMPLES:: - sage: g = graphs.McGeeGraph() - sage: g.order() + sage: g = graphs.McGeeGraph() # optional - networkx + sage: g.order() # optional - networkx 24 - sage: g.size() + sage: g.size() # optional - networkx 36 - sage: g.girth() + sage: g.girth() # optional - networkx 7 - sage: g.diameter() + sage: g.diameter() # optional - networkx 4 - sage: g.show() # optional - sage.plot - sage: graphs.McGeeGraph(embedding=1).show() # long time # optional - sage.plot + sage: g.show() # optional - networkx sage.plot + sage: graphs.McGeeGraph(embedding=1).show() # long time # optional - networkx sage.plot TESTS:: - sage: graphs.McGeeGraph(embedding=3) + sage: graphs.McGeeGraph(embedding=3) # optional - networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -3830,7 +3830,7 @@ def NauruGraph(embedding=2): Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 - sage: graphs.NauruGraph(embedding=1).is_isomorphic(g) + sage: graphs.NauruGraph(embedding=1).is_isomorphic(g) # optional - networkx True """ @@ -3858,9 +3858,9 @@ def PappusGraph(): sage: G = graphs.PappusGraph() sage: G.show() # long time # optional - sage.plot - sage: L = graphs.LCFGraph(18, [5,7,-7,7,-7,-5], 3) - sage: L.show() # long time # optional - sage.plot - sage: G.is_isomorphic(L) + sage: L = graphs.LCFGraph(18, [5,7,-7,7,-7,-5], 3) # optional - networkx + sage: L.show() # long time # optional - networkx sage.plot + sage: G.is_isomorphic(L) # optional - networkx True """ edges = {0: [1, 5, 6], 1: [2, 7], 2: [3, 8], 3: [4, 9], 4: [5, 10], 5: [11], @@ -3970,22 +3970,23 @@ def RobertsonGraph(): EXAMPLES:: - sage: g = graphs.RobertsonGraph() - sage: g.order() + sage: g = graphs.RobertsonGraph() # optional - networkx + sage: g.order() # optional - networkx 19 - sage: g.size() + sage: g.size() # optional - networkx 38 - sage: g.diameter() + sage: g.diameter() # optional - networkx 3 - sage: g.girth() + sage: g.girth() # optional - networkx 5 - sage: g.charpoly().factor() - (x - 4) * (x - 1)^2 * (x^2 + x - 5) * (x^2 + x - 1) * (x^2 - 3)^2 * (x^2 + x - 4)^2 * (x^2 + x - 3)^2 - sage: g.chromatic_number() + sage: g.charpoly().factor() # optional - networkx + (x - 4) * (x - 1)^2 * (x^2 + x - 5) * (x^2 + x - 1) + * (x^2 - 3)^2 * (x^2 + x - 4)^2 * (x^2 + x - 3)^2 + sage: g.chromatic_number() # optional - networkx 3 - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # optional - networkx True - sage: g.is_vertex_transitive() + sage: g.is_vertex_transitive() # optional - networkx False """ from sage.graphs.generators.families import LCFGraph @@ -4023,7 +4024,7 @@ def SchlaefliGraph(): The graph is vertex-transitive:: - sage: S.is_vertex_transitive() + sage: S.is_vertex_transitive() # optional - sage.groups True The neighborhood of each vertex is isomorphic to the complement of the @@ -4235,7 +4236,7 @@ def SousselierGraph(): 2 sage: g.diameter() 3 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - sage.groups 2 sage: g.is_hamiltonian() False @@ -4342,9 +4343,9 @@ def TietzeGraph(): 3 sage: g.girth() 3 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - sage.groups 12 - sage: g.automorphism_group().is_isomorphic(groups.permutation.Dihedral(6)) + sage: g.automorphism_group().is_isomorphic(groups.permutation.Dihedral(6)) # optional - sage.groups True """ g = Graph([(0, 9), (3, 10), (6, 11), (1, 5), (2, 7), (4, 8)], @@ -4396,7 +4397,7 @@ def TruncatedTetrahedralGraph(): Truncated Tetrahedron: Graph on 12 vertices sage: g.order(), g.size() (12, 18) - sage: g.is_isomorphic(polytopes.simplex(3).truncation().graph()) + sage: g.is_isomorphic(polytopes.simplex(3).truncation().graph()) # optional - sage.geometry.polyhedron True """ g = Graph(':K`ESwC_EOyDl\\MCi', loops=False, multiedges=False) @@ -4415,16 +4416,16 @@ def Tutte12Cage(): EXAMPLES:: - sage: g = graphs.Tutte12Cage() - sage: g.order() + sage: g = graphs.Tutte12Cage() # optional - networkx + sage: g.order() # optional - networkx 126 - sage: g.size() + sage: g.size() # optional - networkx 189 - sage: g.girth() + sage: g.girth() # optional - networkx 12 - sage: g.diameter() + sage: g.diameter() # optional - networkx 6 - sage: g.show() # optional - sage.plot + sage: g.show() # optional - networkx sage.plot """ L = [17, 27, -13, -59, -35, 35, -11, 13, -53, 53, -27, 21, 57, 11, -21, -57, 59, -17] @@ -4448,21 +4449,21 @@ def TutteCoxeterGraph(embedding=2): EXAMPLES:: - sage: g = graphs.TutteCoxeterGraph() - sage: g.order() + sage: g = graphs.TutteCoxeterGraph() # optional - networkx + sage: g.order() # optional - networkx 30 - sage: g.size() + sage: g.size() # optional - networkx 45 - sage: g.girth() + sage: g.girth() # optional - networkx 8 - sage: g.diameter() + sage: g.diameter() # optional - networkx 4 - sage: g.show() # optional - sage.plot - sage: graphs.TutteCoxeterGraph(embedding=1).show() # long time + sage: g.show() # optional - networkx sage.plot + sage: graphs.TutteCoxeterGraph(embedding=1).show() # long time # optional - networkx sage.plot TESTS:: - sage: graphs.TutteCoxeterGraph(embedding=3) + sage: graphs.TutteCoxeterGraph(embedding=3) # optional - networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -4515,7 +4516,7 @@ def TutteGraph(): 3 sage: g.girth() 4 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # optional - sage.groups 3 sage: g.is_hamiltonian() False @@ -4561,16 +4562,16 @@ def WagnerGraph(): EXAMPLES:: - sage: g = graphs.WagnerGraph() - sage: g.order() + sage: g = graphs.WagnerGraph() # optional - networkx + sage: g.order() # optional - networkx 8 - sage: g.size() + sage: g.size() # optional - networkx 12 - sage: g.girth() + sage: g.girth() # optional - networkx 4 - sage: g.diameter() + sage: g.diameter() # optional - networkx 2 - sage: g.show() # optional - sage.plot + sage: g.show() # optional - networkx sage.plot """ from sage.graphs.generators.families import LCFGraph g = LCFGraph(8, [4], 8) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index cd1be3f851a..1f8db82faed 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -440,15 +440,16 @@ from sage.misc.cachefunc import cached_method from sage.misc.prandom import random from sage.misc.superseded import deprecation -from sage.misc.lazy_import import LazyImport +from sage.misc.lazy_import import lazy_import, LazyImport from sage.rings.integer_ring import ZZ from sage.rings.integer import Integer from sage.rings.rational import Rational -from sage.matrix.constructor import matrix from sage.rings.rational_field import QQ from sage.features.igraph import python_igraph as igraph_feature +lazy_import('sage.matrix.constructor', 'matrix') + to_hex = LazyImport('matplotlib.colors', 'to_hex') @@ -908,7 +909,7 @@ def _latex_(self): sage: from sage.graphs.graph_latex import check_tkz_graph sage: check_tkz_graph() # random - depends on TeX installation sage: g = graphs.CompleteGraph(2) - sage: print(g._latex_()) + sage: print(g._latex_()) # optional - sage.plot \begin{tikzpicture} \definecolor{cv0}{rgb}{0.0,0.0,0.0} \definecolor{cfv0}{rgb}{1.0,1.0,1.0} @@ -945,21 +946,21 @@ def _matrix_(self, R=None, vertices=None): EXAMPLES:: sage: G = graphs.CompleteBipartiteGraph(2, 3) - sage: m = matrix(G); m.parent() + sage: m = matrix(G); m.parent() # optional - sage.modules Full MatrixSpace of 5 by 5 dense matrices over Integer Ring - sage: m + sage: m # optional - sage.modules [0 0 1 1 1] [0 0 1 1 1] [1 1 0 0 0] [1 1 0 0 0] [1 1 0 0 0] - sage: G._matrix_() + sage: G._matrix_() # optional - sage.modules [0 0 1 1 1] [0 0 1 1 1] [1 1 0 0 0] [1 1 0 0 0] [1 1 0 0 0] - sage: factor(m.charpoly()) + sage: factor(m.charpoly()) # optional - sage.modules x^3 * (x^2 - 6) """ return self.am(vertices=vertices, base_ring=R) @@ -1368,24 +1369,24 @@ def export_to_file(self, filename, format=None, **kwds): sage: g = graphs.PetersenGraph() sage: filename = tmp_filename(ext=".pajek") - sage: g.export_to_file(filename) + sage: g.export_to_file(filename) # optional - networkx sage: import networkx # optional - networkx sage: G_networkx = networkx.read_pajek(filename) # optional - networkx sage: Graph(G_networkx).is_isomorphic(g) # optional - networkx True sage: filename = tmp_filename(ext=".edgelist") - sage: g.export_to_file(filename, data=False) + sage: g.export_to_file(filename, data=False) # optional - networkx sage: h = Graph(networkx.read_edgelist(filename)) # optional - networkx sage: g.is_isomorphic(h) # optional - networkx True TESTS:: - sage: g.export_to_file("hey", format="When I feel heavy metaaaaaallll...") + sage: g.export_to_file("hey", format="When I feel heavy metaaaaaallll...") # optional - networkx Traceback (most recent call last): ... ValueError: format 'When I feel heavy metaaaaaallll...' unknown - sage: g.export_to_file("my_file.Yeeeeppeeeeee") + sage: g.export_to_file("my_file.Yeeeeppeeeeee") # optional - networkx Traceback (most recent call last): ... RuntimeError: the file format could not be guessed from 'my_file.Yeeeeppeeeeee' @@ -1507,20 +1508,24 @@ def networkx_graph(self, weight_function=None): EXAMPLES:: sage: G = graphs.TetrahedralGraph() - sage: N = G.networkx_graph() - sage: type(N) + sage: N = G.networkx_graph() # optional - networkx + sage: type(N) # optional - networkx sage: def weight_fn(e): ....: return e[2] sage: G1 = Graph([(1,2,1), (1,3,4), (2,3,3), (3,4,4)]) - sage: H = G1.networkx_graph(weight_function=weight_fn) - sage: H.edges(data=True) - EdgeDataView([(1, 2, {'weight': 1}), (1, 3, {'weight': 4}), (2, 3, {'weight': 3}), (3, 4, {'weight': 4})]) - sage: G2 = DiGraph([(1,2,1), (1,3,4), (2,3,3), (3,4,4), (3,4,5)], multiedges=True) - sage: H = G2.networkx_graph(weight_function=weight_fn) - sage: H.edges(data=True) - OutMultiEdgeDataView([(1, 2, {'weight': 1}), (1, 3, {'weight': 4}), (2, 3, {'weight': 3}), (3, 4, {'weight': 5}), (3, 4, {'weight': 4})]) + sage: H = G1.networkx_graph(weight_function=weight_fn) # optional - networkx + sage: H.edges(data=True) # optional - networkx + EdgeDataView([(1, 2, {'weight': 1}), (1, 3, {'weight': 4}), + (2, 3, {'weight': 3}), (3, 4, {'weight': 4})]) + sage: G2 = DiGraph([(1,2,1), (1,3,4), (2,3,3), (3,4,4), (3,4,5)], + ....: multiedges=True) + sage: H = G2.networkx_graph(weight_function=weight_fn) # optional - networkx + sage: H.edges(data=True) # optional - networkx + OutMultiEdgeDataView([(1, 2, {'weight': 1}), (1, 3, {'weight': 4}), + (2, 3, {'weight': 3}), (3, 4, {'weight': 5}), + (3, 4, {'weight': 4})]) """ if weight_function is not None: @@ -1907,7 +1912,7 @@ def adjacency_matrix(self, sparse=None, vertices=None, *, base_ring=None, **kwds EXAMPLES:: sage: G = graphs.CubeGraph(4) - sage: G.adjacency_matrix() + sage: G.adjacency_matrix() # optional - sage.modules [0 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0] [1 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0] [1 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0] @@ -1927,7 +1932,7 @@ def adjacency_matrix(self, sparse=None, vertices=None, *, base_ring=None, **kwds :: - sage: matrix(GF(2),G) # matrix over GF(2) + sage: matrix(GF(2), G) # matrix over GF(2) # optional - sage.modules sage.rings.finite_rings [0 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0] [1 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0] [1 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0] @@ -1947,8 +1952,9 @@ def adjacency_matrix(self, sparse=None, vertices=None, *, base_ring=None, **kwds :: - sage: D = DiGraph({0: [1, 2, 3], 1: [0, 2], 2: [3], 3: [4], 4: [0, 5], 5: [1]}) - sage: D.adjacency_matrix() + sage: D = DiGraph({0: [1, 2, 3], 1: [0, 2], 2: [3], + ....: 3: [4], 4: [0, 5], 5: [1]}) + sage: D.adjacency_matrix() # optional - sage.modules [0 1 1 1 0 0] [1 0 1 0 0 0] [0 0 0 1 0 0] @@ -1958,7 +1964,7 @@ def adjacency_matrix(self, sparse=None, vertices=None, *, base_ring=None, **kwds A different ordering of the vertices:: - sage: graphs.PathGraph(5).adjacency_matrix(vertices=[2, 4, 1, 3, 0]) + sage: graphs.PathGraph(5).adjacency_matrix(vertices=[2, 4, 1, 3, 0]) # optional - sage.modules [0 0 1 1 0] [0 0 0 1 0] [1 0 0 0 1] @@ -1967,18 +1973,19 @@ def adjacency_matrix(self, sparse=None, vertices=None, *, base_ring=None, **kwds A different base ring:: - sage: graphs.PathGraph(5).adjacency_matrix(base_ring=RDF) + sage: graphs.PathGraph(5).adjacency_matrix(base_ring=RDF) # optional - sage.modules [0.0 1.0 0.0 0.0 0.0] [1.0 0.0 1.0 0.0 0.0] [0.0 1.0 0.0 1.0 0.0] [0.0 0.0 1.0 0.0 1.0] [0.0 0.0 0.0 1.0 0.0] - sage: type(_) + sage: type(_) # optional - sage.modules A different matrix implementation:: - sage: graphs.PathGraph(5).adjacency_matrix(sparse=False, implementation='numpy') + sage: graphs.PathGraph(5).adjacency_matrix(sparse=False, # optional - sage.modules + ....: implementation='numpy') [0 1 0 0 0] [1 0 1 0 0] [0 1 0 1 0] @@ -1989,7 +1996,8 @@ def adjacency_matrix(self, sparse=None, vertices=None, *, base_ring=None, **kwds As an immutable matrix:: - sage: M = graphs.PathGraph(5).adjacency_matrix(sparse=False, immutable=True); M + sage: M = graphs.PathGraph(5).adjacency_matrix(sparse=False, # optional - sage.modules + ....: immutable=True); M [0 1 0 0 0] [1 0 1 0 0] [0 1 0 1 0] @@ -1998,21 +2006,23 @@ def adjacency_matrix(self, sparse=None, vertices=None, *, base_ring=None, **kwds sage: M[2, 2] = 1 Traceback (most recent call last): ... - ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M). + ValueError: matrix is immutable; please change a copy instead + (i.e., use copy(M) to change a copy of M). TESTS:: - sage: graphs.CubeGraph(8).adjacency_matrix().parent() + sage: graphs.CubeGraph(8).adjacency_matrix().parent() # optional - sage.modules Full MatrixSpace of 256 by 256 dense matrices over Integer Ring - sage: graphs.CubeGraph(9).adjacency_matrix().parent() + sage: graphs.CubeGraph(9).adjacency_matrix().parent() # optional - sage.modules Full MatrixSpace of 512 by 512 sparse matrices over Integer Ring - sage: Graph([(i,i+1) for i in range(500)]+[(0,1),], multiedges=True).adjacency_matrix().parent() + sage: Graph([(i, i+1) for i in range(500)] + [(0,1),], # optional - sage.modules + ....: multiedges=True).adjacency_matrix().parent() Full MatrixSpace of 501 by 501 dense matrices over Integer Ring - sage: graphs.PathGraph(5).adjacency_matrix(vertices=[0,0,0,0,0]) + sage: graphs.PathGraph(5).adjacency_matrix(vertices=[0,0,0,0,0]) # optional - sage.modules Traceback (most recent call last): ... ValueError: ``vertices`` must be a permutation of the vertices - sage: graphs.PathGraph(5).adjacency_matrix(vertices=[1,2,3]) + sage: graphs.PathGraph(5).adjacency_matrix(vertices=[1,2,3]) # optional - sage.modules Traceback (most recent call last): ... ValueError: ``vertices`` must be a permutation of the vertices @@ -2119,7 +2129,7 @@ def incidence_matrix(self, oriented=None, sparse=True, vertices=None, edges=None EXAMPLES:: sage: G = graphs.PetersenGraph() - sage: G.incidence_matrix() + sage: G.incidence_matrix() # optional - sage.modules [1 1 1 0 0 0 0 0 0 0 0 0 0 0 0] [1 0 0 1 1 0 0 0 0 0 0 0 0 0 0] [0 0 0 1 0 1 1 0 0 0 0 0 0 0 0] @@ -2130,7 +2140,7 @@ def incidence_matrix(self, oriented=None, sparse=True, vertices=None, edges=None [0 0 0 0 0 0 1 0 0 0 1 0 0 0 1] [0 0 0 0 0 0 0 0 1 0 0 1 1 0 0] [0 0 0 0 0 0 0 0 0 1 0 0 0 1 1] - sage: G.incidence_matrix(oriented=True) + sage: G.incidence_matrix(oriented=True) # optional - sage.modules [-1 -1 -1 0 0 0 0 0 0 0 0 0 0 0 0] [ 1 0 0 -1 -1 0 0 0 0 0 0 0 0 0 0] [ 0 0 0 1 0 -1 -1 0 0 0 0 0 0 0 0] @@ -2143,18 +2153,18 @@ def incidence_matrix(self, oriented=None, sparse=True, vertices=None, edges=None [ 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1] sage: G = digraphs.Circulant(4, [1, 3]) - sage: G.incidence_matrix() + sage: G.incidence_matrix() # optional - sage.modules [-1 -1 1 0 0 0 1 0] [ 1 0 -1 -1 1 0 0 0] [ 0 0 0 1 -1 -1 0 1] [ 0 1 0 0 0 1 -1 -1] - sage: graphs.CompleteGraph(3).incidence_matrix() + sage: graphs.CompleteGraph(3).incidence_matrix() # optional - sage.modules [1 1 0] [1 0 1] [0 1 1] sage: G = Graph([(0, 0), (0, 1), (0, 1)], loops=True, multiedges=True) - sage: G.incidence_matrix(oriented=False) + sage: G.incidence_matrix(oriented=False) # optional - sage.modules [2 1 1] [0 1 1] @@ -2163,30 +2173,30 @@ def incidence_matrix(self, oriented=None, sparse=True, vertices=None, edges=None Kirchhoff matrix:: sage: G = graphs.PetersenGraph() - sage: m = G.incidence_matrix(oriented=True) - sage: m * m.transpose() == G.kirchhoff_matrix() + sage: m = G.incidence_matrix(oriented=True) # optional - sage.modules + sage: m * m.transpose() == G.kirchhoff_matrix() # optional - sage.modules True sage: K = graphs.CompleteGraph(3) - sage: m = K.incidence_matrix(oriented=True) - sage: m * m.transpose() == K.kirchhoff_matrix() + sage: m = K.incidence_matrix(oriented=True) # optional - sage.modules + sage: m * m.transpose() == K.kirchhoff_matrix() # optional - sage.modules True sage: H = Graph([(0, 0), (0, 1), (0, 1)], loops=True, multiedges=True) - sage: m = H.incidence_matrix(oriented=True) - sage: m * m.transpose() == H.kirchhoff_matrix() + sage: m = H.incidence_matrix(oriented=True) # optional - sage.modules + sage: m * m.transpose() == H.kirchhoff_matrix() # optional - sage.modules True A different ordering of the vertices:: sage: P5 = graphs.PathGraph(5) - sage: P5.incidence_matrix() + sage: P5.incidence_matrix() # optional - sage.modules [1 0 0 0] [1 1 0 0] [0 1 1 0] [0 0 1 1] [0 0 0 1] - sage: P5.incidence_matrix(vertices=[2, 4, 1, 3, 0]) + sage: P5.incidence_matrix(vertices=[2, 4, 1, 3, 0]) # optional - sage.modules [0 1 1 0] [0 0 0 1] [1 1 0 0] @@ -2196,13 +2206,13 @@ def incidence_matrix(self, oriented=None, sparse=True, vertices=None, edges=None A different ordering of the edges:: sage: E = list(P5.edge_iterator(labels=False)) - sage: P5.incidence_matrix(edges=E[::-1]) + sage: P5.incidence_matrix(edges=E[::-1]) # optional - sage.modules [0 0 0 1] [0 0 1 1] [0 1 1 0] [1 1 0 0] [1 0 0 0] - sage: P5.incidence_matrix(vertices=[2, 4, 1, 3, 0], edges=E[::-1]) + sage: P5.incidence_matrix(vertices=[2, 4, 1, 3, 0], edges=E[::-1]) # optional - sage.modules [0 1 1 0] [1 0 0 0] [0 0 1 1] @@ -2211,7 +2221,7 @@ def incidence_matrix(self, oriented=None, sparse=True, vertices=None, edges=None A different base ring:: - sage: P5.incidence_matrix(base_ring=RDF) + sage: P5.incidence_matrix(base_ring=RDF) # optional - sage.modules [1.0 0.0 0.0 0.0] [1.0 1.0 0.0 0.0] [0.0 1.0 1.0 0.0] @@ -2220,29 +2230,30 @@ def incidence_matrix(self, oriented=None, sparse=True, vertices=None, edges=None Creating an immutable matrix:: - sage: m = P5.incidence_matrix(immutable=True); m + sage: m = P5.incidence_matrix(immutable=True); m # optional - sage.modules [1 0 0 0] [1 1 0 0] [0 1 1 0] [0 0 1 1] [0 0 0 1] - sage: m[1,2] = 1 + sage: m[1,2] = 1 # optional - sage.modules Traceback (most recent call last): ... - ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M). + ValueError: matrix is immutable; please change a copy instead + (i.e., use copy(M) to change a copy of M). TESTS:: sage: P5 = graphs.PathGraph(5) - sage: P5.incidence_matrix(vertices=[1] * P5.order()) + sage: P5.incidence_matrix(vertices=[1] * P5.order()) # optional - sage.modules Traceback (most recent call last): ... ValueError: ``vertices`` must be a permutation of the vertices - sage: P5.incidence_matrix(edges=[(0, 1)] * P5.size()) + sage: P5.incidence_matrix(edges=[(0, 1)] * P5.size()) # optional - sage.modules Traceback (most recent call last): ... ValueError: ``edges`` must be a permutation of the edges - sage: P5.incidence_matrix(edges=P5.edges(sort=False, labels=True)) + sage: P5.incidence_matrix(edges=P5.edges(sort=False, labels=True)) # optional - sage.modules [1 0 0 0] [1 1 0 0] [0 1 1 0] @@ -2331,19 +2342,19 @@ def distance_matrix(self, vertices=None, *, base_ring=None, **kwds): EXAMPLES:: sage: d = DiGraph({1: [2, 3], 2: [3], 3: [4], 4: [1]}) - sage: d.distance_matrix() + sage: d.distance_matrix() # optional - sage.modules [0 1 1 2] [3 0 1 2] [2 3 0 1] [1 2 2 0] - sage: d.distance_matrix(vertices=[4, 3, 2, 1]) + sage: d.distance_matrix(vertices=[4, 3, 2, 1]) # optional - sage.modules [0 2 2 1] [1 0 3 2] [2 1 0 3] [2 1 1 0] sage: G = graphs.CubeGraph(3) - sage: G.distance_matrix() + sage: G.distance_matrix() # optional - sage.modules [0 1 1 2 1 2 2 3] [1 0 2 1 2 1 3 2] [1 2 0 1 2 3 1 2] @@ -2357,7 +2368,8 @@ def distance_matrix(self, vertices=None, *, base_ring=None, **kwds): of the distance matrix of any tree of order `n` is `(-1)^{n-1}(n-1)2^{n-2}`:: - sage: all(T.distance_matrix().det() == (-1)^9*(9)*2^8 for T in graphs.trees(10)) + sage: all(T.distance_matrix().det() == (-1)^9*(9)*2^8 # optional - sage.modules + ....: for T in graphs.trees(10)) True .. SEEALSO:: @@ -2370,18 +2382,18 @@ def distance_matrix(self, vertices=None, *, base_ring=None, **kwds): Asking for an immutable matrix:: sage: G = Graph([(0, 1)]) - sage: G.distance_matrix().is_immutable() + sage: G.distance_matrix().is_immutable() # optional - sage.modules False - sage: G.distance_matrix(immutable=True).is_immutable() + sage: G.distance_matrix(immutable=True).is_immutable() # optional - sage.modules True Specifying a base ring:: sage: G = Graph([(0, 1)]) - sage: G.distance_matrix(vertices=[0, 1], base_ring=ZZ) + sage: G.distance_matrix(vertices=[0, 1], base_ring=ZZ) # optional - sage.modules [0 1] [1 0] - sage: G.distance_matrix(vertices=[0, 1], base_ring=RDF) + sage: G.distance_matrix(vertices=[0, 1], base_ring=RDF) # optional - sage.modules [0.0 1.0] [1.0 0.0] @@ -2389,7 +2401,7 @@ def distance_matrix(self, vertices=None, *, base_ring=None, **kwds): constructor:: sage: G = Graph([(0, 1)]) - sage: G.distance_matrix(vertices=[0, 1], weight_function=lambda e:2) + sage: G.distance_matrix(vertices=[0, 1], weight_function=lambda e:2) # optional - sage.modules [0 2] [2 0] """ @@ -2467,15 +2479,15 @@ def weighted_adjacency_matrix(self, sparse=True, vertices=None, sage: G = Graph(sparse=True, weighted=True) sage: G.add_edges([(0, 1, 1), (1, 2, 2), (0, 2, 3), (0, 3, 4)]) - sage: M = G.weighted_adjacency_matrix(); M + sage: M = G.weighted_adjacency_matrix(); M # optional - sage.modules [0 1 3 4] [1 0 2 0] [3 2 0 0] [4 0 0 0] - sage: H = Graph(data=M, format='weighted_adjacency_matrix', sparse=True) - sage: H == G + sage: H = Graph(data=M, format='weighted_adjacency_matrix', sparse=True) # optional - sage.modules + sage: H == G # optional - sage.modules True - sage: G.weighted_adjacency_matrix(vertices=[3, 2, 1, 0]) + sage: G.weighted_adjacency_matrix(vertices=[3, 2, 1, 0]) # optional - sage.modules [0 0 0 4] [0 0 2 3] [0 2 0 1] @@ -2483,7 +2495,8 @@ def weighted_adjacency_matrix(self, sparse=True, vertices=None, Using a different matrix implementation:: - sage: M = G.weighted_adjacency_matrix(sparse=False, base_ring=ZZ, implementation='numpy'); M + sage: M = G.weighted_adjacency_matrix(sparse=False, base_ring=ZZ, # optional - numpy sage.modules + ....: implementation='numpy'); M [0 1 3 4] [1 0 2 0] [3 2 0 0] @@ -2491,22 +2504,23 @@ def weighted_adjacency_matrix(self, sparse=True, vertices=None, As an immutable matrix:: - sage: M = G.weighted_adjacency_matrix(immutable=True); M + sage: M = G.weighted_adjacency_matrix(immutable=True); M # optional - sage.modules [0 1 3 4] [1 0 2 0] [3 2 0 0] [4 0 0 0] - sage: M[2, 2] = 1 + sage: M[2, 2] = 1 # optional - sage.modules Traceback (most recent call last): ... - ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M). + ValueError: matrix is immutable; please change a copy instead + (i.e., use copy(M) to change a copy of M). TESTS: The following doctest verifies that :trac:`4888` is fixed:: sage: G = DiGraph({0:{}, 1:{0:1}, 2:{0:1}}, weighted=True, sparse=True) - sage: G.weighted_adjacency_matrix() + sage: G.weighted_adjacency_matrix() # optional - sage.modules [0 0 0] [1 0 0] [1 0 0] @@ -2514,15 +2528,16 @@ def weighted_adjacency_matrix(self, sparse=True, vertices=None, Check error message for non numerical edge weights (:trac:`33562`):: sage: G = Graph([(0, 1)]) - sage: G.weighted_adjacency_matrix() + sage: G.weighted_adjacency_matrix() # optional - sage.modules Traceback (most recent call last): ... - ValueError: cannot find the weight of (0, 1, None). Consider setting parameter 'default_weight' - sage: G.weighted_adjacency_matrix(default_weight=3) + ValueError: cannot find the weight of (0, 1, None). + Consider setting parameter 'default_weight' + sage: G.weighted_adjacency_matrix(default_weight=3) # optional - sage.modules [0 3] [3 0] sage: G = Graph([(0, 1, 'a')]) - sage: G.weighted_adjacency_matrix() + sage: G.weighted_adjacency_matrix() # optional - sage.modules Traceback (most recent call last): ... TypeError: Cannot convert NoneType to sage.structure.parent.Parent @@ -2641,33 +2656,33 @@ def kirchhoff_matrix(self, weighted=None, indegree=True, normalized=False, signl sage: G = Graph(sparse=True) sage: G.add_edges([(0, 1, 1), (1, 2, 2), (0, 2, 3), (0, 3, 4)]) - sage: M = G.kirchhoff_matrix(weighted=True); M + sage: M = G.kirchhoff_matrix(weighted=True); M # optional - sage.modules [ 8 -1 -3 -4] [-1 3 -2 0] [-3 -2 5 0] [-4 0 0 4] - sage: M = G.kirchhoff_matrix(); M + sage: M = G.kirchhoff_matrix(); M # optional - sage.modules [ 3 -1 -1 -1] [-1 2 -1 0] [-1 -1 2 0] [-1 0 0 1] - sage: M = G.laplacian_matrix(normalized=True); M # optional - sage.symbolic + sage: M = G.laplacian_matrix(normalized=True); M # optional - sage.modules sage.symbolic [ 1 -1/6*sqrt(3)*sqrt(2) -1/6*sqrt(3)*sqrt(2) -1/3*sqrt(3)] [-1/6*sqrt(3)*sqrt(2) 1 -1/2 0] [-1/6*sqrt(3)*sqrt(2) -1/2 1 0] [ -1/3*sqrt(3) 0 0 1] - sage: M = G.kirchhoff_matrix(weighted=True, signless=True); M + sage: M = G.kirchhoff_matrix(weighted=True, signless=True); M # optional - sage.modules [8 1 3 4] [1 3 2 0] [3 2 5 0] [4 0 0 4] sage: G = Graph({0: [], 1: [2]}) - sage: G.laplacian_matrix(normalized=True) + sage: G.laplacian_matrix(normalized=True) # optional - sage.modules [ 0 0 0] [ 0 1 -1] [ 0 -1 1] - sage: G.laplacian_matrix(normalized=True,signless=True) + sage: G.laplacian_matrix(normalized=True, signless=True) # optional - sage.modules [0 0 0] [0 1 1] [0 1 1] @@ -2675,14 +2690,14 @@ def kirchhoff_matrix(self, weighted=None, indegree=True, normalized=False, signl A weighted directed graph with loops, changing the variable ``indegree`` :: sage: G = DiGraph({1: {1: 2, 2: 3}, 2: {1: 4}}, weighted=True, sparse=True) - sage: G.laplacian_matrix() + sage: G.laplacian_matrix() # optional - sage.modules [ 4 -3] [-4 3] :: sage: G = DiGraph({1: {1: 2, 2: 3}, 2: {1: 4}}, weighted=True, sparse=True) - sage: G.laplacian_matrix(indegree=False) + sage: G.laplacian_matrix(indegree=False) # optional - sage.modules [ 3 -3] [-4 4] @@ -2691,12 +2706,12 @@ def kirchhoff_matrix(self, weighted=None, indegree=True, normalized=False, signl sage: G = Graph(sparse=True) sage: G.add_edges([(0, 1, 1), (1, 2, 2), (0, 2, 3), (0, 3, 4)]) - sage: M = G.kirchhoff_matrix(vertices=[3, 2, 1, 0]); M + sage: M = G.kirchhoff_matrix(vertices=[3, 2, 1, 0]); M # optional - sage.modules [ 1 0 0 -1] [ 0 2 -1 -1] [ 0 -1 2 -1] [-1 -1 -1 3] - sage: M = G.kirchhoff_matrix(weighted=True, vertices=[3, 2, 1, 0]); M + sage: M = G.kirchhoff_matrix(weighted=True, vertices=[3, 2, 1, 0]); M # optional - sage.modules [ 4 0 0 -4] [ 0 5 -2 -3] [ 0 -2 3 -1] @@ -2706,8 +2721,8 @@ def kirchhoff_matrix(self, weighted=None, indegree=True, normalized=False, signl immutable:: sage: G = Graph([(0, 1)]) - sage: M = G.kirchhoff_matrix(vertices=[0, 1], immutable=True) - sage: M.is_immutable() + sage: M = G.kirchhoff_matrix(vertices=[0, 1], immutable=True) # optional - sage.modules + sage: M.is_immutable() # optional - sage.modules True """ from sage.matrix.constructor import diagonal_matrix @@ -3959,21 +3974,21 @@ def antisymmetric(self): A directed acyclic graph is antisymmetric:: - sage: G = digraphs.RandomDirectedGNR(20, 0.5) - sage: G.antisymmetric() + sage: G = digraphs.RandomDirectedGNR(20, 0.5) # optional - networkx + sage: G.antisymmetric() # optional - networkx True Loops are allowed:: - sage: G.allow_loops(True) - sage: G.add_edge(0, 0) - sage: G.antisymmetric() + sage: G.allow_loops(True) # optional - networkx + sage: G.add_edge(0, 0) # optional - networkx + sage: G.antisymmetric() # optional - networkx True An undirected graph is never antisymmetric unless it is just a union of isolated vertices (with possible loops):: - sage: graphs.RandomGNP(20, 0.5).antisymmetric() + sage: graphs.RandomGNP(20, 0.5).antisymmetric() # optional - networkx False sage: Graph(3).antisymmetric() True @@ -4055,7 +4070,7 @@ def is_bipartite(self, certificate=False): True sage: graphs.CycleGraph(5).is_bipartite() False - sage: graphs.RandomBipartite(10, 10, 0.7).is_bipartite() + sage: graphs.RandomBipartite(10, 10, 0.7).is_bipartite() # optional - numpy True A random graph is very rarely bipartite:: @@ -4659,37 +4674,45 @@ def min_spanning_tree(self, sage: weight = lambda e: 1 / ((e[0] + 1) * (e[1] + 1)) sage: sorted(g.min_spanning_tree(weight_function=weight)) [(0, 4, None), (1, 4, None), (2, 4, None), (3, 4, None)] - sage: sorted(g.min_spanning_tree(weight_function=weight, algorithm='Kruskal_Boost')) + sage: sorted(g.min_spanning_tree(weight_function=weight, + ....: algorithm='Kruskal_Boost')) [(0, 4, None), (1, 4, None), (2, 4, None), (3, 4, None)] sage: g = graphs.PetersenGraph() sage: g.allow_multiple_edges(True) sage: g.add_edges(g.edge_iterator()) sage: sorted(g.min_spanning_tree()) - [(0, 1, None), (0, 4, None), (0, 5, None), (1, 2, None), (1, 6, None), (3, 8, None), (5, 7, None), (5, 8, None), (6, 9, None)] + [(0, 1, None), (0, 4, None), (0, 5, None), (1, 2, None), (1, 6, None), + (3, 8, None), (5, 7, None), (5, 8, None), (6, 9, None)] Boruvka's algorithm:: sage: sorted(g.min_spanning_tree(algorithm='Boruvka')) - [(0, 1, None), (0, 4, None), (0, 5, None), (1, 2, None), (1, 6, None), (2, 3, None), (2, 7, None), (3, 8, None), (4, 9, None)] + [(0, 1, None), (0, 4, None), (0, 5, None), (1, 2, None), (1, 6, None), + (2, 3, None), (2, 7, None), (3, 8, None), (4, 9, None)] Prim's algorithm:: sage: g = graphs.CompleteGraph(5) - sage: sorted(g.min_spanning_tree(algorithm='Prim_edge', starting_vertex=2, weight_function=weight)) + sage: sorted(g.min_spanning_tree(algorithm='Prim_edge', + ....: starting_vertex=2, weight_function=weight)) [(0, 4, None), (1, 4, None), (2, 4, None), (3, 4, None)] - sage: sorted(g.min_spanning_tree(algorithm='Prim_fringe', starting_vertex=2, weight_function=weight)) + sage: sorted(g.min_spanning_tree(algorithm='Prim_fringe', + ....: starting_vertex=2, weight_function=weight)) [(0, 4, None), (1, 4, None), (2, 4, None), (3, 4, None)] - sage: sorted(g.min_spanning_tree(weight_function=weight, algorithm='Prim_Boost')) + sage: sorted(g.min_spanning_tree(weight_function=weight, + ....: algorithm='Prim_Boost')) [(0, 4, None), (1, 4, None), (2, 4, None), (3, 4, None)] NetworkX algorithm:: - sage: sorted(g.min_spanning_tree(algorithm='NetworkX')) + sage: sorted(g.min_spanning_tree(algorithm='NetworkX')) # optional - networkx [(0, 1, None), (0, 2, None), (0, 3, None), (0, 4, None)] More complicated weights:: - sage: G = Graph([(0,1,{'name':'a','weight':1}), (0,2,{'name':'b','weight':3}), (1,2,{'name':'b','weight':1})]) + sage: G = Graph([(0, 1, {'name': 'a', 'weight': 1}), + ....: (0, 2, {'name': 'b', 'weight': 3}), + ....: (1, 2, {'name': 'b', 'weight': 1})]) sage: sorted(G.min_spanning_tree(weight_function=lambda e: e[2]['weight'])) [(0, 1, {'name': 'a', 'weight': 1}), (1, 2, {'name': 'b', 'weight': 1})] @@ -4733,7 +4756,7 @@ def min_spanning_tree(self, [(0, 1, 1), (1, 2, 1)] sage: sorted(g.min_spanning_tree(algorithm='Prim_Boost')) [(0, 1, 1), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='NetworkX')) + sage: sorted(g.min_spanning_tree(algorithm='NetworkX')) # optional - networkx [(0, 1, 1), (1, 2, 1)] sage: sorted(g.min_spanning_tree(algorithm='Boruvka')) [(0, 1, 1), (1, 2, 1)] @@ -4755,7 +4778,7 @@ def min_spanning_tree(self, [(0, 2, 10), (1, 2, 1)] sage: sorted(g.min_spanning_tree(algorithm='Prim_Boost', weight_function=weight)) [(0, 2, 10), (1, 2, 1)] - sage: sorted(g.min_spanning_tree(algorithm='NetworkX', weight_function=weight)) + sage: sorted(g.min_spanning_tree(algorithm='NetworkX', weight_function=weight)) # optional - networkx [(0, 2, 10), (1, 2, 1)] sage: sorted(g.min_spanning_tree(algorithm='Boruvka', weight_function=weight)) [(0, 2, 10), (1, 2, 1)] @@ -4954,13 +4977,13 @@ def spanning_trees_count(self, root_vertex=None): :: - sage: M = matrix(3, 3, [0, 1, 0, 0, 0, 1, 1, 1, 0]) - sage: D = DiGraph(M) - sage: D.spanning_trees_count() + sage: M = matrix(3, 3, [0, 1, 0, 0, 0, 1, 1, 1, 0]) # optional - sage.modules + sage: D = DiGraph(M) # optional - sage.modules + sage: D.spanning_trees_count() # optional - sage.modules 1 - sage: D.spanning_trees_count(0) + sage: D.spanning_trees_count(0) # optional - sage.modules 1 - sage: D.spanning_trees_count(2) + sage: D.spanning_trees_count(2) # optional - sage.modules 2 """ if not self.order(): @@ -5018,33 +5041,35 @@ def cycle_basis(self, output='vertex'): A cycle basis in Petersen's Graph :: sage: g = graphs.PetersenGraph() - sage: g.cycle_basis() - [[1, 6, 8, 5, 0], [4, 9, 6, 8, 5, 0], [7, 9, 6, 8, 5], [4, 3, 8, 5, 0], [1, 2, 3, 8, 5, 0], [7, 2, 3, 8, 5]] + sage: g.cycle_basis() # optional - networkx + [[1, 6, 8, 5, 0], [4, 9, 6, 8, 5, 0], [7, 9, 6, 8, 5], + [4, 3, 8, 5, 0], [1, 2, 3, 8, 5, 0], [7, 2, 3, 8, 5]] One can also get the result as a list of lists of edges:: - sage: g.cycle_basis(output='edge') + sage: g.cycle_basis(output='edge') # optional - networkx [[(1, 6, None), (6, 8, None), (8, 5, None), (5, 0, None), - (0, 1, None)], [(4, 9, None), (9, 6, None), (6, 8, None), - (8, 5, None), (5, 0, None), (0, 4, None)], [(7, 9, None), - (9, 6, None), (6, 8, None), (8, 5, None), (5, 7, None)], - [(4, 3, None), (3, 8, None), (8, 5, None), (5, 0, None), - (0, 4, None)], [(1, 2, None), (2, 3, None), (3, 8, None), - (8, 5, None), (5, 0, None), (0, 1, None)], [(7, 2, None), - (2, 3, None), (3, 8, None), (8, 5, None), (5, 7, None)]] + (0, 1, None)], [(4, 9, None), (9, 6, None), (6, 8, None), + (8, 5, None), (5, 0, None), (0, 4, None)], [(7, 9, None), + (9, 6, None), (6, 8, None), (8, 5, None), (5, 7, None)], + [(4, 3, None), (3, 8, None), (8, 5, None), (5, 0, None), + (0, 4, None)], [(1, 2, None), (2, 3, None), (3, 8, None), + (8, 5, None), (5, 0, None), (0, 1, None)], [(7, 2, None), + (2, 3, None), (3, 8, None), (8, 5, None), (5, 7, None)]] Checking the given cycles are algebraically free:: - sage: g = graphs.RandomGNP(30, .4) - sage: basis = g.cycle_basis() + sage: g = graphs.RandomGNP(30, .4) # optional - networkx + sage: basis = g.cycle_basis() # optional - networkx Building the space of (directed) edges over `Z/2Z`. On the way, building a dictionary associating a unique vector to each undirected edge:: sage: m = g.size() - sage: edge_space = VectorSpace(FiniteField(2), m) - sage: edge_vector = dict(zip(g.edges(labels=False, sort=False), edge_space.basis())) - sage: for (u, v), vec in list(edge_vector.items()): + sage: edge_space = VectorSpace(FiniteField(2), m) # optional - sage.modules sage.rings.finite_rings + sage: edge_vector = dict(zip(g.edges(labels=False, sort=False), # optional - sage.modules sage.rings.finite_rings + ....: edge_space.basis())) + sage: for (u, v), vec in list(edge_vector.items()): # optional - sage.modules sage.rings.finite_rings ....: edge_vector[(v, u)] = vec Defining a lambda function associating a vector to the vertices of a @@ -5055,27 +5080,29 @@ def cycle_basis(self, output='vertex'): Finally checking the cycles are a free set:: - sage: basis_as_vectors = [cycle_to_vector(_) for _ in basis] - sage: edge_space.span(basis_as_vectors).rank() == len(basis) + sage: basis_as_vectors = [cycle_to_vector(_) for _ in basis] # optional - sage.modules sage.rings.finite_rings + sage: edge_space.span(basis_as_vectors).rank() == len(basis) # optional - sage.modules sage.rings.finite_rings True For undirected graphs with multiple edges:: - sage: G = Graph([(0, 2, 'a'), (0, 2, 'b'), (0, 1, 'c'), (1, 2, 'd')], multiedges=True) - sage: G.cycle_basis() + sage: G = Graph([(0, 2, 'a'), (0, 2, 'b'), (0, 1, 'c'), (1, 2, 'd')], + ....: multiedges=True) + sage: G.cycle_basis() # optional - networkx [[0, 2], [2, 1, 0]] - sage: G.cycle_basis(output='edge') + sage: G.cycle_basis(output='edge') # optional - networkx [[(0, 2, 'a'), (2, 0, 'b')], [(2, 1, 'd'), (1, 0, 'c'), (0, 2, 'a')]] - sage: H = Graph([(1, 2), (2, 3), (2, 3), (3, 4), (1, 4), (1, 4), (4, 5), (5, 6), (4, 6), (6, 7)], multiedges=True) - sage: H.cycle_basis() + sage: H = Graph([(1, 2), (2, 3), (2, 3), (3, 4), (1, 4), + ....: (1, 4), (4, 5), (5, 6), (4, 6), (6, 7)], multiedges=True) + sage: H.cycle_basis() # optional - networkx [[1, 4], [2, 3], [4, 3, 2, 1], [6, 5, 4]] Disconnected graph:: sage: G.add_cycle(["Hey", "Wuuhuu", "Really ?"]) - sage: [sorted(c) for c in G.cycle_basis()] + sage: [sorted(c) for c in G.cycle_basis()] # optional - networkx [['Hey', 'Really ?', 'Wuuhuu'], [0, 2], [0, 1, 2]] - sage: [sorted(c) for c in G.cycle_basis(output='edge')] + sage: [sorted(c) for c in G.cycle_basis(output='edge')] # optional - networkx [[('Hey', 'Wuuhuu', None), ('Really ?', 'Hey', None), ('Wuuhuu', 'Really ?', None)], @@ -5086,13 +5113,13 @@ def cycle_basis(self, output='vertex'): sage: G = graphs.CycleGraph(3) sage: G.allow_multiple_edges(True) - sage: G.cycle_basis() + sage: G.cycle_basis() # optional - networkx [[2, 1, 0]] Not yet implemented for directed graphs:: sage: G = DiGraph([(0, 2, 'a'), (0, 1, 'c'), (1, 2, 'd')]) - sage: G.cycle_basis() + sage: G.cycle_basis() # optional - networkx Traceback (most recent call last): ... NotImplementedError: not implemented for directed graphs @@ -5101,10 +5128,11 @@ def cycle_basis(self, output='vertex'): :trac:`27538`:: - sage: G= Graph([(1, 2, 'a'), (2, 3, 'b'), (2, 3, 'c'), (3, 4, 'd'), (3, 4, 'e'), (4, 1, 'f')], multiedges=True) - sage: G.cycle_basis() + sage: G = Graph([(1, 2, 'a'), (2, 3, 'b'), (2, 3, 'c'), + ....: (3, 4, 'd'), (3, 4, 'e'), (4, 1, 'f')], multiedges=True) + sage: G.cycle_basis() # optional - networkx [[2, 3], [4, 3, 2, 1], [4, 3, 2, 1]] - sage: G.cycle_basis(output='edge') + sage: G.cycle_basis(output='edge') # optional - networkx [[(2, 3, 'b'), (3, 2, 'c')], [(4, 3, 'd'), (3, 2, 'b'), (2, 1, 'a'), (1, 4, 'f')], [(4, 3, 'e'), (3, 2, 'b'), (2, 1, 'a'), (1, 4, 'f')]] @@ -5179,14 +5207,15 @@ def minimum_cycle_basis(self, algorithm=None, weight_function=None, by_weight=Fa EXAMPLES:: - sage: g = Graph([(1, 2, 3), (2, 3, 5), (3, 4, 8), (4, 1, 13), (1, 3, 250), (5, 6, 9), (6, 7, 17), (7, 5, 20)]) + sage: g = Graph([(1, 2, 3), (2, 3, 5), (3, 4, 8), (4, 1, 13), + ....: (1, 3, 250), (5, 6, 9), (6, 7, 17), (7, 5, 20)]) sage: sorted(g.minimum_cycle_basis(by_weight=True)) [[1, 2, 3], [1, 2, 3, 4], [5, 6, 7]] sage: sorted(g.minimum_cycle_basis(by_weight=False)) [[1, 2, 3], [1, 3, 4], [5, 6, 7]] - sage: sorted(g.minimum_cycle_basis(by_weight=True, algorithm='NetworkX')) + sage: sorted(g.minimum_cycle_basis(by_weight=True, algorithm='NetworkX')) # optional - networkx [[1, 2, 3], [1, 2, 3, 4], [5, 6, 7]] - sage: g.minimum_cycle_basis(by_weight=False, algorithm='NetworkX') + sage: g.minimum_cycle_basis(by_weight=False, algorithm='NetworkX') # optional - networkx [[1, 2, 3], [1, 3, 4], [5, 6, 7]] :: @@ -5194,7 +5223,7 @@ def minimum_cycle_basis(self, algorithm=None, weight_function=None, by_weight=Fa sage: g = Graph([(1, 2), (2, 3), (3, 4), (4, 5), (5, 1), (5, 3)]) sage: sorted(g.minimum_cycle_basis(by_weight=False)) [[1, 2, 3, 5], [3, 4, 5]] - sage: sorted(g.minimum_cycle_basis(by_weight=False, algorithm='NetworkX')) + sage: sorted(g.minimum_cycle_basis(by_weight=False, algorithm='NetworkX')) # optional - networkx [[1, 2, 3, 5], [3, 4, 5]] TESTS:: @@ -5323,7 +5352,7 @@ def is_planar(self, on_embedding=None, kuratowski=False, set_embedding=False, se :: sage: g = graphs.PetersenGraph() - sage: (g.is_planar(kuratowski=True))[1].adjacency_matrix() + sage: (g.is_planar(kuratowski=True))[1].adjacency_matrix() # optional - sage.modules [0 1 0 0 0 1 0 0 0] [1 0 1 0 0 0 1 0 0] [0 1 0 1 0 0 0 1 0] @@ -5350,15 +5379,18 @@ def is_planar(self, on_embedding=None, kuratowski=False, set_embedding=False, se sage: G.is_planar(on_embedding={}) Traceback (most recent call last): ... - NotImplementedError: cannot compute with embeddings of multiple-edged or looped graphs + NotImplementedError: cannot compute with embeddings of + multiple-edged or looped graphs sage: G.is_planar(set_pos=True) Traceback (most recent call last): ... - NotImplementedError: cannot compute with embeddings of multiple-edged or looped graphs + NotImplementedError: cannot compute with embeddings of + multiple-edged or looped graphs sage: G.is_planar(set_embedding=True) Traceback (most recent call last): ... - NotImplementedError: cannot compute with embeddings of multiple-edged or looped graphs + NotImplementedError: cannot compute with embeddings of + multiple-edged or looped graphs sage: G.is_planar(kuratowski=True) (True, None) @@ -5699,11 +5731,11 @@ def layout_planar(self, set_embedding=False, on_embedding=None, 7: [2, 4], 8: [1, 6], 9: [2, 5]} - sage: g = graphs.BalancedTree(3, 4) - sage: pos = g.layout(layout='planar', save_pos=True, test=True) - sage: pos[0] + sage: g = graphs.BalancedTree(3, 4) # optional - networkx + sage: pos = g.layout(layout='planar', save_pos=True, test=True) # optional - networkx + sage: pos[0] # optional - networkx [0, 119] - sage: pos[120] + sage: pos[120] # optional - networkx [21, 37] sage: g = graphs.CycleGraph(7) sage: g.layout(layout='planar', save_pos=True, test=True) @@ -5725,20 +5757,21 @@ def layout_planar(self, set_embedding=False, on_embedding=None, Choose the embedding:: sage: H = graphs.LadderGraph(4) - sage: em = {0:[1,4], 4:[0,5], 1:[5,2,0], 5:[4,6,1], 2:[1,3,6], 6:[7,5,2], 3:[7,2], 7:[3,6]} + sage: em = {0:[1,4], 4:[0,5], 1:[5,2,0], 5:[4,6,1], + ....: 2:[1,3,6], 6:[7,5,2], 3:[7,2], 7:[3,6]} sage: p = H.layout_planar(on_embedding=em) - sage: p # random + sage: p # random {2: [8.121320343559642, 1], - 3: [2.1213203435596424, 6], - 7: [3.1213203435596424, 0], - 0: [5.121320343559642, 3], - 1: [3.1213203435596424, 5], - 4: [4.121320343559642, 3], - 5: [4.121320343559642, 2], - 6: [3.1213203435596424, 1], - 9: [9.698670612749268, 1], - 8: [8.698670612749268, 1], - 10: [9.698670612749268, 0]} + 3: [2.1213203435596424, 6], + 7: [3.1213203435596424, 0], + 0: [5.121320343559642, 3], + 1: [3.1213203435596424, 5], + 4: [4.121320343559642, 3], + 5: [4.121320343559642, 2], + 6: [3.1213203435596424, 1], + 9: [9.698670612749268, 1], + 8: [8.698670612749268, 1], + 10: [9.698670612749268, 0]} TESTS:: @@ -5746,7 +5779,8 @@ def layout_planar(self, set_embedding=False, on_embedding=None, sage: G.layout(layout='planar', external_face=(1, 2)) Traceback (most recent call last): ... - ValueError: (1, 2) is not an edge of Graph on 4 vertices but has been provided as an edge of the external face + ValueError: (1, 2) is not an edge of Graph on 4 vertices + but has been provided as an edge of the external face Check the dependence of the computed position on the given combinatorial embedding (:trac:`28152`):: @@ -10127,12 +10161,14 @@ def _build_flow_graph(self, flow, integer): The method removes zero-cost flow cycles and updates the values accordingly:: - sage: g = digraphs.DeBruijn(2,3) - sage: flow = {('001', '010'): 1, ('010', '100'): 1, ('010', '101'): 1, ('101', '010'): 1} + sage: g = digraphs.DeBruijn(2,3) # optional - sage.combinat + sage: flow = {('001', '010'): 1, ('010', '100'): 1, + ....: ('010', '101'): 1, ('101', '010'): 1} sage: flow_graph = g._build_flow_graph(flow, True) sage: flow_graph.edges(sort=True) [('001', '010', 1), ('010', '100', 1)] - sage: flow = {('001', '010'): 2, ('010', '101'): 3, ('101', '011'): 2, ('101', '010'): 1} + sage: flow = {('001', '010'): 2, ('010', '101'): 3, + ....: ('101', '011'): 2, ('101', '010'): 1} sage: flow_graph = g._build_flow_graph(flow, True) sage: flow_graph.edges(sort=True) [('001', '010', 2), ('010', '101', 2), ('101', '011', 2)] @@ -10444,54 +10480,55 @@ def pagerank(self, alpha=0.85, personalization=None, by_weight=False, EXAMPLES:: sage: G = graphs.CycleGraph(4) - sage: G.pagerank(algorithm="Networkx") + sage: G.pagerank(algorithm="Networkx") # optional - networkx {0: 0.25, 1: 0.25, 2: 0.25, 3: 0.25} - sage: G.pagerank(alpha=0.50, algorithm="igraph") # optional - python_igraph # abs tol 1e-9 + sage: G.pagerank(alpha=0.50, algorithm="igraph") # abs tol 1e-9, optional - python_igraph {0: 0.25, 1: 0.25, 2: 0.25, 3: 0.25} - sage: G = Graph([(1, 2, 40), (2, 3, 50), (3, 4, 60), (1, 4, 70), (4, 5, 80), (5, 6, 20)]) - sage: G.pagerank(algorithm="NetworkX") # abs tol 1e-9 + sage: G = Graph([(1, 2, 40), (2, 3, 50), (3, 4, 60), + ....: (1, 4, 70), (4, 5, 80), (5, 6, 20)]) + sage: G.pagerank(algorithm="NetworkX") # abs tol 1e-9 # optional - networkx {1: 0.16112205885619563, 2: 0.1619531043247219, 3: 0.16112205885619563, 4: 0.2374999999999999, 5: 0.17775588228760858, 6: 0.100546895675278} - sage: G.pagerank(algorithm="NetworkX", by_weight=True) # abs tol 1e-9 + sage: G.pagerank(algorithm="NetworkX", by_weight=True) # abs tol 1e-9 # optional - networkx {1: 0.16459583718588994, 2: 0.13977928595154515, 3: 0.16539840184339605, 4: 0.3063198690713853, 5: 0.1700057609707141, 6: 0.05390084497706962} - sage: G.pagerank(algorithm="Scipy") # abs tol 1e-9 + sage: G.pagerank(algorithm="Scipy") # abs tol 1e-9 # optional - scipy {1: 0.16112205885619563, 2: 0.1619531043247219, 3: 0.16112205885619563, 4: 0.2374999999999999, 5: 0.17775588228760858, 6: 0.100546895675278} - sage: G.pagerank(algorithm="Scipy", by_weight=True) # abs tol 1e-9 + sage: G.pagerank(algorithm="Scipy", by_weight=True) # abs tol 1e-9 # optional - scipy {1: 0.16459583718588994, 2: 0.13977928595154515, 3: 0.16539840184339605, 4: 0.3063198690713853, 5: 0.1700057609707141, 6: 0.05390084497706962} - sage: G.pagerank(algorithm="igraph") # optional - python_igraph # abs tol 1e-9 + sage: G.pagerank(algorithm="igraph") # abs tol 1e-9, optional - python_igraph {1: 0.16112198303979128, 2: 0.16195368558382262, 3: 0.16112198303979125, 4: 0.23749999999999993, 5: 0.17775603392041744, 6: 0.10054631441617742} - sage: G.pagerank() # abs tol 1e-9 + sage: G.pagerank() # abs tol 1e-9 {1: 0.16112205885619563, 2: 0.1619531043247219, 3: 0.16112205885619563, 4: 0.2374999999999999, 5: 0.17775588228760858, 6: 0.100546895675278} - sage: G.pagerank(by_weight=True) # abs tol 1e-9 + sage: G.pagerank(by_weight=True) # abs tol 1e-9 {1: 0.16459583718588994, 2: 0.13977928595154515, 3: 0.16539840184339605, @@ -10502,7 +10539,8 @@ def pagerank(self, alpha=0.85, personalization=None, by_weight=False, TESTS:: sage: G = Graph([(1, 2), (2, 3), (3, 4), (1, 3)]) - sage: G.pagerank(algorithm="NetworkX", personalization={1:0, 2:3, 3:-2, 4:-1}) + sage: G.pagerank(algorithm="NetworkX", # optional - networkx + ....: personalization={1:0, 2:3, 3:-2, 4:-1}) Traceback (most recent call last): ... ZeroDivisionError... @@ -12941,13 +12979,13 @@ def degree(self, vertices=None, labels=False): returned list is the degree of the `i`-th vertex in the list ``list(self)``:: - sage: D = digraphs.DeBruijn(4, 2) - sage: D.delete_vertex('20') - sage: print(D.degree()) + sage: D = digraphs.DeBruijn(4, 2) # optional - sage.combinat + sage: D.delete_vertex('20') # optional - sage.combinat + sage: print(D.degree()) # optional - sage.combinat [7, 7, 6, 7, 8, 8, 7, 8, 8, 7, 8, 8, 8, 7, 8] - sage: print(D.degree(vertices=list(D))) + sage: print(D.degree(vertices=list(D))) # optional - sage.combinat [7, 7, 6, 7, 8, 8, 7, 8, 8, 7, 8, 8, 8, 7, 8] - sage: print(D.degree(vertices=D.vertices(sort=False))) + sage: print(D.degree(vertices=D.vertices(sort=False))) # optional - sage.combinat [7, 7, 6, 7, 8, 8, 7, 8, 8, 7, 8, 8, 8, 7, 8] """ if labels: @@ -13085,11 +13123,11 @@ def degree_iterator(self, vertices=None, labels=False): When ``vertices=None`` yields values in the order of ``list(D)``:: sage: V = list(D) - sage: D = digraphs.DeBruijn(4, 2) - sage: D.delete_vertex('20') - sage: print(list(D.degree_iterator())) + sage: D = digraphs.DeBruijn(4, 2) # optional - sage.combinat + sage: D.delete_vertex('20') # optional - sage.combinat + sage: print(list(D.degree_iterator())) # optional - sage.combinat [7, 7, 6, 7, 8, 8, 7, 8, 8, 7, 8, 8, 8, 7, 8] - sage: print([D.degree(v) for v in D]) + sage: print([D.degree(v) for v in D]) # optional - sage.combinat [7, 7, 6, 7, 8, 8, 7, 8, 8, 7, 8, 8, 8, 7, 8] """ if vertices is None: @@ -13720,99 +13758,99 @@ def subgraph_search(self, G, induced=False): The Petersen graph contains the path graph `P_5`:: sage: g = graphs.PetersenGraph() - sage: h1 = g.subgraph_search(graphs.PathGraph(5)); h1 + sage: h1 = g.subgraph_search(graphs.PathGraph(5)); h1 # optional - sage.modules Subgraph of (Petersen graph): Graph on 5 vertices - sage: h1.vertices(sort=True); h1.edges(sort=True, labels=False) + sage: h1.vertices(sort=True); h1.edges(sort=True, labels=False) # optional - sage.modules [0, 1, 2, 3, 4] [(0, 1), (1, 2), (2, 3), (3, 4)] - sage: I1 = g.subgraph_search(graphs.PathGraph(5), induced=True); I1 + sage: I1 = g.subgraph_search(graphs.PathGraph(5), induced=True); I1 # optional - sage.modules Subgraph of (Petersen graph): Graph on 5 vertices - sage: I1.vertices(sort=True); I1.edges(sort=True, labels=False) + sage: I1.vertices(sort=True); I1.edges(sort=True, labels=False) # optional - sage.modules [0, 1, 2, 3, 8] [(0, 1), (1, 2), (2, 3), (3, 8)] It also contains the claw `K_{1,3}`:: - sage: h2 = g.subgraph_search(graphs.ClawGraph()); h2 + sage: h2 = g.subgraph_search(graphs.ClawGraph()); h2 # optional - sage.modules Subgraph of (Petersen graph): Graph on 4 vertices - sage: h2.vertices(sort=True); h2.edges(sort=True, labels=False) + sage: h2.vertices(sort=True); h2.edges(sort=True, labels=False) # optional - sage.modules [0, 1, 4, 5] [(0, 1), (0, 4), (0, 5)] - sage: I2 = g.subgraph_search(graphs.ClawGraph(), induced=True); I2 + sage: I2 = g.subgraph_search(graphs.ClawGraph(), induced=True); I2 # optional - sage.modules Subgraph of (Petersen graph): Graph on 4 vertices - sage: I2.vertices(sort=True); I2.edges(sort=True, labels=False) + sage: I2.vertices(sort=True); I2.edges(sort=True, labels=False) # optional - sage.modules [0, 1, 4, 5] [(0, 1), (0, 4), (0, 5)] Of course the induced copies are isomorphic to the graphs we were looking for:: - sage: I1.is_isomorphic(graphs.PathGraph(5)) + sage: I1.is_isomorphic(graphs.PathGraph(5)) # optional - sage.modules True - sage: I2.is_isomorphic(graphs.ClawGraph()) + sage: I2.is_isomorphic(graphs.ClawGraph()) # optional - sage.modules True However, the Petersen graph does not contain a subgraph isomorphic to `K_3`:: - sage: g.subgraph_search(graphs.CompleteGraph(3)) is None + sage: g.subgraph_search(graphs.CompleteGraph(3)) is None # optional - sage.modules True Nor does it contain a nonempty induced subgraph isomorphic to `P_6`:: - sage: g.subgraph_search(graphs.PathGraph(6), induced=True) is None + sage: g.subgraph_search(graphs.PathGraph(6), induced=True) is None # optional - sage.modules True The empty graph is a subgraph of every graph:: - sage: g.subgraph_search(graphs.EmptyGraph()) + sage: g.subgraph_search(graphs.EmptyGraph()) # optional - sage.modules Graph on 0 vertices - sage: g.subgraph_search(graphs.EmptyGraph(), induced=True) + sage: g.subgraph_search(graphs.EmptyGraph(), induced=True) # optional - sage.modules Graph on 0 vertices The subgraph may just have edges missing:: sage: k3 = graphs.CompleteGraph(3); p3 = graphs.PathGraph(3) sage: k3.relabel(list('abc')) - sage: s = k3.subgraph_search(p3) - sage: s.edges(sort=True, labels=False) + sage: s = k3.subgraph_search(p3) # optional - sage.modules + sage: s.edges(sort=True, labels=False) # optional - sage.modules [('a', 'b'), ('b', 'c')] Of course, `P_3` is not an induced subgraph of `K_3`, though:: sage: k3 = graphs.CompleteGraph(3); p3 = graphs.PathGraph(3) sage: k3.relabel(list('abc')) - sage: k3.subgraph_search(p3, induced=True) is None + sage: k3.subgraph_search(p3, induced=True) is None # optional - sage.modules True If the graph has labels, the labels are just ignored:: sage: g.set_vertex(0, 'foo') - sage: c = g.subgraph_search(graphs.PathGraph(5)) - sage: c.get_vertices() + sage: c = g.subgraph_search(graphs.PathGraph(5)) # optional - sage.modules + sage: c.get_vertices() # optional - sage.modules {0: 'foo', 1: None, 2: None, 3: None, 4: None} TESTS: Inside of a small graph (:trac:`13906`):: - sage: Graph(5).subgraph_search(Graph(1)) + sage: Graph(5).subgraph_search(Graph(1)) # optional - sage.modules Graph on 1 vertex For labelled edges (:trac:`14999`):: sage: G = graphs.CompleteGraph(10) - sage: C = G.subgraph_search(graphs.CycleGraph(4)) - sage: C.size() + sage: C = G.subgraph_search(graphs.CycleGraph(4)) # optional - sage.modules + sage: C.size() # optional - sage.modules 4 - sage: C.edges(sort=True) + sage: C.edges(sort=True) # optional - sage.modules [(0, 1, None), (0, 3, None), (1, 2, None), (2, 3, None)] sage: for (u,v) in G.edges(sort=True, labels=False): ....: G.set_edge_label(u, v, u) - sage: C = G.subgraph_search(graphs.CycleGraph(4)) - sage: C.edges(sort=True) + sage: C = G.subgraph_search(graphs.CycleGraph(4)) # optional - sage.modules + sage: C.edges(sort=True) # optional - sage.modules [(0, 1, 0), (0, 3, 0), (1, 2, 1), (2, 3, 2)] """ @@ -13853,12 +13891,12 @@ def subgraph_search_count(self, G, induced=False): Counting the number of paths `P_5` in a PetersenGraph:: sage: g = graphs.PetersenGraph() - sage: g.subgraph_search_count(graphs.PathGraph(5)) + sage: g.subgraph_search_count(graphs.PathGraph(5)) # optional - sage.modules 240 Requiring these subgraphs be induced:: - sage: g.subgraph_search_count(graphs.PathGraph(5), induced=True) + sage: g.subgraph_search_count(graphs.PathGraph(5), induced=True) # optional - sage.modules 120 If we define the graph `T_k` (the transitive tournament on `k` vertices) @@ -13867,36 +13905,36 @@ def subgraph_search_count(self, G, induced=False): `0`:: sage: T5 = digraphs.TransitiveTournament(5) - sage: T5.subgraph_search_count(digraphs.Circuit(3)) + sage: T5.subgraph_search_count(digraphs.Circuit(3)) # optional - sage.modules 0 If we count instead the number of `T_3` in `T_5`, we expect the answer to be `\binom{5}{3}`:: sage: T3 = digraphs.TransitiveTournament(3) - sage: T5.subgraph_search_count(T3) + sage: T5.subgraph_search_count(T3) # optional - sage.modules 10 sage: binomial(5,3) 10 - sage: T3.is_isomorphic(T5.subgraph(vertices=[0, 1, 2])) + sage: T3.is_isomorphic(T5.subgraph(vertices=[0, 1, 2])) # optional - sage.modules True The empty graph is a subgraph of every graph:: - sage: g.subgraph_search_count(graphs.EmptyGraph()) + sage: g.subgraph_search_count(graphs.EmptyGraph()) # optional - sage.modules 1 If the graph has vertex labels or edge labels, the label is just ignored:: sage: g.set_vertex(0, 'foo') - sage: g.subgraph_search_count(graphs.PathGraph(5)) + sage: g.subgraph_search_count(graphs.PathGraph(5)) # optional - sage.modules 240 TESTS: Inside of a small graph (:trac:`13906`):: - sage: Graph(5).subgraph_search_count(Graph(1)) + sage: Graph(5).subgraph_search_count(Graph(1)) # optional - sage.modules 5 """ from sage.graphs.generic_graph_pyx import SubgraphSearch @@ -13963,7 +14001,7 @@ def subgraph_search_iterator(self, G, induced=False, return_graphs=True): sage: g = graphs.PathGraph(5) sage: P3 = graphs.PathGraph(3) - sage: for p in g.subgraph_search_iterator(P3, return_graphs=False): + sage: for p in g.subgraph_search_iterator(P3, return_graphs=False): # optional - sage.modules ....: print(p) [0, 1, 2] [1, 2, 3] @@ -13971,7 +14009,7 @@ def subgraph_search_iterator(self, G, induced=False, return_graphs=True): [2, 3, 4] [3, 2, 1] [4, 3, 2] - sage: for p in g.subgraph_search_iterator(P3, return_graphs=True): + sage: for p in g.subgraph_search_iterator(P3, return_graphs=True): # optional - sage.modules ....: print(p) Subgraph of (Path graph) Subgraph of (Path graph) @@ -13979,13 +14017,13 @@ def subgraph_search_iterator(self, G, induced=False, return_graphs=True): Subgraph of (Path graph) Subgraph of (Path graph) Subgraph of (Path graph) - sage: all(h.is_isomorphic(P3) for h in g.subgraph_search_iterator(P3)) + sage: all(h.is_isomorphic(P3) for h in g.subgraph_search_iterator(P3)) # optional - sage.modules True If the graph has vertex labels or edge labels, the label is just ignored:: sage: g.set_vertex(0, 'foo') - sage: for p in g.subgraph_search_iterator(P3, return_graphs=False): + sage: for p in g.subgraph_search_iterator(P3, return_graphs=False): # optional - sage.modules ....: print(p) [0, 1, 2] [1, 2, 3] @@ -13998,45 +14036,47 @@ def subgraph_search_iterator(self, G, induced=False, return_graphs=True): sage: H = graphs.HouseGraph() sage: P4 = graphs.PathGraph(4) - sage: all(h.is_isomorphic(P4) for h in H.subgraph_search_iterator(P4, induced=True)) + sage: all(h.is_isomorphic(P4) # optional - sage.modules + ....: for h in H.subgraph_search_iterator(P4, induced=True)) True - sage: sum(1 for h in H.subgraph_search_iterator(P4, induced=True)) + sage: sum(1 for h in H.subgraph_search_iterator(P4, induced=True)) # optional - sage.modules 4 - sage: sum(1 for h in H.subgraph_search_iterator(P4, induced=False)) + sage: sum(1 for h in H.subgraph_search_iterator(P4, induced=False)) # optional - sage.modules 20 Search for subdigraphs:: sage: H = digraphs.Complete(5) sage: P4 = digraphs.Path(4) - sage: sum(1 for _ in H.subgraph_search_iterator(P4, induced=True)) + sage: sum(1 for _ in H.subgraph_search_iterator(P4, induced=True)) # optional - sage.modules 0 - sage: sum(1 for _ in H.subgraph_search_iterator(P4, induced=False)) + sage: sum(1 for _ in H.subgraph_search_iterator(P4, induced=False)) # optional - sage.modules 120 This method also works for bipartite graphs:: sage: K33 = BipartiteGraph(graphs.CompleteBipartiteGraph(3, 3)) sage: K22 = BipartiteGraph(graphs.CompleteBipartiteGraph(2, 2)) - sage: sum(1 for _ in K33.subgraph_search_iterator(K22)) + sage: sum(1 for _ in K33.subgraph_search_iterator(K22)) # optional - sage.modules 72 TESTS: Inside of a small graph (:trac:`13906`):: - sage: list(Graph(5).subgraph_search_iterator(Graph(1))) - [Graph on 1 vertex, Graph on 1 vertex, Graph on 1 vertex, Graph on 1 vertex, Graph on 1 vertex] + sage: list(Graph(5).subgraph_search_iterator(Graph(1))) # optional - sage.modules + [Graph on 1 vertex, Graph on 1 vertex, Graph on 1 vertex, + Graph on 1 vertex, Graph on 1 vertex] Check that the behavior of the method is consistent (:trac:`34004`):: sage: g = graphs.CycleGraph(3) - sage: for i in range(3): + sage: for i in range(3): # optional - sage.modules ....: g.subgraph_search_iterator(graphs.PathGraph(i)) sage: K4 = digraphs.Complete(4) sage: K3 = digraphs.Complete(3) - sage: for g in K4.subgraph_search_iterator(K3, return_graphs=True): + sage: for g in K4.subgraph_search_iterator(K3, return_graphs=True): # optional - sage.modules ....: print(type(g)) ....: break sage: K33 = BipartiteGraph(graphs.CompleteBipartiteGraph(3, 3)) sage: K22 = BipartiteGraph(graphs.CompleteBipartiteGraph(2, 2)) - sage: for b in K33.subgraph_search_iterator(K22, return_graphs=True): + sage: for b in K33.subgraph_search_iterator(K22, return_graphs=True): # optional - sage.modules ....: print(type(b)) ....: break sage: P5 = graphs.PathGraph(5) - sage: for b in K33.subgraph_search_iterator(P5, return_graphs=True): + sage: for b in K33.subgraph_search_iterator(P5, return_graphs=True): # optional - sage.modules ....: print(type(b)) ....: break - sage: for b in Graph(K33).subgraph_search_iterator(K22, return_graphs=True): + sage: for b in Graph(K33).subgraph_search_iterator(K22, return_graphs=True): # optional - sage.modules ....: print(type(b)) ....: break @@ -14142,7 +14182,7 @@ def is_chordal(self, certificate=False, algorithm="B"): cycle of length at least 4). Alternatively, chordality can be defined using a Perfect Elimination - Order : + Order: A Perfect Elimination Order of a graph `G` is an ordering `v_1,...,v_n` of its vertex set such that for all `i`, the neighbors of `v_i` whose @@ -14204,20 +14244,21 @@ def is_chordal(self, certificate=False, algorithm="B"): The same goes with the product of a random lobster (which is a tree) and a Complete Graph :: - sage: g = graphs.RandomLobster(10, .5, .5).lexicographic_product(graphs.CompleteGraph(3)) - sage: g.is_chordal() + sage: grl = graphs.RandomLobster(10, .5, .5) # optional - networkx + sage: g = grl.lexicographic_product(graphs.CompleteGraph(3)) # optional - networkx + sage: g.is_chordal() # optional - networkx True The disjoint union of chordal graphs is still chordal:: - sage: (2 * g).is_chordal() + sage: (2 * g).is_chordal() # optional - networkx True Let us check the certificate given by Sage is indeed a perfect elimination order:: - sage: _, peo = g.is_chordal(certificate=True) - sage: for v in peo: + sage: _, peo = g.is_chordal(certificate=True) # optional - networkx + sage: for v in peo: # optional - networkx ....: if not g.subgraph(g.neighbors(v)).is_clique(): ....: raise ValueError("this should never happen") ....: g.delete_vertex(v) @@ -14437,27 +14478,27 @@ def is_circulant(self, certificate=False): The Petersen graph is not a circulant graph:: sage: g = graphs.PetersenGraph() - sage: g.is_circulant() + sage: g.is_circulant() # optional - sage.groups False A cycle is obviously a circulant graph, but several sets of parameters can be used to define it:: sage: g = graphs.CycleGraph(5) - sage: g.is_circulant(certificate=True) + sage: g.is_circulant(certificate=True) # optional - sage.groups (True, [(5, [1, 4]), (5, [2, 3])]) The same goes for directed graphs:: sage: g = digraphs.Circuit(5) - sage: g.is_circulant(certificate=True) + sage: g.is_circulant(certificate=True) # optional - sage.groups (True, [(5, [1]), (5, [3]), (5, [2]), (5, [4])]) With this information, it is very easy to create (and plot) all possible drawings of a circulant graph:: sage: g = graphs.CirculantGraph(13, [2, 3, 10, 11]) - sage: for param in g.is_circulant(certificate=True)[1]: + sage: for param in g.is_circulant(certificate=True)[1]: # optional - sage.groups ....: graphs.CirculantGraph(*param) Circulant graph ([2, 3, 10, 11]): Graph on 13 vertices Circulant graph ([1, 5, 8, 12]): Graph on 13 vertices @@ -14465,13 +14506,13 @@ def is_circulant(self, certificate=False): TESTS:: - sage: digraphs.DeBruijn(3,1).is_circulant(certificate=True) + sage: digraphs.DeBruijn(3,1).is_circulant(certificate=True) # optional - sage.combinat sage.groups (True, [(3, [0, 1, 2])]) - sage: Graph(1).is_circulant(certificate=True) + sage: Graph(1).is_circulant(certificate=True) # optional - sage.groups (True, (1, [])) - sage: Graph(0).is_circulant(certificate=True) + sage: Graph(0).is_circulant(certificate=True) # optional - sage.groups (True, (0, [])) - sage: Graph({0: [0]}).is_circulant(certificate=True) + sage: Graph({0: [0]}).is_circulant(certificate=True) # optional - sage.groups (True, (1, [0])) """ self._scream_if_not_simple(allow_loops=True) @@ -15061,11 +15102,11 @@ def is_subgraph(self, other, induced=True, up_to_isomorphism=False): sage: p11 = graphs.PathGraph(11) sage: p15 = graphs.PathGraph(15) sage: g = graphs.Grid2dGraph(4, 4) - sage: p15.is_subgraph(g, induced=False, up_to_isomorphism=True) + sage: p15.is_subgraph(g, induced=False, up_to_isomorphism=True) # optional - sage.modules True - sage: p15.is_subgraph(g, induced=True, up_to_isomorphism=True) + sage: p15.is_subgraph(g, induced=True, up_to_isomorphism=True) # optional - sage.modules False - sage: p11.is_subgraph(g, induced=True, up_to_isomorphism=True) + sage: p11.is_subgraph(g, induced=True, up_to_isomorphism=True) # optional - sage.modules True TESTS: @@ -15143,7 +15184,7 @@ def cluster_triangles(self, nbunch=None, implementation=None): :: sage: G = graphs.RandomGNP(20, .3) - sage: d1 = G.cluster_triangles(implementation="networkx") + sage: d1 = G.cluster_triangles(implementation="networkx") # optional - networkx sage: d2 = G.cluster_triangles(implementation="dense_copy") sage: d3 = G.cluster_triangles(implementation="sparse_copy") sage: d1 == d2 and d1 == d3 @@ -15151,7 +15192,7 @@ def cluster_triangles(self, nbunch=None, implementation=None): TESTS:: - sage: DiGraph().cluster_triangles(implementation="networkx") + sage: DiGraph().cluster_triangles(implementation="networkx") # optional - networkx Traceback (most recent call last): ... ValueError: the 'networkx' implementation does not support directed graphs @@ -15211,7 +15252,7 @@ def clustering_average(self, implementation=None): sage: (graphs.FruchtGraph()).clustering_average() 1/4 - sage: (graphs.FruchtGraph()).clustering_average(implementation='networkx') + sage: (graphs.FruchtGraph()).clustering_average(implementation='networkx') # optional - networkx 0.25 TESTS: @@ -15226,9 +15267,11 @@ def clustering_average(self, implementation=None): The result is the same with all implementations:: sage: G = graphs.RandomGNM(10,20) + sage: impls = ['boost','sparse_copy','dense_copy'] + sage: impls += ['networkx'] # optional - networkx sage: coeffs = [G.clustering_average(implementation=impl) - ....: for impl in ['boost','sparse_copy','dense_copy','networkx']] - sage: max(coeffs)-min(coeffs) # tol abs 1e-12 + ....: for impl in impls] + sage: max(coeffs) - min(coeffs) # tol abs 1e-12 0 """ @@ -15305,10 +15348,10 @@ def clustering_coeff(self, sage: (graphs.FruchtGraph()).clustering_coeff(weight=True) {0: 0.3333333333333333, 1: 0.3333333333333333, 2: 0, - 3: 0.3333333333333333, 4: 0.3333333333333333, - 5: 0.3333333333333333, 6: 0.3333333333333333, - 7: 0.3333333333333333, 8: 0, 9: 0.3333333333333333, - 10: 0.3333333333333333, 11: 0} + 3: 0.3333333333333333, 4: 0.3333333333333333, + 5: 0.3333333333333333, 6: 0.3333333333333333, + 7: 0.3333333333333333, 8: 0, 9: 0.3333333333333333, + 10: 0.3333333333333333, 11: 0} sage: (graphs.FruchtGraph()).clustering_coeff(nodes=[0,1,2]) {0: 0.3333333333333333, 1: 0.3333333333333333, 2: 0.0} @@ -15411,7 +15454,7 @@ def cluster_transitivity(self): EXAMPLES:: - sage: graphs.FruchtGraph().cluster_transitivity() + sage: graphs.FruchtGraph().cluster_transitivity() # optional - networkx 0.25 """ import networkx @@ -15616,7 +15659,7 @@ def girth(self, certificate=False): Issue :trac:`12355`:: - sage: H=Graph([(0, 1), (0, 3), (0, 4), (0, 5), (1, 2), (1, 3), (1, 4), (1, 6), (2, 5), (3, 4), (5, 6)]) + sage: H = Graph([(0, 1), (0, 3), (0, 4), (0, 5), (1, 2), (1, 3), (1, 4), (1, 6), (2, 5), (3, 4), (5, 6)]) sage: H.girth() 3 @@ -15646,13 +15689,13 @@ def girth(self, certificate=False): sage: g = digraphs.Circuit(6) sage: g.girth() 6 - sage: g = digraphs.RandomDirectedGNC(10) - sage: g.girth() + sage: g = digraphs.RandomDirectedGNC(10) # optional - networkx + sage: g.girth() # optional - networkx +Infinity - sage: g = DiGraph([(0, 1), (1, 2), (1, 3), (2, 3), (3, 4), (4, 0)]) - sage: g.girth() + sage: g = DiGraph([(0, 1), (1, 2), (1, 3), (2, 3), (3, 4), (4, 0)]) # optional - networkx + sage: g.girth() # optional - networkx 4 - sage: Graph(g).girth() + sage: Graph(g).girth() # optional - networkx 3 """ # Cases where girth <= 2 @@ -15703,10 +15746,10 @@ def odd_girth(self, algorithm="bfs", certificate=False): The McGee graph has girth 7 and therefore its odd girth is 7 as well:: - sage: G = graphs.McGeeGraph() - sage: G.girth() + sage: G = graphs.McGeeGraph() # optional - networkx + sage: G.girth() # optional - networkx 7 - sage: G.odd_girth() + sage: G.odd_girth() # optional - networkx 7 Any complete (directed) graph on more than 2 vertices contains @@ -15731,15 +15774,15 @@ def odd_girth(self, algorithm="bfs", certificate=False): The odd girth of a (directed) graph with loops is 1:: - sage: G = graphs.RandomGNP(10, .5) - sage: G.allow_loops(True) - sage: G.add_edge(0, 0) - sage: G.odd_girth() + sage: G = graphs.RandomGNP(10, .5) # optional - networkx + sage: G.allow_loops(True) # optional - networkx + sage: G.add_edge(0, 0) # optional - networkx + sage: G.odd_girth() # optional - networkx 1 - sage: G = digraphs.RandomDirectedGNP(10, .5) - sage: G.allow_loops(True) - sage: G.add_edge(0, 0) - sage: G.odd_girth() + sage: G = digraphs.RandomDirectedGNP(10, .5) # optional - networkx + sage: G.allow_loops(True) # optional - networkx + sage: G.add_edge(0, 0) # optional - networkx + sage: G.odd_girth() # optional - networkx 1 .. SEEALSO:: @@ -15952,9 +15995,9 @@ def centrality_betweenness(self, k=None, normalized=True, weight=None, TESTS:: - sage: tests = ([graphs.RandomGNP(30,.1) for i in range(10)]+ + sage: tests = ([graphs.RandomGNP(30,.1) for i in range(10)]+ # optional - networkx ....: [digraphs.RandomDirectedGNP(30,.1) for i in range(10)]) - sage: for g in tests: + sage: for g in tests: # optional - networkx ....: r1 = g.centrality_betweenness(algorithm="Sage",exact=0) ....: r2 = g.centrality_betweenness(algorithm="Sage",exact=1) ....: r3 = g.centrality_betweenness(algorithm="NetworkX") @@ -16460,9 +16503,9 @@ def shortest_path(self, u, v, by_weight=False, algorithm=None, [4, 17, 16, 12, 13, 9] sage: D.shortest_path(4, 9, algorithm='BFS') [4, 3, 2, 1, 8, 9] - sage: D.shortest_path(4, 8, algorithm='Dijkstra_NetworkX') + sage: D.shortest_path(4, 8, algorithm='Dijkstra_NetworkX') # optional - networkx [4, 3, 2, 1, 8] - sage: D.shortest_path(4, 8, algorithm='Dijkstra_Bid_NetworkX') + sage: D.shortest_path(4, 8, algorithm='Dijkstra_Bid_NetworkX') # optional - networkx [4, 3, 2, 1, 8] sage: D.shortest_path(4, 9, algorithm='Dijkstra_Bid') [4, 3, 19, 0, 10, 9] @@ -16471,15 +16514,18 @@ def shortest_path(self, u, v, by_weight=False, algorithm=None, sage: D.delete_edges(D.edges_incident(13)) sage: D.shortest_path(13, 4) [] - sage: G = Graph({0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2}}, sparse = True) + sage: G = Graph({0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2}}, + ....: sparse=True) sage: G.plot(edge_labels=True).show() # long time sage: G.shortest_path(0, 3) [0, 4, 3] sage: G.shortest_path(0, 3, by_weight=True) [0, 1, 2, 3] - sage: G.shortest_path(0, 3, by_weight=True, algorithm='Dijkstra_NetworkX') + sage: G.shortest_path(0, 3, by_weight=True, # optional - networkx + ....: algorithm='Dijkstra_NetworkX') [0, 1, 2, 3] - sage: G.shortest_path(0, 3, by_weight=True, algorithm='Dijkstra_Bid_NetworkX') + sage: G.shortest_path(0, 3, by_weight=True, # optional - networkx + ....: algorithm='Dijkstra_Bid_NetworkX') [0, 1, 2, 3] TESTS: @@ -16517,15 +16563,11 @@ def shortest_path(self, u, v, by_weight=False, algorithm=None, sage: G = Graph() sage: G.add_vertices([1, 2]) - sage: for alg in ['BFS', 'BFS_Bid', 'Dijkstra_NetworkX', 'Dijkstra_Bid_NetworkX', - ....: 'Dijkstra_Bid', 'Bellman-Ford_Boost']: - ....: G.shortest_path(1, 2, algorithm=alg) - [] - [] - [] - [] - [] - [] + sage: algs = ['BFS', 'BFS_Bid', 'Dijkstra_Bid', 'Bellman-Ford_Boost'] + sage: algs += ['Dijkstra_NetworkX', 'Dijkstra_Bid_NetworkX'] # optional - networkx + sage: all(G.shortest_path(1, 2, algorithm=alg) == [] + ....: for alg in algs) + True .. TODO:: @@ -16646,9 +16688,9 @@ def shortest_path_length(self, u, v, by_weight=False, algorithm=None, 5 sage: D.shortest_path_length(4, 9, algorithm='BFS') 5 - sage: D.shortest_path_length(4, 9, algorithm='Dijkstra_NetworkX') + sage: D.shortest_path_length(4, 9, algorithm='Dijkstra_NetworkX') # optional - networkx 5 - sage: D.shortest_path_length(4, 9, algorithm='Dijkstra_Bid_NetworkX') + sage: D.shortest_path_length(4, 9, algorithm='Dijkstra_Bid_NetworkX') # optional - networkx 5 sage: D.shortest_path_length(4, 9, algorithm='Dijkstra_Bid') 5 @@ -16659,31 +16701,37 @@ def shortest_path_length(self, u, v, by_weight=False, algorithm=None, sage: D.delete_edges(D.edges_incident(13)) sage: D.shortest_path_length(13, 4) +Infinity - sage: G = Graph({0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2}}, sparse = True) - sage: G.plot(edge_labels=True).show() # long time + sage: G = Graph({0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2}}, + ....: sparse=True) + sage: G.plot(edge_labels=True).show() # long time sage: G.shortest_path_length(0, 3) 2 sage: G.shortest_path_length(0, 3, by_weight=True) 3 - sage: G.shortest_path_length(0, 3, by_weight=True, algorithm='Dijkstra_NetworkX') + sage: G.shortest_path_length(0, 3, by_weight=True, # optional - networkx + ....: algorithm='Dijkstra_NetworkX') 3 - sage: G.shortest_path_length(0, 3, by_weight=True, algorithm='Dijkstra_Bid_NetworkX') + sage: G.shortest_path_length(0, 3, by_weight=True, # optional - networkx + ....: algorithm='Dijkstra_Bid_NetworkX') 3 If Dijkstra is used with negative weights, usually it raises an error:: - sage: G = DiGraph({0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: -2}}, sparse = True) + sage: G = DiGraph({0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: -2}}, + ....: sparse=True) sage: G.shortest_path_length(4, 1, by_weight=True, algorithm=None) Traceback (most recent call last): ... ValueError: the graph contains an edge with negative weight - sage: G.shortest_path_length(4, 1, by_weight=True, algorithm='Bellman-Ford_Boost') + sage: G.shortest_path_length(4, 1, by_weight=True, + ....: algorithm='Bellman-Ford_Boost') -1 However, sometimes the result may be wrong, and no error is raised:: - sage: G = DiGraph([(0,1,1),(1,2,1),(0,3,1000),(3,4,-3000), (4,2,1000)]) - sage: G.shortest_path_length(0, 2, by_weight=True, algorithm='Bellman-Ford_Boost') + sage: G = DiGraph([(0,1,1), (1,2,1), (0,3,1000), (3,4,-3000), (4,2,1000)]) + sage: G.shortest_path_length(0, 2, by_weight=True, + ....: algorithm='Bellman-Ford_Boost') -1000 sage: G.shortest_path_length(0, 2, by_weight=True) 2 @@ -16705,15 +16753,11 @@ def shortest_path_length(self, u, v, by_weight=False, algorithm=None, sage: G = Graph() sage: G.add_vertices([1, 2]) - sage: for alg in ['BFS', 'BFS_Bid', 'Dijkstra_NetworkX', 'Dijkstra_Bid_NetworkX', - ....: 'Dijkstra_Bid', 'Bellman-Ford_Boost']: - ....: G.shortest_path_length(1, 2, algorithm=alg) - +Infinity - +Infinity - +Infinity - +Infinity - +Infinity - +Infinity + sage: algs = ['BFS', 'BFS_Bid', 'Dijkstra_Bid', 'Bellman-Ford_Boost'] + sage: algs += ['Dijkstra_NetworkX', 'Dijkstra_Bid_NetworkX'] # optional - networkx + sage: all(G.shortest_path_length(1, 2, algorithm=alg) == Infinity + ....: for alg in algs) + True """ if not self.has_vertex(u): raise ValueError("vertex '{}' is not in the (di)graph".format(u)) @@ -17214,20 +17258,23 @@ def shortest_path_lengths(self, u, by_weight=False, algorithm=None, sage: D = graphs.DodecahedralGraph() sage: D.shortest_path_lengths(0) - {0: 0, 1: 1, 2: 2, 3: 2, 4: 3, 5: 4, 6: 3, 7: 3, 8: 2, 9: 2, 10: 1, 11: 2, 12: 3, 13: 3, 14: 4, 15: 5, 16: 4, 17: 3, 18: 2, 19: 1} + {0: 0, 1: 1, 2: 2, 3: 2, 4: 3, 5: 4, 6: 3, 7: 3, 8: 2, 9: 2, 10: 1, + 11: 2, 12: 3, 13: 3, 14: 4, 15: 5, 16: 4, 17: 3, 18: 2, 19: 1} Weighted case:: - sage: G = Graph( { 0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2} }, sparse=True) - sage: G.plot(edge_labels=True).show() # long time + sage: G = Graph({0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2}}, + ....: sparse=True) + sage: G.plot(edge_labels=True).show() # long time # optional - sage.plot sage: G.shortest_path_lengths(0, by_weight=True) {0: 0, 1: 1, 2: 2, 3: 3, 4: 2} Using a weight function:: - sage: D = DiGraph([(0,1,{'weight':1}),(1,2,{'weight':3}),(0,2,{'weight':5})]) - sage: weight_function = lambda e:e[2]['weight'] - sage: D.shortest_path_lengths(1, algorithm='Dijkstra_NetworkX', by_weight=False) + sage: D = DiGraph([(0,1,{'weight':1}), (1,2,{'weight':3}), (0,2,{'weight':5})]) + sage: weight_function = lambda e: e[2]['weight'] + sage: D.shortest_path_lengths(1, algorithm='Dijkstra_NetworkX', # optional - networkx + ....: by_weight=False) {1: 0, 2: 1} sage: D.shortest_path_lengths(0, weight_function=weight_function) {0: 0, 1: 1, 2: 4} @@ -17236,13 +17283,13 @@ def shortest_path_lengths(self, u, by_weight=False, algorithm=None, Negative weights:: - sage: D = DiGraph([(0,1,{'weight':-1}),(1,2,{'weight':3}),(0,2,{'weight':5})]) + sage: D = DiGraph([(0,1,{'weight':-1}), (1,2,{'weight':3}), (0,2,{'weight':5})]) sage: D.shortest_path_lengths(0, weight_function=weight_function) {0: 0, 1: -1, 2: 2} Negative cycles:: - sage: D = DiGraph([(0,1,{'weight':-5}),(1,2,{'weight':3}),(2,0,{'weight':1})]) + sage: D = DiGraph([(0,1,{'weight':-5}), (1,2,{'weight':3}), (2,0,{'weight':1})]) sage: D.shortest_path_lengths(0, weight_function=weight_function) Traceback (most recent call last): ... @@ -17252,7 +17299,7 @@ def shortest_path_lengths(self, u, by_weight=False, algorithm=None, sage: g = graphs.Grid2dGraph(5,5) sage: d1 = g.shortest_path_lengths((0,0), algorithm="BFS") - sage: d2 = g.shortest_path_lengths((0,0), algorithm="Dijkstra_NetworkX") + sage: d2 = g.shortest_path_lengths((0,0), algorithm="Dijkstra_NetworkX") # optional - networkx sage: d3 = g.shortest_path_lengths((0,0), algorithm="Dijkstra_Boost") sage: d4 = g.shortest_path_lengths((0,0), algorithm="Bellman-Ford_Boost") sage: d1 == d2 == d3 == d4 @@ -18599,7 +18646,8 @@ def to_simple(self, to_undirected=True, keep_label='any', immutable=None): EXAMPLES:: sage: G = DiGraph(loops=True, multiedges=True, sparse=True) - sage: G.add_edges([(0, 0, None), (1, 1, None), (2, 2, None), (2, 3, 1), (2, 3, 2), (3, 2, None)]) + sage: G.add_edges([(0, 0, None), (1, 1, None), (2, 2, None), + ....: (2, 3, 1), (2, 3, 2), (3, 2, None)]) sage: G.edges(sort=True, labels=False) [(0, 0), (1, 1), (2, 2), (2, 3), (2, 3), (3, 2)] sage: H = G.to_simple() @@ -18845,9 +18893,9 @@ def cartesian_product(self, other): Cartesian product of digraphs:: sage: P = DiGraph([(0, 1)]) - sage: B = digraphs.DeBruijn(['a', 'b'], 2) - sage: Q = P.cartesian_product(B) - sage: Q.edges(sort=True, labels=None) + sage: B = digraphs.DeBruijn(['a', 'b'], 2) # optional - sage.combinat + sage: Q = P.cartesian_product(B) # optional - sage.combinat + sage: Q.edges(sort=True, labels=None) # optional - sage.combinat [((0, 'aa'), (0, 'aa')), ((0, 'aa'), (0, 'ab')), ((0, 'aa'), (1, 'aa')), ((0, 'ab'), (0, 'ba')), ((0, 'ab'), (0, 'bb')), ((0, 'ab'), (1, 'ab')), @@ -18858,10 +18906,10 @@ def cartesian_product(self, other): ((1, 'ab'), (1, 'ba')), ((1, 'ab'), (1, 'bb')), ((1, 'ba'), (1, 'aa')), ((1, 'ba'), (1, 'ab')), ((1, 'bb'), (1, 'ba')), ((1, 'bb'), (1, 'bb'))] - sage: Q.strongly_connected_components_digraph().num_verts() + sage: Q.strongly_connected_components_digraph().num_verts() # optional - sage.combinat 2 - sage: V = Q.strongly_connected_component_containing_vertex((0, 'aa')) - sage: B.is_isomorphic(Q.subgraph(V)) + sage: V = Q.strongly_connected_component_containing_vertex((0, 'aa')) # optional - sage.combinat + sage: B.is_isomorphic(Q.subgraph(V)) # optional - sage.combinat True """ self._scream_if_not_simple(allow_loops=True) @@ -19096,13 +19144,13 @@ def strong_product(self, other): Counting the edges (see :trac:`13699`):: - sage: g = graphs.RandomGNP(5, .5) - sage: gn,gm = g.order(), g.size() - sage: h = graphs.RandomGNP(5, .5) - sage: hn,hm = h.order(), h.size() - sage: product_size = g.strong_product(h).size() - sage: expected = gm * hn + hm * gn + 2 * gm * hm - sage: product_size == expected + sage: g = graphs.RandomGNP(5, .5) # optional - networkx + sage: gn,gm = g.order(), g.size() # optional - networkx + sage: h = graphs.RandomGNP(5, .5) # optional - networkx + sage: hn,hm = h.order(), h.size() # optional - networkx + sage: product_size = g.strong_product(h).size() # optional - networkx + sage: expected = gm * hn + hm * gn + 2 * gm * hm # optional - networkx + sage: product_size == expected # optional - networkx True """ self._scream_if_not_simple(allow_loops=True) @@ -19396,33 +19444,35 @@ def _color_by_label(self, format='hex', as_function=False, default_color="black" We consider the Cayley graph of the symmetric group, whose edges are labelled by the numbers 1,2, and 3:: - sage: G = SymmetricGroup(4).cayley_graph() # optional - sage.groups - sage: set(G.edge_labels()) # optional - sage.groups + sage: G = SymmetricGroup(4).cayley_graph() # optional - sage.groups + sage: set(G.edge_labels()) # optional - sage.groups {1, 2, 3} We first request the coloring as a function:: - sage: f = G._color_by_label(as_function=True) # optional - sage.groups - sage: [f(1), f(2), f(3)] # optional - sage.groups + sage: f = G._color_by_label(as_function=True) # optional - sage.groups + sage: [f(1), f(2), f(3)] # optional - sage.groups ['#0000ff', '#ff0000', '#00ff00'] - sage: f = G._color_by_label({1: "blue", 2: "red", 3: "green"}, as_function=True) # optional - sage.groups - sage: [f(1), f(2), f(3)] # optional - sage.groups + sage: f = G._color_by_label({1: "blue", 2: "red", 3: "green"}, # optional - sage.groups + ....: as_function=True) + sage: [f(1), f(2), f(3)] # optional - sage.groups ['blue', 'red', 'green'] - sage: f = G._color_by_label({1: "red"}, as_function=True) # optional - sage.groups - sage: [f(1), f(2), f(3)] # optional - sage.groups + sage: f = G._color_by_label({1: "red"}, as_function=True) # optional - sage.groups + sage: [f(1), f(2), f(3)] # optional - sage.groups ['red', 'black', 'black'] - sage: f = G._color_by_label({1: "red"}, as_function=True, default_color='blue') # optional - sage.groups - sage: [f(1), f(2), f(3)] # optional - sage.groups + sage: f = G._color_by_label({1: "red"}, as_function=True, # optional - sage.groups + ....: default_color='blue') + sage: [f(1), f(2), f(3)] # optional - sage.groups ['red', 'blue', 'blue'] The default output is a dictionary assigning edges to colors:: - sage: G._color_by_label() # optional - sage.groups + sage: G._color_by_label() # optional - sage.groups {'#0000ff': [((), (1,2), 1), ...], '#00ff00': [((), (3,4), 3), ...], '#ff0000': [((), (2,3), 2), ...]} - sage: G._color_by_label({1: "blue", 2: "red", 3: "green"}) # optional - sage.groups + sage: G._color_by_label({1: "blue", 2: "red", 3: "green"}) # optional - sage.groups {'blue': [((), (1,2), 1), ...], 'green': [((), (3,4), 3), ...], 'red': [((), (2,3), 2), ...]} @@ -19431,12 +19481,12 @@ def _color_by_label(self, format='hex', as_function=False, default_color="black" We check what happens when several labels have the same color:: - sage: result = G._color_by_label({1: "blue", 2: "blue", 3: "green"}) # optional - sage.groups - sage: sorted(result) # optional - sage.groups + sage: result = G._color_by_label({1: "blue", 2: "blue", 3: "green"}) # optional - sage.groups + sage: sorted(result) # optional - sage.groups ['blue', 'green'] - sage: len(result['blue']) # optional - sage.groups + sage: len(result['blue']) # optional - sage.groups 48 - sage: len(result['green']) # optional - sage.groups + sage: len(result['green']) # optional - sage.groups 24 """ if format is True: @@ -19490,8 +19540,8 @@ def latex_options(self): sage: opts = g.latex_options() sage: opts LaTeX options for Petersen graph: {} - sage: opts.set_option('tkz_style', 'Classic') - sage: opts + sage: opts.set_option('tkz_style', 'Classic') # optional - sage.plot + sage: opts # optional - sage.plot LaTeX options for Petersen graph: {'tkz_style': 'Classic'} """ if self._latex_opts is None: @@ -19519,9 +19569,9 @@ def set_latex_options(self, **kwds): EXAMPLES:: sage: g = graphs.PetersenGraph() - sage: g.set_latex_options(tkz_style='Welsh') - sage: opts = g.latex_options() - sage: opts.get_option('tkz_style') + sage: g.set_latex_options(tkz_style='Welsh') # optional - sage.plot + sage: opts = g.latex_options() # optional - sage.plot + sage: opts.get_option('tkz_style') # optional - sage.plot 'Welsh' """ opts = self.latex_options() @@ -19890,9 +19940,10 @@ def layout_forest(self, tree_orientation="down", forest_roots=None, sage: G.plot(pos=p) # random # optional - sage.plot Graphics object consisting of 28 graphics primitives - sage: H = graphs.PathGraph(5) + graphs.PathGraph(5) + graphs.BalancedTree(2,2) - sage: p = H.layout_forest(forest_roots=[14,3]) - sage: H.plot(pos=p) # optional - sage.plot + sage: P5 = graphs.PathGraph(5) + sage: H = P5 + P5 + graphs.BalancedTree(2,2) # optional - networkx + sage: p = H.layout_forest(forest_roots=[14,3]) # optional - networkx + sage: H.plot(pos=p) # optional - networkx sage.plot Graphics object consisting of 32 graphics primitives TESTS:: @@ -19962,16 +20013,16 @@ def layout_tree(self, tree_orientation="down", tree_root=None, sage: G.plot(layout="tree", tree_orientation="right") # optional - sage.plot Graphics object consisting of 160 graphics primitives - sage: T = graphs.RandomLobster(25, 0.3, 0.3) - sage: T.show(layout='tree', tree_orientation='up') # optional - sage.plot + sage: T = graphs.RandomLobster(25, 0.3, 0.3) # optional - networkx + sage: T.show(layout='tree', tree_orientation='up') # optional - networkx sage.plot sage: G = graphs.HoffmanSingletonGraph() sage: T = Graph() sage: T.add_edges(G.min_spanning_tree(starting_vertex=0)) sage: T.show(layout='tree', tree_root=0) # optional - sage.plot - sage: G = graphs.BalancedTree(2, 2) - sage: G.layout_tree(tree_root=0) + sage: G = graphs.BalancedTree(2, 2) # optional - networkx + sage: G.layout_tree(tree_root=0) # optional - networkx {0: [1.5, 0], 1: [2.5, -1], 2: [0.5, -1], @@ -19980,8 +20031,8 @@ def layout_tree(self, tree_orientation="down", tree_root=None, 5: [1.0, -2], 6: [0.0, -2]} - sage: G = graphs.BalancedTree(2, 4) - sage: G.plot(layout="tree", tree_root=0, tree_orientation="up") # optional - sage.plot + sage: G = graphs.BalancedTree(2, 4) # optional - networkx + sage: G.plot(layout="tree", tree_root=0, tree_orientation="up") # optional - networkx sage.plot Graphics object consisting of 62 graphics primitives Using the embedding when it exists:: @@ -20004,8 +20055,8 @@ def layout_tree(self, tree_orientation="down", tree_root=None, TESTS:: - sage: G = graphs.BalancedTree(2, 2) - sage: G.layout_tree(tree_root=0, tree_orientation='left') + sage: G = graphs.BalancedTree(2, 2) # optional - networkx + sage: G.layout_tree(tree_root=0, tree_orientation='left') # optional - networkx {0: [0, 1.5], 1: [-1, 2.5], 2: [-1, 0.5], @@ -20187,8 +20238,8 @@ def layout_graphviz(self, dim=2, prog='dot', **options): Graphics object consisting of 29 graphics primitives sage: g.plot(layout="graphviz", prog="fdp") # optional - dot2tex graphviz Graphics object consisting of 29 graphics primitives - sage: g = graphs.BalancedTree(5,2) - sage: g.plot(layout="graphviz", prog="circo") # optional - dot2tex graphviz + sage: g = graphs.BalancedTree(5,2) # optional - networkx + sage: g.plot(layout="graphviz", prog="circo") # optional - dot2tex graphviz networkx Graphics object consisting of 62 graphics primitives .. TODO:: @@ -20500,7 +20551,7 @@ def _rich_repr_(self, display_manager, **kwds): sage: dm.preferences.supplemental_plot 'never' sage: del dm.preferences.supplemental_plot - sage: graphs.RandomGNP(20,0.0) + sage: graphs.RandomGNP(20,0.0) # optional - networkx RandomGNP(20,0.000000000000000): Graph on 20 vertices (use the .plot() method to plot) sage: dm.preferences.supplemental_plot = 'never' """ @@ -20960,10 +21011,10 @@ def plot3d(self, bgcolor=(1, 1, 1), We plot a fairly complicated Cayley graph:: - sage: A5 = AlternatingGroup(5); A5 + sage: A5 = AlternatingGroup(5); A5 # optional - sage.groups Alternating group of order 5!/2 as a permutation group - sage: G = A5.cayley_graph() - sage: G.plot3d(vertex_size=0.03, edge_size=0.01, # long time, optional - sage.plot + sage: G = A5.cayley_graph() # optional - sage.groups + sage: G.plot3d(vertex_size=0.03, edge_size=0.01, # long time, optional - sage.groups sage.plot ....: vertex_colors={(1,1,1): list(G)}, bgcolor=(0,0,0), ....: color_by_label=True, iterations=200) Graphics3d Object @@ -21217,10 +21268,10 @@ def show3d(self, bgcolor=(1, 1, 1), vertex_colors=None, vertex_size=0.06, We plot a fairly complicated Cayley graph:: - sage: A5 = AlternatingGroup(5); A5 + sage: A5 = AlternatingGroup(5); A5 # optional - sage.groups Alternating group of order 5!/2 as a permutation group - sage: G = A5.cayley_graph() - sage: G.show3d(vertex_size=0.03, # long time, optional - sage.plot + sage: G = A5.cayley_graph() # optional - sage.groups + sage: G.show3d(vertex_size=0.03, # long time, optional - sage.groups sage.plot ....: edge_size=0.01, edge_size2=0.02, ....: vertex_colors={(1,1,1): list(G)}, bgcolor=(0,0,0), ....: color_by_label=True, iterations=200) @@ -21686,12 +21737,12 @@ def graphviz_string(self, **options): The following digraph has vertices with newlines in their string representations:: - sage: m1 = matrix(3, 3) - sage: m2 = matrix(3, 3, 1) - sage: m1.set_immutable() - sage: m2.set_immutable() - sage: g = DiGraph({m1: [m2]}) - sage: print(g.graphviz_string()) + sage: m1 = matrix(3, 3) # optional - sage.modules + sage: m2 = matrix(3, 3, 1) # optional - sage.modules + sage: m1.set_immutable() # optional - sage.modules + sage: m2.set_immutable() # optional - sage.modules + sage: g = DiGraph({m1: [m2]}) # optional - sage.modules + sage: print(g.graphviz_string()) # optional - sage.modules digraph { node_0 [label="[0 0 0]\n\ [0 0 0]\n\ @@ -22002,26 +22053,26 @@ def spectrum(self, laplacian=False): EXAMPLES:: sage: P = graphs.PetersenGraph() - sage: P.spectrum() + sage: P.spectrum() # optional - sage.modules [3, 1, 1, 1, 1, 1, -2, -2, -2, -2] - sage: P.spectrum(laplacian=True) + sage: P.spectrum(laplacian=True) # optional - sage.modules [5, 5, 5, 5, 2, 2, 2, 2, 2, 0] sage: D = P.to_directed() sage: D.delete_edge(7, 9) - sage: D.spectrum() + sage: D.spectrum() # optional - sage.modules [2.9032119259..., 1, 1, 1, 1, 0.8060634335..., -1.7092753594..., -2, -2, -2] :: sage: C = graphs.CycleGraph(8) - sage: C.spectrum() + sage: C.spectrum() # optional - sage.modules [2, 1.4142135623..., 1.4142135623..., 0, 0, -1.4142135623..., -1.4142135623..., -2] A digraph may have complex eigenvalues. Previously, the complex parts of graph eigenvalues were being dropped. For a 3-cycle, we have:: sage: T = DiGraph({0: [1], 1: [2], 2: [0]}) - sage: T.spectrum() + sage: T.spectrum() # optional - sage.modules [1, -0.5000000000... + 0.8660254037...*I, -0.5000000000... - 0.8660254037...*I] TESTS: @@ -22035,10 +22086,10 @@ def spectrum(self, laplacian=False): eigenvalues. :: sage: H = graphs.HoffmanSingletonGraph() - sage: evals = H.spectrum() - sage: lap = [7 - x for x in evals] - sage: lap.sort(reverse=True) - sage: lap == H.spectrum(laplacian=True) + sage: evals = H.spectrum() # optional - sage.modules + sage: lap = [7 - x for x in evals] # optional - sage.modules + sage: lap.sort(reverse=True) # optional - sage.modules + sage: lap == H.spectrum(laplacian=True) # optional - sage.modules True """ # Ideally the spectrum should return something like a Factorization object @@ -22084,11 +22135,11 @@ def characteristic_polynomial(self, var='x', laplacian=False): EXAMPLES:: sage: P = graphs.PetersenGraph() - sage: P.characteristic_polynomial() + sage: P.characteristic_polynomial() # optional - sage.modules x^10 - 15*x^8 + 75*x^6 - 24*x^5 - 165*x^4 + 120*x^3 + 120*x^2 - 160*x + 48 - sage: P.charpoly() + sage: P.charpoly() # optional - sage.modules x^10 - 15*x^8 + 75*x^6 - 24*x^5 - 165*x^4 + 120*x^3 + 120*x^2 - 160*x + 48 - sage: P.characteristic_polynomial(laplacian=True) + sage: P.characteristic_polynomial(laplacian=True) # optional - sage.modules x^10 - 30*x^9 + 390*x^8 - 2880*x^7 + 13305*x^6 - 39882*x^5 + 77640*x^4 - 94800*x^3 + 66000*x^2 - 20000*x """ @@ -22124,7 +22175,7 @@ def eigenvectors(self, laplacian=False): EXAMPLES:: sage: P = graphs.PetersenGraph() - sage: P.eigenvectors() + sage: P.eigenvectors() # optional - sage.modules [(3, [ (1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ], 1), (-2, [ @@ -22144,7 +22195,7 @@ def eigenvectors(self, laplacian=False): graph is regular. However, since the output also contains the eigenvalues, the two outputs are slightly different:: - sage: P.eigenvectors(laplacian=True) + sage: P.eigenvectors(laplacian=True) # optional - sage.modules [(0, [ (1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ], 1), (5, [ @@ -22163,7 +22214,7 @@ def eigenvectors(self, laplacian=False): :: sage: C = graphs.CycleGraph(8) - sage: C.eigenvectors() + sage: C.eigenvectors() # optional - sage.modules [(2, [ (1, 1, 1, 1, 1, 1, 1, 1) @@ -22193,7 +22244,7 @@ def eigenvectors(self, laplacian=False): graph eigenvalues were being dropped. For a 3-cycle, we have:: sage: T = DiGraph({0:[1], 1:[2], 2:[0]}) - sage: T.eigenvectors() + sage: T.eigenvectors() # optional - sage.modules [(1, [ (1, 1, 1) @@ -22234,7 +22285,7 @@ def eigenspaces(self, laplacian=False): EXAMPLES:: sage: P = graphs.PetersenGraph() - sage: P.eigenspaces() + sage: P.eigenspaces() # optional - sage.modules [ (3, Vector space of degree 10 and dimension 1 over Rational Field User basis matrix: @@ -22258,7 +22309,7 @@ def eigenspaces(self, laplacian=False): graph is regular. However, since the output also contains the eigenvalues, the two outputs are slightly different:: - sage: P.eigenspaces(laplacian=True) + sage: P.eigenspaces(laplacian=True) # optional - sage.modules [ (0, Vector space of degree 10 and dimension 1 over Rational Field User basis matrix: @@ -22283,7 +22334,7 @@ def eigenspaces(self, laplacian=False): corresponding eigenspace:: sage: C = graphs.CycleGraph(8) - sage: C.eigenspaces() + sage: C.eigenspaces() # optional - sage.modules [ (2, Vector space of degree 8 and dimension 1 over Rational Field User basis matrix: @@ -22306,7 +22357,7 @@ def eigenspaces(self, laplacian=False): we have:: sage: T = DiGraph({0: [1], 1: [2], 2: [0]}) - sage: T.eigenspaces() + sage: T.eigenspaces() # optional - sage.modules [ (1, Vector space of degree 3 and dimension 1 over Rational Field User basis matrix: @@ -22384,7 +22435,7 @@ def relabel(self, perm=None, inplace=True, return_map=False, check_input=True, c EXAMPLES:: sage: G = graphs.PathGraph(3) - sage: G.am() + sage: G.am() # optional - sage.modules [0 1 0] [1 0 1] [0 1 0] @@ -22392,7 +22443,7 @@ def relabel(self, perm=None, inplace=True, return_map=False, check_input=True, c Relabeling using a dictionary. Note that the dictionary does not define the new label of vertex `0`:: - sage: G.relabel({1:2,2:1}, inplace=False).am() + sage: G.relabel({1:2,2:1}, inplace=False).am() # optional - sage.modules [0 0 1] [0 0 1] [1 1 0] @@ -22402,21 +22453,22 @@ def relabel(self, perm=None, inplace=True, return_map=False, check_input=True, c vertices have an image can require some time, and this feature can be disabled (at your own risk):: - sage: G.relabel({1:2,2:1}, inplace=False, complete_partial_function=False).am() + sage: G.relabel({1:2,2:1}, inplace=False, # optional - sage.modules + ....: complete_partial_function=False).am() Traceback (most recent call last): ... KeyError: 0 Relabeling using a list:: - sage: G.relabel([0,2,1], inplace=False).am() + sage: G.relabel([0,2,1], inplace=False).am() # optional - sage.modules [0 0 1] [0 0 1] [1 1 0] Relabeling using an iterable:: - sage: G.relabel(iter((0,2,1)), inplace=False).am() + sage: G.relabel(iter((0,2,1)), inplace=False).am() # optional - sage.modules [0 0 1] [0 0 1] [1 1 0] @@ -22427,7 +22479,7 @@ def relabel(self, perm=None, inplace=True, return_map=False, check_input=True, c sage: from sage.groups.perm_gps.permgroup_named import SymmetricGroup # optional - sage.groups sage: S = SymmetricGroup(3) # optional - sage.groups sage: gamma = S('(1,2)') # optional - sage.groups - sage: G.relabel(gamma, inplace=False).am() # optional - sage.groups + sage: G.relabel(gamma, inplace=False).am() # optional - sage.groups sage.modules [0 0 1] [0 0 1] [1 1 0] @@ -22546,7 +22598,10 @@ def relabel(self, perm=None, inplace=True, return_map=False, check_input=True, c sage: G.relabel( [ i+1 for i in range(G.order()) ], inplace=True ) sage: G.relabel( [ i+1 for i in range(G.order()) ], inplace=True ) """ - from sage.groups.perm_gps.permgroup_element import PermutationGroupElement + try: + from sage.groups.perm_gps.permgroup_element import PermutationGroupElement + except ImportError: + PermutationGroupElement = () if not inplace: G = copy(self) @@ -22707,7 +22762,7 @@ def is_equitable(self, partition, quotient_matrix=False): False sage: G.is_equitable([[0,4],[1,3,5,9],[2,6,8,7]]) True - sage: G.is_equitable([[0,4],[1,3,5,9],[2,6,8,7]], quotient_matrix=True) + sage: G.is_equitable([[0,4],[1,3,5,9],[2,6,8,7]], quotient_matrix=True) # optional - sage.modules [1 2 0] [1 0 2] [0 2 1] @@ -23231,13 +23286,13 @@ def is_vertex_transitive(self, partition=None, verbosity=0, sage: G.is_vertex_transitive() False sage: P = graphs.PetersenGraph() - sage: P.is_vertex_transitive() + sage: P.is_vertex_transitive() # optional - sage.groups True sage: D = graphs.DodecahedralGraph() - sage: D.is_vertex_transitive() + sage: D.is_vertex_transitive() # optional - sage.groups True - sage: R = graphs.RandomGNP(2000, .01) - sage: R.is_vertex_transitive() + sage: R = graphs.RandomGNP(2000, .01) # optional - networkx + sage: R.is_vertex_transitive() # optional - networkx False """ if partition is None: @@ -23748,7 +23803,7 @@ class by some canonization function `c`. If `G` and `H` are graphs, sage: P = graphs.PetersenGraph() sage: DP = P.to_directed() - sage: DP.canonical_label(algorithm='sage').adjacency_matrix() + sage: DP.canonical_label(algorithm='sage').adjacency_matrix() # optional - sage.modules [0 0 0 0 0 0 0 1 1 1] [0 0 0 0 1 0 1 0 0 1] [0 0 0 1 0 0 1 0 1 0] @@ -23766,10 +23821,12 @@ class by some canonization function `c`. If `G` and `H` are graphs, sage: G.add_edges( [(0,1,'a'),(1,2,'b'),(2,3,'c'),(3,4,'b'),(4,0,'a')] ) sage: G.canonical_label(edge_labels=True) Graph on 5 vertices - sage: G.canonical_label(edge_labels=True, algorithm="bliss", certificate=True) # optional - bliss + sage: G.canonical_label(edge_labels=True, algorithm="bliss", # optional - bliss + ....: certificate=True) (Graph on 5 vertices, {0: 4, 1: 3, 2: 1, 3: 0, 4: 2}) - sage: G.canonical_label(edge_labels=True, algorithm="sage", certificate=True) + sage: G.canonical_label(edge_labels=True, algorithm="sage", + ....: certificate=True) (Graph on 5 vertices, {0: 4, 1: 3, 2: 0, 3: 1, 4: 2}) Another example where different canonization algorithms give @@ -23777,10 +23834,10 @@ class by some canonization function `c`. If `G` and `H` are graphs, sage: g = Graph({'a': ['b'], 'c': ['d']}) sage: g_sage = g.canonical_label(algorithm='sage') - sage: g_bliss = g.canonical_label(algorithm='bliss') # optional - bliss + sage: g_bliss = g.canonical_label(algorithm='bliss') # optional - bliss sage: g_sage.edges(sort=True, labels=False) [(0, 3), (1, 2)] - sage: g_bliss.edges(sort=True, labels=False) # optional - bliss + sage: g_bliss.edges(sort=True, labels=False) # optional - bliss [(0, 1), (2, 3)] TESTS:: @@ -23788,7 +23845,7 @@ class by some canonization function `c`. If `G` and `H` are graphs, sage: G = Graph([['a', 'b'], [('a', 'b')]]) sage: G.canonical_label(algorithm='sage', certificate=True) (Graph on 2 vertices, {'a': 0, 'b': 1}) - sage: G.canonical_label(algorithm='bliss', certificate=True) # optional - bliss + sage: G.canonical_label(algorithm='bliss', certificate=True) # optional - bliss (Graph on 2 vertices, {'a': 1, 'b': 0}) Check for immutable graphs (:trac:`16602`):: @@ -23970,15 +24027,15 @@ def is_cayley(self, return_group=False, mapping=False, A Petersen Graph is not a Cayley graph:: sage: g = graphs.PetersenGraph() - sage: g.is_cayley() + sage: g.is_cayley() # optional - sage.groups False A Cayley digraph is a Cayley graph:: - sage: C7 = groups.permutation.Cyclic(7) + sage: C7 = groups.permutation.Cyclic(7) # optional - sage.groups sage: S = [(1,2,3,4,5,6,7), (1,3,5,7,2,4,6), (1,5,2,6,3,7,4)] - sage: d = C7.cayley_graph(generators=S) - sage: d.is_cayley() + sage: d = C7.cayley_graph(generators=S) # optional - sage.groups + sage: d.is_cayley() # optional - sage.groups True Graphs with loops and multiedges will have identity and repeated @@ -24252,7 +24309,7 @@ def katz_matrix(self, alpha, nonedgesonly=False, vertices=None): We find the Katz matrix of an undirected 4-cycle. :: sage: G = graphs.CycleGraph(4) - sage: G.katz_matrix(1/20) + sage: G.katz_matrix(1/20) # optional - sage.modules [1/198 5/99 1/198 5/99] [ 5/99 1/198 5/99 1/198] [1/198 5/99 1/198 5/99] @@ -24261,7 +24318,7 @@ def katz_matrix(self, alpha, nonedgesonly=False, vertices=None): We find the Katz matrix of an undirected 4-cycle with all entries other than those which correspond to non-edges zeroed out. :: - sage: G.katz_matrix(1/20, True) + sage: G.katz_matrix(1/20, True) # optional - sage.modules [ 0 0 1/198 0] [ 0 0 0 1/198] [1/198 0 0 0] @@ -24273,7 +24330,7 @@ def katz_matrix(self, alpha, nonedgesonly=False, vertices=None): We find the Katz matrix in a fan on 6 vertices. :: sage: H = Graph([(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(1,2),(2,3),(3,4),(4,5)]) - sage: H.katz_matrix(1/10) + sage: H.katz_matrix(1/10) # optional - sage.modules [ 169/2256 545/4512 25/188 605/4512 25/188 545/4512 485/4512] [ 545/4512 7081/297792 4355/37224 229/9024 595/37224 4073/297792 109/9024] [ 25/188 4355/37224 172/4653 45/376 125/4653 595/37224 5/376] @@ -24289,22 +24346,22 @@ def katz_matrix(self, alpha, nonedgesonly=False, vertices=None): TESTS:: - sage: (graphs.CompleteGraph(4)).katz_matrix(1/4) + sage: (graphs.CompleteGraph(4)).katz_matrix(1/4) # optional - sage.modules [3/5 4/5 4/5 4/5] [4/5 3/5 4/5 4/5] [4/5 4/5 3/5 4/5] [4/5 4/5 4/5 3/5] - sage: (graphs.CompleteGraph(4)).katz_matrix(1/4, nonedgesonly=True) + sage: (graphs.CompleteGraph(4)).katz_matrix(1/4, nonedgesonly=True) # optional - sage.modules [0 0 0 0] [0 0 0 0] [0 0 0 0] [0 0 0 0] - sage: (graphs.PathGraph(4)).katz_matrix(1/4, nonedgesonly=False) + sage: (graphs.PathGraph(4)).katz_matrix(1/4, nonedgesonly=False) # optional - sage.modules [15/209 60/209 16/209 4/209] [60/209 31/209 64/209 16/209] [16/209 64/209 31/209 60/209] [ 4/209 16/209 60/209 15/209] - sage: (graphs.PathGraph(4)).katz_matrix(1/4, nonedgesonly=True) + sage: (graphs.PathGraph(4)).katz_matrix(1/4, nonedgesonly=True) # optional - sage.modules [ 0 0 16/209 4/209] [ 0 0 0 16/209] [16/209 0 0 0] @@ -24369,7 +24426,7 @@ def katz_centrality(self, alpha, u=None): all 4 vertices have the same centrality) :: sage: G = graphs.CycleGraph(4) - sage: G.katz_centrality(1/20) + sage: G.katz_centrality(1/20) # optional - sage.modules {0: 1/9, 1: 1/9, 2: 1/9, 3: 1/9} Note that in the below example the nodes having indegree `0` also have @@ -24378,7 +24435,7 @@ def katz_centrality(self, alpha, u=None): sage: G = DiGraph({1: [10], 2:[10,11], 3:[10,11], 4:[], 5:[11, 4], 6:[11], ....: 7:[10,11], 8:[10,11], 9:[10], 10:[11, 5, 8], 11:[6]}) - sage: G.katz_centrality(.85) # rel tol 1e-14 + sage: G.katz_centrality(.85) # rel tol 1e-14 # optional - sage.modules {1: 0.000000000000000, 2: 0.000000000000000, 3: 0.000000000000000, @@ -24399,15 +24456,15 @@ def katz_centrality(self, alpha, u=None): TESTS:: - sage: graphs.PathGraph(3).katz_centrality(1/20) + sage: graphs.PathGraph(3).katz_centrality(1/20) # optional - sage.modules {0: 11/199, 1: 21/199, 2: 11/199} - sage: graphs.PathGraph(4).katz_centrality(1/20) + sage: graphs.PathGraph(4).katz_centrality(1/20) # optional - sage.modules {0: 21/379, 1: 41/379, 2: 41/379, 3: 21/379} - sage: graphs.PathGraph(3).katz_centrality(1/20,2) + sage: graphs.PathGraph(3).katz_centrality(1/20,2) # optional - sage.modules 11/199 - sage: graphs.PathGraph(4).katz_centrality(1/20,3) + sage: graphs.PathGraph(4).katz_centrality(1/20,3) # optional - sage.modules 21/379 - sage: (graphs.PathGraph(3) + graphs.PathGraph(4)).katz_centrality(1/20) + sage: (graphs.PathGraph(3) + graphs.PathGraph(4)).katz_centrality(1/20) # optional - sage.modules {0: 11/199, 1: 21/199, 2: 11/199, 3: 21/379, 4: 41/379, 5: 41/379, 6: 21/379} """ @@ -24458,29 +24515,29 @@ def edge_polytope(self, backend=None): The EP of a `4`-cycle is a square:: sage: G = graphs.CycleGraph(4) - sage: P = G.edge_polytope(); P + sage: P = G.edge_polytope(); P # optional - sage.geometry.polyhedron A 2-dimensional polyhedron in ZZ^4 defined as the convex hull of 4 vertices The EP of a complete graph on `4` vertices is cross polytope:: sage: G = graphs.CompleteGraph(4) - sage: P = G.edge_polytope(); P + sage: P = G.edge_polytope(); P # optional - sage.geometry.polyhedron A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 6 vertices - sage: P.is_combinatorially_isomorphic(polytopes.cross_polytope(3)) + sage: P.is_combinatorially_isomorphic(polytopes.cross_polytope(3)) # optional - sage.geometry.polyhedron True The EP of a graph is isomorphic to the subdirect sum of its connected components EPs:: sage: n = randint(3, 6) - sage: G1 = graphs.RandomGNP(n, 0.2) + sage: G1 = graphs.RandomGNP(n, 0.2) # optional - networkx sage: n = randint(3, 6) - sage: G2 = graphs.RandomGNP(n, 0.2) - sage: G = G1.disjoint_union(G2) - sage: P = G.edge_polytope() - sage: P1 = G1.edge_polytope() - sage: P2 = G2.edge_polytope() - sage: P.is_combinatorially_isomorphic(P1.subdirect_sum(P2)) + sage: G2 = graphs.RandomGNP(n, 0.2) # optional - networkx + sage: G = G1.disjoint_union(G2) # optional - networkx + sage: P = G.edge_polytope() # optional - networkx sage.geometry.polyhedron + sage: P1 = G1.edge_polytope() # optional - networkx sage.geometry.polyhedron + sage: P2 = G2.edge_polytope() # optional - networkx sage.geometry.polyhedron + sage: P.is_combinatorially_isomorphic(P1.subdirect_sum(P2)) # optional - networkx sage.geometry.polyhedron True All trees on `n` vertices have isomorphic EPs:: @@ -24488,9 +24545,9 @@ def edge_polytope(self, backend=None): sage: n = randint(4, 10) sage: G1 = graphs.RandomTree(n) sage: G2 = graphs.RandomTree(n) - sage: P1 = G1.edge_polytope() - sage: P2 = G2.edge_polytope() - sage: P1.is_combinatorially_isomorphic(P2) + sage: P1 = G1.edge_polytope() # optional - sage.geometry.polyhedron + sage: P2 = G2.edge_polytope() # optional - sage.geometry.polyhedron + sage: P1.is_combinatorially_isomorphic(P2) # optional - sage.geometry.polyhedron True However, there are still many different EPs:: @@ -24498,14 +24555,14 @@ def edge_polytope(self, backend=None): sage: len(list(graphs(5))) 34 sage: polys = [] - sage: for G in graphs(5): + sage: for G in graphs(5): # optional - sage.geometry.polyhedron ....: P = G.edge_polytope() ....: for P1 in polys: ....: if P.is_combinatorially_isomorphic(P1): ....: break ....: else: ....: polys.append(P) - sage: len(polys) + sage: len(polys) # optional - sage.geometry.polyhedron 19 TESTS: @@ -24513,7 +24570,7 @@ def edge_polytope(self, backend=None): Obtain the EP with unsortable vertices:: sage: G = Graph([[1, (1, 2)]]) - sage: G.edge_polytope() + sage: G.edge_polytope() # optional - sage.geometry.polyhedron A 0-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex """ from sage.matrix.special import identity_matrix @@ -24544,17 +24601,17 @@ def symmetric_edge_polytope(self, backend=None): The SEP of a `4`-cycle is a cube:: sage: G = graphs.CycleGraph(4) - sage: P = G.symmetric_edge_polytope(); P + sage: P = G.symmetric_edge_polytope(); P # optional - sage.geometry.polyhedron A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 8 vertices - sage: P.is_combinatorially_isomorphic(polytopes.cube()) + sage: P.is_combinatorially_isomorphic(polytopes.cube()) # optional - sage.geometry.polyhedron True The SEP of a complete graph on `4` vertices is a cuboctahedron:: sage: G = graphs.CompleteGraph(4) - sage: P = G.symmetric_edge_polytope(); P + sage: P = G.symmetric_edge_polytope(); P # optional - sage.geometry.polyhedron A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 12 vertices - sage: P.is_combinatorially_isomorphic(polytopes.cuboctahedron()) + sage: P.is_combinatorially_isomorphic(polytopes.cuboctahedron()) # optional - sage.geometry.polyhedron True The SEP of a graph with edges on `n` vertices has dimension `n` @@ -24562,26 +24619,26 @@ def symmetric_edge_polytope(self, backend=None): sage: n = randint(5, 12) sage: G = Graph() - sage: while not G.num_edges(): + sage: while not G.num_edges(): # optional - networkx ....: G = graphs.RandomGNP(n, 0.2) - sage: P = G.symmetric_edge_polytope() - sage: P.ambient_dim() == n + sage: P = G.symmetric_edge_polytope() # optional - networkx sage.geometry.polyhedron + sage: P.ambient_dim() == n # optional - networkx sage.geometry.polyhedron True - sage: P.dim() == n - G.connected_components_number() + sage: P.dim() == n - G.connected_components_number() # optional - networkx sage.geometry.polyhedron True The SEP of a graph is isomorphic to the subdirect sum of its connected components SEP's:: sage: n = randint(3, 6) - sage: G1 = graphs.RandomGNP(n, 0.2) + sage: G1 = graphs.RandomGNP(n, 0.2) # optional - networkx sage: n = randint(3, 6) - sage: G2 = graphs.RandomGNP(n, 0.2) - sage: G = G1.disjoint_union(G2) - sage: P = G.symmetric_edge_polytope() - sage: P1 = G1.symmetric_edge_polytope() - sage: P2 = G2.symmetric_edge_polytope() - sage: P.is_combinatorially_isomorphic(P1.subdirect_sum(P2)) + sage: G2 = graphs.RandomGNP(n, 0.2) # optional - networkx + sage: G = G1.disjoint_union(G2) # optional - networkx + sage: P = G.symmetric_edge_polytope() # optional - networkx sage.geometry.polyhedron + sage: P1 = G1.symmetric_edge_polytope() # optional - networkx sage.geometry.polyhedron + sage: P2 = G2.symmetric_edge_polytope() # optional - networkx sage.geometry.polyhedron + sage: P.is_combinatorially_isomorphic(P1.subdirect_sum(P2)) # optional - networkx sage.geometry.polyhedron True All trees on `n` vertices have isomorphic SEPs:: @@ -24589,9 +24646,9 @@ def symmetric_edge_polytope(self, backend=None): sage: n = randint(4, 10) sage: G1 = graphs.RandomTree(n) sage: G2 = graphs.RandomTree(n) - sage: P1 = G1.symmetric_edge_polytope() - sage: P2 = G2.symmetric_edge_polytope() - sage: P1.is_combinatorially_isomorphic(P2) + sage: P1 = G1.symmetric_edge_polytope() # optional - sage.geometry.polyhedron + sage: P2 = G2.symmetric_edge_polytope() # optional - sage.geometry.polyhedron + sage: P1.is_combinatorially_isomorphic(P2) # optional - sage.geometry.polyhedron True However, there are still many different SEPs:: @@ -24599,7 +24656,7 @@ def symmetric_edge_polytope(self, backend=None): sage: len(list(graphs(5))) 34 sage: polys = [] - sage: for G in graphs(5): + sage: for G in graphs(5): # optional - sage.geometry.polyhedron ....: P = G.symmetric_edge_polytope() ....: for P1 in polys: ....: if P.is_combinatorially_isomorphic(P1): @@ -24618,24 +24675,24 @@ def symmetric_edge_polytope(self, backend=None): sage: G2.add_edges([[0, 7], [7, 3]]) sage: G1.is_isomorphic(G2) False - sage: P1 = G1.symmetric_edge_polytope() - sage: P2 = G2.symmetric_edge_polytope() - sage: P1.is_combinatorially_isomorphic(P2) + sage: P1 = G1.symmetric_edge_polytope() # optional - sage.geometry.polyhedron + sage: P2 = G2.symmetric_edge_polytope() # optional - sage.geometry.polyhedron + sage: P1.is_combinatorially_isomorphic(P2) # optional - sage.geometry.polyhedron True Apparently, glueing two graphs together on a vertex gives isomorphic SEPs:: sage: n = randint(3, 7) - sage: g1 = graphs.RandomGNP(n, 0.2) - sage: g2 = graphs.RandomGNP(n, 0.2) - sage: G = g1.disjoint_union(g2) - sage: H = copy(G) - sage: G.merge_vertices(((0, randrange(n)), (1, randrange(n)))) - sage: H.merge_vertices(((0, randrange(n)), (1, randrange(n)))) - sage: PG = G.symmetric_edge_polytope() - sage: PH = H.symmetric_edge_polytope() - sage: PG.is_combinatorially_isomorphic(PH) + sage: g1 = graphs.RandomGNP(n, 0.2) # optional - networkx + sage: g2 = graphs.RandomGNP(n, 0.2) # optional - networkx + sage: G = g1.disjoint_union(g2) # optional - networkx + sage: H = copy(G) # optional - networkx + sage: G.merge_vertices(((0, randrange(n)), (1, randrange(n)))) # optional - networkx + sage: H.merge_vertices(((0, randrange(n)), (1, randrange(n)))) # optional - networkx + sage: PG = G.symmetric_edge_polytope() # optional - networkx sage.geometry.polyhedron + sage: PH = H.symmetric_edge_polytope() # optional - networkx sage.geometry.polyhedron + sage: PG.is_combinatorially_isomorphic(PH) # optional - networkx sage.geometry.polyhedron True TESTS: @@ -24643,7 +24700,7 @@ def symmetric_edge_polytope(self, backend=None): Obtain the SEP with unsortable vertices:: sage: G = Graph([[1, (1, 2)]]) - sage: G.symmetric_edge_polytope() + sage: G.symmetric_edge_polytope() # optional - sage.geometry.polyhedron A 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices """ from itertools import chain diff --git a/src/sage/graphs/generic_graph_pyx.pyx b/src/sage/graphs/generic_graph_pyx.pyx index 712c2d955f0..520ea4283e2 100644 --- a/src/sage/graphs/generic_graph_pyx.pyx +++ b/src/sage/graphs/generic_graph_pyx.pyx @@ -650,7 +650,7 @@ cdef class SubgraphSearch: EXAMPLES:: sage: g = graphs.PetersenGraph() - sage: g.subgraph_search(graphs.CycleGraph(5)) + sage: g.subgraph_search(graphs.CycleGraph(5)) # optional - sage.modules Subgraph of (Petersen graph): Graph on 5 vertices TESTS: @@ -660,11 +660,11 @@ cdef class SubgraphSearch: computations with it:: sage: from sage.graphs.generic_graph_pyx import SubgraphSearch - sage: SubgraphSearch(Graph(5), Graph(1)) + sage: SubgraphSearch(Graph(5), Graph(1)) # optional - sage.modules Traceback (most recent call last): ... ValueError: Searched graph should have at least 2 vertices. - sage: SubgraphSearch(Graph(5), Graph(2)) + sage: SubgraphSearch(Graph(5), Graph(2)) # optional - sage.modules """ if H.order() <= 1: @@ -690,8 +690,8 @@ cdef class SubgraphSearch: sage: from sage.graphs.generic_graph_pyx import SubgraphSearch sage: g = graphs.PathGraph(5) sage: h = graphs.PathGraph(3) - sage: S = SubgraphSearch(g, h) - sage: for p in S: + sage: S = SubgraphSearch(g, h) # optional - sage.modules + sage: for p in S: # optional - sage.modules ....: print(p) [0, 1, 2] [1, 2, 3] @@ -721,8 +721,8 @@ cdef class SubgraphSearch: sage: from sage.graphs.generic_graph_pyx import SubgraphSearch sage: g = graphs.PathGraph(5) sage: h = graphs.PathGraph(3) - sage: S = SubgraphSearch(g, h) - sage: S.cardinality() + sage: S = SubgraphSearch(g, h) # optional - sage.modules + sage: S.cardinality() # optional - sage.modules 6 """ if self.nh > self.ng: @@ -756,18 +756,18 @@ cdef class SubgraphSearch: sage: from sage.graphs.generic_graph_pyx import SubgraphSearch sage: g = graphs.PathGraph(5) sage: h = graphs.PathGraph(3) - sage: S = SubgraphSearch(g, h) - sage: S.__next__() + sage: S = SubgraphSearch(g, h) # optional - sage.modules + sage: S.__next__() # optional - sage.modules [0, 1, 2] - sage: S._initialization() - sage: S.__next__() + sage: S._initialization() # optional - sage.modules + sage: S.__next__() # optional - sage.modules [0, 1, 2] TESTS: Check that :trac:`21828` is fixed:: - sage: Poset().is_incomparable_chain_free(1,1) # indirect doctest + sage: Poset().is_incomparable_chain_free(1,1) # indirect doctest # optional - sage.modules True """ cdef int i @@ -802,7 +802,7 @@ cdef class SubgraphSearch: EXAMPLES:: sage: g = graphs.PetersenGraph() - sage: g.subgraph_search(graphs.CycleGraph(5)) + sage: g.subgraph_search(graphs.CycleGraph(5)) # optional - sage.modules Subgraph of (Petersen graph): Graph on 5 vertices """ self.mem = MemoryAllocator() @@ -883,8 +883,8 @@ cdef class SubgraphSearch: sage: from sage.graphs.generic_graph_pyx import SubgraphSearch sage: g = graphs.PathGraph(5) sage: h = graphs.PathGraph(3) - sage: S = SubgraphSearch(g, h) - sage: S.__next__() + sage: S = SubgraphSearch(g, h) # optional - sage.modules + sage: S.__next__() # optional - sage.modules [0, 1, 2] """ if not self.ng: diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index b351b8501c0..a83da34a230 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -424,7 +424,7 @@ from sage.graphs.views import EdgesView from sage.parallel.decorate import parallel -from sage.misc.lazy_import import lazy_import +from sage.misc.lazy_import import lazy_import, LazyImport from sage.features import PythonModule lazy_import('sage.graphs.mcqd', ['mcqd'], feature=PythonModule('sage.graphs.mcqd', spkg='mcqd')) @@ -10022,7 +10022,7 @@ def bipartite_double(self, extended=False): # Aliases to functions defined in other modules from sage.graphs.weakly_chordal import is_long_hole_free, is_long_antihole_free, is_weakly_chordal from sage.graphs.asteroidal_triples import is_asteroidal_triple_free - from sage.graphs.chrompoly import chromatic_polynomial + chromatic_polynomial = LazyImport('sage.graphs.chrompoly', 'chromatic_polynomial', at_startup=True) from sage.graphs.graph_decompositions.rankwidth import rank_decomposition from sage.graphs.graph_decompositions.tree_decomposition import treewidth from sage.graphs.graph_decompositions.vertex_separation import pathwidth @@ -10030,7 +10030,7 @@ def bipartite_double(self, extended=False): from sage.graphs.graph_decompositions.clique_separators import atoms_and_clique_separators from sage.graphs.graph_decompositions.bandwidth import bandwidth from sage.graphs.graph_decompositions.cutwidth import cutwidth - from sage.graphs.matchpoly import matching_polynomial + matching_polynomial = LazyImport('sage.graphs.matchpoly', 'matching_polynomial', at_startup=True) from sage.graphs.cliquer import all_max_clique as cliques_maximum from sage.graphs.cliquer import all_cliques from sage.graphs.spanning_tree import random_spanning_tree @@ -10047,7 +10047,7 @@ def bipartite_double(self, extended=False): from sage.graphs.connectivity import is_triconnected from sage.graphs.comparability import is_comparability from sage.graphs.comparability import is_permutation - from sage.graphs.convexity_properties import geodetic_closure + geodetic_closure = LazyImport('sage.graphs.convexity_properties', 'geodetic_closure', at_startup=True) from sage.graphs.domination import is_dominating from sage.graphs.domination import is_redundant from sage.graphs.domination import private_neighbors diff --git a/src/sage/graphs/graph_coloring.pyx b/src/sage/graphs/graph_coloring.pyx index 844969f8b94..f04f1e382e8 100644 --- a/src/sage/graphs/graph_coloring.pyx +++ b/src/sage/graphs/graph_coloring.pyx @@ -65,13 +65,14 @@ Methods # **************************************************************************** from copy import copy -from sage.combinat.matrices.dlxcpp import DLXCPP from libcpp.vector cimport vector from libcpp.pair cimport pair -from sage.numerical.mip import MixedIntegerLinearProgram -from sage.numerical.mip import MIPSolverException from sage.graphs.independent_sets import IndependentSets +from sage.misc.lazy_import import LazyImport + +DLXCPP = LazyImport('sage.combinat.matrices.dlxcpp', 'DLXCPP') +MixedIntegerLinearProgram = LazyImport('sage.numerical.mip', 'MixedIntegerLinearProgram') def all_graph_colorings(G, n, count_only=False, hex_colors=False, vertex_color_dict=False): @@ -643,6 +644,7 @@ def vertex_coloring(g, k=None, value_only=False, hex_colors=False, solver=None, # it, and it can help. p.add_constraint(color[next(g.vertex_iterator()), 0], max=1, min=1) + from sage.numerical.mip import MIPSolverException try: if value_only: p.solve(objective_only=True, log=verbose) @@ -1038,6 +1040,7 @@ def grundy_coloring(g, k, value_only=True, solver=None, verbose=0, # Trying to use as many colors as possible p.set_objective(p.sum(is_used[i] for i in range(k))) + from sage.numerical.mip import MIPSolverException try: p.solve(log=verbose) except MIPSolverException: @@ -1227,6 +1230,7 @@ def b_coloring(g, k, value_only=True, solver=None, verbose=0, # We want to maximize the number of used colors p.set_objective(p.sum(is_used[i] for i in range(k))) + from sage.numerical.mip import MIPSolverException try: p.solve(log=verbose) except MIPSolverException: @@ -1458,6 +1462,8 @@ def edge_coloring(g, value_only=False, vizing=False, hex_colors=False, solver=No # We color the edges of the vertex of maximum degree for i, v in enumerate(h.neighbor_iterator(X)): p.add_constraint(color[frozenset((v, X)), i] == 1) + + from sage.numerical.mip import MIPSolverException try: p.solve(objective_only=value_only, log=verbose) except MIPSolverException: @@ -1885,6 +1891,7 @@ def linear_arboricity(g, plus_one=None, hex_colors=False, value_only=False, # no cycles p.add_constraint(p.sum(r[i, (u, v)] for v in g.neighbor_iterator(u)), max=MAD) + from sage.numerical.mip import MIPSolverException try: p.solve(objective_only=value_only, log=verbose) if value_only: @@ -2139,6 +2146,7 @@ def acyclic_edge_coloring(g, hex_colors=False, value_only=False, k=0, p.set_objective(None) + from sage.numerical.mip import MIPSolverException try: p.solve(objective_only=value_only, log=verbose) if value_only: @@ -2181,9 +2189,9 @@ def acyclic_edge_coloring(g, hex_colors=False, value_only=False, k=0, cdef class Test: r""" - This class performs randomized testing for all_graph_colorings. + This class performs randomized testing for :func:`all_graph_colorings`. - Since everything else in this file is derived from all_graph_colorings, this + Since everything else in this file is derived from :func:`all_graph_colorings`, this is a pretty good randomized tester for the entire file. Note that for a graph `G`, ``G.chromatic_polynomial()`` uses an entirely different algorithm, so we provide a good, independent test. diff --git a/src/sage/graphs/graph_decompositions/bandwidth.pyx b/src/sage/graphs/graph_decompositions/bandwidth.pyx index 874787d4713..d72c6e5ff80 100644 --- a/src/sage/graphs/graph_decompositions/bandwidth.pyx +++ b/src/sage/graphs/graph_decompositions/bandwidth.pyx @@ -160,7 +160,7 @@ def bandwidth(G, k=None): False sage: bandwidth(G) (5, [0, 4, 5, 8, 1, 9, 3, 7, 6, 2]) - sage: G.adjacency_matrix(vertices=[0, 4, 5, 8, 1, 9, 3, 7, 6, 2]) + sage: G.adjacency_matrix(vertices=[0, 4, 5, 8, 1, 9, 3, 7, 6, 2]) # optional - sage.modules [0 1 1 0 1 0 0 0 0 0] [1 0 0 0 0 1 1 0 0 0] [1 0 0 1 0 0 0 1 0 0] @@ -174,7 +174,7 @@ def bandwidth(G, k=None): sage: G = graphs.ChvatalGraph() sage: bandwidth(G) (6, [0, 5, 9, 4, 10, 1, 6, 11, 3, 8, 7, 2]) - sage: G.adjacency_matrix(vertices=[0, 5, 9, 4, 10, 1, 6, 11, 3, 8, 7, 2]) + sage: G.adjacency_matrix(vertices=[0, 5, 9, 4, 10, 1, 6, 11, 3, 8, 7, 2]) # optional - sage.modules [0 0 1 1 0 1 1 0 0 0 0 0] [0 0 0 1 1 1 0 1 0 0 0 0] [1 0 0 0 1 0 0 1 1 0 0 0] diff --git a/src/sage/graphs/graph_decompositions/graph_products.pyx b/src/sage/graphs/graph_decompositions/graph_products.pyx index ed85f6f7ef2..0a948360096 100644 --- a/src/sage/graphs/graph_decompositions/graph_products.pyx +++ b/src/sage/graphs/graph_decompositions/graph_products.pyx @@ -206,8 +206,8 @@ def is_cartesian_product(g, certificate=False, relabeling=False): Wagner's Graph (:trac:`13599`):: - sage: g = graphs.WagnerGraph() - sage: g.is_cartesian_product() + sage: g = graphs.WagnerGraph() # optional - networkx + sage: g.is_cartesian_product() # optional - networkx False Empty and one-element graph (:trac:`19546`):: diff --git a/src/sage/graphs/graph_decompositions/modular_decomposition.py b/src/sage/graphs/graph_decompositions/modular_decomposition.py index 0c1ae4da5b3..794c1d95d7b 100644 --- a/src/sage/graphs/graph_decompositions/modular_decomposition.py +++ b/src/sage/graphs/graph_decompositions/modular_decomposition.py @@ -16,8 +16,12 @@ # **************************************************************************** from enum import Enum + +from sage.misc.lazy_import import lazy_import from sage.misc.random_testing import random_testing +lazy_import('sage.groups.perm_gps.permgroup_element', 'PermutationGroupElement') + class NodeType(Enum): """ @@ -606,7 +610,7 @@ def habib_maurer_algorithm(graph, g_classes=None): decompositions. :: sage: from sage.graphs.graph_decompositions.modular_decomposition import permute_decomposition - sage: permute_decomposition(2, habib_maurer_algorithm, 20, 0.5) + sage: permute_decomposition(2, habib_maurer_algorithm, 20, 0.5) # optional - sage.groups """ if graph.is_directed(): raise ValueError("Graph must be undirected") @@ -1167,7 +1171,6 @@ def relabel_tree(root, perm): 2 1 """ - from sage.groups.perm_gps.permgroup_element import PermutationGroupElement # If perm is not a dictionary, we build one ! if perm is None: diff --git a/src/sage/graphs/graph_decompositions/vertex_separation.pyx b/src/sage/graphs/graph_decompositions/vertex_separation.pyx index 98ab0800e52..bf6070e9c8f 100644 --- a/src/sage/graphs/graph_decompositions/vertex_separation.pyx +++ b/src/sage/graphs/graph_decompositions/vertex_separation.pyx @@ -766,12 +766,12 @@ def vertex_separation(G, algorithm="BAB", cut_off=None, upper_bound=None, verbos Comparison of methods:: sage: from sage.graphs.graph_decompositions.vertex_separation import vertex_separation - sage: G = digraphs.DeBruijn(2,3) - sage: vs,L = vertex_separation(G, algorithm="BAB"); vs + sage: G = digraphs.DeBruijn(2,3) # optional - sage.combinat + sage: vs,L = vertex_separation(G, algorithm="BAB"); vs # optional - sage.combinat 2 - sage: vs,L = vertex_separation(G, algorithm="exponential"); vs + sage: vs,L = vertex_separation(G, algorithm="exponential"); vs # optional - sage.combinat 2 - sage: vs,L = vertex_separation(G, algorithm="MILP"); vs + sage: vs,L = vertex_separation(G, algorithm="MILP"); vs # optional - sage.combinat 2 sage: G = graphs.Grid2dGraph(3,3) sage: vs,L = vertex_separation(G, algorithm="BAB"); vs @@ -954,8 +954,8 @@ def vertex_separation_exp(G, verbose=False): Graphs with non-integer vertices:: sage: from sage.graphs.graph_decompositions.vertex_separation import vertex_separation_exp - sage: D=digraphs.DeBruijn(2,3) - sage: vertex_separation_exp(D) + sage: D = digraphs.DeBruijn(2,3) # optional - sage.combinat + sage: vertex_separation_exp(D) # optional - sage.combinat (2, ['000', '001', '100', '010', '101', '011', '110', '111']) Given a too large graph:: @@ -1211,12 +1211,12 @@ def width_of_path_decomposition(G, L): Path decomposition of a BalancedTree:: sage: from sage.graphs.graph_decompositions import vertex_separation - sage: G = graphs.BalancedTree(3,2) - sage: pw, L = vertex_separation.path_decomposition(G) - sage: pw == vertex_separation.width_of_path_decomposition(G, L) + sage: G = graphs.BalancedTree(3,2) # optional - networkx + sage: pw, L = vertex_separation.path_decomposition(G) # optional - networkx + sage: pw == vertex_separation.width_of_path_decomposition(G, L) # optional - networkx True - sage: L.reverse() - sage: pw == vertex_separation.width_of_path_decomposition(G, L) + sage: L.reverse() # optional - networkx + sage: pw == vertex_separation.width_of_path_decomposition(G, L) # optional - networkx False Directed path decomposition of a circuit:: @@ -1305,9 +1305,9 @@ def _vertex_separation_MILP_formulation(G, integrality=False, solver=None): EXAMPLES:: sage: from sage.graphs.graph_decompositions.vertex_separation import _vertex_separation_MILP_formulation - sage: G = digraphs.DeBruijn(2,3) - sage: p, x, u, y, z = _vertex_separation_MILP_formulation(G) - sage: p + sage: G = digraphs.DeBruijn(2,3) # optional - sage.combinat + sage: p, x, u, y, z = _vertex_separation_MILP_formulation(G) # optional - sage.combinat + sage: p # optional - sage.combinat Mixed Integer Program (minimization, 193 variables, 449 constraints) """ from sage.graphs.graph import Graph @@ -1420,12 +1420,12 @@ def vertex_separation_MILP(G, integrality=False, solver=None, verbose=0, Vertex separation of a De Bruijn digraph:: sage: from sage.graphs.graph_decompositions import vertex_separation - sage: G = digraphs.DeBruijn(2,3) - sage: vs, L = vertex_separation.vertex_separation_MILP(G); vs + sage: G = digraphs.DeBruijn(2,3) # optional - sage.combinat + sage: vs, L = vertex_separation.vertex_separation_MILP(G); vs # optional - sage.combinat 2 - sage: vs == vertex_separation.width_of_path_decomposition(G, L) + sage: vs == vertex_separation.width_of_path_decomposition(G, L) # optional - sage.combinat True - sage: vse, Le = vertex_separation.vertex_separation(G); vse + sage: vse, Le = vertex_separation.vertex_separation(G); vse # optional - sage.combinat 2 The vertex separation of a circuit is 1:: diff --git a/src/sage/graphs/graph_input.py b/src/sage/graphs/graph_input.py index 1c952fcceae..39b22a44b56 100644 --- a/src/sage/graphs/graph_input.py +++ b/src/sage/graphs/graph_input.py @@ -185,8 +185,9 @@ def from_seidel_adjacency_matrix(G, M): sage: from sage.graphs.graph_input import from_seidel_adjacency_matrix sage: g = Graph() - sage: from_seidel_adjacency_matrix(g, graphs.PetersenGraph().seidel_adjacency_matrix()) - sage: g.is_isomorphic(graphs.PetersenGraph()) + sage: sam = graphs.PetersenGraph().seidel_adjacency_matrix() # optional - sage.modules + sage: from_seidel_adjacency_matrix(g, sam) # optional - sage.modules + sage: g.is_isomorphic(graphs.PetersenGraph()) # optional - sage.modules True """ from sage.structure.element import is_Matrix @@ -235,8 +236,8 @@ def from_adjacency_matrix(G, M, loops=False, multiedges=False, weighted=False): sage: from sage.graphs.graph_input import from_adjacency_matrix sage: g = Graph() - sage: from_adjacency_matrix(g, graphs.PetersenGraph().adjacency_matrix()) - sage: g.is_isomorphic(graphs.PetersenGraph()) + sage: from_adjacency_matrix(g, graphs.PetersenGraph().adjacency_matrix()) # optional - sage.modules + sage: g.is_isomorphic(graphs.PetersenGraph()) # optional - sage.modules True """ from sage.structure.element import is_Matrix @@ -311,8 +312,8 @@ def from_incidence_matrix(G, M, loops=False, multiedges=False, weighted=False): sage: from sage.graphs.graph_input import from_incidence_matrix sage: g = Graph() - sage: from_incidence_matrix(g, graphs.PetersenGraph().incidence_matrix()) - sage: g.is_isomorphic(graphs.PetersenGraph()) + sage: from_incidence_matrix(g, graphs.PetersenGraph().incidence_matrix()) # optional - sage.modules + sage: g.is_isomorphic(graphs.PetersenGraph()) # optional - sage.modules True """ from sage.structure.element import is_Matrix @@ -377,38 +378,37 @@ def from_oriented_incidence_matrix(G, M, loops=False, multiedges=False, weighted sage: from sage.graphs.graph_input import from_oriented_incidence_matrix sage: g = DiGraph() - sage: from_oriented_incidence_matrix(g, digraphs.Circuit(10).incidence_matrix()) - sage: g.is_isomorphic(digraphs.Circuit(10)) + sage: im = digraphs.Circuit(10).incidence_matrix() # optional - sage.modules + sage: from_oriented_incidence_matrix(g, im) # optional - sage.modules + sage: g.is_isomorphic(digraphs.Circuit(10)) # optional - sage.modules True TESTS: Fix bug reported in :trac:`22985`:: - sage: DiGraph(matrix ([[1,0,0,1],[0,0,1,1],[0,0,1,1]]).transpose()) + sage: DiGraph(matrix ([[1,0,0,1],[0,0,1,1],[0,0,1,1]]).transpose()) # optional - sage.modules Traceback (most recent call last): ... ValueError: each column represents an edge: -1 goes to 1 Handle incidence matrix containing a column with only zeros (:trac:`29275`):: - sage: m = Matrix([[0,1],[0,-1],[0,0]]) - sage: m + sage: m = Matrix([[0,1],[0,-1],[0,0]]); m # optional - sage.modules [ 0 1] [ 0 -1] [ 0 0] - sage: G = DiGraph(m,format='incidence_matrix') - sage: list(G.edges(sort=True, labels=False)) + sage: G = DiGraph(m, format='incidence_matrix') # optional - sage.modules + sage: list(G.edges(sort=True, labels=False)) # optional - sage.modules [(1, 0)] Handle incidence matrix [[1],[-1]] (:trac:`29275`):: - sage: m = Matrix([[1],[-1]]) - sage: m + sage: m = Matrix([[1],[-1]]); m # optional - sage.modules [ 1] [-1] - sage: G = DiGraph(m,format='incidence_matrix') - sage: list(G.edges(sort=True, labels=False)) + sage: G = DiGraph(m, format='incidence_matrix') # optional - sage.modules + sage: list(G.edges(sort=True, labels=False)) # optional - sage.modules [(1, 0)] """ from sage.structure.element import is_Matrix diff --git a/src/sage/graphs/graph_list.py b/src/sage/graphs/graph_list.py index ea84b183fb2..4a43987a79b 100644 --- a/src/sage/graphs/graph_list.py +++ b/src/sage/graphs/graph_list.py @@ -266,9 +266,9 @@ def to_graphics_array(graph_list, **kwds): options, all of which are available from :func:`to_graphics_array`:: sage: glist = [] - sage: for _ in range(10): + sage: for _ in range(10): # optional - networkx ....: glist.append(graphs.RandomLobster(41, .3, .4)) - sage: graphs_list.to_graphics_array(glist, layout='spring', vertex_size=20) # optional - sage.plot + sage: graphs_list.to_graphics_array(glist, layout='spring', vertex_size=20) # optional - networkx sage.plot Graphics Array of size 3 x 4 """ from sage.graphs import graph diff --git a/src/sage/graphs/graph_plot_js.py b/src/sage/graphs/graph_plot_js.py index 44b6274cf4c..ad846d7a474 100644 --- a/src/sage/graphs/graph_plot_js.py +++ b/src/sage/graphs/graph_plot_js.py @@ -174,14 +174,14 @@ def gen_html_code(G, sage: graphs.DodecahedralGraph().show(method="js") # optional -- internet sage.plot - sage: g = digraphs.DeBruijn(2, 2) - sage: g.allow_multiple_edges(True) - sage: g.add_edge("10", "10", "a") - sage: g.add_edge("10", "10", "b") - sage: g.add_edge("10", "10", "c") - sage: g.add_edge("10", "10", "d") - sage: g.add_edge("01", "11", "1") - sage: g.show(method="js", vertex_labels=True,edge_labels=True, # optional - sage.plot + sage: g = digraphs.DeBruijn(2, 2) # optional - sage.combinat + sage: g.allow_multiple_edges(True) # optional - sage.combinat + sage: g.add_edge("10", "10", "a") # optional - sage.combinat + sage: g.add_edge("10", "10", "b") # optional - sage.combinat + sage: g.add_edge("10", "10", "c") # optional - sage.combinat + sage: g.add_edge("10", "10", "d") # optional - sage.combinat + sage: g.add_edge("01", "11", "1") # optional - sage.combinat + sage: g.show(method="js", vertex_labels=True,edge_labels=True, # optional - sage.combinat sage.plot ....: link_distance=200, gravity=.05, charge=-500, ....: edge_partition=[[("11", "12", "2"), ("21", "21", "a")]], ....: edge_thickness=4) diff --git a/src/sage/graphs/hyperbolicity.pyx b/src/sage/graphs/hyperbolicity.pyx index 05fb3c3da79..ff2d20a4d80 100644 --- a/src/sage/graphs/hyperbolicity.pyx +++ b/src/sage/graphs/hyperbolicity.pyx @@ -146,7 +146,7 @@ Methods # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# https://www.gnu.org/licenses/ +# http://www.gnu.org/licenses/ # **************************************************************************** from libc.string cimport memset @@ -157,7 +157,7 @@ from memory_allocator cimport MemoryAllocator from sage.graphs.distances_all_pairs cimport c_distances_all_pairs from sage.arith.misc import binomial from sage.rings.integer_ring import ZZ -from sage.rings.real_mpfr import RR +from sage.data_structures.bitset import Bitset from sage.graphs.base.static_sparse_graph cimport short_digraph from sage.graphs.base.static_sparse_graph cimport init_short_digraph from sage.graphs.base.static_sparse_graph cimport free_short_digraph @@ -1287,6 +1287,8 @@ def hyperbolicity(G, elif approximation_factor == 1.0: pass elif algorithm in ['CCL', 'CCL+FA', 'BCCM']: + from sage.rings.real_mpfr import RR + if approximation_factor not in RR or approximation_factor < 1.0: raise ValueError("the approximation factor must be >= 1.0") else: @@ -1297,6 +1299,8 @@ def hyperbolicity(G, elif additive_gap == 0.0: pass elif algorithm in ['CCL', 'CCL+FA', 'BCCM']: + from sage.rings.real_mpfr import RR + if additive_gap not in RR or additive_gap < 0.0: raise ValueError("the additive gap must be a real positive number") else: diff --git a/src/sage/graphs/hypergraph_generators.py b/src/sage/graphs/hypergraph_generators.py index a106f3fc7d8..c3e42da9565 100644 --- a/src/sage/graphs/hypergraph_generators.py +++ b/src/sage/graphs/hypergraph_generators.py @@ -306,34 +306,34 @@ def BinomialRandomUniform(self, n, k, p): EXAMPLES:: - sage: hypergraphs.BinomialRandomUniform(50, 3, 1).num_blocks() + sage: hypergraphs.BinomialRandomUniform(50, 3, 1).num_blocks() # optional - numpy 19600 - sage: hypergraphs.BinomialRandomUniform(50, 3, 0).num_blocks() + sage: hypergraphs.BinomialRandomUniform(50, 3, 0).num_blocks() # optional - numpy 0 TESTS:: - sage: hypergraphs.BinomialRandomUniform(50, 3, -0.1) + sage: hypergraphs.BinomialRandomUniform(50, 3, -0.1) # optional - numpy Traceback (most recent call last): ... ValueError: edge probability should be in [0,1] - sage: hypergraphs.BinomialRandomUniform(50, 3, 1.1) + sage: hypergraphs.BinomialRandomUniform(50, 3, 1.1) # optional - numpy Traceback (most recent call last): ... ValueError: edge probability should be in [0,1] - sage: hypergraphs.BinomialRandomUniform(-50, 3, 0.17) + sage: hypergraphs.BinomialRandomUniform(-50, 3, 0.17) # optional - numpy Traceback (most recent call last): ... ValueError: number of vertices should be non-negative - sage: hypergraphs.BinomialRandomUniform(50.9, 3, 0.17) + sage: hypergraphs.BinomialRandomUniform(50.9, 3, 0.17) # optional - numpy Traceback (most recent call last): ... ValueError: number of vertices should be an integer - sage: hypergraphs.BinomialRandomUniform(50, -3, 0.17) + sage: hypergraphs.BinomialRandomUniform(50, -3, 0.17) # optional - numpy Traceback (most recent call last): ... ValueError: the uniformity should be non-negative - sage: hypergraphs.BinomialRandomUniform(50, I, 0.17) + sage: hypergraphs.BinomialRandomUniform(50, I, 0.17) # optional - numpy Traceback (most recent call last): ... ValueError: the uniformity should be an integer diff --git a/src/sage/graphs/isoperimetric_inequalities.pyx b/src/sage/graphs/isoperimetric_inequalities.pyx index b7f6510ba94..b6dfa40d06d 100644 --- a/src/sage/graphs/isoperimetric_inequalities.pyx +++ b/src/sage/graphs/isoperimetric_inequalities.pyx @@ -209,8 +209,8 @@ def edge_isoperimetric_number(g): In general, for `d`-regular graphs the edge-isoperimetric number is `d` times larger than the Cheeger constant of the graph:: - sage: g = graphs.RandomRegular(3, 10) - sage: g.edge_isoperimetric_number() == g.cheeger_constant() * 3 + sage: g = graphs.RandomRegular(3, 10) # optional - networkx + sage: g.edge_isoperimetric_number() == g.cheeger_constant() * 3 # optional - networkx True And the edge-isoperimetric constant of a disconnected graph is `0`:: diff --git a/src/sage/graphs/line_graph.pyx b/src/sage/graphs/line_graph.pyx index 25cd48de951..656c9c08909 100644 --- a/src/sage/graphs/line_graph.pyx +++ b/src/sage/graphs/line_graph.pyx @@ -176,8 +176,8 @@ def is_line_graph(g, certificate=False): This is indeed the subgraph returned:: - sage: C = graphs.PetersenGraph().is_line_graph(certificate=True)[1] - sage: C.is_isomorphic(graphs.ClawGraph()) + sage: C = graphs.PetersenGraph().is_line_graph(certificate=True)[1] # optional - sage.modules + sage: C.is_isomorphic(graphs.ClawGraph()) # optional - sage.modules True The house graph is a line graph:: @@ -188,11 +188,11 @@ def is_line_graph(g, certificate=False): But what is the graph whose line graph is the house ?:: - sage: is_line, R, isom = g.is_line_graph(certificate=True) - sage: R.sparse6_string() + sage: is_line, R, isom = g.is_line_graph(certificate=True) # optional - sage.modules + sage: R.sparse6_string() # optional - sage.modules ':DaHI~' - sage: R.show() # optional - sage.plot - sage: isom + sage: R.show() # optional - sage.modules sage.plot + sage: isom # optional - sage.modules {0: (0, 1), 1: (0, 2), 2: (1, 3), 3: (2, 3), 4: (3, 4)} TESTS: @@ -201,8 +201,8 @@ def is_line_graph(g, certificate=False): sage: g = 2 * graphs.CycleGraph(3) sage: gl = g.line_graph().relabel(inplace=False) - sage: new_g = gl.is_line_graph(certificate=True)[1] - sage: g.line_graph().is_isomorphic(gl) + sage: new_g = gl.is_line_graph(certificate=True)[1] # optional - sage.modules + sage: g.line_graph().is_isomorphic(gl) # optional - sage.modules True Verify that :trac:`29740` is fixed:: @@ -309,12 +309,12 @@ def line_graph(g, labels=True): sage: h = g.line_graph() sage: h.vertices(sort=True) [(0, 1, None), - (0, 2, None), - (0, 3, None), - (1, 2, None), - (1, 3, None), - (2, 3, None)] - sage: h.am() + (0, 2, None), + (0, 3, None), + (1, 2, None), + (1, 3, None), + (2, 3, None)] + sage: h.am() # optional - sage.modules [0 1 1 1 1 0] [1 0 1 1 0 1] [1 1 0 0 1 1] @@ -330,11 +330,11 @@ def line_graph(g, labels=True): sage: h = g.line_graph() sage: h.vertices(sort=True) [(1, 2, None), - (1, 3, None), - (1, 4, None), - (2, 3, None), - (2, 4, None), - (3, 4, None)] + (1, 3, None), + (1, 4, None), + (2, 3, None), + (2, 4, None), + (3, 4, None)] sage: h.edges(sort=True) [((1, 2, None), (2, 3, None), None), ((1, 2, None), (2, 4, None), None), diff --git a/src/sage/graphs/partial_cube.py b/src/sage/graphs/partial_cube.py index bce06dee677..f7bb3e25173 100644 --- a/src/sage/graphs/partial_cube.py +++ b/src/sage/graphs/partial_cube.py @@ -110,8 +110,8 @@ def breadth_first_level_search(G, start): EXAMPLES:: - sage: H = digraphs.DeBruijn(3,2) - sage: list(sage.graphs.partial_cube.breadth_first_level_search(H, '00')) + sage: H = digraphs.DeBruijn(3,2) # optional - sage.combinat + sage: list(sage.graphs.partial_cube.breadth_first_level_search(H, '00')) # optional - sage.combinat [{'00': {'01', '02'}}, {'01': {'10', '11', '12'}, '02': {'20', '21', '22'}}, {'10': set(), @@ -162,9 +162,9 @@ def depth_first_traversal(G, start): EXAMPLES:: - sage: H = digraphs.DeBruijn(3,2) - sage: t = list(sage.graphs.partial_cube.depth_first_traversal(H, '00')) - sage: len(t) + sage: H = digraphs.DeBruijn(3,2) # optional - sage.combinat + sage: t = list(sage.graphs.partial_cube.depth_first_traversal(H, '00')) # optional - sage.combinat + sage: len(t) # optional - sage.combinat 16 """ neighbors = G.neighbor_out_iterator diff --git a/src/sage/graphs/spanning_tree.pyx b/src/sage/graphs/spanning_tree.pyx index 2fb5124596f..179625ab743 100644 --- a/src/sage/graphs/spanning_tree.pyx +++ b/src/sage/graphs/spanning_tree.pyx @@ -569,11 +569,12 @@ def filter_kruskal_iterator(G, threshold=10000, by_weight=True, weight_function= :func:`filter_kruskal_iterator` are the same:: sage: from sage.graphs.spanning_tree import kruskal_iterator - sage: G = graphs.RandomBarabasiAlbert(50, 2) - sage: for u, v in G.edge_iterator(labels=False): + sage: G = graphs.RandomBarabasiAlbert(50, 2) # optional - networkx + sage: for u, v in G.edge_iterator(labels=False): # optional - networkx ....: G.set_edge_label(u, v, randint(1, 10)) - sage: G.weighted(True) - sage: sum(e[2] for e in kruskal_iterator(G)) == sum(e[2] for e in filter_kruskal_iterator(G, threshold=20)) + sage: G.weighted(True) # optional - networkx + sage: sum(e[2] for e in kruskal_iterator(G)) == sum(e[2] # optional - networkx + ....: for e in filter_kruskal_iterator(G, threshold=20)) True TESTS: @@ -999,11 +1000,11 @@ def random_spanning_tree(G, output_as_graph=False, by_weight=False, weight_funct Check that the spanning tree returned when using weights is a tree:: - sage: G = graphs.RandomBarabasiAlbert(50, 2) - sage: for u, v in G.edge_iterator(labels=False): + sage: G = graphs.RandomBarabasiAlbert(50, 2) # optional - networkx + sage: for u, v in G.edge_iterator(labels=False): # optional - networkx ....: G.set_edge_label(u, v, randint(1, 10)) - sage: T = G.random_spanning_tree(by_weight=True, output_as_graph=True) - sage: T.is_tree() + sage: T = G.random_spanning_tree(by_weight=True, output_as_graph=True) # optional - networkx + sage: T.is_tree() # optional - networkx True TESTS:: @@ -1087,12 +1088,12 @@ def spanning_trees(g, labels=False): sage: G = Graph([(1,2),(1,2),(1,3),(1,3),(2,3),(1,4)], multiedges=True) sage: len(list(G.spanning_trees())) 8 - sage: G.spanning_trees_count() + sage: G.spanning_trees_count() # optional - sage.modules 8 sage: G = Graph([(1,2),(2,3),(3,1),(3,4),(4,5),(4,5),(4,6)], multiedges=True) sage: len(list(G.spanning_trees())) 6 - sage: G.spanning_trees_count() + sage: G.spanning_trees_count() # optional - sage.modules 6 .. SEEALSO:: diff --git a/src/sage/graphs/strongly_regular_db.pyx b/src/sage/graphs/strongly_regular_db.pyx index 24f471edd4e..4a72a2da568 100644 --- a/src/sage/graphs/strongly_regular_db.pyx +++ b/src/sage/graphs/strongly_regular_db.pyx @@ -30,21 +30,22 @@ Functions import json import os +from libc.math cimport sqrt, floor +from libc.stdint cimport uint_fast32_t + +from sage.arith.misc import divisors, is_prime_power, is_square from sage.categories.sets_cat import EmptySetError -from sage.misc.unknown import Unknown -from sage.arith.misc import is_square -from sage.arith.misc import is_prime_power -from sage.arith.misc import divisors -from sage.misc.cachefunc import cached_function -from sage.combinat.designs.orthogonal_arrays import orthogonal_array -from sage.combinat.designs.bibd import balanced_incomplete_block_design from sage.graphs.graph import Graph -from libc.math cimport sqrt, floor -from sage.matrix.constructor import Matrix -from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF -from sage.coding.linear_code import LinearCode +from sage.misc.cachefunc import cached_function +from sage.misc.lazy_import import LazyImport +from sage.misc.unknown import Unknown from sage.rings.sum_of_squares cimport two_squares_c -from libc.stdint cimport uint_fast32_t + +orthogonal_array = LazyImport('sage.combinat.designs.orthogonal_arrays', 'orthogonal_array') +balanced_incomplete_block_design = LazyImport('sage.combinat.designs.bibd', 'balanced_incomplete_block_design') +GF = LazyImport('sage.rings.finite_rings.finite_field_constructor', 'GF') +Matrix = LazyImport('sage.matrix.constructor', 'Matrix') +LinearCode = LazyImport('sage.coding.linear_code', 'LinearCode') cdef dict _brouwer_database = None _small_srg_database = None diff --git a/src/sage/graphs/traversals.pyx b/src/sage/graphs/traversals.pyx index e07c502973e..9ebc253b6f9 100644 --- a/src/sage/graphs/traversals.pyx +++ b/src/sage/graphs/traversals.pyx @@ -338,16 +338,16 @@ def lex_BFS(G, reverse=False, tree=False, initial_vertex=None, algorithm="fast") Different orderings for different traversals:: - sage: G = digraphs.DeBruijn(2,3) - sage: G.lex_BFS(initial_vertex='000', algorithm="fast") + sage: G = digraphs.DeBruijn(2,3) # optional - sage.combinat + sage: G.lex_BFS(initial_vertex='000', algorithm="fast") # optional - sage.combinat ['000', '001', '100', '010', '011', '110', '101', '111'] - sage: G.lex_BFS(initial_vertex='000', algorithm="slow") + sage: G.lex_BFS(initial_vertex='000', algorithm="slow") # optional - sage.combinat ['000', '001', '100', '010', '011', '110', '101', '111'] - sage: G.lex_DFS(initial_vertex='000') + sage: G.lex_DFS(initial_vertex='000') # optional - sage.combinat ['000', '001', '100', '010', '101', '110', '011', '111'] - sage: G.lex_UP(initial_vertex='000') + sage: G.lex_UP(initial_vertex='000') # optional - sage.combinat ['000', '001', '010', '101', '110', '111', '011', '100'] - sage: G.lex_DOWN(initial_vertex='000') + sage: G.lex_DOWN(initial_vertex='000') # optional - sage.combinat ['000', '001', '100', '011', '010', '110', '111', '101'] TESTS: @@ -541,14 +541,14 @@ def lex_UP(G, reverse=False, tree=False, initial_vertex=None): Different orderings for different traversals:: - sage: G = digraphs.DeBruijn(2,3) - sage: G.lex_BFS(initial_vertex='000') + sage: G = digraphs.DeBruijn(2,3) # optional - sage.combinat + sage: G.lex_BFS(initial_vertex='000') # optional - sage.combinat ['000', '001', '100', '010', '011', '110', '101', '111'] - sage: G.lex_DFS(initial_vertex='000') + sage: G.lex_DFS(initial_vertex='000') # optional - sage.combinat ['000', '001', '100', '010', '101', '110', '011', '111'] - sage: G.lex_UP(initial_vertex='000') + sage: G.lex_UP(initial_vertex='000') # optional - sage.combinat ['000', '001', '010', '101', '110', '111', '011', '100'] - sage: G.lex_DOWN(initial_vertex='000') + sage: G.lex_DOWN(initial_vertex='000') # optional - sage.combinat ['000', '001', '100', '011', '010', '110', '111', '101'] TESTS: @@ -714,14 +714,14 @@ def lex_DFS(G, reverse=False, tree=False, initial_vertex=None): Different orderings for different traversals:: - sage: G = digraphs.DeBruijn(2,3) - sage: G.lex_BFS(initial_vertex='000') + sage: G = digraphs.DeBruijn(2,3) # optional - sage.combinat + sage: G.lex_BFS(initial_vertex='000') # optional - sage.combinat ['000', '001', '100', '010', '011', '110', '101', '111'] - sage: G.lex_DFS(initial_vertex='000') + sage: G.lex_DFS(initial_vertex='000') # optional - sage.combinat ['000', '001', '100', '010', '101', '110', '011', '111'] - sage: G.lex_UP(initial_vertex='000') + sage: G.lex_UP(initial_vertex='000') # optional - sage.combinat ['000', '001', '010', '101', '110', '111', '011', '100'] - sage: G.lex_DOWN(initial_vertex='000') + sage: G.lex_DOWN(initial_vertex='000') # optional - sage.combinat ['000', '001', '100', '011', '010', '110', '111', '101'] TESTS: @@ -889,14 +889,14 @@ def lex_DOWN(G, reverse=False, tree=False, initial_vertex=None): Different orderings for different traversals:: - sage: G = digraphs.DeBruijn(2,3) - sage: G.lex_BFS(initial_vertex='000') + sage: G = digraphs.DeBruijn(2,3) # optional - sage.combinat + sage: G.lex_BFS(initial_vertex='000') # optional - sage.combinat ['000', '001', '100', '010', '011', '110', '101', '111'] - sage: G.lex_DFS(initial_vertex='000') + sage: G.lex_DFS(initial_vertex='000') # optional - sage.combinat ['000', '001', '100', '010', '101', '110', '011', '111'] - sage: G.lex_UP(initial_vertex='000') + sage: G.lex_UP(initial_vertex='000') # optional - sage.combinat ['000', '001', '010', '101', '110', '111', '011', '100'] - sage: G.lex_DOWN(initial_vertex='000') + sage: G.lex_DOWN(initial_vertex='000') # optional - sage.combinat ['000', '001', '100', '011', '010', '110', '111', '101'] TESTS: diff --git a/src/sage/graphs/views.pyx b/src/sage/graphs/views.pyx index 51a4a738e46..c49511207e5 100644 --- a/src/sage/graphs/views.pyx +++ b/src/sage/graphs/views.pyx @@ -175,11 +175,11 @@ cdef class EdgesView: With a directed graph:: - sage: G = digraphs.DeBruijn(2, 2) - sage: E = EdgesView(G, labels=False, sort=True); E + sage: G = digraphs.DeBruijn(2, 2) # optional - sage.combinat + sage: E = EdgesView(G, labels=False, sort=True); E # optional - sage.combinat [('00', '00'), ('00', '01'), ('01', '10'), ('01', '11'), ('10', '00'), ('10', '01'), ('11', '10'), ('11', '11')] - sage: E = EdgesView(G, labels=False, sort=True, key=lambda e:(e[1], e[0])); E + sage: E = EdgesView(G, labels=False, sort=True, key=lambda e:(e[1], e[0])); E # optional - sage.combinat [('00', '00'), ('10', '00'), ('00', '01'), ('10', '01'), ('01', '10'), ('11', '10'), ('01', '11'), ('11', '11')]