From b0be9aaede582f887d3575fd4600fa93a2c3f3f4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 4 Jul 2023 19:45:51 -0700 Subject: [PATCH 01/10] ./sage -fixdoctests --probe all --distribution sagemath-graphs --only-tags src/sage/graphs/generators/classical_geometries.py; ./sage -fixdoctests src/sage/graphs/generators/classical_geometries.py --- .../graphs/generators/classical_geometries.py | 335 ++++++++++-------- 1 file changed, 179 insertions(+), 156 deletions(-) diff --git a/src/sage/graphs/generators/classical_geometries.py b/src/sage/graphs/generators/classical_geometries.py index 680402dc476..4e2b861b423 100644 --- a/src/sage/graphs/generators/classical_geometries.py +++ b/src/sage/graphs/generators/classical_geometries.py @@ -51,7 +51,7 @@ def SymplecticPolarGraph(d, q, algorithm=None): sage: g = graphs.SymplecticPolarGraph(6,2) sage: g.is_strongly_regular(parameters=True) (63, 30, 13, 15) - sage: set(g.spectrum()) == {-5, 3, 30} + sage: set(g.spectrum()) == {-5, 3, 30} # needs sage.rings.number_field True The parameters of `Sp(4,q)` are the same as of `O(5,q)`, but they are @@ -60,20 +60,32 @@ 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.is_strongly_regular(parameters=True) + sage: O = graphs.OrthogonalPolarGraph(5,3) # needs sage.libs.gap + sage: O.is_strongly_regular(parameters=True) # optional - EXPECTED (40, 12, 2, 4) - sage: O.is_isomorphic(G) + sage: O.is_strongly_regular(parameters=True) # optional - GOT (with --distribution 'sagemath-graphs[modules]') + Traceback (most recent call last): + ... + File "", line 1, in + O.is_strongly_regular(parameters=True) + AttributeError: 'function' object has no attribute 'is_strongly_regular' + sage: O.is_isomorphic(G) # optional - EXPECTED False - 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 + sage: O.is_isomorphic(G) # optional - GOT (with --distribution 'sagemath-graphs[modules]') + Traceback (most recent call last): + ... + File "", line 1, in + O.is_isomorphic(G) + AttributeError: 'function' object has no attribute 'is_isomorphic' + sage: S = graphs.SymplecticPolarGraph(6,4,algorithm="gap") # not tested (long time), needs sage.libs.gap + sage: S.is_strongly_regular(parameters=True) # not tested (long time), needs sage.libs.gap (1365, 340, 83, 85) TESTS:: - sage: graphs.SymplecticPolarGraph(4,4,algorithm="gap").is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: graphs.SymplecticPolarGraph(4,4,algorithm="gap").is_strongly_regular(parameters=True) # needs sage.libs.gap (85, 20, 3, 5) - sage: graphs.SymplecticPolarGraph(4,4).is_strongly_regular(parameters=True) + sage: graphs.SymplecticPolarGraph(4,4).is_strongly_regular(parameters=True) # needs sage.libs.pari (85, 20, 3, 5) sage: graphs.SymplecticPolarGraph(4,4,algorithm="blah") Traceback (most recent call last): @@ -147,31 +159,31 @@ def AffineOrthogonalPolarGraph(d, q, sign="+"): The :meth:`Brouwer-Haemers graph ` is isomorphic to `VO^-(4,3)`:: - sage: g = graphs.AffineOrthogonalPolarGraph(4,3,"-") - sage: g.is_isomorphic(graphs.BrouwerHaemersGraph()) + sage: g = graphs.AffineOrthogonalPolarGraph(4,3,"-") # needs sage.libs.gap + sage: g.is_isomorphic(graphs.BrouwerHaemersGraph()) # optional - NameError: 'g' (with --distribution 'sagemath-graphs[modules]') True Some examples from `Brouwer's table or strongly regular graphs `_:: - sage: g = graphs.AffineOrthogonalPolarGraph(6,2,"-"); g + sage: g = graphs.AffineOrthogonalPolarGraph(6,2,"-"); g # needs sage.libs.gap Affine Polar Graph VO^-(6,2): Graph on 64 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - NameError: 'g' (with --distribution 'sagemath-graphs[modules]') (64, 27, 10, 12) - sage: g = graphs.AffineOrthogonalPolarGraph(6,2,"+"); g + sage: g = graphs.AffineOrthogonalPolarGraph(6,2,"+"); g # needs sage.libs.gap Affine Polar Graph VO^+(6,2): Graph on 64 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - NameError: 'g' (with --distribution 'sagemath-graphs[modules]') (64, 35, 18, 20) When ``sign is None``:: - sage: g = graphs.AffineOrthogonalPolarGraph(5,2,None); g + sage: g = graphs.AffineOrthogonalPolarGraph(5,2,None); g # needs sage.libs.gap Affine Polar Graph VO^-(5,2): Graph on 32 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # optional - NameError: 'g' (with --distribution 'sagemath-graphs[modules]') False - sage: g.is_regular() + sage: g.is_regular() # optional - NameError: 'g' (with --distribution 'sagemath-graphs[modules]') True - sage: g.is_vertex_transitive() + sage: g.is_vertex_transitive() # optional - NameError: 'g' (with --distribution 'sagemath-graphs[modules]') True """ if sign in ["+", "-"]: @@ -224,14 +236,14 @@ 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]) # optional - sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: g = _orthogonal_polar_graph(3,5,point_type=[2,3]) # needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # needs 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]) # optional - sage.libs.gap - sage: g.is_distance_regular(parameters=True) # optional - sage.libs.gap + sage: g = _orthogonal_polar_graph(4,5,'-',point_type=[2,3]) # needs sage.libs.gap + sage: g.is_distance_regular(parameters=True) # needs sage.libs.gap ([10, 6, 4, None], [None, 1, 2, 5]) Various big and slow to build graphs: @@ -250,20 +262,20 @@ def _orthogonal_polar_graph(m, q, sign="+", point_type=[0]): `NO^+(6,3)`:: - 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 + sage: g = _orthogonal_polar_graph(6,3,point_type=[1]) # needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap (117, 36, 15, 9) `NO^-(6,3)`:: - 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 + sage: g = _orthogonal_polar_graph(6,3,'-',point_type=[1]) # needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap (126, 45, 12, 18) `NO^{-,\perp}(5,5)`:: - 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 + sage: g = _orthogonal_polar_graph(5,5,point_type=[2,3]) # long time, needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time, needs sage.libs.gap (300, 65, 10, 15) `NO^{+,\perp}(5,5)`:: @@ -274,11 +286,12 @@ def _orthogonal_polar_graph(m, q, sign="+", point_type=[0]): TESTS:: - 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 + sage: # needs sage.libs.gap + sage: g = _orthogonal_polar_graph(5,3,point_type=[-1]) + sage: g.is_strongly_regular(parameters=True) (45, 12, 3, 3) - 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 + sage: g = _orthogonal_polar_graph(5,3,point_type=[1]) + sage: g.is_strongly_regular(parameters=True) (36, 15, 6, 6) """ @@ -342,34 +355,35 @@ def OrthogonalPolarGraph(m, q, sign="+"): EXAMPLES:: - sage: G = graphs.OrthogonalPolarGraph(6,3,"+"); G # optional - sage.libs.gap + sage: # needs sage.libs.gap + sage: G = graphs.OrthogonalPolarGraph(6,3,"+"); G Orthogonal Polar Graph O^+(6, 3): Graph on 130 vertices - sage: G.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: G.is_strongly_regular(parameters=True) (130, 48, 20, 16) - sage: G = graphs.OrthogonalPolarGraph(6,3,"-"); G # optional - sage.libs.gap + sage: G = graphs.OrthogonalPolarGraph(6,3,"-"); G Orthogonal Polar Graph O^-(6, 3): Graph on 112 vertices - sage: G.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: G.is_strongly_regular(parameters=True) (112, 30, 2, 10) - sage: G = graphs.OrthogonalPolarGraph(5,3); G # optional - sage.libs.gap + sage: G = graphs.OrthogonalPolarGraph(5,3); G Orthogonal Polar Graph O(5, 3): Graph on 40 vertices - sage: G.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: G.is_strongly_regular(parameters=True) (40, 12, 2, 4) - sage: G = graphs.OrthogonalPolarGraph(8,2,"+"); G # optional - sage.libs.gap + sage: G = graphs.OrthogonalPolarGraph(8,2,"+"); G Orthogonal Polar Graph O^+(8, 2): Graph on 135 vertices - sage: G.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: G.is_strongly_regular(parameters=True) (135, 70, 37, 35) - sage: G = graphs.OrthogonalPolarGraph(8,2,"-"); G # optional - sage.libs.gap + sage: G = graphs.OrthogonalPolarGraph(8,2,"-"); G Orthogonal Polar Graph O^-(8, 2): Graph on 119 vertices - sage: G.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: G.is_strongly_regular(parameters=True) (119, 54, 21, 27) TESTS:: - sage: G = graphs.OrthogonalPolarGraph(4,3,"") # optional - sage.libs.gap + sage: G = graphs.OrthogonalPolarGraph(4,3,"") # needs 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,"-") # optional - sage.libs.gap + sage: G = graphs.OrthogonalPolarGraph(5,3,"-") # needs sage.libs.gap Traceback (most recent call last): ... ValueError: sign must be equal to either '' or '+' when m is odd @@ -417,43 +431,45 @@ def NonisotropicOrthogonalPolarGraph(m, q, sign="+", perp=None): `NO^-(4,2)` is isomorphic to Petersen graph:: - sage: g = graphs.NonisotropicOrthogonalPolarGraph(4,2,'-'); g # optional - sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(4,2,'-'); g # needs sage.libs.gap NO^-(4, 2): Graph on 10 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap (10, 3, 0, 1) `NO^-(6,2)` and `NO^+(6,2)`:: - sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,2,'-') # optional - sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: # needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,2,'-') + sage: g.is_strongly_regular(parameters=True) (36, 15, 6, 6) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,2,'+'); g # optional - sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,2,'+'); g NO^+(6, 2): Graph on 28 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) (28, 15, 6, 10) `NO^+(8,2)`:: - sage: g = graphs.NonisotropicOrthogonalPolarGraph(8,2,'+') # optional - sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(8,2,'+') # needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap (120, 63, 30, 36) Wilbrink's graphs for `q=5`:: - 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 + sage: # needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,perp=1) + sage: g.is_strongly_regular(parameters=True) # long time (325, 60, 15, 10) - 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 + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'-',perp=1) + sage: g.is_strongly_regular(parameters=True) # long time (300, 65, 10, 15) Wilbrink's graphs:: - sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,4,'+') # optional - sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,4,'+') # needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap (136, 75, 42, 40) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,4,'-') # optional - sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,4,'-') # needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap (120, 51, 18, 24) sage: g = graphs.NonisotropicOrthogonalPolarGraph(7,4,'+'); g # not tested (long time) NO^+(7, 4): Graph on 2080 vertices @@ -462,29 +478,29 @@ def NonisotropicOrthogonalPolarGraph(m, q, sign="+", perp=None): TESTS:: - sage: g = graphs.NonisotropicOrthogonalPolarGraph(4,2); g # optional - sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(4,2); g # needs sage.libs.gap NO^+(4, 2): Graph on 6 vertices - sage: g = graphs.NonisotropicOrthogonalPolarGraph(4,3,'-') # optional - sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(4,3,'-') # needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap (15, 6, 1, 3) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(3,5,'-',perp=1); g # optional - sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(3,5,'-',perp=1); g # needs sage.libs.gap NO^-,perp(3, 5): Graph on 10 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap (10, 3, 0, 1) - 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 + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'+') # long time, needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time, needs sage.libs.gap (117, 36, 15, 9) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'-'); g # long time, optional - sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'-'); g # long time, needs sage.libs.gap NO^-(6, 3): Graph on 126 vertices - sage: g.is_strongly_regular(parameters=True) # long time, optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time, needs sage.libs.gap (126, 45, 12, 18) - 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 + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'-') # long time, needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time, needs sage.libs.gap (300, 104, 28, 40) - 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 + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'+') # long time, needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time, needs sage.libs.gap (325, 144, 68, 60) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,4,'+') # optional - sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,4,'+') Traceback (most recent call last): ... ValueError: for m even q must be 2 or 3 @@ -565,9 +581,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)) # optional - sage.libs.gap + sage: _polar_graph(4, 4, libgap.GeneralUnitaryGroup(4, 2)) # needs sage.libs.gap Graph on 45 vertices - sage: _polar_graph(4, 4, libgap.GeneralUnitaryGroup(4, 2), intersection_size=1) # optional - sage.libs.gap + sage: _polar_graph(4, 4, libgap.GeneralUnitaryGroup(4, 2), intersection_size=1) # needs sage.libs.gap Graph on 27 vertices """ from sage.libs.gap.libgap import libgap @@ -609,20 +625,21 @@ def UnitaryPolarGraph(m, q, algorithm="gap"): EXAMPLES:: - sage: G = graphs.UnitaryPolarGraph(4,2); G # optional - sage.libs.gap + sage: # needs sage.libs.gap + sage: G = graphs.UnitaryPolarGraph(4,2); G Unitary Polar Graph U(4, 2); GQ(4, 2): Graph on 45 vertices - sage: G.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: G.is_strongly_regular(parameters=True) (45, 12, 3, 3) - sage: graphs.UnitaryPolarGraph(5,2).is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: graphs.UnitaryPolarGraph(5,2).is_strongly_regular(parameters=True) (165, 36, 3, 9) - sage: graphs.UnitaryPolarGraph(6,2) # not tested (long time) # optional - sage.libs.gap + sage: graphs.UnitaryPolarGraph(6,2) # not tested (long time) Unitary Polar Graph U(6, 2): Graph on 693 vertices TESTS:: - sage: graphs.UnitaryPolarGraph(4,3, algorithm="gap").is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: graphs.UnitaryPolarGraph(4,3, algorithm="gap").is_strongly_regular(parameters=True) # needs sage.libs.gap (280, 36, 8, 4) - sage: graphs.UnitaryPolarGraph(4,3).is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: graphs.UnitaryPolarGraph(4,3).is_strongly_regular(parameters=True) # needs sage.libs.gap (280, 36, 8, 4) sage: graphs.UnitaryPolarGraph(4,3, algorithm="foo") Traceback (most recent call last): @@ -676,18 +693,18 @@ def NonisotropicUnitaryPolarGraph(m, q): EXAMPLES:: - sage: g = graphs.NonisotropicUnitaryPolarGraph(5,2); g # optional - sage.libs.gap + sage: g = graphs.NonisotropicUnitaryPolarGraph(5,2); g # needs sage.libs.gap NU(5, 2): Graph on 176 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap (176, 135, 102, 108) TESTS:: - sage: graphs.NonisotropicUnitaryPolarGraph(4,2).is_strongly_regular(parameters=True) # optional - sage.libs.gap + sage: graphs.NonisotropicUnitaryPolarGraph(4,2).is_strongly_regular(parameters=True) # needs sage.libs.gap (40, 27, 18, 18) - sage: graphs.NonisotropicUnitaryPolarGraph(4,3).is_strongly_regular(parameters=True) # long time, optional - sage.libs.gap + sage: graphs.NonisotropicUnitaryPolarGraph(4,3).is_strongly_regular(parameters=True) # long time, needs sage.libs.gap (540, 224, 88, 96) - sage: graphs.NonisotropicUnitaryPolarGraph(6,6) # optional - sage.libs.gap + sage: graphs.NonisotropicUnitaryPolarGraph(6,6) Traceback (most recent call last): ... ValueError: q must be a prime power @@ -742,16 +759,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 # optional - sage.libs.gap + sage: G = graphs.UnitaryDualPolarGraph(5,2); G # long time, needs 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 # optional - sage.libs.gap + sage: G.is_strongly_regular(parameters=True) # long time, needs 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 # optional - sage.libs.gap + sage: G = graphs.UnitaryDualPolarGraph(4,2); G # needs 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,'-')) # optional - sage.libs.gap + sage: G.is_isomorphic(graphs.OrthogonalPolarGraph(6,2,'-')) # needs sage.libs.gap True A bigger graph:: @@ -763,7 +780,7 @@ def UnitaryDualPolarGraph(m, q): TESTS:: - sage: graphs.UnitaryDualPolarGraph(6,6) # optional - sage.libs.gap + sage: graphs.UnitaryDualPolarGraph(6,6) # needs sage.libs.gap Traceback (most recent call last): ... GAPError: Error, must be a prime or a finite field @@ -800,11 +817,11 @@ def SymplecticDualPolarGraph(m, q): TESTS:: - sage: G = graphs.SymplecticDualPolarGraph(6,2); G # optional - sage.libs.gap + sage: G = graphs.SymplecticDualPolarGraph(6,2); G # needs sage.libs.gap Symplectic Dual Polar Graph DSp(6, 2): Graph on 135 vertices - sage: G.is_distance_regular(parameters=True) # optional - sage.libs.gap + sage: G.is_distance_regular(parameters=True) # needs sage.libs.gap ([14, 12, 8, None], [None, 1, 3, 7]) - sage: graphs.SymplecticDualPolarGraph(6,6) # optional - sage.libs.gap + sage: graphs.SymplecticDualPolarGraph(6,6) # needs sage.libs.gap Traceback (most recent call last): ... GAPError: Error, must be a prime or a finite field @@ -848,13 +865,13 @@ def TaylorTwographDescendantSRG(q, clique_partition=False): EXAMPLES:: - sage: g = graphs.TaylorTwographDescendantSRG(3); g # optional - sage.rings.finite_rings + sage: g = graphs.TaylorTwographDescendantSRG(3); g # needs sage.rings.finite_rings Taylor two-graph descendant SRG: Graph on 27 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings (27, 10, 1, 5) sage: from sage.combinat.designs.twographs import taylor_twograph - 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 + sage: T = taylor_twograph(3) # long time, needs sage.rings.finite_rings + sage: g.is_isomorphic(T.descendant(T.ground_set()[1])) # long time, needs 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) @@ -862,14 +879,14 @@ def TaylorTwographDescendantSRG(q, clique_partition=False): TESTS:: - 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 + sage: g,l,_ = graphs.TaylorTwographDescendantSRG(3, clique_partition=True) # needs sage.rings.finite_rings + sage: all(g.is_clique(x) for x in l) # needs sage.rings.finite_rings True - sage: graphs.TaylorTwographDescendantSRG(4) # optional - sage.rings.finite_rings + sage: graphs.TaylorTwographDescendantSRG(4) Traceback (most recent call last): ... ValueError: q must be an odd prime power - sage: graphs.TaylorTwographDescendantSRG(6) # optional - sage.rings.finite_rings + sage: graphs.TaylorTwographDescendantSRG(6) Traceback (most recent call last): ... ValueError: q must be an odd prime power @@ -922,9 +939,9 @@ def TaylorTwographSRG(q): EXAMPLES:: - sage: t = graphs.TaylorTwographSRG(3); t # optional - sage.rings.finite_rings + sage: t = graphs.TaylorTwographSRG(3); t # needs sage.rings.finite_rings Taylor two-graph SRG: Graph on 28 vertices - sage: t.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings + sage: t.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings (28, 15, 6, 10) """ G, l, v0 = TaylorTwographDescendantSRG(q, clique_partition=True) @@ -959,13 +976,13 @@ def AhrensSzekeresGeneralizedQuadrangleGraph(q, dual=False): EXAMPLES:: - sage: g = graphs.AhrensSzekeresGeneralizedQuadrangleGraph(5); g # optional - sage.rings.finite_rings + sage: g = graphs.AhrensSzekeresGeneralizedQuadrangleGraph(5); g AS(5); GQ(4, 6): Graph on 125 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) (125, 28, 3, 7) - sage: g = graphs.AhrensSzekeresGeneralizedQuadrangleGraph(5, dual=True); g # optional - sage.rings.finite_rings + sage: g = graphs.AhrensSzekeresGeneralizedQuadrangleGraph(5, dual=True); g AS(5)*; GQ(6, 4): Graph on 175 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) (175, 30, 5, 5) """ from sage.combinat.designs.incidence_structures import IncidenceStructure @@ -1029,35 +1046,37 @@ def T2starGeneralizedQuadrangleGraph(q, dual=False, hyperoval=None, field=None, using the built-in construction:: - sage: g = graphs.T2starGeneralizedQuadrangleGraph(4); g # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: g = graphs.T2starGeneralizedQuadrangleGraph(4); g T2*(O,4); GQ(3, 5): Graph on 64 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) (64, 18, 2, 6) - sage: g = graphs.T2starGeneralizedQuadrangleGraph(4, dual=True); g # optional - sage.rings.finite_rings + sage: g = graphs.T2starGeneralizedQuadrangleGraph(4, dual=True); g T2*(O,4)*; GQ(5, 3): Graph on 96 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) (96, 20, 4, 4) supplying your own hyperoval:: - 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 + sage: # needs sage.rings.finite_rings + 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 # optional - sage.rings.finite_rings + sage: g = graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F); g T2*(O,4); GQ(3, 5): Graph on 64 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) (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] # optional - sage.rings.finite_rings - sage: graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F) # optional - sage.rings.finite_rings + sage: F = GF(4,'b') # repeating a point... # needs sage.libs.pari + 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] # needs sage.rings.finite_rings + sage: graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F) # needs 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] # optional - sage.rings.finite_rings - sage: graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F) # optional - sage.rings.finite_rings + 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] # needs sage.rings.finite_rings + sage: graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F) # needs sage.rings.finite_rings Traceback (most recent call last): ... RuntimeError: incorrect hyperoval @@ -1149,35 +1168,36 @@ def HaemersGraph(q, hyperoval=None, hyperoval_matching=None, field=None, check_h using the built-in constructions:: - sage: g = graphs.HaemersGraph(4); g # optional - sage.rings.finite_rings + sage: g = graphs.HaemersGraph(4); g # needs sage.rings.finite_rings Haemers(4): Graph on 96 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) # needs 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 # optional - sage.rings.finite_rings + sage: g = graphs.HaemersGraph(4, hyperoval_matching=((0,5),(1,4),(2,3))); g # needs sage.rings.finite_rings Haemers(4): Graph on 96 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings (96, 19, 2, 4) TESTS:: - 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 + sage: # needs sage.rings.finite_rings + 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) 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] # optional - sage.rings.finite_rings - sage: graphs.HaemersGraph(4, hyperoval=O, field=F) # optional - sage.rings.finite_rings + 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) Traceback (most recent call last): ... RuntimeError: incorrect hyperoval - sage: g = graphs.HaemersGraph(8); g # not tested (long time) # optional - sage.rings.finite_rings + sage: g = graphs.HaemersGraph(8); g # not tested (long time), needs sage.rings.finite_rings Haemers(8): Graph on 640 vertices - sage: g.is_strongly_regular(parameters=True) # not tested (long time) # optional - sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) # not tested (long time), needs sage.rings.finite_rings (640, 71, 6, 8) """ @@ -1372,9 +1392,9 @@ def Nowhere0WordsTwoWeightCodeGraph(q, hyperoval=None, field=None, check_hyperov using the built-in construction:: - sage: g = graphs.Nowhere0WordsTwoWeightCodeGraph(8); g # optional - sage.rings.finite_rings + sage: g = graphs.Nowhere0WordsTwoWeightCodeGraph(8); g # needs sage.rings.finite_rings Nowhere0WordsTwoWeightCodeGraph(8): Graph on 196 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) # needs 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) @@ -1382,24 +1402,25 @@ def Nowhere0WordsTwoWeightCodeGraph(q, hyperoval=None, field=None, check_hyperov supplying your own hyperoval:: + sage: # needs sage.rings.finite_rings 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 + 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 # optional - sage.rings.finite_rings + sage: g = graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F); g Nowhere0WordsTwoWeightCodeGraph(8): Graph on 196 vertices - sage: g.is_strongly_regular(parameters=True) # optional - sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) (196, 60, 14, 20) TESTS:: - 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 + sage: F = GF(8) # repeating a point... # needs 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] # needs sage.rings.finite_rings + sage: graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F) # needs 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] # optional - sage.rings.finite_rings - sage: graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F) + sage: O = [vector(F,(1,1,0)),vector(F,(0,1,0))]+[vector(F, (1,x^2,x)) for x in F] # needs sage.rings.finite_rings + sage: graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F) # optional - NameError: 'F' (with --distribution 'sagemath-graphs[modules]') Traceback (most recent call last): ... RuntimeError: incorrect hyperoval @@ -1467,13 +1488,14 @@ def OrthogonalDualPolarGraph(e, d, q): EXAMPLES:: - sage: G = graphs.OrthogonalDualPolarGraph(1,3,2) # optional - sage.libs.gap - sage: G.is_distance_regular(True) # optional - sage.libs.gap + sage: # needs sage.libs.gap + sage: G = graphs.OrthogonalDualPolarGraph(1,3,2) + sage: G.is_distance_regular(True) ([7, 6, 4, None], [None, 1, 3, 7]) - 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 + sage: G = graphs.OrthogonalDualPolarGraph(0,3,3) # long time + sage: G.is_distance_regular(True) # long time ([39, 36, 27, None], [None, 1, 4, 13]) - sage: G.order() # long time # optional - sage.libs.gap + sage: G.order() # long time 1120 REFERENCES: @@ -1482,17 +1504,18 @@ def OrthogonalDualPolarGraph(e, d, q): TESTS:: - sage: G = graphs.OrthogonalDualPolarGraph(0,3,2) # optional - sage.libs.gap - sage: G.is_distance_regular(True) # optional - sage.libs.gap + sage: # needs sage.libs.gap + sage: G = graphs.OrthogonalDualPolarGraph(0,3,2) + sage: G.is_distance_regular(True) ([14, 12, 8, None], [None, 1, 3, 7]) - 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 + sage: G = graphs.OrthogonalDualPolarGraph(-1,3,2) # long time + sage: G.is_distance_regular(True) # long time ([28, 24, 16, None], [None, 1, 3, 7]) - sage: G = graphs.OrthogonalDualPolarGraph(1,3,4) # optional - sage.libs.gap - sage: G.is_distance_regular(True) # optional - sage.libs.gap + sage: G = graphs.OrthogonalDualPolarGraph(1,3,4) + sage: G.is_distance_regular(True) ([21, 20, 16, None], [None, 1, 5, 21]) - sage: G = graphs.OrthogonalDualPolarGraph(1,4,2) # optional - sage.libs.gap - sage: G.is_distance_regular(True) # optional - sage.libs.gap + sage: G = graphs.OrthogonalDualPolarGraph(1,4,2) + sage: G.is_distance_regular(True) ([15, 14, 12, 8, None], [None, 1, 3, 7, 15]) """ from sage.libs.gap.libgap import libgap From ce9e3674f6b76657bb7781134c183a8866e4a32d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 2 Aug 2023 15:49:38 -0700 Subject: [PATCH 02/10] src/sage/graphs/generators/classical_geometries.py: Fix up # needs --- .../graphs/generators/classical_geometries.py | 143 +++++++++--------- 1 file changed, 71 insertions(+), 72 deletions(-) diff --git a/src/sage/graphs/generators/classical_geometries.py b/src/sage/graphs/generators/classical_geometries.py index 4e2b861b423..7ef70020a14 100644 --- a/src/sage/graphs/generators/classical_geometries.py +++ b/src/sage/graphs/generators/classical_geometries.py @@ -48,7 +48,7 @@ def SymplecticPolarGraph(d, q, algorithm=None): Computation of the spectrum of `Sp(6,2)`:: - sage: g = graphs.SymplecticPolarGraph(6,2) + sage: g = graphs.SymplecticPolarGraph(6, 2) sage: g.is_strongly_regular(parameters=True) (63, 30, 13, 15) sage: set(g.spectrum()) == {-5, 3, 30} # needs sage.rings.number_field @@ -57,28 +57,18 @@ def SymplecticPolarGraph(d, q, algorithm=None): The parameters of `Sp(4,q)` are the same as of `O(5,q)`, but they are not isomorphic if `q` is odd:: - sage: G = graphs.SymplecticPolarGraph(4,3) + sage: G = graphs.SymplecticPolarGraph(4, 3) sage: G.is_strongly_regular(parameters=True) (40, 12, 2, 4) - sage: O = graphs.OrthogonalPolarGraph(5,3) # needs sage.libs.gap - sage: O.is_strongly_regular(parameters=True) # optional - EXPECTED + + sage: # needs sage.libs.gap + sage: O = graphs.OrthogonalPolarGraph(5, 3) + sage: O.is_strongly_regular(parameters=True) (40, 12, 2, 4) - sage: O.is_strongly_regular(parameters=True) # optional - GOT (with --distribution 'sagemath-graphs[modules]') - Traceback (most recent call last): - ... - File "", line 1, in - O.is_strongly_regular(parameters=True) - AttributeError: 'function' object has no attribute 'is_strongly_regular' - sage: O.is_isomorphic(G) # optional - EXPECTED + sage: O.is_isomorphic(G) False - sage: O.is_isomorphic(G) # optional - GOT (with --distribution 'sagemath-graphs[modules]') - Traceback (most recent call last): - ... - File "", line 1, in - O.is_isomorphic(G) - AttributeError: 'function' object has no attribute 'is_isomorphic' - sage: S = graphs.SymplecticPolarGraph(6,4,algorithm="gap") # not tested (long time), needs sage.libs.gap - sage: S.is_strongly_regular(parameters=True) # not tested (long time), needs sage.libs.gap + sage: S = graphs.SymplecticPolarGraph(6, 4, algorithm="gap") # not tested (long time) + sage: S.is_strongly_regular(parameters=True) # not tested (long time) (1365, 340, 83, 85) TESTS:: @@ -160,30 +150,32 @@ def AffineOrthogonalPolarGraph(d, q, sign="+"): `VO^-(4,3)`:: sage: g = graphs.AffineOrthogonalPolarGraph(4,3,"-") # needs sage.libs.gap - sage: g.is_isomorphic(graphs.BrouwerHaemersGraph()) # optional - NameError: 'g' (with --distribution 'sagemath-graphs[modules]') + sage: g.is_isomorphic(graphs.BrouwerHaemersGraph()) # needs sage.libs.gap True Some examples from `Brouwer's table or strongly regular graphs `_:: - sage: g = graphs.AffineOrthogonalPolarGraph(6,2,"-"); g # needs sage.libs.gap + sage: # needs sage.libs.gap + sage: g = graphs.AffineOrthogonalPolarGraph(6,2,"-"); g Affine Polar Graph VO^-(6,2): Graph on 64 vertices - sage: g.is_strongly_regular(parameters=True) # optional - NameError: 'g' (with --distribution 'sagemath-graphs[modules]') + sage: g.is_strongly_regular(parameters=True) (64, 27, 10, 12) - sage: g = graphs.AffineOrthogonalPolarGraph(6,2,"+"); g # needs sage.libs.gap + sage: g = graphs.AffineOrthogonalPolarGraph(6,2,"+"); g Affine Polar Graph VO^+(6,2): Graph on 64 vertices - sage: g.is_strongly_regular(parameters=True) # optional - NameError: 'g' (with --distribution 'sagemath-graphs[modules]') + sage: g.is_strongly_regular(parameters=True) (64, 35, 18, 20) When ``sign is None``:: - sage: g = graphs.AffineOrthogonalPolarGraph(5,2,None); g # needs sage.libs.gap + sage: # needs sage.libs.gap + sage: g = graphs.AffineOrthogonalPolarGraph(5,2,None); g Affine Polar Graph VO^-(5,2): Graph on 32 vertices - sage: g.is_strongly_regular(parameters=True) # optional - NameError: 'g' (with --distribution 'sagemath-graphs[modules]') + sage: g.is_strongly_regular(parameters=True) False - sage: g.is_regular() # optional - NameError: 'g' (with --distribution 'sagemath-graphs[modules]') + sage: g.is_regular() True - sage: g.is_vertex_transitive() # optional - NameError: 'g' (with --distribution 'sagemath-graphs[modules]') + sage: g.is_vertex_transitive() True """ if sign in ["+", "-"]: @@ -275,7 +267,7 @@ def _orthogonal_polar_graph(m, q, sign="+", point_type=[0]): `NO^{-,\perp}(5,5)`:: sage: g = _orthogonal_polar_graph(5,5,point_type=[2,3]) # long time, needs sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # long time, needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time # needs sage.libs.gap (300, 65, 10, 15) `NO^{+,\perp}(5,5)`:: @@ -465,11 +457,12 @@ def NonisotropicOrthogonalPolarGraph(m, q, sign="+", perp=None): Wilbrink's graphs:: - sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,4,'+') # needs sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap + sage: # needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,4,'+') + sage: g.is_strongly_regular(parameters=True) (136, 75, 42, 40) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,4,'-') # needs sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,4,'-') + sage: g.is_strongly_regular(parameters=True) (120, 51, 18, 24) sage: g = graphs.NonisotropicOrthogonalPolarGraph(7,4,'+'); g # not tested (long time) NO^+(7, 4): Graph on 2080 vertices @@ -478,27 +471,28 @@ def NonisotropicOrthogonalPolarGraph(m, q, sign="+", perp=None): TESTS:: - sage: g = graphs.NonisotropicOrthogonalPolarGraph(4,2); g # needs sage.libs.gap + sage: # needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(4,2); g NO^+(4, 2): Graph on 6 vertices - sage: g = graphs.NonisotropicOrthogonalPolarGraph(4,3,'-') # needs sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(4,3,'-') + sage: g.is_strongly_regular(parameters=True) (15, 6, 1, 3) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(3,5,'-',perp=1); g # needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(3,5,'-',perp=1); g NO^-,perp(3, 5): Graph on 10 vertices - sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) (10, 3, 0, 1) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'+') # long time, needs sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # long time, needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'+') # long time + sage: g.is_strongly_regular(parameters=True) # long time (117, 36, 15, 9) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'-'); g # long time, needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'-'); g # long time NO^-(6, 3): Graph on 126 vertices - sage: g.is_strongly_regular(parameters=True) # long time, needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time (126, 45, 12, 18) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'-') # long time, needs sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # long time, needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'-') # long time + sage: g.is_strongly_regular(parameters=True) # long time (300, 104, 28, 40) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'+') # long time, needs sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # long time, needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'+') # long time + sage: g.is_strongly_regular(parameters=True) # long time (325, 144, 68, 60) sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,4,'+') Traceback (most recent call last): @@ -581,7 +575,7 @@ 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)) # needs sage.libs.gap + sage: _polar_graph(4, 4, libgap.GeneralUnitaryGroup(4, 2)) # needs sage.libs.gap Graph on 45 vertices sage: _polar_graph(4, 4, libgap.GeneralUnitaryGroup(4, 2), intersection_size=1) # needs sage.libs.gap Graph on 27 vertices @@ -759,9 +753,9 @@ 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, needs sage.libs.gap + sage: G = graphs.UnitaryDualPolarGraph(5,2); G # long time # needs 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, needs sage.libs.gap + sage: G.is_strongly_regular(parameters=True) # long time # needs sage.libs.gap (297, 40, 7, 5) Another way to get the generalized quadrangle of order (2,4):: @@ -865,13 +859,14 @@ def TaylorTwographDescendantSRG(q, clique_partition=False): EXAMPLES:: - sage: g = graphs.TaylorTwographDescendantSRG(3); g # needs sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: g = graphs.TaylorTwographDescendantSRG(3); g Taylor two-graph descendant SRG: Graph on 27 vertices - sage: g.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) (27, 10, 1, 5) sage: from sage.combinat.designs.twographs import taylor_twograph - sage: T = taylor_twograph(3) # long time, needs sage.rings.finite_rings - sage: g.is_isomorphic(T.descendant(T.ground_set()[1])) # long time, needs sage.rings.finite_rings + sage: T = taylor_twograph(3) # long time + sage: g.is_isomorphic(T.descendant(T.ground_set()[1])) # long time True sage: g = graphs.TaylorTwographDescendantSRG(5) # not tested (long time) sage: g.is_strongly_regular(parameters=True) # not tested (long time) @@ -879,8 +874,9 @@ def TaylorTwographDescendantSRG(q, clique_partition=False): TESTS:: - sage: g,l,_ = graphs.TaylorTwographDescendantSRG(3, clique_partition=True) # needs sage.rings.finite_rings - sage: all(g.is_clique(x) for x in l) # needs sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: g,l,_ = graphs.TaylorTwographDescendantSRG(3, clique_partition=True) + sage: all(g.is_clique(x) for x in l) True sage: graphs.TaylorTwographDescendantSRG(4) Traceback (most recent call last): @@ -1069,14 +1065,15 @@ def T2starGeneralizedQuadrangleGraph(q, dual=False, hyperoval=None, field=None, TESTS:: - sage: F = GF(4,'b') # repeating a point... # needs sage.libs.pari - 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] # needs sage.rings.finite_rings - sage: graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F) # needs sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + 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) 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] # needs sage.rings.finite_rings - sage: graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F) # needs sage.rings.finite_rings + 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) Traceback (most recent call last): ... RuntimeError: incorrect hyperoval @@ -1183,21 +1180,21 @@ def HaemersGraph(q, hyperoval=None, hyperoval_matching=None, field=None, check_h TESTS:: sage: # needs sage.rings.finite_rings - 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: 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) 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: 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) Traceback (most recent call last): ... RuntimeError: incorrect hyperoval - sage: g = graphs.HaemersGraph(8); g # not tested (long time), needs sage.rings.finite_rings + sage: g = graphs.HaemersGraph(8); g # not tested (long time) # needs sage.rings.finite_rings Haemers(8): Graph on 640 vertices - sage: g.is_strongly_regular(parameters=True) # not tested (long time), needs sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) # not tested (long time) # needs sage.rings.finite_rings (640, 71, 6, 8) """ @@ -1392,9 +1389,10 @@ def Nowhere0WordsTwoWeightCodeGraph(q, hyperoval=None, field=None, check_hyperov using the built-in construction:: - sage: g = graphs.Nowhere0WordsTwoWeightCodeGraph(8); g # needs sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: g = graphs.Nowhere0WordsTwoWeightCodeGraph(8); g Nowhere0WordsTwoWeightCodeGraph(8): Graph on 196 vertices - sage: g.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) (196, 60, 14, 20) sage: g = graphs.Nowhere0WordsTwoWeightCodeGraph(16) # not tested (long time) sage: g.is_strongly_regular(parameters=True) # not tested (long time) @@ -1413,14 +1411,15 @@ def Nowhere0WordsTwoWeightCodeGraph(q, hyperoval=None, field=None, check_hyperov TESTS:: - sage: F = GF(8) # repeating a point... # needs 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] # needs sage.rings.finite_rings - sage: graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F) # needs sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + 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) 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] # needs sage.rings.finite_rings - sage: graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F) # optional - NameError: 'F' (with --distribution 'sagemath-graphs[modules]') + sage: O = [vector(F,(1,1,0)),vector(F,(0,1,0))]+[vector(F, (1,x^2,x)) for x in F] + sage: graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F) Traceback (most recent call last): ... RuntimeError: incorrect hyperoval From 9dc850b3425cbcd5dadfca1eed24bd29f885cb58 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 4 Jul 2023 19:51:06 -0700 Subject: [PATCH 03/10] ./sage -fixdoctests --probe all --distribution 'sagemath-graphs[modules]' src/sage/graphs/generators/smallgraphs.py; ./sage -fixdoctests src/sage/graphs/generators/smallgraphs.py --- src/sage/graphs/generators/smallgraphs.py | 613 ++++++++++++---------- 1 file changed, 330 insertions(+), 283 deletions(-) diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index 36275b2ce57..27d4fc300ab 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -139,21 +139,22 @@ def HarriesGraph(embedding=1): EXAMPLES:: - sage: g = graphs.HarriesGraph() # optional - networkx - sage: g.order() # optional - networkx + sage: # needs networkx + sage: g = graphs.HarriesGraph() + sage: g.order() 70 - sage: g.size() # optional - networkx + sage: g.size() 105 - sage: g.girth() # optional - networkx + sage: g.girth() 10 - sage: g.diameter() # optional - networkx + sage: g.diameter() 6 - 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 + sage: g.show(figsize=[10, 10]) # long time # needs sage.plot + sage: graphs.HarriesGraph(embedding=2).show(figsize=[10, 10]) # long time, needs sage.plot TESTS:: - sage: graphs.HarriesGraph(embedding=3) # optional - networkx + sage: graphs.HarriesGraph(embedding=3) # needs networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -257,25 +258,26 @@ def HarriesWongGraph(embedding=1): EXAMPLES:: - sage: g = graphs.HarriesWongGraph() # optional - networkx - sage: g.order() # optional - networkx + sage: # needs networkx + sage: g = graphs.HarriesWongGraph() + sage: g.order() 70 - sage: g.size() # optional - networkx + sage: g.size() 105 - sage: g.girth() # optional - networkx + sage: g.girth() 10 - sage: g.diameter() # optional - networkx + sage: g.diameter() 6 - 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 + sage: orbits = g.automorphism_group(orbits=True)[-1] # long time # needs sage.groups + sage: g.show(figsize=[15, 15], partition=orbits) # long time # needs sage.groups sage.plot Alternative embedding:: - sage: graphs.HarriesWongGraph(embedding=2).show() # long time # optional - networkx sage.plot + sage: graphs.HarriesWongGraph(embedding=2).show() # long time # needs networkx sage.plot TESTS:: - sage: graphs.HarriesWongGraph(embedding=3) # optional - networkx + sage: graphs.HarriesWongGraph(embedding=3) # needs networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -453,12 +455,13 @@ def Cell600(embedding=1): EXAMPLES:: - sage: g = graphs.Cell600() # long time - sage: g.size() # long time + sage: # long time + sage: g = graphs.Cell600() + sage: g.size() 720 - sage: g.is_regular(12) # long time + sage: g.is_regular(12) True - sage: g.is_vertex_transitive() # long time + sage: g.is_vertex_transitive() True """ from sage.rings.polynomial.polynomial_ring import polygen @@ -528,12 +531,13 @@ def Cell120(): EXAMPLES:: - sage: g = graphs.Cell120() # long time - sage: g.size() # long time + sage: # long time + sage: g = graphs.Cell120() + sage: g.size() 1200 - sage: g.is_regular(4) # long time + sage: g.is_regular(4) True - sage: g.is_vertex_transitive() # long time + sage: g.is_vertex_transitive() True """ from sage.rings.polynomial.polynomial_ring import polygen @@ -679,7 +683,7 @@ def HallJankoGraph(from_string=True): sage: g = graphs.HallJankoGraph() sage: g.is_regular(36) True - sage: g.is_vertex_transitive() # optional - sage.groups + sage: g.is_vertex_transitive() # needs sage.groups True Is it really strongly regular with parameters 14, 12? :: @@ -702,7 +706,7 @@ def HallJankoGraph(from_string=True): 2 sage: g.girth() 3 - sage: factor(g.characteristic_polynomial()) + sage: factor(g.characteristic_polynomial()) # needs sage.libs.pari sage.modules (x - 36) * (x - 6)^36 * (x + 4)^63 TESTS:: @@ -804,20 +808,21 @@ def Balaban10Cage(embedding=1): EXAMPLES:: - sage: g = graphs.Balaban10Cage() # optional - networkx - sage: g.girth() # optional - networkx + sage: # needs networkx + sage: g = graphs.Balaban10Cage() + sage: g.girth() 10 - sage: g.chromatic_number() # optional - networkx + sage: g.chromatic_number() 2 - sage: g.diameter() # optional - networkx + sage: g.diameter() 6 - sage: g.is_hamiltonian() # optional - networkx + sage: g.is_hamiltonian() # needs sage.numerical.mip True - sage: g.show(figsize=[10,10]) # long time # optional - networkx sage.plot + sage: g.show(figsize=[10,10]) # long time # needs sage.plot TESTS:: - sage: graphs.Balaban10Cage(embedding='foo') # optional - networkx + sage: graphs.Balaban10Cage(embedding='foo') # needs networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -897,21 +902,21 @@ def Balaban11Cage(embedding=1): 11 sage: g.diameter() 8 - sage: g.automorphism_group().cardinality() # optional - sage.groups + sage: g.automorphism_group().cardinality() # needs sage.groups 64 Our many embeddings:: 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 # 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 + sage: g2 = graphs.Balaban11Cage(embedding=2) # needs networkx + sage: g3 = graphs.Balaban11Cage(embedding=3) # needs networkx + sage: g1.show(figsize=[10,10]) # long time # needs sage.plot + sage: g2.show(figsize=[10,10]) # long time # needs networkx sage.plot + sage: g3.show(figsize=[10,10]) # long time # needs sage.plot Proof that the embeddings are the same graph:: - sage: g1.is_isomorphic(g2) # g2 and g3 are obviously isomorphic + sage: g1.is_isomorphic(g2) # g2 and g3 are obviously isomorphic # needs networkx True TESTS:: @@ -1071,7 +1076,7 @@ def BidiakisCube(): It is a Hamiltonian graph with diameter 3 and girth 4:: - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # needs sage.numerical.mip True sage: g.diameter() 3 @@ -1084,11 +1089,11 @@ def BidiakisCube(): sage: g.is_planar() True - sage: char_poly = g.characteristic_polynomial() - sage: x = char_poly.parent()('x') - sage: char_poly == (x - 3) * (x - 2) * (x^4) * (x + 1) * (x + 2) * (x^2 + x - 4)^2 + sage: char_poly = g.characteristic_polynomial() # needs sage.modules + sage: x = char_poly.parent()('x') # needs sage.modules + sage: char_poly == (x - 3) * (x - 2) * (x^4) * (x + 1) * (x + 2) * (x^2 + x - 4)^2 # needs sage.modules True - sage: g.chromatic_number() + sage: g.chromatic_number() # needs sage.modules 3 """ edge_dict = { @@ -1114,26 +1119,27 @@ def BiggsSmithGraph(embedding=1): Basic properties:: - sage: g = graphs.BiggsSmithGraph() # optional - networkx - sage: g.order() # optional - networkx + sage: # needs networkx + sage: g = graphs.BiggsSmithGraph() + sage: g.order() 102 - sage: g.size() # optional - networkx + sage: g.size() 153 - sage: g.girth() # optional - networkx + sage: g.girth() 9 - sage: g.diameter() # optional - networkx + sage: g.diameter() 7 - sage: g.automorphism_group().cardinality() # long time # optional - networkx + sage: g.automorphism_group().cardinality() # long time 2448 - sage: g.show(figsize=[10, 10]) # long time # optional - networkx sage.plot + sage: g.show(figsize=[10, 10]) # long time # needs sage.plot The other embedding:: - sage: graphs.BiggsSmithGraph(embedding=2).show() # long time # optional - networkx + sage: graphs.BiggsSmithGraph(embedding=2).show() # long time # needs networkx TESTS:: - sage: graphs.BiggsSmithGraph(embedding='xyzzy') # optional - networkx + sage: graphs.BiggsSmithGraph(embedding='xyzzy') # needs networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -1199,16 +1205,16 @@ def BlanusaFirstSnarkGraph(): EXAMPLES:: - sage: g = graphs.BlanusaFirstSnarkGraph() # optional - sage.groups - sage: g.order() # optional - sage.groups + sage: g = graphs.BlanusaFirstSnarkGraph() + sage: g.order() 18 - sage: g.size() # optional - sage.groups + sage: g.size() 27 - sage: g.diameter() # optional - sage.groups + sage: g.diameter() 4 - sage: g.girth() # optional - sage.groups + sage: g.girth() 5 - sage: g.automorphism_group().cardinality() # optional - sage.groups + sage: g.automorphism_group().cardinality() # needs sage.groups 8 """ g = Graph({17: [4, 7, 1], 0: [5], 3: [8], 13: [9], 12: [16], @@ -1234,16 +1240,16 @@ def BlanusaSecondSnarkGraph(): EXAMPLES:: - sage: g = graphs.BlanusaSecondSnarkGraph() # optional - sage.groups - sage: g.order() # optional - sage.groups + sage: g = graphs.BlanusaSecondSnarkGraph() + sage: g.order() 18 - sage: g.size() # optional - sage.groups + sage: g.size() 27 - sage: g.diameter() # optional - sage.groups + sage: g.diameter() 4 - sage: g.girth() # optional - sage.groups + sage: g.girth() 5 - sage: g.automorphism_group().cardinality() # optional - sage.groups + sage: g.automorphism_group().cardinality() # needs sage.groups 4 """ c0 = (-1, 0) @@ -1312,15 +1318,15 @@ def BrinkmannGraph(): The Brinkmann graph is also Hamiltonian with chromatic number 4:: - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical.mip True sage: G.chromatic_number() 4 Its automorphism group is isomorphic to `D_7`:: - sage: ag = G.automorphism_group() - sage: ag.is_isomorphic(DihedralGroup(7)) + sage: ag = G.automorphism_group() # needs sage.groups + sage: ag.is_isomorphic(DihedralGroup(7)) # needs sage.groups True """ edge_dict = { @@ -1361,18 +1367,17 @@ def BrouwerHaemersGraph(): EXAMPLES:: - sage: g = graphs.BrouwerHaemersGraph() # optional - sage.modules - sage: g # optional - sage.modules + sage: g = graphs.BrouwerHaemersGraph(); g # needs 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 # optional - sage.modules + sage: g.is_strongly_regular(parameters=True) # long time # needs sage.modules sage.rings.finite_rings (81, 20, 1, 6) Its has as eigenvalues `20,2` and `-7`:: - sage: set(g.spectrum()) == {20,2,-7} # optional - sage.modules + sage: set(g.spectrum()) == {20,2,-7} # needs sage.modules sage.rings.finite_rings True """ from sage.rings.finite_rings.finite_field_constructor import FiniteField @@ -1419,16 +1424,17 @@ 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() # optional - sage.geometry.polyhedron - sage: g.remove_loops() # optional - sage.geometry.polyhedron + sage: # needs sage.geometry.polyhedron sage.rings.number_field + sage: g = polytopes.buckyball().vertex_graph() + sage: g.remove_loops() sage: h = graphs.BuckyBall() - sage: g.is_isomorphic(h) # optional - sage.geometry.polyhedron + sage: g.is_isomorphic(h) 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 # optional - sage.plot + sage: g.plot(vertex_labels=False, vertex_size=10).show() # long time, needs 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), @@ -1573,11 +1579,11 @@ def DoubleStarSnark(): 45 sage: g.chromatic_number() 3 - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # needs sage.numerical.mip False - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # needs sage.groups 80 - sage: g.show() # optional - sage.plot + sage: g.show() # needs sage.plot """ d = {0: [1, 14, 15], 1: [0, 2, 11], @@ -1641,7 +1647,7 @@ def MeredithGraph(): 4 sage: g.chromatic_number() 3 - sage: g.is_hamiltonian() # long time + sage: g.is_hamiltonian() # long time # needs sage.numerical.mip False """ g = Graph(name="Meredith Graph") @@ -1735,12 +1741,13 @@ def CameronGraph(): EXAMPLES:: - sage: g = graphs.CameronGraph() # optional - sage.groups - sage: g.order() # optional - sage.groups + sage: # needs sage.groups + sage: g = graphs.CameronGraph() + sage: g.order() 231 - sage: g.size() # optional - sage.groups + sage: g.size() 3465 - sage: g.is_strongly_regular(parameters=True) # long time # optional - sage.groups + sage: g.is_strongly_regular(parameters=True) # long time (231, 30, 9, 3) """ from sage.groups.perm_gps.permgroup_named import MathieuGroup @@ -1804,9 +1811,9 @@ def ChvatalGraph(): TESTS:: - sage: import networkx # optional - networkx + sage: import networkx # needs networkx sage: G = graphs.ChvatalGraph() - sage: G.is_isomorphic(Graph(networkx.chvatal_graph())) # optional - networkx + sage: G.is_isomorphic(Graph(networkx.chvatal_graph())) # needs networkx True """ edges = {0: [1, 4, 6, 9], 1: [2, 5, 7], 2: [3, 6, 8], 3: [4, 7, 9], @@ -1828,7 +1835,7 @@ def ClebschGraph(): EXAMPLES:: sage: g = graphs.ClebschGraph() - sage: g.automorphism_group().cardinality() # optional - sage.groups + sage: g.automorphism_group().cardinality() # needs sage.groups 1920 sage: g.girth() 4 @@ -1836,7 +1843,7 @@ def ClebschGraph(): 4 sage: g.diameter() 2 - sage: g.show(figsize=[10, 10]) # long time # optional - sage.plot + sage: g.show(figsize=[10, 10]) # long time # needs sage.plot """ g = Graph(pos={}) x = 0 @@ -1865,7 +1872,7 @@ def CoxeterGraph(): EXAMPLES:: sage: g = graphs.CoxeterGraph() - sage: g.automorphism_group().cardinality() # optional - sage.groups + sage: g.automorphism_group().cardinality() # needs sage.groups 336 sage: g.girth() 7 @@ -1873,7 +1880,7 @@ def CoxeterGraph(): 3 sage: g.diameter() 4 - sage: g.show(figsize=[10, 10]) # long time # optional - sage.plot + sage: g.show(figsize=[10, 10]) # long time # needs sage.plot """ g = Graph({ 27: [6, 22, 14], @@ -1904,11 +1911,11 @@ def DejterGraph(): EXAMPLES:: - sage: g = graphs.DejterGraph(); g # optional - sage.rings.finite_rings + sage: g = graphs.DejterGraph(); g # needs sage.rings.finite_rings Dejter Graph: Graph on 112 vertices - sage: g.is_regular(k=6) # optional - sage.rings.finite_rings + sage: g.is_regular(k=6) # needs sage.rings.finite_rings True - sage: g.girth() # optional - sage.rings.finite_rings + sage: g.girth() # needs sage.rings.finite_rings 4 """ from sage.graphs.generators.families import CubeGraph @@ -1931,10 +1938,10 @@ def DesarguesGraph(): EXAMPLES:: sage: D = graphs.DesarguesGraph() - sage: L = graphs.LCFGraph(20,[5,-5,9,-9],5) # optional - networkx - sage: D.is_isomorphic(L) # optional - networkx + sage: L = graphs.LCFGraph(20,[5,-5,9,-9],5) # needs networkx + sage: D.is_isomorphic(L) # needs networkx True - sage: D.show() # long time # optional - sage.plot + sage: D.show() # long time # needs sage.plot """ from sage.graphs.generators.families import GeneralizedPetersenGraph G = GeneralizedPetersenGraph(10, 3) @@ -1973,8 +1980,8 @@ def DurerGraph(): Its automorphism group is isomorphic to `D_6`:: - sage: ag = G.automorphism_group() - sage: ag.is_isomorphic(DihedralGroup(6)) + sage: ag = G.automorphism_group() # needs sage.groups + sage: ag.is_isomorphic(DihedralGroup(6)) # needs sage.groups True """ from sage.graphs.generators.families import GeneralizedPetersenGraph @@ -2012,7 +2019,7 @@ def DyckGraph(): sage: G.is_planar() False - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical.mip True sage: G.is_bipartite() True @@ -2030,12 +2037,12 @@ def DyckGraph(): sage: G.chromatic_number() 2 - sage: G.automorphism_group().cardinality() + sage: G.automorphism_group().cardinality() # needs sage.groups 192 It is a non-integral graph as it has irrational eigenvalues:: - sage: G.characteristic_polynomial().factor() + sage: G.characteristic_polynomial().factor() # needs sage.libs.pari sage.modules (x - 3) * (x + 3) * (x - 1)^9 * (x + 1)^9 * (x^2 - 5)^6 It is a toroidal graph, and its embedding on a torus is dual to an embedding @@ -2085,22 +2092,23 @@ def HortonGraph(): EXAMPLES:: - sage: g = graphs.HortonGraph() # optional - networkx - sage: g.order() # optional - networkx + sage: # needs networkx + sage: g = graphs.HortonGraph() + sage: g.order() 96 - sage: g.size() # optional - networkx + sage: g.size() 144 - sage: g.radius() # optional - networkx + sage: g.radius() 10 - sage: g.diameter() # optional - networkx + sage: g.diameter() 10 - sage: g.girth() # optional - networkx + sage: g.girth() 6 - sage: g.automorphism_group().cardinality() # optional - networkx + sage: g.automorphism_group().cardinality() 96 - sage: g.chromatic_number() # optional - networkx + sage: g.chromatic_number() 2 - sage: g.is_hamiltonian() # not tested -- veeeery long # optional - networkx + sage: g.is_hamiltonian() # not tested # needs sage.numerical.mip False """ g = Graph(name="Horton Graph") @@ -2160,14 +2168,14 @@ def EllinghamHorton54Graph(): It is 3-connected and bipartite:: - sage: g.vertex_connectivity() # not tested - too long + sage: g.vertex_connectivity() # not tested - too long 3 sage: g.is_bipartite() True It is not Hamiltonian:: - sage: g.is_hamiltonian() # not tested - too long + sage: g.is_hamiltonian() # not tested (too long) # needs sage.numerical.mip False ... and it has a nice drawing :: @@ -2237,23 +2245,23 @@ def EllinghamHorton78Graph(): It is 3-connected and bipartite:: - sage: g.vertex_connectivity() # not tested - too long + sage: g.vertex_connectivity() # not tested (too long) 3 sage: g.is_bipartite() True It is not Hamiltonian:: - sage: g.is_hamiltonian() # not tested - too long + sage: g.is_hamiltonian() # not tested (too long) # needs sage.numerical.mip False ... and it has a nice drawing :: - sage: g.show(figsize=[10,10]) # not tested - too long + sage: g.show(figsize=[10,10]) # not tested (too long) TESTS:: - sage: g.show(figsize=[10, 10]) # not tested - too long + sage: g.show(figsize=[10, 10]) # not tested (too long) """ g = Graph({ 0: [1, 5, 60], 1: [2, 12], 2: [3, 7], 3: [4, 14], 4: [5, 9], @@ -2321,7 +2329,7 @@ def ErreraGraph(): The Errera graph is Hamiltonian with radius 3, diameter 4, girth 3, and chromatic number 4:: - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical.mip True sage: G.radius() 3 @@ -2343,8 +2351,8 @@ def ErreraGraph(): The automorphism group of the Errera graph is isomorphic to the dihedral group of order 20:: - sage: ag = G.automorphism_group() - sage: ag.is_isomorphic(DihedralGroup(10)) + sage: ag = G.automorphism_group() # needs sage.groups + sage: ag.is_isomorphic(DihedralGroup(10)) # needs sage.groups True """ edge_dict = { @@ -2374,17 +2382,18 @@ def F26AGraph(): EXAMPLES:: - sage: g = graphs.F26AGraph(); g # optional - networkx + sage: # needs networkx + sage: g = graphs.F26AGraph(); g F26A Graph: Graph on 26 vertices - sage: g.order(), g.size() # optional - networkx + sage: g.order(), g.size() (26, 39) - sage: g.automorphism_group().cardinality() # optional - networkx + sage: g.automorphism_group().cardinality() 78 - sage: g.girth() # optional - networkx + sage: g.girth() 6 - sage: g.is_bipartite() # optional - networkx + sage: g.is_bipartite() True - sage: g.characteristic_polynomial().factor() # optional - networkx + sage: g.characteristic_polynomial().factor() (x - 3) * (x + 3) * (x^4 - 5*x^2 + 3)^6 """ from sage.graphs.generators.families import LCFGraph @@ -2435,26 +2444,27 @@ def FolkmanGraph(): EXAMPLES:: - sage: g = graphs.FolkmanGraph() # optional - networkx - sage: g.order() # optional - networkx + sage: # needs networkx + sage: g = graphs.FolkmanGraph() + sage: g.order() 20 - sage: g.size() # optional - networkx + sage: g.size() 40 - sage: g.diameter() # optional - networkx + sage: g.diameter() 4 - sage: g.girth() # optional - networkx + sage: g.girth() 4 - sage: g.charpoly().factor() # optional - networkx + sage: g.charpoly().factor() (x - 4) * (x + 4) * x^10 * (x^2 - 6)^4 - sage: g.chromatic_number() # optional - networkx + sage: g.chromatic_number() 2 - sage: g.is_eulerian() # optional - networkx + sage: g.is_eulerian() True - sage: g.is_hamiltonian() # optional - networkx + sage: g.is_hamiltonian() # needs sage.numerical_mip True - sage: g.is_vertex_transitive() # optional - networkx + sage: g.is_vertex_transitive() False - sage: g.is_bipartite() # optional - networkx + sage: g.is_bipartite() True """ from sage.graphs.generators.families import LCFGraph @@ -2471,18 +2481,19 @@ def FosterGraph(): EXAMPLES:: - sage: g = graphs.FosterGraph() # optional - networkx - sage: g.order() # optional - networkx + sage: # needs networkx + sage: g = graphs.FosterGraph() + sage: g.order() 90 - sage: g.size() # optional - networkx + sage: g.size() 135 - sage: g.diameter() # optional - networkx + sage: g.diameter() 8 - sage: g.girth() # optional - networkx + sage: g.girth() 10 - sage: g.automorphism_group().cardinality() # optional - networkx + sage: g.automorphism_group().cardinality() 4320 - sage: g.is_hamiltonian() # optional - networkx + sage: g.is_hamiltonian() # needs sage.numerical_mip True """ from sage.graphs.generators.families import LCFGraph @@ -2514,7 +2525,7 @@ def FranklinGraph(): The Franklin graph is a Hamiltonian, bipartite graph with radius 3, diameter 3, and girth 4:: - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical_mip True sage: G.is_bipartite() True @@ -2565,18 +2576,18 @@ def FruchtGraph(): EXAMPLES:: - sage: FRUCHT = graphs.FruchtGraph() # optional - networkx - sage: FRUCHT # optional - networkx + sage: FRUCHT = graphs.FruchtGraph() + sage: FRUCHT Frucht graph: Graph on 12 vertices - sage: FRUCHT.graph6_string() # optional - networkx + sage: FRUCHT.graph6_string() 'KhCKM?_EGK?L' - sage: (graphs.FruchtGraph()).show() # long time # optional - networkx + sage: (graphs.FruchtGraph()).show() # long time # needs networkx TESTS:: - sage: import networkx # optional - networkx - sage: G = graphs.FruchtGraph() # optional - networkx - sage: G.is_isomorphic(Graph(networkx.frucht_graph())) # optional - networkx + sage: import networkx # needs networkx + sage: G = graphs.FruchtGraph() + sage: G.is_isomorphic(Graph(networkx.frucht_graph())) # needs networkx True """ edges = {0: [1, 6, 7], 1: [2, 7], 2: [3, 8], 3: [4, 9], 4: [5, 9], @@ -2624,8 +2635,8 @@ def GoldnerHararyGraph(): sage: G.chromatic_number() 4 - sage: ag = G.automorphism_group() - sage: ag.is_isomorphic(DihedralGroup(6)) + sage: ag = G.automorphism_group() # needs sage.groups + sage: ag.is_isomorphic(DihedralGroup(6)) # needs sage.groups True """ edge_dict = { @@ -2668,12 +2679,12 @@ def GolombGraph(): and 18 edges. It has chromatic number 4, diameter 3, radius 2 and girth 3. It can be drawn in the plane as a unit distance graph:: - sage: G = graphs.GolombGraph(); G # optional - sage.symbolic + sage: G = graphs.GolombGraph(); G # needs sage.symbolic Golomb graph: Graph on 10 vertices - sage: pos = G.get_pos() # optional - sage.symbolic + sage: pos = G.get_pos() # needs sage.symbolic sage: def dist2(u, v): ....: return (u[0]-v[0])**2 + (u[1]-v[1])**2 - sage: all(dist2(pos[u], pos[v]) == 1 for u, v in G.edge_iterator(labels=None)) # optional - sage.symbolic + sage: all(dist2(pos[u], pos[v]) == 1 for u, v in G.edge_iterator(labels=None)) # needs sage.symbolic True """ edge_dict = { @@ -2713,6 +2724,7 @@ def GrayGraph(embedding=1): EXAMPLES:: + sage: # needs networkx sage: g = graphs.GrayGraph() sage: g.order() 54 @@ -2722,12 +2734,12 @@ def GrayGraph(embedding=1): 8 sage: g.diameter() 6 - sage: g.show(figsize=[10, 10]) # long time - sage: graphs.GrayGraph(embedding=2).show(figsize=[10, 10]) # long time + sage: g.show(figsize=[10, 10]) # long time, needs sage.plot + sage: graphs.GrayGraph(embedding=2).show(figsize=[10, 10]) # long time, needs sage.plot TESTS:: - sage: graphs.GrayGraph(embedding=3) + sage: graphs.GrayGraph(embedding=3) # needs networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1, 2, or 3 @@ -2762,7 +2774,7 @@ def GrotzschGraph(): sage: G = graphs.GrotzschGraph(); G Grotzsch graph: Graph on 11 vertices - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical.mip True sage: G.order() 11 @@ -2786,8 +2798,8 @@ def GrotzschGraph(): sage: G.chromatic_number() 4 - sage: ag = G.automorphism_group() - sage: ag.is_isomorphic(DihedralGroup(5)) + sage: ag = G.automorphism_group() # needs sage.groups + sage: ag.is_isomorphic(DihedralGroup(5)) # needs sage.groups True """ edges = [(0, u) for u in range(1, 6)] @@ -2836,9 +2848,9 @@ def HeawoodGraph(): TESTS:: - sage: import networkx # optional - networkx + sage: import networkx # needs networkx sage: G = graphs.HeawoodGraph() - sage: G.is_isomorphic(Graph(networkx.heawood_graph())) # optional - networkx + sage: G.is_isomorphic(Graph(networkx.heawood_graph())) # needs networkx True """ edges = {0: [1, 5, 13], 1: [2, 10], 2: [3, 7], 3: [4, 12], 4: [5, 9], @@ -2888,8 +2900,8 @@ def HerschelGraph(): sage: G.chromatic_number() 2 - sage: ag = G.automorphism_group() # optional - sage.groups - sage: ag.is_isomorphic(DihedralGroup(6)) # optional - sage.groups + sage: ag = G.automorphism_group() # needs sage.groups + sage: ag.is_isomorphic(DihedralGroup(6)) # needs sage.groups True """ edge_dict = { @@ -2919,9 +2931,9 @@ def GritsenkoGraph(): EXAMPLES:: - sage: H = graphs.GritsenkoGraph(); H # optional - sage.groups + sage: H = graphs.GritsenkoGraph(); H # needs sage.groups Gritsenko strongly regular graph: Graph on 65 vertices - sage: H.is_strongly_regular(parameters=True) # optional - sage.groups + sage: H.is_strongly_regular(parameters=True) # needs sage.groups (65, 32, 15, 16) """ from sage.groups.perm_gps.permgroup import PermutationGroup @@ -3000,13 +3012,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() # optional - sage.groups - sage: g = G.order(); g # optional - sage.groups + sage: G = H.automorphism_group() # needs sage.groups + sage: g = G.order(); g # needs sage.groups 88704000 - sage: K = G.normal_subgroups()[1] # optional - sage.groups - sage: K.is_simple() # optional - sage.groups + sage: K = G.normal_subgroups()[1] # needs sage.groups + sage: K.is_simple() # needs sage.groups True - sage: g//K.order() # optional - sage.groups + sage: g//K.order() # needs sage.groups 2 AUTHOR: @@ -3186,13 +3198,13 @@ def HoffmanGraph(): sage: g = graphs.HoffmanGraph() sage: g.is_bipartite() True - sage: g.is_hamiltonian() # long time + sage: g.is_hamiltonian() # long time # needs sage.numerical.mip True sage: g.radius() 3 sage: g.diameter() 4 - sage: g.automorphism_group().cardinality() # optional - sage.groups + sage: g.automorphism_group().cardinality() # needs sage.groups 48 """ g = Graph({ @@ -3231,11 +3243,11 @@ def HoltGraph(): Holt graph: Graph on 27 vertices sage: g.is_regular() True - sage: g.is_vertex_transitive() # optional - sage.groups + sage: g.is_vertex_transitive() # needs sage.groups True sage: g.chromatic_number() 3 - sage: g.is_hamiltonian() # long time + sage: g.is_hamiltonian() # long time # needs sage.numerical.mip True sage: g.radius() 3 @@ -3243,7 +3255,7 @@ def HoltGraph(): 3 sage: g.girth() 5 - sage: g.automorphism_group().cardinality() # optional - sage.groups + sage: g.automorphism_group().cardinality() # needs sage.groups 54 """ g = Graph(loops=False, name="Holt graph", pos={}) @@ -3295,9 +3307,9 @@ def KrackhardtKiteGraph(): TESTS:: - sage: import networkx # optional - networkx + sage: import networkx # needs networkx sage: G = graphs.KrackhardtKiteGraph() - sage: G.is_isomorphic(Graph(networkx.krackhardt_kite_graph())) # optional - networkx + sage: G.is_isomorphic(Graph(networkx.krackhardt_kite_graph())) # needs networkx True """ edges = {0: [1, 2, 3, 5], 1: [3, 4, 6], 2: [3, 5], 3: [4, 5, 6], @@ -3324,7 +3336,7 @@ def Klein3RegularGraph(): (56, 84) sage: g.girth() 7 - sage: g.automorphism_group().cardinality() # optional - sage.groups + sage: g.automorphism_group().cardinality() # needs sage.groups 336 sage: g.chromatic_number() 3 @@ -3357,7 +3369,7 @@ def Klein7RegularGraph(): (24, 84) sage: g.girth() 3 - sage: g.automorphism_group().cardinality() # optional - sage.groups + sage: g.automorphism_group().cardinality() # needs sage.groups 336 sage: g.chromatic_number() 4 @@ -3413,21 +3425,22 @@ def LjubljanaGraph(embedding=1): EXAMPLES:: - sage: g = graphs.LjubljanaGraph() # optional - networkx - sage: g.order() # optional - networkx + sage: # needs networkx + sage: g = graphs.LjubljanaGraph() + sage: g.order() 112 - sage: g.size() # optional - networkx + sage: g.size() 168 - sage: g.girth() # optional - networkx + sage: g.girth() 10 - sage: g.diameter() # optional - networkx + sage: g.diameter() 8 - 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 + sage: g.show(figsize=[10, 10]) # long time # needs sage.plot + sage: graphs.LjubljanaGraph(embedding=2).show(figsize=[10, 10]) # long time, needs sage.plot TESTS:: - sage: graphs.LjubljanaGraph(embedding=3) # optional - networkx + sage: graphs.LjubljanaGraph(embedding=3) # needs networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -3486,16 +3499,17 @@ def LivingstoneGraph(): EXAMPLES:: - sage: g = graphs.LivingstoneGraph() # optional - internet - sage: g.order() # optional - internet + sage: # optional - internet + sage: g = graphs.LivingstoneGraph() + sage: g.order() 266 - sage: g.size() # optional - internet + sage: g.size() 1463 - sage: g.girth() # optional - internet + sage: g.girth() 5 - sage: g.is_vertex_transitive() # optional - internet + sage: g.is_vertex_transitive() True - sage: g.is_distance_regular() # optional - internet + sage: g.is_distance_regular() True """ from sage.groups.perm_gps.permgroup_named import JankoGroup @@ -3518,12 +3532,13 @@ def M22Graph(): EXAMPLES:: - sage: g = graphs.M22Graph() # optional - sage.groups - sage: g.order() # optional - sage.groups + sage: # needs sage.groups + sage: g = graphs.M22Graph() + sage: g.order() 77 - sage: g.size() # optional - sage.groups + sage: g.size() 616 - sage: g.is_strongly_regular(parameters=True) # optional - sage.groups + sage: g.is_strongly_regular(parameters=True) (77, 16, 0, 4) """ from sage.groups.perm_gps.permgroup_named import MathieuGroup @@ -3561,11 +3576,11 @@ def MarkstroemGraph(): True sage: g.is_regular(3) True - sage: g.subgraph_search(graphs.CycleGraph(4)) is None # optional - sage.modules + sage: g.subgraph_search(graphs.CycleGraph(4)) is None # needs sage.modules True - sage: g.subgraph_search(graphs.CycleGraph(8)) is None # optional - sage.modules + sage: g.subgraph_search(graphs.CycleGraph(8)) is None # needs sage.modules True - sage: g.subgraph_search(graphs.CycleGraph(16)) # optional - sage.modules + sage: g.subgraph_search(graphs.CycleGraph(16)) # needs sage.modules Subgraph of (Markstroem Graph): Graph on 16 vertices """ g = Graph(name="Markstroem Graph") @@ -3602,21 +3617,22 @@ def McGeeGraph(embedding=2): EXAMPLES:: - sage: g = graphs.McGeeGraph() # optional - networkx - sage: g.order() # optional - networkx + sage: # needs networkx + sage: g = graphs.McGeeGraph() + sage: g.order() 24 - sage: g.size() # optional - networkx + sage: g.size() 36 - sage: g.girth() # optional - networkx + sage: g.girth() 7 - sage: g.diameter() # optional - networkx + sage: g.diameter() 4 - sage: g.show() # optional - networkx sage.plot - sage: graphs.McGeeGraph(embedding=1).show() # long time # optional - networkx sage.plot + sage: g.show() # needs sage.plot + sage: graphs.McGeeGraph(embedding=1).show() # long time # needs sage.plot TESTS:: - sage: graphs.McGeeGraph(embedding=3) # optional - networkx + sage: graphs.McGeeGraph(embedding=3) # needs networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -3726,7 +3742,7 @@ def MoebiusKantorGraph(): Moebius-Kantor Graph: Graph on 16 vertices sage: MK.graph6_string() 'OhCGKE?O@?ACAC@I?Q_AS' - sage: (graphs.MoebiusKantorGraph()).show() # long time # optional - sage.plot + sage: (graphs.MoebiusKantorGraph()).show() # long time # needs sage.plot """ from sage.graphs.generators.families import GeneralizedPetersenGraph G = GeneralizedPetersenGraph(8, 3) @@ -3744,38 +3760,41 @@ def MoserSpindle(): The Moser spindle is a planar graph having 7 vertices and 11 edges:: - sage: G = graphs.MoserSpindle(); G # optional - sage.symbolic + sage: # needs sage.symbolic + sage: G = graphs.MoserSpindle(); G Moser spindle: Graph on 7 vertices - sage: G.is_planar() # optional - sage.symbolic + sage: G.is_planar() True - sage: G.order() # optional - sage.symbolic + sage: G.order() 7 - sage: G.size() # optional - sage.symbolic + sage: G.size() 11 It is a Hamiltonian graph with radius 2, diameter 2, and girth 3:: - sage: G.is_hamiltonian() # optional - sage.symbolic + sage: # needs sage.symbolic + sage: G.is_hamiltonian() # needs sage.numerical.mip True - sage: G.radius() # optional - sage.symbolic + sage: G.radius() 2 - sage: G.diameter() # optional - sage.symbolic + sage: G.diameter() 2 - sage: G.girth() # optional - sage.symbolic + sage: G.girth() 3 The Moser spindle can be drawn in the plane as a unit distance graph, has chromatic number 4, and its automorphism group is isomorphic to the dihedral group `D_4`:: - sage: pos = G.get_pos() # optional - sage.symbolic - sage: all(sum((ui-vi)**2 for ui, vi in zip(pos[u], pos[v])) == 1 # optional - sage.symbolic + sage: # needs sage.symbolic + sage: pos = G.get_pos() + sage: all(sum((ui-vi)**2 for ui, vi in zip(pos[u], pos[v])) == 1 ....: for u, v in G.edge_iterator(labels=None)) True - sage: G.chromatic_number() # optional - sage.symbolic + sage: G.chromatic_number() 4 - sage: ag = G.automorphism_group() # optional - sage.symbolic - sage: ag.is_isomorphic(DihedralGroup(4)) # optional - sage.symbolic + sage: ag = G.automorphism_group() + sage: ag.is_isomorphic(DihedralGroup(4)) True """ edge_dict = { @@ -3821,8 +3840,8 @@ def NauruGraph(embedding=2): 6 sage: g.diameter() 4 - sage: g.show() # optional - sage.plot - sage: graphs.NauruGraph(embedding=1).show() # long time # optional - sage.plot + sage: g.show() # needs sage.plot + sage: graphs.NauruGraph(embedding=1).show() # long time # needs sage.plot TESTS:: @@ -3830,7 +3849,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) # optional - networkx + sage: graphs.NauruGraph(embedding=1).is_isomorphic(g) # needs networkx True """ @@ -3857,10 +3876,10 @@ def PappusGraph(): EXAMPLES:: sage: G = graphs.PappusGraph() - sage: G.show() # long time # optional - sage.plot - 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 + sage: G.show() # long time # needs sage.plot + sage: L = graphs.LCFGraph(18, [5,7,-7,7,-7,-5], 3) # needs networkx + sage: L.show() # long time # needs networkx sage.plot + sage: G.is_isomorphic(L) # needs networkx True """ edges = {0: [1, 5, 6], 1: [2, 7], 2: [3, 8], 3: [4, 9], 4: [5, 10], 5: [11], @@ -3923,9 +3942,9 @@ def PetersenGraph(): ....: 3:[2,4,8], 4:[0,3,9], 5:[0,7,8], ....: 6:[1,8,9], 7:[2,5,9], 8:[3,5,6], ....: 9:[4,6,7]}) - sage: petersen_spring.show() # long time # optional - sage.plot + sage: petersen_spring.show() # long time # needs sage.plot sage: petersen_database = graphs.PetersenGraph() - sage: petersen_database.show() # long time # optional - sage.plot + sage: petersen_database.show() # long time # needs sage.plot """ from sage.graphs.generators.families import GeneralizedPetersenGraph P = GeneralizedPetersenGraph(5, 2) @@ -3970,23 +3989,24 @@ def RobertsonGraph(): EXAMPLES:: - sage: g = graphs.RobertsonGraph() # optional - networkx - sage: g.order() # optional - networkx + sage: # needs networkx + sage: g = graphs.RobertsonGraph() + sage: g.order() 19 - sage: g.size() # optional - networkx + sage: g.size() 38 - sage: g.diameter() # optional - networkx + sage: g.diameter() 3 - sage: g.girth() # optional - networkx + sage: g.girth() 5 - sage: g.charpoly().factor() # optional - networkx + 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() # optional - networkx + sage: g.chromatic_number() 3 - sage: g.is_hamiltonian() # optional - networkx + sage: g.is_hamiltonian() # needs sage.numerical.mip True - sage: g.is_vertex_transitive() # optional - networkx + sage: g.is_vertex_transitive() False """ from sage.graphs.generators.families import LCFGraph @@ -4024,7 +4044,7 @@ def SchlaefliGraph(): The graph is vertex-transitive:: - sage: S.is_vertex_transitive() # optional - sage.groups + sage: S.is_vertex_transitive() # needs sage.groups True The neighborhood of each vertex is isomorphic to the complement of the @@ -4079,7 +4099,7 @@ def ShrikhandeGraph(): sage: G.is_planar() False - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical.mip True sage: G.is_eulerian() True @@ -4097,12 +4117,12 @@ def ShrikhandeGraph(): sage: G.chromatic_number() 4 - sage: G.automorphism_group().cardinality() + sage: G.automorphism_group().cardinality() # needs sage.groups 192 It is an integral graph since it has only integral eigenvalues:: - sage: G.characteristic_polynomial().factor() + sage: G.characteristic_polynomial().factor() # needs sage.libs.pari sage.modules (x - 6) * (x - 2)^6 * (x + 2)^9 It is a toroidal graph, and its embedding on a torus is dual to an @@ -4236,12 +4256,12 @@ def SousselierGraph(): 2 sage: g.diameter() 3 - sage: g.automorphism_group().cardinality() # optional - sage.groups + sage: g.automorphism_group().cardinality() # needs sage.groups 2 - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # needs sage.numerical.mip False sage: g.delete_vertex(g.random_vertex()) - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # needs sage.numerical.mip True """ g = Graph(name="Sousselier Graph") @@ -4317,7 +4337,7 @@ def ThomsenGraph(): Thomsen graph: Graph on 6 vertices sage: T.graph6_string() 'EFz_' - sage: (graphs.ThomsenGraph()).show() # long time # optional - sage.plot + sage: (graphs.ThomsenGraph()).show() # long time # needs sage.plot """ from sage.graphs.generators.basic import CompleteBipartiteGraph G = CompleteBipartiteGraph(3, 3) @@ -4343,9 +4363,9 @@ def TietzeGraph(): 3 sage: g.girth() 3 - sage: g.automorphism_group().cardinality() # optional - sage.groups + sage: g.automorphism_group().cardinality() # needs sage.groups 12 - sage: g.automorphism_group().is_isomorphic(groups.permutation.Dihedral(6)) # optional - sage.groups + sage: g.automorphism_group().is_isomorphic(groups.permutation.Dihedral(6)) # needs sage.groups True """ g = Graph([(0, 9), (3, 10), (6, 11), (1, 5), (2, 7), (4, 8)], @@ -4370,11 +4390,11 @@ def TruncatedIcosidodecahedralGraph(): Unfortunately, this graph can not be constructed currently, due to numerical issues:: - sage: g = graphs.TruncatedIcosidodecahedralGraph(); g + sage: g = graphs.TruncatedIcosidodecahedralGraph(); g # needs sage.geometry.polyhedron sage.groups sage.rings.number_field Traceback (most recent call last): ... ValueError: *Error: Numerical inconsistency is found. Use the GMP exact arithmetic. - sage: g.order(), g.size() # not tested + sage: g.order(), g.size() # not tested # needs sage.geometry.polyhedron sage.groups sage.rings.number_field (120, 180) """ from sage.geometry.polyhedron.library import polytopes @@ -4397,7 +4417,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()) # optional - sage.geometry.polyhedron + sage: g.is_isomorphic(polytopes.simplex(3).truncation().graph()) # needs sage.geometry.polyhedron True """ g = Graph(':K`ESwC_EOyDl\\MCi', loops=False, multiedges=False) @@ -4416,16 +4436,17 @@ def Tutte12Cage(): EXAMPLES:: - sage: g = graphs.Tutte12Cage() # optional - networkx - sage: g.order() # optional - networkx + sage: # needs networkx + sage: g = graphs.Tutte12Cage() + sage: g.order() 126 - sage: g.size() # optional - networkx + sage: g.size() 189 - sage: g.girth() # optional - networkx + sage: g.girth() 12 - sage: g.diameter() # optional - networkx + sage: g.diameter() 6 - sage: g.show() # optional - networkx sage.plot + sage: g.show() # needs sage.plot """ L = [17, 27, -13, -59, -35, 35, -11, 13, -53, 53, -27, 21, 57, 11, -21, -57, 59, -17] @@ -4449,21 +4470,22 @@ def TutteCoxeterGraph(embedding=2): EXAMPLES:: - sage: g = graphs.TutteCoxeterGraph() # optional - networkx - sage: g.order() # optional - networkx + sage: # needs networkx + sage: g = graphs.TutteCoxeterGraph() + sage: g.order() 30 - sage: g.size() # optional - networkx + sage: g.size() 45 - sage: g.girth() # optional - networkx + sage: g.girth() 8 - sage: g.diameter() # optional - networkx + sage: g.diameter() 4 - sage: g.show() # optional - networkx sage.plot - sage: graphs.TutteCoxeterGraph(embedding=1).show() # long time # optional - networkx sage.plot + sage: g.show() # needs sage.plot + sage: graphs.TutteCoxeterGraph(embedding=1).show() # long time # needs sage.plot TESTS:: - sage: graphs.TutteCoxeterGraph(embedding=3) # optional - networkx + sage: graphs.TutteCoxeterGraph(embedding=3) # needs networkx Traceback (most recent call last): ... ValueError: the value of embedding must be 1 or 2 @@ -4516,9 +4538,13 @@ def TutteGraph(): 3 sage: g.girth() 4 - sage: g.automorphism_group().cardinality() # optional - sage.groups + sage: g.automorphism_group().cardinality() # needs sage.groups 3 +<<<<<<< HEAD sage: g.is_hamiltonian() +======= + sage: g.is_hamiltonian() # needs sage.numerical.mip +>>>>>>> 85d4a8d443 (./sage -fixdoctests --probe all --distribution 'sagemath-graphs[modules]' src/sage/graphs/generators/smallgraphs.py; ./sage -fixdoctests src/sage/graphs/generators/smallgraphs.py) False """ g = Graph(name="Tutte Graph") @@ -4562,16 +4588,17 @@ def WagnerGraph(): EXAMPLES:: - sage: g = graphs.WagnerGraph() # optional - networkx - sage: g.order() # optional - networkx + sage: # needs networkx + sage: g = graphs.WagnerGraph() + sage: g.order() 8 - sage: g.size() # optional - networkx + sage: g.size() 12 - sage: g.girth() # optional - networkx + sage: g.girth() 4 - sage: g.diameter() # optional - networkx + sage: g.diameter() 2 - sage: g.show() # optional - networkx sage.plot + sage: g.show() # needs sage.plot """ from sage.graphs.generators.families import LCFGraph g = LCFGraph(8, [4], 8) @@ -4637,10 +4664,17 @@ def WienerArayaGraph(): 4 sage: g.is_planar() True +<<<<<<< HEAD sage: g.is_hamiltonian() # not tested -- around 30s long False sage: g.delete_vertex(g.random_vertex()) sage: g.is_hamiltonian() +======= + sage: g.is_hamiltonian() # not tested (30s) # needs sage.numerical.mip + False + sage: g.delete_vertex(g.random_vertex()) + sage: g.is_hamiltonian() # needs sage.numerical.mip +>>>>>>> 85d4a8d443 (./sage -fixdoctests --probe all --distribution 'sagemath-graphs[modules]' src/sage/graphs/generators/smallgraphs.py; ./sage -fixdoctests src/sage/graphs/generators/smallgraphs.py) True """ g = Graph(name="Wiener-Araya Graph") @@ -4695,7 +4729,11 @@ def _EllipticLinesProjectivePlaneScheme(k): TESTS:: sage: from sage.graphs.generators.smallgraphs import _EllipticLinesProjectivePlaneScheme +<<<<<<< HEAD sage: _EllipticLinesProjectivePlaneScheme(2) +======= + sage: _EllipticLinesProjectivePlaneScheme(2) # needs sage.libs.gap +>>>>>>> 85d4a8d443 (./sage -fixdoctests --probe all --distribution 'sagemath-graphs[modules]' src/sage/graphs/generators/smallgraphs.py; ./sage -fixdoctests src/sage/graphs/generators/smallgraphs.py) [ [1 0 0 0 0 0] [0 1 1 1 1 0] [0 0 0 0 0 1] [0 1 0 0 0 0] [1 0 1 1 0 1] [0 0 0 0 1 0] @@ -4738,11 +4776,12 @@ def MathonStronglyRegularGraph(t): TESTS:: - sage: G = graphs.MathonStronglyRegularGraph(1) # long time - sage: G.is_strongly_regular(parameters=True) # long time + sage: # long time + sage: G = graphs.MathonStronglyRegularGraph(1) + sage: G.is_strongly_regular(parameters=True) (784, 270, 98, 90) - sage: G = graphs.MathonStronglyRegularGraph(2) # long time - sage: G.is_strongly_regular(parameters=True) # long time + sage: G = graphs.MathonStronglyRegularGraph(2) + sage: G.is_strongly_regular(parameters=True) (784, 297, 116, 110) """ @@ -5009,12 +5048,20 @@ def IoninKharaghani765Graph(): EXAMPLES:: +<<<<<<< HEAD sage: g = graphs.IoninKharaghani765Graph(); g +======= + sage: g = graphs.IoninKharaghani765Graph(); g # needs sage.modules sage.rings.finite_rings +>>>>>>> 85d4a8d443 (./sage -fixdoctests --probe all --distribution 'sagemath-graphs[modules]' src/sage/graphs/generators/smallgraphs.py; ./sage -fixdoctests src/sage/graphs/generators/smallgraphs.py) Ionin-Kharaghani: Graph on 765 vertices TESTS:: +<<<<<<< HEAD sage: graphs.strongly_regular_graph(765, 192, 48, 48) +======= + sage: graphs.strongly_regular_graph(765, 192, 48, 48) # needs sage.modules sage.rings.finite_rings +>>>>>>> 85d4a8d443 (./sage -fixdoctests --probe all --distribution 'sagemath-graphs[modules]' src/sage/graphs/generators/smallgraphs.py; ./sage -fixdoctests src/sage/graphs/generators/smallgraphs.py) Ionin-Kharaghani: Graph on 765 vertices .. TODO:: From cd752ffa3a9806e349a34bc36290b60082398619 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 8 Jul 2023 10:53:43 -0700 Subject: [PATCH 04/10] './sage -fixdoctests --only-tags' for files conflicting with #35749 --- src/sage/graphs/generic_graph.py | 629 ++++++++++++++++--------------- 1 file changed, 323 insertions(+), 306 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index a083ed43e5e..06bee055514 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -4964,15 +4964,15 @@ def spanning_trees_count(self, root_vertex=None): EXAMPLES:: sage: G = graphs.PetersenGraph() - sage: G.spanning_trees_count() + sage: G.spanning_trees_count() # needs sage.modules 2000 :: sage: n = 11 sage: G = graphs.CompleteGraph(n) - sage: ST = G.spanning_trees_count() - sage: ST == n ^ (n - 2) + sage: ST = G.spanning_trees_count() # needs sage.modules + sage: ST == n ^ (n - 2) # needs sage.modules True :: @@ -6860,14 +6860,14 @@ def edge_disjoint_spanning_trees(self, k, algorithm=None, root=None, solver=None The Petersen Graph does have a spanning tree (it is connected):: sage: g = graphs.PetersenGraph() - sage: [T] = g.edge_disjoint_spanning_trees(1) - sage: T.is_tree() + sage: [T] = g.edge_disjoint_spanning_trees(1) # needs sage.numerical.mip + sage: T.is_tree() # needs sage.numerical.mip True Though, it does not have 2 edge-disjoint trees (as it has less than `2(|V|-1)` edges):: - sage: g.edge_disjoint_spanning_trees(2) + sage: g.edge_disjoint_spanning_trees(2) # needs sage.numerical.mip Traceback (most recent call last): ... EmptySetError: this graph does not contain the required number of trees/arborescences @@ -6877,38 +6877,38 @@ def edge_disjoint_spanning_trees(self, k, algorithm=None, root=None, solver=None sage: g = digraphs.RandomDirectedGNP(11, .3) # reduced from 30 to 11, cf. #32169 sage: k = Integer(g.edge_connectivity()) - sage: while not k: + sage: while not k: # needs sage.numerical.mip ....: g = digraphs.RandomDirectedGNP(11, .3) ....: k = Integer(g.edge_connectivity()) - sage: arborescences = g.edge_disjoint_spanning_trees(k) # long time (up to 15s on sage.math, 2011) - sage: all(a.is_directed_acyclic() for a in arborescences) # long time + sage: arborescences = g.edge_disjoint_spanning_trees(k) # long time (up to 15s on sage.math, 2011), needs sage.numerical.mip + sage: all(a.is_directed_acyclic() for a in arborescences) # long time, needs sage.numerical.mip True - sage: all(a.is_connected() for a in arborescences) # long time + sage: all(a.is_connected() for a in arborescences) # long time # needs sage.numerical.mip True In the undirected case, we can only ensure half of it:: sage: g = graphs.RandomGNP(14, .3) # reduced from 30 to 14, see #32169 - sage: while not g.is_biconnected(): + sage: while not g.is_biconnected(): # needs sage.numerical.mip ....: g = graphs.RandomGNP(14, .3) - sage: k = Integer(g.edge_connectivity()) // 2 - sage: trees = g.edge_disjoint_spanning_trees(k) - sage: all(t.is_tree() for t in trees) + sage: k = Integer(g.edge_connectivity()) // 2 # needs sage.numerical.mip + sage: trees = g.edge_disjoint_spanning_trees(k) # needs sage.numerical.mip + sage: all(t.is_tree() for t in trees) # needs sage.numerical.mip True Check the validity of the algorithms for undirected graphs:: sage: g = graphs.RandomGNP(12, .7) sage: k = Integer(g.edge_connectivity()) // 2 - sage: trees = g.edge_disjoint_spanning_trees(k, algorithm="MILP") - sage: all(t.is_tree() for t in trees) + sage: trees = g.edge_disjoint_spanning_trees(k, algorithm="MILP") # needs sage.numerical.mip + sage: all(t.is_tree() for t in trees) # needs sage.numerical.mip True - sage: all(g.order() == t.size() + 1 for t in trees) + sage: all(g.order() == t.size() + 1 for t in trees) # needs sage.numerical.mip True - sage: trees = g.edge_disjoint_spanning_trees(k, algorithm="Roskind-Tarjan") - sage: all(t.is_tree() for t in trees) + sage: trees = g.edge_disjoint_spanning_trees(k, algorithm="Roskind-Tarjan") # needs sage.numerical.mip + sage: all(t.is_tree() for t in trees) # needs sage.numerical.mip True - sage: all(g.order() == t.size() + 1 for t in trees) + sage: all(g.order() == t.size() + 1 for t in trees) # needs sage.numerical.mip True Example of :trac:`32169`:: @@ -6919,7 +6919,7 @@ def edge_disjoint_spanning_trees(self, k, algorithm=None, root=None, solver=None sage: G = DiGraph(d6, format='dig6') sage: G.edge_connectivity() 5 - sage: G.edge_disjoint_spanning_trees(5) # long time + sage: G.edge_disjoint_spanning_trees(5) # long time # needs sage.numerical.mip [Digraph on 28 vertices, Digraph on 28 vertices, Digraph on 28 vertices, @@ -6928,6 +6928,7 @@ def edge_disjoint_spanning_trees(self, k, algorithm=None, root=None, solver=None Small cases:: + sage: # needs sage.numerical.mip sage: Graph().edge_disjoint_spanning_trees(0) [] sage: Graph(1).edge_disjoint_spanning_trees(0) @@ -6947,11 +6948,11 @@ def edge_disjoint_spanning_trees(self, k, algorithm=None, root=None, solver=None Choice of the algorithm:: - sage: Graph().edge_disjoint_spanning_trees(0, algorithm=None) + sage: Graph().edge_disjoint_spanning_trees(0, algorithm=None) # needs sage.numerical.mip [] sage: Graph().edge_disjoint_spanning_trees(0, algorithm="Roskind-Tarjan") [] - sage: Graph().edge_disjoint_spanning_trees(0, algorithm="MILP") + sage: Graph().edge_disjoint_spanning_trees(0, algorithm="MILP") # needs sage.numerical.mip [] sage: Graph().edge_disjoint_spanning_trees(0, algorithm="foo") Traceback (most recent call last): @@ -6959,7 +6960,7 @@ def edge_disjoint_spanning_trees(self, k, algorithm=None, root=None, solver=None ValueError: algorithm must be None, "Rosking-Tarjan" or "MILP" for undirected graphs sage: DiGraph().edge_disjoint_spanning_trees(0, algorithm=None) [] - sage: DiGraph().edge_disjoint_spanning_trees(0, algorithm="MILP") + sage: DiGraph().edge_disjoint_spanning_trees(0, algorithm="MILP") # needs sage.numerical.mip [] sage: DiGraph().edge_disjoint_spanning_trees(0, algorithm="foo") Traceback (most recent call last): @@ -7370,25 +7371,25 @@ def vertex_cut(self, s, t, value_only=True, vertices=False, solver=None, verbose A basic application in the Pappus graph:: sage: g = graphs.PappusGraph() - sage: g.vertex_cut(1, 16, value_only=True) + sage: g.vertex_cut(1, 16, value_only=True) # needs sage.numerical.mip 3 In the bipartite complete graph `K_{2,8}`, a cut between the two vertices in the size `2` part consists of the other `8` vertices:: sage: g = graphs.CompleteBipartiteGraph(2, 8) - sage: [value, vertices] = g.vertex_cut(0, 1, value_only=False) - sage: print(value) + sage: [value, vertices] = g.vertex_cut(0, 1, value_only=False) # needs sage.numerical.mip + sage: print(value) # needs sage.numerical.mip 8 - sage: vertices == list(range(2, 10)) + sage: vertices == list(range(2, 10)) # needs sage.numerical.mip True Clearly, in this case the two sides of the cut are singletons:: - sage: [value, vertices, [set1, set2]] = g.vertex_cut(0, 1, vertices=True) - sage: len(set1) == 1 + sage: [value, vertices, [set1, set2]] = g.vertex_cut(0, 1, vertices=True) # needs sage.numerical.mip + sage: len(set1) == 1 # needs sage.numerical.mip True - sage: len(set2) == 1 + sage: len(set2) == 1 # needs sage.numerical.mip True """ from sage.numerical.mip import MixedIntegerLinearProgram @@ -7495,35 +7496,35 @@ def multiway_cut(self, vertices, value_only=False, use_edge_labels=False, edge cut:: sage: g = graphs.PetersenGraph() - sage: g.edge_cut(0,3) == g.multiway_cut([0,3], value_only = True) + sage: g.edge_cut(0,3) == g.multiway_cut([0,3], value_only=True) # needs sage.numerical.mip True As Petersen's graph is `3`-regular, a minimum multiway cut between three vertices contains at most `2\times 3` edges (which could correspond to the neighborhood of 2 vertices):: - sage: g.multiway_cut([0,3,9], value_only = True) == 2*3 + sage: g.multiway_cut([0,3,9], value_only=True) == 2*3 # needs sage.numerical.mip True In this case, though, the vertices are an independent set. If we pick instead vertices `0,9,` and `7`, we can save `4` edges in the multiway cut:: - sage: g.multiway_cut([0,7,9], value_only = True) == 2*3 - 1 + sage: g.multiway_cut([0,7,9], value_only=True) == 2*3 - 1 # needs sage.numerical.mip True This example, though, does not work in the directed case anymore, as it is not possible in Petersen's graph to mutualise edges:: sage: g = DiGraph(g) - sage: g.multiway_cut([0,7,9], value_only = True) == 3*3 + sage: g.multiway_cut([0,7,9], value_only=True) == 3*3 # needs sage.numerical.mip True Of course, a multiway cut between the whole vertex set contains all the edges of the graph:: - sage: C = g.multiway_cut(g.vertices(sort=False)) - sage: set(C) == set(g.edges(sort=False)) + sage: C = g.multiway_cut(g.vertices(sort=False)) # needs sage.numerical.mip + sage: set(C) == set(g.edges(sort=False)) # needs sage.numerical.mip True """ self._scream_if_not_simple(allow_loops=True) @@ -7634,17 +7635,18 @@ def max_cut(self, value_only=True, use_edge_labels=False, vertices=False, edges, and the two sets of vertices are the two sides:: sage: g = graphs.CompleteBipartiteGraph(5,6) - sage: [ value, edges, [ setA, setB ]] = g.max_cut(vertices=True) - sage: value == 5*6 + sage: [ value, edges, [ setA, setB ]] = g.max_cut(vertices=True) # needs sage.numerical.mip + sage: value == 5*6 # needs sage.numerical.mip True - sage: bsetA, bsetB = map(list,g.bipartite_sets()) - sage: (bsetA == setA and bsetB == setB ) or ((bsetA == setB and bsetB == setA )) + sage: bsetA, bsetB = map(list, g.bipartite_sets()) # needs sage.numerical.mip + sage: ((bsetA == setA and bsetB == setB) # needs sage.numerical.mip + ....: or (bsetA == setB and bsetB == setA)) True The max cut of a Petersen graph:: - sage: g=graphs.PetersenGraph() - sage: g.max_cut() + sage: g = graphs.PetersenGraph() + sage: g.max_cut() # needs sage.numerical.mip 12 TESTS:: @@ -7809,8 +7811,8 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", `n - 2`:: sage: g = graphs.PetersenGraph() - sage: lp = g.longest_path() - sage: lp.order() >= g.order() - 2 + sage: lp = g.longest_path() # needs sage.numerical.mip + sage: lp.order() >= g.order() - 2 # needs sage.numerical.mip True The heuristic totally agrees:: @@ -7831,8 +7833,8 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", sage: g = graphs.RandomGNP(15, 0.3) sage: for u, v in g.edge_iterator(labels=False): ....: g.set_edge_label(u, v, random()) - sage: lp = g.longest_path() - sage: (not lp.is_forest() or not max(lp.degree()) <= 2 + sage: lp = g.longest_path() # needs sage.numerical.mip + sage: (not lp.is_forest() or not max(lp.degree()) <= 2 # needs sage.numerical.mip ....: or not lp.is_connected()) False @@ -7850,9 +7852,9 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", sage: g1 = graphs.PetersenGraph() sage: g2 = 2 * g1 - sage: lp1 = g1.longest_path() - sage: lp2 = g2.longest_path() - sage: len(lp1) == len(lp2) + sage: lp1 = g1.longest_path() # needs sage.numerical.mip + sage: lp2 = g2.longest_path() # needs sage.numerical.mip + sage: len(lp1) == len(lp2) # needs sage.numerical.mip True Disconnected graphs weighted:: @@ -7861,13 +7863,14 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", sage: for u,v in g.edge_iterator(labels=False): ....: g.set_edge_label(u, v, random()) sage: g2 = 2 * g1 - sage: lp1 = g1.longest_path(use_edge_labels=True) - sage: lp2 = g2.longest_path(use_edge_labels=True) - sage: lp1[0] == lp2[0] + sage: lp1 = g1.longest_path(use_edge_labels=True) # needs sage.numerical.mip + sage: lp2 = g2.longest_path(use_edge_labels=True) # needs sage.numerical.mip + sage: lp1[0] == lp2[0] # needs sage.numerical.mip True Empty graphs:: + sage: # needs sage.numerical.mip sage: Graph().longest_path() Graph on 0 vertices sage: Graph().longest_path(use_edge_labels=True) @@ -7881,13 +7884,13 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", sage: G = Graph() sage: G.add_vertex(0) - sage: G.longest_path() + sage: G.longest_path() # needs sage.numerical.mip Graph on 0 vertices - sage: G.longest_path(use_edge_labels=True) + sage: G.longest_path(use_edge_labels=True) # needs sage.numerical.mip [0, Graph on 0 vertices] - sage: graphs.CompleteGraph(1).longest_path() + sage: graphs.CompleteGraph(1).longest_path() # needs sage.numerical.mip Graph on 0 vertices - sage: graphs.CompleteGraph(1).longest_path(use_edge_labels=True) + sage: graphs.CompleteGraph(1).longest_path(use_edge_labels=True) # needs sage.numerical.mip [0, Graph on 0 vertices] Random test for digraphs:: @@ -7895,8 +7898,8 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", sage: g = digraphs.RandomDirectedGNP(15, 0.3) sage: for u, v in g.edge_iterator(labels=False): ....: g.set_edge_label(u, v, random()) - sage: lp = g.longest_path() - sage: (not lp.is_directed_acyclic() or + sage: lp = g.longest_path() # needs sage.numerical.mip + sage: (not lp.is_directed_acyclic() or # needs sage.numerical.mip ....: not max(lp.out_degree()) <= 1 or ....: not max(lp.in_degree()) <= 1 or ....: not lp.is_connected()) @@ -7905,7 +7908,7 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", :trac:`13019`:: sage: g = graphs.CompleteGraph(5).to_directed() - sage: g.longest_path(s=1, t=2) + sage: g.longest_path(s=1, t=2) # needs sage.numerical.mip Subgraph of (Complete graph): Digraph on 5 vertices :trac:`14412`:: @@ -7913,7 +7916,7 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", sage: l = [(0, 1), (0, 3), (2, 0), (3, 4)] sage: G = DiGraph(l) sage: H = {(0, 3), (2, 0), (3, 4)} - sage: H == {x for x in G.longest_path().edge_iterator(labels=False)} + sage: H == {x for x in G.longest_path().edge_iterator(labels=False)} # needs sage.numerical.mip True """ self._scream_if_not_simple() @@ -8190,15 +8193,15 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False, Hamiltonian path starting from `(0, 0)` and ending at `(0, 1)`:: sage: g = graphs.Grid2dGraph(3, 3) - sage: g.hamiltonian_path() + sage: g.hamiltonian_path() # needs sage.numerical.mip Hamiltonian path from 2D Grid Graph for [3, 3]: Graph on 9 vertices - sage: g.hamiltonian_path(s=(0, 0), t=(2, 2)) + sage: g.hamiltonian_path(s=(0, 0), t=(2, 2)) # needs sage.numerical.mip Hamiltonian path from 2D Grid Graph for [3, 3]: Graph on 9 vertices - sage: g.hamiltonian_path(s=(0, 0), t=(2, 2), use_edge_labels=True) + sage: g.hamiltonian_path(s=(0, 0), t=(2, 2), use_edge_labels=True) # needs sage.numerical.mip (8, Hamiltonian path from 2D Grid Graph for [3, 3]: Graph on 9 vertices) - sage: g.hamiltonian_path(s=(0, 0), t=(0, 1)) is None + sage: g.hamiltonian_path(s=(0, 0), t=(0, 1)) is None # needs sage.numerical.mip True - sage: g.hamiltonian_path(s=(0, 0), t=(0, 1), use_edge_labels=True) + sage: g.hamiltonian_path(s=(0, 0), t=(0, 1), use_edge_labels=True) # needs sage.numerical.mip (0, None) TESTS: @@ -8206,13 +8209,13 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False, Empty and one-element graphs:: sage: g = Graph() - sage: g.hamiltonian_path() + sage: g.hamiltonian_path() # needs sage.numerical.mip Traceback (most recent call last): ... ValueError: the Hamiltonian path problem is not well defined for empty and one-element (di)graphs sage: g = Graph(1) - sage: g.hamiltonian_path() + sage: g.hamiltonian_path() # needs sage.numerical.mip Traceback (most recent call last): ... ValueError: the Hamiltonian path problem is not well defined @@ -8221,20 +8224,22 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False, A non-connected (di)graph has no hamiltonian path:: sage: g = Graph(2) - sage: g.hamiltonian_path() is None + sage: g.hamiltonian_path() is None # needs sage.numerical.mip True - sage: g.hamiltonian_path(use_edge_labels=True) + sage: g.hamiltonian_path(use_edge_labels=True) # needs sage.numerical.mip (0, None) sage: g = DiGraph(2) - sage: g.hamiltonian_path() is None + sage: g.hamiltonian_path() is None # needs sage.numerical.mip True Asking for a minimum (resp., maximum) weight Hamiltonian path:: sage: G = Graph([(0, 1, 1), (0, 2, 2), (0, 3, 1), (1, 2, 1), (1, 3, 2), (2, 3, 1)]) - sage: print(G.hamiltonian_path(s=0, t=1, use_edge_labels=True, maximize=False)[0]) + sage: print(G.hamiltonian_path(s=0, t=1, use_edge_labels=True, # needs sage.numerical.mip + ....: maximize=False)[0]) 3 - sage: print(G.hamiltonian_path(s=0, t=1, use_edge_labels=True, maximize=True)[0]) + sage: print(G.hamiltonian_path(s=0, t=1, use_edge_labels=True, # needs sage.numerical.mip + ....: maximize=True)[0]) 5 Parameter ``algorithm`` must be either ``'backtrack'`` or ``'MILP'``:: @@ -8444,29 +8449,28 @@ def traveling_salesman_problem(self, use_edge_labels=False, maximize=False, The Heawood graph is known to be Hamiltonian:: sage: g = graphs.HeawoodGraph() - sage: tsp = g.traveling_salesman_problem() - sage: tsp + sage: tsp = g.traveling_salesman_problem(); tsp # needs sage.numerical.mip TSP from Heawood graph: Graph on 14 vertices The solution to the TSP has to be connected:: - sage: tsp.is_connected() + sage: tsp.is_connected() # needs sage.numerical.mip True It must also be a `2`-regular graph:: - sage: tsp.is_regular(k=2) + sage: tsp.is_regular(k=2) # needs sage.numerical.mip True And obviously it is a subgraph of the Heawood graph:: - sage: tsp.is_subgraph(g, induced=False) + sage: tsp.is_subgraph(g, induced=False) # needs sage.numerical.mip True On the other hand, the Petersen Graph is known not to be Hamiltonian:: sage: g = graphs.PetersenGraph() - sage: tsp = g.traveling_salesman_problem() + sage: tsp = g.traveling_salesman_problem() # needs sage.numerical.mip Traceback (most recent call last): ... EmptySetError: the given graph is not Hamiltonian @@ -8485,8 +8489,8 @@ def traveling_salesman_problem(self, use_edge_labels=False, maximize=False, ....: g.add_edge(u, v) ....: g.set_edge_label(u, v, 2) - sage: tsp = g.traveling_salesman_problem(use_edge_labels=True) - sage: sum( tsp.edge_labels() ) < 2 * 10 + sage: tsp = g.traveling_salesman_problem(use_edge_labels=True) # needs sage.numerical.mip + sage: sum( tsp.edge_labels() ) < 2 * 10 # needs sage.numerical.mip True If we pick `1/2` instead of `2` as a cost for these new edges, they @@ -8495,18 +8499,20 @@ def traveling_salesman_problem(self, use_edge_labels=False, maximize=False, sage: for u, v in cycle.edges(labels=None, sort=False): ....: g.set_edge_label(u,v,1/2) - sage: tsp = g.traveling_salesman_problem(use_edge_labels=True) - sage: sum(tsp.edge_labels()) == (1/2) * 10 + sage: tsp = g.traveling_salesman_problem(use_edge_labels=True) # needs sage.numerical.mip + sage: sum(tsp.edge_labels()) == (1/2) * 10 # needs sage.numerical.mip True Search for a minimum and a maximum weight Hamiltonian cycle:: sage: G = Graph([(0, 1, 1), (0, 2, 2), (0, 3, 1), (1, 2, 1), (1, 3, 2), (2, 3, 1)]) - sage: tsp = G.traveling_salesman_problem(use_edge_labels=True, maximize=False) - sage: print(sum(tsp.edge_labels())) + sage: tsp = G.traveling_salesman_problem(use_edge_labels=True, # needs sage.numerical.mip + ....: maximize=False) + sage: print(sum(tsp.edge_labels())) # needs sage.numerical.mip 4 - sage: tsp = G.traveling_salesman_problem(use_edge_labels=True, maximize=True) - sage: print(sum(tsp.edge_labels())) + sage: tsp = G.traveling_salesman_problem(use_edge_labels=True, # needs sage.numerical.mip + ....: maximize=True) + sage: print(sum(tsp.edge_labels())) # needs sage.numerical.mip 6 TESTS: @@ -8523,9 +8529,10 @@ def traveling_salesman_problem(self, use_edge_labels=False, maximize=False, sage: for u, v in graphs.CycleGraph(n).edges(labels=False, sort=False): ....: if not g.has_edge(u, v): ....: g.add_edge(u, v, ZZ.random_element(1,100000)) - sage: v1 = g.traveling_salesman_problem(constraint_generation=False, use_edge_labels=True) - sage: v2 = g.traveling_salesman_problem(use_edge_labels=True) - sage: sum(v1.edge_labels()) == sum(v2.edge_labels()) + sage: v1 = g.traveling_salesman_problem(constraint_generation=False, # needs sage.numerical.mip + ....: use_edge_labels=True) + sage: v2 = g.traveling_salesman_problem(use_edge_labels=True) # needs sage.numerical.mip + sage: sum(v1.edge_labels()) == sum(v2.edge_labels()) # needs sage.numerical.mip True Then for digraphs:: @@ -8539,61 +8546,62 @@ def traveling_salesman_problem(self, use_edge_labels=False, maximize=False, sage: for u, v in digraphs.Circuit(n).edges(labels=False, sort=False): ....: if not g.has_edge(u, v): ....: g.add_edge(u, v, ZZ.random_element(1,100000)) - sage: v2 = g.traveling_salesman_problem(use_edge_labels=True) - sage: v1 = g.traveling_salesman_problem(constraint_generation=False, use_edge_labels=True) - sage: sum(v1.edge_labels()) == sum(v2.edge_labels()) + sage: v2 = g.traveling_salesman_problem(use_edge_labels=True) # needs sage.numerical.mip + sage: v1 = g.traveling_salesman_problem(constraint_generation=False, # needs sage.numerical.mip + ....: use_edge_labels=True) + sage: sum(v1.edge_labels()) == sum(v2.edge_labels()) # needs sage.numerical.mip True Simple tests for multiple edges and loops:: sage: G = DiGraph(multiedges=True, loops=True) - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical.mip False sage: G.add_vertex(0) - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical.mip False sage: G.add_edge(0, 0, 1) sage: G.add_edge(0, 0, 2) - sage: tsp = G.traveling_salesman_problem(use_edge_labels=True) + sage: tsp = G.traveling_salesman_problem(use_edge_labels=True) # needs sage.numerical.mip Traceback (most recent call last): ... EmptySetError: the given graph is not Hamiltonian sage: G.add_vertex(1) - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical.mip False sage: G.add_edge(0, 1, 2) sage: G.add_edge(0, 1, 3) sage: G.add_edge(1, 1, 1) sage: G.add_edge(1, 0, 2) - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical.mip True - sage: tsp = G.traveling_salesman_problem(use_edge_labels=True) - sage: sum(tsp.edge_labels()) + sage: tsp = G.traveling_salesman_problem(use_edge_labels=True) # needs sage.numerical.mip + sage: sum(tsp.edge_labels()) # needs sage.numerical.mip 4 Graphs on 2 vertices:: - sage: Graph([(0, 1), (0, 1)], multiedges=True).is_hamiltonian() + sage: Graph([(0, 1), (0, 1)], multiedges=True).is_hamiltonian() # needs sage.numerical.mip True - sage: DiGraph([(0, 1), (0, 1)], multiedges=True).is_hamiltonian() + sage: DiGraph([(0, 1), (0, 1)], multiedges=True).is_hamiltonian() # needs sage.numerical.mip False - sage: DiGraph([(0, 1), (1, 0)], multiedges=True).is_hamiltonian() + sage: DiGraph([(0, 1), (1, 0)], multiedges=True).is_hamiltonian() # needs sage.numerical.mip True sage: G = digraphs.Complete(2, loops=True) - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical.mip True sage: G.remove_loops() - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical.mip True sage: G.allow_loops(False) - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical.mip True Check that weight 0 edges are handled correctly (see :trac:`16214`):: sage: G = Graph([(0, 1, 1), (0, 2, 0), (0, 3, 1), (1, 2, 1), (1, 3, 0), (2, 3, 1)]) - sage: tsp = G.traveling_salesman_problem(use_edge_labels=True) - sage: sum(tsp.edge_labels()) + sage: tsp = G.traveling_salesman_problem(use_edge_labels=True) # needs sage.numerical.mip + sage: sum(tsp.edge_labels()) # needs sage.numerical.mip 2 """ from sage.categories.sets_cat import EmptySetError @@ -8953,13 +8961,13 @@ def hamiltonian_cycle(self, algorithm='tsp', solver=None, constraint_generation= The Heawood Graph is known to be Hamiltonian :: sage: g = graphs.HeawoodGraph() - sage: g.hamiltonian_cycle() + sage: g.hamiltonian_cycle() # needs sage.numerical.mip TSP from Heawood graph: Graph on 14 vertices The Petersen Graph, though, is not :: sage: g = graphs.PetersenGraph() - sage: g.hamiltonian_cycle() + sage: g.hamiltonian_cycle() # needs sage.numerical.mip Traceback (most recent call last): ... EmptySetError: the given graph is not Hamiltonian @@ -9093,11 +9101,11 @@ def feedback_vertex_set(self, value_only=False, solver=None, verbose=0, The necessary example:: sage: g = graphs.PetersenGraph() - sage: fvs = g.feedback_vertex_set() - sage: len(fvs) + sage: fvs = g.feedback_vertex_set() # needs sage.numerical.mip + sage: len(fvs) # needs sage.numerical.mip 3 - sage: g.delete_vertices(fvs) - sage: g.is_forest() + sage: g.delete_vertices(fvs) # needs sage.numerical.mip + sage: g.is_forest() # needs sage.numerical.mip True In a digraph built from a graph, any edge is replaced by arcs going in @@ -9108,19 +9116,19 @@ def feedback_vertex_set(self, value_only=False, solver=None, verbose=0, sage: cycle = graphs.CycleGraph(5) sage: dcycle = DiGraph(cycle) - sage: cycle.vertex_cover(value_only=True) + sage: cycle.vertex_cover(value_only=True) # needs sage.numerical.mip 3 - sage: feedback = dcycle.feedback_vertex_set() - sage: len(feedback) + sage: feedback = dcycle.feedback_vertex_set() # needs sage.numerical.mip + sage: len(feedback) # needs sage.numerical.mip 3 - sage: u,v = next(cycle.edge_iterator(labels=None)) - sage: u in feedback or v in feedback + sage: u,v = next(cycle.edge_iterator(labels=None)) # needs sage.numerical.mip + sage: u in feedback or v in feedback # needs sage.numerical.mip True For a circuit, the minimum feedback arc set is clearly `1`:: sage: circuit = digraphs.Circuit(5) - sage: circuit.feedback_vertex_set(value_only=True) == 1 + sage: circuit.feedback_vertex_set(value_only=True) == 1 # needs sage.numerical.mip True TESTS: @@ -9128,16 +9136,16 @@ def feedback_vertex_set(self, value_only=False, solver=None, verbose=0, Comparing with/without constraint generation:: sage: g = digraphs.RandomDirectedGNP(10, .3) - sage: x = g.feedback_vertex_set(value_only=True) - sage: y = g.feedback_vertex_set(value_only=True, - ....: constraint_generation=False) - sage: x == y + sage: x = g.feedback_vertex_set(value_only=True) # needs sage.numerical.mip + sage: y = g.feedback_vertex_set(value_only=True, # needs sage.numerical.mip + ....: constraint_generation=False) + sage: x == y # needs sage.numerical.mip True Bad algorithm:: sage: g = graphs.PetersenGraph() - sage: g.feedback_vertex_set(constraint_generation=False) + sage: g.feedback_vertex_set(constraint_generation=False) # needs sage.numerical.mip Traceback (most recent call last): ... ValueError: the only implementation available for undirected graphs is with constraint_generation set to True @@ -9621,19 +9629,19 @@ def nowhere_zero_flow(self, k=None, solver=None, verbose=0, *, integrality_toler 4-nowhere zero flow:: sage: g = graphs.PetersenGraph() - sage: h = g.nowhere_zero_flow(k=5) - sage: sorted(set(h.edge_labels())) + sage: h = g.nowhere_zero_flow(k=5) # needs sage.numerical.mip + sage: sorted(set(h.edge_labels())) # needs sage.numerical.mip [1, 2, 3, 4] - sage: h = g.nowhere_zero_flow(k=3) + sage: h = g.nowhere_zero_flow(k=3) # needs sage.numerical.mip Traceback (most recent call last): ... EmptySetError: the problem has no feasible solution The de Bruijn digraph admits a 2-nowhere zero flow:: - sage: g = digraphs.DeBruijn(2, 3) - sage: h = g.nowhere_zero_flow(k=2) - sage: sorted(set(h.edge_labels())) + sage: g = digraphs.DeBruijn(2, 3) # needs sage.combinat + sage: h = g.nowhere_zero_flow(k=2) # needs sage.combinat sage.numerical.mip + sage: sorted(set(h.edge_labels())) # needs sage.combinat sage.numerical.mip [-1, 1] TESTS: @@ -9641,7 +9649,7 @@ def nowhere_zero_flow(self, k=None, solver=None, verbose=0, *, integrality_toler Empty graph:: sage: G = Graph() - sage: G.nowhere_zero_flow() + sage: G.nowhere_zero_flow() # needs sage.numerical.mip Digraph on 0 vertices Graph with one vertex:: @@ -9649,47 +9657,47 @@ def nowhere_zero_flow(self, k=None, solver=None, verbose=0, *, integrality_toler sage: G = Graph([[1], []]) sage: G Graph on 1 vertex - sage: G.nowhere_zero_flow() + sage: G.nowhere_zero_flow() # needs sage.numerical.mip Digraph on 1 vertex Loops and multiple edges:: sage: g = Graph([(0, 0), (0, 0)], loops=True, multiedges=True) - sage: g.nowhere_zero_flow().edges(sort=True) + sage: g.nowhere_zero_flow().edges(sort=True) # needs sage.numerical.mip [(0, 0, 1), (0, 0, 1)] sage: g = Graph([(0, 0), (0, 1), (0, 1)], loops=True, multiedges=True) - sage: g.nowhere_zero_flow(k=2).edges(sort=True) + sage: g.nowhere_zero_flow(k=2).edges(sort=True) # needs sage.numerical.mip [(0, 0, 1), (0, 1, 1), (1, 0, 1)] sage: g = DiGraph([(0, 0), (0, 0)], loops=True, multiedges=True) - sage: g.nowhere_zero_flow().edges(sort=True) + sage: g.nowhere_zero_flow().edges(sort=True) # needs sage.numerical.mip [(0, 0, 1), (0, 0, 1)] sage: g = DiGraph([(0, 0), (0, 1), (0, 1)], loops=True, multiedges=True) - sage: g.nowhere_zero_flow(k=2).edges(sort=True) + sage: g.nowhere_zero_flow(k=2).edges(sort=True) # needs sage.numerical.mip [(0, 0, 1), (0, 1, -1), (0, 1, 1)] Multiple connected components:: sage: g = graphs.CycleGraph(3) * 2 - sage: h = g.nowhere_zero_flow() - sage: h.connected_components_sizes() + sage: h = g.nowhere_zero_flow() # needs sage.numerical.mip + sage: h.connected_components_sizes() # needs sage.numerical.mip [3, 3] (Di)Graphs with bridges:: sage: g = graphs.PathGraph(2) - sage: g.nowhere_zero_flow() + sage: g.nowhere_zero_flow() # needs sage.numerical.mip Traceback (most recent call last): ... EmptySetError: (di)graphs with bridges have no feasible solution sage: g = digraphs.Path(2) - sage: g.nowhere_zero_flow() + sage: g.nowhere_zero_flow() # needs sage.numerical.mip Traceback (most recent call last): ... EmptySetError: (di)graphs with bridges have no feasible solution Too small value of ``k``:: - sage: Graph().nowhere_zero_flow(k=1) + sage: Graph().nowhere_zero_flow(k=1) # needs sage.numerical.mip Traceback (most recent call last): ... ValueError: parameter 'k' must be at least 2 @@ -10010,22 +10018,22 @@ def multicommodity_flow(self, terminals, integer=True, use_edge_labels=False, matching in a graph, and to consider the paired vertices as terminals :: sage: g = graphs.PetersenGraph() - sage: matching = [(u,v) for u,v,_ in g.matching()] - sage: h = g.multicommodity_flow(matching) - sage: len(h) + sage: matching = [(u,v) for u,v,_ in g.matching()] # needs networkx + sage: h = g.multicommodity_flow(matching) # needs networkx + sage: len(h) # needs networkx 5 We could also have considered ``g`` as symmetric and computed the multicommodity flow in this version instead. In this case, however edges can be used in both directions at the same time:: - sage: h = DiGraph(g).multicommodity_flow(matching) - sage: len(h) + sage: h = DiGraph(g).multicommodity_flow(matching) # needs networkx + sage: len(h) # needs networkx 5 An exception is raised when the problem has no solution :: - sage: h = g.multicommodity_flow([(u,v,3) for u,v in matching]) + sage: h = g.multicommodity_flow([(u,v,3) for u,v in matching]) # needs networkx Traceback (most recent call last): ... EmptySetError: the multicommodity flow problem has no solution @@ -10182,7 +10190,7 @@ def _build_flow_graph(self, flow, integer): Isolated zero-cost flow cycles are also removed:: - sage: g = digraphs.DeBruijn(2, 3) + sage: g = digraphs.DeBruijn(2, 3) # needs sage.combinat sage: flow = {('000', '001'): 1, ('010', '101'): 1, ('101', '010'): 1} sage: flow_graph = g._build_flow_graph(flow, True) sage: flow_graph.edges(sort=True) @@ -10258,13 +10266,13 @@ def disjoint_routed_paths(self, pairs, solver=None, verbose=0, top-right corner to the bottom-right corner is easy:: sage: g = graphs.Grid2dGraph(5, 5) - sage: p1,p2 = g.disjoint_routed_paths([((0, 0), (0, 4)), ((4, 4), (4, 0))]) + sage: p1,p2 = g.disjoint_routed_paths([((0, 0), (0, 4)), ((4, 4), (4, 0))]) # needs sage.numerical.mip Though there is obviously no solution to the problem in which each corner is sending information to the opposite one:: sage: g = graphs.Grid2dGraph(5, 5) - sage: p1,p2 = g.disjoint_routed_paths([((0, 0), (4, 4)), ((0, 4), (4, 0))]) + sage: p1,p2 = g.disjoint_routed_paths([((0, 0), (4, 4)), ((0, 4), (4, 0))]) # needs sage.numerical.mip Traceback (most recent call last): ... EmptySetError: the disjoint routed paths do not exist @@ -10384,7 +10392,7 @@ def vertex_disjoint_paths(self, s, t, solver=None, verbose=0, In a complete bipartite graph :: sage: g = graphs.CompleteBipartiteGraph(2, 3) - sage: g.vertex_disjoint_paths(0, 1) + sage: g.vertex_disjoint_paths(0, 1) # needs sage.numerical.mip [[0, 2, 1], [0, 3, 1], [0, 4, 1]] TESTS: @@ -10392,9 +10400,9 @@ def vertex_disjoint_paths(self, s, t, solver=None, verbose=0, Fix issues reported in :trac:`22990`:: sage: g = digraphs.Path(2) - sage: g.vertex_disjoint_paths(0, 1) + sage: g.vertex_disjoint_paths(0, 1) # needs sage.numerical.mip [[0, 1]] - sage: g.vertex_disjoint_paths(1, 0) + sage: g.vertex_disjoint_paths(1, 0) # needs sage.numerical.mip [] """ obj, flow_graph = self.flow(s, t, value_only=False, integer=True, use_edge_labels=False, @@ -10507,14 +10515,14 @@ def pagerank(self, alpha=0.85, personalization=None, by_weight=False, 4: 0.3063198690713853, 5: 0.1700057609707141, 6: 0.05390084497706962} - sage: G.pagerank(algorithm="Scipy") # abs tol 1e-9 # needs scipy + sage: G.pagerank(algorithm="Scipy") # abs tol 1e-9 # needs networkx 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 # needs scipy + sage: G.pagerank(algorithm="Scipy", by_weight=True) # abs tol 1e-9 # needs networkx scipy {1: 0.16459583718588994, 2: 0.13977928595154515, 3: 0.16539840184339605, @@ -10528,14 +10536,14 @@ def pagerank(self, alpha=0.85, personalization=None, by_weight=False, 4: 0.23749999999999993, 5: 0.17775603392041744, 6: 0.10054631441617742} - sage: G.pagerank() # abs tol 1e-9 + sage: G.pagerank() # abs tol 1e-9 # needs networkx {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 # needs networkx {1: 0.16459583718588994, 2: 0.13977928595154515, 3: 0.16539840184339605, @@ -11395,11 +11403,11 @@ def vertices(self, sort=None, key=None, degree=None, vertex_property=None): sage: t = polygen(QQ, 't') sage: K = Graph({5*t: [t^2], t^2: [t^2+2], t^2+2: [4*t^2-6], 4*t^2-6: [5*t]}) - sage: dsc = sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint.discriminant - sage: verts = K.vertices(sort=True, key=dsc) - sage: verts + sage: from sage.rings.polynomial.polynomial_rational_flint import Polynomial_rational_flint # needs sage.libs.flint + sage: dsc = Polynomial_rational_flint.discriminant # needs sage.libs.flint + sage: verts = K.vertices(sort=True, key=dsc); verts # needs sage.libs.flint [t^2 + 2, t^2, 5*t, 4*t^2 - 6] - sage: [x.discriminant() for x in verts] + sage: [x.discriminant() for x in verts] # needs sage.libs.flint [-8, 0, 1, 96] TESTS: @@ -13924,7 +13932,7 @@ def subgraph_search_count(self, G, induced=False): sage: T3 = digraphs.TransitiveTournament(3) sage: T5.subgraph_search_count(T3) # needs sage.modules 10 - sage: binomial(5,3) + sage: binomial(5,3) # needs sage.symbolic 10 sage: T3.is_isomorphic(T5.subgraph(vertices=[0, 1, 2])) # needs sage.modules True @@ -15275,9 +15283,9 @@ def clustering_average(self, implementation=None): The result is the same with all implementations:: + sage: # needs networkx sage: G = graphs.RandomGNM(10,20) - sage: impls = ['boost','sparse_copy','dense_copy'] - sage: impls += ['networkx'] # needs networkx + sage: impls = ['boost', 'sparse_copy', 'dense_copy', 'networkx'] sage: coeffs = [G.clustering_average(implementation=impl) ....: for impl in impls] sage: max(coeffs) - min(coeffs) # tol abs 1e-12 @@ -15355,7 +15363,7 @@ def clustering_coeff(self, {0: 1/3, 1: 1/3, 2: 0, 3: 1/3, 4: 1/3, 5: 1/3, 6: 1/3, 7: 1/3, 8: 0, 9: 1/3, 10: 1/3, 11: 0} - sage: (graphs.FruchtGraph()).clustering_coeff(weight=True) + sage: (graphs.FruchtGraph()).clustering_coeff(weight=True) # needs networkx {0: 0.3333333333333333, 1: 0.3333333333333333, 2: 0, 3: 0.3333333333333333, 4: 0.3333333333333333, 5: 0.3333333333333333, 6: 0.3333333333333333, @@ -15365,8 +15373,8 @@ def clustering_coeff(self, sage: (graphs.FruchtGraph()).clustering_coeff(nodes=[0,1,2]) {0: 0.3333333333333333, 1: 0.3333333333333333, 2: 0.0} - sage: (graphs.FruchtGraph()).clustering_coeff(nodes=[0,1,2], - ....: weight=True) + sage: (graphs.FruchtGraph()).clustering_coeff(nodes=[0,1,2], # needs networkx + ....: weight=True) {0: 0.3333333333333333, 1: 0.3333333333333333, 2: 0} sage: (graphs.GridGraph([5,5])).clustering_coeff(nodes=[(0,0),(0,1),(2,2)]) @@ -15390,6 +15398,7 @@ def clustering_coeff(self, Check that the result is the same with all implementations:: + sage: # needs networkx sage: G = graphs.RandomGNM(10, 20) sage: G.relabel(list("abcdefghik")) sage: coeffs = [G.clustering_coeff(implementation=impl) @@ -15774,8 +15783,8 @@ def odd_girth(self, algorithm="bfs", certificate=False): Bipartite graphs have no odd cycle and consequently have infinite odd girth:: - sage: G = graphs.RandomBipartite(6, 6, .5) - sage: G.odd_girth() + sage: G = graphs.RandomBipartite(6, 6, .5) # needs numpy + sage: G.odd_girth() # needs numpy +Infinity sage: G = graphs.Grid2dGraph(3, 4) sage: G.odd_girth() @@ -16186,17 +16195,17 @@ def centrality_closeness(self, vert=None, by_weight=False, algorithm=None, sage: import itertools sage: n = random.randint(2,20) sage: m = random.randint(0, n*(n-1)/2) - sage: g = graphs.RandomGNM(n,m) - sage: c1 = g.centrality_closeness(algorithm='BFS') - sage: c2 = g.centrality_closeness(algorithm='NetworkX') - sage: c3 = g.centrality_closeness(algorithm='Dijkstra_Boost') - sage: c4 = g.centrality_closeness(algorithm='Floyd-Warshall-Cython') - sage: c5 = g.centrality_closeness(algorithm='Floyd-Warshall-Python') - sage: c6 = g.centrality_closeness(algorithm='Johnson_Boost') - sage: len(c1)==len(c2)==len(c3)==len(c4)==len(c5)==len(c6) - True - sage: c = [c1,c2,c3,c4,c5,c6] - sage: all( sum(abs(ci[v] - cj[v]) for v in g if g.degree(v)) < 1e-12 + sage: g = graphs.RandomGNM(n,m) # needs networkx + sage: c1 = g.centrality_closeness(algorithm='BFS') # needs networkx + sage: c2 = g.centrality_closeness(algorithm='NetworkX') # needs networkx + sage: c3 = g.centrality_closeness(algorithm='Dijkstra_Boost') # needs networkx + sage: c4 = g.centrality_closeness(algorithm='Floyd-Warshall-Cython') # needs networkx + sage: c5 = g.centrality_closeness(algorithm='Floyd-Warshall-Python') # needs networkx + sage: c6 = g.centrality_closeness(algorithm='Johnson_Boost') # needs networkx + sage: len(c1)==len(c2)==len(c3)==len(c4)==len(c5)==len(c6) # needs networkx + True + sage: c = [c1,c2,c3,c4,c5,c6] # needs networkx + sage: all( sum(abs(ci[v] - cj[v]) for v in g if g.degree(v)) < 1e-12 # needs networkx ....: for ci, cj in itertools.combinations(c, 2) ) True @@ -16208,15 +16217,15 @@ def centrality_closeness(self, vert=None, by_weight=False, algorithm=None, sage: m = random.randint(0, n*(n-1)/2) sage: g = digraphs.RandomDirectedGNM(n,m) sage: c1 = g.centrality_closeness(algorithm='BFS') - sage: c2 = g.centrality_closeness(algorithm='NetworkX') + sage: c2 = g.centrality_closeness(algorithm='NetworkX') # needs networkx sage: c3 = g.centrality_closeness(algorithm='Dijkstra_Boost') sage: c4 = g.centrality_closeness(algorithm='Floyd-Warshall-Cython') sage: c5 = g.centrality_closeness(algorithm='Floyd-Warshall-Python') sage: c6 = g.centrality_closeness(algorithm='Johnson_Boost') - sage: len(c1)==len(c2)==len(c3)==len(c4)==len(c5)==len(c6) + sage: len(c1)==len(c2)==len(c3)==len(c4)==len(c5)==len(c6) # needs networkx True - sage: c = [c1,c2,c3,c4,c5,c6] - sage: all( sum(abs(ci[v] - cj[v]) for v in g if g.out_degree(v)) < 1e-12 + sage: c = [c1,c2,c3,c4,c5,c6] # needs networkx + sage: all( sum(abs(ci[v] - cj[v]) for v in g if g.out_degree(v)) < 1e-12 # needs networkx ....: for ci, cj in itertools.combinations(c, 2) ) True @@ -16226,17 +16235,17 @@ def centrality_closeness(self, vert=None, by_weight=False, algorithm=None, sage: import itertools sage: n = random.randint(2,20) sage: m = random.randint(0, n*(n-1)/2) - sage: g = graphs.RandomGNM(n,m) - sage: for v,w in g.edges(sort=True, labels=False): + sage: g = graphs.RandomGNM(n,m) # needs networkx + sage: for v,w in g.edges(sort=True, labels=False): # needs networkx ....: g.set_edge_label(v,w,float(random.uniform(1,100))) - sage: c1 = g.centrality_closeness(by_weight=True, algorithm='NetworkX') - sage: c2 = g.centrality_closeness(by_weight=True, algorithm='Dijkstra_Boost') - sage: c3 = g.centrality_closeness(by_weight=True, algorithm='Floyd-Warshall-Python') - sage: c4 = g.centrality_closeness(by_weight=True, algorithm='Johnson_Boost') - sage: len(c1)==len(c2)==len(c3)==len(c4) - True - sage: c = [c1,c2,c3,c4] - sage: all( sum(abs(ci[v] - cj[v]) for v in g if g.degree(v)) < 1e-12 + sage: c1 = g.centrality_closeness(by_weight=True, algorithm='NetworkX') # needs networkx + sage: c2 = g.centrality_closeness(by_weight=True, algorithm='Dijkstra_Boost') # needs networkx + sage: c3 = g.centrality_closeness(by_weight=True, algorithm='Floyd-Warshall-Python') # needs networkx + sage: c4 = g.centrality_closeness(by_weight=True, algorithm='Johnson_Boost') # needs networkx + sage: len(c1)==len(c2)==len(c3)==len(c4) # needs networkx + True + sage: c = [c1,c2,c3,c4] # needs networkx + sage: all( sum(abs(ci[v] - cj[v]) for v in g if g.degree(v)) < 1e-12 # needs networkx ....: for ci, cj in itertools.combinations(c, 2) ) True @@ -16370,29 +16379,29 @@ def triangles_count(self, algorithm=None): have:: sage: G = graphs.CompleteGraph(15) - sage: G.triangles_count() == binomial(15, 3) + sage: G.triangles_count() == binomial(15, 3) # needs sage.symbolic True The 2-dimensional DeBruijn graph of 2 symbols has 2 directed `C_3`:: - sage: G = digraphs.DeBruijn(2,2) - sage: G.triangles_count() + sage: G = digraphs.DeBruijn(2,2) # needs sage.combinat + sage: G.triangles_count() # needs sage.combinat 2 The directed `n`-cycle is trivially triangle free for `n > 3`:: sage: G = digraphs.Circuit(10) - sage: G.triangles_count() + sage: G.triangles_count() # needs sage.modules 0 TESTS: Comparison of algorithms:: - sage: G = graphs.RandomBarabasiAlbert(50,2) + sage: G = graphs.RandomBarabasiAlbert(50,2) # needs networkx sage: results = [] sage: results.append(G.triangles_count(algorithm='matrix')) - sage: results.append(G.triangles_count(algorithm='iter')) + sage: results.append(G.triangles_count(algorithm='iter')) # needs sage.modules sage: results.append(G.triangles_count(algorithm='sparse_copy')) sage: results.append(G.triangles_count(algorithm='dense_copy')) sage: any(x != results[0] for x in results) @@ -17050,7 +17059,8 @@ def shortest_paths(self, u, by_weight=False, algorithm=None, However, if ``check_weight`` is set to ``False``, unexpected behavior may occur:: - sage: D.shortest_paths(0, algorithm='Dijkstra_NetworkX', weight_function=lambda e:e[2], check_weight=False) + sage: D.shortest_paths(0, algorithm='Dijkstra_NetworkX', # needs networkx + ....: weight_function=lambda e:e[2], check_weight=False) Traceback (most recent call last): ... TypeError: unsupported operand type(s) for +: 'int' and 'dict' @@ -17093,7 +17103,7 @@ def shortest_paths(self, u, by_weight=False, algorithm=None, Traceback (most recent call last): ... RuntimeError: Dijkstra algorithm does not work with negative weights, use Bellman-Ford instead - sage: D.shortest_paths(0, algorithm='Dijkstra_NetworkX', by_weight=True) + sage: D.shortest_paths(0, algorithm='Dijkstra_NetworkX', by_weight=True) # needs networkx Traceback (most recent call last): ... ValueError: ('Contradictory paths found:', 'negative weights?') @@ -17500,12 +17510,12 @@ def shortest_path_all_pairs(self, by_weight=False, algorithm=None, sage: d1, _ = g.shortest_path_all_pairs(algorithm="BFS") sage: d2, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall-Cython") sage: d3, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall-Python") - sage: d4, _ = g.shortest_path_all_pairs(algorithm="Dijkstra_NetworkX") + sage: d4, _ = g.shortest_path_all_pairs(algorithm="Dijkstra_NetworkX") # needs networkx sage: d5, _ = g.shortest_path_all_pairs(algorithm="Dijkstra_Boost") sage: d6, _ = g.shortest_path_all_pairs(algorithm="Johnson_Boost") sage: d7, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall_Boost") - sage: d8, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall_SciPy") - sage: d1 == d2 == d3 == d4 == d5 == d6 == d7 == d8 + sage: d8, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall_SciPy") # needs scipy + sage: d1 == d2 == d3 == d4 == d5 == d6 == d7 == d8 # needs networkx scipy True Checking that distances are equal regardless of the algorithm used:: @@ -17514,12 +17524,12 @@ def shortest_path_all_pairs(self, by_weight=False, algorithm=None, sage: d1, _ = g.shortest_path_all_pairs(algorithm="BFS") sage: d2, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall-Cython") sage: d3, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall-Python") - sage: d4, _ = g.shortest_path_all_pairs(algorithm="Dijkstra_NetworkX") + sage: d4, _ = g.shortest_path_all_pairs(algorithm="Dijkstra_NetworkX") # needs networkx sage: d5, _ = g.shortest_path_all_pairs(algorithm="Dijkstra_Boost") sage: d6, _ = g.shortest_path_all_pairs(algorithm="Johnson_Boost") sage: d7, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall_Boost") - sage: d8, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall_SciPy") - sage: d1 == d2 == d3 == d4 == d5 == d6 == d7 == d8 + sage: d8, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall_SciPy") # needs scipy + sage: d1 == d2 == d3 == d4 == d5 == d6 == d7 == d8 # needs networkx scipy True Checking that weighted distances are equal regardless of the algorithm @@ -17530,12 +17540,12 @@ def shortest_path_all_pairs(self, by_weight=False, algorithm=None, sage: for v, w in g.edges(labels=False, sort=False): ....: g.add_edge(v, w, random.uniform(1, 10)) sage: d1, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall-Python") - sage: d2, _ = g.shortest_path_all_pairs(algorithm="Dijkstra_NetworkX") + sage: d2, _ = g.shortest_path_all_pairs(algorithm="Dijkstra_NetworkX") # needs networkx sage: d3, _ = g.shortest_path_all_pairs(algorithm="Dijkstra_Boost") sage: d4, _ = g.shortest_path_all_pairs(algorithm="Johnson_Boost") sage: d5, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall_Boost") - sage: d6, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall_SciPy") - sage: d1 == d2 == d3 == d4 == d5 == d6 + sage: d6, _ = g.shortest_path_all_pairs(algorithm="Floyd-Warshall_SciPy") # needs scipy + sage: d1 == d2 == d3 == d4 == d5 == d6 # needs networkx scipy True Checking a random path is valid:: @@ -17562,7 +17572,7 @@ def shortest_path_all_pairs(self, by_weight=False, algorithm=None, sage: g.shortest_path_all_pairs(algorithm='BFS') ({0: {0: 0, 1: 1, 2: 2}, 1: {1: 0, 2: 1}, 2: {2: 0}}, {0: {0: None, 1: 0, 2: 1}, 1: {1: None, 2: 1}, 2: {2: None}}) - sage: g.shortest_path_all_pairs(algorithm='Dijkstra_NetworkX') + sage: g.shortest_path_all_pairs(algorithm='Dijkstra_NetworkX') # needs networkx ({0: {0: 0, 1: 1, 2: 2}, 1: {1: 0, 2: 1}, 2: {2: 0}}, {0: {0: None, 1: 1, 2: 1}, 1: {1: None, 2: 2}, 2: {2: None}}) sage: g.shortest_path_all_pairs(algorithm='Dijkstra_Boost') @@ -17574,7 +17584,7 @@ def shortest_path_all_pairs(self, by_weight=False, algorithm=None, sage: g.shortest_path_all_pairs(algorithm='Floyd-Warshall-Cython') ({0: {0: 0, 1: 1, 2: 2}, 1: {1: 0, 2: 1}, 2: {2: 0}}, {0: {0: None, 1: 0, 2: 1}, 1: {1: None, 2: 1}, 2: {2: None}}) - sage: g.shortest_path_all_pairs(algorithm='Floyd-Warshall_SciPy') + sage: g.shortest_path_all_pairs(algorithm='Floyd-Warshall_SciPy') # needs scipy ({0: {0: 0.0, 1: 1.0, 2: 2.0}, 1: {1: 0.0, 2: 1.0}, 2: {2: 0.0}}, {0: {0: None, 1: 0, 2: 1}, 1: {1: None, 2: 1}, 2: {2: None}}) @@ -17846,7 +17856,7 @@ def wiener_index(self, by_weight=False, algorithm=None, 15 sage: G.wiener_index(algorithm='Johnson_Boost') 15 - sage: G.wiener_index(algorithm='Dijkstra_NetworkX') + sage: G.wiener_index(algorithm='Dijkstra_NetworkX') # needs networkx 15 Wiener index of complete (di)graphs:: @@ -19000,6 +19010,7 @@ def tensor_product(self, other): The tensor product of two DeBruijn digraphs of same diameter is a DeBruijn digraph:: + sage: # needs sage.combinat sage: B1 = digraphs.DeBruijn(2, 3) sage: B2 = digraphs.DeBruijn(3, 3) sage: T = B1.tensor_product(B2) @@ -20277,13 +20288,14 @@ def layout_graphviz(self, dim=2, prog='dot', **options): Make sure that :trac:`12364` is fixed:: + sage: # needs sage.combinat sage: m = WordMorphism('a->abb,b->ba') sage: w = m.fixed_point('a') - sage: prefix = Word(list(w[:100])) - sage: pals = prefix.palindromes() - sage: poset = Poset((pals, lambda x,y: x.is_factor(y))) - sage: H = poset.hasse_diagram() - sage: d = H.layout_graphviz() # optional - dot2tex graphviz + sage: prefix = Word(list(w[:100])) # needs sage.modules + sage: pals = prefix.palindromes() # needs sage.modules + sage: poset = Poset((pals, lambda x,y: x.is_factor(y))) # needs sage.modules + sage: H = poset.hasse_diagram() # needs sage.modules + sage: d = H.layout_graphviz() # optional - dot2tex graphviz # needs sage.modules """ assert_have_dot2tex() assert dim == 2, "3D graphviz layout not implemented" @@ -20750,11 +20762,11 @@ def plot(self, **options): :: - sage: from sage.plot.colors import rainbow + sage: from sage.plot.colors import rainbow # needs sage.plot sage: C = graphs.CubeGraph(5) - sage: R = rainbow(5) - sage: edge_colors = {R[i]: [] for i in range(5)} - sage: for u, v, l in C.edges(sort=False): + sage: R = rainbow(5) # needs sage.plot + sage: edge_colors = {R[i]: [] for i in range(5)} # needs sage.plot + sage: for u, v, l in C.edges(sort=False): # needs sage.plot ....: for i in range(5): ....: if u[i] != v[i]: ....: edge_colors[R[i]].append((u, v, l)) @@ -20887,6 +20899,7 @@ def plot(self, **options): :: + sage: # needs sage.modular sage: S = SupersingularModule(389) sage: H = S.hecke_matrix(2) sage: D = DiGraph(H, sparse=True) @@ -21074,9 +21087,9 @@ def plot3d(self, bgcolor=(1, 1, 1), :: sage: P = graphs.PetersenGraph().to_directed() - sage: from sage.plot.colors import rainbow - sage: R = rainbow(P.size(), 'rgbtuple') - sage: edge_colors = {R[i]: [e] for i, e in enumerate(P.edge_iterator())} + sage: from sage.plot.colors import rainbow # needs sage.plot + sage: R = rainbow(P.size(), 'rgbtuple') # needs sage.plot + sage: edge_colors = {R[i]: [e] for i, e in enumerate(P.edge_iterator())} # needs sage.plot sage: P.plot3d(engine='tachyon', edge_colors=edge_colors).show() # long time, needs sage.plot @@ -21816,12 +21829,12 @@ def graphviz_string(self, **options): Check that :trac:`25121` is fixed:: sage: G = Graph([(0, 1)]) - sage: G.graphviz_string(edge_colors={(0.25, 0.5, 1.0): [(0, 1)]}) + sage: G.graphviz_string(edge_colors={(0.25, 0.5, 1.0): [(0, 1)]}) # needs sage.plot 'graph {\n node_0 [label="0"];\n node_1 [label="1"];\n\n node_0 -- node_1 [color = "#4080ff"];\n}' sage: G = Graph([(0, 1)]) - sage: G.set_latex_options(edge_colors={(0, 1): (0.25, 0.5, 1.0)}) - sage: print(G.latex_options().dot2tex_picture()) # optional - dot2tex graphviz + sage: G.set_latex_options(edge_colors={(0, 1): (0.25, 0.5, 1.0)}) # needs sage.plot + sage: print(G.latex_options().dot2tex_picture()) # optional - dot2tex graphviz, needs sage.plot \begin{tikzpicture}[>=latex,line join=bevel,] ... \definecolor{strokecolor}{rgb}{0.25,0.5,1.0}; @@ -22069,26 +22082,26 @@ def spectrum(self, laplacian=False): EXAMPLES:: sage: P = graphs.PetersenGraph() - sage: P.spectrum() # needs sage.modules + sage: P.spectrum() # needs sage.modules sage.rings.number_field [3, 1, 1, 1, 1, 1, -2, -2, -2, -2] - sage: P.spectrum(laplacian=True) # needs sage.modules + sage: P.spectrum(laplacian=True) # needs sage.modules sage.rings.number_field [5, 5, 5, 5, 2, 2, 2, 2, 2, 0] sage: D = P.to_directed() sage: D.delete_edge(7, 9) - sage: D.spectrum() # needs sage.modules + sage: D.spectrum() # needs sage.modules sage.rings.number_field [2.9032119259..., 1, 1, 1, 1, 0.8060634335..., -1.7092753594..., -2, -2, -2] :: sage: C = graphs.CycleGraph(8) - sage: C.spectrum() # needs sage.modules + sage: C.spectrum() # needs sage.modules sage.rings.number_field [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() # needs sage.modules + sage: T.spectrum() # needs sage.modules sage.rings.number_field [1, -0.5000000000... + 0.8660254037...*I, -0.5000000000... - 0.8660254037...*I] TESTS: @@ -22102,10 +22115,10 @@ def spectrum(self, laplacian=False): eigenvalues. :: sage: H = graphs.HoffmanSingletonGraph() - sage: evals = H.spectrum() # needs sage.modules - sage: lap = [7 - x for x in evals] # needs sage.modules - sage: lap.sort(reverse=True) # needs sage.modules - sage: lap == H.spectrum(laplacian=True) # needs sage.modules + sage: evals = H.spectrum() # needs sage.modules sage.rings.number_field + sage: lap = [7 - x for x in evals] # needs sage.modules sage.rings.number_field + sage: lap.sort(reverse=True) # needs sage.modules sage.rings.number_field + sage: lap == H.spectrum(laplacian=True) # needs sage.modules sage.rings.number_field True """ # Ideally the spectrum should return something like a Factorization object @@ -22191,7 +22204,7 @@ def eigenvectors(self, laplacian=False): EXAMPLES:: sage: P = graphs.PetersenGraph() - sage: P.eigenvectors() # needs sage.modules + sage: P.eigenvectors() # needs sage.modules sage.rings.number_field [(3, [ (1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ], 1), (-2, [ @@ -22211,7 +22224,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) # needs sage.modules + sage: P.eigenvectors(laplacian=True) # needs sage.modules sage.rings.number_field [(0, [ (1, 1, 1, 1, 1, 1, 1, 1, 1, 1) ], 1), (5, [ @@ -22230,7 +22243,7 @@ def eigenvectors(self, laplacian=False): :: sage: C = graphs.CycleGraph(8) - sage: C.eigenvectors() # needs sage.modules + sage: C.eigenvectors() # needs sage.modules sage.rings.number_field [(2, [ (1, 1, 1, 1, 1, 1, 1, 1) @@ -22260,7 +22273,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() # needs sage.modules + sage: T.eigenvectors() # needs sage.modules sage.rings.number_field [(1, [ (1, 1, 1) @@ -22301,7 +22314,7 @@ def eigenspaces(self, laplacian=False): EXAMPLES:: sage: P = graphs.PetersenGraph() - sage: P.eigenspaces() # needs sage.modules + sage: P.eigenspaces() # needs sage.modules sage.rings.number_field [ (3, Vector space of degree 10 and dimension 1 over Rational Field User basis matrix: @@ -22325,7 +22338,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) # needs sage.modules + sage: P.eigenspaces(laplacian=True) # needs sage.modules sage.rings.number_field [ (0, Vector space of degree 10 and dimension 1 over Rational Field User basis matrix: @@ -22350,7 +22363,7 @@ def eigenspaces(self, laplacian=False): corresponding eigenspace:: sage: C = graphs.CycleGraph(8) - sage: C.eigenspaces() # needs sage.modules + sage: C.eigenspaces() # needs sage.modules sage.rings.number_field [ (2, Vector space of degree 8 and dimension 1 over Rational Field User basis matrix: @@ -22373,7 +22386,7 @@ def eigenspaces(self, laplacian=False): we have:: sage: T = DiGraph({0: [1], 1: [2], 2: [0]}) - sage: T.eigenspaces() # needs sage.modules + sage: T.eigenspaces() # needs sage.modules sage.rings.number_field [ (1, Vector space of degree 3 and dimension 1 over Rational Field User basis matrix: @@ -22980,7 +22993,7 @@ def automorphism_group(self, partition=None, verbosity=0, (4, ((2,3), (0,1))) (24, ((2,3), (1,2), (0,1))) sage: C = graphs.CubeGraph(4) - sage: G = C.automorphism_group() + sage: G = C.automorphism_group() # needs sage.groups sage: M = G.character_table() # random order of rows, thus abs() below sage: QQ(M.determinant()).abs() 712483534798848 @@ -22990,7 +23003,7 @@ def automorphism_group(self, partition=None, verbosity=0, :: sage: D = graphs.DodecahedralGraph() - sage: G = D.automorphism_group() + sage: G = D.automorphism_group() # needs sage.groups sage: A5 = AlternatingGroup(5) sage: Z2 = CyclicPermutationGroup(2) sage: H = A5.direct_product(Z2)[0] #see documentation for direct_product to explain the [0] @@ -23003,49 +23016,49 @@ def automorphism_group(self, partition=None, verbosity=0, sage: G.add_edge(('a', 'b')) sage: G.add_edge(('a', 'b')) sage: G.add_edge(('a', 'b')) - sage: G.automorphism_group() + sage: G.automorphism_group() # needs sage.groups Permutation Group with generators [('a','b')] Digraphs:: sage: D = DiGraph( { 0:[1], 1:[2], 2:[3], 3:[4], 4:[0] } ) - sage: D.automorphism_group() + sage: D.automorphism_group() # needs sage.groups Permutation Group with generators [(0,1,2,3,4)] Edge labeled graphs:: sage: G = Graph(sparse=True) sage: G.add_edges( [(0,1,'a'),(1,2,'b'),(2,3,'c'),(3,4,'b'),(4,0,'a')] ) - sage: G.automorphism_group(edge_labels=True) + sage: G.automorphism_group(edge_labels=True) # needs sage.groups Permutation Group with generators [(1,4)(2,3)] sage: G.automorphism_group(edge_labels=True, algorithm="bliss") # optional - bliss Permutation Group with generators [(1,4)(2,3)] - sage: G.automorphism_group(edge_labels=True, algorithm="sage") + sage: G.automorphism_group(edge_labels=True, algorithm="sage") # needs sage.groups Permutation Group with generators [(1,4)(2,3)] :: sage: G = Graph({0 : {1 : 7}}) - sage: G.automorphism_group(edge_labels=True) + sage: G.automorphism_group(edge_labels=True) # needs sage.groups Permutation Group with generators [(0,1)] sage: foo = Graph(sparse=True) sage: bar = Graph(sparse=True) sage: foo.add_edges([(0,1,1),(1,2,2), (2,3,3)]) sage: bar.add_edges([(0,1,1),(1,2,2), (2,3,3)]) - sage: foo.automorphism_group(edge_labels=True) + sage: foo.automorphism_group(edge_labels=True) # needs sage.groups Permutation Group with generators [()] - sage: foo.automorphism_group() + sage: foo.automorphism_group() # needs sage.groups Permutation Group with generators [(0,3)(1,2)] - sage: bar.automorphism_group(edge_labels=True) + sage: bar.automorphism_group(edge_labels=True) # needs sage.groups Permutation Group with generators [()] You can also ask for just the order of the group:: sage: G = graphs.PetersenGraph() - sage: G.automorphism_group(return_group=False, order=True) + sage: G.automorphism_group(return_group=False, order=True) # needs sage.groups 120 Or, just the orbits (note that each graph here is vertex transitive) @@ -23053,15 +23066,15 @@ def automorphism_group(self, partition=None, verbosity=0, :: sage: G = graphs.PetersenGraph() - sage: G.automorphism_group(return_group=False, orbits=True, algorithm='sage') + sage: G.automorphism_group(return_group=False, orbits=True, algorithm='sage') # needs sage.groups [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] - sage: orb = G.automorphism_group(partition=[[0],list(range(1,10))], + sage: orb = G.automorphism_group(partition=[[0],list(range(1,10))], # needs sage.groups ....: return_group=False, orbits=True, algorithm='sage') - sage: sorted([sorted(o) for o in orb], key=len) + sage: sorted([sorted(o) for o in orb], key=len) # needs sage.groups [[0], [1, 4, 5], [2, 3, 6, 7, 8, 9]] sage: C = graphs.CubeGraph(3) - sage: orb = C.automorphism_group(orbits=True, return_group=False, algorithm='sage') - sage: [sorted(o) for o in orb] + sage: orb = C.automorphism_group(orbits=True, return_group=False, algorithm='sage') # needs sage.groups + sage: [sorted(o) for o in orb] # needs sage.groups [['000', '001', '010', '011', '100', '101', '110', '111']] One can also use the faster algorithm for computing the automorphism @@ -23069,9 +23082,9 @@ def automorphism_group(self, partition=None, verbosity=0, sage: # optional - bliss sage: G = graphs.HallJankoGraph() - sage: A1 = G.automorphism_group() + sage: A1 = G.automorphism_group() # needs sage.groups sage: A2 = G.automorphism_group(algorithm='bliss') - sage: A1.is_isomorphic(A2) + sage: A1.is_isomorphic(A2) # needs sage.groups True TESTS: @@ -23080,47 +23093,47 @@ def automorphism_group(self, partition=None, verbosity=0, sage: g=graphs.CubeGraph(3) sage: g.relabel() - sage: g.automorphism_group(partition=[[0,1,2],[3,4,5]],algorithm='sage') + sage: g.automorphism_group(partition=[[0,1,2],[3,4,5]],algorithm='sage') # needs sage.groups Traceback (most recent call last): ... KeyError: ... Labeled automorphism group:: - sage: d = digraphs.DeBruijn(3,2) - sage: A = d.automorphism_group(algorithm='sage') + sage: d = digraphs.DeBruijn(3,2) # needs sage.combinat + sage: A = d.automorphism_group(algorithm='sage') # needs sage.combinat sage: A_target = PermutationGroup(["('02','10','21')('00','11','22')('01','12','20')", ....: "('02','01')('10','20')('21','12')('22','11')"]) - sage: A.is_isomorphic(A_target) + sage: A.is_isomorphic(A_target) # needs sage.combinat True - sage: d.allow_multiple_edges(True) - sage: d.add_edge(('00', '00', '0')) - sage: A = d.automorphism_group(algorithm='sage') + sage: d.allow_multiple_edges(True) # needs sage.combinat + sage: d.add_edge(('00', '00', '0')) # needs sage.combinat + sage: A = d.automorphism_group(algorithm='sage') # needs sage.combinat sage: A_target = PermutationGroup(["('01','02')('10','20')('11','22')('12','21')"]) - sage: A.is_isomorphic(A_target) + sage: A.is_isomorphic(A_target) # needs sage.combinat True The labeling is correct:: sage: g = graphs.PetersenGraph() - sage: ag = g.automorphism_group() - sage: all(len(ag.orbit(e, action="OnPairs")) == 30 + sage: ag = g.automorphism_group() # needs sage.groups + sage: all(len(ag.orbit(e, action="OnPairs")) == 30 # needs sage.groups ....: for e in g.edge_iterator(labels=False)) True Empty group, correct domain:: - sage: ag = Graph({'a':['a'], 'b':[]}).automorphism_group() - sage: ag + sage: ag = Graph({'a':['a'], 'b':[]}).automorphism_group() # needs sage.groups + sage: ag # needs sage.groups Permutation Group with generators [()] - sage: sorted(ag.domain()) + sage: sorted(ag.domain()) # needs sage.groups ['a', 'b'] We can check that the subgroups are labelled correctly (:trac:`15656`):: sage: G1 = Graph(':H`ECw@HGXGAGUG`e') - sage: G = G1.automorphism_group() + sage: G = G1.automorphism_group() # needs sage.groups sage: G.subgroups() [Subgroup generated by [()] of (Permutation Group with generators [(0,7)(1,4)(2,3)(6,8)]), Subgroup generated by [(0,7)(1,4)(2,3)(6,8)] of (Permutation Group with generators [(0,7)(1,4)(2,3)(6,8)])] @@ -23128,19 +23141,19 @@ def automorphism_group(self, partition=None, verbosity=0, We check that the representations of the groups returned with ``'sage'`` and ``'bliss'`` are the same (:trac:`27571`):: - sage: G = graphs.PaleyGraph(9) - sage: a1 = G.automorphism_group(algorithm='sage') + sage: G = graphs.PaleyGraph(9) # needs sage.libs.pari + sage: a1 = G.automorphism_group(algorithm='sage') # needs sage.groups sage: V = sorted(G, reverse=True) - sage: a2 = G.automorphism_group(algorithm='sage', partition=[V]) - sage: a1.is_isomorphic(a2) + sage: a2 = G.automorphism_group(algorithm='sage', partition=[V]) # needs sage.groups + sage: a1.is_isomorphic(a2) # needs sage.groups True - sage: str(a1) == str(a2) + sage: str(a1) == str(a2) # needs sage.groups False sage: b1 = G.automorphism_group(algorithm='bliss') # optional - bliss - sage: str(a1) == str(b1) # optional - bliss + sage: str(a1) == str(b1) # optional - bliss, needs sage.groups True sage: b2 = G.automorphism_group(algorithm='bliss', partition=[V]) # optional - bliss - sage: str(a2) == str(b2) # optional - bliss + sage: str(a2) == str(b2) # optional - bliss, needs sage.groups True """ from sage.features.bliss import Bliss @@ -23387,19 +23400,19 @@ def is_hamiltonian(self, solver=None, constraint_generation=None, The Heawood Graph is known to be Hamiltonian :: sage: g = graphs.HeawoodGraph() - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # needs sage.numerical.mip True The Petergraph, though, is not :: sage: g = graphs.PetersenGraph() - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # needs sage.numerical.mip False TESTS:: sage: g = graphs.ChvatalGraph() - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # needs sage.numerical.mip True :trac:`16210`:: @@ -23407,7 +23420,7 @@ def is_hamiltonian(self, solver=None, constraint_generation=None, sage: g = graphs.CycleGraph(10) sage: g.allow_loops(True) sage: g.add_edge(0,0) - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # needs sage.numerical.mip True """ from sage.categories.sets_cat import EmptySetError @@ -23904,7 +23917,7 @@ class by some canonization function `c`. If `G` and `H` are graphs, sage: algos = ['sage'] sage: algos.append('bliss') # optional - bliss sage: S = Set([0,1,2]) - sage: for (algo, edges) in product(algos, edges_list): + sage: for (algo, edges) in product(algos, edges_list): # needs sage.combinat ....: L = cartesian_product([S] * len(edges)) ....: O = OrderedSetPartitions([0,1,2,3]) ....: P = Permutations([0,1,2,3]) @@ -24058,11 +24071,12 @@ def is_cayley(self, return_group=False, mapping=False, Graphs with loops and multiedges will have identity and repeated elements, respectively, among the generators:: + sage: # needs sage.rings.finite_rings sage: g = Graph(graphs.PaleyGraph(9), loops=True, multiedges=True) sage: g.add_edges([(u, u) for u in g]) sage: g.add_edges([(u, u+1) for u in g]) - sage: _, S = g.is_cayley(generators=True) - sage: S # random + sage: _, S = g.is_cayley(generators=True) # needs sage.groups + sage: S # random # needs sage.groups [(), (0,2,1)(a,a + 2,a + 1)(2*a,2*a + 2,2*a + 1), (0,2,1)(a,a + 2,a + 1)(2*a,2*a + 2,2*a + 1), @@ -24075,24 +24089,27 @@ def is_cayley(self, return_group=False, mapping=False, Cayley graphs can be reconstructed from the group and generating set:: - sage: g = graphs.PaleyGraph(9) - sage: _, G, S = g.is_cayley(return_group=True, generators=True) - sage: Graph(G.cayley_graph(generators=S)).is_isomorphic(g) + sage: g = graphs.PaleyGraph(9) # needs sage.rings.finite_rings + sage: _, G, S = g.is_cayley(return_group=True, generators=True) # needs sage.groups sage.rings.finite_rings + sage: Graph(G.cayley_graph(generators=S)).is_isomorphic(g) # needs sage.groups sage.rings.finite_rings True A disconnected graphs may also be a Cayley graph:: + sage: # needs sage.rings.finite_rings sage: g = graphs.PaleyGraph(9) sage: h = g.disjoint_union(g) sage: h = h.disjoint_union(h) sage: h = h.disjoint_union(g) - sage: _, G, d, S = h.is_cayley(return_group=True, mapping=True, generators=True, allow_disconnected=True) - sage: all(set(d[u] for u in h.neighbors(v)) == set(d[v]*x for x in S) for v in h) + sage: _, G, d, S = h.is_cayley(return_group=True, mapping=True, # needs sage.groups + ....: generators=True, allow_disconnected=True) + sage: all(set(d[u] for u in h.neighbors(v)) == set(d[v]*x for x in S) # needs sage.groups + ....: for v in h) True The method also works efficiently with dense simple graphs:: - sage: graphs.CompleteBipartiteGraph(50, 50).is_cayley() + sage: graphs.CompleteBipartiteGraph(50, 50).is_cayley() # needs sage.groups True TESTS:: @@ -24198,8 +24215,8 @@ def is_self_complementary(self): Every Paley graph is self-complementary:: - sage: G = graphs.PaleyGraph(9) - sage: G.is_self_complementary() + sage: G = graphs.PaleyGraph(9) # needs sage.libs.pari + sage: G.is_self_complementary() # needs sage.libs.pari True TESTS: @@ -24327,7 +24344,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) # needs sage.modules + sage: G.katz_matrix(1/20) # needs sage.modules sage.rings.number_field [1/198 5/99 1/198 5/99] [ 5/99 1/198 5/99 1/198] [1/198 5/99 1/198 5/99] @@ -24336,7 +24353,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) # needs sage.modules + sage: G.katz_matrix(1/20, True) # needs sage.modules sage.rings.number_field [ 0 0 1/198 0] [ 0 0 0 1/198] [1/198 0 0 0] @@ -24348,7 +24365,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) # needs sage.modules + sage: H.katz_matrix(1/10) # needs sage.modules sage.rings.number_field [ 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] @@ -24364,7 +24381,7 @@ def katz_matrix(self, alpha, nonedgesonly=False, vertices=None): TESTS:: - sage: # needs sage.modules + sage: # needs sage.modules sage.rings.number_field sage: (graphs.CompleteGraph(4)).katz_matrix(1/4) [3/5 4/5 4/5 4/5] [4/5 3/5 4/5 4/5] @@ -24683,7 +24700,7 @@ def symmetric_edge_polytope(self, backend=None): ....: break ....: else: ....: polys.append(P) - sage: len(polys) + sage: len(polys) # needs sage.geometry.polyhedron 25 A non-trivial example of two graphs with isomorphic SEPs:: From 0d94e55c356a8d533ff855a67ab99e020d4edc43 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 2 Aug 2023 15:35:46 -0700 Subject: [PATCH 05/10] ./sage -fixdoctests --only-tags src/sage/graphs --- src/sage/graphs/base/boost_graph.pyx | 6 +- src/sage/graphs/base/c_graph.pyx | 30 +- .../graphs/base/static_sparse_backend.pyx | 17 +- src/sage/graphs/base/static_sparse_graph.pyx | 18 +- src/sage/graphs/bipartite_graph.py | 195 +++-- src/sage/graphs/bliss.pyx | 109 +-- src/sage/graphs/centrality.pyx | 35 +- src/sage/graphs/cliquer.pyx | 4 +- src/sage/graphs/comparability.pyx | 26 +- src/sage/graphs/connectivity.pyx | 80 +- src/sage/graphs/digraph.py | 187 ++-- src/sage/graphs/digraph_generators.py | 118 +-- src/sage/graphs/distances_all_pairs.pyx | 49 +- src/sage/graphs/domination.py | 44 +- src/sage/graphs/dot2tex_utils.py | 6 +- src/sage/graphs/edge_connectivity.pyx | 19 +- src/sage/graphs/generators/basic.py | 147 ++-- src/sage/graphs/generators/chessboard.py | 2 +- .../graphs/generators/classical_geometries.py | 30 +- src/sage/graphs/generators/degree_sequence.py | 49 +- .../graphs/generators/distance_regular.pyx | 255 +++--- src/sage/graphs/generators/families.py | 315 +++---- src/sage/graphs/generators/intersection.py | 37 +- src/sage/graphs/generators/platonic_solids.py | 36 +- src/sage/graphs/generators/random.py | 185 ++-- src/sage/graphs/generators/smallgraphs.py | 12 +- src/sage/graphs/generic_graph.py | 7 +- src/sage/graphs/generic_graph_pyx.pyx | 36 +- src/sage/graphs/graph.py | 819 +++++++++--------- src/sage/graphs/graph_coloring.pyx | 122 +-- src/sage/graphs/graph_database.py | 2 +- .../graphs/graph_decompositions/bandwidth.pyx | 4 +- .../graphs/graph_decompositions/cutwidth.pyx | 20 +- .../graph_decompositions/fast_digraph.pyx | 10 +- .../graph_decompositions/graph_products.pyx | 4 +- .../modular_decomposition.py | 2 +- .../graphs/graph_decompositions/tdlib.pyx | 11 +- .../vertex_separation.pyx | 52 +- src/sage/graphs/graph_generators.py | 40 +- src/sage/graphs/graph_generators_pyx.pyx | 4 +- src/sage/graphs/graph_input.py | 142 +-- src/sage/graphs/graph_latex.py | 10 +- src/sage/graphs/graph_list.py | 16 +- src/sage/graphs/graph_plot_js.py | 17 +- src/sage/graphs/hypergraph_generators.py | 19 +- src/sage/graphs/independent_sets.pyx | 2 +- .../graphs/isoperimetric_inequalities.pyx | 4 +- src/sage/graphs/line_graph.pyx | 21 +- src/sage/graphs/matchpoly.pyx | 6 +- src/sage/graphs/partial_cube.py | 10 +- src/sage/graphs/path_enumeration.pyx | 22 +- src/sage/graphs/planarity.pyx | 13 +- src/sage/graphs/schnyder.py | 2 +- src/sage/graphs/spanning_tree.pyx | 37 +- src/sage/graphs/strongly_regular_db.pyx | 328 +++---- src/sage/graphs/traversals.pyx | 46 +- src/sage/graphs/tutte_polynomial.py | 6 +- src/sage/graphs/views.pyx | 6 +- 58 files changed, 1980 insertions(+), 1871 deletions(-) diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index d6508f172f8..ff222837117 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)) # optional - networkx + sage: bandwidth_heuristics(graphs.RandomGNM(10,0)) # needs 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) # optional - networkx - sage: diameter_DHV(G) == G.diameter(algorithm = 'Dijkstra_Boost') # optional - networkx + sage: G = graphs.RandomBarabasiAlbert(17,6) # needs networkx + sage: diameter_DHV(G) == G.diameter(algorithm = 'Dijkstra_Boost') # needs 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 a4f2efd6060..0f5c09aa12f 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) # 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 + sage: R. = GF(3**3) # needs sage.rings.finite_rings + sage: S. = R[] # needs sage.rings.finite_rings + sage: G.add_vertex(a**2) # needs sage.rings.finite_rings + sage: G.add_vertex(x) # needs sage.rings.finite_rings + sage: G.vertices(sort=True) # needs 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]) # optional - sage.combinat sage.groups - sage: G = W.cayley_graph() # optional - sage.combinat sage.groups - sage: Graph(G).degree() # optional - sage.combinat sage.groups + sage: W = WeylGroup(["A",1]) # needs sage.combinat sage.groups + sage: G = W.cayley_graph() # needs sage.combinat sage.groups + sage: Graph(G).degree() # needs 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() # optional - sage.modules - sage: H = P._hasse_diagram # optional - sage.modules - sage: H._backend.is_connected() # optional - sage.modules + sage: P = posets.PentagonPoset() # needs sage.modules + sage: H = P._hasse_diagram # needs sage.modules + sage: H._backend.is_connected() # needs sage.modules True """ cdef int v_int @@ -4548,7 +4548,7 @@ cdef class CGraphBackend(GenericGraphBackend): At first, the following graph is acyclic:: sage: D = DiGraph({ 0:[1,2,3], 4:[2,5], 1:[8], 2:[7], 3:[7], 5:[6,7], 7:[8], 6:[9], 8:[10], 9:[10] }) - sage: D.plot(layout='circular').show() # optional - sage.plot + sage: D.plot(layout='circular').show() # needs sage.plot sage: D.is_directed_acyclic() True @@ -4589,9 +4589,9 @@ cdef class CGraphBackend(GenericGraphBackend): TESTS:: - 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 + sage: m = Matrix(3,[0, 1, 1, 0, 0, 0, 0, 1, 0]) # needs sage.modules + sage: g = DiGraph(m) # needs sage.modules + sage: g.is_directed_acyclic(certificate=True) # needs 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 a8de583d4db..2eecc1a69d0 100644 --- a/src/sage/graphs/base/static_sparse_backend.pyx +++ b/src/sage/graphs/base/static_sparse_backend.pyx @@ -446,17 +446,18 @@ cdef class StaticSparseBackend(CGraphBackend): :: - 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 + sage: # needs sage.combinat + 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] ('000', '000', '0') - sage: sorted(gi.edges_incident('111')) # optional - sage.combinat + sage: sorted(gi.edges_incident('111')) [('111', '110', '0'), ('111', '111', '1'), ('111', '112', '2'), ('111', '113', '3')] - sage: set(g.edges(sort=False)) == set(gi.edges(sort=False)) # optional - sage.combinat + sage: set(g.edges(sort=False)) == set(gi.edges(sort=False)) # needs sage.combinat True :: @@ -671,10 +672,10 @@ cdef class StaticSparseBackend(CGraphBackend): :: sage: from sage.graphs.base.static_sparse_backend import StaticSparseBackend - sage: g = StaticSparseBackend(digraphs.DeBruijn(3, 2)) # optional - sage.combinat - sage: g.has_edge('00', '01', '1') # optional - sage.combinat + sage: g = StaticSparseBackend(digraphs.DeBruijn(3, 2)) # needs sage.combinat + sage: g.has_edge('00', '01', '1') # needs sage.combinat True - sage: g.has_edge('00', '01', '0') # optional - sage.combinat + sage: g.has_edge('00', '01', '0') # needs sage.combinat False """ try: diff --git a/src/sage/graphs/base/static_sparse_graph.pyx b/src/sage/graphs/base/static_sparse_graph.pyx index cfaff95ccde..6fd78510c94 100644 --- a/src/sage/graphs/base/static_sparse_graph.pyx +++ b/src/sage/graphs/base/static_sparse_graph.pyx @@ -731,8 +731,8 @@ def tarjan_strongly_connected_components(G): Checking against NetworkX:: - sage: import networkx # optional - networkx - sage: for i in range(10): # long time # optional - networkx + sage: import networkx # needs networkx + sage: for i in range(10): # long time # needs networkx ....: g = digraphs.RandomDirectedGNP(100,.05) ....: h = g.networkx_graph() ....: scc1 = g.strongly_connected_components() @@ -1023,8 +1023,8 @@ def spectral_radius(G, prec=1e-10): sage: G = Graph([(0,1),(0,2),(1,2),(1,3),(2,4),(3,4)]) sage: e_min, e_max = spectral_radius(G, 1e-14) - sage: e = max(G.adjacency_matrix().charpoly().roots(AA, multiplicities=False)) - sage: e_min < e < e_max + sage: e = max(G.adjacency_matrix().charpoly().roots(AA, multiplicities=False)) # needs sage.modules + sage: e_min < e < e_max # needs sage.modules True sage: G.spectral_radius() # abs tol 1e-9 @@ -1037,10 +1037,10 @@ def spectral_radius(G, prec=1e-10): sage: G.add_edge(200,0) sage: G.add_edge(1,0) sage: e_min, e_max = spectral_radius(G, 0.00001) - sage: p = G.adjacency_matrix(sparse=True).charpoly() - sage: p + sage: p = G.adjacency_matrix(sparse=True).charpoly() # needs sage.modules + sage: p # needs sage.modules x^201 - x^199 - 1 - sage: r = p.roots(AA, multiplicities=False)[0] + sage: r = p.roots(AA, multiplicities=False)[0] # needs sage.modules sage: e_min < r < e_max True @@ -1060,7 +1060,7 @@ def spectral_radius(G, prec=1e-10): sage: G.add_edges([(0,0),(0,0),(0,1),(1,0)]) sage: spectral_radius(G, 1e-14) # abs tol 1e-14 (2.414213562373094, 2.414213562373095) - sage: max(G.adjacency_matrix().eigenvalues(AA)) + sage: max(G.adjacency_matrix().eigenvalues(AA)) # needs sage.modules 2.414213562373095? Some bipartite graphs:: @@ -1091,7 +1091,7 @@ def spectral_radius(G, prec=1e-10): ... ValueError: precision (=1.00000000000000e-20) is too small - sage: for _ in range(100): + sage: for _ in range(100): # needs sage.modules ....: G = digraphs.RandomDirectedGNM(10,35) ....: if not G.is_strongly_connected(): ....: continue diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index 635d5554329..0aaae8e1551 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -161,7 +161,7 @@ class BipartiteGraph(Graph): sage: B = BipartiteGraph(P, partition, check=False) sage: B.left {0, 1, 2, 3, 4} - sage: B.show() # optional - sage.plot + sage: B.show() # needs sage.plot :: @@ -198,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), # optional - sage.modules + sage: M = Matrix([(1,1,1,0,0,0,0), (1,0,0,1,1,0,0), # needs sage.modules ....: (0,1,0,1,0,1,0), (1,1,0,1,0,0,1)]) - sage: M # optional - sage.modules + sage: M # needs 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 # optional - sage.modules + sage: H = BipartiteGraph(M); H # needs sage.modules Bipartite graph on 11 vertices - sage: H.edges(sort=True) # optional - sage.modules + sage: H.edges(sort=True) # needs sage.modules [(0, 7, None), (0, 8, None), (0, 10, None), @@ -224,9 +224,9 @@ class BipartiteGraph(Graph): :: - 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 + sage: M = Matrix([(1, 1, 2, 0, 0), (0, 2, 1, 1, 1), (0, 1, 2, 1, 1)]) # needs sage.modules + sage: B = BipartiteGraph(M, multiedges=True, sparse=True) # needs sage.modules + sage: B.edges(sort=True) # needs sage.modules [(0, 5, None), (1, 5, None), (1, 6, None), @@ -244,13 +244,13 @@ class BipartiteGraph(Graph): :: - 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 + sage: F. = GF(4) # needs sage.modules sage.rings.finite_rings + sage: MS = MatrixSpace(F, 2, 3) # needs sage.modules sage.rings.finite_rings + sage: M = MS.matrix([[0, 1, a + 1], [a, 1, 1]]) # needs sage.modules sage.rings.finite_rings + sage: B = BipartiteGraph(M, weighted=True, sparse=True) # needs sage.modules sage.rings.finite_rings + sage: B.edges(sort=True) # needs 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() # optional - sage.modules sage.rings.finite_rings + sage: B.weighted() # needs sage.modules sage.rings.finite_rings True #. From an alist file:: @@ -264,7 +264,7 @@ class BipartiteGraph(Graph): ....: 1 2 4 7 \n") ....: f.flush() ....: B = BipartiteGraph(f.name) - sage: B.is_isomorphic(H) # optional - sage.modules + sage: B.is_isomorphic(H) # needs sage.modules True #. From a ``graph6`` string:: @@ -307,14 +307,14 @@ class BipartiteGraph(Graph): sage: B = BipartiteGraph('F?^T_\n', partition=[[0, 1, 2], [3, 4, 5, 6]], check=False) sage: B.left {0, 1, 2} - sage: B.show() # optional - sage.plot + sage: B.show() # needs sage.plot #. From a NetworkX bipartite graph:: - sage: import networkx # optional - networkx - sage: G = graphs.OctahedralGraph() # optional - networkx - sage: N = networkx.make_clique_bipartite(G.networkx_graph()) # optional - networkx - sage: B = BipartiteGraph(N) # optional - networkx + sage: import networkx # needs networkx + sage: G = graphs.OctahedralGraph() # needs networkx + sage: N = networkx.make_clique_bipartite(G.networkx_graph()) # needs networkx + sage: B = BipartiteGraph(N) # needs networkx TESTS: @@ -328,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])) # optional - sage.modules - sage: a # optional - sage.modules + sage: a = BipartiteGraph(matrix(2, 2, [1, 0, 1, 0])) # needs sage.modules + sage: a # needs sage.modules Bipartite graph on 4 vertices - sage: a.vertices(sort=True) # optional - sage.modules + sage: a.vertices(sort=True) # needs sage.modules [0, 1, 2, 3] - sage: g = BipartiteGraph(matrix(4, 4, [1] * 4 + [0] * 12)) # optional - sage.modules - sage: g.vertices(sort=True) # optional - sage.modules + sage: g = BipartiteGraph(matrix(4, 4, [1] * 4 + [0] * 12)) # needs sage.modules + sage: g.vertices(sort=True) # needs sage.modules [0, 1, 2, 3, 4, 5, 6, 7] - sage: sorted(g.left.union(g.right)) # optional - sage.modules + sage: sorted(g.left.union(g.right)) # needs sage.modules [0, 1, 2, 3, 4, 5, 6, 7] Make sure that loops are not allowed (:trac:`23275`):: @@ -1291,10 +1291,10 @@ def is_bipartite(self, certificate=False): EXAMPLES:: - sage: g = BipartiteGraph(graphs.RandomBipartite(3, 3, .5)) # optional - numpy - sage: g.is_bipartite() # optional - numpy + sage: g = BipartiteGraph(graphs.RandomBipartite(3, 3, .5)) # needs numpy + sage: g.is_bipartite() # needs numpy True - sage: g.is_bipartite(certificate=True) # random # optional - numpy + sage: g.is_bipartite(certificate=True) # random # needs numpy (True, {(0, 0): 0, (0, 1): 0, (0, 2): 0, (1, 0): 1, (1, 1): 1, (1, 2): 1}) TESTS:: @@ -1466,7 +1466,7 @@ def plot(self, *args, **kwds): EXAMPLES:: sage: B = BipartiteGraph(graphs.CycleGraph(20)) - sage: B.plot() # optional - sage.plot + sage: B.plot() # needs sage.plot Graphics object consisting of 41 graphics primitives """ if "pos" not in kwds: @@ -1511,14 +1511,16 @@ def matching_polynomial(self, algorithm="Godsil", name=None): sage: x = polygen(QQ) sage: g = BipartiteGraph(graphs.CompleteBipartiteGraph(16, 16)) - sage: bool(factorial(16) * laguerre(16, x^2) == g.matching_polynomial(algorithm='rook')) # optional - sage.symbolic + sage: bool(factorial(16) * laguerre(16, x^2) # needs sage.symbolic + ....: == g.matching_polynomial(algorithm='rook')) True Compute the matching polynomial of a line with `60` vertices:: - sage: from sage.functions.orthogonal_polys import chebyshev_U # optional - sage.symbolic + sage: from sage.functions.orthogonal_polys import chebyshev_U # needs sage.symbolic sage: g = next(graphs.trees(60)) - sage: chebyshev_U(60, x/2) == BipartiteGraph(g).matching_polynomial(algorithm='rook') # optional - sage.symbolic + sage: (chebyshev_U(60, x/2) # needs sage.symbolic + ....: == BipartiteGraph(g).matching_polynomial(algorithm='rook')) True The matching polynomial of a tree is equal to its characteristic @@ -1627,7 +1629,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) # optional - sage.modules + sage: B.matching_polynomial(algorithm='rook')(0) # needs sage.modules 24 TESTS:: @@ -1804,26 +1806,26 @@ def save_afile(self, fname): EXAMPLES:: - sage: M = Matrix([(1,1,1,0,0,0,0), (1,0,0,1,1,0,0), # optional - sage.modules + sage: M = Matrix([(1,1,1,0,0,0,0), (1,0,0,1,1,0,0), # needs sage.modules ....: (0,1,0,1,0,1,0), (1,1,0,1,0,0,1)]) - sage: M # optional - sage.modules + sage: M # needs 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) # optional - sage.modules - sage: import tempfile # optional - sage.modules - sage: with tempfile.NamedTemporaryFile() as f: # optional - sage.modules + sage: b = BipartiteGraph(M) # needs sage.modules + sage: import tempfile # needs sage.modules + sage: with tempfile.NamedTemporaryFile() as f: # needs sage.modules ....: b.save_afile(f.name) ....: b2 = BipartiteGraph(f.name) - sage: b.is_isomorphic(b2) # optional - sage.modules + sage: b.is_isomorphic(b2) # needs sage.modules True TESTS:: sage: import tempfile sage: f = tempfile.NamedTemporaryFile() - sage: for order in range(3, 13, 3): # optional - sage.combinat + sage: for order in range(3, 13, 3): # needs 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))) @@ -1921,78 +1923,77 @@ 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), # optional - sage.modules + sage: M = Matrix([(1,1,1,0,0,0,0), (1,0,0,1,1,0,0), # needs sage.modules ....: (0,1,0,1,0,1,0), (1,1,0,1,0,0,1)]) - sage: B = BipartiteGraph(M) # optional - sage.modules - sage: N = B.reduced_adjacency_matrix() # optional - sage.modules - sage: N # optional - sage.modules + sage: B = BipartiteGraph(M) # needs sage.modules + sage: N = B.reduced_adjacency_matrix(); N # needs 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 # optional - sage.modules + sage: N == M # needs sage.modules True - sage: N[0,0].parent() # optional - sage.modules + sage: N[0,0].parent() # needs sage.modules Integer Ring - sage: N2 = B.reduced_adjacency_matrix(base_ring=RDF); N2 # optional - sage.modules + sage: N2 = B.reduced_adjacency_matrix(base_ring=RDF); N2 # needs 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() # optional - sage.modules + sage: N2[0, 0].parent() # needs 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)]) # 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 + sage: M = Matrix([(1,1,2,0,0), (0,2,1,1,1), (0,1,2,1,1)]) # needs sage.modules + sage: B = BipartiteGraph(M, multiedges=True, sparse=True) # needs sage.modules + sage: N = B.reduced_adjacency_matrix() # needs sage.modules + sage: N == M # needs sage.modules True - sage: N[0,0].parent() # optional - sage.modules + sage: N[0,0].parent() # needs sage.modules Integer Ring - sage: N2 = B.reduced_adjacency_matrix(base_ring=RDF) # optional - sage.modules - sage: N2[0, 0].parent() # optional - sage.modules + sage: N2 = B.reduced_adjacency_matrix(base_ring=RDF) # needs sage.modules + sage: N2[0, 0].parent() # needs 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) # 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 + sage: F. = GF(4) # needs sage.modules sage.rings.finite_rings + sage: MS = MatrixSpace(F, 2, 3) # needs sage.modules sage.rings.finite_rings + sage: M = MS.matrix([[0, 1, a+1], [a, 1, 1]]) # needs sage.modules sage.rings.finite_rings + sage: B = BipartiteGraph(M, weighted=True, sparse=True) # needs sage.modules sage.rings.finite_rings + sage: N = B.reduced_adjacency_matrix(sparse=False) # needs sage.modules sage.rings.finite_rings + sage: N == M # needs sage.modules sage.rings.finite_rings True - sage: N[0,0].parent() # optional - sage.modules sage.rings.finite_rings + sage: N[0,0].parent() # needs sage.modules sage.rings.finite_rings Finite Field in a of size 2^2 - 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 + sage: N2 = B.reduced_adjacency_matrix(base_ring=F) # needs sage.modules sage.rings.finite_rings + sage: N2[0, 0].parent() # needs sage.modules sage.rings.finite_rings Finite Field in a of size 2^2 TESTS:: sage: B = BipartiteGraph() - sage: B.reduced_adjacency_matrix() # optional - sage.modules + sage: B.reduced_adjacency_matrix() # needs sage.modules [] - sage: M = Matrix([[0,0], [0,0]]) # optional - sage.modules - sage: BipartiteGraph(M).reduced_adjacency_matrix() == M # optional - sage.modules + sage: M = Matrix([[0,0], [0,0]]) # needs sage.modules + sage: BipartiteGraph(M).reduced_adjacency_matrix() == M # needs sage.modules True - 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 + sage: M = Matrix([[10,2/3], [0,0]]) # needs sage.modules + sage: B = BipartiteGraph(M, weighted=True, sparse=True) # needs sage.modules + sage: M == B.reduced_adjacency_matrix() # needs 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) # 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 + sage: F. = GF(4) # needs sage.modules sage.rings.finite_rings + sage: MS = MatrixSpace(F, 2, 3) # needs sage.modules sage.rings.finite_rings + sage: M = MS.matrix([[0, 1, a+1], [a, 1, 1]]) # needs sage.modules sage.rings.finite_rings + sage: B = BipartiteGraph(M, weighted=True, sparse=True) # needs sage.modules sage.rings.finite_rings + sage: B.reduced_adjacency_matrix(base_ring=RDF) # needs 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' @@ -2098,14 +2099,14 @@ class :class:`MixedIntegerLinearProgram Maximum matching in a cycle graph:: sage: G = BipartiteGraph(graphs.CycleGraph(10)) - sage: G.matching() # optional - networkx + sage: G.matching() # needs 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 Eppstein:: sage: G = BipartiteGraph(graphs.CompleteBipartiteGraph(4,5)) - sage: G.matching(algorithm="Eppstein", value_only=True) + sage: G.matching(algorithm="Eppstein", value_only=True) # needs networkx 4 TESTS: @@ -2123,11 +2124,11 @@ class :class:`MixedIntegerLinearProgram sage: G = graphs.CycleGraph(4) sage: B = BipartiteGraph([(u,v,2) for u,v in G.edges(sort=True, labels=0)]) - sage: sorted(B.matching(use_edge_labels=True)) + sage: sorted(B.matching(use_edge_labels=True)) # needs networkx [(0, 3, 2), (1, 2, 2)] - sage: B.matching(use_edge_labels=True, value_only=True) # optional - networkx + sage: B.matching(use_edge_labels=True, value_only=True) # needs networkx 4 - sage: B.matching(use_edge_labels=True, value_only=True, algorithm='Edmonds') + sage: B.matching(use_edge_labels=True, value_only=True, algorithm='Edmonds') # needs networkx 4 sage: B.matching(use_edge_labels=True, value_only=True, algorithm='LP') 4 @@ -2139,11 +2140,13 @@ 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') # optional - networkx + sage: B.matching(use_edge_labels=False, value_only=True, # needs networkx + ....: algorithm='Hopcroft-Karp') 2 - sage: B.matching(use_edge_labels=False, value_only=True, algorithm='Eppstein') # optional - networkx + sage: B.matching(use_edge_labels=False, value_only=True, # needs networkx + ....: algorithm='Eppstein') 2 - sage: B.matching(use_edge_labels=False, value_only=True, algorithm='Edmonds') + sage: B.matching(use_edge_labels=False, value_only=True, algorithm='Edmonds') # needs networkx 2 sage: B.matching(use_edge_labels=False, value_only=True, algorithm='LP') 2 @@ -2154,23 +2157,23 @@ class :class:`MixedIntegerLinearProgram sage: for e in G.edges(sort=True): ....: G.set_edge_label(e[0], e[1], int(e[0]) + int(e[1])) sage: G.allow_multiple_edges(True) - sage: G.matching(use_edge_labels=True, value_only=True) + sage: G.matching(use_edge_labels=True, value_only=True) # needs networkx 444 Empty bipartite graph and bipartite graphs without edges:: sage: B = BipartiteGraph() sage: algorithms = ["Hopcroft-Karp", "Eppstein", "Edmonds", "LP"] - sage: not any(B.matching(algorithm=algo) for algo in algorithms) + sage: not any(B.matching(algorithm=algo) for algo in algorithms) # needs networkx True - sage: all(B.matching(algorithm=algo, value_only=True) == 0 for algo in algorithms) + sage: all(B.matching(algorithm=algo, value_only=True) == 0 for algo in algorithms) # needs networkx True sage: B.add_vertex(1, left=True) sage: B.add_vertex(2, left=True) sage: B.add_vertex(3, right=True) - sage: not any(B.matching(algorithm=algo) for algo in algorithms) + sage: not any(B.matching(algorithm=algo) for algo in algorithms) # needs networkx True - sage: all(B.matching(algorithm=algo, value_only=True) == 0 for algo in algorithms) + sage: all(B.matching(algorithm=algo, value_only=True) == 0 for algo in algorithms) # needs networkx True """ if algorithm is None: @@ -2285,17 +2288,17 @@ def vertex_cover(self, algorithm="Konig", value_only=False, On the Cycle Graph:: sage: B = BipartiteGraph(graphs.CycleGraph(6)) - sage: len(B.vertex_cover()) # optional - networkx + sage: len(B.vertex_cover()) # needs networkx 3 - sage: B.vertex_cover(value_only=True) # optional - networkx + sage: B.vertex_cover(value_only=True) # needs networkx 3 The two algorithms should return the same result:: - sage: g = BipartiteGraph(graphs.RandomBipartite(10, 10, .5)) - sage: vc1 = g.vertex_cover(algorithm="Konig") - sage: vc2 = g.vertex_cover(algorithm="Cliquer") - sage: len(vc1) == len(vc2) + sage: g = BipartiteGraph(graphs.RandomBipartite(10, 10, .5)) # needs numpy + sage: vc1 = g.vertex_cover(algorithm="Konig") # needs numpy + sage: vc2 = g.vertex_cover(algorithm="Cliquer") # needs numpy + sage: len(vc1) == len(vc2) # needs numpy True TESTS: @@ -2303,7 +2306,7 @@ def vertex_cover(self, algorithm="Konig", value_only=False, Giving a non connected bipartite graph:: sage: B = BipartiteGraph(graphs.CycleGraph(4) * 2) - sage: len(B.vertex_cover()) + sage: len(B.vertex_cover()) # needs networkx 4 Empty bipartite graph and bipartite graphs without edges:: diff --git a/src/sage/graphs/bliss.pyx b/src/sage/graphs/bliss.pyx index d8c50f220e3..5911778953c 100644 --- a/src/sage/graphs/bliss.pyx +++ b/src/sage/graphs/bliss.pyx @@ -437,12 +437,13 @@ cpdef canonical_form(G, partition=None, return_graph=False, use_edge_labels=True sage: g.is_isomorphic(canonical_form(g, return_graph=True)) # optional - bliss True - sage: g1 = graphs.RandomGNP(100, .4) # optional - bliss - sage: r = Permutations(range(100)).random_element() # optional - bliss - sage: g2 = Graph([(r[u],r[v]) for u,v in g1.edges(sort=True, labels=False)]) # optional - bliss - sage: g1 = canonical_form(g1, return_graph=True) # optional - bliss - sage: g2 = canonical_form(g2, return_graph=True) # optional - bliss - sage: g2 == g2 # optional - bliss + sage: # optional - bliss + sage: g1 = graphs.RandomGNP(100, .4) + sage: r = Permutations(range(100)).random_element() + sage: g2 = Graph([(r[u],r[v]) for u,v in g1.edges(sort=True, labels=False)]) + sage: g1 = canonical_form(g1, return_graph=True) + sage: g2 = canonical_form(g2, return_graph=True) + sage: g2 == g2 True sage: g = Graph({1: [2]}) @@ -476,11 +477,12 @@ 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')]) # 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 + sage: # needs sage.modules + 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 True Check that :trac:`32395` is fixed:: @@ -677,11 +679,12 @@ cpdef automorphism_group(G, partition=None, use_edge_labels=True): Computing the automorphism group of a graph or digraph:: - sage: G = graphs.CompleteMultipartiteGraph([1, 1, 1, 2]) # optional - bliss - sage: automorphism_group(G).cardinality() # optional - bliss + sage: # optional - bliss + sage: G = graphs.CompleteMultipartiteGraph([1, 1, 1, 2]) + sage: automorphism_group(G).cardinality() 12 - sage: D = DiGraph(G.edges(sort=True)) # optional - bliss - sage: automorphism_group(D).cardinality() # optional - bliss + sage: D = DiGraph(G.edges(sort=True)) + sage: automorphism_group(D).cardinality() 2 Observe that the order 12 is given by permuting the first three vertices, or the last two @@ -690,12 +693,13 @@ cpdef automorphism_group(G, partition=None, use_edge_labels=True): Partitioning the vertices into classes:: - sage: G = graphs.CompleteMultipartiteGraph([3, 2]) # optional - bliss - sage: automorphism_group(G).cardinality() # optional - bliss + sage: # optional - bliss + sage: G = graphs.CompleteMultipartiteGraph([3, 2]) + sage: automorphism_group(G).cardinality() 12 - sage: automorphism_group(G,partition=[[0],[1],[2],[3,4]]).cardinality() # optional - bliss + sage: automorphism_group(G,partition=[[0],[1],[2],[3,4]]).cardinality() 2 - sage: automorphism_group(G,partition=[[0],[1,2],[3,4]]).cardinality() # optional - bliss + sage: automorphism_group(G,partition=[[0],[1,2],[3,4]]).cardinality() 4 sage: automorphism_group(G,partition=[[1,2],[0,3],[4]]).cardinality() # optional - bliss @@ -724,10 +728,11 @@ cpdef automorphism_group(G, partition=None, use_edge_labels=True): sage: automorphism_group(G).is_isomorphic(G.automorphism_group()) # optional - bliss True - sage: G = graphs.HeawoodGraph() # optional - bliss - sage: p = G.bipartite_sets() # optional - bliss - sage: A = G.automorphism_group(partition=[list(p[0]), list(p[1])]) # optional - bliss - sage: automorphism_group(G, partition=p).is_isomorphic(A) # optional - bliss + sage: # optional - bliss + sage: G = graphs.HeawoodGraph() + sage: p = G.bipartite_sets() + sage: A = G.automorphism_group(partition=[list(p[0]), list(p[1])]) + sage: automorphism_group(G, partition=p).is_isomorphic(A) True sage: G = graphs.CompleteMultipartiteGraph([5,7,11]) @@ -735,55 +740,59 @@ cpdef automorphism_group(G, partition=None, use_edge_labels=True): sage: B.cardinality() == prod(factorial(n) for n in [5,7,11]) # optional - bliss True - sage: G = Graph(graphs.CompleteMultipartiteGraph([8,8,8,5]),sparse=True)# optional - bliss - sage: for i,j in G.edges(labels=False, sort=False): # optional - bliss + sage: # optional - bliss + sage: G = Graph(graphs.CompleteMultipartiteGraph([8,8,8,5]),sparse=True) + sage: for i,j in G.edges(labels=False, sort=False): ....: if 0 <= i < 3: ....: G.set_edge_label(i, j, "A") ....: if 3 <= i < 6: ....: G.set_edge_label(i, j, "B") ....: if 6 <= i < 8: ....: G.set_edge_label(i, j, "C") - sage: automorphism_group(G).cardinality() == prod( factorial(n) for n in [3,3,2,8,8,5,2] ) # optional - bliss + sage: automorphism_group(G).cardinality() == prod( factorial(n) for n in [3,3,2,8,8,5,2] ) True - sage: automorphism_group(G, use_edge_labels=False).cardinality() == prod( factorial(n) for n in [8,8,8,5,3] ) # optional - bliss + sage: automorphism_group(G, use_edge_labels=False).cardinality() == prod( factorial(n) for n in [8,8,8,5,3] ) True - sage: automorphism_group(G,[[0 .. 7],[8 .. 11],[12 .. 28]]).cardinality() == prod( factorial(n) for n in [3,3,2,4,4,8,5] ) # optional - bliss + sage: automorphism_group(G,[[0 .. 7],[8 .. 11],[12 .. 28]]).cardinality() == prod( factorial(n) for n in [3,3,2,4,4,8,5] ) True - sage: G = Graph() # optional - bliss - sage: G.add_edges((i,j,"A") for i in range(0, 2) for j in range(14,20)) # optional - bliss - sage: G.add_edges((i,j,"B") for i in range(2, 5) for j in range(14,20)) # optional - bliss - sage: G.add_edges((i,j,"C") for i in range(5, 9) for j in range(14,20)) # optional - bliss - sage: G.add_edges((i,j,"D") for i in range(9,14) for j in range(14,20)) # optional - bliss - sage: A = automorphism_group(G) # optional - bliss - sage: print(A.gens()) # random, optional - bliss + sage: # optional - bliss + sage: G = Graph() + sage: G.add_edges((i,j,"A") for i in range(0, 2) for j in range(14,20)) + sage: G.add_edges((i,j,"B") for i in range(2, 5) for j in range(14,20)) + sage: G.add_edges((i,j,"C") for i in range(5, 9) for j in range(14,20)) + sage: G.add_edges((i,j,"D") for i in range(9,14) for j in range(14,20)) + sage: A = automorphism_group(G) + sage: print(A.gens()) # random [(9,13), (18,19), (17,18), (16,17), (15,16), (14,15), (12,9), (11,12), (10,11), (7,8), (6,7), (5,6), (3,4), (2,3), (0,1)] - sage: A.cardinality() == prod(factorial(n) for n in [2,3,4,5,6]) # optional - bliss + sage: A.cardinality() == prod(factorial(n) for n in [2,3,4,5,6]) True sage: alpha = "abcdefghijklmnopqrstuvwxyz" - sage: G = Graph() # optional - bliss - sage: G.add_edges((alpha[i],alpha[j],"A") for i in range(0, 2) for j in range(14,20)) # optional - bliss - sage: G.add_edges((alpha[i],alpha[j],"B") for i in range(2, 5) for j in range(14,20)) # optional - bliss - sage: G.add_edges((alpha[i],alpha[j],"C") for i in range(5, 9) for j in range(14,20)) # optional - bliss - sage: G.add_edges((alpha[i],alpha[j],"D") for i in range(9,14) for j in range(14,20)) # optional - bliss - sage: A = automorphism_group(G) # optional - bliss - sage: print(A.gens()) # random, optional - bliss + sage: # optional - bliss + sage: G = Graph() + sage: G.add_edges((alpha[i],alpha[j],"A") for i in range(0, 2) for j in range(14,20)) + sage: G.add_edges((alpha[i],alpha[j],"B") for i in range(2, 5) for j in range(14,20)) + sage: G.add_edges((alpha[i],alpha[j],"C") for i in range(5, 9) for j in range(14,20)) + sage: G.add_edges((alpha[i],alpha[j],"D") for i in range(9,14) for j in range(14,20)) + sage: A = automorphism_group(G) + sage: print(A.gens()) [('r','t'), ('s','r'), ('p','s'), ('q','p'), ('o','q'), ('l','n'), ('m','l'), ('j','m'), ('k','j'), ('i','h'), ('f','i'), ('g','f'), ('e','d'), ('c','e'), ('a','b')] - sage: A.cardinality() == prod(factorial(n) for n in [2,3,4,5,6]) # optional - bliss + sage: A.cardinality() == prod(factorial(n) for n in [2,3,4,5,6]) True - sage: gg = graphs.CompleteGraph(5) # optional - bliss - sage: gg.allow_loops(True) # optional - bliss - sage: gg.add_edge(0,0) # optional - bliss - sage: gg.add_edge(1,1) # optional - bliss - sage: automorphism_group(gg).cardinality() # optional - bliss + sage: # optional - bliss + sage: gg = graphs.CompleteGraph(5) + sage: gg.allow_loops(True) + sage: gg.add_edge(0,0) + sage: gg.add_edge(1,1) + sage: automorphism_group(gg).cardinality() 12 - sage: automorphism_group(gg,[[0],[1,2,3,4]]).cardinality() # optional - bliss + sage: automorphism_group(gg,[[0],[1,2,3,4]]).cardinality() 6 """ # We need this to convert the numbers from to diff --git a/src/sage/graphs/centrality.pyx b/src/sage/graphs/centrality.pyx index 9de214115f9..fa659c13d94 100755 --- a/src/sage/graphs/centrality.pyx +++ b/src/sage/graphs/centrality.pyx @@ -99,11 +99,12 @@ 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: # needs networkx + sage: import networkx + sage: g = graphs.RandomGNP(100, .2) + sage: nw = networkx.betweenness_centrality(g.networkx_graph()) + sage: sg = centrality_betweenness(g) + sage: max(abs(nw[x] - sg[x]) for x in g) # abs tol 1e-10 0 Stupid cases:: @@ -642,13 +643,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) # 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 + sage: g = graphs.RandomGNM(n, m) # needs networkx + sage: topk = centrality_closeness_top_k(g, k) # needs networkx + sage: centr = g.centrality_closeness(algorithm='BFS') # needs networkx + sage: sorted_centr = sorted(centr.values(), reverse=True) # needs networkx + sage: len(topk) == min(k, len(sorted_centr)) # needs networkx True - sage: all(abs(topk[i][0] - sorted_centr[i]) < 1e-12 for i in range(len(topk))) # optional - networkx + sage: all(abs(topk[i][0] - sorted_centr[i]) < 1e-12 for i in range(len(topk))) # needs networkx True Directed case:: @@ -658,13 +659,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) # 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 + sage: g = digraphs.RandomDirectedGNM(n, m) # needs networkx + sage: topk = centrality_closeness_top_k(g, k) # needs networkx + sage: centr = g.centrality_closeness(algorithm='BFS') # needs networkx + sage: sorted_centr = sorted(centr.values(), reverse=True) # needs networkx + sage: len(topk) == min(k, len(sorted_centr)) # needs networkx True - sage: all(abs(topk[i][0] - sorted_centr[i]) < 1e-12 for i in range(len(topk))) # optional - networkx + sage: all(abs(topk[i][0] - sorted_centr[i]) < 1e-12 for i in range(len(topk))) # needs networkx True """ cdef list res diff --git a/src/sage/graphs/cliquer.pyx b/src/sage/graphs/cliquer.pyx index 9ff02b8572e..6f232d97e16 100644 --- a/src/sage/graphs/cliquer.pyx +++ b/src/sage/graphs/cliquer.pyx @@ -115,7 +115,7 @@ def all_max_clique(graph): [2, 6], [2, 8], [3, 4], [3, 7], [3, 9], [4, 5], [4, 8], [5, 10], [5, 11], [6, 10], [6, 11], [7, 8], [7, 11], [8, 10], [9, 10], [9, 11]] sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]}) - sage: G.show(figsize=[2,2]) # optional - sage.plot + sage: G.show(figsize=[2,2]) # needs sage.plot sage: G.cliques_maximum() [[0, 1, 2], [0, 1, 3]] sage: C = graphs.PetersenGraph() @@ -302,7 +302,7 @@ def clique_number(graph): sage: C.clique_number() 4 sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]}) - sage: G.show(figsize=[2,2]) # optional - sage.plot + sage: G.show(figsize=[2,2]) # needs sage.plot sage: G.clique_number() 3 diff --git a/src/sage/graphs/comparability.pyx b/src/sage/graphs/comparability.pyx index b694b552ee8..119cd892265 100644 --- a/src/sage/graphs/comparability.pyx +++ b/src/sage/graphs/comparability.pyx @@ -417,20 +417,20 @@ def is_comparability_MILP(g, certificate=False, solver=None, verbose=0): The 5-cycle or the Petersen Graph are not transitively orientable:: sage: from sage.graphs.comparability import is_comparability_MILP as is_comparability - sage: is_comparability(graphs.CycleGraph(5), certificate = True) + sage: is_comparability(graphs.CycleGraph(5), certificate=True) # needs sage.numerical.mip (False, None) sage: g = graphs.PetersenGraph() - sage: is_comparability(g, certificate = True) + sage: is_comparability(g, certificate=True) # needs sage.numerical.mip (False, None) But the Bull graph is:: sage: g = graphs.BullGraph() - sage: is_comparability(g) + sage: is_comparability(g) # needs sage.numerical.mip True - sage: is_comparability(g, certificate = True) + sage: is_comparability(g, certificate=True) # needs sage.numerical.mip (True, Digraph on 5 vertices) - sage: is_comparability(g, certificate = True)[1].is_transitive() + sage: is_comparability(g, certificate=True)[1].is_transitive() # needs sage.numerical.mip True """ from sage.numerical.mip import MixedIntegerLinearProgram, MIPSolverException @@ -642,7 +642,7 @@ def is_permutation(g, algorithm="greedy", certificate=False, check=True, sage: p1 = Permutation([nn+1 for nn in perm[0]]) sage: p2 = Permutation([nn+1 for nn in perm[1]]) sage: p = p2 * p1.inverse() - sage: p.show(representation="braid") # optional - sage.plot + sage: p.show(representation="braid") # needs sage.plot TESTS: @@ -664,7 +664,7 @@ def is_permutation(g, algorithm="greedy", certificate=False, check=True, Then with MILP:: sage: from sage.graphs.comparability import is_permutation - sage: for i in range(20): + sage: for i in range(20): # needs sage.numerical.mip ....: p = Permutations(10).random_element() ....: g1 = graphs.PermutationGraph(p) ....: isit, certif = is_permutation(g1, algorithm="MILP", certificate=True) @@ -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) # optional - sage.combinat - sage: D.is_transitive() # optional - sage.combinat + sage: D = digraphs.DeBruijn(5, 2) # needs sage.combinat + sage: D.is_transitive() # needs sage.combinat False - sage: cert = D.is_transitive(certificate=True) # optional - sage.combinat - sage: D.has_edge(*cert) # optional - sage.combinat + sage: cert = D.is_transitive(certificate=True) # needs sage.combinat + sage: D.has_edge(*cert) # needs sage.combinat False - sage: bool(D.shortest_path(*cert)) # optional - sage.combinat + sage: bool(D.shortest_path(*cert)) # needs sage.combinat True - sage: digraphs.RandomDirectedGNP(20,.2).transitive_closure().is_transitive() # optional - networkx + sage: digraphs.RandomDirectedGNP(20,.2).transitive_closure().is_transitive() # needs networkx True """ cdef int n = g.order() diff --git a/src/sage/graphs/connectivity.pyx b/src/sage/graphs/connectivity.pyx index c2100141f30..ff0cabb8f37 100644 --- a/src/sage/graphs/connectivity.pyx +++ b/src/sage/graphs/connectivity.pyx @@ -258,12 +258,12 @@ def connected_components_subgraphs(G): sage: from sage.graphs.connectivity import connected_components_subgraphs sage: G = Graph({0: [1, 3], 1: [2], 2: [3], 4: [5, 6], 5: [6]}) sage: L = connected_components_subgraphs(G) - sage: graphs_list.show_graphs(L) # optional - sage.plot + sage: graphs_list.show_graphs(L) # needs sage.plot sage: D = DiGraph({0: [1, 3], 1: [2], 2: [3], 4: [5, 6], 5: [6]}) sage: L = connected_components_subgraphs(D) - sage: graphs_list.show_graphs(L) # optional - sage.plot + sage: graphs_list.show_graphs(L) # needs sage.plot sage: L = D.connected_components_subgraphs() - sage: graphs_list.show_graphs(L) # optional - sage.plot + sage: graphs_list.show_graphs(L) # needs sage.plot TESTS: @@ -1361,25 +1361,25 @@ def vertex_connectivity(G, value_only=True, sets=False, k=None, solver=None, ver A basic application on a ``PappusGraph``:: sage: from sage.graphs.connectivity import vertex_connectivity - sage: g=graphs.PappusGraph() - sage: vertex_connectivity(g) + sage: g = graphs.PappusGraph() + sage: vertex_connectivity(g) # needs sage.numerical.mip 3 - sage: g.vertex_connectivity() + sage: g.vertex_connectivity() # needs sage.numerical.mip 3 In a grid, the vertex connectivity is equal to the minimum degree, in which case one of the two sets is of cardinality `1`:: sage: g = graphs.GridGraph([ 3,3 ]) - sage: [value, cut, [ setA, setB ]] = vertex_connectivity(g, sets=True) - sage: len(setA) == 1 or len(setB) == 1 + sage: [value, cut, [ setA, setB ]] = vertex_connectivity(g, sets=True) # needs sage.numerical.mip + sage: len(setA) == 1 or len(setB) == 1 # needs sage.numerical.mip True A vertex cut in a tree is any internal vertex:: sage: tree = graphs.RandomTree(15) - sage: val, [cut_vertex] = vertex_connectivity(tree, value_only=False) - sage: tree.degree(cut_vertex) > 1 + sage: val, [cut_vertex] = vertex_connectivity(tree, value_only=False) # needs sage.numerical.mip + sage: tree.degree(cut_vertex) > 1 # needs sage.numerical.mip True When ``value_only = True``, this function is optimized for small @@ -1388,41 +1388,41 @@ def vertex_connectivity(G, value_only=True, sets=False, k=None, solver=None, ver It is the case for connected graphs which are not connected:: sage: g = 2 * graphs.PetersenGraph() - sage: vertex_connectivity(g) + sage: vertex_connectivity(g) # needs sage.numerical.mip 0 Or if they are just 1-connected:: sage: g = graphs.PathGraph(10) - sage: vertex_connectivity(g) + sage: vertex_connectivity(g) # needs sage.numerical.mip 1 For directed graphs, the strong connectivity is tested through the dedicated function:: sage: g = digraphs.ButterflyGraph(3) - sage: vertex_connectivity(g) + sage: vertex_connectivity(g) # needs sage.numerical.mip 0 A complete graph on `10` vertices is `9`-connected:: sage: g = graphs.CompleteGraph(10) - sage: vertex_connectivity(g) + sage: vertex_connectivity(g) # needs sage.numerical.mip 9 A complete digraph on `10` vertices is `9`-connected:: sage: g = DiGraph(graphs.CompleteGraph(10)) - sage: vertex_connectivity(g) + sage: vertex_connectivity(g) # needs sage.numerical.mip 9 When parameter ``k`` is set, we only check for the existence of a vertex cut of order at least ``k``:: sage: g = graphs.PappusGraph() - sage: vertex_connectivity(g, k=3) + sage: vertex_connectivity(g, k=3) # needs sage.numerical.mip True - sage: vertex_connectivity(g, k=4) + sage: vertex_connectivity(g, k=4) # needs sage.numerical.mip False TESTS: @@ -1441,13 +1441,13 @@ def vertex_connectivity(G, value_only=True, sets=False, k=None, solver=None, ver sage: from sage.graphs.connectivity import is_strongly_connected sage: from sage.graphs.connectivity import is_connected sage: empty = Graph() - sage: vertex_connectivity(empty) + sage: vertex_connectivity(empty) # needs sage.numerical.mip 0 - sage: vertex_connectivity(empty, k=1) == is_connected(empty) + sage: vertex_connectivity(empty, k=1) == is_connected(empty) # needs sage.numerical.mip True - sage: vertex_connectivity(Graph(), k=2) == empty.is_biconnected() + sage: vertex_connectivity(Graph(), k=2) == empty.is_biconnected() # needs sage.numerical.mip True - sage: vertex_connectivity(DiGraph(), k=1) == is_strongly_connected(DiGraph()) + sage: vertex_connectivity(DiGraph(), k=1) == is_strongly_connected(DiGraph()) # needs sage.numerical.mip True If ``G`` is not a Sage (Di)Graph, an error is raised:: @@ -1460,16 +1460,16 @@ def vertex_connectivity(G, value_only=True, sets=False, k=None, solver=None, ver Complete Graph with loops or multiple edges (:trac:`25589`):: sage: G = Graph([(0, 1), (0, 1)], multiedges=True) - sage: G.vertex_connectivity() + sage: G.vertex_connectivity() # needs sage.numerical.mip 1 sage: G = graphs.CompleteGraph(4) sage: G.allow_loops(True) sage: G.add_edge(0, 0) - sage: G.vertex_connectivity(value_only=False, verbose=1) + sage: G.vertex_connectivity(value_only=False, verbose=1) # needs sage.numerical.mip (3, []) sage: G.allow_multiple_edges(True) sage: G.add_edge(0, 1) - sage: G.vertex_connectivity(value_only=False, verbose=1) + sage: G.vertex_connectivity(value_only=False, verbose=1) # needs sage.numerical.mip (3, []) """ from sage.graphs.generic_graph import GenericGraph @@ -2379,21 +2379,21 @@ def spqr_tree(G, algorithm="Hopcroft_Tarjan", solver=None, verbose=0, sage: T = spqr_tree(G, algorithm="Hopcroft_Tarjan") sage: G.is_isomorphic(spqr_tree_to_graph(T)) True - sage: T2 = spqr_tree(G, algorithm='cleave') - sage: G.is_isomorphic(spqr_tree_to_graph(T2)) + sage: T2 = spqr_tree(G, algorithm='cleave') # needs sage.numerical.mip + sage: G.is_isomorphic(spqr_tree_to_graph(T2)) # needs sage.numerical.mip True sage: G = Graph([(0, 1)], multiedges=True) - sage: T = spqr_tree(G, algorithm='cleave') - sage: T.vertices(sort=True) + sage: T = spqr_tree(G, algorithm='cleave') # needs sage.numerical.mip + sage: T.vertices(sort=True) # needs sage.numerical.mip [('Q', Multi-graph on 2 vertices)] - sage: G.is_isomorphic(spqr_tree_to_graph(T)) + sage: G.is_isomorphic(spqr_tree_to_graph(T)) # needs sage.numerical.mip True sage: T = spqr_tree(G, algorithm='Hopcroft_Tarjan') sage: T.vertices(sort=True) [('Q', Multi-graph on 2 vertices)] sage: G.add_edge(0, 1) - sage: spqr_tree(G, algorithm='cleave').vertices(sort=True) + sage: spqr_tree(G, algorithm='cleave').vertices(sort=True) # needs sage.numerical.mip [('P', Multi-graph on 2 vertices)] sage: from collections import Counter @@ -2401,24 +2401,24 @@ def spqr_tree(G, algorithm="Hopcroft_Tarjan", solver=None, verbose=0, sage: T = G.spqr_tree(algorithm="Hopcroft_Tarjan") sage: Counter(u[0] for u in T) Counter({'R': 1}) - sage: T = G.spqr_tree(algorithm="cleave") - sage: Counter(u[0] for u in T) + sage: T = G.spqr_tree(algorithm="cleave") # needs sage.numerical.mip + sage: Counter(u[0] for u in T) # needs sage.numerical.mip Counter({'R': 1}) sage: for u,v in list(G.edges(labels=False, sort=False)): ....: G.add_path([u, G.add_vertex(), G.add_vertex(), v]) sage: T = G.spqr_tree(algorithm="Hopcroft_Tarjan") sage: sorted(Counter(u[0] for u in T).items()) [('P', 15), ('R', 1), ('S', 15)] - sage: T = G.spqr_tree(algorithm="cleave") - sage: sorted(Counter(u[0] for u in T).items()) + sage: T = G.spqr_tree(algorithm="cleave") # needs sage.numerical.mip + sage: sorted(Counter(u[0] for u in T).items()) # needs sage.numerical.mip [('P', 15), ('R', 1), ('S', 15)] sage: for u,v in list(G.edges(labels=False, sort=False)): ....: G.add_path([u, G.add_vertex(), G.add_vertex(), v]) sage: T = G.spqr_tree(algorithm="Hopcroft_Tarjan") sage: sorted(Counter(u[0] for u in T).items()) [('P', 60), ('R', 1), ('S', 75)] - sage: T = G.spqr_tree(algorithm="cleave") # long time - sage: sorted(Counter(u[0] for u in T).items()) # long time + sage: T = G.spqr_tree(algorithm="cleave") # long time # needs sage.numerical.mip + sage: sorted(Counter(u[0] for u in T).items()) # long time # needs sage.numerical.mip [('P', 60), ('R', 1), ('S', 75)] TESTS:: @@ -2814,7 +2814,7 @@ cdef class _Component: ....: 'comp.add_edge(3)', ....: 'comp.finish_tric_or_poly(4)', ....: 'print(comp)'] - sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython + sage: cython(os.linesep.join(cython_code)) # needs sage.misc.cython Polygon: 2 3 4 """ self.mem = MemoryAllocator() @@ -2861,7 +2861,7 @@ cdef class _Component: ....: 'comp.add_edge(3)', ....: 'comp.finish_tric_or_poly(4)', ....: 'print(comp)'] - sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython + sage: cython(os.linesep.join(cython_code)) # needs sage.misc.cython Polygon: 2 3 4 """ if self.component_type == 0: @@ -4344,8 +4344,8 @@ def is_triconnected(G): Comparing different methods on random graphs that are not always triconnected:: - sage: G = graphs.RandomBarabasiAlbert(50, 3) # optional - networkx - sage: G.is_triconnected() == G.vertex_connectivity(k=3) # optional - networkx + sage: G = graphs.RandomBarabasiAlbert(50, 3) # needs networkx + sage: G.is_triconnected() == G.vertex_connectivity(k=3) # needs networkx True .. SEEALSO:: diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index b1d046ee25d..1017f8490eb 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() # optional - sage.modules + sage: g.adjacency_matrix() # needs 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,28 +377,28 @@ class DiGraph(GenericGraph): - an adjacency matrix:: - sage: M = Matrix([[0, 1, 1, 1, 0], [0, 0, 0, 0, 0], # optional - sage.modules + sage: M = Matrix([[0, 1, 1, 1, 0], [0, 0, 0, 0, 0], # needs 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) # optional - sage.modules + sage: DiGraph(M) # needs sage.modules Digraph on 5 vertices - sage: M = Matrix([[0,1,-1], [-1,0,-1/2], [1,1/2,0]]); M # optional - sage.modules + sage: M = Matrix([[0,1,-1], [-1,0,-1/2], [1,1/2,0]]); M # needs sage.modules [ 0 1 -1] [ -1 0 -1/2] [ 1 1/2 0] - sage: G = DiGraph(M, sparse=True, weighted=True); G # optional - sage.modules + sage: G = DiGraph(M, sparse=True, weighted=True); G # needs sage.modules Digraph on 3 vertices - sage: G.weighted() # optional - sage.modules + sage: G.weighted() # needs 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, # optional - sage.modules + sage: M = Matrix(6, [-1,0,0,0,1, 1,-1,0,0,0, 0,1,-1,0,0, # needs 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] @@ -406,7 +406,7 @@ class DiGraph(GenericGraph): [ 0 0 1 -1 0] [ 0 0 0 1 -1] [ 0 0 0 0 0] - sage: DiGraph(M) # optional - sage.modules + sage: DiGraph(M) # needs sage.modules Digraph on 6 vertices #. A ``dig6`` string: Sage automatically recognizes whether a string is in @@ -429,17 +429,17 @@ class DiGraph(GenericGraph): #. A NetworkX MultiDiGraph:: - sage: import networkx # optional - networkx - sage: g = networkx.MultiDiGraph({0: [1, 2, 3], 2: [4]}) # optional - networkx - sage: DiGraph(g) # optional - networkx + sage: import networkx # needs networkx + sage: g = networkx.MultiDiGraph({0: [1, 2, 3], 2: [4]}) # needs networkx + sage: DiGraph(g) # needs networkx Multi-digraph on 5 vertices #. A NetworkX digraph:: - sage: import networkx # optional - networkx - sage: g = networkx.DiGraph({0: [1, 2, 3], 2: [4]}) # optional - networkx - sage: DiGraph(g) # optional - networkx + sage: import networkx # needs networkx + sage: g = networkx.DiGraph({0: [1, 2, 3], 2: [4]}) # needs networkx + sage: DiGraph(g) # needs networkx Digraph on 5 vertices #. An igraph directed Graph (see also @@ -453,11 +453,12 @@ class DiGraph(GenericGraph): If ``vertex_labels`` is ``True``, the names of the vertices are given by the vertex attribute ``'name'``, if available:: - sage: g = igraph.Graph([(0,1),(0,2)], directed=True, vertex_attrs={'name':['a','b','c']}) # optional - python_igraph - sage: DiGraph(g).vertices(sort=True) # optional - python_igraph + sage: # optional - python_igraph + sage: g = igraph.Graph([(0,1),(0,2)], directed=True, vertex_attrs={'name':['a','b','c']}) + sage: DiGraph(g).vertices(sort=True) ['a', 'b', 'c'] - sage: g = igraph.Graph([(0,1),(0,2)], directed=True, vertex_attrs={'label':['a','b','c']}) # optional - python_igraph - sage: DiGraph(g).vertices(sort=True) # optional - python_igraph + sage: g = igraph.Graph([(0,1),(0,2)], directed=True, vertex_attrs={'label':['a','b','c']}) + sage: DiGraph(g).vertices(sort=True) [0, 1, 2] If the igraph Graph has edge attributes, they are used as edge labels:: @@ -479,18 +480,19 @@ class DiGraph(GenericGraph): Demonstrate that digraphs using the static backend are equal to mutable graphs but can be used as dictionary keys:: - sage: import networkx # optional - networkx - sage: g = networkx.DiGraph({0:[1,2,3], 2:[4]}) # optional - networkx - sage: G = DiGraph(g) # optional - networkx - sage: G_imm = DiGraph(G, data_structure="static_sparse") # optional - networkx - sage: H_imm = DiGraph(G, data_structure="static_sparse") # optional - networkx - sage: H_imm is G_imm # optional - networkx + sage: # needs networkx + sage: import networkx + sage: g = networkx.DiGraph({0:[1,2,3], 2:[4]}) + sage: G = DiGraph(g) + sage: G_imm = DiGraph(G, data_structure="static_sparse") + sage: H_imm = DiGraph(G, data_structure="static_sparse") + sage: H_imm is G_imm False - sage: H_imm == G_imm == G # optional - networkx + sage: H_imm == G_imm == G True - sage: {G_imm:1}[H_imm] # optional - networkx + sage: {G_imm:1}[H_imm] 1 - sage: {G_imm:1}[G] # optional - networkx + sage: {G_imm:1}[G] Traceback (most recent call last): ... TypeError: This graph is mutable, and thus not hashable. Create an @@ -500,10 +502,10 @@ class DiGraph(GenericGraph): specifying the ``immutable`` optional argument (not only by ``data_structure='static_sparse'`` as above):: - sage: J_imm = DiGraph(G, immutable=True) # optional - networkx - sage: J_imm == G_imm # optional - networkx + sage: J_imm = DiGraph(G, immutable=True) # needs networkx + sage: J_imm == G_imm # needs networkx True - sage: type(J_imm._backend) == type(G_imm._backend) # optional - networkx + sage: type(J_imm._backend) == type(G_imm._backend) # needs networkx True From a list of vertices and a list of edges:: @@ -515,7 +517,7 @@ class DiGraph(GenericGraph): Check that :trac:`27505` is fixed:: - sage: DiGraph(DiGraph().networkx_graph(), weighted=None, format='NX') # optional - networkx + sage: DiGraph(DiGraph().networkx_graph(), weighted=None, format='NX') # needs networkx Digraph on 0 vertices """ _directed = True @@ -532,12 +534,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]) # optional - sage.modules - sage: DiGraph(a, sparse=True).adjacency_matrix() == a # optional - sage.modules + sage: a = matrix(2,2,[1,2,0,1]) # needs sage.modules + sage: DiGraph(a, sparse=True).adjacency_matrix() == a # needs sage.modules True - sage: a = matrix(2,2,[3,2,0,1]) # optional - sage.modules - sage: DiGraph(a, sparse=True).adjacency_matrix() == a # optional - sage.modules + sage: a = matrix(2,2,[3,2,0,1]) # needs sage.modules + sage: DiGraph(a, sparse=True).adjacency_matrix() == a # needs sage.modules True The positions are copied when the DiGraph is built from another DiGraph @@ -580,9 +582,9 @@ def __init__(self, data=None, pos=None, loops=None, format=None, 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() # 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 + sage: matad = grafo3.weighted_adjacency_matrix() # needs sage.modules + sage: grafo4 = DiGraph(matad, format="adjacency_matrix", weighted=True) # needs sage.modules + sage: grafo4.shortest_path(0, 6, by_weight=True) # needs sage.modules [0, 1, 2, 5, 4, 6] Building a DiGraph with ``immutable=False`` returns a mutable graph:: @@ -954,7 +956,7 @@ def is_directed_acyclic(self, certificate=False): At first, the following graph is acyclic:: sage: D = DiGraph({0:[1, 2, 3], 4:[2, 5], 1:[8], 2:[7], 3:[7], 5:[6,7], 7:[8], 6:[9], 8:[10], 9:[10]}) - sage: D.plot(layout='circular').show() # optional - sage.plot + sage: D.plot(layout='circular').show() # needs sage.plot sage: D.is_directed_acyclic() True @@ -1457,12 +1459,12 @@ def degree_polynomial(self): EXAMPLES:: - sage: G = posets.PentagonPoset().hasse_diagram() # optional - sage.matrix - sage: G.degree_polynomial() # optional - sage.matrix + sage: G = posets.PentagonPoset().hasse_diagram() # needs sage.modules + sage: G.degree_polynomial() # needs sage.modules x^2 + 3*x*y + y^2 sage: G = posets.BooleanLattice(4).hasse_diagram() - sage: G.degree_polynomial().factor() + sage: G.degree_polynomial().factor() # needs sage.libs.pari (x + y)^4 """ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing @@ -1563,7 +1565,7 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False, sage: dcycle=DiGraph(cycle) sage: cycle.size() 5 - sage: dcycle.feedback_edge_set(value_only=True) + sage: dcycle.feedback_edge_set(value_only=True) # needs sage.numerical.mip 5 And in this situation, for any edge `uv` of the first graph, `uv` of @@ -1573,9 +1575,9 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False, sage: while not g.num_edges(): ....: g = graphs.RandomGNP(5,.3) sage: dg = DiGraph(g) - sage: feedback = dg.feedback_edge_set() + sage: feedback = dg.feedback_edge_set() # needs sage.numerical.mip sage: u,v,l = next(g.edge_iterator()) - sage: (u,v) in feedback or (v,u) in feedback + sage: (u,v) in feedback or (v,u) in feedback # needs sage.numerical.mip True TESTS: @@ -1583,7 +1585,7 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False, Comparing with/without constraint generation. Also double-checks issue :trac:`12833`:: - sage: for i in range(20): + sage: for i in range(20): # needs sage.numerical.mip ....: g = digraphs.RandomDirectedGNP(10, .3) ....: x = g.feedback_edge_set(value_only=True) ....: y = g.feedback_edge_set(value_only=True, @@ -1594,34 +1596,37 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False, Loops are part of the feedback edge set (:trac:`23989`):: + sage: # needs sage.combinat sage: D = digraphs.DeBruijn(2, 2) sage: sorted(D.loops(labels=None)) [('00', '00'), ('11', '11')] - sage: FAS = D.feedback_edge_set(value_only=False) - sage: all(l in FAS for l in D.loops(labels=None)) + sage: FAS = D.feedback_edge_set(value_only=False) # needs sage.numerical.mip + sage: all(l in FAS for l in D.loops(labels=None)) # needs sage.numerical.mip True - sage: FAS2 = D.feedback_edge_set(value_only=False, constraint_generation=False) - sage: len(FAS) == len(FAS2) + sage: FAS2 = D.feedback_edge_set(value_only=False, # needs sage.numerical.mip + ....: constraint_generation=False) + sage: len(FAS) == len(FAS2) # needs sage.numerical.mip True Check that multi-edges are properly taken into account:: sage: cycle = graphs.CycleGraph(5) sage: dcycle = DiGraph(cycle) - sage: dcycle.feedback_edge_set(value_only=True) + sage: dcycle.feedback_edge_set(value_only=True) # needs sage.numerical.mip 5 sage: dcycle.allow_multiple_edges(True) sage: dcycle.add_edges(dcycle.edges(sort=True)) - sage: dcycle.feedback_edge_set(value_only=True) + sage: dcycle.feedback_edge_set(value_only=True) # needs sage.numerical.mip 10 - sage: dcycle.feedback_edge_set(value_only=True, constraint_generation=False) + sage: dcycle.feedback_edge_set(value_only=True, # needs sage.numerical.mip + ....: constraint_generation=False) 10 Strongly connected components are well handled (:trac:`23989`):: sage: g = digraphs.Circuit(3) * 2 sage: g.add_edge(0, 3) - sage: g.feedback_edge_set(value_only=True) + sage: g.feedback_edge_set(value_only=True) # needs sage.numerical.mip 2 """ # It would be a pity to start a LP if the digraph is already acyclic @@ -2071,10 +2076,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) # optional - sage.combinat - sage: Dr = D.reverse_edges(D.edges(sort=True), inplace=False, # optional - sage.combinat + sage: D = digraphs.Kautz(2, 3) # needs sage.combinat + sage: Dr = D.reverse_edges(D.edges(sort=True), inplace=False, # needs sage.combinat ....: multiedges=True) - sage: Dr.edges(sort=True) == D.reverse().edges(sort=True) # optional - sage.combinat + sage: Dr.edges(sort=True) == D.reverse().edges(sort=True) # needs sage.combinat True """ tempG = self if inplace else copy(self) @@ -2181,7 +2186,7 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, [2, 2, 2] sage: G.eccentricity(algorithm='Floyd-Warshall-Cython') [2, 2, 2] - sage: G.eccentricity(by_weight=True, algorithm='Dijkstra_NetworkX') # optional - networkx + sage: G.eccentricity(by_weight=True, algorithm='Dijkstra_NetworkX') # needs networkx [5, 5, 4] sage: G.eccentricity(by_weight=True, algorithm='Dijkstra_Boost') [5, 5, 4] @@ -2446,11 +2451,12 @@ def diameter(self, by_weight=False, algorithm=None, weight_function=None, EXAMPLES:: - sage: G = digraphs.DeBruijn(5,4) # optional - sage.combinat - sage: G.diameter() # optional - sage.combinat + sage: # needs sage.combinat + sage: G = digraphs.DeBruijn(5,4) + sage: G.diameter() 4 - sage: G = digraphs.GeneralizedDeBruijn(9, 3) # optional - sage.combinat - sage: G.diameter() # optional - sage.combinat + sage: G = digraphs.GeneralizedDeBruijn(9, 3) + sage: G.diameter() 2 TESTS:: @@ -3144,7 +3150,7 @@ def topological_sort(self, implementation="default"): sage: D = DiGraph({0: [1, 2, 3], 4: [2, 5], 1: [8], 2: [7], 3: [7], ....: 5: [6, 7], 7: [8], 6: [9], 8: [10], 9: [10]}) - sage: D.plot(layout='circular').show() # optional - sage.plot + sage: D.plot(layout='circular').show() # needs sage.plot sage: D.topological_sort() [4, 5, 6, 9, 0, 1, 2, 3, 7, 8, 10] @@ -3156,9 +3162,9 @@ def topological_sort(self, implementation="default"): Using the NetworkX implementation :: - sage: s = list(D.topological_sort(implementation="NetworkX")); s # random # optional - networkx + sage: s = list(D.topological_sort(implementation="NetworkX")); s # random # needs networkx [0, 4, 1, 3, 2, 5, 6, 9, 7, 8, 10] - sage: all(s.index(u) < s.index(v) # optional - networkx + sage: all(s.index(u) < s.index(v) # needs networkx ....: for u, v in D.edges(sort=False, labels=False)) True @@ -3225,14 +3231,14 @@ def topological_sort_generator(self): EXAMPLES:: 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()) # optional - sage.modules sage.rings.finite_rings + sage: D.plot(layout='circular').show() # needs sage.plot + sage: list(D.topological_sort_generator()) # needs 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]] :: - sage: for sort in D.topological_sort_generator(): + sage: for sort in D.topological_sort_generator(): # needs sage.modules sage.rings.finite_rings ....: for u, v in D.edge_iterator(labels=False): ....: if sort.index(u) > sort.index(v): ....: print("this should never happen") @@ -3592,7 +3598,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)) # optional - sage.geometry.polyhedron + sage: polytopes.flow_polytope(digraphs.Path(5)) # needs sage.geometry.polyhedron A 0-dimensional polyhedron in QQ^4 defined as the convex hull of 1 vertex EXAMPLES: @@ -3600,26 +3606,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 # optional - sage.geometry.polyhedron + sage: fl = G.flow_polytope(); fl # needs sage.geometry.polyhedron A 1-dimensional polyhedron in QQ^4 defined as the convex hull of 2 vertices - sage: fl.vertices() # optional - sage.geometry.polyhedron + sage: fl.vertices() # needs 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 # optional - sage.geometry.polyhedron + sage: fl = G.flow_polytope(edges=G.edges(key=lambda x: x[0] - x[1])); fl # needs sage.geometry.polyhedron A 1-dimensional polyhedron in QQ^4 defined as the convex hull of 2 vertices - sage: fl.vertices() # optional - sage.geometry.polyhedron + sage: fl.vertices() # needs 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 # optional - sage.geometry.polyhedron + sage: fl = H.flow_polytope(); fl # needs sage.geometry.polyhedron A 3-dimensional polyhedron in QQ^6 defined as the convex hull of 4 vertices - sage: fl.vertices() # optional - sage.geometry.polyhedron + sage: fl.vertices() # needs 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), @@ -3627,40 +3633,41 @@ 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), # optional - sage.geometry.polyhedron + sage: fl = H.flow_polytope(edges=[(0, 1, None), (1, 2, None), # needs 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() # optional - sage.geometry.polyhedron + sage: fl.vertices() # needs 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 # optional - sage.geometry.polyhedron + sage: # needs sage.geometry.polyhedron + sage: fl = H.flow_polytope(ends=([1], [3])); fl A 1-dimensional polyhedron in QQ^6 defined as the convex hull of 2 vertices - sage: fl.vertices() # optional - sage.geometry.polyhedron + sage: fl.vertices() (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 # optional - sage.geometry.polyhedron + sage: fl = H.flow_polytope(ends=([0, 1], [3])); fl The empty polyhedron in QQ^6 - sage: fl = H.flow_polytope(ends=([3], [0])); fl # optional - sage.geometry.polyhedron + sage: fl = H.flow_polytope(ends=([3], [0])); fl The empty polyhedron in QQ^6 - sage: fl = H.flow_polytope(ends=([0, 1], [2, 3])); fl # optional - sage.geometry.polyhedron + sage: fl = H.flow_polytope(ends=([0, 1], [2, 3])); fl A 3-dimensional polyhedron in QQ^6 defined as the convex hull of 5 vertices - sage: fl.vertices() # optional - sage.geometry.polyhedron + sage: fl.vertices() (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), # optional - sage.geometry.polyhedron + sage: fl = H.flow_polytope(edges=[(0, 1, None), (1, 2, None), ....: (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() # optional - sage.geometry.polyhedron + sage: fl.vertices() (A vertex at (0, 0, 0, 1, 1), A vertex at (1, 2, 1, 0, 0), A vertex at (1, 1, 0, 0, 1), @@ -3669,13 +3676,13 @@ 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() # optional - sage.geometry.polyhedron + sage: Y.flow_polytope() # needs 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() # optional - sage.geometry.polyhedron + sage: Z.flow_polytope() # needs sage.geometry.polyhedron A 0-dimensional polyhedron in QQ^0 defined as the convex hull of 1 vertex @@ -3683,11 +3690,11 @@ def flow_polytope(self, edges=None, ends=None, backend=None): sage: G = DiGraph([(0, 1), (0,1)], multiedges=True); G Multi-digraph on 2 vertices - sage: P = G.flow_polytope(); P # optional - sage.geometry.polyhedron + sage: P = G.flow_polytope(); P # needs sage.geometry.polyhedron A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - sage.geometry.polyhedron + sage: P.vertices() # needs sage.geometry.polyhedron (A vertex at (1, 0), A vertex at (0, 1)) - sage: P.lines() # optional - sage.geometry.polyhedron + sage: P.lines() # needs sage.geometry.polyhedron () """ from sage.geometry.polyhedron.constructor import Polyhedron diff --git a/src/sage/graphs/digraph_generators.py b/src/sage/graphs/digraph_generators.py index b9a87601a47..3070cb2f37f 100644 --- a/src/sage/graphs/digraph_generators.py +++ b/src/sage/graphs/digraph_generators.py @@ -226,22 +226,23 @@ def ButterflyGraph(self, n, vertices='strings'): sage: digraphs.ButterflyGraph(2).edges(sort=True, labels=False) [(('00', 0), ('00', 1)), - (('00', 0), ('10', 1)), - (('00', 1), ('00', 2)), - (('00', 1), ('01', 2)), - (('01', 0), ('01', 1)), - (('01', 0), ('11', 1)), - (('01', 1), ('00', 2)), - (('01', 1), ('01', 2)), - (('10', 0), ('00', 1)), - (('10', 0), ('10', 1)), - (('10', 1), ('10', 2)), - (('10', 1), ('11', 2)), - (('11', 0), ('01', 1)), - (('11', 0), ('11', 1)), - (('11', 1), ('10', 2)), - (('11', 1), ('11', 2))] - sage: digraphs.ButterflyGraph(2,vertices='vectors').edges(sort=True, labels=False) + (('00', 0), ('10', 1)), + (('00', 1), ('00', 2)), + (('00', 1), ('01', 2)), + (('01', 0), ('01', 1)), + (('01', 0), ('11', 1)), + (('01', 1), ('00', 2)), + (('01', 1), ('01', 2)), + (('10', 0), ('00', 1)), + (('10', 0), ('10', 1)), + (('10', 1), ('10', 2)), + (('10', 1), ('11', 2)), + (('11', 0), ('01', 1)), + (('11', 0), ('11', 1)), + (('11', 1), ('10', 2)), + (('11', 1), ('11', 2))] + sage: digraphs.ButterflyGraph(2, vertices='vectors').edges(sort=True, # needs sage.modules sage.rings.finite_rings + ....: labels=False) [(((0, 0), 0), ((0, 0), 1)), (((0, 0), 0), ((1, 0), 1)), (((0, 0), 1), ((0, 0), 2)), @@ -338,7 +339,7 @@ def Path(self, n): [0, 1, 2, 3, 4] sage: g.size() 4 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # needs sage.groups 1 """ g = DiGraph(n, name="Path") @@ -370,9 +371,11 @@ def StronglyRegular(self, n): A Strongly Regular digraph satisfies the condition `AJ = JA = kJ` where `A` is the adjacency matrix:: + sage: # needs sage.modules sage: g = digraphs.StronglyRegular(7); g Strongly regular digraph: Digraph on 7 vertices - sage: A = g.adjacency_matrix()*ones_matrix(7); B = ones_matrix(7)*g.adjacency_matrix() + sage: A = g.adjacency_matrix()*ones_matrix(7) + sage: B = ones_matrix(7)*g.adjacency_matrix() sage: A == B == A[0, 0]*ones_matrix(7) True @@ -380,7 +383,7 @@ def StronglyRegular(self, n): Wrong parameter:: - sage: digraphs.StronglyRegular(73) + sage: digraphs.StronglyRegular(73) # needs sage.modules Traceback (most recent call last): ... ValueError: strongly regular digraph with 73 vertices not yet implemented @@ -413,16 +416,16 @@ def Paley(self, q): A Paley digraph has `n * (n-1) / 2` edges, its underlying graph is a clique, and so it is a tournament:: - sage: g = digraphs.Paley(7); g + sage: g = digraphs.Paley(7); g # needs sage.rings.finite_rings Paley digraph with parameter 7: Digraph on 7 vertices - sage: g.size() == g.order() * (g.order() - 1) / 2 + sage: g.size() == g.order() * (g.order() - 1) / 2 # needs sage.rings.finite_rings True - sage: g.to_undirected().is_clique() + sage: g.to_undirected().is_clique() # needs sage.rings.finite_rings True A Paley digraph is always self-complementary:: - sage: g.complement().is_isomorphic(g) + sage: g.complement().is_isomorphic(g) # needs sage.rings.finite_rings True TESTS: @@ -470,7 +473,7 @@ def TransitiveTournament(self, n): [0, 1, 2, 3, 4] sage: g.size() 10 - sage: g.automorphism_group().cardinality() + sage: g.automorphism_group().cardinality() # needs sage.groups 1 .. SEEALSO:: @@ -890,15 +893,16 @@ def DeBruijn(self, k, n, vertices='strings'): de Bruijn digraph of degree 2 and diameter 2:: - sage: db = digraphs.DeBruijn(2, 2); db + sage: db = digraphs.DeBruijn(2, 2); db # needs sage.combinat De Bruijn digraph (k=2, n=2): Looped digraph on 4 vertices - sage: db.order(), db.size() + sage: db.order(), db.size() # needs sage.combinat (4, 8) - sage: db.diameter() + sage: db.diameter() # needs sage.combinat 2 Building a de Bruijn digraph on a different alphabet:: + sage: # needs sage.combinat sage: g = digraphs.DeBruijn(['a', 'b'], 2) sage: g.vertices(sort=True) ['aa', 'ab', 'ba', 'bb'] @@ -914,20 +918,20 @@ def DeBruijn(self, k, n, vertices='strings'): Alphabet of null size or words of length zero:: - sage: digraphs.DeBruijn(5, 0) + sage: digraphs.DeBruijn(5, 0) # needs sage.combinat De Bruijn digraph (k=5, n=0): Looped multi-digraph on 1 vertex - sage: digraphs.DeBruijn(0, 0) + sage: digraphs.DeBruijn(0, 0) # needs sage.combinat De Bruijn digraph (k=0, n=0): Looped multi-digraph on 0 vertices :trac:`22355`:: - sage: db = digraphs.DeBruijn(2, 2, vertices='strings') - sage: db.vertices(sort=True) + sage: db = digraphs.DeBruijn(2, 2, vertices='strings') # needs sage.combinat + sage: db.vertices(sort=True) # needs sage.combinat ['00', '01', '10', '11'] sage: h = digraphs.DeBruijn(2, 2, vertices='integers') sage: h.vertices(sort=True) [0, 1, 2, 3] - sage: db.is_isomorphic(h) + sage: db.is_isomorphic(h) # needs sage.combinat True sage: digraphs.DeBruijn(0, 0, vertices='integers') De Bruijn digraph (k=0, n=0): Looped multi-digraph on 0 vertices @@ -998,8 +1002,9 @@ def GeneralizedDeBruijn(self, n, d): EXAMPLES:: sage: GB = digraphs.GeneralizedDeBruijn(8, 2) - sage: GB.is_isomorphic(digraphs.DeBruijn(2, 3), certificate = True) - (True, {0: '000', 1: '001', 2: '010', 3: '011', 4: '100', 5: '101', 6: '110', 7: '111'}) + sage: GB.is_isomorphic(digraphs.DeBruijn(2, 3), certificate=True) # needs sage.combinat + (True, {0: '000', 1: '001', 2: '010', 3: '011', + 4: '100', 5: '101', 6: '110', 7: '111'}) TESTS: @@ -1054,14 +1059,15 @@ def ImaseItoh(self, n, d): EXAMPLES:: sage: II = digraphs.ImaseItoh(8, 2) - sage: II.is_isomorphic(digraphs.DeBruijn(2, 3), certificate = True) - (True, {0: '010', 1: '011', 2: '000', 3: '001', 4: '110', 5: '111', 6: '100', 7: '101'}) + sage: II.is_isomorphic(digraphs.DeBruijn(2, 3), certificate=True) # needs sage.combinat + (True, {0: '010', 1: '011', 2: '000', 3: '001', + 4: '110', 5: '111', 6: '100', 7: '101'}) sage: II = digraphs.ImaseItoh(12, 2) - sage: b,D = II.is_isomorphic(digraphs.Kautz(2, 3), certificate=True) - sage: b + sage: b,D = II.is_isomorphic(digraphs.Kautz(2, 3), certificate=True) # needs sage.combinat + sage: b # needs sage.combinat True - sage: D # random isomorphism + sage: D # random isomorphism # needs sage.combinat {0: '202', 1: '201', 2: '210', 3: '212', 4: '121', 5: '120', 6: '102', 7: '101', 8: '010', 9: '012', 10: '021', 11: '020'} @@ -1132,23 +1138,24 @@ def Kautz(self, k, D, vertices='strings'): EXAMPLES:: + sage: # needs sage.combinat sage: K = digraphs.Kautz(2, 3) - sage: b,D = K.is_isomorphic(digraphs.ImaseItoh(12, 2), certificate=True) + sage: b, D = K.is_isomorphic(digraphs.ImaseItoh(12, 2), certificate=True) sage: b True sage: D # random isomorphism {'010': 8, '012': 9, '020': 11, '021': 10, '101': 7, '102': 6, '120': 5, '121': 4, '201': 1, '202': 0, '210': 2, '212': 3} - sage: K = digraphs.Kautz([1,'a','B'], 2) - sage: K.edges(sort=True) + sage: K = digraphs.Kautz([1,'a','B'], 2) # needs sage.combinat + sage: K.edges(sort=True) # needs sage.combinat [('1B', 'B1', '1'), ('1B', 'Ba', 'a'), ('1a', 'a1', '1'), ('1a', 'aB', 'B'), ('B1', '1B', 'B'), ('B1', '1a', 'a'), ('Ba', 'a1', '1'), ('Ba', 'aB', 'B'), ('a1', '1B', 'B'), ('a1', '1a', 'a'), ('aB', 'B1', '1'), ('aB', 'Ba', 'a')] - sage: K = digraphs.Kautz([1,'aA','BB'], 2) - sage: K.edges(sort=True) + sage: K = digraphs.Kautz([1,'aA','BB'], 2) # needs sage.combinat + sage: K.edges(sort=True) # needs sage.combinat [('1,BB', 'BB,1', '1'), ('1,BB', 'BB,aA', 'aA'), ('1,aA', 'aA,1', '1'), ('1,aA', 'aA,BB', 'BB'), ('BB,1', '1,BB', 'BB'), ('BB,1', '1,aA', 'aA'), @@ -1160,12 +1167,12 @@ def Kautz(self, k, D, vertices='strings'): An exception is raised when the degree is less than one:: - sage: G = digraphs.Kautz(0, 2) + sage: G = digraphs.Kautz(0, 2) # needs sage.combinat Traceback (most recent call last): ... ValueError: degree must be greater than or equal to one - sage: G = digraphs.Kautz(['a'], 2) + sage: G = digraphs.Kautz(['a'], 2) # needs sage.combinat Traceback (most recent call last): ... ValueError: degree must be greater than or equal to one @@ -1173,23 +1180,23 @@ def Kautz(self, k, D, vertices='strings'): An exception is raised when the diameter of the graph is less than one:: - sage: G = digraphs.Kautz(2, 0) + sage: G = digraphs.Kautz(2, 0) # needs sage.combinat Traceback (most recent call last): ... ValueError: diameter must be greater than or equal to one :trac:`22355`:: - sage: K = digraphs.Kautz(2, 2, vertices='strings') - sage: K.vertices(sort=True) + sage: K = digraphs.Kautz(2, 2, vertices='strings') # needs sage.combinat + sage: K.vertices(sort=True) # needs sage.combinat ['01', '02', '10', '12', '20', '21'] sage: h = digraphs.Kautz(2, 2, vertices='integers') sage: h.vertices(sort=True) [0, 1, 2, 3, 4, 5] - sage: h.is_isomorphic(K) + sage: h.is_isomorphic(K) # needs sage.combinat True sage: h = digraphs.Kautz([1,'aA','BB'], 2, vertices='integers') - sage: h.is_isomorphic(K) + sage: h.is_isomorphic(K) # needs sage.combinat True sage: h.vertices(sort=True) [0, 1, 2, 3, 4, 5] @@ -1346,6 +1353,7 @@ def RandomDirectedGN(self, n, kernel=lambda x: x, seed=None): EXAMPLES:: + sage: # needs networkx sage: D = digraphs.RandomDirectedGN(25) sage: D.num_verts() 25 @@ -1355,7 +1363,7 @@ def RandomDirectedGN(self, n, kernel=lambda x: x, seed=None): True sage: D.parent() is DiGraph True - sage: D.show() # long time + sage: D.show() # long time """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) @@ -1382,12 +1390,13 @@ def RandomDirectedGNC(self, n, seed=None): EXAMPLES:: + sage: # needs networkx sage: D = digraphs.RandomDirectedGNC(25) sage: D.is_directed_acyclic() True sage: D.topological_sort() [24, 23, ..., 1, 0] - sage: D.show() # long time + sage: D.show() # long time """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) @@ -1583,12 +1592,13 @@ def RandomDirectedGNR(self, n, p, seed=None): EXAMPLES:: + sage: # needs networkx sage: D = digraphs.RandomDirectedGNR(25, .2) sage: D.is_directed_acyclic() True sage: D.to_undirected().is_tree() True - sage: D.show() # long time + sage: D.show() # long time # needs sage.plot """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) diff --git a/src/sage/graphs/distances_all_pairs.pyx b/src/sage/graphs/distances_all_pairs.pyx index 46baaf8ca73..a5a90cc0c0c 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) # optional - networkx + sage: graphs.Tutte12Cage().is_distance_regular(parameters=True) # needs 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) # optional - networkx - sage: eccentricity(G, algorithm='bounds') == eccentricity(G, algorithm='DHV') # optional - networkx + sage: G = graphs.RandomBarabasiAlbert(50, 2) # needs networkx + sage: eccentricity(G, algorithm='bounds') == eccentricity(G, algorithm='DHV') # needs networkx True """ cdef uint32_t n = sd.n @@ -1777,26 +1777,28 @@ def diameter(G, algorithm=None, source=None): Comparison of exact algorithms for graphs:: - 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 + sage: # needs networkx + 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!") Comparison of lower bound algorithms:: - 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 + sage: lb2 = diameter(G, algorithm='2sweep') # needs networkx + sage: lbm = diameter(G, algorithm='multi-sweep') # needs networkx + sage: if not (lb2 <= lbm and lbm <= d3): print("Something goes wrong!") # needs networkx Comparison of exact algorithms for digraphs:: - 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 + sage: # needs networkx + 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 True TESTS: @@ -2294,10 +2296,11 @@ def szeged_index(G, algorithm=None): Check that both algorithms return same value:: - sage: G = graphs.RandomBarabasiAlbert(100, 2) # long time - sage: a = szeged_index(G, algorithm='low') # long time - sage: b = szeged_index(G, algorithm='high') # long time - sage: a == b # long time + sage: # long time + sage: G = graphs.RandomBarabasiAlbert(100, 2) + sage: a = szeged_index(G, algorithm='low') + sage: b = szeged_index(G, algorithm='high') + sage: a == b True The Szeged index of a directed circuit of order `n` is `(n-1)^2`:: @@ -2438,8 +2441,8 @@ def distances_distribution(G): The de Bruijn digraph dB(2,3):: - sage: D = digraphs.DeBruijn(2,3) # optional - sage.combinat - sage: D.distances_distribution() # optional - sage.combinat + sage: D = digraphs.DeBruijn(2,3) # needs sage.combinat + sage: D.distances_distribution() # needs sage.combinat {1: 1/4, 2: 11/28, 3: 5/14} """ cdef size_t n = G.order() diff --git a/src/sage/graphs/domination.py b/src/sage/graphs/domination.py index ed2fdd17183..a92c814c7fa 100644 --- a/src/sage/graphs/domination.py +++ b/src/sage/graphs/domination.py @@ -24,7 +24,7 @@ We compute the size of a minimum dominating set of the Petersen graph:: sage: g = graphs.PetersenGraph() - sage: g.dominating_set(value_only=True) + sage: g.dominating_set(value_only=True) # needs sage.numerical.mip 3 We enumerate the minimal dominating sets of the 5-star graph:: @@ -281,7 +281,7 @@ def dominating_sets(g, k=1, independent=False, total=False, Number of distance-`k` dominating sets of a Path graph of order 10:: sage: g = graphs.PathGraph(10) - sage: [sum(1 for _ in g.dominating_sets(k=k)) for k in range(11)] + sage: [sum(1 for _ in g.dominating_sets(k=k)) for k in range(11)] # needs sage.numerical.mip [1, 13, 1, 13, 25, 2, 4, 6, 8, 10, 10] If we build a graph from two disjoint stars, then link their centers we will @@ -290,15 +290,15 @@ def dominating_sets(g, k=1, independent=False, total=False, sage: g = 2 * graphs.StarGraph(5) sage: g.add_edge(0, 6) - sage: [sum(1 for _ in g.dominating_sets(k=k)) for k in range(11)] + sage: [sum(1 for _ in g.dominating_sets(k=k)) for k in range(11)] # needs sage.numerical.mip [1, 1, 2, 12, 12, 12, 12, 12, 12, 12, 12] The total dominating set of the Petersen graph has cardinality 4:: sage: G = graphs.PetersenGraph() - sage: G.dominating_set(total=True, value_only=True) + sage: G.dominating_set(total=True, value_only=True) # needs sage.numerical.mip 4 - sage: sorted(G.dominating_sets(k=1)) + sage: sorted(G.dominating_sets(k=1)) # needs sage.numerical.mip [[0, 2, 6], [0, 3, 9], [0, 7, 8], @@ -313,33 +313,33 @@ def dominating_sets(g, k=1, independent=False, total=False, Independent distance-`k` dominating sets of a Path graph:: sage: G = graphs.PathGraph(6) - sage: sorted(G.dominating_sets(k=1, independent=True)) + sage: sorted(G.dominating_sets(k=1, independent=True)) # needs sage.numerical.mip [[1, 4]] - sage: sorted(G.dominating_sets(k=2, independent=True)) + sage: sorted(G.dominating_sets(k=2, independent=True)) # needs sage.numerical.mip [[0, 3], [0, 4], [0, 5], [1, 3], [1, 4], [1, 5], [2, 4], [2, 5]] - sage: sorted(G.dominating_sets(k=3, independent=True)) + sage: sorted(G.dominating_sets(k=3, independent=True)) # needs sage.numerical.mip [[2], [3]] The dominating set is calculated for both the directed and undirected graphs (modification introduced in :trac:`17905`):: sage: g = digraphs.Path(3) - sage: g.dominating_set(value_only=True) + sage: g.dominating_set(value_only=True) # needs sage.numerical.mip 2 - sage: list(g.dominating_sets()) + sage: list(g.dominating_sets()) # needs sage.numerical.mip [[0, 1], [0, 2]] - sage: list(g.dominating_sets(k=2)) + sage: list(g.dominating_sets(k=2)) # needs sage.numerical.mip [[0]] sage: g = graphs.PathGraph(3) - sage: g.dominating_set(value_only=True) + sage: g.dominating_set(value_only=True) # needs sage.numerical.mip 1 - sage: next(g.dominating_sets()) + sage: next(g.dominating_sets()) # needs sage.numerical.mip [1] TESTS:: sage: g = Graph([(0, 1)]) - sage: next(g.dominating_sets(k=-1)) + sage: next(g.dominating_sets(k=-1)) # needs sage.numerical.mip Traceback (most recent call last): ... ValueError: the domination distance must be a non-negative integer @@ -468,7 +468,7 @@ def dominating_set(g, k=1, independent=False, total=False, value_only=False, A basic illustration on a ``PappusGraph``:: sage: g = graphs.PappusGraph() - sage: g.dominating_set(value_only=True) + sage: g.dominating_set(value_only=True) # needs sage.numerical.mip 5 If we build a graph from two disjoint stars, then link their centers we will @@ -477,34 +477,34 @@ def dominating_set(g, k=1, independent=False, total=False, value_only=False, sage: g = 2 * graphs.StarGraph(5) sage: g.add_edge(0, 6) - sage: len(g.dominating_set()) + sage: len(g.dominating_set()) # needs sage.numerical.mip 2 - sage: len(g.dominating_set(independent=True)) + sage: len(g.dominating_set(independent=True)) # needs sage.numerical.mip 6 The total dominating set of the Petersen graph has cardinality 4:: sage: G = graphs.PetersenGraph() - sage: G.dominating_set(total=True, value_only=True) + sage: G.dominating_set(total=True, value_only=True) # needs sage.numerical.mip 4 The dominating set is calculated for both the directed and undirected graphs (modification introduced in :trac:`17905`):: sage: g = digraphs.Path(3) - sage: g.dominating_set(value_only=True) + sage: g.dominating_set(value_only=True) # needs sage.numerical.mip 2 sage: g = graphs.PathGraph(3) - sage: g.dominating_set(value_only=True) + sage: g.dominating_set(value_only=True) # needs sage.numerical.mip 1 Cardinality of distance-`k` dominating sets:: sage: G = graphs.PetersenGraph() - sage: [G.dominating_set(k=k, value_only=True) for k in range(G.radius() + 1)] + sage: [G.dominating_set(k=k, value_only=True) for k in range(G.radius() + 1)] # needs sage.numerical.mip [10, 3, 1] sage: G = graphs.PathGraph(5) - sage: [G.dominating_set(k=k, value_only=True) for k in range(G.radius() + 1)] + sage: [G.dominating_set(k=k, value_only=True) for k in range(G.radius() + 1)] # needs sage.numerical.mip [5, 2, 1] """ dom = next(dominating_sets(g, k=k, independent=independent, total=total, diff --git a/src/sage/graphs/dot2tex_utils.py b/src/sage/graphs/dot2tex_utils.py index 95850012885..ce2cd873c8b 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]])) # optional - sage.modules + sage: sage.graphs.dot2tex_utils.quoted_latex(matrix([[1,1],[0,1],[0,0]])) # needs 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]])) # optional - sage.modules + sage: sage.graphs.dot2tex_utils.quoted_str(matrix([[1,1],[0,1],[0,0]])) # needs 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]]))) # optional - sage.modules + sage: print(sage.graphs.dot2tex_utils.quoted_str(matrix([[1,1],[0,1],[0,0]]))) # needs 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 c4cf6a4f81b..02326437a54 100644 --- a/src/sage/graphs/edge_connectivity.pyx +++ b/src/sage/graphs/edge_connectivity.pyx @@ -56,10 +56,10 @@ 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)) # optional - networkx - sage: while not D.is_strongly_connected(): # optional - networkx + sage: D = DiGraph(graphs.RandomRegular(6, 50)) # needs networkx + sage: while not D.is_strongly_connected(): # needs networkx ....: D = DiGraph(graphs.RandomRegular(6, 50)) - sage: GabowEdgeConnectivity(D).edge_connectivity() # optional - networkx + sage: GabowEdgeConnectivity(D).edge_connectivity() # needs networkx 6 A complete digraph with `n` vertices is `n-1`-edge-connected:: @@ -72,15 +72,16 @@ cdef class GabowEdgeConnectivity: 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) # optional - networkx - sage: D = DiGraph(G) # optional - networkx - sage: ec1 = GabowEdgeConnectivity(D, # optional - networkx + sage: # needs networkx + sage: G = graphs.RandomBarabasiAlbert(100, 2) + sage: D = DiGraph(G) + sage: ec1 = GabowEdgeConnectivity(D, ....: dfs_preprocessing=False).edge_connectivity() - sage: ec2 = GabowEdgeConnectivity(D, # optional - networkx + sage: ec2 = GabowEdgeConnectivity(D, ....: dfs_preprocessing=True).edge_connectivity() - sage: ec3 = GabowEdgeConnectivity(D, dfs_preprocessing=True, # optional - networkx + sage: ec3 = GabowEdgeConnectivity(D, dfs_preprocessing=True, ....: use_rec=True).edge_connectivity() - sage: ec1 == ec2 and ec2 == ec3 # optional - networkx + sage: ec1 == ec2 and ec2 == ec3 True TESTS: diff --git a/src/sage/graphs/generators/basic.py b/src/sage/graphs/generators/basic.py index 43e0b683703..89555fec008 100644 --- a/src/sage/graphs/generators/basic.py +++ b/src/sage/graphs/generators/basic.py @@ -179,13 +179,13 @@ def CircularLadderGraph(n): sage: for i in range(9): ....: k = graphs.CircularLadderGraph(i+3) ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs 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) # needs sage.plot + sage: G.show() # long time # needs sage.plot """ G = Graph(2 * n, name="Circular Ladder graph") G._circle_embedding(list(range(n)), radius=1, angle=pi/2) @@ -248,12 +248,13 @@ def CycleGraph(n): Compare plotting using the predefined layout and networkx:: - sage: import networkx # optional - networkx - sage: n = networkx.cycle_graph(23) # optional - networkx - sage: spring23 = Graph(n) # optional - networkx - sage: posdict23 = graphs.CycleGraph(23) # optional - networkx - sage: spring23.show() # long time # optional - networkx - sage: posdict23.show() # long time # optional - networkx + sage: # needs networkx + sage: import networkx + sage: n = networkx.cycle_graph(23) + sage: spring23 = Graph(n) + sage: posdict23 = graphs.CycleGraph(23) + sage: spring23.show() # long time + sage: posdict23.show() # long time We next view many cycle graphs as a Sage graphics array. First we use the ``CycleGraph`` constructor, which fills in the position dictionary:: @@ -263,29 +264,29 @@ def CycleGraph(n): sage: for i in range(9): ....: k = graphs.CycleGraph(i+3) ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs 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) # needs sage.plot + sage: G.show() # long time # needs sage.plot Compare to plotting with the spring-layout algorithm:: sage: g = [] sage: j = [] - sage: for i in range(9): # optional - networkx + sage: for i in range(9): # needs networkx ....: spr = networkx.cycle_graph(i+3) ....: k = Graph(spr) ....: g.append(k) - sage: for i in range(3): # optional - networkx sage.plot + sage: for i in range(3): # needs 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 - networkx sage.plot - sage: G.show() # long time # optional - networkx sage.plot + sage: G = graphics_array(j) # needs networkx sage.plot + sage: G.show() # long time # needs networkx sage.plot TESTS: @@ -339,37 +340,37 @@ def CompleteGraph(n): sage: for i in range(9): ....: k = graphs.CompleteGraph(i+3) ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs 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) # needs sage.plot + sage: G.show() # long time # needs sage.plot We compare to plotting with the spring-layout algorithm:: - sage: import networkx # optional - networkx + sage: import networkx # needs networkx sage: g = [] sage: j = [] - sage: for i in range(9): # optional - networkx + sage: for i in range(9): # needs networkx ....: spr = networkx.complete_graph(i+3) ....: k = Graph(spr) ....: g.append(k) - sage: for i in range(3): # optional - networkx sage.plot + sage: for i in range(3): # needs 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 - networkx sage.plot - sage: G.show() # long time # optional - networkx sage.plot + sage: G = graphics_array(j) # needs networkx sage.plot + sage: G.show() # long time # needs networkx sage.plot Compare the constructors (results will vary):: - sage: import networkx # optional - networkx - sage: t = cputime() # optional - networkx - sage: n = networkx.complete_graph(389); spring389 = Graph(n) # optional - networkx - sage: cputime(t) # random # optional - networkx + sage: import networkx # needs networkx + sage: t = cputime() # needs networkx + sage: n = networkx.complete_graph(389); spring389 = Graph(n) # needs networkx + sage: cputime(t) # random # needs networkx 0.59203700000000126 sage: t = cputime() sage: posdict389 = graphs.CompleteGraph(389) @@ -378,12 +379,12 @@ def CompleteGraph(n): We compare plotting:: - sage: import networkx # optional - networkx - sage: n = networkx.complete_graph(23) # optional - networkx - sage: spring23 = Graph(n) # optional - networkx + sage: import networkx # needs networkx + sage: n = networkx.complete_graph(23) # needs networkx + sage: spring23 = Graph(n) # needs networkx sage: posdict23 = graphs.CompleteGraph(23) - sage: spring23.show() # long time # optional - networkx sage.plot - sage: posdict23.show() # long time # optional - sage.plot + sage: spring23.show() # long time # needs networkx sage.plot + sage: posdict23.show() # long time # needs sage.plot """ G = Graph(n, name="Complete graph") if n == 1: @@ -405,14 +406,14 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation): 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) # 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 + sage: CG1 = CorrelationGraph(data, 0.9, False) # needs numpy + sage: CG2 = CorrelationGraph(data, 0.9, True) # needs numpy + sage: CG3 = CorrelationGraph(data, 0.1, True) # needs numpy + sage: CG1.edges(sort=False) # needs numpy [(0, 0, None), (0, 1, None), (1, 1, None), (2, 2, None)] - sage: CG2.edges(sort=False) # optional - numpy + sage: CG2.edges(sort=False) # needs numpy [(0, 0, None), (0, 1, None), (1, 1, None), (2, 2, None)] - sage: CG3.edges(sort=False) # optional - numpy + sage: CG3.edges(sort=False) # needs numpy [(0, 0, None), (0, 1, None), (0, 2, None), (1, 1, None), (1, 2, None), (2, 2, None)] """ @@ -477,20 +478,20 @@ def CompleteBipartiteGraph(p, q, set_position=True): Two ways of constructing the complete bipartite graph, using different layout algorithms:: - sage: import networkx # optional - networkx - sage: n = networkx.complete_bipartite_graph(389, 157) # long time # optional - networkx - sage: spring_big = Graph(n) # long time # optional - networkx + sage: import networkx # needs networkx + sage: n = networkx.complete_bipartite_graph(389, 157) # long time # needs networkx + sage: spring_big = Graph(n) # long time # needs networkx sage: posdict_big = graphs.CompleteBipartiteGraph(389, 157) # long time Compare the plotting:: - sage: n = networkx.complete_bipartite_graph(11, 17) # optional - networkx - sage: spring_med = Graph(n) # optional - networkx + sage: n = networkx.complete_bipartite_graph(11, 17) # needs networkx + sage: spring_med = Graph(n) # needs networkx sage: posdict_med = graphs.CompleteBipartiteGraph(11, 17) Notice here how the spring-layout tends to center the nodes of `n1`:: - sage: spring_med.show() # long time # optional - networkx + sage: spring_med.show() # long time # needs networkx sage: posdict_med.show() # long time View many complete bipartite graphs with a Sage Graphics Array, with this @@ -501,29 +502,29 @@ def CompleteBipartiteGraph(p, q, set_position=True): sage: for i in range(9): ....: k = graphs.CompleteBipartiteGraph(i+1,4) ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs 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) # needs sage.plot + sage: G.show() # long time # needs sage.plot We compare to plotting with the spring-layout algorithm:: sage: g = [] sage: j = [] - sage: for i in range(9): # optional - networkx + sage: for i in range(9): # needs networkx ....: spr = networkx.complete_bipartite_graph(i+1,4) ....: k = Graph(spr) ....: g.append(k) - sage: for i in range(3): # optional - networkx sage.plot + sage: for i in range(3): # needs 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 - networkx sage.plot - sage: G.show() # long time # optional - networkx sage.plot + sage: G = graphics_array(j) # needs networkx sage.plot + sage: G.show() # long time # needs networkx sage.plot :trac:`12155`:: @@ -825,13 +826,13 @@ def Toroidal6RegularGrid2dGraph(p, q): sage: g = graphs.Toroidal6RegularGrid2dGraph(5,5) sage: g.is_regular(k=6) True - sage: g.is_vertex_transitive() # optional - sage.groups + sage: g.is_vertex_transitive() # needs sage.groups True - sage: g.line_graph().is_vertex_transitive() # optional - sage.groups + sage: g.line_graph().is_vertex_transitive() # needs sage.groups True - sage: g.automorphism_group().cardinality() # optional - sage.groups + sage: g.automorphism_group().cardinality() # needs sage.groups 300 - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # needs sage.numerical.mip True TESTS: @@ -973,9 +974,9 @@ def GridGraph(dim_list): sage: dim = [randint(1,4) for i in range(4)] sage: g = graphs.GridGraph(dim) - sage: import networkx # optional - networkx - sage: h = Graph(networkx.grid_graph(list(dim))) # optional - networkx - sage: g.is_isomorphic(h) # optional - networkx + sage: import networkx # needs networkx + sage: h = Graph(networkx.grid_graph(list(dim))) # needs networkx + sage: g.is_isomorphic(h) # needs networkx True Trivial cases:: @@ -1115,13 +1116,13 @@ def LadderGraph(n): sage: for i in range(9): ....: k = graphs.LadderGraph(i+2) ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs 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) # needs sage.plot + sage: G.show() # long time # needs sage.plot """ pos_dict = {} for i in range(n): @@ -1263,14 +1264,14 @@ def StarGraph(n): EXAMPLES:: - sage: import networkx # optional - networkx + sage: import networkx # needs networkx Compare the plots:: - sage: n = networkx.star_graph(23) # optional - networkx - sage: spring23 = Graph(n) # optional - networkx + sage: n = networkx.star_graph(23) # needs networkx + sage: spring23 = Graph(n) # needs networkx sage: posdict23 = graphs.StarGraph(23) - sage: spring23.show() # long time # optional - networkx + sage: spring23.show() # long time # needs networkx sage: posdict23.show() # long time View many star graphs as a Sage Graphics Array @@ -1284,13 +1285,13 @@ def StarGraph(n): sage: for i in range(9): ....: k = graphs.StarGraph(i+3) ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs 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) # needs sage.plot + sage: G.show() # long time # needs sage.plot Compared to plotting with the spring-layout algorithm @@ -1298,17 +1299,17 @@ def StarGraph(n): sage: g = [] sage: j = [] - sage: for i in range(9): # optional - networkx + sage: for i in range(9): # needs networkx ....: spr = networkx.star_graph(i+3) ....: k = Graph(spr) ....: g.append(k) - sage: for i in range(3): # optional - networkx sage.plot + sage: for i in range(3): # needs 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 - networkx sage.plot - sage: G.show() # long time # optional - networkx sage.plot + sage: G = graphics_array(j) # needs networkx sage.plot + sage: G.show() # long time # needs networkx sage.plot """ G = Graph({0: list(range(1, n + 1))}, name="Star graph", format="dict_of_lists") G.set_pos({0: (0, 0)}) diff --git a/src/sage/graphs/generators/chessboard.py b/src/sage/graphs/generators/chessboard.py index 2835fbe987f..59517d128bb 100644 --- a/src/sage/graphs/generators/chessboard.py +++ b/src/sage/graphs/generators/chessboard.py @@ -414,7 +414,7 @@ def KnightGraph(dim_list, one=1, two=2, relabel=False): The `(6,6)`-Knight Graph is Hamiltonian:: sage: G = graphs.KnightGraph( [6, 6] ) - sage: G.is_hamiltonian() + sage: G.is_hamiltonian() # needs sage.numerical.mip True """ G, dimstr = ChessboardGraphGenerator(dim_list, diff --git a/src/sage/graphs/generators/classical_geometries.py b/src/sage/graphs/generators/classical_geometries.py index 7ef70020a14..48481b3b240 100644 --- a/src/sage/graphs/generators/classical_geometries.py +++ b/src/sage/graphs/generators/classical_geometries.py @@ -67,8 +67,14 @@ def SymplecticPolarGraph(d, q, algorithm=None): (40, 12, 2, 4) sage: O.is_isomorphic(G) False - sage: S = graphs.SymplecticPolarGraph(6, 4, algorithm="gap") # not tested (long time) - sage: S.is_strongly_regular(parameters=True) # not tested (long time) + sage: O.is_isomorphic(G) # optional - GOT (with --distribution 'sagemath-graphs[modules]') + Traceback (most recent call last): + ... + File "", line 1, in + O.is_isomorphic(G) + AttributeError: 'function' object has no attribute 'is_isomorphic' + sage: S = graphs.SymplecticPolarGraph(6,4,algorithm="gap") # not tested (long time), needs sage.libs.gap + sage: S.is_strongly_regular(parameters=True) # not tested (long time) # needs sage.libs.gap (1365, 340, 83, 85) TESTS:: @@ -481,18 +487,18 @@ def NonisotropicOrthogonalPolarGraph(m, q, sign="+", perp=None): NO^-,perp(3, 5): Graph on 10 vertices sage: g.is_strongly_regular(parameters=True) (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, needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time # needs sage.libs.gap (117, 36, 15, 9) sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'-'); g # long time 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 # needs 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, needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time # needs 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, needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time # needs sage.libs.gap (325, 144, 68, 60) sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,4,'+') Traceback (most recent call last): @@ -865,8 +871,8 @@ def TaylorTwographDescendantSRG(q, clique_partition=False): sage: g.is_strongly_regular(parameters=True) (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 # needs sage.rings.finite_rings + sage: g.is_isomorphic(T.descendant(T.ground_set()[1])) # long time # needs 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) @@ -1192,7 +1198,7 @@ def HaemersGraph(q, hyperoval=None, hyperoval_matching=None, field=None, check_h ... RuntimeError: incorrect hyperoval - sage: g = graphs.HaemersGraph(8); g # not tested (long time) # needs sage.rings.finite_rings + sage: g = graphs.HaemersGraph(8); g # not tested (long time) # needs sage.rings.finite_rings Haemers(8): Graph on 640 vertices sage: g.is_strongly_regular(parameters=True) # not tested (long time) # needs sage.rings.finite_rings (640, 71, 6, 8) diff --git a/src/sage/graphs/generators/degree_sequence.py b/src/sage/graphs/generators/degree_sequence.py index 071878d124e..ed89ce43abc 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]) # optional - networkx - sage: G.edges(sort=True, labels=False) # optional - networkx + sage: G = graphs.DegreeSequence([3,3,3,3]) # needs networkx + sage: G.edges(sort=True, labels=False) # needs networkx [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] - sage: G.show() # long time # optional - networkx sage.plot + sage: G.show() # long time # needs 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]) # optional - networkx - 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]) # needs networkx + sage: G.show() # long time # needs networkx sage.plot :: - 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([4,4,4,4,4,4,4,4]) # needs networkx + sage: G.show() # long time # needs networkx sage.plot :: - 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 + sage: G = graphs.DegreeSequence([1,2,3,4,3,4,3,2,3,2,1]) # needs networkx + sage: G.show() # long time # needs 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]) # optional - sage.modules - sage: g.is_isomorphic(graphs.CompleteBipartiteGraph(5,2)) # optional - sage.modules + sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]) # needs sage.modules + sage: g.is_isomorphic(graphs.CompleteBipartiteGraph(5,2)) # needs 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]) # optional - sage.modules + sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,1],[5,5]) # needs 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() # optional - sage.modules + sage: graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]).complement() # needs sage.modules Graph on 7 vertices """ from sage.combinat.integer_vector import gale_ryser_theorem @@ -147,20 +147,21 @@ def DegreeSequenceConfigurationModel(deg_sequence, seed=None): EXAMPLES:: - sage: G = graphs.DegreeSequenceConfigurationModel([1,1]) # optional - networkx - sage: G.adjacency_matrix() # optional - networkx sage.modules + sage: G = graphs.DegreeSequenceConfigurationModel([1,1]) # needs networkx + sage: G.adjacency_matrix() # needs 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] # optional - networkx - sage: G = graphs.DegreeSequenceConfigurationModel(deg_sequence) # optional - networkx - sage: G.order(), G.size() # optional - networkx + sage: # needs networkx + 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() (20, 30) - sage: G.has_loops() or G.has_multiple_edges() # random # optional - networkx + sage: G.has_loops() or G.has_multiple_edges() # random True - sage: G.show() # long time # optional - networkx sage.plot + sage: G.show() # long time # needs sage.plot REFERENCE: @@ -191,9 +192,9 @@ def DegreeSequenceTree(deg_sequence): EXAMPLES:: - sage: G = graphs.DegreeSequenceTree([3,1,3,3,1,1,1,2,1]); G # optional - networkx + sage: G = graphs.DegreeSequenceTree([3,1,3,3,1,1,1,2,1]); G # needs networkx Graph on 9 vertices - sage: G.show() # long time # optional - networkx sage.plot + sage: G.show() # long time # needs networkx sage.plot """ import networkx return Graph(networkx.degree_sequence_tree([int(i) for i in deg_sequence])) @@ -219,9 +220,9 @@ def DegreeSequenceExpected(deg_sequence, seed=None): EXAMPLES:: - sage: G = graphs.DegreeSequenceExpected([1,2,3,2,3]); G # optional - networkx + sage: G = graphs.DegreeSequenceExpected([1,2,3,2,3]); G # needs networkx Looped graph on 5 vertices - sage: G.show() # long time # optional - networkx sage.plot + sage: G.show() # long time # needs networkx sage.plot REFERENCE: diff --git a/src/sage/graphs/generators/distance_regular.pyx b/src/sage/graphs/generators/distance_regular.pyx index dd809a835af..edcb9ad4cfa 100644 --- a/src/sage/graphs/generators/distance_regular.pyx +++ b/src/sage/graphs/generators/distance_regular.pyx @@ -132,8 +132,8 @@ def ConwaySmith_for_3S7(): EXAMPLES:: - sage: G = graphs.ConwaySmith_for_3S7() - sage: G.is_distance_regular(True) + sage: G = graphs.ConwaySmith_for_3S7() # needs sage.modules sage.rings.finite_rings sage.rings.number_field + sage: G.is_distance_regular(True) # needs sage.modules sage.rings.finite_rings sage.rings.number_field ([10, 6, 4, 1, None], [None, 1, 2, 6, 10]) REFERENCES: @@ -243,8 +243,8 @@ def FosterGraph3S6(): EXAMPLES:: - sage: G = graphs.FosterGraph3S6() - sage: G.is_distance_regular(True) + sage: G = graphs.FosterGraph3S6() # needs sage.libs.gap + sage: G.is_distance_regular(True) # needs sage.libs.gap ([6, 4, 2, 1, None], [None, 1, 1, 4, 6]) REFERENCES: @@ -321,8 +321,8 @@ def LargeWittGraph(): EXAMPLES:: - sage: g = graphs.LargeWittGraph() - sage: g.is_distance_regular(True) + sage: g = graphs.LargeWittGraph() # needs sage.modules + sage: g.is_distance_regular(True) # needs sage.modules ([30, 28, 24, None], [None, 1, 3, 15]) REFERENCES: @@ -359,8 +359,8 @@ def TruncatedWittGraph(): EXAMPLES:: - sage: G = graphs.TruncatedWittGraph() # long time - sage: G.is_distance_regular(True) # long time (due to above) + sage: G = graphs.TruncatedWittGraph() # long time # needs sage.modules + sage: G.is_distance_regular(True) # long time (due to above) # needs sage.modules ([15, 14, 12, None], [None, 1, 1, 9]) REFERENCES: @@ -388,8 +388,8 @@ def DoublyTruncatedWittGraph(): EXAMPLES:: - sage: G = graphs.DoublyTruncatedWittGraph() - sage: G.is_distance_regular(True) + sage: G = graphs.DoublyTruncatedWittGraph() # needs sage.modules + sage: G.is_distance_regular(True) # needs sage.modules ([7, 6, 4, 4, None], [None, 1, 1, 1, 6]) REFERENCES: @@ -411,8 +411,8 @@ def distance_3_doubly_truncated_Golay_code_graph(): EXAMPLES:: - sage: G = graphs.distance_3_doubly_truncated_Golay_code_graph() # long time - sage: G.is_distance_regular(True) # long time (due to above) + sage: G = graphs.distance_3_doubly_truncated_Golay_code_graph() # long time, needs sage.modules sage.rings.finite_rings + sage: G.is_distance_regular(True) # long time (due to above) # needs sage.modules sage.rings.finite_rings ([9, 8, 6, 3, None], [None, 1, 1, 3, 8]) ALGORITHM: @@ -446,8 +446,8 @@ def shortened_00_11_binary_Golay_code_graph(): EXAMPLES:: - sage: G = graphs.shortened_00_11_binary_Golay_code_graph() # long time (9 s) - sage: G.is_distance_regular(True) # long time + sage: G = graphs.shortened_00_11_binary_Golay_code_graph() # long time (9 s), needs sage.modules sage.rings.finite_rings + sage: G.is_distance_regular(True) # long time # needs sage.modules sage.rings.finite_rings ([21, 20, 16, 6, 2, 1, None], [None, 1, 2, 6, 16, 20, 21]) ALGORITHM: @@ -485,8 +485,8 @@ def shortened_000_111_extended_binary_Golay_code_graph(): EXAMPLES:: - sage: G = graphs.shortened_000_111_extended_binary_Golay_code_graph() # long time (25 s) - sage: G.is_distance_regular(True) # long time + sage: G = graphs.shortened_000_111_extended_binary_Golay_code_graph() # long time (25 s), needs sage.modules sage.rings.finite_rings + sage: G.is_distance_regular(True) # long time # needs sage.modules sage.rings.finite_rings ([21, 20, 16, 9, 2, 1, None], [None, 1, 2, 3, 16, 20, 21]) ALGORITHM: @@ -526,8 +526,8 @@ def vanLintSchrijverGraph(): EXAMPLES:: - sage: G = graphs.vanLintSchrijverGraph() - sage: G.is_distance_regular(True) + sage: G = graphs.vanLintSchrijverGraph() # needs sage.modules + sage: G.is_distance_regular(True) # needs sage.modules ([6, 5, 5, 4, None], [None, 1, 1, 2, 6]) REFERENCES: @@ -557,8 +557,8 @@ def LeonardGraph(): EXAMPLES:: - sage: G = graphs.LeonardGraph() - sage: G.is_distance_regular(True) + sage: G = graphs.LeonardGraph() # needs sage.combinat sage.modules + sage: G.is_distance_regular(True) # needs sage.combinat sage.modules ([12, 11, 10, 7, None], [None, 1, 2, 5, 12]) REFERENCES: @@ -597,8 +597,8 @@ def UstimenkoGraph(const int m, const int q): EXAMPLES:: - sage: G = graphs.UstimenkoGraph(4, 2) - sage: G.is_distance_regular(True) + sage: G = graphs.UstimenkoGraph(4, 2) # needs sage.libs.gap + sage: G.is_distance_regular(True) # needs sage.libs.gap ([70, 32, None], [None, 1, 35]) REFERENCES: @@ -607,13 +607,14 @@ def UstimenkoGraph(const int m, const int q): TESTS:: - sage: G = graphs.UstimenkoGraph(5, 2) # long time - sage: G.order() # long time + sage: # long time, needs sage.libs.gap + sage: G = graphs.UstimenkoGraph(5, 2) + sage: G.order() 2295 - sage: G.is_distance_regular(True) # long time + sage: G.is_distance_regular(True) ([310, 224, None], [None, 1, 35]) - sage: G = graphs.UstimenkoGraph(4,3) # long time - sage: G.is_distance_regular(True) # long time + sage: G = graphs.UstimenkoGraph(4,3) + sage: G.is_distance_regular(True) ([390, 243, None], [None, 1, 130]) """ from sage.graphs.graph_generators import graphs @@ -652,14 +653,15 @@ def BilinearFormsGraph(const int d, const int e, const int q): EXAMPLES:: + sage: # needs sage.modules sage: G = graphs.BilinearFormsGraph(3, 3, 2) sage: G.is_distance_regular(True) ([49, 36, 16, None], [None, 1, 6, 28]) - sage: G = graphs.BilinearFormsGraph(3,3,3) # not tested (20 s) - sage: G.order() # not tested (due to above) + sage: G = graphs.BilinearFormsGraph(3,3,3) # not tested (20 s) # needs sage.rings.finite_rings + sage: G.order() # not tested (due to above) # needs sage.rings.finite_rings 19683 - sage: G = graphs.BilinearFormsGraph(3, 4, 2) # long time - sage: G.is_distance_regular(True) # long time + sage: G = graphs.BilinearFormsGraph(3, 4, 2) # long time # needs sage.rings.finite_rings + sage: G.is_distance_regular(True) # long time # needs sage.rings.finite_rings ([105, 84, 48, None], [None, 1, 6, 28]) REFERENCES: @@ -669,6 +671,7 @@ def BilinearFormsGraph(const int d, const int e, const int q): TESTS:: + sage: # needs sage.modules sage: G = graphs.BilinearFormsGraph(2,3,2) sage: G.is_distance_regular(True) ([21, 12, None], [None, 1, 6]) @@ -754,10 +757,11 @@ def AlternatingFormsGraph(const int n, const int q): TESTS:: - sage: G = graphs.AlternatingFormsGraph(6,2) # not tested (2 min) - sage: G.order() # not tested (because of above) + sage: # needs sage.modules + sage: G = graphs.AlternatingFormsGraph(6,2) # not tested (2 min) # needs sage.rings.finite_rings + sage: G.order() # not tested (because of above) # needs sage.rings.finite_rings 32768 - sage: G.is_distance_regular(True) # not tested (33 min) + sage: G.is_distance_regular(True) # not tested (33 min) # needs sage.rings.finite_rings ([651, 560, 256, None], [None, 1, 20, 336]) sage: G = graphs.AlternatingFormsGraph(4, 3) sage: G.is_distance_regular(True) @@ -840,11 +844,12 @@ def HermitianFormsGraph(const int n, const int r): EXAMPLES:: + sage: # needs sage.modules sage.rings.finite_rings sage: G = graphs.HermitianFormsGraph(2, 2) sage: G.is_distance_regular(True) ([5, 4, None], [None, 1, 2]) - sage: G = graphs.HermitianFormsGraph(3, 3) # not tested (2 min) - sage: G.order() # not tested (bacuase of the above) + sage: G = graphs.HermitianFormsGraph(3, 3) # not tested (2 min) + sage: G.order() # not tested (bacuase of the above) 19683 REFERENCES: @@ -853,6 +858,7 @@ def HermitianFormsGraph(const int n, const int r): TESTS:: + sage: # needs sage.modules sage.rings.finite_rings sage: G = graphs.HermitianFormsGraph(3, 2) sage: G.is_distance_regular(True) ([21, 20, 16, None], [None, 1, 2, 12]) @@ -1079,8 +1085,8 @@ def GrassmannGraph(const int q, const int n, const int input_e): EXAMPLES:: - sage: G = graphs.GrassmannGraph(2, 4, 2) - sage: G.is_distance_regular(True) + sage: G = graphs.GrassmannGraph(2, 4, 2) # needs sage.modules sage.rings.finite_rings + sage: G.is_distance_regular(True) # needs sage.modules sage.rings.finite_rings ([18, 8, None], [None, 1, 9]) REFERENCES: @@ -1089,8 +1095,9 @@ def GrassmannGraph(const int q, const int n, const int input_e): TESTS:: - sage: G = graphs.GrassmannGraph(2, 6, 3) # long time - sage: G.is_distance_regular(True) # long time + sage: # needs sage.modules sage.rings.finite_rings + sage: G = graphs.GrassmannGraph(2, 6, 3) # long time + sage: G.is_distance_regular(True) # long time ([98, 72, 32, None], [None, 1, 9, 49]) sage: G = graphs.GrassmannGraph(3, 4, 2) sage: G.is_distance_regular(True) @@ -1132,10 +1139,10 @@ def DoubleGrassmannGraph(const int q, const int e): EXAMPLES:: - sage: G = graphs.DoubleGrassmannGraph(2,1) - sage: G.diameter() + sage: G = graphs.DoubleGrassmannGraph(2,1) # needs sage.modules + sage: G.diameter() # needs sage.modules 3 - sage: G.is_distance_regular(True) + sage: G.is_distance_regular(True) # needs sage.modules ([3, 2, 2, None], [None, 1, 1, 3]) @@ -1145,15 +1152,16 @@ def DoubleGrassmannGraph(const int q, const int e): TESTS:: + sage: # needs sage.modules sage: G = graphs.DoubleGrassmannGraph(5,1) sage: G.order() 62 sage: G.is_distance_regular(True) ([6, 5, 5, None], [None, 1, 1, 6]) - sage: G = graphs.DoubleGrassmannGraph(3, 2) # long time - sage: G.order() # long time + sage: G = graphs.DoubleGrassmannGraph(3, 2) # long time # needs sage.rings.finite_rings + sage: G.order() # long time # needs sage.rings.finite_rings 2420 - sage: G.is_distance_regular(True) # long time + sage: G.is_distance_regular(True) # long time # needs sage.rings.finite_rings ([13, 12, 12, 9, 9, None], [None, 1, 1, 4, 4, 13]) """ n = 2*e + 1 @@ -1187,10 +1195,10 @@ def is_from_GQ_spread(list arr): sage: from sage.graphs.generators.distance_regular import \ ....: is_from_GQ_spread, graph_from_GQ_spread - sage: is_from_GQ_spread([125, 120, 1, 1, 24, 125]) + sage: is_from_GQ_spread([125, 120, 1, 1, 24, 125]) # needs sage.libs.pari (5, 25) - sage: G = graph_from_GQ_spread(5, 25) - sage: G.is_distance_regular(True) + sage: G = graph_from_GQ_spread(5, 25) # needs sage.libs.pari + sage: G.is_distance_regular(True) # needs sage.libs.pari ([125, 120, 1, None], [None, 1, 24, 125]) REFERENCES: @@ -1202,9 +1210,9 @@ def is_from_GQ_spread(list arr): sage: from sage.graphs.generators.distance_regular import \ ....: is_from_GQ_spread - sage: is_from_GQ_spread([343, 336, 1, 1, 48, 343]) + sage: is_from_GQ_spread([343, 336, 1, 1, 48, 343]) # needs sage.libs.pari (7, 49) - sage: is_from_GQ_spread([343, 336, 1, 2, 48, 343]) + sage: is_from_GQ_spread([343, 336, 1, 2, 48, 343]) # needs sage.libs.pari False Check that we don't get ``True`` for inexisting GQs:: @@ -1215,7 +1223,7 @@ def is_from_GQ_spread(list arr): sage: t = 6 sage: [s * t, s * (t-1), 1, 1, t - 1, s * t] [30, 25, 1, 1, 5, 30] - sage: is_from_GQ_spread([30, 25, 1, 1, 5, 30]) + sage: is_from_GQ_spread([30, 25, 1, 1, 5, 30]) # needs sage.libs.pari False """ from sage.combinat.designs import design_catalog as designs @@ -1258,8 +1266,8 @@ def graph_from_GQ_spread(const int s, const int t): sage: from sage.graphs.generators.distance_regular import \ ....: graph_from_GQ_spread - sage: G = graph_from_GQ_spread(4, 16) - sage: G.is_distance_regular(True) + sage: G = graph_from_GQ_spread(4, 16) # needs sage.libs.pari + sage: G.is_distance_regular(True) # needs sage.libs.pari ([64, 60, 1, None], [None, 1, 15, 64]) REFERENCES: @@ -1270,11 +1278,11 @@ def graph_from_GQ_spread(const int s, const int t): sage: from sage.graphs.generators.distance_regular import \ ....: graph_from_GQ_spread, is_from_GQ_spread - sage: is_from_GQ_spread([64, 60, 1, 1, 15, 64]) + sage: is_from_GQ_spread([64, 60, 1, 1, 15, 64]) # needs sage.libs.pari (4, 16) - sage: graph_from_GQ_spread(*is_from_GQ_spread([27, 24, 1, 1, 8, 27])) + sage: graph_from_GQ_spread(*is_from_GQ_spread([27, 24, 1, 1, 8, 27])) # needs sage.libs.pari Graph on 112 vertices - sage: _.is_distance_regular(True) + sage: _.is_distance_regular(True) # needs sage.libs.pari ([27, 24, 1, None], [None, 1, 8, 27]) """ from sage.combinat.designs import design_catalog as designs @@ -1302,13 +1310,14 @@ def GeneralisedDodecagonGraph(const int s, const int t): EXAMPLES:: - sage: G = graphs.GeneralisedDodecagonGraph(1, 5) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: # optional - gap_packages internet + sage: G = graphs.GeneralisedDodecagonGraph(1, 5) + sage: G.is_distance_regular(True) ([6, 5, 5, 5, 5, 5, None], [None, 1, 1, 1, 1, 1, 6]) - sage: H = graphs.GeneralisedDodecagonGraph(5, 1) # optional - gap_packages internet - sage: H.order() # optional - gap_packages internet + sage: H = graphs.GeneralisedDodecagonGraph(5, 1) + sage: H.order() 23436 - sage: H.is_distance_regular(True) # not tested (6 min); optional - gap_packages internet + sage: H.is_distance_regular(True) # not tested (6 min) ([10, 5, 5, 5, 5, 5, None], [None, 1, 1, 1, 1, 1, 2]) .. NOTE:: @@ -1326,29 +1335,31 @@ def GeneralisedDodecagonGraph(const int s, const int t): Test all graphs of order `(1, q)`:: - sage: G = graphs.GeneralisedDodecagonGraph(1, 4) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: # optional - gap_packages internet + sage: G = graphs.GeneralisedDodecagonGraph(1, 4) + sage: G.is_distance_regular(True) ([5, 4, 4, 4, 4, 4, None], [None, 1, 1, 1, 1, 1, 5]) - sage: G = graphs.GeneralisedDodecagonGraph(1, 3) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: G = graphs.GeneralisedDodecagonGraph(1, 3) + sage: G.is_distance_regular(True) ([4, 3, 3, 3, 3, 3, None], [None, 1, 1, 1, 1, 1, 4]) - sage: G = graphs.GeneralisedDodecagonGraph(1, 2) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: G = graphs.GeneralisedDodecagonGraph(1, 2) + sage: G.is_distance_regular(True) ([3, 2, 2, 2, 2, 2, None], [None, 1, 1, 1, 1, 1, 3]) - sage: G = graphs.GeneralisedDodecagonGraph(1, 1) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: G = graphs.GeneralisedDodecagonGraph(1, 1) + sage: G.is_distance_regular(True) ([2, 1, 1, 1, 1, 1, None], [None, 1, 1, 1, 1, 1, 2]) Now test all graphs of order `(q, 1)`:: - sage: G = graphs.GeneralisedDodecagonGraph(4, 1) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: # optional - gap_packages internet + sage: G = graphs.GeneralisedDodecagonGraph(4, 1) + sage: G.is_distance_regular(True) ([8, 4, 4, 4, 4, 4, None], [None, 1, 1, 1, 1, 1, 2]) - sage: G = graphs.GeneralisedDodecagonGraph(3, 1) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: G = graphs.GeneralisedDodecagonGraph(3, 1) + sage: G.is_distance_regular(True) ([6, 3, 3, 3, 3, 3, None], [None, 1, 1, 1, 1, 1, 2]) - sage: G = graphs.GeneralisedDodecagonGraph(2, 1) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: G = graphs.GeneralisedDodecagonGraph(2, 1) + sage: G.is_distance_regular(True) ([4, 2, 2, 2, 2, 2, None], [None, 1, 1, 1, 1, 1, 2]) """ from sage.arith.misc import is_prime_power @@ -1407,14 +1418,14 @@ def GeneralisedOctagonGraph(const int s, const int t): EXAMPLES:: - sage: G = graphs.GeneralisedOctagonGraph(1, 4) - sage: G.is_distance_regular(True) + sage: G = graphs.GeneralisedOctagonGraph(1, 4) # needs sage.libs.gap + sage: G.is_distance_regular(True) # needs sage.libs.gap ([5, 4, 4, 4, None], [None, 1, 1, 1, 5]) sage: G = graphs.GeneralisedOctagonGraph(2, 4) # optional - gap_packages internet sage: G.is_distance_regular(True) # optional - gap_packages internet ([10, 8, 8, 8, None], [None, 1, 1, 1, 5]) - sage: G = graphs.GeneralisedOctagonGraph(5, 1) - sage: G.is_distance_regular(True) + sage: G = graphs.GeneralisedOctagonGraph(5, 1) # needs sage.libs.gap + sage: G.is_distance_regular(True) # needs sage.libs.gap ([10, 5, 5, 5, None], [None, 1, 1, 1, 2]) .. NOTE:: @@ -1430,11 +1441,11 @@ def GeneralisedOctagonGraph(const int s, const int t): TESTS:: - sage: G = graphs.GeneralisedOctagonGraph(8, 64) + sage: G = graphs.GeneralisedOctagonGraph(8, 64) # needs sage.libs.gap Traceback (most recent call last): ... NotImplementedError: Graph would be too big - sage: G = graphs.GeneralisedOctagonGraph(4, 16) + sage: G = graphs.GeneralisedOctagonGraph(4, 16) # needs sage.libs.gap Traceback (most recent call last): ... ValueError: generalised octagons of order (q, q^2) are known only for odd powers q of 2 @@ -1520,10 +1531,10 @@ def GeneralisedHexagonGraph(const int s, const int t): sage: G = graphs.GeneralisedHexagonGraph(5, 5) # optional - gap_packages internet sage: G.is_distance_regular(True) # optional - gap_packages internet ([30, 25, 25, None], [None, 1, 1, 6]) - sage: G = graphs.GeneralisedHexagonGraph(7, 1) - sage: G.is_distance_regular(True) + sage: G = graphs.GeneralisedHexagonGraph(7, 1) # needs sage.libs.gap + sage: G.is_distance_regular(True) # needs sage.libs.gap ([14, 7, 7, None], [None, 1, 1, 2]) - sage: graphs.GeneralisedHexagonGraph(1, 1) + sage: graphs.GeneralisedHexagonGraph(1, 1) # needs sage.libs.gap Cycle graph: Graph on 6 vertices .. NOTE:: @@ -1539,17 +1550,18 @@ def GeneralisedHexagonGraph(const int s, const int t): TESTS:: - sage: G = graphs.GeneralisedHexagonGraph(4, 4) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: # optional - gap_packages internet + sage: G = graphs.GeneralisedHexagonGraph(4, 4) + sage: G.is_distance_regular(True) ([20, 16, 16, None], [None, 1, 1, 5]) - sage: G = graphs.GeneralisedHexagonGraph(3, 3) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: G = graphs.GeneralisedHexagonGraph(3, 3) + sage: G.is_distance_regular(True) ([12, 9, 9, None], [None, 1, 1, 4]) - sage: G = graphs.GeneralisedHexagonGraph(2, 2) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: G = graphs.GeneralisedHexagonGraph(2, 2) + sage: G.is_distance_regular(True) ([6, 4, 4, None], [None, 1, 1, 3]) - sage: G = graphs.GeneralisedHexagonGraph(2, 8) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet + sage: G = graphs.GeneralisedHexagonGraph(2, 8) + sage: G.is_distance_regular(True) ([18, 16, 16, None], [None, 1, 1, 9]) """ from sage.arith.misc import is_prime_power @@ -1672,6 +1684,7 @@ def _extract_lines(G): EXAMPLES:: + sage: # needs sage.libs.gap sage: from sage.graphs.generators.distance_regular import _extract_lines sage: G = graphs.GeneralisedHexagonGraph(1, 8) sage: lines = _extract_lines(G) @@ -1741,9 +1754,9 @@ def _line_graph_generalised_polygon(H): sage: from sage.graphs.generators.distance_regular import \ ....: _line_graph_generalised_polygon - sage: G = graphs.GeneralisedHexagonGraph(1, 8) - sage: H = _line_graph_generalised_polygon(G) - sage: H.is_distance_regular(True) + sage: G = graphs.GeneralisedHexagonGraph(1, 8) # needs sage.libs.gap + sage: H = _line_graph_generalised_polygon(G) # needs sage.libs.gap + sage: H.is_distance_regular(True) # needs sage.libs.gap ([16, 8, 8, None], [None, 1, 1, 2]) sage: G = graphs.GeneralisedHexagonGraph(3, 3) # optional - gap_packages internet sage: H = _line_graph_generalised_polygon(G) # optional - gap_packages internet @@ -1792,9 +1805,9 @@ def _intersection_array_from_graph(G): sage: from sage.graphs.generators.distance_regular import \ ....: _intersection_array_from_graph - sage: _intersection_array_from_graph(graphs.FosterGraph()) + sage: _intersection_array_from_graph(graphs.FosterGraph()) # needs networkx [3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3] - sage: graphs.FosterGraph().is_distance_regular(True) + sage: graphs.FosterGraph().is_distance_regular(True) # needs networkx ([3, 2, 2, 2, 2, 1, 1, 1, None], [None, 1, 1, 1, 1, 2, 2, 2, 3]) sage: graphs.DartGraph().is_distance_regular() False @@ -1877,7 +1890,7 @@ def is_classical_parameters_graph(list array): sage: G = graphs.HammingGraph(5, 4) sage: G.is_distance_regular(True) ([15, 12, 9, 6, 3, None], [None, 1, 2, 3, 4, 5]) - sage: is_classical_parameters_graph([15, 12, 9, 6, 3, 1, 2, 3, 4, 5]) + sage: is_classical_parameters_graph([15, 12, 9, 6, 3, 1, 2, 3, 4, 5]) # needs sage.combinat (5, 1, 0, 3, 2) REFERENCES: @@ -1890,12 +1903,12 @@ def is_classical_parameters_graph(list array): sage: from sage.graphs.generators.distance_regular import \ ....: is_classical_parameters_graph - sage: is_classical_parameters_graph([68, 64, 1, 17]) # srg not drg + sage: is_classical_parameters_graph([68, 64, 1, 17]) # srg not drg # needs sage.combinat False sage: G = graphs.GossetGraph() # sporadic classical parameters graph sage: G.is_distance_regular(True) ([27, 10, 1, None], [None, 1, 10, 27]) - sage: is_classical_parameters_graph([27, 10, 1, 1, 10, 27]) + sage: is_classical_parameters_graph([27, 10, 1, 1, 10, 27]) # needs sage.combinat False """ from sage.misc.functional import log @@ -2101,7 +2114,7 @@ def graph_with_classical_parameters(int d, int b, alpha_in, beta_in, int gamma): Hamming Graph with parameters 3,4: Graph on 64 vertices sage: G = _; G.is_distance_regular(True) ([9, 6, 3, None], [None, 1, 2, 3]) - sage: is_classical_parameters_graph([9, 6, 3, 1, 2, 3]) + sage: is_classical_parameters_graph([9, 6, 3, 1, 2, 3]) # needs sage.combinat (3, 1, 0, 3, 2) Two families of graphs are not implemented yet:: @@ -2125,7 +2138,7 @@ def graph_with_classical_parameters(int d, int b, alpha_in, beta_in, int gamma): sage: graph_with_classical_parameters(3, 1, 2, 3, 3) Half 4 Cube: Graph on 8 vertices - sage: graph_with_classical_parameters(3, 2, 0, 2, 9) + sage: graph_with_classical_parameters(3, 2, 0, 2, 9) # needs sage.libs.gap Symplectic Dual Polar Graph DSp(6, 2): Graph on 135 vertices sage: graph_with_classical_parameters(3, 2, 2, 14, 7) # long time Grassmann graph J_2(6, 3): Graph on 1395 vertices @@ -2389,7 +2402,7 @@ def is_near_polygon(array): sage: from sage.graphs.generators.distance_regular import ( ....: is_near_polygon, near_polygon_graph) - sage: is_near_polygon([7, 6, 6, 5, 5, 4, 1, 1, 2, 2, 3, 3]) + sage: is_near_polygon([7, 6, 6, 5, 5, 4, 1, 1, 2, 2, 3, 3]) # needs sage.combinat (2, 7) sage: near_polygon_graph(2, 7) Odd Graph with parameter 7: Graph on 1716 vertices @@ -2405,17 +2418,17 @@ def is_near_polygon(array): sage: from sage.graphs.generators.distance_regular import ( ....: is_near_polygon, near_polygon_graph) - sage: is_near_polygon([7, 6, 6, 4, 4, 1, 1, 3, 3, 7]) + sage: is_near_polygon([7, 6, 6, 4, 4, 1, 1, 3, 3, 7]) # needs sage.combinat sage.libs.pari (4, (2, 2)) sage: near_polygon_graph(4, (2, 2)) Double Grassmann graph (5, 2, 2): Graph on 310 vertices - sage: near_polygon_graph(*is_near_polygon([3, 2, 2, 1, 1, 3])) + sage: near_polygon_graph(*is_near_polygon([3, 2, 2, 1, 1, 3])) # needs sage.combinat sage.rings.finite_rings Generalised hexagon of order (1, 2): Graph on 14 vertices - sage: is_near_polygon([16, 12, 8, 4, 1, 2, 3, 4]) + sage: is_near_polygon([16, 12, 8, 4, 1, 2, 3, 4]) # needs sage.combinat sage.libs.pari (6, (4, 5)) - sage: is_near_polygon([]) + sage: is_near_polygon([]) # needs sage.combinat sage.libs.pari False - sage: is_near_polygon([25, 16, 9, 4, 1, 1, 4, 9, 16, 25]) # JohnsonGraph + sage: is_near_polygon([25, 16, 9, 4, 1, 1, 4, 9, 16, 25]) # JohnsonGraph # needs sage.combinat sage.libs.pari False """ from sage.arith.misc import is_prime_power @@ -2525,12 +2538,11 @@ def near_polygon_graph(family, params): EXAMPLES:: - sage: from sage.graphs.generators.distance_regular import ( - ....: is_near_polygon, near_polygon_graph) - sage: near_polygon_graph(*is_near_polygon([6, 5, 5, 4, 4, 3, 3, 2, 2, \ - ....: 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6])) + sage: from sage.graphs.generators.distance_regular import is_near_polygon, near_polygon_graph + sage: near_polygon_graph(*is_near_polygon( # needs sage.combinat + ....: [6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6])) Bipartite double of Odd graph on a set of 11 elements: Graph on 924 vertices - sage: G=_; G.is_distance_regular(True) + sage: G=_; G.is_distance_regular(True) # needs sage.combinat ([6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, None], [None, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6]) @@ -2541,6 +2553,7 @@ def near_polygon_graph(family, params): TESTS:: + sage: # needs sage.combinat sage: near_polygon_graph(12, 9) Traceback (most recent call last): ... @@ -2695,8 +2708,8 @@ def distance_regular_graph(list arr, existence=False, check=True): sage: graphs.distance_regular_graph([21,20,16,1,2,12], existence=True) True - sage: G = graphs.distance_regular_graph([12,11,10,7,1,2,5,12], check=False) - sage: G.is_distance_regular(True) + sage: G = graphs.distance_regular_graph([12,11,10,7,1,2,5,12], check=False) # needs sage.combinat sage.modules + sage: G.is_distance_regular(True) # needs sage.combinat sage.modules ([12, 11, 10, 7, None], [None, 1, 2, 5, 12]) REFERENCES: @@ -2705,7 +2718,7 @@ def distance_regular_graph(list arr, existence=False, check=True): TESTS:: - sage: graphs.distance_regular_graph([3, 2, 2, 1, 1, 1, 1, 2, 2, 3], + sage: graphs.distance_regular_graph([3, 2, 2, 1, 1, 1, 1, 2, 2, 3], # needs sage.combinat ....: existence=True) True sage: graphs.distance_regular_graph([3, 2, 2, 1, 2, 1, 1, 2, 2, 3], @@ -2713,14 +2726,14 @@ def distance_regular_graph(list arr, existence=False, check=True): False sage: graphs.distance_regular_graph([18, 16, 16, 1, 1, 9]) # optional - internet gap_packages Generalised hexagon of order (2, 8): Graph on 819 vertices - sage: graphs.distance_regular_graph([14, 12, 10, 8, 6, 4, 2, + sage: graphs.distance_regular_graph([14, 12, 10, 8, 6, 4, 2, # needs sage.combinat ....: 1, 2, 3, 4, 5, 6, 7]) Hamming Graph with parameters 7,3: Graph on 2187 vertices - sage: graphs.distance_regular_graph([66, 45, 28, 1, 6, 30]) + sage: graphs.distance_regular_graph([66, 45, 28, 1, 6, 30]) # needs sage.combinat Graph on 1024 vertices - sage: graphs.distance_regular_graph([6,5,5,5,1,1,1,6]) + sage: graphs.distance_regular_graph([6,5,5,5,1,1,1,6]) # needs sage.combinat Generalised octagon of order (1, 5): Graph on 312 vertices - sage: graphs.distance_regular_graph([64, 60, 1, 1, 15, 64], check=True) + sage: graphs.distance_regular_graph([64, 60, 1, 1, 15, 64], check=True) # needs sage.combinat Graph on 325 vertices """ from sage.misc.unknown import Unknown diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index 30396e1ab9e..dba8ec3d5c9 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -40,13 +40,13 @@ def JohnsonGraph(n, k): The Johnson graph is a Hamiltonian graph:: sage: g = graphs.JohnsonGraph(7, 3) - sage: g.is_hamiltonian() + sage: g.is_hamiltonian() # needs sage.numerical.mip True Every Johnson graph is vertex transitive:: sage: g = graphs.JohnsonGraph(6, 4) - sage: g.is_vertex_transitive() + sage: g.is_vertex_transitive() # needs sage.groups True The complement of the Johnson graph `J(n,2)` is isomorphic to the Kneser @@ -452,7 +452,7 @@ def HammingGraph(n, q, X=None): True sage: g.is_regular() True - sage: g.is_vertex_transitive() # optional - sage.groups + sage: g.is_vertex_transitive() # needs 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 # optional - networkx + sage: G = graphs.BalancedTree(2, 1); G # needs networkx Balanced tree: Graph on 3 vertices - sage: G.order(); G.size() # optional - networkx + sage: G.order(); G.size() # needs 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) # optional - networkx - sage: G.show() # long time # optional - networkx sage.plot + sage: G = graphs.BalancedTree(3, 5) # needs networkx + sage: G.show() # long time # needs 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) # optional - networkx - sage: T.is_bipartite() # optional - networkx + sage: T = graphs.BalancedTree(r, h) # needs networkx + sage: T.is_bipartite() # needs networkx True - sage: T.is_planar() # optional - networkx + sage: T.is_planar() # needs networkx True - sage: v = (r^(h + 1) - 1) / (r - 1) # optional - networkx - sage: T.order() == v # optional - networkx + sage: v = (r^(h + 1) - 1) / (r - 1) # needs networkx + sage: T.order() == v # needs networkx True - sage: T.size() == v - 1 # optional - networkx + sage: T.size() == v - 1 # needs 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) # optional - networkx + sage: graphs.BalancedTree(1, 10) # needs 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) # optional - networkx + sage: graphs.BalancedTree(3, 0) # needs 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) # 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 + sage: s_K = g.subgraph_search(K_n1, induced=True) # needs sage.modules + sage: s_P = g.subgraph_search(P_n2, induced=True) # needs sage.modules + sage: K_n1.is_isomorphic(s_K) # needs sage.modules True - sage: P_n2.is_isomorphic(s_P) # optional - sage.modules + sage: P_n2.is_isomorphic(s_P) # needs sage.modules True TESTS:: @@ -640,7 +640,7 @@ def BarbellGraph(n1, n2): sage: g = graphs.BarbellGraph(n1, n2) sage: g.num_verts() == 2 * n1 + n2 True - sage: g.num_edges() == 2 * binomial(n1, 2) + n2 + 1 + sage: g.num_edges() == 2 * binomial(n1, 2) + n2 + 1 # needs sage.symbolic True sage: g.is_connected() True @@ -717,7 +717,7 @@ def LollipopGraph(n1, n2): sage: g = graphs.LollipopGraph(n1, n2) sage: g.num_verts() == n1 + n2 True - sage: g.num_edges() == binomial(n1, 2) + n2 + sage: g.num_edges() == binomial(n1, 2) + n2 # needs sage.symbolic True sage: g.is_connected() True @@ -1027,10 +1027,10 @@ def 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 + sage: s = [K8.subgraph_search(c8).edges(sort=False), # needs 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 + sage: [T8.seidel_switching(x, inplace=False).is_isomorphic(G) # needs sage.modules ....: for x, G in zip(s, chang_graphs)] [True, True, True] @@ -1076,11 +1076,11 @@ def CirculantGraph(n, adjacency): EXAMPLES: Compare plotting using the predefined layout and networkx:: - sage: import networkx # optional - networkx - sage: n = networkx.cycle_graph(23) # optional - networkx - sage: spring23 = Graph(n) # optional - networkx + sage: import networkx # needs networkx + sage: n = networkx.cycle_graph(23) # needs networkx + sage: spring23 = Graph(n) # needs networkx sage: posdict23 = graphs.CirculantGraph(23,2) - sage: spring23.show() # long time # optional - networkx + sage: spring23.show() # long time # needs networkx sage: posdict23.show() # long time We next view many cycle graphs as a Sage graphics array. First we @@ -1092,29 +1092,29 @@ def CirculantGraph(n, adjacency): sage: for i in range(9): ....: k = graphs.CirculantGraph(i+4, i+1) ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs 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) # needs sage.plot + sage: G.show() # long time # needs sage.plot Compare to plotting with the spring-layout algorithm:: sage: g = [] sage: j = [] - sage: for i in range(9): # optional - networkx + sage: for i in range(9): # needs networkx ....: spr = networkx.cycle_graph(i+3) ....: k = Graph(spr) ....: g.append(k) - sage: for i in range(3): # optional - networkx sage.plot + sage: for i in range(3): # needs 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 - networkx sage.plot - sage: G.show() # long time # optional - networkx sage.plot + sage: G = graphics_array(j) # needs networkx sage.plot + sage: G.show() # long time # needs networkx sage.plot Passing a 1 into adjacency should give the cycle. @@ -1193,21 +1193,21 @@ def CubeGraph(n, embedding=1): ....: k = graphs.CubeGraph(i+1) ....: g.append(k) ... - sage: for i in range(2): # optional - sage.plot + sage: for i in range(2): # needs 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(figsize=[6,4]) # long time # optional - sage.plot + sage: G = graphics_array(j) # needs sage.plot + sage: G.show(figsize=[6,4]) # long time # needs sage.plot Use the plot options to display larger `n`-cubes:: sage: g = graphs.CubeGraph(9, embedding=1) - sage: g.show(figsize=[12,12],vertex_labels=False, vertex_size=20) # long time # optional - sage.plot + sage: g.show(figsize=[12,12],vertex_labels=False, vertex_size=20) # long time, needs sage.plot sage: g = graphs.CubeGraph(9, embedding=2) - sage: g.show(figsize=[12,12],vertex_labels=False, vertex_size=20) # long time # optional - sage.plot + sage: g.show(figsize=[12,12],vertex_labels=False, vertex_size=20) # long time, needs sage.plot AUTHORS: @@ -1306,9 +1306,9 @@ def GoethalsSeidelGraph(k, r): EXAMPLES:: - sage: graphs.GoethalsSeidelGraph(3,3) + sage: graphs.GoethalsSeidelGraph(3,3) # needs sage.modules Graph on 28 vertices - sage: graphs.GoethalsSeidelGraph(3,3).is_strongly_regular(parameters=True) + sage: graphs.GoethalsSeidelGraph(3,3).is_strongly_regular(parameters=True) # needs sage.modules (28, 15, 6, 10) """ from sage.combinat.designs.bibd import balanced_incomplete_block_design @@ -1353,8 +1353,8 @@ def DorogovtsevGoltsevMendesGraph(n): EXAMPLES:: - sage: G = graphs.DorogovtsevGoltsevMendesGraph(8) # optional - networkx - sage: G.size() # optional - networkx + sage: G = graphs.DorogovtsevGoltsevMendesGraph(8) # needs networkx + sage: G.size() # needs networkx 6561 REFERENCE: @@ -1442,20 +1442,20 @@ def FriendshipGraph(n): sage: for i in range(9): ....: g = graphs.FriendshipGraph(i + 1) ....: A.append(g) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs sage.plot ....: n = [] ....: for j in range(3): ....: n.append(A[3*i + j].plot(vertex_size=20, vertex_labels=False)) ....: B.append(n) - sage: G = graphics_array(B) # optional - sage.plot - sage: G.show() # long time # optional - sage.plot + sage: G = graphics_array(B) # needs sage.plot + sage: G.show() # long time # needs sage.plot For `n = 1`, the friendship graph `F_1` is isomorphic to the cycle graph `C_3`, whose visual representation is a triangle. :: sage: G = graphs.FriendshipGraph(1); G Friendship graph: Graph on 3 vertices - sage: G.show() # long time # optional - sage.plot + sage: G.show() # long time # needs sage.plot sage: G.is_isomorphic(graphs.CycleGraph(3)) True @@ -1538,7 +1538,7 @@ def FuzzyBallGraph(partition, q): EXAMPLES:: sage: F = graphs.FuzzyBallGraph([3,1],2) - sage: F.adjacency_matrix(vertices=list(F)) # optional - sage.modules + sage: F.adjacency_matrix(vertices=list(F)) # needs 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] @@ -1554,9 +1554,9 @@ def FuzzyBallGraph(partition, q): Laplacian:: sage: m = 4; q = 2; k = 2 - sage: g_list = [graphs.FuzzyBallGraph(p,q) # optional - sage.combinat sage.modules + sage: g_list = [graphs.FuzzyBallGraph(p,q) # needs 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 + sage: set(g.laplacian_matrix(normalized=True, # long time (7s on sage.math, 2011), needs 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 @@ -1588,15 +1588,15 @@ def FibonacciTree(n): EXAMPLES:: - sage: g = graphs.FibonacciTree(3) - sage: g.is_tree() + sage: g = graphs.FibonacciTree(3) # needs sage.libs.pari + sage: g.is_tree() # needs sage.libs.pari True :: - sage: l1 = [ len(graphs.FibonacciTree(_)) + 1 for _ in range(6) ] - sage: l2 = list(fibonacci_sequence(2,8)) - sage: l1 == l2 + sage: l1 = [ len(graphs.FibonacciTree(_)) + 1 for _ in range(6) ] # needs sage.libs.pari + sage: l2 = list(fibonacci_sequence(2,8)) # needs sage.libs.pari + sage: l1 == l2 # needs sage.libs.pari True AUTHORS: @@ -2074,15 +2074,15 @@ def HararyGraph(k, n): 9 sage: h.size() 23 - sage: h.vertex_connectivity() + sage: h.vertex_connectivity() # needs sage.numerical.mip 5 TESTS: Connectivity of some Harary graphs:: - sage: n=10 - sage: for k in range(2,n): + sage: n = 10 + sage: for k in range(2,n): # needs sage.numerical.mip ....: g = graphs.HararyGraph(k,n) ....: if k != g.vertex_connectivity(): ....: print("Connectivity of Harary graphs not satisfied.") @@ -2207,31 +2207,31 @@ def LCFGraph(n, shift_list, repeats): EXAMPLES:: - sage: G = graphs.LCFGraph(4, [2,-2], 2) # optional - networkx - sage: G.is_isomorphic(graphs.TetrahedralGraph()) # optional - networkx + sage: G = graphs.LCFGraph(4, [2,-2], 2) # needs networkx + sage: G.is_isomorphic(graphs.TetrahedralGraph()) # needs networkx True :: - 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 + sage: G = graphs.LCFGraph(20, [10,7,4,-4,-7,10,-4,7,-7,4], 2) # needs networkx + sage: G.is_isomorphic(graphs.DodecahedralGraph()) # needs networkx True :: - sage: G = graphs.LCFGraph(14, [5,-5], 7) # optional - networkx - sage: G.is_isomorphic(graphs.HeawoodGraph()) # optional - networkx + sage: G = graphs.LCFGraph(14, [5,-5], 7) # needs networkx + sage: G.is_isomorphic(graphs.HeawoodGraph()) # needs 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, # optional - networkx + sage: G = graphs.LCFGraph(20, [-10,-7,-5,4,7,-10,-7,-4,5,7, # needs networkx ....: -10,-7,6,-5,7,-10,-7,5,-6,7], 1) - sage: G.degree() # optional - networkx + sage: G.degree() # needs networkx [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3] - sage: G.diameter() # optional - networkx + sage: G.diameter() # needs networkx 3 - sage: G.show() # long time # optional - networkx sage.plot + sage: G.show() # long time # needs networkx sage.plot PLOTTING: LCF Graphs are plotted as an n-cycle with edges in the middle, as described above. @@ -2538,14 +2538,14 @@ def PaleyGraph(q): EXAMPLES:: - sage: G = graphs.PaleyGraph(9); G + sage: G = graphs.PaleyGraph(9); G # needs sage.rings.finite_rings Paley graph with parameter 9: Graph on 9 vertices - sage: G.is_regular() + sage: G.is_regular() # needs sage.rings.finite_rings True A Paley graph is always self-complementary:: - sage: G.is_self_complementary() + sage: G.is_self_complementary() # needs sage.rings.finite_rings True TESTS: @@ -2588,9 +2588,9 @@ def PasechnikGraph(n): EXAMPLES:: - sage: graphs.PasechnikGraph(4).is_strongly_regular(parameters=True) # optional - sage.combinat sage.modules + sage: graphs.PasechnikGraph(4).is_strongly_regular(parameters=True) # needs sage.combinat sage.modules (225, 98, 43, 42) - sage: graphs.PasechnikGraph(5).is_strongly_regular(parameters=True) # long time, optional - sage.combinat sage.modules + sage: graphs.PasechnikGraph(5).is_strongly_regular(parameters=True) # long time, needs sage.combinat sage.modules (361, 162, 73, 72) sage: graphs.PasechnikGraph(9).is_strongly_regular(parameters=True) # not tested (1225, 578, 273, 272) @@ -2630,11 +2630,14 @@ def SquaredSkewHadamardMatrixGraph(n): EXAMPLES:: - sage: graphs.SquaredSkewHadamardMatrixGraph(4).is_strongly_regular(parameters=True) + sage: G = graphs.SquaredSkewHadamardMatrixGraph(4) # needs sage.modules + sage: G.is_strongly_regular(parameters=True) # needs sage.modules (225, 112, 55, 56) - sage: graphs.SquaredSkewHadamardMatrixGraph(5).is_strongly_regular(parameters=True) # long time + sage: G = graphs.SquaredSkewHadamardMatrixGraph(5) # needs sage.modules + sage: G.is_strongly_regular(parameters=True) # long time # needs sage.modules (361, 180, 89, 90) - sage: graphs.SquaredSkewHadamardMatrixGraph(9).is_strongly_regular(parameters=True) # not tested + sage: G = graphs.SquaredSkewHadamardMatrixGraph(9) # needs sage.modules + sage: G.is_strongly_regular(parameters=True) # not tested # needs sage.modules (1225, 612, 305, 306) TESTS:: @@ -2680,13 +2683,14 @@ def SwitchedSquaredSkewHadamardMatrixGraph(n): EXAMPLES:: - sage: g=graphs.SwitchedSquaredSkewHadamardMatrixGraph(4) - sage: g.is_strongly_regular(parameters=True) + sage: g = graphs.SwitchedSquaredSkewHadamardMatrixGraph(4) # needs sage.modules + sage: g.is_strongly_regular(parameters=True) # needs sage.modules (226, 105, 48, 49) sage: from sage.combinat.designs.twographs import twograph_descendant - sage: twograph_descendant(g,0).is_strongly_regular(parameters=True) + sage: twograph_descendant(g, 0).is_strongly_regular(parameters=True) # needs sage.modules (225, 112, 55, 56) - sage: twograph_descendant(g.complement(),0).is_strongly_regular(parameters=True) + sage: gc = g.complement() # needs sage.modules + sage: twograph_descendant(gc, 0).is_strongly_regular(parameters=True) # needs sage.modules (225, 112, 55, 56) TESTS:: @@ -2817,7 +2821,7 @@ def HanoiTowerGraph(pegs, disks, labels=True, positions=True): :: sage: H = graphs.HanoiTowerGraph(3, 4, labels=False, positions=False) - sage: H.automorphism_group().is_isomorphic(SymmetricGroup(3)) # optional - sage.groups + sage: H.automorphism_group().is_isomorphic(SymmetricGroup(3)) # needs sage.groups True sage: H.chromatic_number() 3 @@ -3065,10 +3069,10 @@ def petersen_family(generate=False): The two different inputs generate the same graphs:: sage: F1 = graphs.petersen_family(generate=False) - sage: F2 = graphs.petersen_family(generate=True) + sage: F2 = graphs.petersen_family(generate=True) # needs sage.modules sage: F1 = [g.canonical_label().graph6_string() for g in F1] - sage: F2 = [g.canonical_label().graph6_string() for g in F2] - sage: set(F1) == set(F2) + sage: F2 = [g.canonical_label().graph6_string() for g in F2] # needs sage.modules + sage: set(F1) == set(F2) # needs sage.modules True """ from sage.graphs.generators.smallgraphs import PetersenGraph @@ -3183,13 +3187,13 @@ def SierpinskiGasketGraph(n): EXAMPLES:: - sage: s4 = graphs.SierpinskiGasketGraph(4); s4 + sage: s4 = graphs.SierpinskiGasketGraph(4); s4 # needs sage.modules Graph on 42 vertices - sage: s4.size() + sage: s4.size() # needs sage.modules 81 - sage: s4.degree_histogram() + sage: s4.degree_histogram() # needs sage.modules [0, 0, 3, 0, 39] - sage: s4.is_hamiltonian() + sage: s4.is_hamiltonian() # needs sage.modules True REFERENCES: @@ -3272,9 +3276,9 @@ def GeneralizedSierpinskiGraph(G, k, stretch=None): of `G` are isomorphic to Hanoi Tower graphs:: sage: k = randint(1, 5) - sage: S = graphs.GeneralizedSierpinskiGraph(graphs.CompleteGraph(3), k) + sage: S = graphs.GeneralizedSierpinskiGraph(graphs.CompleteGraph(3), k) # needs sage.modules sage: H = graphs.HanoiTowerGraph(3, k) - sage: S.is_isomorphic(H) + sage: S.is_isomorphic(H) # needs sage.modules True The generalized Sierpinski graph of dimension `k` of any graph `G` with `n` @@ -3284,16 +3288,16 @@ def GeneralizedSierpinskiGraph(G, k, stretch=None): sage: k = randint(1, 5) sage: G = graphs.RandomGNP(n, .5) sage: m = G.size() - sage: S = graphs.GeneralizedSierpinskiGraph(G, k) - sage: S.order() == n**k + sage: S = graphs.GeneralizedSierpinskiGraph(G, k) # needs sage.modules + sage: S.order() == n**k # needs sage.modules True - sage: S.size() == m*sum([n**i for i in range(k)]) + sage: S.size() == m*sum([n**i for i in range(k)]) # needs sage.modules True sage: G = graphs.CompleteGraph(n) - sage: S = graphs.GeneralizedSierpinskiGraph(G, k) - sage: S.order() == n**k + sage: S = graphs.GeneralizedSierpinskiGraph(G, k) # needs sage.modules + sage: S.order() == n**k # needs sage.modules True - sage: S.size() == (n*(n - 1)/2)*sum([n**i for i in range(k)]) + sage: S.size() == (n*(n - 1)/2)*sum([n**i for i in range(k)]) # needs sage.modules True The positions of the vertices of the output graph are determined from the @@ -3302,14 +3306,14 @@ def GeneralizedSierpinskiGraph(G, k, stretch=None): sage: G = graphs.HouseGraph() sage: G.get_pos() is not None True - sage: H = graphs.GeneralizedSierpinskiGraph(G, 2) # optional - sage.symbolic - sage: H.get_pos() is not None # optional - sage.symbolic + sage: H = graphs.GeneralizedSierpinskiGraph(G, 2) # needs sage.symbolic + sage: H.get_pos() is not None # needs sage.symbolic True sage: G = Graph([(0, 1)]) sage: G.get_pos() is not None False - sage: H = graphs.GeneralizedSierpinskiGraph(G, 2) # optional - sage.symbolic - sage: H.get_pos() is not None # optional - sage.symbolic + sage: H = graphs.GeneralizedSierpinskiGraph(G, 2) # needs sage.symbolic + sage: H.get_pos() is not None # needs sage.symbolic False .. PLOT:: @@ -3318,18 +3322,18 @@ def GeneralizedSierpinskiGraph(G, k, stretch=None): TESTS:: - sage: graphs.GeneralizedSierpinskiGraph(Graph(), 3) + sage: graphs.GeneralizedSierpinskiGraph(Graph(), 3) # needs sage.modules Generalized Sierpinski Graph of Graph on 0 vertices of dimension 3: Graph on 0 vertices - sage: graphs.GeneralizedSierpinskiGraph(Graph(1), 3).vertices(sort=False) + sage: graphs.GeneralizedSierpinskiGraph(Graph(1), 3).vertices(sort=False) # needs sage.modules [(0, 0, 0)] - sage: G = graphs.GeneralizedSierpinskiGraph(Graph(2), 3) - sage: G.order(), G.size() + sage: G = graphs.GeneralizedSierpinskiGraph(Graph(2), 3) # needs sage.modules + sage: G.order(), G.size() # needs sage.modules (8, 0) - sage: graphs.GeneralizedSierpinskiGraph("foo", 1) + sage: graphs.GeneralizedSierpinskiGraph("foo", 1) # needs sage.modules Traceback (most recent call last): ... ValueError: parameter G must be a Graph - sage: graphs.GeneralizedSierpinskiGraph(Graph(), 0) + sage: graphs.GeneralizedSierpinskiGraph(Graph(), 0) # needs sage.modules Traceback (most recent call last): ... ValueError: parameter k must be >= 1 @@ -3403,40 +3407,40 @@ def WheelGraph(n): ....: k = graphs.WheelGraph(i+3) ....: g.append(k) ... - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs 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) # needs sage.plot + sage: G.show() # long time # needs sage.plot Next, using the spring-layout algorithm:: - sage: import networkx # optional - networkx + sage: import networkx # needs networkx sage: g = [] sage: j = [] - sage: for i in range(9): # optional - networkx + sage: for i in range(9): # needs networkx ....: spr = networkx.wheel_graph(i+3) ....: k = Graph(spr) ....: g.append(k) ... - sage: for i in range(3): # optional - networkx sage.plot + sage: for i in range(3): # needs 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 - networkx sage.plot - sage: G.show() # long time # optional - networkx sage.plot + sage: G = graphics_array(j) # needs networkx sage.plot + sage: G.show() # long time # needs networkx sage.plot Compare the plotting:: - sage: n = networkx.wheel_graph(23) # optional - networkx - sage: spring23 = Graph(n) # optional - networkx + sage: n = networkx.wheel_graph(23) # needs networkx + sage: spring23 = Graph(n) # needs networkx sage: posdict23 = graphs.WheelGraph(23) - sage: spring23.show() # long time # optional - networkx + sage: spring23.show() # long time # needs networkx sage: posdict23.show() # long time """ from sage.graphs.generators.basic import CycleGraph @@ -3740,10 +3744,10 @@ def RingedTree(k, vertex_labels=True): EXAMPLES:: - sage: G = graphs.RingedTree(5) - sage: P = G.plot(vertex_labels=False, vertex_size=10) # optional - sage.plot - sage: P.show() # long time # optional - sage.plot - sage: G.vertices(sort=True) + sage: G = graphs.RingedTree(5) # needs networkx + sage: P = G.plot(vertex_labels=False, vertex_size=10) # needs networkx sage.plot + sage: P.show() # long time # needs networkx sage.plot + sage: G.vertices(sort=True) # needs networkx ['', '0', '00', '000', '0000', '0001', '001', '0010', '0011', '01', '010', '0100', '0101', '011', '0110', '0111', '1', '10', '100', '1000', '1001', '101', '1010', '1011', '11', '110', '1100', '1101', @@ -3755,8 +3759,8 @@ def RingedTree(k, vertex_labels=True): Traceback (most recent call last): ... ValueError: The number of levels must be >= 1. - sage: G = graphs.RingedTree(5, vertex_labels = False) - sage: G.vertices(sort=True) + sage: G = graphs.RingedTree(5, vertex_labels=False) # needs networkx + sage: G.vertices(sort=True) # needs networkx [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30] """ @@ -3828,13 +3832,13 @@ def MathonPseudocyclicMergingGraph(M, t): sage: G = mer(ES(3), 2) # long time sage: G.is_strongly_regular(parameters=True) # long time (784, 297, 116, 110) - sage: G = mer(ES(2), 2) + sage: G = mer(ES(2), 2) # needs sage.libs.gap Traceback (most recent call last): ... AssertionError... - sage: M = ES(3) - sage: M = [M[1],M[0],M[2],M[3]] - sage: G = mer(M, 2) + sage: M = ES(3) # needs sage.libs.gap + sage: M = [M[1],M[0],M[2],M[3]] # needs sage.libs.gap + sage: G = mer(M, 2) # needs sage.libs.gap Traceback (most recent call last): ... AssertionError... @@ -3889,22 +3893,22 @@ def MathonPseudocyclicStronglyRegularGraph(t, G=None, L=None): Using default ``G`` and ``L``. :: sage: from sage.graphs.generators.families import MathonPseudocyclicStronglyRegularGraph - sage: G=MathonPseudocyclicStronglyRegularGraph(1); G + sage: G = MathonPseudocyclicStronglyRegularGraph(1); G # needs sage.modules sage.rings.finite_rings Mathon's PC SRG on 45 vertices: Graph on 45 vertices - sage: G.is_strongly_regular(parameters=True) + sage: G.is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings (45, 22, 10, 11) Supplying ``G`` and ``L`` (constructed from the automorphism group of ``G``). :: - sage: G = graphs.PaleyGraph(9) - sage: a = G.automorphism_group(partition=[sorted(G)]) - sage: it = (x for x in a.normal_subgroups() if x.order() == 9) - sage: subg = next(iter(it)) - sage: r = [matrix(libgap.PermutationMat(libgap(z), 9).sage()) + sage: G = graphs.PaleyGraph(9) # needs sage.rings.finite_rings + sage: a = G.automorphism_group(partition=[sorted(G)]) # needs sage.groups sage.rings.finite_rings + sage: it = (x for x in a.normal_subgroups() if x.order() == 9) # needs sage.groups sage.rings.finite_rings + sage: subg = next(iter(it)) # needs sage.groups sage.rings.finite_rings + sage: r = [matrix(libgap.PermutationMat(libgap(z), 9).sage()) # needs sage.groups sage.libs.gap sage.rings.finite_rings ....: for z in subg] - sage: ff = list(map(lambda y: (y[0]-1,y[1]-1), + sage: ff = list(map(lambda y: (y[0]-1,y[1]-1), # needs sage.groups sage.libs.gap sage.rings.finite_rings ....: Permutation(map(lambda x: 1+r.index(x^-1), r)).cycle_tuples()[1:])) - sage: L = sum(i*(r[a]-r[b]) for i,(a,b) in zip(range(1,len(ff)+1), ff)); L + sage: L = sum(i*(r[a]-r[b]) for i,(a,b) in zip(range(1,len(ff)+1), ff)); L # needs sage.groups sage.libs.gap sage.rings.finite_rings [ 0 1 -1 -3 -2 -4 3 4 2] [-1 0 1 -4 -3 -2 2 3 4] [ 1 -1 0 -2 -4 -3 4 2 3] @@ -3915,21 +3919,21 @@ def MathonPseudocyclicStronglyRegularGraph(t, G=None, L=None): [-4 -3 -2 2 3 4 -1 0 1] [-2 -4 -3 4 2 3 1 -1 0] - sage: G.relabel(range(9)) - sage: G3x3=graphs.MathonPseudocyclicStronglyRegularGraph(2,G=G,L=L) - sage: G3x3.is_strongly_regular(parameters=True) + sage: G.relabel(range(9)) # needs sage.rings.finite_rings + sage: G3x3 = graphs.MathonPseudocyclicStronglyRegularGraph(2, G=G, L=L) # needs sage.modules sage.rings.finite_rings + sage: G3x3.is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings (441, 220, 109, 110) - sage: G3x3.automorphism_group(algorithm="bliss").order() # optional - bliss + sage: G3x3.automorphism_group(algorithm="bliss").order() # optional - bliss, needs sage.modules sage.rings.finite_rings 27 - sage: G9=graphs.MathonPseudocyclicStronglyRegularGraph(2) - sage: G9.is_strongly_regular(parameters=True) + sage: G9 = graphs.MathonPseudocyclicStronglyRegularGraph(2) # needs sage.modules sage.rings.finite_rings + sage: G9.is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings (441, 220, 109, 110) - sage: G9.automorphism_group(algorithm="bliss").order() # optional - bliss + sage: G9.automorphism_group(algorithm="bliss").order() # optional - bliss, needs sage.modules sage.rings.finite_rings 9 TESTS:: - sage: graphs.MathonPseudocyclicStronglyRegularGraph(5) + sage: graphs.MathonPseudocyclicStronglyRegularGraph(5) # needs sage.modules Traceback (most recent call last): ... ValueError: 21 must be a sum of two squares!... @@ -4123,36 +4127,37 @@ def MuzychukS6Graph(n, d, Phi='fixed', Sigma='fixed', verbose=False): EXAMPLES:: - sage: graphs.MuzychukS6Graph(3, 3).is_strongly_regular(parameters=True) + sage: graphs.MuzychukS6Graph(3, 3).is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings (378, 116, 34, 36) - sage: phi={(2,(0,2)):0,(1,(1,3)):1,(0,(0,3)):1,(2,(1,2)):1,(1,(1, - ....: 2)):0,(0,(0,2)):0,(3,(0,3)):0,(3,(1,3)):1} - sage: graphs.MuzychukS6Graph(2,2,Phi=phi).is_strongly_regular(parameters=True) + sage: phi = {(2,(0,2)):0, (1,(1,3)):1, (0,(0,3)):1, (2,(1,2)):1, # needs sage.modules + ....: (1,(1,2)):0, (0,(0,2)):0, (3,(0,3)):0, (3,(1,3)):1} + sage: graphs.MuzychukS6Graph(2, 2, # needs sage.modules sage.rings.finite_rings + ....: Phi=phi).is_strongly_regular(parameters=True) (16, 5, 0, 2) TESTS:: - sage: graphs.MuzychukS6Graph(2,2,Phi='random',Sigma='random').is_strongly_regular(parameters=True) + sage: graphs.MuzychukS6Graph(2,2,Phi='random',Sigma='random').is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings (16, 5, 0, 2) - sage: graphs.MuzychukS6Graph(3,3,Phi='random',Sigma='random').is_strongly_regular(parameters=True) + sage: graphs.MuzychukS6Graph(3,3,Phi='random',Sigma='random').is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings (378, 116, 34, 36) - sage: graphs.MuzychukS6Graph(3,2) + sage: graphs.MuzychukS6Graph(3,2) # needs sage.modules Traceback (most recent call last): ... AssertionError: n must be even or d must be odd - sage: graphs.MuzychukS6Graph(6,2) + sage: graphs.MuzychukS6Graph(6,2) # needs sage.modules Traceback (most recent call last): ... AssertionError: n must be a prime power - sage: graphs.MuzychukS6Graph(3,1) + sage: graphs.MuzychukS6Graph(3,1) # needs sage.modules Traceback (most recent call last): ... AssertionError: d must be at least 2 - sage: graphs.MuzychukS6Graph(3,3,Phi=42) + sage: graphs.MuzychukS6Graph(3,3,Phi=42) # needs sage.modules sage.rings.finite_rings Traceback (most recent call last): ... AssertionError: Phi must be a dictionary or 'random' or 'fixed' - sage: graphs.MuzychukS6Graph(3,3,Sigma=42) + sage: graphs.MuzychukS6Graph(3,3,Sigma=42) # needs sage.modules sage.rings.finite_rings Traceback (most recent call last): ... ValueError: Sigma must be 'random' or 'fixed' diff --git a/src/sage/graphs/generators/intersection.py b/src/sage/graphs/generators/intersection.py index f2cd8b248ad..06368795029 100644 --- a/src/sage/graphs/generators/intersection.py +++ b/src/sage/graphs/generators/intersection.py @@ -417,9 +417,10 @@ def OrthogonalArrayBlockGraph(k, n, OA=None): EXAMPLES:: - sage: G = graphs.OrthogonalArrayBlockGraph(5,5); G + sage: # needs sage.modules + sage: G = graphs.OrthogonalArrayBlockGraph(5,5); G # needs sage.schemes OA(5,5): Graph on 25 vertices - sage: G.is_strongly_regular(parameters=True) + sage: G.is_strongly_regular(parameters=True) # needs sage.schemes (25, 20, 15, 20) sage: G = graphs.OrthogonalArrayBlockGraph(4,10); G OA(4,10): Graph on 100 vertices @@ -428,20 +429,20 @@ def OrthogonalArrayBlockGraph(k, n, OA=None): Two graphs built from different orthogonal arrays are also different:: - sage: k=4;n=10 - sage: OAa = designs.orthogonal_arrays.build(k,n) - sage: OAb = [[(x+1)%n for x in R] for R in OAa] - sage: set(map(tuple,OAa)) == set(map(tuple,OAb)) + sage: k = 4; n = 10 + sage: OAa = designs.orthogonal_arrays.build(k,n) # needs sage.modules + sage: OAb = [[(x+1)%n for x in R] for R in OAa] # needs sage.modules + sage: set(map(tuple,OAa)) == set(map(tuple,OAb)) # needs sage.modules False - sage: Ga = graphs.OrthogonalArrayBlockGraph(k,n,OAa) - sage: Gb = graphs.OrthogonalArrayBlockGraph(k,n,OAb) - sage: Ga == Gb + sage: Ga = graphs.OrthogonalArrayBlockGraph(k, n, OAa) # needs sage.modules + sage: Gb = graphs.OrthogonalArrayBlockGraph(k, n, OAb) # needs sage.modules + sage: Ga == Gb # needs sage.modules False As ``OAb`` was obtained from ``OAa`` by a relabelling the two graphs are isomorphic:: - sage: Ga.is_isomorphic(Gb) + sage: Ga.is_isomorphic(Gb) # needs sage.modules True But there are examples of `OA(k,n)` for which the resulting graphs are not @@ -455,31 +456,31 @@ def OrthogonalArrayBlockGraph(k, n, OA=None): ....: [1, 0, 3], [1, 1, 2], [1, 2, 0], [1, 3, 1], ....: [2, 0, 0], [2, 1, 1], [2, 2, 2], [2, 3, 3], ....: [3, 0, 2], [3, 1, 3], [3, 2, 1], [3, 3, 0]] - sage: g0 = graphs.OrthogonalArrayBlockGraph(3,4,oa0) - sage: g1 = graphs.OrthogonalArrayBlockGraph(3,4,oa1) - sage: g0.is_isomorphic(g1) + sage: g0 = graphs.OrthogonalArrayBlockGraph(3, 4, oa0) # needs sage.modules + sage: g1 = graphs.OrthogonalArrayBlockGraph(3, 4, oa1) # needs sage.modules + sage: g0.is_isomorphic(g1) # needs sage.modules False But nevertheless isospectral:: - sage: g0.spectrum() + sage: g0.spectrum() # needs sage.modules [9, 1, 1, 1, 1, 1, 1, 1, 1, 1, -3, -3, -3, -3, -3, -3] - sage: g1.spectrum() + sage: g1.spectrum() # needs sage.modules [9, 1, 1, 1, 1, 1, 1, 1, 1, 1, -3, -3, -3, -3, -3, -3] Note that the graph ``g0`` is actually isomorphic to the affine polar graph `VO^+(4,2)`:: - sage: graphs.AffineOrthogonalPolarGraph(4,2,'+').is_isomorphic(g0) + sage: graphs.AffineOrthogonalPolarGraph(4,2,'+').is_isomorphic(g0) # needs sage.modules True TESTS:: - sage: G = graphs.OrthogonalArrayBlockGraph(4,6) + sage: G = graphs.OrthogonalArrayBlockGraph(4,6) # needs sage.modules Traceback (most recent call last): ... NotImplementedError: I don't know how to build an OA(4,6)! - sage: G = graphs.OrthogonalArrayBlockGraph(8,2) + sage: G = graphs.OrthogonalArrayBlockGraph(8,2) # needs sage.modules Traceback (most recent call last): ... ValueError: There is no OA(8,2). Beware, Brouwer's website uses OA(n,k) instead of OA(k,n) ! diff --git a/src/sage/graphs/generators/platonic_solids.py b/src/sage/graphs/generators/platonic_solids.py index f36fa8ecf66..b0f97da83fa 100644 --- a/src/sage/graphs/generators/platonic_solids.py +++ b/src/sage/graphs/generators/platonic_solids.py @@ -43,24 +43,24 @@ def TetrahedralGraph(): The following example requires networkx:: - sage: import networkx as NX # optional - networkx + sage: import networkx as NX # needs networkx Compare this Tetrahedral, Wheel(4), Complete(4), and the Tetrahedral plotted with the spring-layout algorithm below in a Sage graphics array:: sage: tetra_pos = graphs.TetrahedralGraph() - sage: tetra_spring = Graph(NX.tetrahedral_graph()) # optional - networkx + sage: tetra_spring = Graph(NX.tetrahedral_graph()) # needs networkx sage: wheel = graphs.WheelGraph(4) sage: complete = graphs.CompleteGraph(4) - sage: g = [tetra_pos, tetra_spring, wheel, complete] # optional - networkx + sage: g = [tetra_pos, tetra_spring, wheel, complete] # needs networkx sage: j = [] - sage: for i in range(2): # optional - networkx sage.plot + sage: for i in range(2): # needs networkx sage.plot ....: n = [] ....: for m in range(2): ....: n.append(g[i + m].plot(vertex_size=50, vertex_labels=False)) ....: j.append(n) - sage: G = graphics_array(j) # optional - networkx sage.plot - sage: G.show() # long time # optional - networkx sage.plot + sage: G = graphics_array(j) # needs networkx sage.plot + sage: G.show() # long time # needs networkx sage.plot """ edges = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] pos = {0: (0, 0), @@ -98,13 +98,13 @@ def HexahedralGraph(): sage: for i in range(9): ....: k = graphs.HexahedralGraph() ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs 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) # needs sage.plot + sage: G.show() # long time # needs sage.plot """ adj = {0: [1, 3, 4], 1: [2, 5], 2: [3, 6], 3: [7], 4: [5, 7], 5: [6], 6: [7]} pos = { @@ -150,13 +150,13 @@ def OctahedralGraph(): sage: for i in range(9): ....: k = graphs.OctahedralGraph() ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs 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) # needs sage.plot + sage: G.show() # long time # needs sage.plot """ adj = {0: [1, 2, 3, 4], 1: [2, 3, 5], 2: [4, 5], 3: [4, 5], 4: [5]} G = Graph(adj, format='dict_of_lists', name="Octahedron") @@ -194,13 +194,13 @@ def IcosahedralGraph(): sage: for i in range(9): ....: k = graphs.IcosahedralGraph() ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs 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) # needs sage.plot + sage: G.show() # long time # needs sage.plot """ adj = {0: [1, 5, 7, 8, 11], 1: [2, 5, 6, 8], 2: [3, 6, 8, 9], 3: [4, 6, 9, 10], 4: [5, 6, 10, 11], 5: [6, 11], @@ -238,13 +238,13 @@ def DodecahedralGraph(): sage: for i in range(9): ....: k = graphs.DodecahedralGraph() ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs 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) # needs sage.plot + sage: G.show() # long time # needs sage.plot """ adj = {0: [1, 10, 19], 1: [2, 8], 2: [3, 6], 3: [4, 19], 4: [5, 17], 5: [6, 15], 6: [7], 7: [8, 14], 8: [9], 9: [10, 13], 10: [11], diff --git a/src/sage/graphs/generators/random.py b/src/sage/graphs/generators/random.py index 288515ac397..22459ca6930 100644 --- a/src/sage/graphs/generators/random.py +++ b/src/sage/graphs/generators/random.py @@ -78,13 +78,13 @@ def RandomGNP(n, p, seed=None, fast=True, algorithm='Sage'): sage: for i in range(9): ....: k = graphs.RandomGNP(i+3,.43) ....: g.append(k) - sage: for i in range(3): # optional - sage.plot + sage: for i in range(3): # needs 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) # needs sage.plot + sage: G.show() # long time # needs sage.plot sage: graphs.RandomGNP(4,1) Complete graph: Graph on 4 vertices @@ -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() # optional - networkx + sage: graphs.RandomGNP(50,.2, algorithm="networkx").size() # needs 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) # optional - networkx - sage: G.order(), G.size() # optional - networkx + sage: G = graphs.RandomBarabasiAlbert(6,2) # needs networkx + sage: G.order(), G.size() # needs networkx (6, 8) - sage: G.degree_sequence() # random # optional - networkx + sage: G.degree_sequence() # random # needs networkx [4, 3, 3, 2, 2, 2] We plot a random graph on 12 nodes with `m = 3`:: - sage: ba = graphs.RandomBarabasiAlbert(12,3) # optional - networkx - sage: ba.show() # long time # optional - networkx sage.plot + sage: ba = graphs.RandomBarabasiAlbert(12,3) # needs networkx + sage: ba.show() # long time # needs networkx sage.plot We view many random graphs using a graphics array:: sage: g = [] sage: j = [] - sage: for i in range(1,10): # optional - networkx + sage: for i in range(1,10): # needs networkx ....: k = graphs.RandomBarabasiAlbert(i+3, 3) ....: g.append(k) - sage: for i in range(3): # optional - networkx sage.plot + sage: for i in range(3): # needs 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 - networkx sage.plot - sage: G.show() # long time # optional - networkx sage.plot + sage: G = graphics_array(j) # needs networkx sage.plot + sage: G.show() # long time # needs networkx sage.plot When `m = 1`, the generated graph is a tree:: - sage: graphs.RandomBarabasiAlbert(6, 1).is_tree() # optional - networkx + sage: graphs.RandomBarabasiAlbert(6, 1).is_tree() # needs networkx True """ if seed is None: @@ -206,35 +206,36 @@ def RandomBipartite(n1, n2, p, set_position=False, seed=None): EXAMPLES:: - sage: g = graphs.RandomBipartite(5, 2, 0.5) # optional - numpy - sage: g.vertices(sort=True) # optional - numpy + sage: g = graphs.RandomBipartite(5, 2, 0.5) # needs numpy + sage: g.vertices(sort=True) # needs numpy [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1)] TESTS:: - sage: g = graphs.RandomBipartite(5, -3, 0.5) # optional - numpy + sage: g = graphs.RandomBipartite(5, -3, 0.5) # needs 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) # optional - numpy + sage: g = graphs.RandomBipartite(5, 3, 1.5) # needs 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() # optional - numpy + sage: graphs.RandomBipartite(5, 6, .2).complement() # needs 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() # optional - numpy + sage: # needs numpy + sage: graphs.RandomBipartite(1, 2, .1, set_position=True).get_pos() {(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() # optional - numpy + sage: graphs.RandomBipartite(2, 1, .1, set_position=True).get_pos() {(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() # optional - numpy + sage: graphs.RandomBipartite(2, 2, .1, set_position=True).get_pos() {(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() # optional - numpy + sage: graphs.RandomBipartite(2, 2, .1, set_position=False).get_pos() """ if not (p >= 0 and p <= 1): @@ -512,7 +513,7 @@ def RandomBlockGraph(m, k, kmax=None, incidence_structure=False, seed=None): sage: m, k = 6, 4 sage: IS = graphs.RandomBlockGraph(m, k, incidence_structure=True) sage: from sage.combinat.designs.incidence_structures import IncidenceStructure - sage: IncidenceStructure(IS) + sage: IncidenceStructure(IS) # needs sage.modules Incidence structure with 19 points and 6 blocks sage: m*(k-1)+1 19 @@ -679,28 +680,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) # optional - networkx + sage: graphs.RandomGNM(5, 10).edges(sort=True, labels=False) # needs 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) # optional - networkx - sage: gnm.show() # long time # optional - networkx sage.plot + sage: gnm = graphs.RandomGNM(12, 12) # needs networkx + sage: gnm.show() # long time # needs networkx sage.plot We view many random graphs using a graphics array:: sage: g = [] sage: j = [] - sage: for i in range(9): # optional - networkx + sage: for i in range(9): # needs networkx ....: k = graphs.RandomGNM(i+3, i^2-i) ....: g.append(k) - sage: for i in range(3): # optional - networkx sage.plot + sage: for i in range(3): # needs 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 - networkx sage.plot - sage: G.show() # long time # optional - networkx sage.plot + sage: G = graphics_array(j) # needs networkx sage.plot + sage: G.show() # long time # needs networkx sage.plot """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) @@ -737,33 +738,34 @@ 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) # optional - networkx - sage: G.order() # optional - networkx + sage: # needs networkx + sage: G = graphs.RandomNewmanWattsStrogatz(7, 2, 0.2) + sage: G.order() 7 - sage: C7 = graphs.CycleGraph(7) # optional - networkx - sage: G.subgraph_search(C7) # optional - networkx + sage: C7 = graphs.CycleGraph(7) + sage: G.subgraph_search(C7) Subgraph of (): Graph on 7 vertices - sage: G.diameter() <= C7.diameter() # optional - networkx + sage: G.diameter() <= C7.diameter() True :: - sage: G = graphs.RandomNewmanWattsStrogatz(12, 2, .3) # optional - networkx - sage: G.show() # long time # optional - networkx sage.plot + sage: G = graphs.RandomNewmanWattsStrogatz(12, 2, .3) # needs networkx + sage: G.show() # long time # needs 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) # optional - networkx - sage: G.is_cycle() # optional - networkx + sage: G = graphs.RandomNewmanWattsStrogatz(7, 2, 0) # needs networkx + sage: G.is_cycle() # needs 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) # optional - networkx - sage: G.is_isomorphic(graphs.CirculantGraph(7, [1, 2])) # optional - networkx + sage: G = graphs.RandomNewmanWattsStrogatz(7, 4, 0) # needs networkx + sage: G.is_isomorphic(graphs.CirculantGraph(7, [1, 2])) # needs networkx True REFERENCE: @@ -807,8 +809,8 @@ def RandomHolmeKim(n, m, p, seed=None): EXAMPLES:: - sage: G = graphs.RandomHolmeKim(12, 3, .3) # optional - networkx - sage: G.show() # long time # optional - networkx sage.plot + sage: G = graphs.RandomHolmeKim(12, 3, .3) # needs networkx + sage: G.show() # long time # needs networkx sage.plot REFERENCE: @@ -952,8 +954,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) # optional - numpy - sage: len(S) # optional - numpy + sage: S = connecting_nodes(T, 5) # needs numpy + sage: len(S) # needs numpy 10 """ from sage.combinat.permutation import Permutations @@ -1178,8 +1180,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) # optional - numpy - sage: T.is_chordal() # optional - numpy + sage: T = RandomChordalGraph(20, algorithm="connecting", l=3) # needs numpy + sage: T.is_chordal() # needs numpy True sage: T = RandomChordalGraph(20, algorithm="pruned", f=1/3, s=.5) sage: T.is_chordal() @@ -1303,13 +1305,14 @@ 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) # 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 + sage: # needs networkx + 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: ....: if G.num_verts() == 1: ....: assert s == [0] ....: else: @@ -1318,8 +1321,8 @@ def RandomLobster(n, p, q, seed=None): :: - sage: G = graphs.RandomLobster(9, .6, .3) # optional - networkx - sage: G.show() # long time # optional - networkx sage.plot + sage: G = graphs.RandomLobster(9, .6, .3) # needs networkx + sage: G.show() # long time # needs networkx sage.plot """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) @@ -1434,16 +1437,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) # optional - networkx - sage: G.is_tree() # optional - networkx + sage: G = graphs.RandomTreePowerlaw(10, 3) # needs networkx + sage: G.is_tree() # needs networkx True - sage: G.order(), G.size() # optional - networkx + sage: G.order(), G.size() # needs networkx (10, 9) :: - sage: G = graphs.RandomTreePowerlaw(15, 2) # optional - networkx - sage: if G: # random output, long time # optional - networkx sage.plot + sage: G = graphs.RandomTreePowerlaw(15, 2) # needs networkx + sage: if G: # random output # long time # needs networkx sage.plot ....: G.show() """ if seed is None: @@ -1474,16 +1477,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) # optional - networkx - sage: G.is_regular(k=3) # optional - networkx + sage: G = graphs.RandomRegular(3, 8) # needs networkx + sage: G.is_regular(k=3) # needs networkx True - sage: G.degree_histogram() # optional - networkx + sage: G.degree_histogram() # needs networkx [0, 0, 0, 8] :: - sage: G = graphs.RandomRegular(3, 20) # optional - networkx - sage: if G: # random output, long time # optional - networkx sage.plot + sage: G = graphs.RandomRegular(3, 20) # needs networkx + sage: if G: # random output # long time # needs networkx sage.plot ....: G.show() REFERENCES: @@ -1524,10 +1527,10 @@ def RandomShell(constructor, seed=None): EXAMPLES:: - sage: G = graphs.RandomShell([(10,20,0.8),(20,40,0.8)]) # optional - networkx - sage: G.order(), G.size() # optional - networkx + sage: G = graphs.RandomShell([(10,20,0.8),(20,40,0.8)]) # needs networkx + sage: G.order(), G.size() # needs networkx (30, 52) - sage: G.show() # long time # optional - networkx sage.plot + sage: G.show() # long time # needs networkx sage.plot """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) @@ -1889,7 +1892,7 @@ def RandomTriangulation(n, set_position=False, k=3, seed=None): True sage: G.girth() 3 - sage: G.plot(vertex_size=0, vertex_labels=False) # optional - sage.plot + sage: G.plot(vertex_size=0, vertex_labels=False) # needs sage.plot Graphics object consisting of 13 graphics primitives sage: H = graphs.RandomTriangulation(7, k=5) @@ -2005,16 +2008,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() # optional - sage.combinat - sage: print(blossoming_contour(t)) # random # optional - sage.combinat + sage: t = BinaryTrees(2).random_element() # needs sage.combinat + sage: print(blossoming_contour(t)) # random # needs 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) # optional - sage.combinat + sage: w = blossoming_contour(BinaryTrees(3).random_element()); len(w) # needs sage.combinat 21 - sage: w.count(('xb',)) # optional - sage.combinat + sage: w.count(('xb',)) # needs sage.combinat 4 - sage: w.count(('x',)) # optional - sage.combinat + sage: w.count(('x',)) # needs sage.combinat 2 TESTS:: @@ -2099,16 +2102,16 @@ def RandomBicubicPlanar(n, seed=None): EXAMPLES:: sage: n = randint(200, 300) - sage: G = graphs.RandomBicubicPlanar(n) # optional - sage.combinat - sage: G.order() == 2*n # optional - sage.combinat + sage: G = graphs.RandomBicubicPlanar(n) # needs sage.combinat + sage: G.order() == 2*n # needs sage.combinat True - sage: G.size() == 3*n # optional - sage.combinat + sage: G.size() == 3*n # needs sage.combinat True - sage: G.is_bipartite() and G.is_planar() and G.is_regular(3) # optional - sage.combinat + sage: G.is_bipartite() and G.is_planar() and G.is_regular(3) # needs sage.combinat True - sage: dic = {'red': [v for v in G.vertices(sort=False) if v[0] == 'n'], # optional - sage.combinat + sage: dic = {'red': [v for v in G.vertices(sort=False) if v[0] == 'n'], # needs 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.combinat sage.plot + sage: G.plot(vertex_labels=False, vertex_size=20, vertex_colors=dic) # needs sage.combinat sage.plot Graphics object consisting of ... graphics primitives .. PLOT:: @@ -2212,21 +2215,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) # optional - scipy - sage: H = graphs.RandomUnitDiskGraph(20, radius=.2, side=1, seed=seed) # optional - scipy - sage: H.is_subgraph(G, induced=False) # optional - scipy + sage: G = graphs.RandomUnitDiskGraph(20, radius=.5, side=1, seed=seed) # needs scipy + sage: H = graphs.RandomUnitDiskGraph(20, radius=.2, side=1, seed=seed) # needs scipy + sage: H.is_subgraph(G, induced=False) # needs scipy True - sage: H.size() <= G.size() # optional - scipy + sage: H.size() <= G.size() # needs scipy True - 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 + sage: Gpos = G.get_pos() # needs scipy + sage: Hpos = H.get_pos() # needs scipy + sage: all(Gpos[u] == Hpos[u] for u in G) # needs 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) # optional - scipy - sage: G.is_clique() # optional - scipy + sage: G = graphs.RandomUnitDiskGraph(10, radius=2, side=1) # needs scipy + sage: G.is_clique() # needs scipy True """ if seed is not None: diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index 27d4fc300ab..e879b708aaf 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -2175,7 +2175,7 @@ def EllinghamHorton54Graph(): It is not Hamiltonian:: - sage: g.is_hamiltonian() # not tested (too long) # needs sage.numerical.mip + sage: g.is_hamiltonian() # not tested # needs sage.numerical.mip False ... and it has a nice drawing :: @@ -2252,7 +2252,7 @@ def EllinghamHorton78Graph(): It is not Hamiltonian:: - sage: g.is_hamiltonian() # not tested (too long) # needs sage.numerical.mip + sage: g.is_hamiltonian() # not tested # needs sage.numerical.mip False ... and it has a nice drawing :: @@ -2734,7 +2734,7 @@ def GrayGraph(embedding=1): 8 sage: g.diameter() 6 - sage: g.show(figsize=[10, 10]) # long time, needs sage.plot + sage: g.show(figsize=[10, 10]) # long time # needs sage.plot sage: graphs.GrayGraph(embedding=2).show(figsize=[10, 10]) # long time, needs sage.plot TESTS:: @@ -4664,12 +4664,6 @@ def WienerArayaGraph(): 4 sage: g.is_planar() True -<<<<<<< HEAD - sage: g.is_hamiltonian() # not tested -- around 30s long - False - sage: g.delete_vertex(g.random_vertex()) - sage: g.is_hamiltonian() -======= sage: g.is_hamiltonian() # not tested (30s) # needs sage.numerical.mip False sage: g.delete_vertex(g.random_vertex()) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 06bee055514..64cdd8dffcb 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -15285,7 +15285,8 @@ def clustering_average(self, implementation=None): sage: # needs networkx sage: G = graphs.RandomGNM(10,20) - sage: impls = ['boost', 'sparse_copy', 'dense_copy', 'networkx'] + sage: impls = ['boost', 'sparse_copy', 'dense_copy'] + sage: impls += ['networkx'] sage: coeffs = [G.clustering_average(implementation=impl) ....: for impl in impls] sage: max(coeffs) - min(coeffs) # tol abs 1e-12 @@ -23150,10 +23151,10 @@ def automorphism_group(self, partition=None, verbosity=0, sage: str(a1) == str(a2) # needs sage.groups False sage: b1 = G.automorphism_group(algorithm='bliss') # optional - bliss - sage: str(a1) == str(b1) # optional - bliss, needs sage.groups + sage: str(a1) == str(b1) # optional - bliss # needs sage.groups True sage: b2 = G.automorphism_group(algorithm='bliss', partition=[V]) # optional - bliss - sage: str(a2) == str(b2) # optional - bliss, needs sage.groups + sage: str(a2) == str(b2) # optional - bliss # needs sage.groups True """ from sage.features.bliss import Bliss diff --git a/src/sage/graphs/generic_graph_pyx.pyx b/src/sage/graphs/generic_graph_pyx.pyx index 45867176382..0e05f3a4ec9 100644 --- a/src/sage/graphs/generic_graph_pyx.pyx +++ b/src/sage/graphs/generic_graph_pyx.pyx @@ -400,7 +400,7 @@ cdef inline double sqrt_approx(double x, double y, double xx, double yy): ....: y = abs(y) ....: return max(x,y) + min(x,y)**2/(2*max(x,y)) - sage: polar_plot([1,lambda x:dist(cos(x),sin(x))], (0, 2*math.pi)) # optional - sage.plot + sage: polar_plot([1,lambda x:dist(cos(x),sin(x))], (0, 2*math.pi)) # needs sage.plot Graphics object consisting of 2 graphics primitives """ if xx < yy: @@ -651,7 +651,7 @@ cdef class SubgraphSearch: EXAMPLES:: sage: g = graphs.PetersenGraph() - sage: g.subgraph_search(graphs.CycleGraph(5)) # optional - sage.modules + sage: g.subgraph_search(graphs.CycleGraph(5)) # needs sage.modules Subgraph of (Petersen graph): Graph on 5 vertices TESTS: @@ -661,11 +661,11 @@ cdef class SubgraphSearch: computations with it:: sage: from sage.graphs.generic_graph_pyx import SubgraphSearch - sage: SubgraphSearch(Graph(5), Graph(1)) # optional - sage.modules + sage: SubgraphSearch(Graph(5), Graph(1)) # needs sage.modules Traceback (most recent call last): ... ValueError: searched graph should have at least 2 vertices - sage: SubgraphSearch(Graph(5), Graph(2)) # optional - sage.modules + sage: SubgraphSearch(Graph(5), Graph(2)) # needs sage.modules """ if H.order() <= 1: @@ -691,8 +691,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) # optional - sage.modules - sage: for p in S: # optional - sage.modules + sage: S = SubgraphSearch(g, h) # needs sage.modules + sage: for p in S: # needs sage.modules ....: print(p) [0, 1, 2] [1, 2, 3] @@ -722,8 +722,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) # optional - sage.modules - sage: S.cardinality() # optional - sage.modules + sage: S = SubgraphSearch(g, h) # needs sage.modules + sage: S.cardinality() # needs sage.modules 6 Check that the method is working even when vertices or edges are of @@ -734,8 +734,8 @@ cdef class SubgraphSearch: sage: G.add_cycle(['A', 1, 2, 3, ('a', 1)]) sage: H = Graph() sage: H.add_path("xyz") - sage: S = SubgraphSearch(G, H) # optional - sage.modules - sage: S.cardinality() # optional - sage.modules + sage: S = SubgraphSearch(G, H) # needs sage.modules + sage: S.cardinality() # needs sage.modules 10 """ if self.nh > self.ng: @@ -769,18 +769,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) # optional - sage.modules - sage: S.__next__() # optional - sage.modules + sage: S = SubgraphSearch(g, h) # needs sage.modules + sage: S.__next__() # needs sage.modules [0, 1, 2] - sage: S._initialization() # optional - sage.modules - sage: S.__next__() # optional - sage.modules + sage: S._initialization() # needs sage.modules + sage: S.__next__() # needs sage.modules [0, 1, 2] TESTS: Check that :trac:`21828` is fixed:: - sage: Poset().is_incomparable_chain_free(1,1) # indirect doctest # optional - sage.modules + sage: Poset().is_incomparable_chain_free(1,1) # indirect doctest # needs sage.modules True """ cdef int i @@ -815,7 +815,7 @@ cdef class SubgraphSearch: EXAMPLES:: sage: g = graphs.PetersenGraph() - sage: g.subgraph_search(graphs.CycleGraph(5)) # optional - sage.modules + sage: g.subgraph_search(graphs.CycleGraph(5)) # needs sage.modules Subgraph of (Petersen graph): Graph on 5 vertices """ self.mem = MemoryAllocator() @@ -904,8 +904,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) # optional - sage.modules - sage: S.__next__() # optional - sage.modules + sage: S = SubgraphSearch(g, h) # needs sage.modules + sage: S.__next__() # needs sage.modules [0, 1, 2] """ if not self.ng: diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index e2c86f69d40..c6a32319305 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -106,16 +106,16 @@ 5: [7, 8], 6: [8,9], 7: [9]} sage: G = Graph(d); G Graph on 10 vertices - sage: G.plot().show() # or G.show() # optional - sage.plot + sage: G.plot().show() # or G.show() # needs sage.plot - A NetworkX graph: :: - sage: import networkx # optional - networkx - sage: K = networkx.complete_bipartite_graph(12,7) # optional - networkx - sage: G = Graph(K) # optional - networkx - sage: G.degree() # optional - networkx + sage: import networkx # needs networkx + sage: K = networkx.complete_bipartite_graph(12,7) # needs networkx + sage: G = Graph(K) # needs networkx + sage: G.degree() # needs networkx [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12] - graph6 or sparse6 format: @@ -125,7 +125,7 @@ sage: s = ':I`AKGsaOs`cI]Gb~' sage: G = Graph(s, sparse=True); G Looped multi-graph on 10 vertices - sage: G.plot().show() # or G.show() # optional - sage.plot + sage: G.plot().show() # or G.show() # needs sage.plot Note that the ``\`` character is an escape character in Python, and also a character used by graph6 strings: @@ -142,18 +142,18 @@ :: sage: G = Graph('Ihe\\n@GUA') - sage: G.plot().show() # or G.show() # optional - sage.plot + sage: G.plot().show() # or G.show() # needs sage.plot - adjacency matrix: In an adjacency matrix, each column and each row represent a vertex. If a 1 shows up in row `i`, column `j`, there is an edge `(i,j)`. :: - sage: M = Matrix([(0,1,0,0,1,1,0,0,0,0),(1,0,1,0,0,0,1,0,0,0), \ - (0,1,0,1,0,0,0,1,0,0), (0,0,1,0,1,0,0,0,1,0),(1,0,0,1,0,0,0,0,0,1), \ - (1,0,0,0,0,0,0,1,1,0), (0,1,0,0,0,0,0,0,1,1),(0,0,1,0,0,1,0,0,0,1), \ - (0,0,0,1,0,1,1,0,0,0), (0,0,0,0,1,0,1,1,0,0)]) - sage: M + sage: M = Matrix([(0,1,0,0,1,1,0,0,0,0), (1,0,1,0,0,0,1,0,0,0), # needs sage.modules + ....: (0,1,0,1,0,0,0,1,0,0), (0,0,1,0,1,0,0,0,1,0), + ....: (1,0,0,1,0,0,0,0,0,1), (1,0,0,0,0,0,0,1,1,0), (0,1,0,0,0,0,0,0,1,1), + ....: (0,0,1,0,0,1,0,0,0,1), (0,0,0,1,0,1,1,0,0,0), (0,0,0,0,1,0,1,1,0,0)]) + sage: M # needs sage.modules [0 1 0 0 1 1 0 0 0 0] [1 0 1 0 0 0 1 0 0 0] [0 1 0 1 0 0 0 1 0 0] @@ -164,16 +164,16 @@ [0 0 1 0 0 1 0 0 0 1] [0 0 0 1 0 1 1 0 0 0] [0 0 0 0 1 0 1 1 0 0] - sage: G = Graph(M); G + sage: G = Graph(M); G # needs sage.modules Graph on 10 vertices - sage: G.plot().show() # or G.show() # optional - sage.plot + sage: G.plot().show() # or G.show() # needs sage.modules sage.plot - incidence matrix: In an incidence matrix, each row represents a vertex and each column represents an edge. :: - sage: M = Matrix([(-1, 0, 0, 0, 1, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0), + sage: M = Matrix([(-1, 0, 0, 0, 1, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0), # needs sage.modules ....: ( 1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0), ....: ( 0, 1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0), ....: ( 0, 0, 1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0), @@ -183,7 +183,7 @@ ....: ( 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 0, 1, 0, 0), ....: ( 0, 0, 0, 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 1, 0), ....: ( 0, 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 0, 0, 1)]) - sage: M + sage: M # needs sage.modules [-1 0 0 0 1 0 0 0 0 0 -1 0 0 0 0] [ 1 -1 0 0 0 0 0 0 0 0 0 -1 0 0 0] [ 0 1 -1 0 0 0 0 0 0 0 0 0 -1 0 0] @@ -194,10 +194,10 @@ [ 0 0 0 0 0 1 -1 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 0 0 0 1 -1 0 0 0 1 0] [ 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 1] - sage: G = Graph(M); G + sage: G = Graph(M); G # needs sage.modules Graph on 10 vertices - sage: G.plot().show() # or G.show() # optional - sage.plot - sage: DiGraph(matrix(2,[0,0,-1,1]), format="incidence_matrix") + sage: G.plot().show() # or G.show() # needs sage.modules sage.plot + sage: DiGraph(matrix(2, [0,0,-1,1]), format="incidence_matrix") # needs sage.modules Traceback (most recent call last): ... ValueError: there must be two nonzero entries (-1 & 1) per column @@ -254,10 +254,10 @@ :: sage: G = graphs.PetersenGraph() - sage: G.plot().show() # or G.show() # optional - sage.plot + sage: G.plot().show() # or G.show() # needs sage.plot sage: G.degree_histogram() [0, 0, 0, 10] - sage: G.adjacency_matrix() + sage: G.adjacency_matrix() # needs sage.modules [0 1 0 0 1 1 0 0 0 0] [1 0 1 0 0 0 1 0 0 0] [0 1 0 1 0 0 0 1 0 0] @@ -272,7 +272,7 @@ :: sage: S = G.subgraph([0,1,2,3]) - sage: S.plot().show() # or S.show() # optional - sage.plot + sage: S.plot().show() # or S.show() # needs sage.plot sage: S.density() 1/2 @@ -280,7 +280,7 @@ sage: G = GraphQuery(display_cols=['graph6'], num_vertices=7, diameter=5) sage: L = G.get_graphs_list() - sage: graphs_list.show_graphs(L) # optional - sage.plot + sage: graphs_list.show_graphs(L) # needs sage.plot .. _Graph:labels: @@ -295,8 +295,8 @@ Note that vertex labels themselves cannot be mutable items:: - sage: M = Matrix( [[0,0],[0,0]] ) - sage: G = Graph({ 0 : { M : None } }) + sage: M = Matrix([[0,0], [0,0]]) # needs sage.modules + sage: G = Graph({ 0 : { M : None } }) # needs sage.modules Traceback (most recent call last): ... TypeError: mutable matrices are unhashable @@ -349,7 +349,7 @@ Show each graph as you iterate through the results:: - sage: for g in Q: # optional - sage.plot + sage: for g in Q: # needs sage.plot ....: show(g) Visualization @@ -359,11 +359,11 @@ view the graph in two dimensions via matplotlib with ``show()``. :: sage: G = graphs.RandomGNP(15,.3) - sage: G.show() # optional - sage.plot + sage: G.show() # needs sage.plot And you can view it in three dimensions via jmol with ``show3d()``. :: - sage: G.show3d() # optional - sage.plot + sage: G.show3d() # needs sage.plot Or it can be rendered with `\LaTeX`. This requires the right additions to a standard `\mbox{\rm\TeX}` installation. Then standard Sage commands, such as @@ -608,8 +608,8 @@ class Graph(GenericGraph): 'out' is the label for the edge on 2 and 5. Labels can be used as weights, if all the labels share some common parent.:: - sage: a, b, c, d, e, f = sorted(SymmetricGroup(3)) # optional - sage.groups - sage: Graph({b: {d: 'c', e: 'p'}, c: {d: 'p', e: 'c'}}) # optional - sage.groups + sage: a, b, c, d, e, f = sorted(SymmetricGroup(3)) # needs sage.groups + sage: Graph({b: {d: 'c', e: 'p'}, c: {d: 'p', e: 'c'}}) # needs sage.groups Graph on 4 vertices #. A dictionary of lists:: @@ -623,10 +623,10 @@ class Graph(GenericGraph): Construct the Paley graph over GF(13).:: - sage: g=Graph([GF(13), lambda i,j: i!=j and (i-j).is_square()]) - sage: g.vertices(sort=True) + sage: g = Graph([GF(13), lambda i,j: i!=j and (i-j).is_square()]) # needs sage.rings.finite_rings + sage: g.vertices(sort=True) # needs sage.rings.finite_rings [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] - sage: g.adjacency_matrix() + sage: g.adjacency_matrix() # needs sage.modules sage.rings.finite_rings [0 1 0 1 1 0 0 0 0 1 1 0 1] [1 0 1 0 1 1 0 0 0 0 1 1 0] [0 1 0 1 0 1 1 0 0 0 0 1 1] @@ -649,7 +649,7 @@ class Graph(GenericGraph): loops=False) sage: line_graph.vertices(sort=True) [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] - sage: line_graph.adjacency_matrix() + sage: line_graph.adjacency_matrix() # needs sage.modules [0 1 1 1 1 0] [1 0 1 1 0 1] [1 1 0 0 1 1] @@ -697,7 +697,7 @@ class Graph(GenericGraph): - an adjacency matrix:: - sage: M = graphs.PetersenGraph().am(); M + sage: M = graphs.PetersenGraph().am(); M # needs sage.modules [0 1 0 0 1 1 0 0 0 0] [1 0 1 0 0 0 1 0 0 0] [0 1 0 1 0 0 0 1 0 0] @@ -708,82 +708,84 @@ class Graph(GenericGraph): [0 0 1 0 0 1 0 0 0 1] [0 0 0 1 0 1 1 0 0 0] [0 0 0 0 1 0 1 1 0 0] - sage: Graph(M) + sage: Graph(M) # needs sage.modules Graph on 10 vertices :: - sage: Graph(matrix([[1,2],[2,4]]),loops=True,sparse=True) + sage: Graph(matrix([[1,2], [2,4]]), loops=True, sparse=True) # needs sage.modules Looped multi-graph on 2 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 # needs sage.modules [ 0 1 -1] [ 1 0 -1/2] [ -1 -1/2 0] - sage: G = Graph(M,sparse=True); G + sage: G = Graph(M, sparse=True); G # needs sage.modules Graph on 3 vertices - sage: G.weighted() + sage: G.weighted() # needs 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, # needs 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: Graph(M) + sage: Graph(M) # needs sage.modules Graph on 6 vertices - sage: Graph(Matrix([[1],[1],[1]])) + sage: Graph(Matrix([[1],[1],[1]])) # needs sage.modules Traceback (most recent call last): ... - ValueError: there must be one or two nonzero entries per column in an incidence matrix, got entries [1, 1, 1] in column 0 - sage: Graph(Matrix([[1],[1],[0]])) + ValueError: there must be one or two nonzero entries per column + in an incidence matrix, got entries [1, 1, 1] in column 0 + sage: Graph(Matrix([[1],[1],[0]])) # needs sage.modules Graph on 3 vertices - sage: M = Matrix([[0,1,-1],[1,0,-1],[-1,-1,0]]); M + sage: M = Matrix([[0,1,-1], [1,0,-1], [-1,-1,0]]); M # needs sage.modules [ 0 1 -1] [ 1 0 -1] [-1 -1 0] - sage: Graph(M,sparse=True) + sage: Graph(M, sparse=True) # needs sage.modules Graph on 3 vertices - sage: M = Matrix([[0,1,1],[1,0,1],[-1,-1,0]]); M + sage: M = Matrix([[0,1,1], [1,0,1], [-1,-1,0]]); M # needs sage.modules [ 0 1 1] [ 1 0 1] [-1 -1 0] - sage: Graph(M) + sage: Graph(M) # needs sage.modules Traceback (most recent call last): ... ValueError: there must be one or two nonzero entries per column in an incidence matrix, got entries [1, 1] in column 2 Check that :trac:`9714` is fixed:: - sage: MA = Matrix([[1,2,0], [0,2,0], [0,0,1]]) - sage: GA = Graph(MA, format='adjacency_matrix') - sage: MI = GA.incidence_matrix(oriented=False) - sage: MI + sage: MA = Matrix([[1,2,0], [0,2,0], [0,0,1]]) # needs sage.modules + sage: GA = Graph(MA, format='adjacency_matrix') # needs sage.modules + sage: MI = GA.incidence_matrix(oriented=False); MI # needs sage.modules [2 1 1 0 0 0] [0 1 1 2 2 0] [0 0 0 0 0 2] - sage: Graph(MI).edges(sort=True, labels=None) + sage: Graph(MI).edges(sort=True, labels=None) # needs sage.modules [(0, 0), (0, 1), (0, 1), (1, 1), (1, 1), (2, 2)] - sage: M = Matrix([[1], [-1]]); M + sage: M = Matrix([[1], [-1]]); M # needs sage.modules [ 1] [-1] - sage: Graph(M).edges(sort=True) + sage: Graph(M).edges(sort=True) # needs sage.modules [(0, 1, None)] #. A Seidel adjacency matrix:: - sage: from sage.combinat.matrices.hadamard_matrix import \ - ....: regular_symmetric_hadamard_matrix_with_constant_diagonal as rshcd - sage: m=rshcd(16,1)- matrix.identity(16) - sage: Graph(m,format="seidel_adjacency_matrix").is_strongly_regular(parameters=True) + sage: from sage.combinat.matrices.hadamard_matrix import ( # needs sage.modules + ....: regular_symmetric_hadamard_matrix_with_constant_diagonal as rshcd) + sage: m = rshcd(16,1) - matrix.identity(16) # needs sage.modules + sage: Graph(m, # needs sage.modules + ....: format="seidel_adjacency_matrix").is_strongly_regular(parameters=True) (16, 6, 2, 2) #. List of edges, or labelled edges:: @@ -801,16 +803,16 @@ class Graph(GenericGraph): #. A NetworkX MultiGraph:: - sage: import networkx # optional - networkx - sage: g = networkx.MultiGraph({0:[1,2,3], 2:[4]}) # optional - networkx - sage: Graph(g) # optional - networkx + sage: import networkx # needs networkx + sage: g = networkx.MultiGraph({0:[1,2,3], 2:[4]}) # needs networkx + sage: Graph(g) # needs networkx Multi-graph on 5 vertices #. A NetworkX graph:: - sage: import networkx # optional - networkx - sage: g = networkx.Graph({0:[1,2,3], 2:[4]}) # optional - networkx - sage: DiGraph(g) # optional - networkx + sage: import networkx # needs networkx + sage: g = networkx.Graph({0:[1,2,3], 2:[4]}) # needs networkx + sage: DiGraph(g) # needs networkx Digraph on 5 vertices #. An igraph Graph (see also @@ -883,17 +885,17 @@ class Graph(GenericGraph): ... ValueError: An *undirected* igraph graph was expected. To build an directed graph, call the DiGraph constructor. - sage: m = matrix([[0, -1], [-1, 0]]) - sage: Graph(m, format="seidel_adjacency_matrix") + sage: m = matrix([[0, -1], [-1, 0]]) # needs sage.modules + sage: Graph(m, format="seidel_adjacency_matrix") # needs sage.modules Graph on 2 vertices - sage: m[0,1] = 1 - sage: Graph(m, format="seidel_adjacency_matrix") + sage: m[0,1] = 1 # needs sage.modules + sage: Graph(m, format="seidel_adjacency_matrix") # needs sage.modules Traceback (most recent call last): ... ValueError: the adjacency matrix of a Seidel graph must be symmetric - sage: m[0,1] = -1; m[1,1] = 1 - sage: Graph(m, format="seidel_adjacency_matrix") + sage: m[0,1] = -1; m[1,1] = 1 # needs sage.modules + sage: Graph(m, format="seidel_adjacency_matrix") # needs sage.modules Traceback (most recent call last): ... ValueError: the adjacency matrix of a Seidel graph must have 0s on the main diagonal @@ -907,7 +909,7 @@ class Graph(GenericGraph): Check that :trac:`27505` is fixed:: - sage: Graph(Graph().networkx_graph(), weighted=None, format='NX') + sage: Graph(Graph().networkx_graph(), weighted=None, format='NX') # needs networkx Graph on 0 vertices """ _directed = False @@ -923,12 +925,12 @@ def __init__(self, data=None, pos=None, loops=None, format=None, sage: G = Graph() sage: loads(dumps(G)) == G True - sage: a = matrix(2,2,[1,0,0,1]) - sage: Graph(a).adjacency_matrix() == a + sage: a = matrix(2,2,[1,0,0,1]) # needs sage.modules + sage: Graph(a).adjacency_matrix() == a # needs sage.modules True - sage: a = matrix(2,2,[2,0,0,1]) - sage: Graph(a,sparse=True).adjacency_matrix() == a + sage: a = matrix(2,2,[2,0,0,1]) # needs sage.modules + sage: Graph(a,sparse=True).adjacency_matrix() == a # needs sage.modules True The positions are copied when the graph is built from another graph :: @@ -973,7 +975,7 @@ def __init__(self, data=None, pos=None, loops=None, format=None, Verify that the int format works as expected (:trac:`12557`):: - sage: Graph(2).adjacency_matrix() + sage: Graph(2).adjacency_matrix() # needs sage.modules [0 0] [0 0] sage: Graph(3) == Graph(3,format='int') @@ -982,10 +984,10 @@ 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:{6:7}} - sage: grafo3 = Graph(B,weighted=True) - sage: matad = grafo3.weighted_adjacency_matrix() - sage: grafo4 = Graph(matad,format = "adjacency_matrix", weighted=True) - sage: grafo4.shortest_path(0,6,by_weight=True) + sage: grafo3 = Graph(B, weighted=True) + sage: matad = grafo3.weighted_adjacency_matrix() # needs sage.modules + sage: grafo4 = Graph(matad, format="adjacency_matrix", weighted=True) # needs sage.modules + sage: grafo4.shortest_path(0, 6, by_weight=True) # needs sage.modules [0, 1, 2, 5, 4, 6] Graphs returned when setting ``immutable=False`` are mutable:: @@ -1003,15 +1005,17 @@ def __init__(self, data=None, pos=None, loops=None, format=None, Check error messages for graphs built from incidence matrices (see :trac:`18440`):: - sage: Graph(matrix([[-1, 1, 0],[1, 0, 0]])) + sage: Graph(matrix([[-1, 1, 0],[1, 0, 0]])) # needs sage.modules Traceback (most recent call last): ... - ValueError: column 1 of the (oriented) incidence matrix contains only one nonzero value - sage: Graph(matrix([[1,1],[1,1],[1,0]])) + ValueError: column 1 of the (oriented) incidence matrix + contains only one nonzero value + sage: Graph(matrix([[1,1],[1,1],[1,0]])) # needs sage.modules Traceback (most recent call last): ... - ValueError: there must be one or two nonzero entries per column in an incidence matrix, got entries [1, 1, 1] in column 0 - sage: Graph(matrix([[3,1,1],[0,1,1]])) + ValueError: there must be one or two nonzero entries per column + in an incidence matrix, got entries [1, 1, 1] in column 0 + sage: Graph(matrix([[3,1,1],[0,1,1]])) # needs sage.modules Traceback (most recent call last): ... ValueError: each column of a non-oriented incidence matrix must sum to 2, but column 0 does not @@ -1695,7 +1699,7 @@ def is_cactus(self): Test a graph that is not outerplanar, see :trac:`24480`:: - sage: graphs.Balaban10Cage().is_cactus() + sage: graphs.Balaban10Cage().is_cactus() # needs networkx False """ self._scream_if_not_simple() @@ -1816,7 +1820,7 @@ def is_cograph(self): sage: graphs.HouseXGraph().is_cograph() True - sage: graphs.HouseGraph().is_cograph() + sage: graphs.HouseGraph().is_cograph() # needs sage.modules False .. TODO:: @@ -1827,9 +1831,9 @@ def is_cograph(self): TESTS:: - sage: [graphs.PathGraph(i).is_cograph() for i in range(6)] + sage: [graphs.PathGraph(i).is_cograph() for i in range(6)] # needs sage.modules [True, True, True, True, False, False] - sage: graphs.CycleGraph(5).is_cograph() # Self-complemented + sage: graphs.CycleGraph(5).is_cograph() # Self-complemented # needs sage.modules False """ # A cograph has no 4-vertex path as an induced subgraph. @@ -2136,7 +2140,7 @@ def is_overfull(self): sage: g = graphs.ClawGraph() sage: g Claw graph: Graph on 4 vertices - sage: edge_coloring(g, value_only=True) + sage: edge_coloring(g, value_only=True) # needs sage.numerical_mip 3 sage: g.is_overfull() False @@ -2191,7 +2195,7 @@ def is_overfull(self): sage: g.is_overfull() False sage: from sage.graphs.graph_coloring import edge_coloring - sage: max(g.degree()) + 1 == edge_coloring(g, value_only=True) + sage: max(g.degree()) + 1 == edge_coloring(g, value_only=True) # needs sage.numerical_mip True """ # # A possible optimized version. But the gain in speed is very little. @@ -2226,25 +2230,25 @@ def is_even_hole_free(self, certificate=False): Is the Petersen Graph even-hole-free :: sage: g = graphs.PetersenGraph() - sage: g.is_even_hole_free() + sage: g.is_even_hole_free() # needs sage.modules False As any chordal graph is hole-free, interval graphs behave the same way:: sage: g = graphs.RandomIntervalGraph(20) - sage: g.is_even_hole_free() + sage: g.is_even_hole_free() # needs sage.modules True It is clear, though, that a random Bipartite Graph which is not a forest has an even hole:: - sage: g = graphs.RandomBipartite(10, 10, .5) - sage: g.is_even_hole_free() and not g.is_forest() + sage: g = graphs.RandomBipartite(10, 10, .5) # needs numpy + sage: g.is_even_hole_free() and not g.is_forest() # needs numpy sage.modules False We can check the certificate returned is indeed an even cycle:: - sage: if not g.is_forest(): + sage: if not g.is_forest(): # needs numpy sage.modules ....: cycle = g.is_even_hole_free(certificate=True) ....: if cycle.order() % 2 == 1: ....: print("Error !") @@ -2259,17 +2263,18 @@ def is_even_hole_free(self, certificate=False): Bug reported in :trac:`9925`, and fixed by :trac:`9420`:: - sage: g = Graph(':SiBFGaCEF_@CE`DEGH`CEFGaCDGaCDEHaDEF`CEH`ABCDEF', loops=False, multiedges=False) - sage: g.is_even_hole_free() + sage: g = Graph(':SiBFGaCEF_@CE`DEGH`CEFGaCDGaCDEHaDEF`CEH`ABCDEF', + ....: loops=False, multiedges=False) + sage: g.is_even_hole_free() # needs sage.modules False - sage: g.is_even_hole_free(certificate=True) + sage: g.is_even_hole_free(certificate=True) # needs sage.modules Subgraph of (): Graph on 4 vertices Making sure there are no other counter-examples around :: sage: t = lambda x: (Graph(x).is_forest() or ....: isinstance(Graph(x).is_even_hole_free(certificate=True), Graph)) - sage: all( t(graphs.RandomBipartite(10, 10, .5)) for i in range(100) ) + sage: all(t(graphs.RandomBipartite(10, 10, .5)) for i in range(100)) # needs numpy sage.modules True """ girth = self.girth() @@ -2326,7 +2331,7 @@ def is_odd_hole_free(self, certificate=False): Is the Petersen Graph odd-hole-free :: sage: g = graphs.PetersenGraph() - sage: g.is_odd_hole_free() + sage: g.is_odd_hole_free() # needs sage.modules False Which was to be expected, as its girth is 5 :: @@ -2336,14 +2341,14 @@ def is_odd_hole_free(self, certificate=False): We can check the certificate returned is indeed a 5-cycle:: - sage: cycle = g.is_odd_hole_free(certificate=True) - sage: cycle.is_isomorphic(graphs.CycleGraph(5)) + sage: cycle = g.is_odd_hole_free(certificate=True) # needs sage.modules + sage: cycle.is_isomorphic(graphs.CycleGraph(5)) # needs sage.modules True As any chordal graph is hole-free, no interval graph has an odd hole:: sage: g = graphs.RandomIntervalGraph(20) - sage: g.is_odd_hole_free() + sage: g.is_odd_hole_free() # needs sage.modules True """ girth = self.odd_girth() @@ -2409,7 +2414,7 @@ def is_triangle_free(self, algorithm='dense_graph', certificate=False): or a complete Bipartite Graph:: sage: G = graphs.CompleteBipartiteGraph(5,6) - sage: G.is_triangle_free(algorithm='matrix') + sage: G.is_triangle_free(algorithm='matrix') # needs sage.modules True sage: G.is_triangle_free(algorithm='bitset') True @@ -2419,7 +2424,7 @@ def is_triangle_free(self, algorithm='dense_graph', certificate=False): a tripartite graph, though, contains many triangles:: sage: G = (3 * graphs.CompleteGraph(5)).complement() - sage: G.is_triangle_free(algorithm='matrix') + sage: G.is_triangle_free(algorithm='matrix') # needs sage.modules False sage: G.is_triangle_free(algorithm='bitset') False @@ -2542,8 +2547,11 @@ def is_split(self): graph if and only if does not contain the 4-cycle, 5-cycle or `2K_2` as an induced subgraph. Hence for the above graph we have:: - sage: forbidden_subgraphs = [graphs.CycleGraph(4), graphs.CycleGraph(5), 2 * graphs.CompleteGraph(2)] - sage: sum(g.subgraph_search_count(H,induced=True) for H in forbidden_subgraphs) + sage: forbidden_subgraphs = [graphs.CycleGraph(4), + ....: graphs.CycleGraph(5), + ....: 2 * graphs.CompleteGraph(2)] + sage: sum(g.subgraph_search_count(H, induced=True) # needs sage.modules + ....: for H in forbidden_subgraphs) 0 """ self._scream_if_not_simple() @@ -2593,45 +2601,45 @@ def is_perfect(self, certificate=False): A Bipartite Graph is always perfect :: - sage: g = graphs.RandomBipartite(8,4,.5) - sage: g.is_perfect() + sage: g = graphs.RandomBipartite(8,4,.5) # needs numpy + sage: g.is_perfect() # needs numpy sage.modules True So is the line graph of a bipartite graph:: - sage: g = graphs.RandomBipartite(4,3,0.7) - sage: g.line_graph().is_perfect() # long time + sage: g = graphs.RandomBipartite(4,3,0.7) # needs numpy + sage: g.line_graph().is_perfect() # long time # needs numpy sage.modules True As well as the Cartesian product of two complete graphs:: sage: g = graphs.CompleteGraph(3).cartesian_product(graphs.CompleteGraph(3)) - sage: g.is_perfect() + sage: g.is_perfect() # needs sage.modules True Interval Graphs, which are chordal graphs, too :: sage: g = graphs.RandomIntervalGraph(7) - sage: g.is_perfect() + sage: g.is_perfect() # needs sage.modules True The PetersenGraph, which is triangle-free and has chromatic number 3 is obviously not perfect:: sage: g = graphs.PetersenGraph() - sage: g.is_perfect() + sage: g.is_perfect() # needs sage.modules False We can obtain an induced 5-cycle as a certificate:: - sage: g.is_perfect(certificate=True) + sage: g.is_perfect(certificate=True) # needs sage.modules Subgraph of (Petersen graph): Graph on 5 vertices TESTS: Check that :trac:`13546` has been fixed:: - sage: Graph(':FgGE@I@GxGs', loops=False, multiedges=False).is_perfect() + sage: Graph(':FgGE@I@GxGs', loops=False, multiedges=False).is_perfect() # needs sage.modules False sage: g = Graph({0: [2, 3, 4, 5], ....: 1: [3, 4, 5, 6], @@ -2640,12 +2648,12 @@ def is_perfect(self, certificate=False): ....: 4: [0, 1, 2, 6], ....: 5: [0, 1, 2, 3], ....: 6: [1, 2, 3, 4]}) - sage: g.is_perfect() + sage: g.is_perfect() # needs sage.modules False TESTS:: - sage: Graph(':Ab').is_perfect() + sage: Graph(':Ab').is_perfect() # needs sage.modules Traceback (most recent call last): ... ValueError: This method is only defined for simple graphs, and yours is not one of them ! @@ -2654,7 +2662,7 @@ def is_perfect(self, certificate=False): sage: g.add_edge(0,0) sage: g.edges(sort=True) [(0, 0, None)] - sage: g.is_perfect() + sage: g.is_perfect() # needs sage.modules Traceback (most recent call last): ... ValueError: This method is only defined for simple graphs, and yours is not one of them ! @@ -2701,16 +2709,16 @@ def is_edge_transitive(self): EXAMPLES:: sage: P = graphs.PetersenGraph() - sage: P.is_edge_transitive() + sage: P.is_edge_transitive() # needs sage.libs.gap True sage: C = graphs.CubeGraph(3) - sage: C.is_edge_transitive() + sage: C.is_edge_transitive() # needs sage.libs.gap True - sage: G = graphs.GrayGraph() - sage: G.is_edge_transitive() + sage: G = graphs.GrayGraph() # needs networkx + sage: G.is_edge_transitive() # needs networkx sage.libs.gap True sage: P = graphs.PathGraph(4) - sage: P.is_edge_transitive() + sage: P.is_edge_transitive() # needs sage.libs.gap False """ from sage.libs.gap.libgap import libgap @@ -2747,10 +2755,10 @@ def is_arc_transitive(self): EXAMPLES:: sage: P = graphs.PetersenGraph() - sage: P.is_arc_transitive() + sage: P.is_arc_transitive() # needs sage.libs.gap True - sage: G = graphs.GrayGraph() - sage: G.is_arc_transitive() + sage: G = graphs.GrayGraph() # needs networkx + sage: G.is_arc_transitive() # needs networkx sage.libs.gap False """ from sage.libs.gap.libgap import libgap @@ -2784,13 +2792,13 @@ def is_half_transitive(self): The Petersen Graph is not half-transitive:: sage: P = graphs.PetersenGraph() - sage: P.is_half_transitive() + sage: P.is_half_transitive() # needs sage.libs.gap False The smallest half-transitive graph is the Holt Graph:: sage: H = graphs.HoltGraph() - sage: H.is_half_transitive() + sage: H.is_half_transitive() # needs sage.libs.gap True """ # A half-transitive graph always has only vertices of even degree @@ -2821,19 +2829,19 @@ def is_semi_symmetric(self): The Petersen graph is not semi-symmetric:: sage: P = graphs.PetersenGraph() - sage: P.is_semi_symmetric() + sage: P.is_semi_symmetric() # needs sage.libs.gap False The Gray graph is the smallest possible cubic semi-symmetric graph:: - sage: G = graphs.GrayGraph() - sage: G.is_semi_symmetric() + sage: G = graphs.GrayGraph() # needs networkx + sage: G.is_semi_symmetric() # needs networkx sage.libs.gap True Another well known semi-symmetric graph is the Ljubljana graph:: - sage: L = graphs.LjubljanaGraph() - sage: L.is_semi_symmetric() + sage: L = graphs.LjubljanaGraph() # needs networkx + sage: L.is_semi_symmetric() # needs networkx sage.libs.gap True """ # A semi-symmetric graph is always bipartite @@ -2955,8 +2963,8 @@ def degree_constrained_subgraph(self, bounds, solver=None, verbose=0, sage: g = graphs.CycleGraph(6) sage: bounds = lambda x: [1,1] - sage: m = g.degree_constrained_subgraph(bounds=bounds) - sage: m.size() + sage: m = g.degree_constrained_subgraph(bounds=bounds) # needs sage.numerical.mip + sage: m.size() # needs sage.numerical.mip 3 """ self._scream_if_not_simple() @@ -3161,8 +3169,8 @@ def minimum_outdegree_orientation(self, use_edge_labels=False, solver=None, verb optimal orientation is `\left\lceil \frac {nm} {n+m}\right\rceil`:: sage: g = graphs.CompleteBipartiteGraph(3,4) - sage: o = g.minimum_outdegree_orientation() - sage: max(o.out_degree()) == integer_ceil((4*3)/(3+4)) + sage: o = g.minimum_outdegree_orientation() # needs sage.numerical.mip + sage: max(o.out_degree()) == integer_ceil((4*3)/(3+4)) # needs sage.numerical.mip True """ self._scream_if_not_simple() @@ -3632,23 +3640,23 @@ def chromatic_index(self, solver=None, verbose=0, *, integrality_tolerance=1e-3) The path `P_n` with `n \geq 2` has chromatic index 2:: - sage: graphs.PathGraph(5).chromatic_index() + sage: graphs.PathGraph(5).chromatic_index() # needs sage.numerical.mip 2 The windmill graph with parameters `k,n` has chromatic index `(k-1)n`:: sage: k,n = 3,4 sage: G = graphs.WindmillGraph(k,n) - sage: G.chromatic_index() == (k-1)*n + sage: G.chromatic_index() == (k-1)*n # needs sage.numerical.mip True TESTS: Graphs without vertices or edges:: - sage: Graph().chromatic_index() + sage: Graph().chromatic_index() # needs sage.numerical.mip 0 - sage: Graph(2).chromatic_index() + sage: Graph(2).chromatic_index() # needs sage.numerical.mip 0 """ if not self.order() or not self.size(): @@ -3725,7 +3733,7 @@ def chromatic_number(self, algorithm="DLX", solver=None, verbose=0, A bipartite graph has (by definition) chromatic number 2:: - sage: graphs.RandomBipartite(50,50,0.7).chromatic_number() + sage: graphs.RandomBipartite(50,50,0.7).chromatic_number() # needs numpy 2 A complete multipartite graph with k parts has chromatic number `k`:: @@ -3855,14 +3863,13 @@ def coloring(self, algorithm="DLX", hex_colors=False, solver=None, verbose=0, True sage: are_equal_colorings(P, Q) True - sage: G.plot(partition=P) # optional - sage.plot + sage: G.plot(partition=P) # needs sage.plot Graphics object consisting of 16 graphics primitives - sage: G.coloring(hex_colors=True, algorithm="MILP") + sage: G.coloring(hex_colors=True, algorithm="MILP") # needs sage.plot {'#0000ff': [4], '#00ff00': [0, 6, 5], '#ff0000': [2, 1, 3]} - sage: H = G.coloring(hex_colors=True, algorithm="DLX") - sage: H + sage: H = G.coloring(hex_colors=True, algorithm="DLX"); H # needs sage.plot {'#0000ff': [4], '#00ff00': [1, 2, 3], '#ff0000': [0, 5, 6]} - sage: G.plot(vertex_colors=H) # optional - sage.plot + sage: G.plot(vertex_colors=H) # needs sage.plot Graphics object consisting of 16 graphics primitives .. PLOT:: @@ -3911,37 +3918,37 @@ def chromatic_symmetric_function(self, R=None): EXAMPLES:: - sage: s = SymmetricFunctions(ZZ).s() + sage: s = SymmetricFunctions(ZZ).s() # needs sage.combinat sage.modules sage: G = graphs.CycleGraph(5) - sage: XG = G.chromatic_symmetric_function(); XG + sage: XG = G.chromatic_symmetric_function(); XG # needs sage.combinat sage.modules p[1, 1, 1, 1, 1] - 5*p[2, 1, 1, 1] + 5*p[2, 2, 1] + 5*p[3, 1, 1] - 5*p[3, 2] - 5*p[4, 1] + 4*p[5] - sage: s(XG) + sage: s(XG) # needs sage.combinat sage.modules 30*s[1, 1, 1, 1, 1] + 10*s[2, 1, 1, 1] + 10*s[2, 2, 1] Not all graphs have a positive Schur expansion:: sage: G = graphs.ClawGraph() - sage: XG = G.chromatic_symmetric_function(); XG + sage: XG = G.chromatic_symmetric_function(); XG # needs sage.combinat sage.modules p[1, 1, 1, 1] - 3*p[2, 1, 1] + 3*p[3, 1] - p[4] - sage: s(XG) + sage: s(XG) # needs sage.combinat sage.modules 8*s[1, 1, 1, 1] + 5*s[2, 1, 1] - s[2, 2] + s[3, 1] We show that given a triangle `\{e_1, e_2, e_3\}`, we have `X_G = X_{G - e_1} + X_{G - e_2} - X_{G - e_1 - e_2}`:: sage: G = Graph([[1,2],[1,3],[2,3]]) - sage: XG = G.chromatic_symmetric_function() + sage: XG = G.chromatic_symmetric_function() # needs sage.combinat sage.modules sage: G1 = copy(G) sage: G1.delete_edge([1,2]) - sage: XG1 = G1.chromatic_symmetric_function() + sage: XG1 = G1.chromatic_symmetric_function() # needs sage.combinat sage.modules sage: G2 = copy(G) sage: G2.delete_edge([1,3]) - sage: XG2 = G2.chromatic_symmetric_function() + sage: XG2 = G2.chromatic_symmetric_function() # needs sage.combinat sage.modules sage: G3 = copy(G1) sage: G3.delete_edge([1,3]) - sage: XG3 = G3.chromatic_symmetric_function() - sage: XG == XG1 + XG2 - XG3 + sage: XG3 = G3.chromatic_symmetric_function() # needs sage.combinat sage.modules + sage: XG == XG1 + XG2 - XG3 # needs sage.combinat sage.modules True """ from sage.combinat.sf.sf import SymmetricFunctions @@ -3988,44 +3995,44 @@ def chromatic_quasisymmetric_function(self, t=None, R=None): EXAMPLES:: sage: G = Graph([[1,2,3], [[1,3], [2,3]]]) - sage: G.chromatic_quasisymmetric_function() + sage: G.chromatic_quasisymmetric_function() # needs sage.combinat sage.modules (2*t^2+2*t+2)*M[1, 1, 1] + M[1, 2] + t^2*M[2, 1] sage: G = graphs.PathGraph(4) - sage: XG = G.chromatic_quasisymmetric_function(); XG + sage: XG = G.chromatic_quasisymmetric_function(); XG # needs sage.combinat sage.modules (t^3+11*t^2+11*t+1)*M[1, 1, 1, 1] + (3*t^2+3*t)*M[1, 1, 2] + (3*t^2+3*t)*M[1, 2, 1] + (3*t^2+3*t)*M[2, 1, 1] + (t^2+t)*M[2, 2] - sage: XG.to_symmetric_function() + sage: XG.to_symmetric_function() # needs sage.combinat sage.modules (t^3+11*t^2+11*t+1)*m[1, 1, 1, 1] + (3*t^2+3*t)*m[2, 1, 1] + (t^2+t)*m[2, 2] sage: G = graphs.CompleteGraph(4) - sage: G.chromatic_quasisymmetric_function() + sage: G.chromatic_quasisymmetric_function() # needs sage.combinat sage.modules (t^6+3*t^5+5*t^4+6*t^3+5*t^2+3*t+1)*M[1, 1, 1, 1] Not all chromatic quasisymmetric functions are symmetric:: sage: G = Graph([[1,2], [1,5], [3,4], [3,5]]) - sage: G.chromatic_quasisymmetric_function().is_symmetric() + sage: G.chromatic_quasisymmetric_function().is_symmetric() # needs sage.combinat sage.modules False We check that at `t = 1`, we recover the usual chromatic symmetric function:: - sage: p = SymmetricFunctions(QQ).p() + sage: p = SymmetricFunctions(QQ).p() # needs sage.combinat sage.modules sage: G = graphs.CycleGraph(5) - sage: XG = G.chromatic_quasisymmetric_function(t=1); XG + sage: XG = G.chromatic_quasisymmetric_function(t=1); XG # needs sage.combinat sage.modules 120*M[1, 1, 1, 1, 1] + 30*M[1, 1, 1, 2] + 30*M[1, 1, 2, 1] + 30*M[1, 2, 1, 1] + 10*M[1, 2, 2] + 30*M[2, 1, 1, 1] + 10*M[2, 1, 2] + 10*M[2, 2, 1] - sage: p(XG.to_symmetric_function()) + sage: p(XG.to_symmetric_function()) # needs sage.combinat sage.modules p[1, 1, 1, 1, 1] - 5*p[2, 1, 1, 1] + 5*p[2, 2, 1] + 5*p[3, 1, 1] - 5*p[3, 2] - 5*p[4, 1] + 4*p[5] sage: G = graphs.ClawGraph() - sage: XG = G.chromatic_quasisymmetric_function(t=1); XG + sage: XG = G.chromatic_quasisymmetric_function(t=1); XG # needs sage.combinat sage.modules 24*M[1, 1, 1, 1] + 6*M[1, 1, 2] + 6*M[1, 2, 1] + M[1, 3] + 6*M[2, 1, 1] + M[3, 1] - sage: p(XG.to_symmetric_function()) + sage: p(XG.to_symmetric_function()) # needs sage.combinat sage.modules p[1, 1, 1, 1] - 3*p[2, 1, 1] + 3*p[3, 1] - p[4] """ from sage.combinat.ncsf_qsym.qsym import QuasiSymmetricFunctions @@ -4129,7 +4136,7 @@ def matching(self, value_only=False, algorithm="Edmonds", Maximum matching in a Pappus Graph:: sage: g = graphs.PappusGraph() - sage: g.matching(value_only=True) + sage: g.matching(value_only=True) # needs sage.networkx 9 Same test with the Linear Program formulation:: @@ -4149,7 +4156,7 @@ def matching(self, value_only=False, algorithm="Edmonds", and LP formulation:: sage: g = Graph([(0,1,0), (1,2,999), (2,3,-5)]) - sage: sorted(g.matching()) + sage: sorted(g.matching()) # needs sage.networkx [(0, 1, 0), (2, 3, -5)] sage: sorted(g.matching(algorithm="LP")) [(0, 1, 0), (2, 3, -5)] @@ -4158,7 +4165,7 @@ def matching(self, value_only=False, algorithm="Edmonds", LP formulation:: sage: g = Graph([(0,1,0), (1,2,999), (2,3,-5)]) - sage: g.matching(use_edge_labels=True) + sage: g.matching(use_edge_labels=True) # needs sage.networkx [(1, 2, 999)] sage: g.matching(algorithm="LP", use_edge_labels=True) [(1, 2, 999)] @@ -4168,10 +4175,10 @@ def matching(self, value_only=False, algorithm="Edmonds", sage: edge_list = [(0,0,5), (0,1,1), (0,2,2), (0,3,3), (1,2,6) ....: , (1,2,3), (1,3,3), (2,3,3)] sage: g = Graph(edge_list, loops=True, multiedges=True) - sage: m = g.matching(use_edge_labels=True) - sage: type(m) + sage: m = g.matching(use_edge_labels=True) # needs sage.networkx + sage: type(m) # needs sage.networkx - sage: sorted(m) + sage: sorted(m) # needs sage.networkx [(0, 3, 3), (1, 2, 6)] TESTS: @@ -4306,9 +4313,9 @@ def is_factor_critical(self, matching=None, algorithm='Edmonds', solver=None, ve Odd length cycles and odd cliques of order at least 3 are factor-critical graphs:: - sage: [graphs.CycleGraph(2*i + 1).is_factor_critical() for i in range(5)] + sage: [graphs.CycleGraph(2*i + 1).is_factor_critical() for i in range(5)] # needs networkx [True, True, True, True, True] - sage: [graphs.CompleteGraph(2*i + 1).is_factor_critical() for i in range(5)] + sage: [graphs.CompleteGraph(2*i + 1).is_factor_critical() for i in range(5)] # needs networkx [True, True, True, True, True] More generally, every Hamiltonian graph with an odd number of vertices @@ -4319,18 +4326,18 @@ def is_factor_critical(self, matching=None, algorithm='Edmonds', solver=None, ve sage: G.add_edge(14, 0) sage: G.is_hamiltonian() True - sage: G.is_factor_critical() + sage: G.is_factor_critical() # needs networkx True Friendship graphs are non-Hamiltonian factor-critical graphs:: - sage: [graphs.FriendshipGraph(i).is_factor_critical() for i in range(1, 5)] + sage: [graphs.FriendshipGraph(i).is_factor_critical() for i in range(1, 5)] # needs networkx [True, True, True, True] Bipartite graphs are not factor-critical:: - sage: G = graphs.RandomBipartite(randint(1, 10), randint(1, 10), .5) - sage: G.is_factor_critical() + sage: G = graphs.RandomBipartite(randint(1, 10), randint(1, 10), .5) # needs numpy + sage: G.is_factor_critical() # needs numpy False Graphs with even order are not factor critical:: @@ -4342,10 +4349,10 @@ def is_factor_critical(self, matching=None, algorithm='Edmonds', solver=None, ve One can specify a matching:: sage: F = graphs.FriendshipGraph(4) - sage: M = F.matching() - sage: F.is_factor_critical(matching=M) + sage: M = F.matching() # needs networkx + sage: F.is_factor_critical(matching=M) # needs networkx True - sage: F.is_factor_critical(matching=Graph(M)) + sage: F.is_factor_critical(matching=Graph(M)) # needs networkx True TESTS: @@ -4355,8 +4362,8 @@ def is_factor_critical(self, matching=None, algorithm='Edmonds', solver=None, ve sage: G = graphs.RandomGNP(15, .3) sage: while not G.is_biconnected(): ....: G = graphs.RandomGNP(15, .3) - sage: M = G.matching() - sage: G.is_factor_critical(matching=M[:-1]) + sage: M = G.matching() # needs networkx + sage: G.is_factor_critical(matching=M[:-1]) # needs networkx Traceback (most recent call last): ... ValueError: the input is not a near perfect matching of the graph @@ -4498,8 +4505,8 @@ def has_homomorphism_to(self, H, core=False, solver=None, verbose=0, with this method :: sage: g = graphs.CycleGraph(10) - sage: mapping = g.has_homomorphism_to(g, core = True) - sage: print("The size of the core is {}".format(len(set(mapping.values())))) + sage: mapping = g.has_homomorphism_to(g, core=True) # needs sage.numerical.mip + sage: print("The size of the core is {}".format(len(set(mapping.values())))) # needs sage.numerical.mip The size of the core is 2 OUTPUT: @@ -4513,18 +4520,18 @@ def has_homomorphism_to(self, H, core=False, solver=None, verbose=0, Is Petersen's graph 3-colorable:: sage: P = graphs.PetersenGraph() - sage: P.has_homomorphism_to(graphs.CompleteGraph(3)) is not False + sage: P.has_homomorphism_to(graphs.CompleteGraph(3)) is not False # needs sage.numerical.mip True An odd cycle admits a homomorphism to a smaller odd cycle, but not to an even cycle:: sage: g = graphs.CycleGraph(9) - sage: g.has_homomorphism_to(graphs.CycleGraph(5)) is not False + sage: g.has_homomorphism_to(graphs.CycleGraph(5)) is not False # needs sage.numerical.mip True - sage: g.has_homomorphism_to(graphs.CycleGraph(7)) is not False + sage: g.has_homomorphism_to(graphs.CycleGraph(7)) is not False # needs sage.numerical.mip True - sage: g.has_homomorphism_to(graphs.CycleGraph(4)) is not False + sage: g.has_homomorphism_to(graphs.CycleGraph(4)) is not False # needs sage.numerical.mip False """ self._scream_if_not_simple() @@ -4616,7 +4623,7 @@ def fractional_clique_number(self, solver='PPL', verbose=0, The fractional clique number of a `C_7` is `7/3`:: sage: g = graphs.CycleGraph(7) - sage: g.fractional_clique_number() + sage: g.fractional_clique_number() # needs sage.numerical.mip 7/3 """ return self.fractional_chromatic_number(solver=solver, verbose=verbose, @@ -4660,48 +4667,48 @@ def maximum_average_degree(self, value_only=True, solver=None, verbose=0): In any graph, the `Mad` is always larger than the average degree:: sage: g = graphs.RandomGNP(20,.3) - sage: mad_g = g.maximum_average_degree() - sage: g.average_degree() <= mad_g + sage: mad_g = g.maximum_average_degree() # needs sage.numerical.mip + sage: g.average_degree() <= mad_g # needs sage.numerical.mip True Unlike the average degree, the `Mad` of the disjoint union of two graphs is the maximum of the `Mad` of each graphs:: sage: h = graphs.RandomGNP(20,.3) - sage: mad_h = h.maximum_average_degree() - sage: (g+h).maximum_average_degree() == max(mad_g, mad_h) + sage: mad_h = h.maximum_average_degree() # needs sage.numerical.mip + sage: (g+h).maximum_average_degree() == max(mad_g, mad_h) # needs sage.numerical.mip True The subgraph of a regular graph realizing the maximum average degree is always the whole graph :: sage: g = graphs.CompleteGraph(5) - sage: mad_g = g.maximum_average_degree(value_only=False) - sage: g.is_isomorphic(mad_g) + sage: mad_g = g.maximum_average_degree(value_only=False) # needs sage.numerical.mip + sage: g.is_isomorphic(mad_g) # needs sage.numerical.mip True This also works for complete bipartite graphs :: sage: g = graphs.CompleteBipartiteGraph(3,4) - sage: mad_g = g.maximum_average_degree(value_only=False) - sage: g.is_isomorphic(mad_g) + sage: mad_g = g.maximum_average_degree(value_only=False) # needs sage.numerical.mip + sage: g.is_isomorphic(mad_g) # needs sage.numerical.mip True TESTS: Check corner cases:: - sage: Graph().maximum_average_degree(value_only=True) + sage: Graph().maximum_average_degree(value_only=True) # needs sage.numerical.mip 0 - sage: Graph().maximum_average_degree(value_only=False) + sage: Graph().maximum_average_degree(value_only=False) # needs sage.numerical.mip Graph on 0 vertices - sage: Graph(1).maximum_average_degree(value_only=True) + sage: Graph(1).maximum_average_degree(value_only=True) # needs sage.numerical.mip 0 - sage: Graph(1).maximum_average_degree(value_only=False) + sage: Graph(1).maximum_average_degree(value_only=False) # needs sage.numerical.mip Graph on 1 vertex - sage: Graph(2).maximum_average_degree(value_only=True) + sage: Graph(2).maximum_average_degree(value_only=True) # needs sage.numerical.mip 0 - sage: Graph(2).maximum_average_degree(value_only=False) + sage: Graph(2).maximum_average_degree(value_only=False) # needs sage.numerical.mip Graph on 1 vertex """ self._scream_if_not_simple() @@ -4794,7 +4801,7 @@ def independent_set_of_representatives(self, family, solver=None, verbose=0, sage: g = graphs.CompleteBipartiteGraph(3,3) sage: g.delete_edge(1,4) - sage: g.independent_set_of_representatives([[0,1,2],[3,4,5]]) + sage: g.independent_set_of_representatives([[0,1,2],[3,4,5]]) # needs sage.numerical.mip [1, 4] The Petersen Graph is 3-colorable, which can be expressed as an @@ -4806,12 +4813,12 @@ def independent_set_of_representatives(self, family, solver=None, verbose=0, sage: g = 3 * graphs.PetersenGraph() sage: n = g.order() / 3 sage: f = [[i, i + n, i + 2*n] for i in range(n)] - sage: isr = g.independent_set_of_representatives(f) - sage: c = [integer_floor(i / n) for i in isr] + sage: isr = g.independent_set_of_representatives(f) # needs sage.numerical.mip + sage: c = [integer_floor(i / n) for i in isr] # needs sage.numerical.mip sage: color_classes = [[], [], []] - sage: for v, i in enumerate(c): + sage: for v, i in enumerate(c): # needs sage.numerical.mip ....: color_classes[i].append(v) - sage: for classs in color_classes: + sage: for classs in color_classes: # needs sage.numerical.mip ....: g.subgraph(classs).size() == 0 True True @@ -4925,21 +4932,21 @@ def minor(self, H, solver=None, verbose=0, *, integrality_tolerance=1e-3): sage: g = graphs.GridGraph([4,4]) sage: h = graphs.CompleteGraph(4) - sage: L = g.minor(h) - sage: gg = g.subgraph(flatten(L.values(), max_level = 1)) - sage: _ = [gg.merge_vertices(l) for l in L.values() if len(l)>1] - sage: gg.is_isomorphic(h) + sage: L = g.minor(h) # needs sage.numerical.mip + sage: gg = g.subgraph(flatten(L.values(), max_level = 1)) # needs sage.numerical.mip + sage: _ = [gg.merge_vertices(l) for l in L.values() if len(l)>1] # needs sage.numerical.mip + sage: gg.is_isomorphic(h) # needs sage.numerical.mip True We can also try to prove this way that the Petersen graph is not planar, as it has a `K_5` minor:: sage: g = graphs.PetersenGraph() - sage: K5_minor = g.minor(graphs.CompleteGraph(5)) # long time + sage: K5_minor = g.minor(graphs.CompleteGraph(5)) # long time # needs sage.numerical.mip And even a `K_{3,3}` minor:: - sage: K33_minor = g.minor(graphs.CompleteBipartiteGraph(3,3)) # long time + sage: K33_minor = g.minor(graphs.CompleteBipartiteGraph(3,3)) # long time, needs sage.numerical.mip (It is much faster to use the linear-time test of planarity in this situation, though.) @@ -4951,7 +4958,7 @@ def minor(self, H, solver=None, verbose=0, *, integrality_tolerance=1e-3): sage: g = g.subgraph(edges = g.min_spanning_tree()) sage: g.is_tree() True - sage: L = g.minor(graphs.CompleteGraph(3)) + sage: L = g.minor(graphs.CompleteGraph(3)) # needs sage.numerical.mip Traceback (most recent call last): ... ValueError: This graph has no minor isomorphic to H ! @@ -5234,7 +5241,7 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, [1, 1, 1] sage: G.eccentricity(algorithm = 'Floyd-Warshall-Cython') [1, 1, 1] - sage: G.eccentricity(by_weight = True, algorithm = 'Dijkstra_NetworkX') + sage: G.eccentricity(by_weight=True, algorithm='Dijkstra_NetworkX') # needs networkx [2, 1, 2] sage: G.eccentricity(by_weight = True, algorithm = 'Dijkstra_Boost') [2, 1, 2] @@ -5769,7 +5776,7 @@ def distance_graph(self, dist): sage: G = graphs.CompleteGraph(3) sage: H = G.cartesian_product(graphs.CompleteGraph(2)) sage: K = H.distance_graph(2) - sage: K.am() + sage: K.am() # needs sage.modules [0 0 0 1 0 1] [0 0 1 0 1 0] [0 1 0 0 0 1] @@ -5797,8 +5804,8 @@ def distance_graph(self, dist): that sum to the matrix of all ones:: sage: P = graphs.PathGraph(20) - sage: all_ones = sum([P.distance_graph(i).am() for i in range(20)]) - sage: all_ones == matrix(ZZ, 20, 20, [1]*400) + sage: all_ones = sum([P.distance_graph(i).am() for i in range(20)]) # needs sage.modules + sage: all_ones == matrix(ZZ, 20, 20, [1]*400) # needs sage.modules True Four-bit strings differing in one bit is the same as @@ -5825,7 +5832,7 @@ def distance_graph(self, dist): sage: G = graphs.CompleteGraph(3) sage: H = G.disjoint_union(graphs.CompleteGraph(2)) sage: L = H.distance_graph(Infinity) - sage: L.am() + sage: L.am() # needs sage.modules [0 0 0 1 1] [0 0 0 1 1] [0 0 0 1 1] @@ -5950,12 +5957,12 @@ def to_directed(self, data_structure=None, sparse=None): :trac:`22424`:: sage: G1 = graphs.RandomGNP(5,0.5) - sage: gp1 = G1.graphplot(save_pos=True) # optional - sage.plot + sage: gp1 = G1.graphplot(save_pos=True) # needs sage.plot sage: G2 = G1.to_directed() sage: G2.delete_vertex(0) sage: G2.add_vertex(5) - sage: gp2 = G2.graphplot() # optional - sage.plot - sage: gp1 = G1.graphplot() # optional - sage.plot + sage: gp2 = G2.graphplot() # needs sage.plot + sage: gp1 = G1.graphplot() # needs sage.plot Vertex labels will be retained (:trac:`14708`):: @@ -6114,14 +6121,14 @@ def seidel_adjacency_matrix(self, vertices=None, *, base_ring=None, **kwds): sage: G = graphs.CycleGraph(5) sage: G = G.disjoint_union(graphs.CompleteGraph(1)) - sage: G.seidel_adjacency_matrix().minpoly() + sage: G.seidel_adjacency_matrix().minpoly() # needs sage.libs.pari sage.modules x^2 - 5 Selecting the base ring:: - sage: G.seidel_adjacency_matrix()[0, 0].parent() + sage: G.seidel_adjacency_matrix()[0, 0].parent() # needs sage.modules Integer Ring - sage: G.seidel_adjacency_matrix(base_ring=RDF)[0, 0].parent() + sage: G.seidel_adjacency_matrix(base_ring=RDF)[0, 0].parent() # needs sage.modules Real Double Field """ set_immutable = kwds.pop('immutable', False) @@ -6161,7 +6168,7 @@ def seidel_switching(self, s, inplace=True): sage: G = graphs.CycleGraph(5) sage: G = G.disjoint_union(graphs.CompleteGraph(1)) sage: G.seidel_switching([(0,1),(1,0),(0,0)]) - sage: G.seidel_adjacency_matrix().minpoly() + sage: G.seidel_adjacency_matrix().minpoly() # needs sage.libs.pari sage.modules x^2 - 5 sage: G.is_connected() True @@ -6192,13 +6199,14 @@ def twograph(self): EXAMPLES:: - sage: p=graphs.PetersenGraph() - sage: p.twograph() + sage: p = graphs.PetersenGraph() + sage: p.twograph() # needs sage.modules Incidence structure with 10 points and 60 blocks sage: p=graphs.chang_graphs() sage: T8 = graphs.CompleteGraph(8).line_graph() - sage: C = T8.seidel_switching([(0,1,None),(2,3,None),(4,5,None),(6,7,None)],inplace=False) - sage: T8.twograph() == C.twograph() + sage: C = T8.seidel_switching([(0,1,None), (2,3,None), (4,5,None), (6,7,None)], + ....: inplace=False) + sage: T8.twograph() == C.twograph() # needs sage.modules True sage: T8.is_isomorphic(C) False @@ -6206,8 +6214,8 @@ def twograph(self): TESTS:: sage: from sage.combinat.designs.twographs import TwoGraph - sage: p=graphs.PetersenGraph().twograph() - sage: TwoGraph(p, check=True) + sage: p = graphs.PetersenGraph().twograph() # needs sage.modules + sage: TwoGraph(p, check=True) # needs sage.modules Incidence structure with 10 points and 60 blocks .. SEEALSO:: @@ -6341,19 +6349,19 @@ def topological_minor(self, H, vertices=False, paths=False, solver=None, verbose Petersen's graph has a topological `K_4`-minor:: sage: g = graphs.PetersenGraph() - sage: g.topological_minor(graphs.CompleteGraph(4)) + sage: g.topological_minor(graphs.CompleteGraph(4)) # needs sage.numerical.mip Subgraph of (Petersen graph): Graph on ... And a topological `K_{3,3}`-minor:: - sage: g.topological_minor(graphs.CompleteBipartiteGraph(3,3)) + sage: g.topological_minor(graphs.CompleteBipartiteGraph(3,3)) # needs sage.numerical.mip Subgraph of (Petersen graph): Graph on ... And of course, a tree has no topological `C_3`-minor:: sage: g = graphs.RandomGNP(15,.3) - sage: g = g.subgraph(edges = g.min_spanning_tree()) - sage: g.topological_minor(graphs.CycleGraph(3)) + sage: g = g.subgraph(edges=g.min_spanning_tree()) + sage: g.topological_minor(graphs.CycleGraph(3)) # needs sage.numerical.mip False """ self._scream_if_not_simple() @@ -6545,7 +6553,7 @@ def cliques_maximal(self, algorithm="native"): [2, 6], [2, 8], [3, 4], [3, 7], [3, 9], [4, 5], [4, 8], [5, 10], [5, 11], [6, 10], [6, 11], [7, 8], [7, 11], [8, 10], [9, 10], [9, 11]] sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]}) - sage: G.show(figsize=[2, 2]) # optional - sage.plot + sage: G.show(figsize=[2, 2]) # needs sage.plot sage: G.cliques_maximal() [[0, 1, 2], [0, 1, 3]] sage: C = graphs.PetersenGraph() @@ -6559,9 +6567,9 @@ def cliques_maximal(self, algorithm="native"): Comparing the two implementations:: sage: g = graphs.RandomGNP(20,.7) - sage: s1 = Set(map(Set, g.cliques_maximal(algorithm="NetworkX"))) + sage: s1 = Set(map(Set, g.cliques_maximal(algorithm="NetworkX"))) # needs networkx sage: s2 = Set(map(Set, g.cliques_maximal(algorithm="native"))) - sage: s1 == s2 + sage: s1 == s2 # needs networkx True """ if algorithm == "native": @@ -6720,7 +6728,7 @@ def clique_number(self, algorithm="Cliquer", cliques=None, solver=None, verbose= sage: C.clique_number() 4 sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]}) - sage: G.show(figsize=[2,2]) # optional - sage.plot + sage: G.show(figsize=[2,2]) # needs sage.plot sage: G.clique_number() 3 @@ -6744,9 +6752,9 @@ def clique_number(self, algorithm="Cliquer", cliques=None, solver=None, verbose= TESTS:: sage: g = graphs.PetersenGraph() - sage: g.clique_number(algorithm="MILP") + sage: g.clique_number(algorithm="MILP") # needs sage.numerical.mip 2 - sage: for i in range(10): # optional - mcqd + sage: for i in range(10): # optional - mcqd # needs sage.numerical.mip ....: g = graphs.RandomGNP(15,.5) ....: if g.clique_number() != g.clique_number(algorithm="mcqd"): ....: print("This is dead wrong !") @@ -6789,23 +6797,23 @@ def cliques_number_of(self, vertices=None, cliques=None): EXAMPLES:: sage: C = Graph('DJ{') - sage: C.cliques_number_of() + sage: C.cliques_number_of() # needs networkx {0: 1, 1: 1, 2: 1, 3: 1, 4: 2} sage: E = C.cliques_maximal() sage: E [[0, 4], [1, 2, 3, 4]] - sage: C.cliques_number_of(cliques=E) + sage: C.cliques_number_of(cliques=E) # needs networkx {0: 1, 1: 1, 2: 1, 3: 1, 4: 2} sage: F = graphs.Grid2dGraph(2,3) - sage: F.cliques_number_of() + sage: F.cliques_number_of() # needs networkx {(0, 0): 2, (0, 1): 3, (0, 2): 2, (1, 0): 2, (1, 1): 3, (1, 2): 2} - sage: F.cliques_number_of(vertices=[(0, 1), (1, 2)]) + sage: F.cliques_number_of(vertices=[(0, 1), (1, 2)]) # needs networkx {(0, 1): 3, (1, 2): 2} sage: F.cliques_number_of(vertices=(0, 1)) 3 sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]}) - sage: G.show(figsize=[2,2]) # optional - sage.plot - sage: G.cliques_number_of() + sage: G.show(figsize=[2,2]) # needs sage.plot + sage: G.cliques_number_of() # needs networkx {0: 2, 1: 2, 2: 1, 3: 1} """ if cliques is None: @@ -6840,14 +6848,14 @@ def cliques_get_max_clique_graph(self): EXAMPLES:: - sage: MCG = graphs.ChvatalGraph().cliques_get_max_clique_graph(); MCG + sage: MCG = graphs.ChvatalGraph().cliques_get_max_clique_graph(); MCG # needs networkx Graph on 24 vertices - sage: MCG.show(figsize=[2,2], vertex_size=20, vertex_labels=False) # optional - sage.plot + sage: MCG.show(figsize=[2,2], vertex_size=20, vertex_labels=False) # needs networkx sage.plot sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]}) - sage: G.show(figsize=[2,2]) # optional - sage.plot - sage: G.cliques_get_max_clique_graph() + sage: G.show(figsize=[2,2]) # needs sage.plot + sage: G.cliques_get_max_clique_graph() # needs networkx Graph on 2 vertices - sage: G.cliques_get_max_clique_graph().show(figsize=[2,2]) # optional - sage.plot + sage: G.cliques_get_max_clique_graph().show(figsize=[2,2]) # needs networkx sage.plot """ import networkx return Graph(networkx.make_max_clique_graph(self.networkx_graph(), create_using=networkx.MultiGraph()), @@ -6868,14 +6876,14 @@ def cliques_get_clique_bipartite(self, **kwds): EXAMPLES:: - sage: CBG = graphs.ChvatalGraph().cliques_get_clique_bipartite(); CBG + sage: CBG = graphs.ChvatalGraph().cliques_get_clique_bipartite(); CBG # needs networkx Bipartite graph on 36 vertices - sage: CBG.show(figsize=[2,2], vertex_size=20, vertex_labels=False) # optional - sage.plot + sage: CBG.show(figsize=[2,2], vertex_size=20, vertex_labels=False) # needs networkx sage.plot sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]}) - sage: G.show(figsize=[2,2]) # optional - sage.plot - sage: G.cliques_get_clique_bipartite() + sage: G.show(figsize=[2,2]) # needs sage.plot + sage: G.cliques_get_clique_bipartite() # needs networkx Bipartite graph on 6 vertices - sage: G.cliques_get_clique_bipartite().show(figsize=[2,2]) # optional - sage.plot + sage: G.cliques_get_clique_bipartite().show(figsize=[2,2]) # needs networkx sage.plot """ from .bipartite_graph import BipartiteGraph import networkx @@ -6958,7 +6966,7 @@ def independent_set(self, algorithm="Cliquer", value_only=False, reduction_rules As a linear program:: sage: C = graphs.PetersenGraph() - sage: len(C.independent_set(algorithm="MILP")) + sage: len(C.independent_set(algorithm="MILP")) # needs sage.numerical.mip 4 .. PLOT:: @@ -7057,9 +7065,9 @@ def vertex_cover(self, algorithm="Cliquer", value_only=False, The two algorithms should return the same result:: sage: g = graphs.RandomGNP(10, .5) - sage: vc1 = g.vertex_cover(algorithm="MILP") + sage: vc1 = g.vertex_cover(algorithm="MILP") # needs sage.numerical.mip sage: vc2 = g.vertex_cover(algorithm="Cliquer") - sage: len(vc1) == len(vc2) + sage: len(vc1) == len(vc2) # needs sage.numerical.mip True The cardinality of the vertex cover is unchanged when reduction rules @@ -7110,9 +7118,9 @@ def vertex_cover(self, algorithm="Cliquer", value_only=False, Issue :trac:`24287` is fixed:: sage: G = Graph([(0,1)]*5 + [(1,2)]*2, multiedges=True) - sage: G.vertex_cover(reduction_rules=True, algorithm='MILP') + sage: G.vertex_cover(reduction_rules=True, algorithm='MILP') # needs sage.numerical.mip [1] - sage: G.vertex_cover(reduction_rules=False) + sage: G.vertex_cover(reduction_rules=False) # needs sage.numerical.mip [1] Issue :trac:`25988` is fixed:: @@ -7466,20 +7474,20 @@ def cliques_vertex_clique_number(self, algorithm="cliquer", vertices=None, EXAMPLES:: sage: C = Graph('DJ{') - sage: C.cliques_vertex_clique_number() # optional - sage.plot + sage: C.cliques_vertex_clique_number() # needs sage.plot {0: 2, 1: 4, 2: 4, 3: 4, 4: 4} sage: E = C.cliques_maximal(); E [[0, 4], [1, 2, 3, 4]] - sage: C.cliques_vertex_clique_number(cliques=E, algorithm="networkx") # optional - sage.plot + sage: C.cliques_vertex_clique_number(cliques=E, algorithm="networkx") # needs networkx sage.plot {0: 2, 1: 4, 2: 4, 3: 4, 4: 4} sage: F = graphs.Grid2dGraph(2,3) - sage: F.cliques_vertex_clique_number(algorithm="networkx") # optional - sage.plot + sage: F.cliques_vertex_clique_number(algorithm="networkx") # needs networkx sage.plot {(0, 0): 2, (0, 1): 2, (0, 2): 2, (1, 0): 2, (1, 1): 2, (1, 2): 2} - sage: F.cliques_vertex_clique_number(vertices=[(0, 1), (1, 2)]) # optional - sage.plot + sage: F.cliques_vertex_clique_number(vertices=[(0, 1), (1, 2)]) # needs sage.plot {(0, 1): 2, (1, 2): 2} sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]}) - sage: G.show(figsize=[2,2]) # optional - sage.plot - sage: G.cliques_vertex_clique_number() # optional - sage.plot + sage: G.show(figsize=[2,2]) # needs sage.plot + sage: G.cliques_vertex_clique_number() # needs sage.plot {0: 3, 1: 3, 2: 3, 3: 3} """ if algorithm == "cliquer": @@ -7519,20 +7527,19 @@ def cliques_containing_vertex(self, vertices=None, cliques=None): EXAMPLES:: sage: C = Graph('DJ{') - sage: C.cliques_containing_vertex() + sage: C.cliques_containing_vertex() # needs networkx {0: [[0, 4]], 1: [[1, 2, 3, 4]], 2: [[1, 2, 3, 4]], 3: [[1, 2, 3, 4]], 4: [[0, 4], [1, 2, 3, 4]]} - sage: C.cliques_containing_vertex(4) + sage: C.cliques_containing_vertex(4) # needs networkx [[0, 4], [1, 2, 3, 4]] - sage: C.cliques_containing_vertex([0, 1]) + sage: C.cliques_containing_vertex([0, 1]) # needs networkx {0: [[0, 4]], 1: [[1, 2, 3, 4]]} - sage: E = C.cliques_maximal() - sage: E + sage: E = C.cliques_maximal(); E # needs networkx [[0, 4], [1, 2, 3, 4]] - sage: C.cliques_containing_vertex(cliques=E) + sage: C.cliques_containing_vertex(cliques=E) # needs networkx {0: [[0, 4]], 1: [[1, 2, 3, 4]], 2: [[1, 2, 3, 4]], @@ -7540,8 +7547,8 @@ def cliques_containing_vertex(self, vertices=None, cliques=None): 4: [[0, 4], [1, 2, 3, 4]]} sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]}) - sage: G.show(figsize=[2,2]) # optional - sage.plot - sage: G.cliques_containing_vertex() + sage: G.show(figsize=[2,2]) # needs sage.plot + sage: G.cliques_containing_vertex() # needs networkx {0: [[0, 1, 2], [0, 1, 3]], 1: [[0, 1, 2], [0, 1, 3]], 2: [[0, 1, 2]], @@ -7551,13 +7558,13 @@ def cliques_containing_vertex(self, vertices=None, cliques=None): number of cliques in which a vertex is involved equals its degree:: sage: F = graphs.Grid2dGraph(2,3) - sage: d = F.cliques_containing_vertex() - sage: all(F.degree(u) == len(cliques) for u,cliques in d.items()) + sage: d = F.cliques_containing_vertex() # needs networkx + sage: all(F.degree(u) == len(cliques) for u,cliques in d.items()) # needs networkx True - sage: d = F.cliques_containing_vertex(vertices=[(0, 1)]) - sage: list(d) + sage: d = F.cliques_containing_vertex(vertices=[(0, 1)]) # needs networkx + sage: list(d) # needs networkx [(0, 1)] - sage: sorted(sorted(x for x in L) for L in d[(0, 1)]) + sage: sorted(sorted(x for x in L) for L in d[(0, 1)]) # needs networkx [[(0, 0), (0, 1)], [(0, 1), (0, 2)], [(0, 1), (1, 1)]] """ if cliques is None: @@ -7717,19 +7724,20 @@ def cores(self, k=None, with_labels=False): sage: (graphs.FruchtGraph()).cores(with_labels=True) {0: 3, 1: 3, 2: 3, 3: 3, 4: 3, 5: 3, 6: 3, 7: 3, 8: 3, 9: 3, 10: 3, 11: 3} sage: set_random_seed(0) - sage: a = random_matrix(ZZ, 20, x=2, sparse=True, density=.1) + sage: a = random_matrix(ZZ, 20, x=2, sparse=True, density=.1) # needs sage.modules sage: b = Graph(20) - sage: b.add_edges(a.nonzero_positions(), loops=False) - sage: cores = b.cores(with_labels=True); cores - {0: 3, 1: 3, 2: 3, 3: 3, 4: 2, 5: 2, 6: 3, 7: 1, 8: 3, 9: 3, 10: 3, 11: 3, 12: 3, 13: 3, 14: 2, 15: 3, 16: 3, 17: 3, 18: 3, 19: 3} - sage: [v for v,c in cores.items() if c >= 2] # the vertices in the 2-core + sage: b.add_edges(a.nonzero_positions(), loops=False) # needs sage.modules + sage: cores = b.cores(with_labels=True); cores # needs sage.modules + {0: 3, 1: 3, 2: 3, 3: 3, 4: 2, 5: 2, 6: 3, 7: 1, 8: 3, 9: 3, 10: 3, + 11: 3, 12: 3, 13: 3, 14: 2, 15: 3, 16: 3, 17: 3, 18: 3, 19: 3} + sage: [v for v,c in cores.items() if c >= 2] # the vertices in the 2-core # needs sage.modules [0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] Checking the 2-core of a random lobster is indeed the empty set:: - sage: g = graphs.RandomLobster(20, .5, .5) - sage: ordering, core = g.cores(2) - sage: len(core) == 0 + sage: g = graphs.RandomLobster(20, .5, .5) # needs networkx + sage: ordering, core = g.cores(2) # needs networkx + sage: len(core) == 0 # needs networkx True Checking the cores of a bull graph:: @@ -8127,22 +8135,22 @@ def is_circumscribable(self, solver="ppl", verbose=0): EXAMPLES:: sage: C = graphs.CubeGraph(3) - sage: C.is_circumscribable() + sage: C.is_circumscribable() # needs sage.numerical.mip True sage: O = graphs.OctahedralGraph() - sage: O.is_circumscribable() + sage: O.is_circumscribable() # needs sage.numerical.mip True - sage: TT = polytopes.truncated_tetrahedron().graph() - sage: TT.is_circumscribable() + sage: TT = polytopes.truncated_tetrahedron().graph() # needs sage.geometry.polyhedron + sage: TT.is_circumscribable() # needs sage.geometry.polyhedron sage.numerical.mip False Stellating in a face of the octahedral graph is not circumscribable:: sage: f = set(flatten(choice(O.faces()))) sage: O.add_edges([[6, i] for i in f]) - sage: O.is_circumscribable() + sage: O.is_circumscribable() # needs sage.numerical.mip False .. SEEALSO:: @@ -8249,7 +8257,7 @@ def is_inscribable(self, solver="ppl", verbose=0): True sage: C = graphs.CubeGraph(3) - sage: C.is_inscribable() + sage: C.is_inscribable() # needs sage.numerical.mip True Cutting off a vertex from the cube yields an uninscribable graph:: @@ -8260,7 +8268,7 @@ def is_inscribable(self, solver="ppl", verbose=0): sage: C.add_edges(Combinations(triangle, 2)) sage: C.add_edges(zip(triangle, C.neighbors(v))) sage: C.delete_vertex(v) - sage: C.is_inscribable() + sage: C.is_inscribable() # needs sage.numerical.mip False Breaking a face of the cube yields an uninscribable graph:: @@ -8268,7 +8276,7 @@ def is_inscribable(self, solver="ppl", verbose=0): sage: C = graphs.CubeGraph(3) sage: face = choice(C.faces()) sage: C.add_edge([face[0][0], face[2][0]]) - sage: C.is_inscribable() + sage: C.is_inscribable() # needs sage.numerical.mip False @@ -8554,22 +8562,24 @@ def two_factor_petersen(self, solver=None, verbose=0, *, integrality_tolerance=1 edge-partitionned into `2`-regular graphs:: sage: g = graphs.CompleteGraph(7) - sage: classes = g.two_factor_petersen() - sage: for c in classes: + sage: classes = g.two_factor_petersen() # needs sage.numerical.mip + sage: for c in classes: # needs sage.numerical.mip ....: gg = Graph() ....: gg.add_edges(c) ....: print(max(gg.degree())<=2) True True True - sage: Set(set(classes[0]) | set(classes[1]) | set(classes[2])).cardinality() == g.size() + sage: Set(set(classes[0]) # needs sage.numerical.mip + ....: | set(classes[1]) + ....: | set(classes[2])).cardinality() == g.size() True :: sage: g = graphs.CirculantGraph(24, [7, 11]) - sage: cl = g.two_factor_petersen() - sage: g.plot(edge_colors={'black':cl[0], 'red':cl[1]}) # optional - sage.plot + sage: cl = g.two_factor_petersen() # needs sage.numerical.mip + sage: g.plot(edge_colors={'black':cl[0], 'red':cl[1]}) # needs sage.numerical.mip sage.plot Graphics object consisting of 73 graphics primitives """ @@ -8641,30 +8651,30 @@ def kirchhoff_symanzik_polynomial(self, name='t'): For the cycle of length 5:: sage: G = graphs.CycleGraph(5) - sage: G.kirchhoff_symanzik_polynomial() + sage: G.kirchhoff_symanzik_polynomial() # needs networkx sage.modules t0 + t1 + t2 + t3 + t4 One can use another letter for variables:: - sage: G.kirchhoff_symanzik_polynomial(name='u') + sage: G.kirchhoff_symanzik_polynomial(name='u') # needs networkx sage.modules u0 + u1 + u2 + u3 + u4 For the 'coffee bean' graph:: sage: G = Graph([(0,1,'a'),(0,1,'b'),(0,1,'c')], multiedges=True) - sage: G.kirchhoff_symanzik_polynomial() + sage: G.kirchhoff_symanzik_polynomial() # needs networkx sage.modules t0*t1 + t0*t2 + t1*t2 For the 'parachute' graph:: sage: G = Graph([(0,2,'a'),(0,2,'b'),(0,1,'c'),(1,2,'d')], multiedges=True) - sage: G.kirchhoff_symanzik_polynomial() + sage: G.kirchhoff_symanzik_polynomial() # needs networkx sage.modules t0*t1 + t0*t2 + t1*t2 + t1*t3 + t2*t3 For the complete graph with 4 vertices:: sage: G = graphs.CompleteGraph(4) - sage: G.kirchhoff_symanzik_polynomial() + sage: G.kirchhoff_symanzik_polynomial() # needs networkx sage.modules t0*t1*t3 + t0*t2*t3 + t1*t2*t3 + t0*t1*t4 + t0*t2*t4 + t1*t2*t4 + t1*t3*t4 + t2*t3*t4 + t0*t1*t5 + t0*t2*t5 + t1*t2*t5 + t0*t3*t5 + t2*t3*t5 + t0*t4*t5 + t1*t4*t5 + t3*t4*t5 @@ -8714,44 +8724,44 @@ def magnitude_function(self): EXAMPLES:: sage: g = Graph({1:[], 2:[]}) - sage: g.magnitude_function() + sage: g.magnitude_function() # needs sage.modules 2 sage: g = graphs.CycleGraph(4) - sage: g.magnitude_function() + sage: g.magnitude_function() # needs sage.modules 4/(q^2 + 2*q + 1) sage: g = graphs.CycleGraph(5) - sage: m = g.magnitude_function(); m + sage: m = g.magnitude_function(); m # needs sage.modules 5/(2*q^2 + 2*q + 1) One can expand the magnitude as a power series in `q` as follows:: sage: q = QQ[['q']].gen() - sage: m(q) + sage: m(q) # needs sage.modules 5 - 10*q + 10*q^2 - 20*q^4 + 40*q^5 - 40*q^6 + ... One can also use the substitution `q = exp(-t)` to obtain the magnitude function as a function of `t`:: sage: g = graphs.CycleGraph(6) - sage: m = g.magnitude_function() - sage: t = var('t') # optional - sage.symbolic - sage: m(exp(-t)) # optional - sage.symbolic + sage: m = g.magnitude_function() # needs sage.modules + sage: t = var('t') # needs sage.modules sage.symbolic + sage: m(exp(-t)) # needs sage.modules sage.symbolic 6/(2*e^(-t) + 2*e^(-2*t) + e^(-3*t) + 1) TESTS:: sage: g = Graph() - sage: g.magnitude_function() + sage: g.magnitude_function() # needs sage.modules 0 sage: g = Graph({1:[]}) - sage: g.magnitude_function() + sage: g.magnitude_function() # needs sage.modules 1 sage: g = graphs.PathGraph(4) - sage: g.magnitude_function() + sage: g.magnitude_function() # needs sage.modules (-2*q + 4)/(q + 1) REFERENCES: @@ -8805,20 +8815,20 @@ def ihara_zeta_function_inverse(self): EXAMPLES:: sage: G = graphs.CompleteGraph(4) - sage: factor(G.ihara_zeta_function_inverse()) + sage: factor(G.ihara_zeta_function_inverse()) # needs sage.libs.pari sage.modules (2*t - 1) * (t + 1)^2 * (t - 1)^3 * (2*t^2 + t + 1)^3 sage: G = graphs.CompleteGraph(5) - sage: factor(G.ihara_zeta_function_inverse()) + sage: factor(G.ihara_zeta_function_inverse()) # needs sage.libs.pari sage.modules (-1) * (3*t - 1) * (t + 1)^5 * (t - 1)^6 * (3*t^2 + t + 1)^4 sage: G = graphs.PetersenGraph() - sage: factor(G.ihara_zeta_function_inverse()) + sage: factor(G.ihara_zeta_function_inverse()) # needs sage.libs.pari sage.modules (-1) * (2*t - 1) * (t + 1)^5 * (t - 1)^6 * (2*t^2 + 2*t + 1)^4 * (2*t^2 - t + 1)^5 sage: G = graphs.RandomTree(10) - sage: G.ihara_zeta_function_inverse() + sage: G.ihara_zeta_function_inverse() # needs sage.libs.pari sage.modules 1 REFERENCES: @@ -9001,11 +9011,11 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0, EXAMPLES:: - sage: graphs.PetersenGraph().has_perfect_matching() + sage: graphs.PetersenGraph().has_perfect_matching() # needs networkx True - sage: graphs.WheelGraph(6).has_perfect_matching() + sage: graphs.WheelGraph(6).has_perfect_matching() # needs networkx True - sage: graphs.WheelGraph(5).has_perfect_matching() + sage: graphs.WheelGraph(5).has_perfect_matching() # needs networkx False sage: graphs.PetersenGraph().has_perfect_matching(algorithm="LP_matching") True @@ -9023,14 +9033,16 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0, TESTS:: sage: G = graphs.EmptyGraph() - sage: all(G.has_perfect_matching(algorithm=algo) for algo in ['Edmonds', 'LP_matching', 'LP']) + sage: all(G.has_perfect_matching(algorithm=algo) # needs networkx + ....: for algo in ['Edmonds', 'LP_matching', 'LP']) True Be careful with isolated vertices:: sage: G = graphs.PetersenGraph() sage: G.add_vertex(11) - sage: any(G.has_perfect_matching(algorithm=algo) for algo in ['Edmonds', 'LP_matching', 'LP']) + sage: any(G.has_perfect_matching(algorithm=algo) # needs networkx + ....: for algo in ['Edmonds', 'LP_matching', 'LP']) False """ if self.order() % 2: @@ -9089,30 +9101,30 @@ def effective_resistance(self, i, j, *, base_ring=None): Effective resistances in a straight linear 2-tree on 6 vertices :: sage: G = Graph([(0,1),(0,2),(1,2),(1,3),(3,5),(2,4),(2,3),(3,4),(4,5)]) - sage: G.effective_resistance(0,1) + sage: G.effective_resistance(0,1) # needs sage.modules 34/55 - sage: G.effective_resistance(0,3) + sage: G.effective_resistance(0,3) # needs sage.modules 49/55 - sage: G.effective_resistance(1,4) + sage: G.effective_resistance(1,4) # needs sage.modules 9/11 - sage: G.effective_resistance(0,5) + sage: G.effective_resistance(0,5) # needs sage.modules 15/11 Effective resistances 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.effective_resistance(1,5) + sage: H.effective_resistance(1,5) # needs sage.modules 6/5 - sage: H.effective_resistance(1,3) + sage: H.effective_resistance(1,3) # needs sage.modules 49/55 - sage: H.effective_resistance(1,1) + sage: H.effective_resistance(1,1) # needs sage.modules 0 Using a different base ring:: - sage: H.effective_resistance(1, 5, base_ring=RDF) # abs tol 1e-14 + sage: H.effective_resistance(1, 5, base_ring=RDF) # abs tol 1e-14 # needs sage.modules 1.2000000000000000 - sage: H.effective_resistance(1, 1, base_ring=RDF) + sage: H.effective_resistance(1, 1, base_ring=RDF) # needs sage.modules 0.0 .. SEEALSO:: @@ -9129,25 +9141,26 @@ def effective_resistance(self, i, j, *, base_ring=None): TESTS:: sage: G = graphs.CompleteGraph(4) - sage: all(G.effective_resistance(u, v) == 1/2 for u,v in G.edge_iterator(labels=False)) + sage: all(G.effective_resistance(u, v) == 1/2 # needs sage.modules + ....: for u,v in G.edge_iterator(labels=False)) True - sage: Graph(1).effective_resistance(0,0) + sage: Graph(1).effective_resistance(0,0) # needs sage.modules 0 sage: G = Graph([(0,1),(1,2)]) - sage: G.effective_resistance(0,2) + sage: G.effective_resistance(0,2) # needs sage.modules 2 sage: G = Graph([(0,1),(1,2),(2,0)]) - sage: G.effective_resistance(0,2) + sage: G.effective_resistance(0,2) # needs sage.modules 2/3 sage: G = Graph([(0,1),(0,2),(0,3),(0,4),(0,5),(1,2),(2,3),(3,4),(4,5),(5,1)]) - sage: r = G.effective_resistance(0,3) - sage: r == fibonacci(2*(5-3)+1)*fibonacci(2*3-1)/fibonacci(2*5) + sage: r = G.effective_resistance(0,3) # needs sage.modules + sage: r == fibonacci(2*(5-3)+1)*fibonacci(2*3-1)/fibonacci(2*5) # needs sage.modules True sage: G = graphs.PathGraph(4) sage: G.delete_edge(2,3) - sage: G.effective_resistance(0,2) + sage: G.effective_resistance(0,2) # needs sage.modules 2 - sage: G.effective_resistance(0,3) + sage: G.effective_resistance(0,3) # needs sage.modules +Infinity """ from sage.matrix.constructor import matrix @@ -9221,7 +9234,7 @@ def effective_resistance_matrix(self, vertices=None, nonedgesonly=True, only non-adjacent vertex pairs :: sage: G = Graph([(0,1),(0,2),(1,2),(1,3),(3,5),(2,4),(2,3),(3,4),(4,5)]) - sage: G.effective_resistance_matrix() + sage: G.effective_resistance_matrix() # needs sage.modules [ 0 0 0 49/55 59/55 15/11] [ 0 0 0 0 9/11 59/55] [ 0 0 0 0 0 49/55] @@ -9232,7 +9245,7 @@ def effective_resistance_matrix(self, vertices=None, nonedgesonly=True, The same effective resistance matrix, this time including adjacent vertices :: - sage: G.effective_resistance_matrix(nonedgesonly=False) + sage: G.effective_resistance_matrix(nonedgesonly=False) # needs sage.modules [ 0 34/55 34/55 49/55 59/55 15/11] [34/55 0 26/55 31/55 9/11 59/55] [34/55 26/55 0 5/11 31/55 49/55] @@ -9244,7 +9257,7 @@ def effective_resistance_matrix(self, vertices=None, nonedgesonly=True, vertices counting only non-adjacent vertex pairs :: 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.effective_resistance_matrix() + sage: H.effective_resistance_matrix() # needs sage.modules [ 0 0 0 0 0 0 0] [ 0 0 0 49/55 56/55 6/5 89/55] [ 0 0 0 0 4/5 56/55 81/55] @@ -9255,7 +9268,7 @@ def effective_resistance_matrix(self, vertices=None, nonedgesonly=True, A different base ring:: - sage: H.effective_resistance_matrix(base_ring=RDF)[0, 0].parent() + sage: H.effective_resistance_matrix(base_ring=RDF)[0, 0].parent() # needs sage.modules Real Double Field .. SEEALSO:: @@ -9270,7 +9283,7 @@ def effective_resistance_matrix(self, vertices=None, nonedgesonly=True, TESTS:: - sage: graphs.CompleteGraph(4).effective_resistance_matrix() + sage: graphs.CompleteGraph(4).effective_resistance_matrix() # needs sage.modules [0 0 0 0] [0 0 0 0] [0 0 0 0] @@ -9278,7 +9291,7 @@ def effective_resistance_matrix(self, vertices=None, nonedgesonly=True, sage: G = Graph(multiedges=True, sparse=True) sage: G.add_edges([(0, 1)] * 3) - sage: G.effective_resistance_matrix() + sage: G.effective_resistance_matrix() # needs sage.modules Traceback (most recent call last): ... ValueError: This method is not known to work on graphs with @@ -9286,36 +9299,36 @@ def effective_resistance_matrix(self, vertices=None, nonedgesonly=True, in the meantime if you want to use it please disallow multiedges using allow_multiple_edges(). - sage: graphs.CompleteGraph(4).effective_resistance_matrix(nonedgesonly=False) + sage: graphs.CompleteGraph(4).effective_resistance_matrix(nonedgesonly=False) # needs sage.modules [ 0 1/2 1/2 1/2] [1/2 0 1/2 1/2] [1/2 1/2 0 1/2] [1/2 1/2 1/2 0] - sage: Graph(1).effective_resistance_matrix() + sage: Graph(1).effective_resistance_matrix() # needs sage.modules [0] - sage: Graph().effective_resistance_matrix() + sage: Graph().effective_resistance_matrix() # needs sage.modules Traceback (most recent call last): ... ValueError: unable to compute effective resistance for an empty Graph object sage: G = Graph([(0,1),(1,2),(2,3),(3,0),(0,2)]) - sage: G.effective_resistance_matrix() + sage: G.effective_resistance_matrix() # needs sage.modules [0 0 0 0] [0 0 0 1] [0 0 0 0] [0 1 0 0] sage: G = Graph([(0,1),(0,2),(0,3),(0,4),(0,5),(1,2),(2,3),(3,4),(4,5),(5,1)]) - sage: r = G.effective_resistance_matrix(nonedgesonly=False)[0,3] - sage: r == fibonacci(2*(5-3)+1)*fibonacci(2*3-1)/fibonacci(2*5) + sage: r = G.effective_resistance_matrix(nonedgesonly=False)[0,3] # needs sage.modules + sage: r == fibonacci(2*(5-3)+1)*fibonacci(2*3-1)/fibonacci(2*5) # needs sage.libs.pari sage.modules True Ask for an immutable matrix:: sage: G = Graph([(0, 1)]) - sage: M = G.effective_resistance_matrix(immutable=False) - sage: M.is_immutable() + sage: M = G.effective_resistance_matrix(immutable=False) # needs sage.modules + sage: M.is_immutable() # needs sage.modules False - sage: M = G.effective_resistance_matrix(immutable=True) - sage: M.is_immutable() + sage: M = G.effective_resistance_matrix(immutable=True) # needs sage.modules + sage: M.is_immutable() # needs sage.modules True """ from sage.matrix.constructor import matrix @@ -9375,20 +9388,20 @@ def least_effective_resistance(self, nonedgesonly=True): straight linear 2-tree on 6 vertices:: sage: G = Graph([(0,1),(0,2),(1,2),(1,3),(3,5),(2,4),(2,3),(3,4),(4,5)]) - sage: G.least_effective_resistance() + sage: G.least_effective_resistance() # needs sage.modules [(1, 4)] Pairs of (adjacent or non-adjacent) nodes with least effective resistance in a straight linear 2-tree on 6 vertices :: - sage: G.least_effective_resistance(nonedgesonly = False) + sage: G.least_effective_resistance(nonedgesonly=False) # needs sage.modules [(2, 3)] Pairs of non-adjacent nodes with least effective resistance in a fan on 6 vertices counting only non-adjacent vertex pairs :: 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.least_effective_resistance() + sage: H.least_effective_resistance() # needs sage.modules [(2, 4)] .. SEEALSO:: @@ -9405,14 +9418,14 @@ def least_effective_resistance(self, nonedgesonly=True): TESTS:: - sage: graphs.CompleteGraph(4).least_effective_resistance() + sage: graphs.CompleteGraph(4).least_effective_resistance() # needs sage.modules [] - sage: graphs.CompleteGraph(4).least_effective_resistance(nonedgesonly=False) + sage: graphs.CompleteGraph(4).least_effective_resistance(nonedgesonly=False) # needs sage.modules [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] - sage: Graph(1).least_effective_resistance() + sage: Graph(1).least_effective_resistance() # needs sage.modules [] sage: G = Graph([(0,1),(1,2),(2,3),(3,0),(0,2)]) - sage: G.least_effective_resistance() + sage: G.least_effective_resistance() # needs sage.modules [(1, 3)] """ n = self.order() @@ -9470,7 +9483,7 @@ def common_neighbors_matrix(self, vertices=None, nonedgesonly=True, sage: G1 = Graph() sage: G1.add_edges([(0,1),(0,2),(1,2),(1,3),(3,5),(2,4),(2,3),(3,4),(4,5)]) - sage: G1.common_neighbors_matrix(nonedgesonly = True) + sage: G1.common_neighbors_matrix(nonedgesonly=True) # needs sage.modules [0 0 0 2 1 0] [0 0 0 0 2 1] [0 0 0 0 0 2] @@ -9481,7 +9494,7 @@ def common_neighbors_matrix(self, vertices=None, nonedgesonly=True, We now show the common neighbors matrix which includes adjacent vertices :: - sage: G1.common_neighbors_matrix(nonedgesonly = False) + sage: G1.common_neighbors_matrix(nonedgesonly=False) # needs sage.modules [0 1 1 2 1 0] [1 0 2 1 2 1] [1 2 0 2 1 2] @@ -9493,7 +9506,7 @@ def common_neighbors_matrix(self, vertices=None, nonedgesonly=True, non-adjacent vertex pairs :: 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.common_neighbors_matrix() + sage: H.common_neighbors_matrix() # needs sage.modules [0 0 0 0 0 0 0] [0 0 0 2 1 1 1] [0 0 0 0 2 1 1] @@ -9504,7 +9517,7 @@ def common_neighbors_matrix(self, vertices=None, nonedgesonly=True, A different base ring:: - sage: H.common_neighbors_matrix(base_ring=RDF) + sage: H.common_neighbors_matrix(base_ring=RDF) # needs sage.modules [0.0 0.0 0.0 0.0 0.0 0.0 0.0] [0.0 0.0 0.0 2.0 1.0 1.0 1.0] [0.0 0.0 0.0 0.0 2.0 1.0 1.0] @@ -9515,8 +9528,8 @@ def common_neighbors_matrix(self, vertices=None, nonedgesonly=True, It is an error to input anything other than a simple graph:: - sage: G = Graph([(0,0)],loops=True) - sage: G.common_neighbors_matrix() + sage: G = Graph([(0,0)], loops=True) + sage: G.common_neighbors_matrix() # needs sage.modules Traceback (most recent call last): ... ValueError: This method is not known to work on graphs with loops. @@ -9532,15 +9545,15 @@ def common_neighbors_matrix(self, vertices=None, nonedgesonly=True, TESTS:: sage: G = graphs.CompleteGraph(4) - sage: M = G.common_neighbors_matrix() - sage: M.is_zero() + sage: M = G.common_neighbors_matrix() # needs sage.modules + sage: M.is_zero() # needs sage.modules True - sage: Graph(1).common_neighbors_matrix() + sage: Graph(1).common_neighbors_matrix() # needs sage.modules [0] - sage: Graph().common_neighbors_matrix() + sage: Graph().common_neighbors_matrix() # needs sage.modules [] sage: G = Graph([(0,1),(1,2),(2,3),(3,0),(0,2)]) - sage: G.common_neighbors_matrix() + sage: G.common_neighbors_matrix() # needs sage.modules [0 0 0 0] [0 0 0 2] [0 0 0 0] @@ -9549,11 +9562,11 @@ def common_neighbors_matrix(self, vertices=None, nonedgesonly=True, Asking for an immutable matrix:: sage: G = Graph([(0, 1)]) - sage: M = G.common_neighbors_matrix() - sage: M.is_immutable() + sage: M = G.common_neighbors_matrix() # needs sage.modules + sage: M.is_immutable() # needs sage.modules False - sage: M = G.common_neighbors_matrix(immutable=True) - sage: M.is_immutable() + sage: M = G.common_neighbors_matrix(immutable=True) # needs sage.modules + sage: M.is_immutable() # needs sage.modules True """ self._scream_if_not_simple() @@ -9593,19 +9606,19 @@ def most_common_neighbors(self, nonedgesonly=True): linear 2-tree :: sage: G1 = Graph([(0,1),(0,2),(1,2),(1,3),(3,5),(2,4),(2,3),(3,4),(4,5)]) - sage: G1.most_common_neighbors() + sage: G1.most_common_neighbors() # needs sage.modules [(0, 3), (1, 4), (2, 5)] If we include non-adjacent pairs :: - sage: G1.most_common_neighbors(nonedgesonly = False) + sage: G1.most_common_neighbors(nonedgesonly=False) # needs sage.modules [(0, 3), (1, 2), (1, 4), (2, 3), (2, 5), (3, 4)] The common neighbors matrix for a fan on 6 vertices counting only non-adjacent vertex pairs :: 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.most_common_neighbors() + sage: H.most_common_neighbors() # needs sage.modules [(1, 3), (2, 4), (3, 5)] .. SEEALSO:: @@ -9616,22 +9629,22 @@ def most_common_neighbors(self, nonedgesonly=True): TESTS:: sage: G=graphs.CompleteGraph(4) - sage: G.most_common_neighbors() + sage: G.most_common_neighbors() # needs sage.modules [] - sage: G.most_common_neighbors(nonedgesonly=False) + sage: G.most_common_neighbors(nonedgesonly=False) # needs sage.modules [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] - sage: Graph(1).most_common_neighbors() + sage: Graph(1).most_common_neighbors() # needs sage.modules Traceback (most recent call last): ... ValueError: this method is defined for graphs with at least 2 vertices - sage: Graph().most_common_neighbors() + sage: Graph().most_common_neighbors() # needs sage.modules Traceback (most recent call last): ... ValueError: this method is defined for graphs with at least 2 vertices sage: G = Graph([(0,1),(1,2),(2,3),(3,0),(0,2)]) - sage: G.most_common_neighbors() + sage: G.most_common_neighbors() # needs sage.modules [(1, 3)] - sage: G.most_common_neighbors(nonedgesonly=False) + sage: G.most_common_neighbors(nonedgesonly=False) # needs sage.modules [(0, 2), (1, 3)] """ self._scream_if_not_simple() @@ -9682,18 +9695,18 @@ def arboricity(self, certificate=False): EXAMPLES:: sage: G = graphs.PetersenGraph() - sage: a,F = G.arboricity(True) - sage: a + sage: a, F = G.arboricity(True) # needs sage.modules + sage: a # needs sage.modules 2 - sage: all([f.is_forest() for f in F]) + sage: all([f.is_forest() for f in F]) # needs sage.modules True - sage: len(set.union(*[set(f.edges(sort=False)) for f in F])) == G.size() + sage: len(set.union(*[set(f.edges(sort=False)) for f in F])) == G.size() # needs sage.modules True TESTS:: sage: g = Graph() - sage: g.arboricity(True) + sage: g.arboricity(True) # needs sage.modules (0, []) """ from sage.matroids.constructor import Matroid diff --git a/src/sage/graphs/graph_coloring.pyx b/src/sage/graphs/graph_coloring.pyx index 60abd45d4d1..8360f71bfca 100644 --- a/src/sage/graphs/graph_coloring.pyx +++ b/src/sage/graphs/graph_coloring.pyx @@ -104,11 +104,12 @@ def format_coloring(data, value_only=False, hex_colors=False, vertex_color_dict= 3 sage: format_coloring(color_classes, value_only=False) {0: ['a', 'b'], 1: ['c'], 2: ['d']} - sage: format_coloring(color_classes, value_only=False, hex_colors=True) + sage: format_coloring(color_classes, value_only=False, hex_colors=True) # needs sage.plot {'#0000ff': ['d'], '#00ff00': ['c'], '#ff0000': ['a', 'b']} sage: format_coloring(color_classes, value_only=False, hex_colors=False, vertex_color_dict=True) {'a': 0, 'b': 0, 'c': 1, 'd': 2} - sage: format_coloring(color_classes, value_only=False, hex_colors=True, vertex_color_dict=True) + sage: format_coloring(color_classes, value_only=False, hex_colors=True, # needs sage.plot + ....: vertex_color_dict=True) {'a': '#ff0000', 'b': '#ff0000', 'c': '#00ff00', 'd': '#0000ff'} TESTS:: @@ -116,9 +117,10 @@ def format_coloring(data, value_only=False, hex_colors=False, vertex_color_dict= sage: from sage.graphs.graph_coloring import format_coloring sage: format_coloring([], value_only=True) [] - sage: format_coloring([], value_only=False, hex_colors=True) + sage: format_coloring([], value_only=False, hex_colors=True) # needs sage.plot {} - sage: format_coloring([], value_only=False, hex_colors=True, vertex_color_dict=True) + sage: format_coloring([], value_only=False, hex_colors=True, # needs sage.plot + ....: vertex_color_dict=True) {} sage: format_coloring([], value_only=False, hex_colors=False, vertex_color_dict=True) {} @@ -210,7 +212,7 @@ def all_graph_colorings(G, n, count_only=False, hex_colors=False, sage: from sage.graphs.graph_coloring import all_graph_colorings sage: G = Graph({0: [1, 2, 3], 1: [2]}) sage: n = 0 - sage: for C in all_graph_colorings(G, 3, hex_colors=True): + sage: for C in all_graph_colorings(G, 3, hex_colors=True): # needs sage.plot ....: parts = [C[k] for k in C] ....: for P in parts: ....: l = len(P) @@ -218,8 +220,8 @@ def all_graph_colorings(G, n, count_only=False, hex_colors=False, ....: for j in range(i + 1, l): ....: if G.has_edge(P[i], P[j]): ....: raise RuntimeError("Coloring Failed.") - ....: n+=1 - sage: print("G has %s 3-colorings." % n) + ....: n += 1 + sage: print("G has %s 3-colorings." % n) # needs sage.plot G has 12 3-colorings. TESTS:: @@ -237,11 +239,12 @@ def all_graph_colorings(G, n, count_only=False, hex_colors=False, ....: print(c) {0: 0, 2: 0, 1: 1} {1: 0, 0: 1, 2: 1} - sage: for c in all_graph_colorings(G, 2, hex_colors=True): + sage: for c in all_graph_colorings(G, 2, hex_colors=True): # needs sage.plot ....: print(sorted(c.items())) [('#00ffff', [1]), ('#ff0000', [0, 2])] [('#00ffff', [0, 2]), ('#ff0000', [1])] - sage: for c in all_graph_colorings(G, 2, hex_colors=True, vertex_color_dict=True): + sage: for c in all_graph_colorings(G, 2, hex_colors=True, # needs sage.plot + ....: vertex_color_dict=True): ....: print(c) {0: '#ff0000', 2: '#ff0000', 1: '#00ffff'} {1: '#ff0000', 0: '#00ffff', 2: '#00ffff'} @@ -513,7 +516,7 @@ def vertex_coloring(g, k=None, value_only=False, hex_colors=False, solver=None, sage: from sage.graphs.graph_coloring import vertex_coloring sage: g = graphs.PetersenGraph() - sage: vertex_coloring(g, value_only=True) + sage: vertex_coloring(g, value_only=True) # needs sage.numerical.mip 3 TESTS: @@ -532,7 +535,7 @@ def vertex_coloring(g, k=None, value_only=False, hex_colors=False, solver=None, :trac:`33559` is fixed:: sage: G = Graph('MgCgS?_O@IeTHKG??') - sage: len(G.coloring(algorithm='MILP')) + sage: len(G.coloring(algorithm='MILP')) # needs sage.numerical.mip 4 """ g._scream_if_not_simple(allow_multiple_edges=True) @@ -775,15 +778,15 @@ def fractional_chromatic_number(G, solver='PPL', verbose=0, The fractional chromatic number of a `C_5` is `5/2`:: sage: g = graphs.CycleGraph(5) - sage: g.fractional_chromatic_number() + sage: g.fractional_chromatic_number() # needs sage.numerical.mip 5/2 TESTS:: sage: G = graphs.RandomGNP(20, .2) - sage: a = G.fractional_chromatic_number(check_components=True) - sage: b = G.fractional_chromatic_number(check_components=False) - sage: a == b + sage: a = G.fractional_chromatic_number(check_components=True) # needs sage.numerical.mip + sage: b = G.fractional_chromatic_number(check_components=False) # needs sage.numerical.mip + sage: a == b # needs sage.numerical.mip True """ G._scream_if_not_simple() @@ -884,7 +887,7 @@ def fractional_chromatic_index(G, solver="PPL", verbose_constraints=False, verbo The fractional chromatic index of a `C_5` is `5/2`:: sage: g = graphs.CycleGraph(5) - sage: g.fractional_chromatic_index() + sage: g.fractional_chromatic_index() # needs sage.numerical.mip 5/2 TESTS: @@ -893,9 +896,9 @@ def fractional_chromatic_index(G, solver="PPL", verbose_constraints=False, verbo solvers:: sage: g = graphs.PetersenGraph() - sage: g.fractional_chromatic_index(solver='GLPK') # known bug (#23798) + sage: g.fractional_chromatic_index(solver='GLPK') # known bug # needs sage.numerical.mip 3.0 - sage: g.fractional_chromatic_index(solver='PPL') + sage: g.fractional_chromatic_index(solver='PPL') # needs sage.numerical.mip 3 """ G._scream_if_not_simple() @@ -1025,13 +1028,13 @@ def grundy_coloring(g, k, value_only=True, solver=None, verbose=0, sage: from sage.graphs.graph_coloring import grundy_coloring sage: g = graphs.PathGraph(4) - sage: grundy_coloring(g, 4) + sage: grundy_coloring(g, 4) # needs sage.numerical.mip 3 The Grundy number of the PetersenGraph is equal to 4:: sage: g = graphs.PetersenGraph() - sage: grundy_coloring(g, 5) + sage: grundy_coloring(g, 5) # needs sage.numerical.mip 4 It would have been sufficient to set the value of ``k`` to 4 in @@ -1179,13 +1182,13 @@ def b_coloring(g, k, value_only=True, solver=None, verbose=0, sage: from sage.graphs.graph_coloring import b_coloring sage: g = graphs.PathGraph(5) - sage: b_coloring(g, 5) + sage: b_coloring(g, 5) # needs sage.numerical.mip 3 The b-chromatic number of the Petersen Graph is equal to 3:: sage: g = graphs.PetersenGraph() - sage: b_coloring(g, 5) + sage: b_coloring(g, 5) # needs sage.numerical.mip 3 It would have been sufficient to set the value of ``k`` to 4 in this case, @@ -1380,32 +1383,33 @@ def edge_coloring(g, value_only=False, vizing=False, hex_colors=False, solver=No sage: from sage.graphs.graph_coloring import edge_coloring sage: g = graphs.PetersenGraph() - sage: edge_coloring(g, value_only=True, solver='GLPK') + sage: edge_coloring(g, value_only=True, solver='GLPK') # needs sage.numerical.mip 4 - sage: color_classes = edge_coloring(g, value_only=False, solver='GLPK') - sage: len(color_classes) + sage: color_classes = edge_coloring(g, value_only=False, solver='GLPK') # needs sage.numerical.mip + sage: len(color_classes) # needs sage.numerical.mip 4 - sage: len(set(frozenset(e) for C in color_classes for e in C)) == g.size() + sage: len(set(frozenset(e) for C in color_classes for e in C)) == g.size() # needs sage.numerical.mip True - sage: all(g.has_edge(e) for C in color_classes for e in C) + sage: all(g.has_edge(e) for C in color_classes for e in C) # needs sage.numerical.mip True - sage: all(len(Graph(C).matching()) == len(C) for C in color_classes) + sage: all(len(Graph(C).matching()) == len(C) for C in color_classes) # needs networkx sage.numerical.mip True - sage: color_classes = edge_coloring(g, value_only=False, hex_colors=True, solver='GLPK') - sage: sorted(color_classes.keys()) + sage: color_classes = edge_coloring(g, value_only=False, # needs sage.numerical.mip + ....: hex_colors=True, solver='GLPK') + sage: sorted(color_classes.keys()) # needs sage.numerical.mip ['#00ffff', '#7f00ff', '#7fff00', '#ff0000'] Complete graphs are colored using the linear-time round-robin coloring:: sage: from sage.graphs.graph_coloring import edge_coloring - sage: len(edge_coloring(graphs.CompleteGraph(20))) + sage: len(edge_coloring(graphs.CompleteGraph(20))) # needs sage.numerical.mip 19 The chromatic index of a non connected graph is the maximum over its connected components:: sage: g = graphs.CompleteGraph(4) + graphs.CompleteGraph(10) - sage: edge_coloring(g, value_only=True) + sage: edge_coloring(g, value_only=True) # needs sage.numerical.mip 9 TESTS: @@ -1413,11 +1417,11 @@ def edge_coloring(g, value_only=False, vizing=False, hex_colors=False, solver=No Graph without edge:: sage: g = Graph(2) - sage: edge_coloring(g) + sage: edge_coloring(g) # needs sage.numerical.mip [] - sage: edge_coloring(g, value_only=True) + sage: edge_coloring(g, value_only=True) # needs sage.numerical.mip 0 - sage: edge_coloring(g, hex_colors=True) + sage: edge_coloring(g, hex_colors=True) # needs sage.numerical.mip {} """ g._scream_if_not_simple() @@ -1564,7 +1568,7 @@ def _vizing_edge_coloring(g): True sage: all(g.has_edge(e) for C in color_classes for e in C) True - sage: all(len(Graph(C).matching()) == len(C) for C in color_classes) + sage: all(len(Graph(C).matching()) == len(C) for C in color_classes) # needs networkx True Coloring the edges of the Star Graph:: @@ -1832,22 +1836,23 @@ def linear_arboricity(g, plus_one=None, hex_colors=False, value_only=False, horizontal lines and the set of vertical lines are an admissible partition:: sage: from sage.graphs.graph_coloring import linear_arboricity - sage: g = graphs.Grid2dGraph(4, 4) - sage: g1,g2 = linear_arboricity(g) + sage: g = graphs.Grid2dGraph(4, 4) # needs sage.numerical.mip + sage: g1,g2 = linear_arboricity(g) # needs sage.numerical.mip Each graph is of course a forest:: - sage: g1.is_forest() and g2.is_forest() + sage: g1.is_forest() and g2.is_forest() # needs sage.numerical.mip True Of maximum degree 2:: - sage: max(g1.degree()) <= 2 and max(g2.degree()) <= 2 + sage: max(g1.degree()) <= 2 and max(g2.degree()) <= 2 # needs sage.numerical.mip True Which constitutes a partition of the whole edge set:: - sage: all((g1.has_edge(e) or g2.has_edge(e)) for e in g.edge_iterator(labels=None)) + sage: all((g1.has_edge(e) or g2.has_edge(e)) # needs sage.numerical.mip + ....: for e in g.edge_iterator(labels=None)) True TESTS: @@ -1855,15 +1860,15 @@ def linear_arboricity(g, plus_one=None, hex_colors=False, value_only=False, Asking for the value of the linear arboricity only (:trac:`24991`):: sage: from sage.graphs.graph_coloring import linear_arboricity - sage: sorted(linear_arboricity(G, value_only=True) for G in graphs(4)) + sage: sorted(linear_arboricity(G, value_only=True) for G in graphs(4)) # needs sage.numerical.mip [0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2] Test parameter ``hex_color`` (:trac:`26228`):: sage: from sage.graphs.graph_coloring import linear_arboricity sage: g = graphs.Grid2dGraph(4, 4) - sage: d = linear_arboricity(g, hex_colors=True) - sage: sorted(d) + sage: d = linear_arboricity(g, hex_colors=True) # needs sage.numerical.mip + sage: sorted(d) # needs sage.numerical.mip ['#00ffff', '#ff0000'] """ g._scream_if_not_simple() @@ -2036,21 +2041,22 @@ def acyclic_edge_coloring(g, hex_colors=False, value_only=False, k=0, sage: from sage.graphs.graph_coloring import acyclic_edge_coloring sage: g = graphs.CompleteGraph(8) - sage: colors = acyclic_edge_coloring(g) + sage: colors = acyclic_edge_coloring(g) # needs sage.numerical.mip Each color class is of course a matching :: - sage: all(max(gg.degree()) <= 1 for gg in colors) + sage: all(max(gg.degree()) <= 1 for gg in colors) # needs sage.numerical.mip True These matchings being a partition of the edge set:: - sage: all(any(gg.has_edge(e) for gg in colors) for e in g.edge_iterator(labels=False)) + sage: all(any(gg.has_edge(e) for gg in colors) # needs sage.numerical.mip + ....: for e in g.edge_iterator(labels=False)) True Besides, the union of any two of them is a forest :: - sage: all(g1.union(g2).is_forest() for g1 in colors for g2 in colors) + sage: all(g1.union(g2).is_forest() for g1 in colors for g2 in colors) # needs sage.numerical.mip True If one wants to acyclically color a cycle on `4` vertices, at least 3 colors @@ -2058,15 +2064,15 @@ def acyclic_edge_coloring(g, hex_colors=False, value_only=False, k=0, with only 2:: sage: g = graphs.CycleGraph(4) - sage: acyclic_edge_coloring(g, k=2) + sage: acyclic_edge_coloring(g, k=2) # needs sage.numerical.mip Traceback (most recent call last): ... ValueError: this graph cannot be colored with the given number of colors The optimal coloring give us `3` classes:: - sage: colors = acyclic_edge_coloring(g, k=None) - sage: len(colors) + sage: colors = acyclic_edge_coloring(g, k=None) # needs sage.numerical.mip + sage: len(colors) # needs sage.numerical.mip 3 TESTS: @@ -2074,32 +2080,32 @@ def acyclic_edge_coloring(g, hex_colors=False, value_only=False, k=0, Issue :trac:`24991` is fixed:: sage: from sage.graphs.graph_coloring import acyclic_edge_coloring - sage: sorted(acyclic_edge_coloring(G, value_only=True) for G in graphs(4)) + sage: sorted(acyclic_edge_coloring(G, value_only=True) for G in graphs(4)) # needs sage.numerical.mip [2, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5] Test parameter ``hex_color`` (:trac:`26228`):: sage: from sage.graphs.graph_coloring import acyclic_edge_coloring sage: g = graphs.CompleteGraph(4) - sage: d = acyclic_edge_coloring(g, hex_colors=True) - sage: sorted(d) + sage: d = acyclic_edge_coloring(g, hex_colors=True) # needs sage.numerical.mip + sage: sorted(d) # needs sage.numerical.mip ['#0066ff', '#00ff66', '#cbff00', '#cc00ff', '#ff0000'] The acyclic chromatic index of a graph without edge is 0 (:trac:`27079`):: sage: from sage.graphs.graph_coloring import acyclic_edge_coloring sage: g = Graph(3) - sage: acyclic_edge_coloring(g, k=None, value_only=True) + sage: acyclic_edge_coloring(g, k=None, value_only=True) # needs sage.numerical.mip 0 - sage: acyclic_edge_coloring(g, k=None, hex_colors=True) + sage: acyclic_edge_coloring(g, k=None, hex_colors=True) # needs sage.numerical.mip {} - sage: acyclic_edge_coloring(g, k=None, hex_colors=False) + sage: acyclic_edge_coloring(g, k=None, hex_colors=False) # needs sage.numerical.mip [] Empty graph (:trac:`27079`):: sage: from sage.graphs.graph_coloring import acyclic_edge_coloring - sage: acyclic_edge_coloring(Graph(), k=None, value_only=True) + sage: acyclic_edge_coloring(Graph(), k=None, value_only=True) # needs sage.numerical.mip 0 """ g._scream_if_not_simple(allow_multiple_edges=True) diff --git a/src/sage/graphs/graph_database.py b/src/sage/graphs/graph_database.py index 9274ca13452..b8e9226bc2c 100644 --- a/src/sage/graphs/graph_database.py +++ b/src/sage/graphs/graph_database.py @@ -120,7 +120,7 @@ def graph6_to_plot(graph6): EXAMPLES:: sage: from sage.graphs.graph_database import graph6_to_plot - sage: type(graph6_to_plot('D??')) # optional - sage.plot + sage: type(graph6_to_plot('D??')) # needs sage.plot """ g = Graph(str(graph6)) diff --git a/src/sage/graphs/graph_decompositions/bandwidth.pyx b/src/sage/graphs/graph_decompositions/bandwidth.pyx index d72c6e5ff80..bbd3916ac2b 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]) # optional - sage.modules + sage: G.adjacency_matrix(vertices=[0, 4, 5, 8, 1, 9, 3, 7, 6, 2]) # needs 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]) # optional - sage.modules + sage: G.adjacency_matrix(vertices=[0, 5, 9, 4, 10, 1, 6, 11, 3, 8, 7, 2]) # needs 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/cutwidth.pyx b/src/sage/graphs/graph_decompositions/cutwidth.pyx index 440d80ee2f6..208bd69dea4 100644 --- a/src/sage/graphs/graph_decompositions/cutwidth.pyx +++ b/src/sage/graphs/graph_decompositions/cutwidth.pyx @@ -372,7 +372,7 @@ def cutwidth(G, algorithm="exponential", cut_off=0, solver=None, verbose=False, sage: G = Graph([(0, 1)]) sage: cutwidth(G, algorithm="exponential") (1, [0, 1]) - sage: cutwidth(G, algorithm="MILP", solver='GLPK') + sage: cutwidth(G, algorithm="MILP", solver='GLPK') # needs sage.numerical.mip (1, [0, 1]) Cutwidth of a disconnected graph:: @@ -382,7 +382,7 @@ def cutwidth(G, algorithm="exponential", cut_off=0, solver=None, verbose=False, sage: G.add_edge(2, 3) sage: cutwidth(G, algorithm="exponential") (1, [2, 3, 0, 1, 4]) - sage: cutwidth(G, algorithm="MILP", solver='GLPK') + sage: cutwidth(G, algorithm="MILP", solver='GLPK') # needs sage.numerical.mip (1, [2, 3, 0, 1, 4]) """ from sage.graphs.graph import Graph @@ -643,9 +643,9 @@ def cutwidth_MILP(G, lower_bound=0, solver=None, verbose=0, sage: from sage.graphs.graph_decompositions import cutwidth sage: G = graphs.CycleGraph(5) - sage: cw, L = cutwidth.cutwidth_MILP(G); cw + sage: cw, L = cutwidth.cutwidth_MILP(G); cw # needs sage.numerical.mip 2 - sage: cw == cutwidth.width_of_cut_decomposition(G, L) + sage: cw == cutwidth.width_of_cut_decomposition(G, L) # needs sage.numerical.mip True sage: cwe, Le = cutwidth.cutwidth_dyn(G); cwe 2 @@ -654,18 +654,18 @@ def cutwidth_MILP(G, lower_bound=0, solver=None, verbose=0, sage: from sage.graphs.graph_decompositions import cutwidth sage: G = graphs.CompleteGraph(4) - sage: cw, L = cutwidth.cutwidth_MILP(G); cw + sage: cw, L = cutwidth.cutwidth_MILP(G); cw # needs sage.numerical.mip 4 - sage: cw == cutwidth.width_of_cut_decomposition(G, L) + sage: cw == cutwidth.width_of_cut_decomposition(G, L) # needs sage.numerical.mip True Cutwidth of a Path graph:: sage: from sage.graphs.graph_decompositions import cutwidth sage: G = graphs.PathGraph(3) - sage: cw, L = cutwidth.cutwidth_MILP(G); cw + sage: cw, L = cutwidth.cutwidth_MILP(G); cw # needs sage.numerical.mip 1 - sage: cw == cutwidth.width_of_cut_decomposition(G, L) + sage: cw == cutwidth.width_of_cut_decomposition(G, L) # needs sage.numerical.mip True TESTS: @@ -673,7 +673,7 @@ def cutwidth_MILP(G, lower_bound=0, solver=None, verbose=0, Comparison with exponential algorithm:: sage: from sage.graphs.graph_decompositions import cutwidth - sage: for i in range(2): # long time + sage: for i in range(2): # long time # needs sage.numerical.mip ....: G = graphs.RandomGNP(7, 0.3) ....: ve, le = cutwidth.cutwidth_dyn(G) ....: vm, lm = cutwidth.cutwidth_MILP(G, solver='GLPK') @@ -684,7 +684,7 @@ def cutwidth_MILP(G, lower_bound=0, solver=None, verbose=0, sage: from sage.graphs.graph_decompositions.cutwidth import cutwidth_MILP sage: G = graphs.CycleGraph(3) - sage: cutwidth_MILP(G, lower_bound=G.size()+1) + sage: cutwidth_MILP(G, lower_bound=G.size()+1) # needs sage.numerical.mip Traceback (most recent call last): ... MIPSolverException: ... diff --git a/src/sage/graphs/graph_decompositions/fast_digraph.pyx b/src/sage/graphs/graph_decompositions/fast_digraph.pyx index fd75e5e63c3..3d7c4b2fea7 100644 --- a/src/sage/graphs/graph_decompositions/fast_digraph.pyx +++ b/src/sage/graphs/graph_decompositions/fast_digraph.pyx @@ -41,7 +41,7 @@ cdef class FastDigraph: ....: 'cdef FastDigraph F = FastDigraph(G)', ....: 'cdef int i', ....: 'print([F.degree[i] for i in range(F.n)])'] - sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython + sage: cython(os.linesep.join(cython_code)) # needs sage.misc.cython [1, 2, 1] """ if D.order() > 8*sizeof(int): @@ -98,7 +98,7 @@ cdef class FastDigraph: ....: 'from sage.graphs.graph import Graph', ....: 'from sage.graphs.graph_decompositions.fast_digraph cimport FastDigraph', ....: 'FastDigraph(Graph([(0, 1), (1, 2)])).print_adjacency_matrix()'] - sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython + sage: cython(os.linesep.join(cython_code)) # needs sage.misc.cython 010 101 010 @@ -128,7 +128,7 @@ cdef inline int compute_out_neighborhood_cardinality(FastDigraph g, int S): ....: 'cdef FastDigraph F = FastDigraph(Graph([(0, 1), (1, 2)]))', ....: 'cdef int i', ....: 'print([compute_out_neighborhood_cardinality(F, 1<> 1) & 0x55555555) @@ -198,7 +198,7 @@ cdef inline int slow_popcount32(int i): ....: 'from sage.graphs.graph_decompositions.fast_digraph cimport slow_popcount32', ....: 'cdef int i', ....: 'print(all(popcount32(i) == slow_popcount32(i) for i in range(16)))'] - sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython + sage: cython(os.linesep.join(cython_code)) # needs sage.misc.cython True """ # Slow popcount for 32bits integers diff --git a/src/sage/graphs/graph_decompositions/graph_products.pyx b/src/sage/graphs/graph_decompositions/graph_products.pyx index 7042eabbfaf..31f49206586 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() # optional - networkx - sage: g.is_cartesian_product() # optional - networkx + sage: g = graphs.WagnerGraph() # needs networkx + sage: g.is_cartesian_product() # needs 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 230525e00e1..7a0c71c2fb1 100644 --- a/src/sage/graphs/graph_decompositions/modular_decomposition.py +++ b/src/sage/graphs/graph_decompositions/modular_decomposition.py @@ -610,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) # optional - sage.groups + sage: permute_decomposition(2, habib_maurer_algorithm, 20, 0.5) # needs sage.groups """ if graph.is_directed(): raise ValueError("Graph must be undirected") diff --git a/src/sage/graphs/graph_decompositions/tdlib.pyx b/src/sage/graphs/graph_decompositions/tdlib.pyx index 017b120abd3..a673b44d1ee 100644 --- a/src/sage/graphs/graph_decompositions/tdlib.pyx +++ b/src/sage/graphs/graph_decompositions/tdlib.pyx @@ -132,11 +132,12 @@ def treedecomposition_exact(G, lb=-1): TESTS:: - sage: import sage.graphs.graph_decompositions.tdlib as tdlib # optional - tdlib - sage: G = graphs.HouseGraph() # optional - tdlib - sage: T = tdlib.treedecomposition_exact(G) # optional - tdlib - sage: G = graphs.PetersenGraph() # optional - tdlib - sage: T = tdlib.treedecomposition_exact(G) # optional - tdlib + sage: # optional - tdlib + sage: import sage.graphs.graph_decompositions.tdlib as tdlib + sage: G = graphs.HouseGraph() + sage: T = tdlib.treedecomposition_exact(G) + sage: G = graphs.PetersenGraph() + sage: T = tdlib.treedecomposition_exact(G) """ cdef vector[unsigned int] V_G, E_G, E_T diff --git a/src/sage/graphs/graph_decompositions/vertex_separation.pyx b/src/sage/graphs/graph_decompositions/vertex_separation.pyx index bf6070e9c8f..c3e2948e9d6 100644 --- a/src/sage/graphs/graph_decompositions/vertex_separation.pyx +++ b/src/sage/graphs/graph_decompositions/vertex_separation.pyx @@ -665,7 +665,7 @@ def path_decomposition(G, algorithm="BAB", cut_off=None, upper_bound=None, verbo 2 sage: pw, L = path_decomposition(g, algorithm = "exponential"); pw 2 - sage: pw, L = path_decomposition(g, algorithm = "MILP"); pw + sage: pw, L = path_decomposition(g, algorithm="MILP"); pw # needs sage.numerical.mip 2 TESTS: @@ -766,19 +766,19 @@ 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) # optional - sage.combinat - sage: vs,L = vertex_separation(G, algorithm="BAB"); vs # optional - sage.combinat + sage: G = digraphs.DeBruijn(2,3) # needs sage.combinat + sage: vs,L = vertex_separation(G, algorithm="BAB"); vs # needs sage.combinat 2 - sage: vs,L = vertex_separation(G, algorithm="exponential"); vs # optional - sage.combinat + sage: vs,L = vertex_separation(G, algorithm="exponential"); vs # needs sage.combinat 2 - sage: vs,L = vertex_separation(G, algorithm="MILP"); vs # optional - sage.combinat + sage: vs,L = vertex_separation(G, algorithm="MILP"); vs # needs sage.combinat sage.numerical.mip 2 sage: G = graphs.Grid2dGraph(3,3) sage: vs,L = vertex_separation(G, algorithm="BAB"); vs 3 sage: vs,L = vertex_separation(G, algorithm="exponential"); vs 3 - sage: vs,L = vertex_separation(G, algorithm="MILP"); vs + sage: vs,L = vertex_separation(G, algorithm="MILP"); vs # needs sage.numerical.mip 3 Digraphs with multiple strongly connected components:: @@ -805,7 +805,7 @@ def vertex_separation(G, algorithm="BAB", cut_off=None, upper_bound=None, verbos sage: from sage.graphs.graph_decompositions.vertex_separation import vertex_separation sage: G = graphs.PetersenGraph() - sage: vs, L = vertex_separation(G, algorithm="MILP", solver="SCIP"); vs # optional - pyscipopt + sage: vs, L = vertex_separation(G, algorithm="MILP", solver="SCIP"); vs # optional - pyscipopt, needs sage.numerical.mip 5 TESTS: @@ -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) # optional - sage.combinat - sage: vertex_separation_exp(D) # optional - sage.combinat + sage: D = digraphs.DeBruijn(2,3) # needs sage.combinat + sage: vertex_separation_exp(D) # needs sage.combinat (2, ['000', '001', '100', '010', '101', '011', '110', '111']) Given a too large graph:: @@ -1210,13 +1210,14 @@ def width_of_path_decomposition(G, L): Path decomposition of a BalancedTree:: + sage: # needs networkx sage: from sage.graphs.graph_decompositions import vertex_separation - 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 + sage: G = graphs.BalancedTree(3,2) + sage: pw, L = vertex_separation.path_decomposition(G) + sage: pw == vertex_separation.width_of_path_decomposition(G, L) True - sage: L.reverse() # optional - networkx - sage: pw == vertex_separation.width_of_path_decomposition(G, L) # optional - networkx + sage: L.reverse() + sage: pw == vertex_separation.width_of_path_decomposition(G, L) False Directed path decomposition of a circuit:: @@ -1305,9 +1306,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) # optional - sage.combinat - sage: p, x, u, y, z = _vertex_separation_MILP_formulation(G) # optional - sage.combinat - sage: p # optional - sage.combinat + sage: G = digraphs.DeBruijn(2,3) # needs sage.combinat + sage: p, x, u, y, z = _vertex_separation_MILP_formulation(G) # needs sage.combinat sage.numerical.mip + sage: p # needs sage.combinat sage.numerical.mip Mixed Integer Program (minimization, 193 variables, 449 constraints) """ from sage.graphs.graph import Graph @@ -1419,20 +1420,21 @@ def vertex_separation_MILP(G, integrality=False, solver=None, verbose=0, Vertex separation of a De Bruijn digraph:: + sage: # needs sage.combinat sage: from sage.graphs.graph_decompositions import vertex_separation - sage: G = digraphs.DeBruijn(2,3) # optional - sage.combinat - sage: vs, L = vertex_separation.vertex_separation_MILP(G); vs # optional - sage.combinat + sage: G = digraphs.DeBruijn(2,3) + sage: vs, L = vertex_separation.vertex_separation_MILP(G); vs # needs sage.numerical.mip 2 - sage: vs == vertex_separation.width_of_path_decomposition(G, L) # optional - sage.combinat + sage: vs == vertex_separation.width_of_path_decomposition(G, L) # needs sage.numerical.mip True - sage: vse, Le = vertex_separation.vertex_separation(G); vse # optional - sage.combinat + sage: vse, Le = vertex_separation.vertex_separation(G); vse 2 The vertex separation of a circuit is 1:: sage: from sage.graphs.graph_decompositions import vertex_separation sage: G = digraphs.Circuit(6) - sage: vs, L = vertex_separation.vertex_separation_MILP(G); vs + sage: vs, L = vertex_separation.vertex_separation_MILP(G); vs # needs sage.numerical.mip 1 TESTS: @@ -1440,7 +1442,7 @@ def vertex_separation_MILP(G, integrality=False, solver=None, verbose=0, Comparison with exponential algorithm:: sage: from sage.graphs.graph_decompositions import vertex_separation - sage: for i in range(10): + sage: for i in range(10): # needs sage.numerical.mip ....: G = digraphs.RandomDirectedGNP(10, 0.2) ....: ve, le = vertex_separation.vertex_separation(G) ....: vm, lm = vertex_separation.vertex_separation_MILP(G) @@ -1450,7 +1452,7 @@ def vertex_separation_MILP(G, integrality=False, solver=None, verbose=0, Comparison with different values of the integrality parameter:: sage: from sage.graphs.graph_decompositions import vertex_separation - sage: for i in range(10): # long time (11s on sage.math, 2012) + sage: for i in range(10): # long time (11s on sage.math, 2012), needs sage.numerical.mip ....: G = digraphs.RandomDirectedGNP(10, 0.2) ....: va, la = vertex_separation.vertex_separation_MILP(G, integrality=False) ....: vb, lb = vertex_separation.vertex_separation_MILP(G, integrality=True) @@ -1460,7 +1462,7 @@ def vertex_separation_MILP(G, integrality=False, solver=None, verbose=0, Giving anything else than a Graph or a DiGraph:: sage: from sage.graphs.graph_decompositions import vertex_separation - sage: vertex_separation.vertex_separation_MILP([]) + sage: vertex_separation.vertex_separation_MILP([]) # needs sage.numerical.mip Traceback (most recent call last): ... ValueError: the first input parameter must be a Graph or a DiGraph diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index ba6992f5070..12e80870fc2 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -651,9 +651,9 @@ class GraphGenerators(): except for appropriately inheritable properties:: sage: property = lambda G: G.is_vertex_transitive() - sage: len(list(graphs(4, property))) + sage: len(list(graphs(4, property))) # needs sage.groups 1 - sage: sum(1 for g in graphs(4) if property(g)) + sage: sum(1 for g in graphs(4) if property(g)) # needs sage.groups 4 sage: property = lambda G: G.is_bipartite() @@ -1231,39 +1231,39 @@ def cospectral_graphs(self, vertices, matrix_function=lambda g: g.adjacency_matr EXAMPLES:: - sage: g=graphs.cospectral_graphs(5) - sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) + sage: g = graphs.cospectral_graphs(5) # needs sage.modules + sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) # needs sage.modules [['Dr?', 'Ds_']] - sage: g[0][1].am().charpoly()==g[0][1].am().charpoly() + sage: g[0][1].am().charpoly()==g[0][1].am().charpoly() # needs sage.modules True There are two sets of cospectral graphs on six vertices with no isolated vertices:: - sage: g=graphs.cospectral_graphs(6, graphs=lambda x: min(x.degree())>0) - sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) + sage: g = graphs.cospectral_graphs(6, graphs=lambda x: min(x.degree())>0) # needs sage.modules + sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) # needs sage.modules [['Ep__', 'Er?G'], ['ExGg', 'ExoG']] - sage: g[0][1].am().charpoly()==g[0][1].am().charpoly() + sage: g[0][1].am().charpoly()==g[0][1].am().charpoly() # needs sage.modules True - sage: g[1][1].am().charpoly()==g[1][1].am().charpoly() + sage: g[1][1].am().charpoly()==g[1][1].am().charpoly() # needs sage.modules True There is one pair of cospectral trees on eight vertices:: - sage: g=graphs.cospectral_graphs(6, graphs=graphs.trees(8)) - sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) + sage: g = graphs.cospectral_graphs(6, graphs=graphs.trees(8)) # needs sage.modules + sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) # needs sage.modules [['GiPC?C', 'GiQCC?']] - sage: g[0][1].am().charpoly()==g[0][1].am().charpoly() + sage: g[0][1].am().charpoly()==g[0][1].am().charpoly() # needs sage.modules True There are two sets of cospectral graphs (with respect to the Laplacian matrix) on six vertices:: - sage: g=graphs.cospectral_graphs(6, matrix_function=lambda g: g.laplacian_matrix()) - sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) + sage: g = graphs.cospectral_graphs(6, matrix_function=lambda g: g.laplacian_matrix()) # needs sage.modules + sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) # needs sage.modules [['Edq_', 'ErcG'], ['Exoo', 'EzcG']] - sage: g[0][1].laplacian_matrix().charpoly()==g[0][1].laplacian_matrix().charpoly() + sage: g[0][1].laplacian_matrix().charpoly()==g[0][1].laplacian_matrix().charpoly() # needs sage.modules True - sage: g[1][1].laplacian_matrix().charpoly()==g[1][1].laplacian_matrix().charpoly() + sage: g[1][1].laplacian_matrix().charpoly()==g[1][1].laplacian_matrix().charpoly() # needs sage.modules True To find cospectral graphs with respect to the normalized @@ -1278,10 +1278,12 @@ def cospectral_graphs(self, vertices, matrix_function=lambda g: g.adjacency_matr ....: for i in range(g.order()): ....: A.rescale_row(i, 1 / len(A.nonzero_positions_in_row(i))) ....: return A - sage: g = graphs.cospectral_graphs(5, matrix_function=DinverseA, graphs=lambda g: min(g.degree()) > 0) - sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) + sage: g = graphs.cospectral_graphs(5, matrix_function=DinverseA, # needs sage.modules + ....: graphs=lambda g: min(g.degree()) > 0) + sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) # needs sage.modules [['Dlg', 'Ds_']] - sage: g[0][1].laplacian_matrix(normalized=True).charpoly()==g[0][1].laplacian_matrix(normalized=True).charpoly() # optional - sage.symbolic + sage: (g[0][1].laplacian_matrix(normalized=True).charpoly() # needs sage.modules sage.symbolic + ....: == g[0][1].laplacian_matrix(normalized=True).charpoly()) True """ from sage.graphs.graph_generators import graphs as graph_gen diff --git a/src/sage/graphs/graph_generators_pyx.pyx b/src/sage/graphs/graph_generators_pyx.pyx index 716f4e5975a..060ea9275c6 100644 --- a/src/sage/graphs/graph_generators_pyx.pyx +++ b/src/sage/graphs/graph_generators_pyx.pyx @@ -55,8 +55,8 @@ def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None): TESTS:: - sage: from numpy import mean # optional - numpy - sage: abs(mean([RandomGNP(200, .2).density() for i in range(30)]) - .2) < .001 # optional - numpy + sage: from numpy import mean # needs numpy + sage: abs(mean([RandomGNP(200, .2).density() for i in range(30)]) - .2) < .001 # needs numpy True sage: RandomGNP(150, .2, loops=True) Traceback (most recent call last): diff --git a/src/sage/graphs/graph_input.py b/src/sage/graphs/graph_input.py index 39b22a44b56..e46a2156809 100644 --- a/src/sage/graphs/graph_input.py +++ b/src/sage/graphs/graph_input.py @@ -185,9 +185,9 @@ def from_seidel_adjacency_matrix(G, M): sage: from sage.graphs.graph_input import from_seidel_adjacency_matrix sage: g = Graph() - 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 + sage: sam = graphs.PetersenGraph().seidel_adjacency_matrix() # needs sage.modules + sage: from_seidel_adjacency_matrix(g, sam) # needs sage.modules + sage: g.is_isomorphic(graphs.PetersenGraph()) # needs sage.modules True """ from sage.structure.element import is_Matrix @@ -236,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()) # optional - sage.modules - sage: g.is_isomorphic(graphs.PetersenGraph()) # optional - sage.modules + sage: from_adjacency_matrix(g, graphs.PetersenGraph().adjacency_matrix()) # needs sage.modules + sage: g.is_isomorphic(graphs.PetersenGraph()) # needs sage.modules True """ from sage.structure.element import is_Matrix @@ -312,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()) # optional - sage.modules - sage: g.is_isomorphic(graphs.PetersenGraph()) # optional - sage.modules + sage: from_incidence_matrix(g, graphs.PetersenGraph().incidence_matrix()) # needs sage.modules + sage: g.is_isomorphic(graphs.PetersenGraph()) # needs sage.modules True """ from sage.structure.element import is_Matrix @@ -378,37 +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: 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 + sage: im = digraphs.Circuit(10).incidence_matrix() # needs sage.modules + sage: from_oriented_incidence_matrix(g, im) # needs sage.modules + sage: g.is_isomorphic(digraphs.Circuit(10)) # needs 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()) # optional - sage.modules + sage: DiGraph(matrix ([[1,0,0,1],[0,0,1,1],[0,0,1,1]]).transpose()) # needs 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]]); m # optional - sage.modules + sage: m = Matrix([[0,1],[0,-1],[0,0]]); m # needs sage.modules [ 0 1] [ 0 -1] [ 0 0] - sage: G = DiGraph(m, format='incidence_matrix') # optional - sage.modules - sage: list(G.edges(sort=True, labels=False)) # optional - sage.modules + sage: G = DiGraph(m, format='incidence_matrix') # needs sage.modules + sage: list(G.edges(sort=True, labels=False)) # needs sage.modules [(1, 0)] Handle incidence matrix [[1],[-1]] (:trac:`29275`):: - sage: m = Matrix([[1],[-1]]); m # optional - sage.modules + sage: m = Matrix([[1],[-1]]); m # needs sage.modules [ 1] [-1] - sage: G = DiGraph(m, format='incidence_matrix') # optional - sage.modules - sage: list(G.edges(sort=True, labels=False)) # optional - sage.modules + sage: G = DiGraph(m, format='incidence_matrix') # needs sage.modules + sage: list(G.edges(sort=True, labels=False)) # needs sage.modules [(1, 0)] """ from sage.structure.element import is_Matrix @@ -614,42 +614,42 @@ def from_networkx_graph(G, gnx, weighted=None, loops=None, multiedges=None, Feeding a :class:`Graph` with a NetworkX ``Graph``:: sage: from sage.graphs.graph_input import from_networkx_graph - sage: import networkx # optional - networkx + sage: import networkx # needs networkx sage: G = Graph() - sage: _ = gnx = networkx.Graph() # optional - networkx - sage: _ = gnx.add_edge(0, 1) # optional - networkx - sage: _ = gnx.add_edge(1, 2) # optional - networkx - sage: from_networkx_graph(G, gnx) # optional - networkx - sage: G.edges(sort=True, labels=False) # optional - networkx + sage: _ = gnx = networkx.Graph() # needs networkx + sage: _ = gnx.add_edge(0, 1) # needs networkx + sage: _ = gnx.add_edge(1, 2) # needs networkx + sage: from_networkx_graph(G, gnx) # needs networkx + sage: G.edges(sort=True, labels=False) # needs networkx [(0, 1), (1, 2)] Feeding a :class:`Graph` with a NetworkX ``MultiGraph``:: sage: G = Graph() - sage: gnx = networkx.MultiGraph() # optional - networkx - sage: _ = gnx.add_edge(0, 1) # optional - networkx - sage: _ = gnx.add_edge(0, 1) # optional - networkx - sage: from_networkx_graph(G, gnx) # optional - networkx - sage: G.edges(sort=True, labels=False) # optional - networkx + sage: gnx = networkx.MultiGraph() # needs networkx + sage: _ = gnx.add_edge(0, 1) # needs networkx + sage: _ = gnx.add_edge(0, 1) # needs networkx + sage: from_networkx_graph(G, gnx) # needs networkx + sage: G.edges(sort=True, labels=False) # needs networkx [(0, 1), (0, 1)] sage: G = Graph() - sage: from_networkx_graph(G, gnx, multiedges=False) # optional - networkx - sage: G.edges(sort=True, labels=False) # optional - networkx + sage: from_networkx_graph(G, gnx, multiedges=False) # needs networkx + sage: G.edges(sort=True, labels=False) # needs networkx [(0, 1)] When feeding a :class:`Graph` `G` with a NetworkX ``DiGraph`` `D`, `G` has one edge `(u, v)` whenever `D` has arc `(u, v)` or `(v, u)` or both:: sage: G = Graph() - sage: D = networkx.DiGraph() # optional - networkx - sage: _ = D.add_edge(0, 1) # optional - networkx - sage: from_networkx_graph(G, D) # optional - networkx - sage: G.edges(sort=True, labels=False) # optional - networkx + sage: D = networkx.DiGraph() # needs networkx + sage: _ = D.add_edge(0, 1) # needs networkx + sage: from_networkx_graph(G, D) # needs networkx + sage: G.edges(sort=True, labels=False) # needs networkx [(0, 1)] sage: G = Graph() - sage: _ = D.add_edge(1, 0) # optional - networkx - sage: from_networkx_graph(G, D) # optional - networkx - sage: G.edges(sort=True, labels=False) # optional - networkx + sage: _ = D.add_edge(1, 0) # needs networkx + sage: from_networkx_graph(G, D) # needs networkx + sage: G.edges(sort=True, labels=False) # needs networkx [(0, 1)] When feeding a :class:`Graph` `G` with a NetworkX ``MultiDiGraph`` `D`, the @@ -657,50 +657,50 @@ def from_networkx_graph(G, gnx, weighted=None, loops=None, multiedges=None, of arcs `(u, v)` and the number of arcs `(v, u)` in D`:: sage: G = Graph() - sage: D = networkx.MultiDiGraph() # optional - networkx - sage: _ = D.add_edge(0, 1) # optional - networkx - sage: _ = D.add_edge(1, 0) # optional - networkx - sage: _ = D.add_edge(1, 0) # optional - networkx - sage: D.edges() # optional - networkx + sage: D = networkx.MultiDiGraph() # needs networkx + sage: _ = D.add_edge(0, 1) # needs networkx + sage: _ = D.add_edge(1, 0) # needs networkx + sage: _ = D.add_edge(1, 0) # needs networkx + sage: D.edges() # needs networkx OutMultiEdgeDataView([(0, 1), (1, 0), (1, 0)]) - sage: from_networkx_graph(G, D) # optional - networkx - sage: G.edges(sort=True, labels=False) # optional - networkx + sage: from_networkx_graph(G, D) # needs networkx + sage: G.edges(sort=True, labels=False) # needs networkx [(0, 1), (0, 1)] Feeding a :class:`DiGraph` with a NetworkX ``DiGraph``:: sage: from sage.graphs.graph_input import from_networkx_graph - sage: import networkx # optional - networkx + sage: import networkx # needs networkx sage: G = DiGraph() - sage: _ = gnx = networkx.DiGraph() # optional - networkx - sage: _ = gnx.add_edge(0, 1) # optional - networkx - sage: _ = gnx.add_edge(1, 2) # optional - networkx - sage: from_networkx_graph(G, gnx) # optional - networkx - sage: G.edges(sort=True, labels=False) # optional - networkx + sage: _ = gnx = networkx.DiGraph() # needs networkx + sage: _ = gnx.add_edge(0, 1) # needs networkx + sage: _ = gnx.add_edge(1, 2) # needs networkx + sage: from_networkx_graph(G, gnx) # needs networkx + sage: G.edges(sort=True, labels=False) # needs networkx [(0, 1), (1, 2)] Feeding a :class:`DiGraph` with a NetworkX ``MultiDiGraph``:: sage: G = DiGraph() - sage: gnx = networkx.MultiDiGraph() # optional - networkx - sage: _ = gnx.add_edge(0, 1) # optional - networkx - sage: _ = gnx.add_edge(0, 1) # optional - networkx - sage: from_networkx_graph(G, gnx) # optional - networkx - sage: G.edges(sort=True, labels=False) # optional - networkx + sage: gnx = networkx.MultiDiGraph() # needs networkx + sage: _ = gnx.add_edge(0, 1) # needs networkx + sage: _ = gnx.add_edge(0, 1) # needs networkx + sage: from_networkx_graph(G, gnx) # needs networkx + sage: G.edges(sort=True, labels=False) # needs networkx [(0, 1), (0, 1)] sage: G = DiGraph() - sage: from_networkx_graph(G, gnx, multiedges=False) # optional - networkx - sage: G.edges(sort=True, labels=False) # optional - networkx + sage: from_networkx_graph(G, gnx, multiedges=False) # needs networkx + sage: G.edges(sort=True, labels=False) # needs networkx [(0, 1)] When feeding a :class:`DiGraph` `G` with a NetworkX ``Graph`` `H`, `G` has both arcs `(u, v)` and `(v, u)` if `G` has edge `(u, v)`:: sage: G = DiGraph() - sage: H = networkx.Graph() # optional - networkx - sage: _ = H.add_edge(0, 1) # optional - networkx - sage: from_networkx_graph(G, H) # optional - networkx - sage: G.edges(labels=False, sort=True) # optional - networkx + sage: H = networkx.Graph() # needs networkx + sage: _ = H.add_edge(0, 1) # needs networkx + sage: from_networkx_graph(G, H) # needs networkx + sage: G.edges(labels=False, sort=True) # needs networkx [(0, 1), (1, 0)] When feeding a :class:`DiGraph` `G` with a NetworkX ``MultiGraph`` `H`, `G` @@ -708,18 +708,18 @@ def from_networkx_graph(G, gnx, weighted=None, loops=None, multiedges=None, unless parameter ``multiedges`` is set to ``False``:: sage: G = DiGraph() - sage: H = networkx.MultiGraph() # optional - networkx - sage: _ = H.add_edge(0, 1) # optional - networkx - sage: _ = H.add_edge(0, 1) # optional - networkx - sage: _ = H.add_edge(0, 1) # optional - networkx - sage: H.edges() # optional - networkx + sage: H = networkx.MultiGraph() # needs networkx + sage: _ = H.add_edge(0, 1) # needs networkx + sage: _ = H.add_edge(0, 1) # needs networkx + sage: _ = H.add_edge(0, 1) # needs networkx + sage: H.edges() # needs networkx MultiEdgeDataView([(0, 1), (0, 1), (0, 1)]) - sage: from_networkx_graph(G, H) # optional - networkx - sage: G.edges(labels=False, sort=True) # optional - networkx + sage: from_networkx_graph(G, H) # needs networkx + sage: G.edges(labels=False, sort=True) # needs networkx [(0, 1), (0, 1), (0, 1), (1, 0), (1, 0), (1, 0)] sage: G = DiGraph() - sage: from_networkx_graph(G, H, multiedges=False) # optional - networkx - sage: G.edges(labels=False, sort=True) # optional - networkx + sage: from_networkx_graph(G, H, multiedges=False) # needs networkx + sage: G.edges(labels=False, sort=True) # needs networkx [(0, 1), (1, 0)] TESTS: @@ -736,7 +736,7 @@ def from_networkx_graph(G, gnx, weighted=None, loops=None, multiedges=None, ``DiGraph`` or ``MultiDiGraph``:: sage: from sage.graphs.graph_input import from_networkx_graph - sage: from_networkx_graph(Graph(), "bar") # optional - networkx + sage: from_networkx_graph(Graph(), "bar") # needs networkx Traceback (most recent call last): ... ValueError: the second parameter must be a NetworkX (Multi)(Di)Graph diff --git a/src/sage/graphs/graph_latex.py b/src/sage/graphs/graph_latex.py index 7666151fb50..7988f6e3518 100644 --- a/src/sage/graphs/graph_latex.py +++ b/src/sage/graphs/graph_latex.py @@ -265,14 +265,14 @@ package. So it is worth viewing this in the notebook to see the effects of various defaults and choices.:: - sage: var('x y u w') # optional - sage.symbolic + sage: var('x y u w') # needs sage.symbolic (x, y, u, w) sage: G = Graph(loops=True) - sage: for i in range(5): # optional - sage.symbolic + sage: for i in range(5): # needs sage.symbolic ....: for j in range(i+1, 5): ....: G.add_edge((i, j), label=(x^i*y^j).expand()) - sage: G.add_edge((0,0), label=sin(u)) # optional - sage.symbolic - sage: G.add_edge((4,4), label=w^5) # optional - sage.symbolic + sage: G.add_edge((0,0), label=sin(u)) # needs sage.symbolic + sage: G.add_edge((4,4), label=w^5) # needs sage.symbolic sage: G.set_pos(G.layout_circular()) sage: G.set_latex_options( ....: units='in', @@ -307,7 +307,7 @@ ....: ) sage: from sage.graphs.graph_latex import check_tkz_graph sage: check_tkz_graph() # random - depends on TeX installation - sage: print(latex(G)) # optional - sage.symbolic + sage: print(latex(G)) # needs sage.symbolic \begin{tikzpicture} \definecolor{cv0}{rgb}{0.8,0.8,0.8} \definecolor{cfv0}{rgb}{0.0,0.0,1.0} diff --git a/src/sage/graphs/graph_list.py b/src/sage/graphs/graph_list.py index 4a43987a79b..6994a821948 100644 --- a/src/sage/graphs/graph_list.py +++ b/src/sage/graphs/graph_list.py @@ -258,17 +258,17 @@ def to_graphics_array(graph_list, **kwds): sage: glist = [] sage: for i in range(999): ....: glist.append(graphs.RandomGNP(6, .45)) - sage: garray = graphs_list.to_graphics_array(glist) # optional - sage.plot - sage: garray.nrows(), garray.ncols() # optional - sage.plot + sage: garray = graphs_list.to_graphics_array(glist) # needs sage.plot + sage: garray.nrows(), garray.ncols() # needs sage.plot (250, 4) See the .plot() or .show() documentation for an individual graph for options, all of which are available from :func:`to_graphics_array`:: sage: glist = [] - sage: for _ in range(10): # optional - networkx + sage: for _ in range(10): # needs networkx ....: glist.append(graphs.RandomLobster(41, .3, .4)) - sage: graphs_list.to_graphics_array(glist, layout='spring', vertex_size=20) # optional - networkx sage.plot + sage: graphs_list.to_graphics_array(glist, layout='spring', vertex_size=20) # needs networkx sage.plot Graphics Array of size 3 x 4 """ from sage.graphs import graph @@ -342,7 +342,7 @@ def show_graphs(graph_list, **kwds): Show the graphs in a graphics array:: - sage: graphs_list.show_graphs(glist) # optional - sage.plot + sage: graphs_list.show_graphs(glist) # needs sage.plot Example where more than one graphics array is used:: @@ -350,15 +350,15 @@ def show_graphs(graph_list, **kwds): sage: g = gq.get_graphs_list() sage: len(g) 34 - sage: graphs_list.show_graphs(g) # optional - sage.plot + sage: graphs_list.show_graphs(g) # needs sage.plot See the .plot() or .show() documentation for an individual graph for options, all of which are available from :func:`to_graphics_array`:: sage: glist = [] - sage: for _ in range(10): + sage: for _ in range(10): # needs networkx ....: glist.append(graphs.RandomLobster(41, .3, .4)) - sage: graphs_list.show_graphs(glist, layout='spring', vertex_size=20) # optional - sage.plot + sage: graphs_list.show_graphs(glist, layout='spring', vertex_size=20) # needs sage.plot """ graph_list = list(graph_list) for i in range(len(graph_list) // 20 + 1): diff --git a/src/sage/graphs/graph_plot_js.py b/src/sage/graphs/graph_plot_js.py index ad846d7a474..a29e7293df8 100644 --- a/src/sage/graphs/graph_plot_js.py +++ b/src/sage/graphs/graph_plot_js.py @@ -174,14 +174,15 @@ def gen_html_code(G, sage: graphs.DodecahedralGraph().show(method="js") # optional -- internet 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 + sage: # needs sage.combinat + 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, ....: link_distance=200, gravity=.05, charge=-500, ....: edge_partition=[[("11", "12", "2"), ("21", "21", "a")]], ....: edge_thickness=4) diff --git a/src/sage/graphs/hypergraph_generators.py b/src/sage/graphs/hypergraph_generators.py index c3e42da9565..3d6a7d28cd6 100644 --- a/src/sage/graphs/hypergraph_generators.py +++ b/src/sage/graphs/hypergraph_generators.py @@ -217,7 +217,7 @@ def CompleteUniform(self, n, k): sage: h = hypergraphs.CompleteUniform(5, 2); h Incidence structure with 5 points and 10 blocks - sage: len(h.packing()) + sage: len(h.packing()) # needs sage.numerical.mip 2 """ from sage.combinat.designs.incidence_structures import IncidenceStructure @@ -306,34 +306,35 @@ def BinomialRandomUniform(self, n, k, p): EXAMPLES:: - sage: hypergraphs.BinomialRandomUniform(50, 3, 1).num_blocks() # optional - numpy + sage: hypergraphs.BinomialRandomUniform(50, 3, 1).num_blocks() # needs numpy 19600 - sage: hypergraphs.BinomialRandomUniform(50, 3, 0).num_blocks() # optional - numpy + sage: hypergraphs.BinomialRandomUniform(50, 3, 0).num_blocks() # needs numpy 0 TESTS:: - sage: hypergraphs.BinomialRandomUniform(50, 3, -0.1) # optional - numpy + sage: # needs numpy + sage: hypergraphs.BinomialRandomUniform(50, 3, -0.1) Traceback (most recent call last): ... ValueError: edge probability should be in [0,1] - sage: hypergraphs.BinomialRandomUniform(50, 3, 1.1) # optional - numpy + sage: hypergraphs.BinomialRandomUniform(50, 3, 1.1) Traceback (most recent call last): ... ValueError: edge probability should be in [0,1] - sage: hypergraphs.BinomialRandomUniform(-50, 3, 0.17) # optional - numpy + sage: hypergraphs.BinomialRandomUniform(-50, 3, 0.17) Traceback (most recent call last): ... ValueError: number of vertices should be non-negative - sage: hypergraphs.BinomialRandomUniform(50.9, 3, 0.17) # optional - numpy + sage: hypergraphs.BinomialRandomUniform(50.9, 3, 0.17) Traceback (most recent call last): ... ValueError: number of vertices should be an integer - sage: hypergraphs.BinomialRandomUniform(50, -3, 0.17) # optional - numpy + sage: hypergraphs.BinomialRandomUniform(50, -3, 0.17) Traceback (most recent call last): ... ValueError: the uniformity should be non-negative - sage: hypergraphs.BinomialRandomUniform(50, I, 0.17) # optional - numpy + sage: hypergraphs.BinomialRandomUniform(50, I, 0.17) Traceback (most recent call last): ... ValueError: the uniformity should be an integer diff --git a/src/sage/graphs/independent_sets.pyx b/src/sage/graphs/independent_sets.pyx index d894f1706ed..23c8677b34a 100644 --- a/src/sage/graphs/independent_sets.pyx +++ b/src/sage/graphs/independent_sets.pyx @@ -162,7 +162,7 @@ cdef class IndependentSets: ....: IS2.extend(map(Set, list(G.subgraph_search_iterator(Graph(n), induced=True, return_graphs=False)))) ....: if len(IS) != len(set(IS2)): ....: raise ValueError("something goes wrong") - sage: for i in range(5): + sage: for i in range(5): # needs sage.modules ....: check_with_subgraph_search(graphs.RandomGNP(11, .3)) Empty graph:: diff --git a/src/sage/graphs/isoperimetric_inequalities.pyx b/src/sage/graphs/isoperimetric_inequalities.pyx index b6dfa40d06d..1d01e311c1c 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) # optional - networkx - sage: g.edge_isoperimetric_number() == g.cheeger_constant() * 3 # optional - networkx + sage: g = graphs.RandomRegular(3, 10) # needs networkx + sage: g.edge_isoperimetric_number() == g.cheeger_constant() * 3 # needs 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 656c9c08909..a30055e891c 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] # optional - sage.modules - sage: C.is_isomorphic(graphs.ClawGraph()) # optional - sage.modules + sage: C = graphs.PetersenGraph().is_line_graph(certificate=True)[1] # needs sage.modules + sage: C.is_isomorphic(graphs.ClawGraph()) # needs sage.modules True The house graph is a line graph:: @@ -188,11 +188,12 @@ 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) # optional - sage.modules - sage: R.sparse6_string() # optional - sage.modules + sage: # needs sage.modules + sage: is_line, R, isom = g.is_line_graph(certificate=True) + sage: R.sparse6_string() ':DaHI~' - sage: R.show() # optional - sage.modules sage.plot - sage: isom # optional - sage.modules + sage: R.show() # needs sage.plot + sage: isom {0: (0, 1), 1: (0, 2), 2: (1, 3), 3: (2, 3), 4: (3, 4)} TESTS: @@ -201,8 +202,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] # optional - sage.modules - sage: g.line_graph().is_isomorphic(gl) # optional - sage.modules + sage: new_g = gl.is_line_graph(certificate=True)[1] # needs sage.modules + sage: g.line_graph().is_isomorphic(gl) # needs sage.modules True Verify that :trac:`29740` is fixed:: @@ -314,7 +315,7 @@ def line_graph(g, labels=True): (1, 2, None), (1, 3, None), (2, 3, None)] - sage: h.am() # optional - sage.modules + sage: h.am() # needs sage.modules [0 1 1 1 1 0] [1 0 1 1 0 1] [1 1 0 0 1 1] @@ -324,7 +325,7 @@ def line_graph(g, labels=True): sage: h2 = g.line_graph(labels=False) sage: h2.vertices(sort=True) [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] - sage: h2.am() == h.am() + sage: h2.am() == h.am() # needs sage.modules True sage: g = DiGraph([[1..4], lambda i,j: i < j]) sage: h = g.line_graph() diff --git a/src/sage/graphs/matchpoly.pyx b/src/sage/graphs/matchpoly.pyx index 7845b225f9c..e98cc8d6b63 100644 --- a/src/sage/graphs/matchpoly.pyx +++ b/src/sage/graphs/matchpoly.pyx @@ -328,9 +328,9 @@ def complete_poly(n): Checking the numerical results up to 20:: - sage: from sage.functions.orthogonal_polys import hermite # optional - sage.symbolic - sage: p = lambda n: 2^(-n/2)*hermite(n, x/sqrt(2)) # optional - sage.symbolic - sage: all(p(i) == complete_poly(i) for i in range(2, 20)) # optional - sage.symbolic + sage: from sage.functions.orthogonal_polys import hermite # needs sage.symbolic + sage: p = lambda n: 2^(-n/2)*hermite(n, x/sqrt(2)) # needs sage.symbolic + sage: all(p(i) == complete_poly(i) for i in range(2, 20)) # needs sage.symbolic True """ # global complete_matching_polys # if we do eventually make it a C array... diff --git a/src/sage/graphs/partial_cube.py b/src/sage/graphs/partial_cube.py index 0ec81f6b200..70456e548c9 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) # optional - sage.combinat - sage: list(sage.graphs.partial_cube.breadth_first_level_search(H, '00')) # optional - sage.combinat + sage: H = digraphs.DeBruijn(3,2) # needs sage.combinat + sage: list(sage.graphs.partial_cube.breadth_first_level_search(H, '00')) # needs 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) # optional - sage.combinat - sage: t = list(sage.graphs.partial_cube.depth_first_traversal(H, '00')) # optional - sage.combinat - sage: len(t) # optional - sage.combinat + sage: H = digraphs.DeBruijn(3,2) # needs sage.combinat + sage: t = list(sage.graphs.partial_cube.depth_first_traversal(H, '00')) # needs sage.combinat + sage: len(t) # needs sage.combinat 16 """ neighbors = G.neighbor_out_iterator diff --git a/src/sage/graphs/path_enumeration.pyx b/src/sage/graphs/path_enumeration.pyx index 032ebd95ec2..50836ffdcb9 100644 --- a/src/sage/graphs/path_enumeration.pyx +++ b/src/sage/graphs/path_enumeration.pyx @@ -432,20 +432,20 @@ def shortest_simple_paths(self, source, target, weight_function=None, [1, 2, 3, 4, 5], [1, 6, 9, 3, 4, 5], [1, 6, 9, 11, 10, 5]] - sage: G = digraphs.DeBruijn(2, 3) - sage: for u,v in G.edges(sort=True, labels=False): + sage: G = digraphs.DeBruijn(2, 3) # needs sage.combinat + sage: for u,v in G.edges(sort=True, labels=False): # needs sage.combinat ....: G.set_edge_label(u, v, 1) - sage: G.allow_multiple_edges(True) - sage: for u,v in G.edges(sort=True, labels=False): + sage: G.allow_multiple_edges(True) # needs sage.combinat + sage: for u,v in G.edges(sort=True, labels=False): # needs sage.combinat ....: G.add_edge(u, v, 2) - sage: list(G.shortest_simple_paths('000', '111')) + sage: list(G.shortest_simple_paths('000', '111')) # needs sage.combinat [['000', '001', '011', '111'], ['000', '001', '010', '101', '011', '111']] - sage: list(G.shortest_simple_paths('000', '111', by_weight=True)) + sage: list(G.shortest_simple_paths('000', '111', by_weight=True)) # needs sage.combinat [['000', '001', '011', '111'], ['000', '001', '010', '101', '011', '111']] - sage: list(G.shortest_simple_paths('000', '111', by_weight=True, report_weight=True)) + sage: list(G.shortest_simple_paths('000', '111', by_weight=True, report_weight=True)) # needs sage.combinat [(3, ['000', '001', '011', '111']), (5, ['000', '001', '010', '101', '011', '111'])] - sage: list(G.shortest_simple_paths('000', '111', by_weight=True, report_weight=True, report_edges=True, labels=True)) + sage: list(G.shortest_simple_paths('000', '111', by_weight=True, report_weight=True, report_edges=True, labels=True)) # needs sage.combinat [(3, [('000', '001', 1), ('001', '011', 1), ('011', '111', 1)]), (5, [('000', '001', 1), @@ -470,12 +470,12 @@ def shortest_simple_paths(self, source, target, weight_function=None, Check for consistency of results of Yen's and Feng's:: - sage: G = digraphs.DeBruijn(2, 4) + sage: G = digraphs.DeBruijn(2, 4) # needs sage.combinat sage: s = set() - sage: for p in G.shortest_simple_paths('0000', '1111', by_weight=False, algorithm='Yen'): + sage: for p in G.shortest_simple_paths('0000', '1111', by_weight=False, algorithm='Yen'): # needs sage.combinat ....: s.add(tuple(p)) sage: k = set() - sage: for p in G.shortest_simple_paths('0000', '1111', by_weight=False, algorithm='Feng'): + sage: for p in G.shortest_simple_paths('0000', '1111', by_weight=False, algorithm='Feng'): # needs sage.combinat ....: k.add(tuple(p)) sage: k == s True diff --git a/src/sage/graphs/planarity.pyx b/src/sage/graphs/planarity.pyx index 839039a2bde..ff501043ea5 100644 --- a/src/sage/graphs/planarity.pyx +++ b/src/sage/graphs/planarity.pyx @@ -72,17 +72,18 @@ def is_planar(g, kuratowski=False, set_pos=False, set_embedding=False, circular= vertices. In fact, to try to track down a segfault, we do it twice. :: - sage: import networkx.generators.atlas # long time # optional - networkx - sage: atlas_graphs = [Graph(i) for i in networkx.generators.atlas.graph_atlas_g()] # long time # optional - networkx - sage: a = [i for i in [1..1252] if atlas_graphs[i].is_planar()] # long time # optional - networkx - sage: b = [i for i in [1..1252] if atlas_graphs[i].is_planar()] # long time # optional - networkx - sage: a == b # long time # optional - networkx + sage: # long time, needs networkx + sage: import networkx.generators.atlas + sage: atlas_graphs = [Graph(i) for i in networkx.generators.atlas.graph_atlas_g()] + sage: a = [i for i in [1..1252] if atlas_graphs[i].is_planar()] + sage: b = [i for i in [1..1252] if atlas_graphs[i].is_planar()] + sage: a == b True There were some problems with ``set_pos`` stability in the past, so let's check if this runs without exception:: - sage: for i, g in enumerate(atlas_graphs): # long time # optional - networkx + sage: for i, g in enumerate(atlas_graphs): # long time # needs networkx ....: if (not g.is_connected() or i == 0): ....: continue ....: _ = g.is_planar(set_embedding=True, set_pos=True) diff --git a/src/sage/graphs/schnyder.py b/src/sage/graphs/schnyder.py index 5427a93691e..40f6d923656 100644 --- a/src/sage/graphs/schnyder.py +++ b/src/sage/graphs/schnyder.py @@ -743,7 +743,7 @@ def minimal_schnyder_wood(graph, root_edge=None, minimal=True, check=True): sage: newg = minimal_schnyder_wood(g) sage: newg.edges(sort=True) [(0, -3, 'red'), (0, -2, 'blue'), (0, -1, 'green')] - sage: newg.plot(color_by_label={'red':'red','blue':'blue', # optional - sage.plot + sage: newg.plot(color_by_label={'red':'red','blue':'blue', # needs sage.plot ....: 'green':'green',None:'black'}) Graphics object consisting of 8 graphics primitives diff --git a/src/sage/graphs/spanning_tree.pyx b/src/sage/graphs/spanning_tree.pyx index 08f441d90a8..11fd83c0759 100644 --- a/src/sage/graphs/spanning_tree.pyx +++ b/src/sage/graphs/spanning_tree.pyx @@ -196,6 +196,7 @@ def kruskal(G, by_weight=True, weight_function=None, check_weight=False, check=F The input graph must be connected. :: + sage: # long time sage: def my_disconnected_graph(n, ntries, directed=False, multiedges=False, loops=False): ....: G = Graph() ....: k = randint(2, n) @@ -216,14 +217,14 @@ def kruskal(G, by_weight=True, weight_function=None, check_weight=False, check=F ....: v = randint(0, k-1) ....: G.delete_edge(u, v) ....: return G - sage: G = my_disconnected_graph(100, 50, directed=False, multiedges=False, loops=False) # long time - sage: kruskal(G, check=True) # long time + sage: G = my_disconnected_graph(100, 50, directed=False, multiedges=False, loops=False) + sage: kruskal(G, check=True) [] - sage: G = my_disconnected_graph(100, 50, directed=False, multiedges=True, loops=False) # long time - sage: kruskal(G, check=True) # long time + sage: G = my_disconnected_graph(100, 50, directed=False, multiedges=True, loops=False) + sage: kruskal(G, check=True) [] - sage: G = my_disconnected_graph(100, 50, directed=False, multiedges=True, loops=True) # long time - sage: kruskal(G, check=True) # long time + sage: G = my_disconnected_graph(100, 50, directed=False, multiedges=True, loops=True) + sage: kruskal(G, check=True) [] If the input graph is a tree, then return its edges:: @@ -568,12 +569,13 @@ def filter_kruskal_iterator(G, threshold=10000, by_weight=True, weight_function= The weights of the spanning trees returned by :func:`kruskal_iterator` and :func:`filter_kruskal_iterator` are the same:: + sage: # needs networkx sage: from sage.graphs.spanning_tree import kruskal_iterator - sage: G = graphs.RandomBarabasiAlbert(50, 2) # optional - networkx - sage: for u, v in G.edge_iterator(labels=False): # optional - networkx + sage: G = graphs.RandomBarabasiAlbert(50, 2) + sage: for u, v in G.edge_iterator(labels=False): ....: G.set_edge_label(u, v, randint(1, 10)) - sage: G.weighted(True) # optional - networkx - sage: sum(e[2] for e in kruskal_iterator(G)) == sum(e[2] # optional - networkx + 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)) True @@ -976,7 +978,7 @@ def random_spanning_tree(G, output_as_graph=False, by_weight=False, weight_funct sage: pos = G.get_pos() sage: T = G.random_spanning_tree(True) sage: T.set_pos(pos) - sage: T.show(vertex_labels=False) # optional - sage.plot + sage: T.show(vertex_labels=False) # needs sage.plot We can also use edge weights to change the probability of returning a spanning tree:: @@ -1000,11 +1002,12 @@ 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) # optional - networkx - sage: for u, v in G.edge_iterator(labels=False): # optional - networkx + sage: # needs networkx + sage: G = graphs.RandomBarabasiAlbert(50, 2) + sage: for u, v in G.edge_iterator(labels=False): ....: G.set_edge_label(u, v, randint(1, 10)) - sage: T = G.random_spanning_tree(by_weight=True, output_as_graph=True) # optional - networkx - sage: T.is_tree() # optional - networkx + sage: T = G.random_spanning_tree(by_weight=True, output_as_graph=True) + sage: T.is_tree() True TESTS:: @@ -1088,12 +1091,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() # optional - sage.modules + sage: G.spanning_trees_count() # needs 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() # optional - sage.modules + sage: G.spanning_trees_count() # needs sage.modules 6 .. SEEALSO:: diff --git a/src/sage/graphs/strongly_regular_db.pyx b/src/sage/graphs/strongly_regular_db.pyx index 3d48b45e58d..1c9e8699905 100644 --- a/src/sage/graphs/strongly_regular_db.pyx +++ b/src/sage/graphs/strongly_regular_db.pyx @@ -70,9 +70,9 @@ def is_paley(int v, int k, int l, int mu): sage: from sage.graphs.strongly_regular_db import is_paley sage: t = is_paley(13,6,2,3); t (..., 13) - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.rings.finite_rings Paley graph with parameter 13: Graph on 13 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings (13, 6, 2, 3) sage: t = is_paley(5,5,5,5); t """ @@ -110,18 +110,18 @@ def is_mathon_PC_srg(int v, int k, int l, int mu): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import is_mathon_PC_srg - sage: t = is_mathon_PC_srg(45,22,10,11); t + sage: t = is_mathon_PC_srg(45,22,10,11); t # needs sage.libs.pari (..., 1) - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.libs.pari Mathon's PC SRG on 45 vertices: Graph on 45 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.pari (45, 22, 10, 11) TESTS:: - sage: t = is_mathon_PC_srg(5,5,5,5); t - sage: mu = 1895 # t=5 case -- the construction cannot work - sage: t = is_mathon_PC_srg(4*mu+1,2*mu,mu-1,mu); t + sage: t = is_mathon_PC_srg(5,5,5,5); t # needs sage.libs.pari + sage: mu = 1895 # t=5 case -- the construction cannot work # needs sage.libs.pari + sage: t = is_mathon_PC_srg(4*mu+1,2*mu,mu-1,mu); t # needs sage.libs.pari """ cdef int t if (v % 4 == 1 and @@ -162,6 +162,7 @@ def is_muzychuk_S6(int v, int k, int l, int mu): EXAMPLES:: + sage: # needs sage.libs.pari sage: from sage.graphs.strongly_regular_db import is_muzychuk_S6 sage: t = is_muzychuk_S6(378, 116, 34, 36) sage: G = t[0](*t[1:]); G @@ -211,6 +212,7 @@ def is_orthogonal_array_block_graph(int v, int k, int l, int mu): EXAMPLES:: + sage: # needs sage.combinat sage.modules sage: from sage.graphs.strongly_regular_db import is_orthogonal_array_block_graph sage: t = is_orthogonal_array_block_graph(64, 35, 18, 20); t (..., 5, 8) @@ -218,20 +220,20 @@ def is_orthogonal_array_block_graph(int v, int k, int l, int mu): OA(5,8): Graph on 64 vertices sage: g.is_strongly_regular(parameters=True) (64, 35, 18, 20) - sage: t=is_orthogonal_array_block_graph(225,98,43,42); t + sage: t = is_orthogonal_array_block_graph(225,98,43,42); t (..., 4) sage: g = t[0](*t[1:]); g Pasechnik Graph_4: Graph on 225 vertices sage: g.is_strongly_regular(parameters=True) (225, 98, 43, 42) - sage: t=is_orthogonal_array_block_graph(225,112,55,56); t + sage: t = is_orthogonal_array_block_graph(225,112,55,56); t (..., 4) sage: g = t[0](*t[1:]); g skewhad^2_4: Graph on 225 vertices sage: g.is_strongly_regular(parameters=True) (225, 112, 55, 56) - sage: t = is_orthogonal_array_block_graph(5,5,5,5); t + sage: t = is_orthogonal_array_block_graph(5,5,5,5); t # needs sage.combinat sage.modules """ # notations from # https://www.win.tue.nl/~aeb/graphs/OA.html @@ -356,11 +358,11 @@ def is_affine_polar(int v, int k, int l, int mu): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import is_affine_polar - sage: t = is_affine_polar(81,32,13,12); t + sage: t = is_affine_polar(81,32,13,12); t # needs sage.rings.finite_rings (..., 4, 3) - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.rings.finite_rings Affine Polar Graph VO^+(4,3): Graph on 81 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings (81, 32, 13, 12) sage: t = is_affine_polar(5,5,5,5); t @@ -413,12 +415,12 @@ def is_orthogonal_polar(int v, int k, int l, int mu): sage: from sage.graphs.strongly_regular_db import is_orthogonal_polar sage: t = is_orthogonal_polar(85, 20, 3, 5); t (, 5, 4, '') - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.rings.finite_rings Orthogonal Polar Graph O(5, 4): Graph on 85 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings (85, 20, 3, 5) - sage: t = is_orthogonal_polar(5,5,5,5); t + sage: t = is_orthogonal_polar(5,5,5,5); t # needs sage.rings.finite_rings TESTS: @@ -428,7 +430,7 @@ def is_orthogonal_polar(int v, int k, int l, int mu): (, 5, 4, '') sage: is_orthogonal_polar(119,54,21,27) (, 8, 2, '-') - sage: is_orthogonal_polar(130,48,20,16) + sage: is_orthogonal_polar(130,48,20,16) # needs sage.rings.finite_rings (, 6, 3, '+') """ @@ -487,25 +489,26 @@ def is_goethals_seidel(int v, int k, int l, int mu): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import is_goethals_seidel - sage: t = is_goethals_seidel(28, 15, 6, 10); t + sage: t = is_goethals_seidel(28, 15, 6, 10); t # needs sage.combinat sage.modules [, 3, 3] - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.combinat sage.modules Graph on 28 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.combinat sage.modules (28, 15, 6, 10) - sage: t = is_goethals_seidel(256, 135, 70, 72); t + sage: t = is_goethals_seidel(256, 135, 70, 72); t # needs sage.combinat sage.modules [, 2, 15] - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.combinat sage.modules Graph on 256 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.combinat sage.modules (256, 135, 70, 72) - sage: t = is_goethals_seidel(5,5,5,5); t + sage: t = is_goethals_seidel(5,5,5,5); t # needs sage.combinat sage.modules TESTS:: - sage: for p in [(16, 9, 4, 6), (28, 15, 6, 10), (64, 35, 18, 20), (120, 63, 30, 36), + sage: for p in [(16, 9, 4, 6), (28, 15, 6, 10), # needs sage.combinat sage.modules + ....: (64, 35, 18, 20), (120, 63, 30, 36), ....: (144, 77, 40, 42), (256, 135, 70, 72), (400, 209, 108, 110), ....: (496, 255, 126, 136), (540, 275, 130, 150), (576, 299, 154, 156), ....: (780, 399, 198, 210), (784, 405, 208, 210), (976, 495, 238, 264)]: @@ -567,26 +570,27 @@ def is_NOodd(int v, int k, int l, int mu): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import is_NOodd - sage: t = is_NOodd(120, 51, 18, 24); t + sage: t = is_NOodd(120, 51, 18, 24); t # needs sage.libs.pari (, 5, 4, '-') - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.libs.pari NO^-(5, 4): Graph on 120 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.pari (120, 51, 18, 24) TESTS: All of ``NO^+(2m+1,q)`` and ``NO^-(2m+1,q)`` appear:: + sage: # needs sage.libs.pari sage: t = is_NOodd(120, 51, 18, 24); t (, 5, 4, '-') sage: t = is_NOodd(136, 75, 42, 40); t (, 5, 4, '+') - sage: t=is_NOodd(378, 260, 178, 180); t + sage: t = is_NOodd(378, 260, 178, 180); t (, 7, 3, '+') - sage: t=is_NOodd(45, 32, 22, 24); t + sage: t = is_NOodd(45, 32, 22, 24); t (, 5, 3, '+') - sage: t=is_NOodd(351, 224, 142, 144); t + sage: t = is_NOodd(351, 224, 142, 144); t (, 7, 3, '-') sage: t = is_NOodd(325, 144, 68, 60); t (, 5, 5, '+') @@ -637,22 +641,22 @@ def is_NOperp_F5(int v, int k, int l, int mu): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import is_NOperp_F5 - sage: t = is_NOperp_F5(10, 3, 0, 1); t + sage: t = is_NOperp_F5(10, 3, 0, 1); t # needs sage.libs.pari (, 3, 5, '-', 1) - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.libs.pari NO^-,perp(3, 5): Graph on 10 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.pari (10, 3, 0, 1) TESTS: All of ``NO^+,perp(2m+1,5)`` and ``NO^-,perp(2m+1,5)`` appear:: - sage: t = is_NOperp_F5(325, 60, 15, 10); t + sage: t = is_NOperp_F5(325, 60, 15, 10); t # needs sage.libs.pari (, 5, 5, '+', 1) - sage: t = is_NOperp_F5(300, 65, 10, 15); t + sage: t = is_NOperp_F5(300, 65, 10, 15); t # needs sage.libs.pari (, 5, 5, '-', 1) - sage: t = is_NOperp_F5(5,5,5,5); t + sage: t = is_NOperp_F5(5,5,5,5); t # needs sage.libs.pari """ cdef int n r, s = eigenvalues(v, k, l, mu) # 2*e*5**(n-1), -e*5**(n-1); note exceptional case n=1 @@ -692,22 +696,22 @@ def is_NO_F2(int v, int k, int l, int mu): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import is_NO_F2 - sage: t = is_NO_F2(10, 3, 0, 1); t + sage: t = is_NO_F2(10, 3, 0, 1); t # needs sage.libs.pari (, 4, 2, '-') - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.libs.pari NO^-(4, 2): Graph on 10 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.pari (10, 3, 0, 1) TESTS: All of ``NO^+(2m,2)`` and ``NO^-(2m,2)`` appear:: - sage: t = is_NO_F2(36, 15, 6, 6); t + sage: t = is_NO_F2(36, 15, 6, 6); t # needs sage.libs.pari (, 6, 2, '-') - sage: t = is_NO_F2(28, 15, 6, 10); t + sage: t = is_NO_F2(28, 15, 6, 10); t # needs sage.libs.pari (, 6, 2, '+') - sage: t = is_NO_F2(5,5,5,5); t + sage: t = is_NO_F2(5,5,5,5); t # needs sage.libs.pari """ cdef int n, e, p p, n = is_prime_power(k+1, get_data=True) # k+1==2**(2*n-2) @@ -743,22 +747,22 @@ def is_NO_F3(int v, int k, int l, int mu): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import is_NO_F3 - sage: t = is_NO_F3(15, 6, 1, 3); t + sage: t = is_NO_F3(15, 6, 1, 3); t # needs sage.libs.pari (, 4, 3, '-') - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.libs.pari NO^-(4, 3): Graph on 15 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.pari (15, 6, 1, 3) TESTS: All of ``NO^+(2m,3)`` and ``NO^-(2m,3)`` appear:: - sage: t = is_NO_F3(126, 45, 12, 18); t + sage: t = is_NO_F3(126, 45, 12, 18); t # needs sage.libs.pari (, 6, 3, '-') - sage: t = is_NO_F3(117, 36, 15, 9); t + sage: t = is_NO_F3(117, 36, 15, 9); t # needs sage.libs.pari (, 6, 3, '+') - sage: t = is_NO_F3(5,5,5,5); t + sage: t = is_NO_F3(5,5,5,5); t # needs sage.libs.pari """ cdef int n, e, p r, s = eigenvalues(v, k, l, mu) # e*3**(n-1), -e*3**(n-2) @@ -799,15 +803,16 @@ def is_NU(int v, int k, int l, int mu): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import is_NU - sage: t = is_NU(40, 27, 18, 18); t + sage: t = is_NU(40, 27, 18, 18); t # needs sage.libs.pari (, 4, 2) - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.libs.pari NU(4, 2): Graph on 40 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.pari (40, 27, 18, 18) TESTS:: + sage: # needs sage.libs.pari sage: t = is_NU(176, 135, 102, 108); t (, 5, 2) sage: t = is_NU(540, 224, 88, 96); t @@ -866,16 +871,16 @@ def is_haemers(int v, int k, int l, int mu): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import is_haemers - sage: t = is_haemers(96, 19, 2, 4); t + sage: t = is_haemers(96, 19, 2, 4); t # needs sage.libs.pari (, 4) - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.libs.pari Haemers(4): Graph on 96 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.pari (96, 19, 2, 4) TESTS:: - sage: t = is_haemers(5,5,5,5); t + sage: t = is_haemers(5,5,5,5); t # needs sage.libs.pari """ cdef int q, n, p p, n = is_prime_power(mu, get_data=True) @@ -908,20 +913,20 @@ def is_cossidente_penttila(int v, int k, int l, int mu): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import is_cossidente_penttila - sage: t = is_cossidente_penttila(378, 52, 1, 8); t + sage: t = is_cossidente_penttila(378, 52, 1, 8); t # needs sage.libs.pari (, 5) - sage: g = t[0](*t[1:]); g # optional - gap_packages + sage: g = t[0](*t[1:]); g # optional - gap_packages # needs sage.libs.pari CossidentePenttila(5): Graph on 378 vertices - sage: g.is_strongly_regular(parameters=True) # optional - gap_packages + sage: g.is_strongly_regular(parameters=True) # optional - gap_packages, needs sage.libs.pari (378, 52, 1, 8) TESTS:: - sage: t = is_cossidente_penttila(56,10,0,2); t + sage: t = is_cossidente_penttila(56,10,0,2); t # needs sage.libs.pari (, 3) - sage: t = is_cossidente_penttila(1376,150,2,18); t + sage: t = is_cossidente_penttila(1376,150,2,18); t # needs sage.libs.pari (, 7) - sage: t = is_cossidente_penttila(5,5,5,5); t + sage: t = is_cossidente_penttila(5,5,5,5); t # needs sage.libs.pari """ cdef int q, n, p q = 2*l + 3 @@ -1008,12 +1013,13 @@ def is_polhill(int v, int k, int l, int mu): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: from sage.graphs.strongly_regular_db import is_polhill sage: t = is_polhill(1024, 231, 38, 56); t [. at ...>] - sage: g = t[0](*t[1:]); g # not tested (too long) + sage: g = t[0](*t[1:]); g # not tested (too long) Graph on 1024 vertices - sage: g.is_strongly_regular(parameters=True) # not tested (too long) + sage: g.is_strongly_regular(parameters=True) # not tested (too long) (1024, 231, 38, 56) sage: t = is_polhill(1024, 264, 56, 72); t [. at ...>] @@ -1156,11 +1162,11 @@ def is_RSHCD(int v, int k, int l, int mu): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import is_RSHCD - sage: t = is_RSHCD(64,27,10,12); t + sage: t = is_RSHCD(64,27,10,12); t # needs sage.combinat sage.modules [, 64, 27, 10, 12] - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.combinat sage.modules Graph on 64 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.combinat sage.modules (64, 27, 10, 12) """ if SRG_from_RSHCD(v, k, l, mu, existence=True) is True: @@ -1191,26 +1197,27 @@ def SRG_from_RSHCD(v, k, l, mu, existence=False, check=True): some graphs :: sage: from sage.graphs.strongly_regular_db import SRG_from_RSHCD - sage: SRG_from_RSHCD(784, 0, 14, 38, existence=True) + sage: SRG_from_RSHCD(784, 0, 14, 38, existence=True) # needs sage.combinat sage.modules False - sage: SRG_from_RSHCD(784, 377, 180, 182, existence=True) + sage: SRG_from_RSHCD(784, 377, 180, 182, existence=True) # needs sage.combinat sage.modules True - sage: SRG_from_RSHCD(144, 65, 28, 30) + sage: SRG_from_RSHCD(144, 65, 28, 30) # needs sage.combinat sage.modules Graph on 144 vertices an example with vertex-transitive automorphism group, found during the implementation of the case `v=324` :: - sage: G=SRG_from_RSHCD(324,152,70,72) # long time - sage: a=G.automorphism_group() # long time - sage: a.order() # long time + sage: # long time, needs sage.combinat sage.modules + sage: G = SRG_from_RSHCD(324,152,70,72) + sage: a = G.automorphism_group() + sage: a.order() 2592 - sage: len(a.orbits()) # long time + sage: len(a.orbits()) 1 TESTS:: - sage: SRG_from_RSHCD(784, 0, 14, 38) + sage: SRG_from_RSHCD(784, 0, 14, 38) # needs sage.combinat sage.modules Traceback (most recent call last): ... ValueError: I do not know how to build a (784, 0, 14, 38)-SRG from a RSHCD @@ -1267,19 +1274,20 @@ def is_unitary_polar(int v, int k, int l, int mu): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import is_unitary_polar - sage: t = is_unitary_polar(45, 12, 3, 3); t + sage: t = is_unitary_polar(45, 12, 3, 3); t # needs sage.libs.pari (, 4, 2) - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.libs.pari 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) # needs sage.libs.pari (45, 12, 3, 3) - sage: t = is_unitary_polar(5,5,5,5); t + sage: t = is_unitary_polar(5,5,5,5); t # needs sage.libs.pari TESTS: All the ``U(n,q)`` appear:: + sage: # needs sage.libs.pari sage: t = is_unitary_polar(45, 12, 3, 3); t (, 4, 2) sage: t = is_unitary_polar(165, 36, 3, 9); t @@ -1342,6 +1350,7 @@ def is_unitary_dual_polar(int v, int k, int l, int mu): EXAMPLES:: + sage: # needs sage.libs.pari sage: from sage.graphs.strongly_regular_db import is_unitary_dual_polar sage: t = is_unitary_dual_polar(297, 40, 7, 5); t (, 5, 2) @@ -1353,7 +1362,7 @@ def is_unitary_dual_polar(int v, int k, int l, int mu): TESTS:: - sage: is_unitary_dual_polar(6832, 270, 26, 10) + sage: is_unitary_dual_polar(6832, 270, 26, 10) # needs sage.libs.pari (, 5, 3) """ r, s = eigenvalues(v, k, l, mu) @@ -1392,6 +1401,7 @@ def is_GQqmqp(int v, int k, int l, int mu): EXAMPLES:: + sage: # needs sage.libs.pari sage: from sage.graphs.strongly_regular_db import is_GQqmqp sage: t = is_GQqmqp(27,10,1,5); t (, 3, False) @@ -1418,19 +1428,19 @@ def is_GQqmqp(int v, int k, int l, int mu): TESTS:: - sage: (S,T)=(127,129) - sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t + sage: (S,T) = (127,129) + sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t # needs sage.libs.pari (, 128, False) - sage: (S,T)=(129,127) - sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t + sage: (S,T) = (129,127) + sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t # needs sage.libs.pari (, 128, True) - sage: (S,T)=(124,126) - sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t + sage: (S,T) = (124,126) + sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t # needs sage.libs.pari (, 125, False) - sage: (S,T)=(126,124) - sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t + sage: (S,T) = (126,124) + sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t # needs sage.libs.pari (, 125, True) - sage: t = is_GQqmqp(5,5,5,5); t + sage: t = is_GQqmqp(5,5,5,5); t # needs sage.libs.pari """ # do we have GQ(s,t)? we must have mu=t+1, s=l+1, # v=(s+1)(st+1), k=s(t+1) @@ -1484,17 +1494,17 @@ def is_twograph_descendant_of_srg(int v, int k0, int l, int mu): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import is_twograph_descendant_of_srg - sage: t = is_twograph_descendant_of_srg(27, 10, 1, 5); t + sage: t = is_twograph_descendant_of_srg(27, 10, 1, 5); t # needs sage.rings.finite_rings (.la at... - sage: g = t[0](*t[1:]); g + sage: g = t[0](*t[1:]); g # needs sage.rings.finite_rings descendant of complement(Johnson graph with parameters 8,2) at {0, 1}: Graph on 27 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings (27, 10, 1, 5) sage: t = is_twograph_descendant_of_srg(5,5,5,5); t TESTS:: - sage: graphs.strongly_regular_graph(279, 150, 85, 75, existence=True) + sage: graphs.strongly_regular_graph(279, 150, 85, 75, existence=True) # needs sage.combinat True sage: graphs.strongly_regular_graph(279, 150, 85, 75).is_strongly_regular(parameters=True) # optional - gap_packages internet (279, 150, 85, 75) @@ -1545,6 +1555,7 @@ def is_taylor_twograph_srg(int v, int k, int l, int mu): EXAMPLES:: + sage: # needs sage.libs.pari sage: from sage.graphs.strongly_regular_db import is_taylor_twograph_srg sage: t = is_taylor_twograph_srg(28, 15, 6, 10); t (, 3) @@ -1556,7 +1567,7 @@ def is_taylor_twograph_srg(int v, int k, int l, int mu): TESTS:: - sage: is_taylor_twograph_srg(730, 369, 168, 205) + sage: is_taylor_twograph_srg(730, 369, 168, 205) # needs sage.libs.pari (, 9) """ @@ -1595,13 +1606,13 @@ def is_switch_skewhad(int v, int k, int l, int mu): EXAMPLES:: - sage: graphs.strongly_regular_graph(226, 105, 48, 49) + sage: graphs.strongly_regular_graph(226, 105, 48, 49) # needs sage.combinat sage.modules switch skewhad^2+*_4: Graph on 226 vertices TESTS:: sage: from sage.graphs.strongly_regular_db import is_switch_skewhad - sage: t = is_switch_skewhad(5,5,5,5); t + sage: t = is_switch_skewhad(5,5,5,5); t # needs sage.combinat sage.modules """ from sage.combinat.matrices.hadamard_matrix import skew_hadamard_matrix @@ -1642,22 +1653,22 @@ def is_switch_OA_srg(int v, int k, int l, int mu): EXAMPLES:: - sage: graphs.strongly_regular_graph(170, 78, 35, 36) # indirect doctest + sage: graphs.strongly_regular_graph(170, 78, 35, 36) # indirect doctest # needs sage.combinat sage.modules Graph on 170 vertices TESTS:: sage: from sage.graphs.strongly_regular_db import is_switch_OA_srg sage: t = is_switch_OA_srg(5,5,5,5); t - sage: t = is_switch_OA_srg(170, 78, 35, 36) - sage: t[0](*t[1:]).is_strongly_regular(parameters=True) + sage: t = is_switch_OA_srg(170, 78, 35, 36) # needs sage.schemes + sage: t[0](*t[1:]).is_strongly_regular(parameters=True) # needs sage.schemes (170, 78, 35, 36) - sage: t = is_switch_OA_srg(290, 136, 63, 64) - sage: t[0](*t[1:]).is_strongly_regular(parameters=True) + sage: t = is_switch_OA_srg(290, 136, 63, 64) # needs sage.schemes + sage: t[0](*t[1:]).is_strongly_regular(parameters=True) # needs sage.schemes (290, 136, 63, 64) - sage: is_switch_OA_srg(626, 300, 143, 144) + sage: is_switch_OA_srg(626, 300, 143, 144) # needs sage.schemes (.switch_OA_srg at ..., 12, 25) - sage: is_switch_OA_srg(842, 406, 195, 196) + sage: is_switch_OA_srg(842, 406, 195, 196) # needs sage.schemes (.switch_OA_srg at ..., 14, 29) """ cdef int n_2_p_1 = v @@ -1700,15 +1711,15 @@ def is_nowhere0_twoweight(int v, int k, int l, int mu): EXAMPLES:: - sage: graphs.strongly_regular_graph(196, 60, 14, 20) + sage: graphs.strongly_regular_graph(196, 60, 14, 20) # needs sage.combinat sage.modules Nowhere0WordsTwoWeightCodeGraph(8): Graph on 196 vertices TESTS:: sage: from sage.graphs.strongly_regular_db import is_nowhere0_twoweight - sage: t = is_nowhere0_twoweight(1800, 728, 268, 312); t + sage: t = is_nowhere0_twoweight(1800, 728, 268, 312); t # needs sage.libs.pari (, 16) - sage: t = is_nowhere0_twoweight(5,5,5,5); t + sage: t = is_nowhere0_twoweight(5,5,5,5); t # needs sage.libs.pari """ from sage.graphs.generators.classical_geometries import Nowhere0WordsTwoWeightCodeGraph @@ -1787,22 +1798,22 @@ def eigenmatrix(int v, int k, int l, int mu): Petersen's graph's C-algebra does not have a dual coming from an s.r.g.:: sage: from sage.graphs.strongly_regular_db import eigenmatrix - sage: P=eigenmatrix(10,3,0,1); P + sage: P = eigenmatrix(10,3,0,1); P # needs sage.modules [ 1 3 6] [ 1 1 -2] [ 1 -2 1] - sage: 10*P^-1 + sage: 10*P^-1 # needs sage.modules [ 1 5 4] [ 1 5/3 -8/3] [ 1 -5/3 2/3] The line graph of `K_{3,3}` is self-dual:: - sage: P=eigenmatrix(9,4,1,2); P + sage: P = eigenmatrix(9,4,1,2); P # needs sage.modules [ 1 4 4] [ 1 1 -2] [ 1 -2 1] - sage: 9*P^-1 + sage: 9*P^-1 # needs sage.modules [ 1 4 4] [ 1 1 -2] [ 1 -2 1] @@ -1810,11 +1821,12 @@ def eigenmatrix(int v, int k, int l, int mu): A strongly regular graph with a non-isomorphic dual coming from another strongly regular graph:: - sage: graphs.strongly_regular_graph(243,220,199,200, existence=True) + sage: # needs sage.modules + sage: graphs.strongly_regular_graph(243,220,199,200, existence=True) # needs sage.combinat True - sage: graphs.strongly_regular_graph(243,110,37,60, existence=True) + sage: graphs.strongly_regular_graph(243,110,37,60, existence=True) # needs sage.combinat True - sage: P=eigenmatrix(243,220,199,200); P + sage: P = eigenmatrix(243,220,199,200); P [ 1 220 22] [ 1 4 -5] [ 1 -5 4] @@ -1882,7 +1894,7 @@ def _H_3_cayley_graph(L): TESTS:: sage: from sage.graphs.strongly_regular_db import _H_3_cayley_graph - sage: _H_3_cayley_graph(["100","110","130","140","200","230","240","300"]) + sage: _H_3_cayley_graph(["100","110","130","140","200","230","240","300"]) # needs sage.groups Graph on 100 vertices """ from sage.groups.free_group import FreeGroup @@ -1955,9 +1967,9 @@ def SRG_105_32_4_12(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import SRG_105_32_4_12 - sage: G = SRG_105_32_4_12(); G + sage: G = SRG_105_32_4_12(); G # needs sage.rings.finite_rings Aut L(3,4) on flags: Graph on 105 vertices - sage: G.is_strongly_regular(parameters=True) + sage: G.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings (105, 32, 4, 12) """ from sage.combinat.designs.block_design import ProjectiveGeometryDesign @@ -2009,8 +2021,8 @@ def SRG_144_39_6_12(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import SRG_144_39_6_12 - sage: G = SRG_144_39_6_12() - sage: G.is_strongly_regular(parameters=True) + sage: G = SRG_144_39_6_12() # needs sage.libs.gap + sage: G.is_strongly_regular(parameters=True) # needs sage.libs.gap (144, 39, 6, 12) """ from sage.libs.gap.libgap import libgap @@ -2107,8 +2119,8 @@ def SRG_210_99_48_45(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import SRG_210_99_48_45 - sage: g=SRG_210_99_48_45() - sage: g.is_strongly_regular(parameters=True) + sage: g = SRG_210_99_48_45() # needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # needs sage.libs.gap (210, 99, 48, 45) """ from sage.libs.gap.libgap import libgap @@ -2154,8 +2166,8 @@ def SRG_243_110_37_60(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import SRG_243_110_37_60 - sage: G = SRG_243_110_37_60() - sage: G.is_strongly_regular(parameters=True) + sage: G = SRG_243_110_37_60() # needs sage.modules sage.rings.finite_rings + sage: G.is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings (243, 110, 37, 60) """ from sage.coding.golay_code import GolayCode @@ -2365,13 +2377,13 @@ def strongly_regular_from_two_weight_code(L): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import strongly_regular_from_two_weight_code - sage: x=("100022021001111", - ....: "010011211122000", - ....: "001021112100011", - ....: "000110120222220") - sage: M = Matrix(GF(3),[list(l) for l in x]) - sage: G = strongly_regular_from_two_weight_code(LinearCode(M)) - sage: G.is_strongly_regular(parameters=True) + sage: x = ("100022021001111", + ....: "010011211122000", + ....: "001021112100011", + ....: "000110120222220") + sage: M = Matrix(GF(3),[list(l) for l in x]) # needs sage.modules sage.rings.finite_rings + sage: G = strongly_regular_from_two_weight_code(LinearCode(M)) # needs sage.modules sage.rings.finite_rings + sage: G.is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings (81, 50, 31, 30) """ from sage.structure.element import is_Matrix @@ -2472,10 +2484,10 @@ def strongly_regular_from_two_intersection_set(M): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import strongly_regular_from_two_intersection_set - sage: S = Matrix([(0,0,1),(0,1,0)] + [(1,x^2,x) for x in GF(4,'b')]) - sage: g = strongly_regular_from_two_intersection_set(S); g + sage: S = Matrix([(0,0,1),(0,1,0)] + [(1,x^2,x) for x in GF(4,'b')]) # needs sage.modules sage.rings.finite_rings + sage: g = strongly_regular_from_two_intersection_set(S); g # needs sage.modules sage.rings.finite_rings two-intersection set in PG(3,4): Graph on 64 vertices - sage: g.is_strongly_regular(parameters=True) + sage: g.is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings (64, 18, 2, 6) """ from itertools import product @@ -2662,8 +2674,8 @@ def SRG_1288_792_476_504(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import SRG_1288_792_476_504 - sage: G = SRG_1288_792_476_504() # long time - sage: G.is_strongly_regular(parameters=True) # long time + sage: G = SRG_1288_792_476_504() # long time # needs sage.rings.finite_rings + sage: G.is_strongly_regular(parameters=True) # long time # needs sage.rings.finite_rings (1288, 792, 476, 504) """ from sage.coding.golay_code import GolayCode @@ -2691,7 +2703,7 @@ cdef bint seems_feasible(int v, int k, int l, int mu): :trac:`32306` is fixed:: sage: from sage.graphs.strongly_regular_db import strongly_regular_graph - sage: strongly_regular_graph(16384, 8256, 4160, 4160, existence=True) + sage: strongly_regular_graph(16384, 8256, 4160, 4160, existence=True) # needs sage.combinat sage.modules True """ cdef uint_fast32_t tmp[2] @@ -2821,9 +2833,9 @@ def strongly_regular_graph(int v, int k, int l, int mu=-1, bint existence=False, An set of parameters proved in a paper to be infeasible:: - sage: graphs.strongly_regular_graph(324,57,0,12,existence=True) + sage: graphs.strongly_regular_graph(324,57,0,12,existence=True) # needs sage.combinat sage.modules False - sage: graphs.strongly_regular_graph(324,57,0,12) + sage: graphs.strongly_regular_graph(324,57,0,12) # needs sage.combinat sage.modules Traceback (most recent call last): ... EmptySetError: Andries Brouwer's database reports that no (324, 57, 0, @@ -2832,9 +2844,9 @@ def strongly_regular_graph(int v, int k, int l, int mu=-1, bint existence=False, A set of parameters unknown to be realizable in Andries Brouwer's database:: - sage: graphs.strongly_regular_graph(324,95,22,30,existence=True) + sage: graphs.strongly_regular_graph(324,95,22,30,existence=True) # needs sage.combinat Unknown - sage: graphs.strongly_regular_graph(324,95,22,30) + sage: graphs.strongly_regular_graph(324,95,22,30) # needs sage.combinat Traceback (most recent call last): ... RuntimeError: Andries Brouwer's database reports that no @@ -2843,9 +2855,9 @@ def strongly_regular_graph(int v, int k, int l, int mu=-1, bint existence=False, A large unknown set of parameters (not in Andries Brouwer's database):: - sage: graphs.strongly_regular_graph(1394,175,0,25,existence=True) + sage: graphs.strongly_regular_graph(1394,175,0,25,existence=True) # needs sage.combinat Unknown - sage: graphs.strongly_regular_graph(1394,175,0,25) + sage: graphs.strongly_regular_graph(1394,175,0,25) # needs sage.combinat Traceback (most recent call last): ... RuntimeError: Sage cannot figure out if a (1394, 175, 0, 25)-strongly @@ -2860,11 +2872,11 @@ def strongly_regular_graph(int v, int k, int l, int mu=-1, bint existence=False, Check that :trac:`26513` is fixed:: - sage: graphs.strongly_regular_graph(539, 288, 162, 144) + sage: graphs.strongly_regular_graph(539, 288, 162, 144) # needs sage.combinat descendant of (540, 264, 138, 120)-strongly regular graph at ... 539 vertices - sage: graphs.strongly_regular_graph(539, 250, 105, 125) + sage: graphs.strongly_regular_graph(539, 250, 105, 125) # needs sage.combinat descendant of (540, 275, 130, 150)-strongly regular graph at ... 539 vertices - sage: graphs.strongly_regular_graph(209, 100, 45, 50) + sage: graphs.strongly_regular_graph(209, 100, 45, 50) # needs sage.libs.pari descendant of complement(merging of S_7 on Circulant(6,[1,4])s) at ... 209 vertices @@ -2930,11 +2942,11 @@ def strongly_regular_graph_lazy(int v, int k, int l, int mu=-1, bint existence=F (3, 4)) sage: g(p) complement(Multipartite Graph with set sizes [4, 4, 4]): Graph on 12 vertices - sage: g=strongly_regular_graph_lazy(539,250,105); g + sage: g = strongly_regular_graph_lazy(539,250,105); g # needs sage.combinat sage.modules (.la at...>, 5, 11) - sage: g[0](*g[1:]) + sage: g[0](*g[1:]) # needs sage.combinat sage.modules descendant of (540, 275, 130, 150)-strongly regular graph at 0: Graph on 539 vertices """ load_brouwer_database() @@ -3065,14 +3077,16 @@ def apparently_feasible_parameters(int n): (16, 9, 4, 6), (16, 10, 6, 6), (17, 8, 3, 4)} - sage: all(graphs.strongly_regular_graph(*x,existence=True) is True for x in small_feasible) + sage: all(graphs.strongly_regular_graph(*x,existence=True) is True # needs sage.libs.pari + ....: for x in small_feasible) True But that becomes wrong for `v<60` (because of the non-existence of a `(49,16,3,6)`-strongly regular graph):: sage: small_feasible = apparently_feasible_parameters(60) - sage: all(graphs.strongly_regular_graph(*x,existence=True) is True for x in small_feasible) + sage: all(graphs.strongly_regular_graph(*x,existence=True) is True # needs sage.libs.pari + ....: for x in small_feasible) False """ cdef int v, k, l, mu @@ -3100,28 +3114,28 @@ def _build_small_srg_database(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import _build_small_srg_database - sage: _build_small_srg_database() + sage: _build_small_srg_database() # needs sage.modules sage.rings.finite_rings TESTS: Make sure that all two-weight codes yield the strongly regular graphs we expect:: - sage: graphs.strongly_regular_graph(81, 50, 31, 30) + sage: graphs.strongly_regular_graph(81, 50, 31, 30) # needs sage.libs.pari complement(two-intersection set in PG(4,3)): Graph on 81 vertices - sage: graphs.strongly_regular_graph(243, 220, 199, 200) # long time + sage: graphs.strongly_regular_graph(243, 220, 199, 200) # long time, needs sage.rings.finite_rings two-weight code: [55, 5] linear code over GF(3): Graph on 243 vertices - sage: graphs.strongly_regular_graph(256, 153, 92, 90) + sage: graphs.strongly_regular_graph(256, 153, 92, 90) # needs sage.combinat complement(two-intersection set in PG(4,4)): Graph on 256 vertices - sage: graphs.strongly_regular_graph(256, 170, 114, 110) + sage: graphs.strongly_regular_graph(256, 170, 114, 110) # needs sage.combinat complement(two-intersection set in PG(8,2)): Graph on 256 vertices - sage: graphs.strongly_regular_graph(256, 187, 138, 132) + sage: graphs.strongly_regular_graph(256, 187, 138, 132) # needs sage.combinat complement(two-intersection set in PG(8,2)): Graph on 256 vertices - sage: graphs.strongly_regular_graph(512, 73, 12, 10) # not tested (too long) + sage: graphs.strongly_regular_graph(512, 73, 12, 10) # not tested (too long), needs sage.rings.finite_rings two-weight code: [219, 9] linear code over GF(2): Graph on 512 vertices sage: graphs.strongly_regular_graph(512, 219, 106, 84) # long time two-intersection set in PG(9,2): Graph on 512 vertices - sage: graphs.strongly_regular_graph(512, 315, 202, 180) # not tested (too long) + sage: graphs.strongly_regular_graph(512, 315, 202, 180) # not tested (too long), needs sage.rings.finite_rings two-weight code: [70, 9] linear code over GF(2): Graph on 512 vertices sage: graphs.strongly_regular_graph(625, 364, 213, 210) # long time complement(two-intersection set in PG(4,5)): Graph on 625 vertices diff --git a/src/sage/graphs/traversals.pyx b/src/sage/graphs/traversals.pyx index a565d46fdcb..6180cb8db08 100644 --- a/src/sage/graphs/traversals.pyx +++ b/src/sage/graphs/traversals.pyx @@ -338,16 +338,17 @@ def lex_BFS(G, reverse=False, tree=False, initial_vertex=None, algorithm="fast") Different orderings for different traversals:: - sage: G = digraphs.DeBruijn(2,3) # optional - sage.combinat - sage: G.lex_BFS(initial_vertex='000', algorithm="fast") # optional - sage.combinat + sage: # needs sage.combinat + sage: G = digraphs.DeBruijn(2,3) + sage: G.lex_BFS(initial_vertex='000', algorithm="fast") ['000', '001', '100', '010', '011', '110', '101', '111'] - sage: G.lex_BFS(initial_vertex='000', algorithm="slow") # optional - sage.combinat + sage: G.lex_BFS(initial_vertex='000', algorithm="slow") ['000', '001', '100', '010', '011', '110', '101', '111'] - sage: G.lex_DFS(initial_vertex='000') # optional - sage.combinat + sage: G.lex_DFS(initial_vertex='000') ['000', '001', '100', '010', '101', '110', '011', '111'] - sage: G.lex_UP(initial_vertex='000') # optional - sage.combinat + sage: G.lex_UP(initial_vertex='000') ['000', '001', '010', '101', '110', '111', '011', '100'] - sage: G.lex_DOWN(initial_vertex='000') # optional - sage.combinat + sage: G.lex_DOWN(initial_vertex='000') ['000', '001', '100', '011', '010', '110', '111', '101'] TESTS: @@ -541,14 +542,15 @@ def lex_UP(G, reverse=False, tree=False, initial_vertex=None): Different orderings for different traversals:: - sage: G = digraphs.DeBruijn(2,3) # optional - sage.combinat - sage: G.lex_BFS(initial_vertex='000') # optional - sage.combinat + sage: # needs sage.combinat + sage: G = digraphs.DeBruijn(2,3) + sage: G.lex_BFS(initial_vertex='000') ['000', '001', '100', '010', '011', '110', '101', '111'] - sage: G.lex_DFS(initial_vertex='000') # optional - sage.combinat + sage: G.lex_DFS(initial_vertex='000') ['000', '001', '100', '010', '101', '110', '011', '111'] - sage: G.lex_UP(initial_vertex='000') # optional - sage.combinat + sage: G.lex_UP(initial_vertex='000') ['000', '001', '010', '101', '110', '111', '011', '100'] - sage: G.lex_DOWN(initial_vertex='000') # optional - sage.combinat + sage: G.lex_DOWN(initial_vertex='000') ['000', '001', '100', '011', '010', '110', '111', '101'] TESTS: @@ -714,14 +716,15 @@ def lex_DFS(G, reverse=False, tree=False, initial_vertex=None): Different orderings for different traversals:: - sage: G = digraphs.DeBruijn(2,3) # optional - sage.combinat - sage: G.lex_BFS(initial_vertex='000') # optional - sage.combinat + sage: # needs sage.combinat + sage: G = digraphs.DeBruijn(2,3) + sage: G.lex_BFS(initial_vertex='000') ['000', '001', '100', '010', '011', '110', '101', '111'] - sage: G.lex_DFS(initial_vertex='000') # optional - sage.combinat + sage: G.lex_DFS(initial_vertex='000') ['000', '001', '100', '010', '101', '110', '011', '111'] - sage: G.lex_UP(initial_vertex='000') # optional - sage.combinat + sage: G.lex_UP(initial_vertex='000') ['000', '001', '010', '101', '110', '111', '011', '100'] - sage: G.lex_DOWN(initial_vertex='000') # optional - sage.combinat + sage: G.lex_DOWN(initial_vertex='000') ['000', '001', '100', '011', '010', '110', '111', '101'] TESTS: @@ -889,14 +892,15 @@ def lex_DOWN(G, reverse=False, tree=False, initial_vertex=None): Different orderings for different traversals:: - sage: G = digraphs.DeBruijn(2,3) # optional - sage.combinat - sage: G.lex_BFS(initial_vertex='000') # optional - sage.combinat + sage: # needs sage.combinat + sage: G = digraphs.DeBruijn(2,3) + sage: G.lex_BFS(initial_vertex='000') ['000', '001', '100', '010', '011', '110', '101', '111'] - sage: G.lex_DFS(initial_vertex='000') # optional - sage.combinat + sage: G.lex_DFS(initial_vertex='000') ['000', '001', '100', '010', '101', '110', '011', '111'] - sage: G.lex_UP(initial_vertex='000') # optional - sage.combinat + sage: G.lex_UP(initial_vertex='000') ['000', '001', '010', '101', '110', '111', '011', '100'] - sage: G.lex_DOWN(initial_vertex='000') # optional - sage.combinat + sage: G.lex_DOWN(initial_vertex='000') ['000', '001', '100', '011', '010', '110', '111', '101'] TESTS: diff --git a/src/sage/graphs/tutte_polynomial.py b/src/sage/graphs/tutte_polynomial.py index 6794c960805..5a7b048ddfe 100644 --- a/src/sage/graphs/tutte_polynomial.py +++ b/src/sage/graphs/tutte_polynomial.py @@ -532,7 +532,7 @@ def tutte_polynomial(G, edge_selector=None, cache=None): The Tutte polynomial of any tree of order `n` is `x^{n-1}`:: - sage: all(T.tutte_polynomial() == x**9 for T in graphs.trees(10)) # optional - sage.symbolic + sage: all(T.tutte_polynomial() == x**9 for T in graphs.trees(10)) # needs sage.symbolic True The Tutte polynomial of the Petersen graph is:: @@ -550,7 +550,7 @@ def tutte_polynomial(G, edge_selector=None, cache=None): sage: G = graphs.RandomGNP(10,0.6) sage: while not G.is_connected(): ....: G = graphs.RandomGNP(10,0.6) - sage: G.tutte_polynomial()(1,1) == G.spanning_trees_count() + sage: G.tutte_polynomial()(1,1) == G.spanning_trees_count() # needs sage.modules True Given that `T(x,y)` is the Tutte polynomial of a graph `G` with @@ -560,7 +560,7 @@ def tutte_polynomial(G, edge_selector=None, cache=None): sage: G = graphs.OctahedralGraph() sage: T = G.tutte_polynomial() sage: R = PolynomialRing(ZZ, 'x') - sage: R((-1)^5*x*T(1-x,0)).factor() # optional - sage.symbolic + sage: R((-1)^5*x*T(1-x,0)).factor() # needs sage.symbolic (x - 2) * (x - 1) * x * (x^3 - 9*x^2 + 29*x - 32) sage: G.chromatic_polynomial().factor() (x - 2) * (x - 1) * x * (x^3 - 9*x^2 + 29*x - 32) diff --git a/src/sage/graphs/views.pyx b/src/sage/graphs/views.pyx index c49511207e5..958de960d86 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) # optional - sage.combinat - sage: E = EdgesView(G, labels=False, sort=True); E # optional - sage.combinat + sage: G = digraphs.DeBruijn(2, 2) # needs sage.combinat + sage: E = EdgesView(G, labels=False, sort=True); E # needs 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 # optional - sage.combinat + sage: E = EdgesView(G, labels=False, sort=True, key=lambda e:(e[1], e[0])); E # needs sage.combinat [('00', '00'), ('10', '00'), ('00', '01'), ('10', '01'), ('01', '10'), ('11', '10'), ('01', '11'), ('11', '11')] From bc9bb1befa259c500a9fa9eb4bdfad8127586455 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 2 Aug 2023 16:19:53 -0700 Subject: [PATCH 06/10] src/sage/graphs/graph.py: Use more block # needs --- src/sage/graphs/graph.py | 249 +++++++++++++++++++++------------------ 1 file changed, 137 insertions(+), 112 deletions(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index c6a32319305..0f207ffb1ee 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -112,10 +112,11 @@ :: - sage: import networkx # needs networkx - sage: K = networkx.complete_bipartite_graph(12,7) # needs networkx - sage: G = Graph(K) # needs networkx - sage: G.degree() # needs networkx + sage: # needs networkx + sage: import networkx + sage: K = networkx.complete_bipartite_graph(12,7) + sage: G = Graph(K) + sage: G.degree() [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12] - graph6 or sparse6 format: @@ -149,11 +150,12 @@ :: - sage: M = Matrix([(0,1,0,0,1,1,0,0,0,0), (1,0,1,0,0,0,1,0,0,0), # needs sage.modules + sage: # needs sage.modules + sage: M = Matrix([(0,1,0,0,1,1,0,0,0,0), (1,0,1,0,0,0,1,0,0,0), ....: (0,1,0,1,0,0,0,1,0,0), (0,0,1,0,1,0,0,0,1,0), ....: (1,0,0,1,0,0,0,0,0,1), (1,0,0,0,0,0,0,1,1,0), (0,1,0,0,0,0,0,0,1,1), ....: (0,0,1,0,0,1,0,0,0,1), (0,0,0,1,0,1,1,0,0,0), (0,0,0,0,1,0,1,1,0,0)]) - sage: M # needs sage.modules + sage: M [0 1 0 0 1 1 0 0 0 0] [1 0 1 0 0 0 1 0 0 0] [0 1 0 1 0 0 0 1 0 0] @@ -164,16 +166,17 @@ [0 0 1 0 0 1 0 0 0 1] [0 0 0 1 0 1 1 0 0 0] [0 0 0 0 1 0 1 1 0 0] - sage: G = Graph(M); G # needs sage.modules + sage: G = Graph(M); G Graph on 10 vertices - sage: G.plot().show() # or G.show() # needs sage.modules sage.plot + sage: G.plot().show() # or G.show() # needs sage.plot - incidence matrix: In an incidence matrix, each row represents a vertex and each column represents an edge. :: - sage: M = Matrix([(-1, 0, 0, 0, 1, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0), # needs sage.modules + sage: # needs sage.modules + sage: M = Matrix([(-1, 0, 0, 0, 1, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0), ....: ( 1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0), ....: ( 0, 1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0), ....: ( 0, 0, 1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0), @@ -183,7 +186,7 @@ ....: ( 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 0, 1, 0, 0), ....: ( 0, 0, 0, 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 1, 0), ....: ( 0, 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 0, 0, 1)]) - sage: M # needs sage.modules + sage: M [-1 0 0 0 1 0 0 0 0 0 -1 0 0 0 0] [ 1 -1 0 0 0 0 0 0 0 0 0 -1 0 0 0] [ 0 1 -1 0 0 0 0 0 0 0 0 0 -1 0 0] @@ -194,10 +197,10 @@ [ 0 0 0 0 0 1 -1 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 0 0 0 1 -1 0 0 0 1 0] [ 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 1] - sage: G = Graph(M); G # needs sage.modules + sage: G = Graph(M); G Graph on 10 vertices - sage: G.plot().show() # or G.show() # needs sage.modules sage.plot - sage: DiGraph(matrix(2, [0,0,-1,1]), format="incidence_matrix") # needs sage.modules + sage: G.plot().show() # or G.show() # needs sage.plot + sage: DiGraph(matrix(2, [0,0,-1,1]), format="incidence_matrix") Traceback (most recent call last): ... ValueError: there must be two nonzero entries (-1 & 1) per column @@ -764,13 +767,14 @@ class Graph(GenericGraph): Check that :trac:`9714` is fixed:: - sage: MA = Matrix([[1,2,0], [0,2,0], [0,0,1]]) # needs sage.modules - sage: GA = Graph(MA, format='adjacency_matrix') # needs sage.modules - sage: MI = GA.incidence_matrix(oriented=False); MI # needs sage.modules + sage: # needs sage.modules + sage: MA = Matrix([[1,2,0], [0,2,0], [0,0,1]]) + sage: GA = Graph(MA, format='adjacency_matrix') + sage: MI = GA.incidence_matrix(oriented=False); MI [2 1 1 0 0 0] [0 1 1 2 2 0] [0 0 0 0 0 2] - sage: Graph(MI).edges(sort=True, labels=None) # needs sage.modules + sage: Graph(MI).edges(sort=True, labels=None) [(0, 0), (0, 1), (0, 1), (1, 1), (1, 1), (2, 2)] sage: M = Matrix([[1], [-1]]); M # needs sage.modules @@ -826,11 +830,12 @@ class Graph(GenericGraph): If ``vertex_labels`` is ``True``, the names of the vertices are given by the vertex attribute ``'name'``, if available:: - sage: g = igraph.Graph([(0,1),(0,2)], vertex_attrs={'name':['a','b','c']}) # optional - python_igraph - sage: Graph(g).vertices(sort=True) # optional - python_igraph + sage: # optional - python_igraph + sage: g = igraph.Graph([(0,1),(0,2)], vertex_attrs={'name':['a','b','c']}) + sage: Graph(g).vertices(sort=True) ['a', 'b', 'c'] - sage: g = igraph.Graph([(0,1),(0,2)], vertex_attrs={'label':['a','b','c']}) # optional - python_igraph - sage: Graph(g).vertices(sort=True) # optional - python_igraph + sage: g = igraph.Graph([(0,1),(0,2)], vertex_attrs={'label':['a','b','c']}) + sage: Graph(g).vertices(sort=True) [0, 1, 2] If the igraph Graph has edge attributes, they are used as edge labels:: @@ -885,11 +890,12 @@ class Graph(GenericGraph): ... ValueError: An *undirected* igraph graph was expected. To build an directed graph, call the DiGraph constructor. - sage: m = matrix([[0, -1], [-1, 0]]) # needs sage.modules - sage: Graph(m, format="seidel_adjacency_matrix") # needs sage.modules + sage: # needs sage.modules + sage: m = matrix([[0, -1], [-1, 0]]) + sage: Graph(m, format="seidel_adjacency_matrix") Graph on 2 vertices - sage: m[0,1] = 1 # needs sage.modules - sage: Graph(m, format="seidel_adjacency_matrix") # needs sage.modules + sage: m[0,1] = 1 + sage: Graph(m, format="seidel_adjacency_matrix") Traceback (most recent call last): ... ValueError: the adjacency matrix of a Seidel graph must be symmetric @@ -3937,18 +3943,19 @@ def chromatic_symmetric_function(self, R=None): We show that given a triangle `\{e_1, e_2, e_3\}`, we have `X_G = X_{G - e_1} + X_{G - e_2} - X_{G - e_1 - e_2}`:: + sage: # needs sage.combinat sage.modules sage: G = Graph([[1,2],[1,3],[2,3]]) - sage: XG = G.chromatic_symmetric_function() # needs sage.combinat sage.modules + sage: XG = G.chromatic_symmetric_function() sage: G1 = copy(G) sage: G1.delete_edge([1,2]) - sage: XG1 = G1.chromatic_symmetric_function() # needs sage.combinat sage.modules + sage: XG1 = G1.chromatic_symmetric_function() sage: G2 = copy(G) sage: G2.delete_edge([1,3]) - sage: XG2 = G2.chromatic_symmetric_function() # needs sage.combinat sage.modules + sage: XG2 = G2.chromatic_symmetric_function() sage: G3 = copy(G1) sage: G3.delete_edge([1,3]) - sage: XG3 = G3.chromatic_symmetric_function() # needs sage.combinat sage.modules - sage: XG == XG1 + XG2 - XG3 # needs sage.combinat sage.modules + sage: XG3 = G3.chromatic_symmetric_function() + sage: XG == XG1 + XG2 - XG3 True """ from sage.combinat.sf.sf import SymmetricFunctions @@ -3994,19 +4001,20 @@ def chromatic_quasisymmetric_function(self, t=None, R=None): EXAMPLES:: + sage: # needs sage.combinat sage.modules sage: G = Graph([[1,2,3], [[1,3], [2,3]]]) - sage: G.chromatic_quasisymmetric_function() # needs sage.combinat sage.modules + sage: G.chromatic_quasisymmetric_function() (2*t^2+2*t+2)*M[1, 1, 1] + M[1, 2] + t^2*M[2, 1] sage: G = graphs.PathGraph(4) - sage: XG = G.chromatic_quasisymmetric_function(); XG # needs sage.combinat sage.modules + sage: XG = G.chromatic_quasisymmetric_function(); XG (t^3+11*t^2+11*t+1)*M[1, 1, 1, 1] + (3*t^2+3*t)*M[1, 1, 2] + (3*t^2+3*t)*M[1, 2, 1] + (3*t^2+3*t)*M[2, 1, 1] + (t^2+t)*M[2, 2] - sage: XG.to_symmetric_function() # needs sage.combinat sage.modules + sage: XG.to_symmetric_function() (t^3+11*t^2+11*t+1)*m[1, 1, 1, 1] + (3*t^2+3*t)*m[2, 1, 1] + (t^2+t)*m[2, 2] sage: G = graphs.CompleteGraph(4) - sage: G.chromatic_quasisymmetric_function() # needs sage.combinat sage.modules + sage: G.chromatic_quasisymmetric_function() (t^6+3*t^5+5*t^4+6*t^3+5*t^2+3*t+1)*M[1, 1, 1, 1] Not all chromatic quasisymmetric functions are symmetric:: @@ -4698,17 +4706,18 @@ def maximum_average_degree(self, value_only=True, solver=None, verbose=0): Check corner cases:: - sage: Graph().maximum_average_degree(value_only=True) # needs sage.numerical.mip + sage: # needs sage.numerical.mip + sage: Graph().maximum_average_degree(value_only=True) 0 - sage: Graph().maximum_average_degree(value_only=False) # needs sage.numerical.mip + sage: Graph().maximum_average_degree(value_only=False) Graph on 0 vertices - sage: Graph(1).maximum_average_degree(value_only=True) # needs sage.numerical.mip + sage: Graph(1).maximum_average_degree(value_only=True) 0 - sage: Graph(1).maximum_average_degree(value_only=False) # needs sage.numerical.mip + sage: Graph(1).maximum_average_degree(value_only=False) Graph on 1 vertex - sage: Graph(2).maximum_average_degree(value_only=True) # needs sage.numerical.mip + sage: Graph(2).maximum_average_degree(value_only=True) 0 - sage: Graph(2).maximum_average_degree(value_only=False) # needs sage.numerical.mip + sage: Graph(2).maximum_average_degree(value_only=False) Graph on 1 vertex """ self._scream_if_not_simple() @@ -4810,15 +4819,16 @@ def independent_set_of_representatives(self, family, solver=None, verbose=0, partition of the set of vertices the family defined by the three copies of each vertex. The ISR of such a family defines a 3-coloring:: + sage: # needs sage.numerical.mip sage: g = 3 * graphs.PetersenGraph() sage: n = g.order() / 3 sage: f = [[i, i + n, i + 2*n] for i in range(n)] - sage: isr = g.independent_set_of_representatives(f) # needs sage.numerical.mip - sage: c = [integer_floor(i / n) for i in isr] # needs sage.numerical.mip + sage: isr = g.independent_set_of_representatives(f) + sage: c = [integer_floor(i / n) for i in isr] sage: color_classes = [[], [], []] - sage: for v, i in enumerate(c): # needs sage.numerical.mip + sage: for v, i in enumerate(c): ....: color_classes[i].append(v) - sage: for classs in color_classes: # needs sage.numerical.mip + sage: for classs in color_classes: ....: g.subgraph(classs).size() == 0 True True @@ -4930,12 +4940,13 @@ def minor(self, H, solver=None, verbose=0, *, integrality_tolerance=1e-3): Trying to find a minor isomorphic to `K_4` in the `4\times 4` grid:: + sage: # needs sage.numerical.mip sage: g = graphs.GridGraph([4,4]) sage: h = graphs.CompleteGraph(4) - sage: L = g.minor(h) # needs sage.numerical.mip - sage: gg = g.subgraph(flatten(L.values(), max_level = 1)) # needs sage.numerical.mip - sage: _ = [gg.merge_vertices(l) for l in L.values() if len(l)>1] # needs sage.numerical.mip - sage: gg.is_isomorphic(h) # needs sage.numerical.mip + sage: L = g.minor(h) + sage: gg = g.subgraph(flatten(L.values(), max_level = 1)) + sage: _ = [gg.merge_vertices(l) for l in L.values() if len(l)>1] + sage: gg.is_isomorphic(h) True We can also try to prove this way that the Petersen graph is not planar, @@ -5819,11 +5830,12 @@ def distance_graph(self, dist): The graph of eight-bit strings, adjacent if different in an odd number of bits:: - sage: G = graphs.CubeGraph(8) # long time - sage: H = G.distance_graph([1,3,5,7]) # long time - sage: degrees = [0]*sum([binomial(8,j) for j in [1,3,5,7]]) # long time - sage: degrees.append(2^8) # long time - sage: degrees == H.degree_histogram() # long time + sage: # long time + sage: G = graphs.CubeGraph(8) + sage: H = G.distance_graph([1,3,5,7]) + sage: degrees = [0]*sum([binomial(8,j) for j in [1,3,5,7]]) + sage: degrees.append(2^8) + sage: degrees == H.degree_histogram() True An example of using ``Infinity`` as the distance in a graph that is not @@ -7526,20 +7538,21 @@ def cliques_containing_vertex(self, vertices=None, cliques=None): EXAMPLES:: + sage: # needs networkx sage: C = Graph('DJ{') - sage: C.cliques_containing_vertex() # needs networkx + sage: C.cliques_containing_vertex() {0: [[0, 4]], 1: [[1, 2, 3, 4]], 2: [[1, 2, 3, 4]], 3: [[1, 2, 3, 4]], 4: [[0, 4], [1, 2, 3, 4]]} - sage: C.cliques_containing_vertex(4) # needs networkx + sage: C.cliques_containing_vertex(4) [[0, 4], [1, 2, 3, 4]] - sage: C.cliques_containing_vertex([0, 1]) # needs networkx + sage: C.cliques_containing_vertex([0, 1]) {0: [[0, 4]], 1: [[1, 2, 3, 4]]} - sage: E = C.cliques_maximal(); E # needs networkx + sage: E = C.cliques_maximal(); E [[0, 4], [1, 2, 3, 4]] - sage: C.cliques_containing_vertex(cliques=E) # needs networkx + sage: C.cliques_containing_vertex(cliques=E) {0: [[0, 4]], 1: [[1, 2, 3, 4]], 2: [[1, 2, 3, 4]], @@ -7557,14 +7570,15 @@ def cliques_containing_vertex(self, vertices=None, cliques=None): Since each clique of a 2 dimensional grid corresponds to an edge, the number of cliques in which a vertex is involved equals its degree:: + sage: # needs networkx sage: F = graphs.Grid2dGraph(2,3) - sage: d = F.cliques_containing_vertex() # needs networkx - sage: all(F.degree(u) == len(cliques) for u,cliques in d.items()) # needs networkx + sage: d = F.cliques_containing_vertex() + sage: all(F.degree(u) == len(cliques) for u,cliques in d.items()) True - sage: d = F.cliques_containing_vertex(vertices=[(0, 1)]) # needs networkx - sage: list(d) # needs networkx + sage: d = F.cliques_containing_vertex(vertices=[(0, 1)]) + sage: list(d) [(0, 1)] - sage: sorted(sorted(x for x in L) for L in d[(0, 1)]) # needs networkx + sage: sorted(sorted(x for x in L) for L in d[(0, 1)]) [[(0, 0), (0, 1)], [(0, 1), (0, 2)], [(0, 1), (1, 1)]] """ if cliques is None: @@ -7723,14 +7737,16 @@ def cores(self, k=None, with_labels=False): [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3] sage: (graphs.FruchtGraph()).cores(with_labels=True) {0: 3, 1: 3, 2: 3, 3: 3, 4: 3, 5: 3, 6: 3, 7: 3, 8: 3, 9: 3, 10: 3, 11: 3} + + sage: # needs sage.modules sage: set_random_seed(0) - sage: a = random_matrix(ZZ, 20, x=2, sparse=True, density=.1) # needs sage.modules + sage: a = random_matrix(ZZ, 20, x=2, sparse=True, density=.1) sage: b = Graph(20) - sage: b.add_edges(a.nonzero_positions(), loops=False) # needs sage.modules - sage: cores = b.cores(with_labels=True); cores # needs sage.modules + sage: b.add_edges(a.nonzero_positions(), loops=False) + sage: cores = b.cores(with_labels=True); cores {0: 3, 1: 3, 2: 3, 3: 3, 4: 2, 5: 2, 6: 3, 7: 1, 8: 3, 9: 3, 10: 3, 11: 3, 12: 3, 13: 3, 14: 2, 15: 3, 16: 3, 17: 3, 18: 3, 19: 3} - sage: [v for v,c in cores.items() if c >= 2] # the vertices in the 2-core # needs sage.modules + sage: [v for v,c in cores.items() if c >= 2] # the vertices in the 2-core [0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] Checking the 2-core of a random lobster is indeed the empty set:: @@ -9100,24 +9116,26 @@ def effective_resistance(self, i, j, *, base_ring=None): Effective resistances in a straight linear 2-tree on 6 vertices :: + sage: # needs sage.modules sage: G = Graph([(0,1),(0,2),(1,2),(1,3),(3,5),(2,4),(2,3),(3,4),(4,5)]) - sage: G.effective_resistance(0,1) # needs sage.modules + sage: G.effective_resistance(0,1) 34/55 - sage: G.effective_resistance(0,3) # needs sage.modules + sage: G.effective_resistance(0,3) 49/55 - sage: G.effective_resistance(1,4) # needs sage.modules + sage: G.effective_resistance(1,4) 9/11 - sage: G.effective_resistance(0,5) # needs sage.modules + sage: G.effective_resistance(0,5) 15/11 Effective resistances in a fan on 6 vertices :: + sage: # needs sage.modules 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.effective_resistance(1,5) # needs sage.modules + sage: H.effective_resistance(1,5) 6/5 - sage: H.effective_resistance(1,3) # needs sage.modules + sage: H.effective_resistance(1,3) 49/55 - sage: H.effective_resistance(1,1) # needs sage.modules + sage: H.effective_resistance(1,1) 0 Using a different base ring:: @@ -9140,27 +9158,28 @@ def effective_resistance(self, i, j, *, base_ring=None): TESTS:: + sage: # needs sage.modules sage: G = graphs.CompleteGraph(4) - sage: all(G.effective_resistance(u, v) == 1/2 # needs sage.modules + sage: all(G.effective_resistance(u, v) == 1/2 ....: for u,v in G.edge_iterator(labels=False)) True - sage: Graph(1).effective_resistance(0,0) # needs sage.modules + sage: Graph(1).effective_resistance(0,0) 0 sage: G = Graph([(0,1),(1,2)]) - sage: G.effective_resistance(0,2) # needs sage.modules + sage: G.effective_resistance(0,2) 2 sage: G = Graph([(0,1),(1,2),(2,0)]) - sage: G.effective_resistance(0,2) # needs sage.modules + sage: G.effective_resistance(0,2) 2/3 sage: G = Graph([(0,1),(0,2),(0,3),(0,4),(0,5),(1,2),(2,3),(3,4),(4,5),(5,1)]) - sage: r = G.effective_resistance(0,3) # needs sage.modules - sage: r == fibonacci(2*(5-3)+1)*fibonacci(2*3-1)/fibonacci(2*5) # needs sage.modules + sage: r = G.effective_resistance(0,3) + sage: r == fibonacci(2*(5-3)+1)*fibonacci(2*3-1)/fibonacci(2*5) True sage: G = graphs.PathGraph(4) sage: G.delete_edge(2,3) - sage: G.effective_resistance(0,2) # needs sage.modules + sage: G.effective_resistance(0,2) 2 - sage: G.effective_resistance(0,3) # needs sage.modules + sage: G.effective_resistance(0,3) +Infinity """ from sage.matrix.constructor import matrix @@ -9299,36 +9318,38 @@ def effective_resistance_matrix(self, vertices=None, nonedgesonly=True, in the meantime if you want to use it please disallow multiedges using allow_multiple_edges(). - sage: graphs.CompleteGraph(4).effective_resistance_matrix(nonedgesonly=False) # needs sage.modules + sage: # needs sage.modules + sage: graphs.CompleteGraph(4).effective_resistance_matrix(nonedgesonly=False) [ 0 1/2 1/2 1/2] [1/2 0 1/2 1/2] [1/2 1/2 0 1/2] [1/2 1/2 1/2 0] - sage: Graph(1).effective_resistance_matrix() # needs sage.modules + sage: Graph(1).effective_resistance_matrix() [0] - sage: Graph().effective_resistance_matrix() # needs sage.modules + sage: Graph().effective_resistance_matrix() Traceback (most recent call last): ... ValueError: unable to compute effective resistance for an empty Graph object sage: G = Graph([(0,1),(1,2),(2,3),(3,0),(0,2)]) - sage: G.effective_resistance_matrix() # needs sage.modules + sage: G.effective_resistance_matrix() [0 0 0 0] [0 0 0 1] [0 0 0 0] [0 1 0 0] sage: G = Graph([(0,1),(0,2),(0,3),(0,4),(0,5),(1,2),(2,3),(3,4),(4,5),(5,1)]) - sage: r = G.effective_resistance_matrix(nonedgesonly=False)[0,3] # needs sage.modules - sage: r == fibonacci(2*(5-3)+1)*fibonacci(2*3-1)/fibonacci(2*5) # needs sage.libs.pari sage.modules + sage: r = G.effective_resistance_matrix(nonedgesonly=False)[0,3] + sage: r == fibonacci(2*(5-3)+1)*fibonacci(2*3-1)/fibonacci(2*5) # needs sage.libs.pari True Ask for an immutable matrix:: + sage: # needs sage.modules sage: G = Graph([(0, 1)]) - sage: M = G.effective_resistance_matrix(immutable=False) # needs sage.modules - sage: M.is_immutable() # needs sage.modules + sage: M = G.effective_resistance_matrix(immutable=False) + sage: M.is_immutable() False - sage: M = G.effective_resistance_matrix(immutable=True) # needs sage.modules - sage: M.is_immutable() # needs sage.modules + sage: M = G.effective_resistance_matrix(immutable=True) + sage: M.is_immutable() True """ from sage.matrix.constructor import matrix @@ -9418,14 +9439,15 @@ def least_effective_resistance(self, nonedgesonly=True): TESTS:: - sage: graphs.CompleteGraph(4).least_effective_resistance() # needs sage.modules + sage: # needs sage.modules + sage: graphs.CompleteGraph(4).least_effective_resistance() [] - sage: graphs.CompleteGraph(4).least_effective_resistance(nonedgesonly=False) # needs sage.modules + sage: graphs.CompleteGraph(4).least_effective_resistance(nonedgesonly=False) [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] - sage: Graph(1).least_effective_resistance() # needs sage.modules + sage: Graph(1).least_effective_resistance() [] sage: G = Graph([(0,1),(1,2),(2,3),(3,0),(0,2)]) - sage: G.least_effective_resistance() # needs sage.modules + sage: G.least_effective_resistance() [(1, 3)] """ n = self.order() @@ -9544,16 +9566,17 @@ def common_neighbors_matrix(self, vertices=None, nonedgesonly=True, TESTS:: + sage: # needs sage.modules sage: G = graphs.CompleteGraph(4) - sage: M = G.common_neighbors_matrix() # needs sage.modules - sage: M.is_zero() # needs sage.modules + sage: M = G.common_neighbors_matrix() + sage: M.is_zero() True - sage: Graph(1).common_neighbors_matrix() # needs sage.modules + sage: Graph(1).common_neighbors_matrix() [0] - sage: Graph().common_neighbors_matrix() # needs sage.modules + sage: Graph().common_neighbors_matrix() [] sage: G = Graph([(0,1),(1,2),(2,3),(3,0),(0,2)]) - sage: G.common_neighbors_matrix() # needs sage.modules + sage: G.common_neighbors_matrix() [0 0 0 0] [0 0 0 2] [0 0 0 0] @@ -9561,12 +9584,13 @@ def common_neighbors_matrix(self, vertices=None, nonedgesonly=True, Asking for an immutable matrix:: + sage: # needs sage.modules sage: G = Graph([(0, 1)]) - sage: M = G.common_neighbors_matrix() # needs sage.modules - sage: M.is_immutable() # needs sage.modules + sage: M = G.common_neighbors_matrix() + sage: M.is_immutable() False - sage: M = G.common_neighbors_matrix(immutable=True) # needs sage.modules - sage: M.is_immutable() # needs sage.modules + sage: M = G.common_neighbors_matrix(immutable=True) + sage: M.is_immutable() True """ self._scream_if_not_simple() @@ -9628,23 +9652,24 @@ def most_common_neighbors(self, nonedgesonly=True): TESTS:: - sage: G=graphs.CompleteGraph(4) - sage: G.most_common_neighbors() # needs sage.modules + sage: # needs sage.modules + sage: G = graphs.CompleteGraph(4) + sage: G.most_common_neighbors() [] - sage: G.most_common_neighbors(nonedgesonly=False) # needs sage.modules + sage: G.most_common_neighbors(nonedgesonly=False) [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] - sage: Graph(1).most_common_neighbors() # needs sage.modules + sage: Graph(1).most_common_neighbors() Traceback (most recent call last): ... ValueError: this method is defined for graphs with at least 2 vertices - sage: Graph().most_common_neighbors() # needs sage.modules + sage: Graph().most_common_neighbors() Traceback (most recent call last): ... ValueError: this method is defined for graphs with at least 2 vertices sage: G = Graph([(0,1),(1,2),(2,3),(3,0),(0,2)]) - sage: G.most_common_neighbors() # needs sage.modules + sage: G.most_common_neighbors() [(1, 3)] - sage: G.most_common_neighbors(nonedgesonly=False) # needs sage.modules + sage: G.most_common_neighbors(nonedgesonly=False) [(0, 2), (1, 3)] """ self._scream_if_not_simple() From d7b2cb24fac46d8475656bd52d978bc68d4568b2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 2 Aug 2023 16:40:01 -0700 Subject: [PATCH 07/10] sage.graphs: Use more block # needs --- src/sage/graphs/base/c_graph.pyx | 11 +-- src/sage/graphs/bipartite_graph.py | 126 +++++++++++++++------------- src/sage/graphs/centrality.pyx | 26 +++--- src/sage/graphs/domination.py | 70 ++++++++-------- src/sage/graphs/generators/basic.py | 113 ++++++++++++++----------- 5 files changed, 187 insertions(+), 159 deletions(-) diff --git a/src/sage/graphs/base/c_graph.pyx b/src/sage/graphs/base/c_graph.pyx index 0f5c09aa12f..79e62e13a33 100644 --- a/src/sage/graphs/base/c_graph.pyx +++ b/src/sage/graphs/base/c_graph.pyx @@ -1576,12 +1576,13 @@ cdef class CGraphBackend(GenericGraphBackend): We check that the bug described in :trac:`8406` is gone:: + sage: # needs sage.rings.finite_rings sage: G = Graph() - sage: R. = GF(3**3) # needs sage.rings.finite_rings - sage: S. = R[] # needs sage.rings.finite_rings - sage: G.add_vertex(a**2) # needs sage.rings.finite_rings - sage: G.add_vertex(x) # needs sage.rings.finite_rings - sage: G.vertices(sort=True) # needs sage.rings.finite_rings + sage: R. = GF(3**3) + sage: S. = R[] + sage: G.add_vertex(a**2) + sage: G.add_vertex(x) + sage: G.vertices(sort=True) [a^2, x] And that the bug described in :trac:`9610` is gone:: diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index 0aaae8e1551..b2c9fdbf3db 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -198,16 +198,17 @@ 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), # needs sage.modules + sage: # needs sage.modules + sage: M = Matrix([(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: M # needs sage.modules + sage: M [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 # needs sage.modules + sage: H = BipartiteGraph(M); H Bipartite graph on 11 vertices - sage: H.edges(sort=True) # needs sage.modules + sage: H.edges(sort=True) [(0, 7, None), (0, 8, None), (0, 10, None), @@ -244,13 +245,14 @@ class BipartiteGraph(Graph): :: - sage: F. = GF(4) # needs sage.modules sage.rings.finite_rings - sage: MS = MatrixSpace(F, 2, 3) # needs sage.modules sage.rings.finite_rings - sage: M = MS.matrix([[0, 1, a + 1], [a, 1, 1]]) # needs sage.modules sage.rings.finite_rings - sage: B = BipartiteGraph(M, weighted=True, sparse=True) # needs sage.modules sage.rings.finite_rings - sage: B.edges(sort=True) # needs sage.modules sage.rings.finite_rings + sage: # needs sage.modules sage.rings.finite_rings + 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) [(0, 4, a), (1, 3, 1), (1, 4, 1), (2, 3, a + 1), (2, 4, 1)] - sage: B.weighted() # needs sage.modules sage.rings.finite_rings + sage: B.weighted() True #. From an alist file:: @@ -311,10 +313,11 @@ class BipartiteGraph(Graph): #. From a NetworkX bipartite graph:: - sage: import networkx # needs networkx - sage: G = graphs.OctahedralGraph() # needs networkx - sage: N = networkx.make_clique_bipartite(G.networkx_graph()) # needs networkx - sage: B = BipartiteGraph(N) # needs networkx + sage: # needs networkx + sage: import networkx + sage: G = graphs.OctahedralGraph() + sage: N = networkx.make_clique_bipartite(G.networkx_graph()) + sage: B = BipartiteGraph(N) TESTS: @@ -328,15 +331,16 @@ 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])) # needs sage.modules - sage: a # needs sage.modules + sage: # needs sage.modules + sage: a = BipartiteGraph(matrix(2, 2, [1, 0, 1, 0])) + sage: a Bipartite graph on 4 vertices - sage: a.vertices(sort=True) # needs sage.modules + sage: a.vertices(sort=True) [0, 1, 2, 3] - sage: g = BipartiteGraph(matrix(4, 4, [1] * 4 + [0] * 12)) # needs sage.modules - sage: g.vertices(sort=True) # needs sage.modules + sage: g = BipartiteGraph(matrix(4, 4, [1] * 4 + [0] * 12)) + sage: g.vertices(sort=True) [0, 1, 2, 3, 4, 5, 6, 7] - sage: sorted(g.left.union(g.right)) # needs sage.modules + sage: sorted(g.left.union(g.right)) [0, 1, 2, 3, 4, 5, 6, 7] Make sure that loops are not allowed (:trac:`23275`):: @@ -1806,19 +1810,20 @@ def save_afile(self, fname): EXAMPLES:: - sage: M = Matrix([(1,1,1,0,0,0,0), (1,0,0,1,1,0,0), # needs sage.modules + sage: # needs sage.modules + sage: M = Matrix([(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: M # needs sage.modules + sage: M [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) # needs sage.modules - sage: import tempfile # needs sage.modules - sage: with tempfile.NamedTemporaryFile() as f: # needs sage.modules + sage: b = BipartiteGraph(M) + sage: import tempfile + sage: with tempfile.NamedTemporaryFile() as f: ....: b.save_afile(f.name) ....: b2 = BipartiteGraph(f.name) - sage: b.is_isomorphic(b2) # needs sage.modules + sage: b.is_isomorphic(b2) True TESTS:: @@ -1923,54 +1928,57 @@ 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), # needs sage.modules + sage: # needs sage.modules + sage: M = Matrix([(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) # needs sage.modules - sage: N = B.reduced_adjacency_matrix(); N # needs sage.modules + sage: B = BipartiteGraph(M) + sage: N = B.reduced_adjacency_matrix(); N [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 # needs sage.modules + sage: N == M True - sage: N[0,0].parent() # needs sage.modules + sage: N[0,0].parent() Integer Ring - sage: N2 = B.reduced_adjacency_matrix(base_ring=RDF); N2 # needs sage.modules + sage: N2 = B.reduced_adjacency_matrix(base_ring=RDF); N2 [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() # needs sage.modules + sage: N2[0, 0].parent() 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)]) # needs sage.modules - sage: B = BipartiteGraph(M, multiedges=True, sparse=True) # needs sage.modules - sage: N = B.reduced_adjacency_matrix() # needs sage.modules - sage: N == M # needs sage.modules + sage: # needs sage.modules + 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 True - sage: N[0,0].parent() # needs sage.modules + sage: N[0,0].parent() Integer Ring - sage: N2 = B.reduced_adjacency_matrix(base_ring=RDF) # needs sage.modules - sage: N2[0, 0].parent() # needs sage.modules + sage: N2 = B.reduced_adjacency_matrix(base_ring=RDF) + sage: N2[0, 0].parent() 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) # needs sage.modules sage.rings.finite_rings - sage: MS = MatrixSpace(F, 2, 3) # needs sage.modules sage.rings.finite_rings - sage: M = MS.matrix([[0, 1, a+1], [a, 1, 1]]) # needs sage.modules sage.rings.finite_rings - sage: B = BipartiteGraph(M, weighted=True, sparse=True) # needs sage.modules sage.rings.finite_rings - sage: N = B.reduced_adjacency_matrix(sparse=False) # needs sage.modules sage.rings.finite_rings - sage: N == M # needs sage.modules sage.rings.finite_rings + sage: # needs sage.modules sage.rings.finite_rings + 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 True - sage: N[0,0].parent() # needs sage.modules sage.rings.finite_rings + sage: N[0,0].parent() Finite Field in a of size 2^2 - sage: N2 = B.reduced_adjacency_matrix(base_ring=F) # needs sage.modules sage.rings.finite_rings - sage: N2[0, 0].parent() # needs sage.modules sage.rings.finite_rings + sage: N2 = B.reduced_adjacency_matrix(base_ring=F) + sage: N2[0, 0].parent() Finite Field in a of size 2^2 TESTS:: @@ -1989,11 +1997,12 @@ def reduced_adjacency_matrix(self, sparse=True, *, base_ring=None, **kwds): 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) # needs sage.modules sage.rings.finite_rings - sage: MS = MatrixSpace(F, 2, 3) # needs sage.modules sage.rings.finite_rings - sage: M = MS.matrix([[0, 1, a+1], [a, 1, 1]]) # needs sage.modules sage.rings.finite_rings - sage: B = BipartiteGraph(M, weighted=True, sparse=True) # needs sage.modules sage.rings.finite_rings - sage: B.reduced_adjacency_matrix(base_ring=RDF) # needs sage.modules sage.rings.finite_rings + sage: # needs sage.modules sage.rings.finite_rings + 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) Traceback (most recent call last): ... TypeError: float() argument must be a string or a ...number, not 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement' @@ -2295,10 +2304,11 @@ def vertex_cover(self, algorithm="Konig", value_only=False, The two algorithms should return the same result:: - sage: g = BipartiteGraph(graphs.RandomBipartite(10, 10, .5)) # needs numpy - sage: vc1 = g.vertex_cover(algorithm="Konig") # needs numpy - sage: vc2 = g.vertex_cover(algorithm="Cliquer") # needs numpy - sage: len(vc1) == len(vc2) # needs numpy + sage: # needs numpy + sage: g = BipartiteGraph(graphs.RandomBipartite(10, 10, .5)) + sage: vc1 = g.vertex_cover(algorithm="Konig") + sage: vc2 = g.vertex_cover(algorithm="Cliquer") + sage: len(vc1) == len(vc2) True TESTS: diff --git a/src/sage/graphs/centrality.pyx b/src/sage/graphs/centrality.pyx index fa659c13d94..0f6e83565ee 100755 --- a/src/sage/graphs/centrality.pyx +++ b/src/sage/graphs/centrality.pyx @@ -638,34 +638,36 @@ def centrality_closeness_top_k(G, int k=1, int verbose=0): The result is correct:: + sage: # needs networkx sage: from sage.graphs.centrality import centrality_closeness_top_k sage: import random sage: n = 20 sage: m = random.randint(1, n * (n - 1) / 2) sage: k = random.randint(1, n) - sage: g = graphs.RandomGNM(n, m) # needs networkx - sage: topk = centrality_closeness_top_k(g, k) # needs networkx - sage: centr = g.centrality_closeness(algorithm='BFS') # needs networkx - sage: sorted_centr = sorted(centr.values(), reverse=True) # needs networkx - sage: len(topk) == min(k, len(sorted_centr)) # needs networkx + 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)) True - sage: all(abs(topk[i][0] - sorted_centr[i]) < 1e-12 for i in range(len(topk))) # needs networkx + sage: all(abs(topk[i][0] - sorted_centr[i]) < 1e-12 for i in range(len(topk))) True Directed case:: + sage: # needs networkx sage: from sage.graphs.centrality import centrality_closeness_top_k sage: import random sage: n = 20 sage: m = random.randint(1, n * (n - 1)) sage: k = random.randint(1, n) - sage: g = digraphs.RandomDirectedGNM(n, m) # needs networkx - sage: topk = centrality_closeness_top_k(g, k) # needs networkx - sage: centr = g.centrality_closeness(algorithm='BFS') # needs networkx - sage: sorted_centr = sorted(centr.values(), reverse=True) # needs networkx - sage: len(topk) == min(k, len(sorted_centr)) # needs networkx + 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)) True - sage: all(abs(topk[i][0] - sorted_centr[i]) < 1e-12 for i in range(len(topk))) # needs networkx + sage: all(abs(topk[i][0] - sorted_centr[i]) < 1e-12 for i in range(len(topk))) True """ cdef list res diff --git a/src/sage/graphs/domination.py b/src/sage/graphs/domination.py index a92c814c7fa..00cc3ed5900 100644 --- a/src/sage/graphs/domination.py +++ b/src/sage/graphs/domination.py @@ -312,28 +312,30 @@ def dominating_sets(g, k=1, independent=False, total=False, Independent distance-`k` dominating sets of a Path graph:: + sage: # needs sage.numerical.mip sage: G = graphs.PathGraph(6) - sage: sorted(G.dominating_sets(k=1, independent=True)) # needs sage.numerical.mip + sage: sorted(G.dominating_sets(k=1, independent=True)) [[1, 4]] - sage: sorted(G.dominating_sets(k=2, independent=True)) # needs sage.numerical.mip + sage: sorted(G.dominating_sets(k=2, independent=True)) [[0, 3], [0, 4], [0, 5], [1, 3], [1, 4], [1, 5], [2, 4], [2, 5]] - sage: sorted(G.dominating_sets(k=3, independent=True)) # needs sage.numerical.mip + sage: sorted(G.dominating_sets(k=3, independent=True)) [[2], [3]] The dominating set is calculated for both the directed and undirected graphs (modification introduced in :trac:`17905`):: + sage: # needs sage.numerical.mip sage: g = digraphs.Path(3) - sage: g.dominating_set(value_only=True) # needs sage.numerical.mip + sage: g.dominating_set(value_only=True) 2 - sage: list(g.dominating_sets()) # needs sage.numerical.mip + sage: list(g.dominating_sets()) [[0, 1], [0, 2]] - sage: list(g.dominating_sets(k=2)) # needs sage.numerical.mip + sage: list(g.dominating_sets(k=2)) [[0]] sage: g = graphs.PathGraph(3) - sage: g.dominating_set(value_only=True) # needs sage.numerical.mip + sage: g.dominating_set(value_only=True) 1 - sage: next(g.dominating_sets()) # needs sage.numerical.mip + sage: next(g.dominating_sets()) [1] TESTS:: @@ -780,32 +782,32 @@ def minimal_dominating_sets(G, to_dominate=None, work_on_copy=False, k=1): sage: ll = list(graphs.PetersenGraph().minimal_dominating_sets()) sage: pp = [{0, 2, 6}, - ....: {0, 9, 3}, - ....: {0, 8, 7}, - ....: {1, 3, 7}, - ....: {1, 4, 5}, - ....: {8, 1, 9}, - ....: {8, 2, 4}, - ....: {9, 2, 5}, - ....: {3, 5, 6}, - ....: {4, 6, 7}, - ....: {0, 8, 2, 9}, - ....: {0, 3, 6, 7}, - ....: {1, 3, 5, 9}, - ....: {8, 1, 4, 7}, - ....: {2, 4, 5, 6}, - ....: {0, 1, 2, 3, 4}, - ....: {0, 1, 2, 5, 7}, - ....: {0, 1, 4, 6, 9}, - ....: {0, 1, 5, 6, 8}, - ....: {0, 8, 3, 4, 5}, - ....: {0, 9, 4, 5, 7}, - ....: {8, 1, 2, 3, 6}, - ....: {1, 2, 9, 6, 7}, - ....: {9, 2, 3, 4, 7}, - ....: {8, 2, 3, 5, 7}, - ....: {8, 9, 3, 4, 6}, - ....: {8, 9, 5, 6, 7}] + ....: {0, 9, 3}, + ....: {0, 8, 7}, + ....: {1, 3, 7}, + ....: {1, 4, 5}, + ....: {8, 1, 9}, + ....: {8, 2, 4}, + ....: {9, 2, 5}, + ....: {3, 5, 6}, + ....: {4, 6, 7}, + ....: {0, 8, 2, 9}, + ....: {0, 3, 6, 7}, + ....: {1, 3, 5, 9}, + ....: {8, 1, 4, 7}, + ....: {2, 4, 5, 6}, + ....: {0, 1, 2, 3, 4}, + ....: {0, 1, 2, 5, 7}, + ....: {0, 1, 4, 6, 9}, + ....: {0, 1, 5, 6, 8}, + ....: {0, 8, 3, 4, 5}, + ....: {0, 9, 4, 5, 7}, + ....: {8, 1, 2, 3, 6}, + ....: {1, 2, 9, 6, 7}, + ....: {9, 2, 3, 4, 7}, + ....: {8, 2, 3, 5, 7}, + ....: {8, 9, 3, 4, 6}, + ....: {8, 9, 5, 6, 7}] sage: len(ll) == len(pp) and all(x in pp for x in ll) and all(x in ll for x in pp) True diff --git a/src/sage/graphs/generators/basic.py b/src/sage/graphs/generators/basic.py index 89555fec008..314d66aef43 100644 --- a/src/sage/graphs/generators/basic.py +++ b/src/sage/graphs/generators/basic.py @@ -248,7 +248,7 @@ def CycleGraph(n): Compare plotting using the predefined layout and networkx:: - sage: # needs networkx + sage: # needs networkx sage.plot sage: import networkx sage: n = networkx.cycle_graph(23) sage: spring23 = Graph(n) @@ -259,34 +259,36 @@ def CycleGraph(n): We next view many cycle graphs as a Sage graphics array. First we use the ``CycleGraph`` constructor, which fills in the position dictionary:: + sage: # needs networkx sage.plot sage: g = [] sage: j = [] sage: for i in range(9): ....: k = graphs.CycleGraph(i+3) ....: g.append(k) - sage: for i in range(3): # needs sage.plot + sage: for i in range(3): ....: 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) # needs sage.plot - sage: G.show() # long time # needs sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time Compare to plotting with the spring-layout algorithm:: + sage: # needs networkx sage.plot sage: g = [] sage: j = [] - sage: for i in range(9): # needs networkx + sage: for i in range(9): ....: spr = networkx.cycle_graph(i+3) ....: k = Graph(spr) ....: g.append(k) - sage: for i in range(3): # needs networkx sage.plot + sage: for i in range(3): ....: 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) # needs networkx sage.plot - sage: G.show() # long time # needs networkx sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time TESTS: @@ -335,42 +337,45 @@ def CompleteGraph(n): We view many Complete graphs with a Sage Graphics Array, first with this constructor (i.e., the position dictionary filled):: + sage: # needs sage.plot sage: g = [] sage: j = [] sage: for i in range(9): ....: k = graphs.CompleteGraph(i+3) ....: g.append(k) - sage: for i in range(3): # needs sage.plot + sage: for i in range(3): ....: 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) # needs sage.plot - sage: G.show() # long time # needs sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time We compare to plotting with the spring-layout algorithm:: - sage: import networkx # needs networkx + sage: # needs networkx sage.plot + sage: import networkx sage: g = [] sage: j = [] - sage: for i in range(9): # needs networkx + sage: for i in range(9): ....: spr = networkx.complete_graph(i+3) ....: k = Graph(spr) ....: g.append(k) - sage: for i in range(3): # needs networkx sage.plot + sage: for i in range(3): ....: 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) # needs networkx sage.plot - sage: G.show() # long time # needs networkx sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time Compare the constructors (results will vary):: - sage: import networkx # needs networkx - sage: t = cputime() # needs networkx - sage: n = networkx.complete_graph(389); spring389 = Graph(n) # needs networkx - sage: cputime(t) # random # needs networkx + sage: # needs networkx + sage: import networkx + sage: t = cputime() + sage: n = networkx.complete_graph(389); spring389 = Graph(n) + sage: cputime(t) # random 0.59203700000000126 sage: t = cputime() sage: posdict389 = graphs.CompleteGraph(389) @@ -379,11 +384,12 @@ def CompleteGraph(n): We compare plotting:: - sage: import networkx # needs networkx - sage: n = networkx.complete_graph(23) # needs networkx - sage: spring23 = Graph(n) # needs networkx + sage: # needs networkx + sage: import networkx + sage: n = networkx.complete_graph(23) + sage: spring23 = Graph(n) sage: posdict23 = graphs.CompleteGraph(23) - sage: spring23.show() # long time # needs networkx sage.plot + sage: spring23.show() # long time # needs sage.plot sage: posdict23.show() # long time # needs sage.plot """ G = Graph(n, name="Complete graph") @@ -404,16 +410,17 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation): EXAMPLES: + sage: # needs numpy 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) # needs numpy - sage: CG2 = CorrelationGraph(data, 0.9, True) # needs numpy - sage: CG3 = CorrelationGraph(data, 0.1, True) # needs numpy - sage: CG1.edges(sort=False) # needs numpy + 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) [(0, 0, None), (0, 1, None), (1, 1, None), (2, 2, None)] - sage: CG2.edges(sort=False) # needs numpy + sage: CG2.edges(sort=False) [(0, 0, None), (0, 1, None), (1, 1, None), (2, 2, None)] - sage: CG3.edges(sort=False) # needs numpy + sage: CG3.edges(sort=False) [(0, 0, None), (0, 1, None), (0, 2, None), (1, 1, None), (1, 2, None), (2, 2, None)] """ @@ -478,9 +485,10 @@ def CompleteBipartiteGraph(p, q, set_position=True): Two ways of constructing the complete bipartite graph, using different layout algorithms:: - sage: import networkx # needs networkx - sage: n = networkx.complete_bipartite_graph(389, 157) # long time # needs networkx - sage: spring_big = Graph(n) # long time # needs networkx + sage: # needs networkx + sage: import networkx + sage: n = networkx.complete_bipartite_graph(389, 157) # long time + sage: spring_big = Graph(n) # long time sage: posdict_big = graphs.CompleteBipartiteGraph(389, 157) # long time Compare the plotting:: @@ -512,19 +520,20 @@ def CompleteBipartiteGraph(p, q, set_position=True): We compare to plotting with the spring-layout algorithm:: + sage: # needs networkx sage.plot sage: g = [] sage: j = [] - sage: for i in range(9): # needs networkx + sage: for i in range(9): ....: spr = networkx.complete_bipartite_graph(i+1,4) ....: k = Graph(spr) ....: g.append(k) - sage: for i in range(3): # needs networkx sage.plot + sage: for i in range(3): ....: 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) # needs networkx sage.plot - sage: G.show() # long time # needs networkx sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time :trac:`12155`:: @@ -1111,18 +1120,19 @@ def LadderGraph(n): Create several ladder graphs in a Sage graphics array:: + sage: # needs sage.plot sage: g = [] sage: j = [] sage: for i in range(9): ....: k = graphs.LadderGraph(i+2) ....: g.append(k) - sage: for i in range(3): # needs sage.plot + sage: for i in range(3): ....: 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) # needs sage.plot - sage: G.show() # long time # needs sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time """ pos_dict = {} for i in range(n): @@ -1268,10 +1278,11 @@ def StarGraph(n): Compare the plots:: - sage: n = networkx.star_graph(23) # needs networkx - sage: spring23 = Graph(n) # needs networkx + sage: # needs networkx sage.plot + sage: n = networkx.star_graph(23) + sage: spring23 = Graph(n) sage: posdict23 = graphs.StarGraph(23) - sage: spring23.show() # long time # needs networkx + sage: spring23.show() # long time sage: posdict23.show() # long time View many star graphs as a Sage Graphics Array @@ -1280,36 +1291,38 @@ def StarGraph(n): :: + sage: # needs sage.plot sage: g = [] sage: j = [] sage: for i in range(9): ....: k = graphs.StarGraph(i+3) ....: g.append(k) - sage: for i in range(3): # needs sage.plot + sage: for i in range(3): ....: 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) # needs sage.plot - sage: G.show() # long time # needs sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time Compared to plotting with the spring-layout algorithm :: + sage: # needs networkx sage.plot sage: g = [] sage: j = [] - sage: for i in range(9): # needs networkx + sage: for i in range(9): ....: spr = networkx.star_graph(i+3) ....: k = Graph(spr) ....: g.append(k) - sage: for i in range(3): # needs networkx sage.plot + sage: for i in range(3): ....: 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) # needs networkx sage.plot - sage: G.show() # long time # needs networkx sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time """ G = Graph({0: list(range(1, n + 1))}, name="Star graph", format="dict_of_lists") G.set_pos({0: (0, 0)}) From db061a95a817934ad2e4336754e8748ed50788c1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 2 Aug 2023 17:22:15 -0700 Subject: [PATCH 08/10] sage.graphs: Use even more block # needs --- src/sage/graphs/generators/random.py | 50 ++-- src/sage/graphs/generators/smallgraphs.py | 18 +- src/sage/graphs/generic_graph.py | 268 ++++++++++-------- src/sage/graphs/graph.py | 22 +- src/sage/graphs/graph_coloring.pyx | 61 ++-- .../vertex_separation.pyx | 11 +- src/sage/graphs/graph_generators.py | 67 +++-- src/sage/graphs/graph_input.py | 114 ++++---- src/sage/graphs/graph_latex.py | 81 +++--- src/sage/graphs/graph_plot_js.py | 10 +- src/sage/graphs/path_enumeration.pyx | 27 +- src/sage/graphs/strongly_regular_db.pyx | 11 +- 12 files changed, 394 insertions(+), 346 deletions(-) diff --git a/src/sage/graphs/generators/random.py b/src/sage/graphs/generators/random.py index 22459ca6930..5dab4071f49 100644 --- a/src/sage/graphs/generators/random.py +++ b/src/sage/graphs/generators/random.py @@ -162,18 +162,19 @@ def RandomBarabasiAlbert(n, m, seed=None): We view many random graphs using a graphics array:: + sage: # needs networkx sage.plot sage: g = [] sage: j = [] - sage: for i in range(1,10): # needs networkx + sage: for i in range(1,10): ....: k = graphs.RandomBarabasiAlbert(i+3, 3) ....: g.append(k) - sage: for i in range(3): # needs networkx sage.plot + sage: for i in range(3): ....: 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) # needs networkx sage.plot - sage: G.show() # long time # needs networkx sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time When `m = 1`, the generated graph is a tree:: @@ -690,18 +691,19 @@ def RandomGNM(n, m, dense=False, seed=None): We view many random graphs using a graphics array:: + sage: # needs networkx sage.plot sage: g = [] sage: j = [] - sage: for i in range(9): # needs networkx + sage: for i in range(9): ....: k = graphs.RandomGNM(i+3, i^2-i) ....: g.append(k) - sage: for i in range(3): # needs networkx sage.plot + sage: for i in range(3): ....: 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) # needs networkx sage.plot - sage: G.show() # long time # needs networkx sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time """ if seed is None: seed = int(current_randstate().long_seed() % sys.maxsize) @@ -1446,7 +1448,7 @@ def RandomTreePowerlaw(n, gamma=3, tries=1000, seed=None): :: sage: G = graphs.RandomTreePowerlaw(15, 2) # needs networkx - sage: if G: # random output # long time # needs networkx sage.plot + sage: if G: # random output # long time, needs networkx sage.plot ....: G.show() """ if seed is None: @@ -1486,7 +1488,7 @@ def RandomRegular(d, n, seed=None): :: sage: G = graphs.RandomRegular(3, 20) # needs networkx - sage: if G: # random output # long time # needs networkx sage.plot + sage: if G: # random output # long time, needs networkx sage.plot ....: G.show() REFERENCES: @@ -2101,17 +2103,18 @@ def RandomBicubicPlanar(n, seed=None): EXAMPLES:: + sage: # needs sage.combinat sage: n = randint(200, 300) - sage: G = graphs.RandomBicubicPlanar(n) # needs sage.combinat - sage: G.order() == 2*n # needs sage.combinat + sage: G = graphs.RandomBicubicPlanar(n) + sage: G.order() == 2*n True - sage: G.size() == 3*n # needs sage.combinat + sage: G.size() == 3*n True - sage: G.is_bipartite() and G.is_planar() and G.is_regular(3) # needs sage.combinat + sage: G.is_bipartite() and G.is_planar() and G.is_regular(3) True - sage: dic = {'red': [v for v in G.vertices(sort=False) if v[0] == 'n'], # needs sage.combinat + sage: dic = {'red': [v for v in G.vertices(sort=False) if v[0] == 'n'], ....: '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) # needs sage.combinat sage.plot + sage: G.plot(vertex_labels=False, vertex_size=20, vertex_colors=dic) # needs sage.plot Graphics object consisting of ... graphics primitives .. PLOT:: @@ -2213,17 +2216,18 @@ def RandomUnitDiskGraph(n, radius=.1, side=1, seed=None): When using twice the same seed, the vertices get the same positions:: + sage: # needs scipy sage: from sage.misc.randstate import current_randstate sage: seed = current_randstate().seed() - sage: G = graphs.RandomUnitDiskGraph(20, radius=.5, side=1, seed=seed) # needs scipy - sage: H = graphs.RandomUnitDiskGraph(20, radius=.2, side=1, seed=seed) # needs scipy - sage: H.is_subgraph(G, induced=False) # needs scipy + 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) True - sage: H.size() <= G.size() # needs scipy + sage: H.size() <= G.size() True - sage: Gpos = G.get_pos() # needs scipy - sage: Hpos = H.get_pos() # needs scipy - sage: all(Gpos[u] == Hpos[u] for u in G) # needs scipy + sage: Gpos = G.get_pos() + sage: Hpos = H.get_pos() + sage: all(Gpos[u] == Hpos[u] for u in G) True When the radius is more than `\sqrt{2 \text{side}}`, the graph is a clique:: diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index e879b708aaf..ccc4610bb8c 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -2108,7 +2108,7 @@ def HortonGraph(): 96 sage: g.chromatic_number() 2 - sage: g.is_hamiltonian() # not tested # needs sage.numerical.mip + sage: g.is_hamiltonian() # not tested (veeeery long) # needs sage.numerical.mip False """ g = Graph(name="Horton Graph") @@ -4540,11 +4540,7 @@ def TutteGraph(): 4 sage: g.automorphism_group().cardinality() # needs sage.groups 3 -<<<<<<< HEAD - sage: g.is_hamiltonian() -======= sage: g.is_hamiltonian() # needs sage.numerical.mip ->>>>>>> 85d4a8d443 (./sage -fixdoctests --probe all --distribution 'sagemath-graphs[modules]' src/sage/graphs/generators/smallgraphs.py; ./sage -fixdoctests src/sage/graphs/generators/smallgraphs.py) False """ g = Graph(name="Tutte Graph") @@ -4723,11 +4719,7 @@ def _EllipticLinesProjectivePlaneScheme(k): TESTS:: sage: from sage.graphs.generators.smallgraphs import _EllipticLinesProjectivePlaneScheme -<<<<<<< HEAD - sage: _EllipticLinesProjectivePlaneScheme(2) -======= sage: _EllipticLinesProjectivePlaneScheme(2) # needs sage.libs.gap ->>>>>>> 85d4a8d443 (./sage -fixdoctests --probe all --distribution 'sagemath-graphs[modules]' src/sage/graphs/generators/smallgraphs.py; ./sage -fixdoctests src/sage/graphs/generators/smallgraphs.py) [ [1 0 0 0 0 0] [0 1 1 1 1 0] [0 0 0 0 0 1] [0 1 0 0 0 0] [1 0 1 1 0 1] [0 0 0 0 1 0] @@ -5042,20 +5034,12 @@ def IoninKharaghani765Graph(): EXAMPLES:: -<<<<<<< HEAD - sage: g = graphs.IoninKharaghani765Graph(); g -======= sage: g = graphs.IoninKharaghani765Graph(); g # needs sage.modules sage.rings.finite_rings ->>>>>>> 85d4a8d443 (./sage -fixdoctests --probe all --distribution 'sagemath-graphs[modules]' src/sage/graphs/generators/smallgraphs.py; ./sage -fixdoctests src/sage/graphs/generators/smallgraphs.py) Ionin-Kharaghani: Graph on 765 vertices TESTS:: -<<<<<<< HEAD - sage: graphs.strongly_regular_graph(765, 192, 48, 48) -======= sage: graphs.strongly_regular_graph(765, 192, 48, 48) # needs sage.modules sage.rings.finite_rings ->>>>>>> 85d4a8d443 (./sage -fixdoctests --probe all --distribution 'sagemath-graphs[modules]' src/sage/graphs/generators/smallgraphs.py; ./sage -fixdoctests src/sage/graphs/generators/smallgraphs.py) Ionin-Kharaghani: Graph on 765 vertices .. TODO:: diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 64cdd8dffcb..afae6f5de21 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -6872,43 +6872,46 @@ def edge_disjoint_spanning_trees(self, k, algorithm=None, root=None, solver=None ... EmptySetError: this graph does not contain the required number of trees/arborescences - By Edmond's theorem, a graph which is `k`-connected always has `k` + By Edmonds' theorem, a graph which is `k`-connected always has `k` edge-disjoint arborescences, regardless of the root we pick:: + sage: # needs sage.numerical.mip sage: g = digraphs.RandomDirectedGNP(11, .3) # reduced from 30 to 11, cf. #32169 sage: k = Integer(g.edge_connectivity()) - sage: while not k: # needs sage.numerical.mip + sage: while not k: ....: g = digraphs.RandomDirectedGNP(11, .3) ....: k = Integer(g.edge_connectivity()) - sage: arborescences = g.edge_disjoint_spanning_trees(k) # long time (up to 15s on sage.math, 2011), needs sage.numerical.mip - sage: all(a.is_directed_acyclic() for a in arborescences) # long time, needs sage.numerical.mip + sage: arborescences = g.edge_disjoint_spanning_trees(k) # long time (up to 15s on sage.math, 2011) + sage: all(a.is_directed_acyclic() for a in arborescences) # long time True - sage: all(a.is_connected() for a in arborescences) # long time # needs sage.numerical.mip + sage: all(a.is_connected() for a in arborescences) # long time True In the undirected case, we can only ensure half of it:: + sage: # needs sage.numerical.mip sage: g = graphs.RandomGNP(14, .3) # reduced from 30 to 14, see #32169 - sage: while not g.is_biconnected(): # needs sage.numerical.mip + sage: while not g.is_biconnected(): ....: g = graphs.RandomGNP(14, .3) - sage: k = Integer(g.edge_connectivity()) // 2 # needs sage.numerical.mip - sage: trees = g.edge_disjoint_spanning_trees(k) # needs sage.numerical.mip - sage: all(t.is_tree() for t in trees) # needs sage.numerical.mip + sage: k = Integer(g.edge_connectivity()) // 2 + sage: trees = g.edge_disjoint_spanning_trees(k) + sage: all(t.is_tree() for t in trees) True Check the validity of the algorithms for undirected graphs:: + sage: # needs sage.numerical.mip sage: g = graphs.RandomGNP(12, .7) sage: k = Integer(g.edge_connectivity()) // 2 - sage: trees = g.edge_disjoint_spanning_trees(k, algorithm="MILP") # needs sage.numerical.mip - sage: all(t.is_tree() for t in trees) # needs sage.numerical.mip + sage: trees = g.edge_disjoint_spanning_trees(k, algorithm="MILP") + sage: all(t.is_tree() for t in trees) True - sage: all(g.order() == t.size() + 1 for t in trees) # needs sage.numerical.mip + sage: all(g.order() == t.size() + 1 for t in trees) True - sage: trees = g.edge_disjoint_spanning_trees(k, algorithm="Roskind-Tarjan") # needs sage.numerical.mip - sage: all(t.is_tree() for t in trees) # needs sage.numerical.mip + sage: trees = g.edge_disjoint_spanning_trees(k, algorithm="Roskind-Tarjan") + sage: all(t.is_tree() for t in trees) True - sage: all(g.order() == t.size() + 1 for t in trees) # needs sage.numerical.mip + sage: all(g.order() == t.size() + 1 for t in trees) True Example of :trac:`32169`:: @@ -7634,12 +7637,13 @@ def max_cut(self, value_only=True, use_edge_labels=False, vertices=False, Quite obviously, the max cut of a bipartite graph is the number of edges, and the two sets of vertices are the two sides:: + sage: # needs sage.numerical.mip sage: g = graphs.CompleteBipartiteGraph(5,6) - sage: [ value, edges, [ setA, setB ]] = g.max_cut(vertices=True) # needs sage.numerical.mip - sage: value == 5*6 # needs sage.numerical.mip + sage: [ value, edges, [ setA, setB ]] = g.max_cut(vertices=True) + sage: value == 5*6 True - sage: bsetA, bsetB = map(list, g.bipartite_sets()) # needs sage.numerical.mip - sage: ((bsetA == setA and bsetB == setB) # needs sage.numerical.mip + sage: bsetA, bsetB = map(list, g.bipartite_sets()) + sage: ((bsetA == setA and bsetB == setB) ....: or (bsetA == setB and bsetB == setA)) True @@ -7882,15 +7886,16 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", Trivial graphs:: + sage: # needs sage.numerical.mip sage: G = Graph() sage: G.add_vertex(0) - sage: G.longest_path() # needs sage.numerical.mip + sage: G.longest_path() Graph on 0 vertices - sage: G.longest_path(use_edge_labels=True) # needs sage.numerical.mip + sage: G.longest_path(use_edge_labels=True) [0, Graph on 0 vertices] - sage: graphs.CompleteGraph(1).longest_path() # needs sage.numerical.mip + sage: graphs.CompleteGraph(1).longest_path() Graph on 0 vertices - sage: graphs.CompleteGraph(1).longest_path(use_edge_labels=True) # needs sage.numerical.mip + sage: graphs.CompleteGraph(1).longest_path(use_edge_labels=True) [0, Graph on 0 vertices] Random test for digraphs:: @@ -8192,16 +8197,17 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False, starting from vertex `(0, 0)` and ending at vertex `(2, 2)`, but no Hamiltonian path starting from `(0, 0)` and ending at `(0, 1)`:: + sage: # needs sage.numerical.mip sage: g = graphs.Grid2dGraph(3, 3) - sage: g.hamiltonian_path() # needs sage.numerical.mip + sage: g.hamiltonian_path() Hamiltonian path from 2D Grid Graph for [3, 3]: Graph on 9 vertices - sage: g.hamiltonian_path(s=(0, 0), t=(2, 2)) # needs sage.numerical.mip + sage: g.hamiltonian_path(s=(0, 0), t=(2, 2)) Hamiltonian path from 2D Grid Graph for [3, 3]: Graph on 9 vertices - sage: g.hamiltonian_path(s=(0, 0), t=(2, 2), use_edge_labels=True) # needs sage.numerical.mip + sage: g.hamiltonian_path(s=(0, 0), t=(2, 2), use_edge_labels=True) (8, Hamiltonian path from 2D Grid Graph for [3, 3]: Graph on 9 vertices) - sage: g.hamiltonian_path(s=(0, 0), t=(0, 1)) is None # needs sage.numerical.mip + sage: g.hamiltonian_path(s=(0, 0), t=(0, 1)) is None True - sage: g.hamiltonian_path(s=(0, 0), t=(0, 1), use_edge_labels=True) # needs sage.numerical.mip + sage: g.hamiltonian_path(s=(0, 0), t=(0, 1), use_edge_labels=True) (0, None) TESTS: @@ -8505,14 +8511,15 @@ def traveling_salesman_problem(self, use_edge_labels=False, maximize=False, Search for a minimum and a maximum weight Hamiltonian cycle:: + sage: # needs sage.numerical.mip sage: G = Graph([(0, 1, 1), (0, 2, 2), (0, 3, 1), (1, 2, 1), (1, 3, 2), (2, 3, 1)]) - sage: tsp = G.traveling_salesman_problem(use_edge_labels=True, # needs sage.numerical.mip + sage: tsp = G.traveling_salesman_problem(use_edge_labels=True, ....: maximize=False) - sage: print(sum(tsp.edge_labels())) # needs sage.numerical.mip + sage: print(sum(tsp.edge_labels())) 4 - sage: tsp = G.traveling_salesman_problem(use_edge_labels=True, # needs sage.numerical.mip + sage: tsp = G.traveling_salesman_problem(use_edge_labels=True, ....: maximize=True) - sage: print(sum(tsp.edge_labels())) # needs sage.numerical.mip + sage: print(sum(tsp.edge_labels())) 6 TESTS: @@ -8554,47 +8561,49 @@ def traveling_salesman_problem(self, use_edge_labels=False, maximize=False, Simple tests for multiple edges and loops:: + sage: # needs sage.numerical.mip sage: G = DiGraph(multiedges=True, loops=True) - sage: G.is_hamiltonian() # needs sage.numerical.mip + sage: G.is_hamiltonian() False sage: G.add_vertex(0) - sage: G.is_hamiltonian() # needs sage.numerical.mip + sage: G.is_hamiltonian() False sage: G.add_edge(0, 0, 1) sage: G.add_edge(0, 0, 2) - sage: tsp = G.traveling_salesman_problem(use_edge_labels=True) # needs sage.numerical.mip + sage: tsp = G.traveling_salesman_problem(use_edge_labels=True) Traceback (most recent call last): ... EmptySetError: the given graph is not Hamiltonian sage: G.add_vertex(1) - sage: G.is_hamiltonian() # needs sage.numerical.mip + sage: G.is_hamiltonian() False sage: G.add_edge(0, 1, 2) sage: G.add_edge(0, 1, 3) sage: G.add_edge(1, 1, 1) sage: G.add_edge(1, 0, 2) - sage: G.is_hamiltonian() # needs sage.numerical.mip + sage: G.is_hamiltonian() True - sage: tsp = G.traveling_salesman_problem(use_edge_labels=True) # needs sage.numerical.mip - sage: sum(tsp.edge_labels()) # needs sage.numerical.mip + sage: tsp = G.traveling_salesman_problem(use_edge_labels=True) + sage: sum(tsp.edge_labels()) 4 Graphs on 2 vertices:: - sage: Graph([(0, 1), (0, 1)], multiedges=True).is_hamiltonian() # needs sage.numerical.mip + sage: # needs sage.numerical.mip + sage: Graph([(0, 1), (0, 1)], multiedges=True).is_hamiltonian() True - sage: DiGraph([(0, 1), (0, 1)], multiedges=True).is_hamiltonian() # needs sage.numerical.mip + sage: DiGraph([(0, 1), (0, 1)], multiedges=True).is_hamiltonian() False - sage: DiGraph([(0, 1), (1, 0)], multiedges=True).is_hamiltonian() # needs sage.numerical.mip + sage: DiGraph([(0, 1), (1, 0)], multiedges=True).is_hamiltonian() True sage: G = digraphs.Complete(2, loops=True) - sage: G.is_hamiltonian() # needs sage.numerical.mip + sage: G.is_hamiltonian() True sage: G.remove_loops() - sage: G.is_hamiltonian() # needs sage.numerical.mip + sage: G.is_hamiltonian() True sage: G.allow_loops(False) - sage: G.is_hamiltonian() # needs sage.numerical.mip + sage: G.is_hamiltonian() True Check that weight 0 edges are handled correctly (see :trac:`16214`):: @@ -9100,12 +9109,13 @@ def feedback_vertex_set(self, value_only=False, solver=None, verbose=0, The necessary example:: + sage: # needs sage.numerical.mip sage: g = graphs.PetersenGraph() - sage: fvs = g.feedback_vertex_set() # needs sage.numerical.mip - sage: len(fvs) # needs sage.numerical.mip + sage: fvs = g.feedback_vertex_set() + sage: len(fvs) 3 - sage: g.delete_vertices(fvs) # needs sage.numerical.mip - sage: g.is_forest() # needs sage.numerical.mip + sage: g.delete_vertices(fvs) + sage: g.is_forest() True In a digraph built from a graph, any edge is replaced by arcs going in @@ -9114,15 +9124,16 @@ def feedback_vertex_set(self, value_only=False, solver=None, verbose=0, of its neighbors removed: a feedback vertex set is in this situation a vertex cover:: + sage: # needs sage.numerical.mip sage: cycle = graphs.CycleGraph(5) sage: dcycle = DiGraph(cycle) - sage: cycle.vertex_cover(value_only=True) # needs sage.numerical.mip + sage: cycle.vertex_cover(value_only=True) 3 - sage: feedback = dcycle.feedback_vertex_set() # needs sage.numerical.mip - sage: len(feedback) # needs sage.numerical.mip + sage: feedback = dcycle.feedback_vertex_set() + sage: len(feedback) 3 - sage: u,v = next(cycle.edge_iterator(labels=None)) # needs sage.numerical.mip - sage: u in feedback or v in feedback # needs sage.numerical.mip + sage: u,v = next(cycle.edge_iterator(labels=None)) + sage: u in feedback or v in feedback True For a circuit, the minimum feedback arc set is clearly `1`:: @@ -9662,17 +9673,18 @@ def nowhere_zero_flow(self, k=None, solver=None, verbose=0, *, integrality_toler Loops and multiple edges:: + sage: # needs sage.numerical.mip sage: g = Graph([(0, 0), (0, 0)], loops=True, multiedges=True) - sage: g.nowhere_zero_flow().edges(sort=True) # needs sage.numerical.mip + sage: g.nowhere_zero_flow().edges(sort=True) [(0, 0, 1), (0, 0, 1)] sage: g = Graph([(0, 0), (0, 1), (0, 1)], loops=True, multiedges=True) - sage: g.nowhere_zero_flow(k=2).edges(sort=True) # needs sage.numerical.mip + sage: g.nowhere_zero_flow(k=2).edges(sort=True) [(0, 0, 1), (0, 1, 1), (1, 0, 1)] sage: g = DiGraph([(0, 0), (0, 0)], loops=True, multiedges=True) - sage: g.nowhere_zero_flow().edges(sort=True) # needs sage.numerical.mip + sage: g.nowhere_zero_flow().edges(sort=True) [(0, 0, 1), (0, 0, 1)] sage: g = DiGraph([(0, 0), (0, 1), (0, 1)], loops=True, multiedges=True) - sage: g.nowhere_zero_flow(k=2).edges(sort=True) # needs sage.numerical.mip + sage: g.nowhere_zero_flow(k=2).edges(sort=True) [(0, 0, 1), (0, 1, -1), (0, 1, 1)] Multiple connected components:: @@ -11401,13 +11413,14 @@ def vertices(self, sort=None, key=None, degree=None, vertex_property=None): are first-class objects in Python, we can specify precisely the function from the Sage library that we wish to use as the key:: + sage: # needs sage.libs.flint sage: t = polygen(QQ, 't') sage: K = Graph({5*t: [t^2], t^2: [t^2+2], t^2+2: [4*t^2-6], 4*t^2-6: [5*t]}) - sage: from sage.rings.polynomial.polynomial_rational_flint import Polynomial_rational_flint # needs sage.libs.flint - sage: dsc = Polynomial_rational_flint.discriminant # needs sage.libs.flint - sage: verts = K.vertices(sort=True, key=dsc); verts # needs sage.libs.flint + sage: from sage.rings.polynomial.polynomial_rational_flint import Polynomial_rational_flint + sage: dsc = Polynomial_rational_flint.discriminant + sage: verts = K.vertices(sort=True, key=dsc); verts [t^2 + 2, t^2, 5*t, 4*t^2 - 6] - sage: [x.discriminant() for x in verts] # needs sage.libs.flint + sage: [x.discriminant() for x in verts] [-8, 0, 1, 96] TESTS: @@ -16192,21 +16205,22 @@ def centrality_closeness(self, vert=None, by_weight=False, algorithm=None, The result does not depend on the algorithm:: + sage: # needs networkx sage: import random sage: import itertools sage: n = random.randint(2,20) sage: m = random.randint(0, n*(n-1)/2) - sage: g = graphs.RandomGNM(n,m) # needs networkx - sage: c1 = g.centrality_closeness(algorithm='BFS') # needs networkx - sage: c2 = g.centrality_closeness(algorithm='NetworkX') # needs networkx - sage: c3 = g.centrality_closeness(algorithm='Dijkstra_Boost') # needs networkx - sage: c4 = g.centrality_closeness(algorithm='Floyd-Warshall-Cython') # needs networkx - sage: c5 = g.centrality_closeness(algorithm='Floyd-Warshall-Python') # needs networkx - sage: c6 = g.centrality_closeness(algorithm='Johnson_Boost') # needs networkx - sage: len(c1)==len(c2)==len(c3)==len(c4)==len(c5)==len(c6) # needs networkx + sage: g = graphs.RandomGNM(n,m) + sage: c1 = g.centrality_closeness(algorithm='BFS') + sage: c2 = g.centrality_closeness(algorithm='NetworkX') + sage: c3 = g.centrality_closeness(algorithm='Dijkstra_Boost') + sage: c4 = g.centrality_closeness(algorithm='Floyd-Warshall-Cython') + sage: c5 = g.centrality_closeness(algorithm='Floyd-Warshall-Python') + sage: c6 = g.centrality_closeness(algorithm='Johnson_Boost') + sage: len(c1)==len(c2)==len(c3)==len(c4)==len(c5)==len(c6) True - sage: c = [c1,c2,c3,c4,c5,c6] # needs networkx - sage: all( sum(abs(ci[v] - cj[v]) for v in g if g.degree(v)) < 1e-12 # needs networkx + sage: c = [c1,c2,c3,c4,c5,c6] + sage: all( sum(abs(ci[v] - cj[v]) for v in g if g.degree(v)) < 1e-12 ....: for ci, cj in itertools.combinations(c, 2) ) True @@ -16232,21 +16246,22 @@ def centrality_closeness(self, vert=None, by_weight=False, algorithm=None, Weighted graphs:: + sage: # needs networkx sage: import random sage: import itertools sage: n = random.randint(2,20) sage: m = random.randint(0, n*(n-1)/2) - sage: g = graphs.RandomGNM(n,m) # needs networkx - sage: for v,w in g.edges(sort=True, labels=False): # needs networkx + sage: g = graphs.RandomGNM(n,m) + sage: for v,w in g.edges(sort=True, labels=False): ....: g.set_edge_label(v,w,float(random.uniform(1,100))) - sage: c1 = g.centrality_closeness(by_weight=True, algorithm='NetworkX') # needs networkx - sage: c2 = g.centrality_closeness(by_weight=True, algorithm='Dijkstra_Boost') # needs networkx - sage: c3 = g.centrality_closeness(by_weight=True, algorithm='Floyd-Warshall-Python') # needs networkx - sage: c4 = g.centrality_closeness(by_weight=True, algorithm='Johnson_Boost') # needs networkx - sage: len(c1)==len(c2)==len(c3)==len(c4) # needs networkx - True - sage: c = [c1,c2,c3,c4] # needs networkx - sage: all( sum(abs(ci[v] - cj[v]) for v in g if g.degree(v)) < 1e-12 # needs networkx + sage: c1 = g.centrality_closeness(by_weight=True, algorithm='NetworkX') + sage: c2 = g.centrality_closeness(by_weight=True, algorithm='Dijkstra_Boost') + sage: c3 = g.centrality_closeness(by_weight=True, algorithm='Floyd-Warshall-Python') + sage: c4 = g.centrality_closeness(by_weight=True, algorithm='Johnson_Boost') + sage: len(c1)==len(c2)==len(c3)==len(c4) + True + sage: c = [c1,c2,c3,c4] + sage: all( sum(abs(ci[v] - cj[v]) for v in g if g.degree(v)) < 1e-12 ....: for ci, cj in itertools.combinations(c, 2) ) True @@ -20255,16 +20270,17 @@ def layout_graphviz(self, dim=2, prog='dot', **options): By default, an acyclic layout is computed using ``graphviz``'s ``dot`` layout program. One may specify an alternative layout program:: - sage: g.plot(layout="graphviz", prog="dot") # optional - dot2tex graphviz + sage: # optional - dot2tex graphviz + sage: g.plot(layout="graphviz", prog="dot") Graphics object consisting of 29 graphics primitives - sage: g.plot(layout="graphviz", prog="neato") # optional - dot2tex graphviz + sage: g.plot(layout="graphviz", prog="neato") Graphics object consisting of 29 graphics primitives - sage: g.plot(layout="graphviz", prog="twopi") # optional - dot2tex graphviz + sage: g.plot(layout="graphviz", prog="twopi") Graphics object consisting of 29 graphics primitives - sage: g.plot(layout="graphviz", prog="fdp") # optional - dot2tex graphviz + sage: g.plot(layout="graphviz", prog="fdp") Graphics object consisting of 29 graphics primitives sage: g = graphs.BalancedTree(5,2) # needs networkx - sage: g.plot(layout="graphviz", prog="circo") # optional - dot2tex graphviz, needs networkx + sage: g.plot(layout="graphviz", prog="circo") # needs networkx Graphics object consisting of 62 graphics primitives .. TODO:: @@ -20289,14 +20305,14 @@ def layout_graphviz(self, dim=2, prog='dot', **options): Make sure that :trac:`12364` is fixed:: - sage: # needs sage.combinat + sage: # needs sage.combinat sage.modules sage: m = WordMorphism('a->abb,b->ba') sage: w = m.fixed_point('a') - sage: prefix = Word(list(w[:100])) # needs sage.modules - sage: pals = prefix.palindromes() # needs sage.modules - sage: poset = Poset((pals, lambda x,y: x.is_factor(y))) # needs sage.modules - sage: H = poset.hasse_diagram() # needs sage.modules - sage: d = H.layout_graphviz() # optional - dot2tex graphviz # needs sage.modules + sage: prefix = Word(list(w[:100])) + sage: pals = prefix.palindromes() + sage: poset = Poset((pals, lambda x,y: x.is_factor(y))) + sage: H = poset.hasse_diagram() + sage: d = H.layout_graphviz() # optional - dot2tex graphviz """ assert_have_dot2tex() assert dim == 2, "3D graphviz layout not implemented" @@ -22115,11 +22131,12 @@ def spectrum(self, laplacian=False): test both the Laplacian construction and the computation of eigenvalues. :: + sage: # needs sage.modules sage.rings.number_field sage: H = graphs.HoffmanSingletonGraph() - sage: evals = H.spectrum() # needs sage.modules sage.rings.number_field - sage: lap = [7 - x for x in evals] # needs sage.modules sage.rings.number_field - sage: lap.sort(reverse=True) # needs sage.modules sage.rings.number_field - sage: lap == H.spectrum(laplacian=True) # needs sage.modules sage.rings.number_field + sage: evals = H.spectrum() + sage: lap = [7 - x for x in evals] + sage: lap.sort(reverse=True) + sage: lap == H.spectrum(laplacian=True) True """ # Ideally the spectrum should return something like a Factorization object @@ -22976,6 +22993,7 @@ def automorphism_group(self, partition=None, verbosity=0, Graphs:: + sage: # needs sage.groups sage: graphs_query = GraphQuery(display_cols=['graph6'],num_vertices=4) sage: L = graphs_query.get_graphs_list() sage: graphs_list.show_graphs(L) # needs sage.plot @@ -22994,7 +23012,7 @@ def automorphism_group(self, partition=None, verbosity=0, (4, ((2,3), (0,1))) (24, ((2,3), (1,2), (0,1))) sage: C = graphs.CubeGraph(4) - sage: G = C.automorphism_group() # needs sage.groups + sage: G = C.automorphism_group() sage: M = G.character_table() # random order of rows, thus abs() below sage: QQ(M.determinant()).abs() 712483534798848 @@ -23003,8 +23021,9 @@ def automorphism_group(self, partition=None, verbosity=0, :: + sage: # needs sage.groups sage: D = graphs.DodecahedralGraph() - sage: G = D.automorphism_group() # needs sage.groups + sage: G = D.automorphism_group() sage: A5 = AlternatingGroup(5) sage: Z2 = CyclicPermutationGroup(2) sage: H = A5.direct_product(Z2)[0] #see documentation for direct_product to explain the [0] @@ -23045,15 +23064,16 @@ def automorphism_group(self, partition=None, verbosity=0, sage: G.automorphism_group(edge_labels=True) # needs sage.groups Permutation Group with generators [(0,1)] + sage: # needs sage.groups sage: foo = Graph(sparse=True) sage: bar = Graph(sparse=True) sage: foo.add_edges([(0,1,1),(1,2,2), (2,3,3)]) sage: bar.add_edges([(0,1,1),(1,2,2), (2,3,3)]) - sage: foo.automorphism_group(edge_labels=True) # needs sage.groups + sage: foo.automorphism_group(edge_labels=True) Permutation Group with generators [()] - sage: foo.automorphism_group() # needs sage.groups + sage: foo.automorphism_group() Permutation Group with generators [(0,3)(1,2)] - sage: bar.automorphism_group(edge_labels=True) # needs sage.groups + sage: bar.automorphism_group(edge_labels=True) Permutation Group with generators [()] You can also ask for just the order of the group:: @@ -23066,16 +23086,17 @@ def automorphism_group(self, partition=None, verbosity=0, :: + sage: # needs sage.groups sage: G = graphs.PetersenGraph() - sage: G.automorphism_group(return_group=False, orbits=True, algorithm='sage') # needs sage.groups + sage: G.automorphism_group(return_group=False, orbits=True, algorithm='sage') [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] - sage: orb = G.automorphism_group(partition=[[0],list(range(1,10))], # needs sage.groups + sage: orb = G.automorphism_group(partition=[[0],list(range(1,10))], ....: return_group=False, orbits=True, algorithm='sage') - sage: sorted([sorted(o) for o in orb], key=len) # needs sage.groups + sage: sorted([sorted(o) for o in orb], key=len) [[0], [1, 4, 5], [2, 3, 6, 7, 8, 9]] sage: C = graphs.CubeGraph(3) - sage: orb = C.automorphism_group(orbits=True, return_group=False, algorithm='sage') # needs sage.groups - sage: [sorted(o) for o in orb] # needs sage.groups + sage: orb = C.automorphism_group(orbits=True, return_group=False, algorithm='sage') + sage: [sorted(o) for o in orb] [['000', '001', '010', '011', '100', '101', '110', '111']] One can also use the faster algorithm for computing the automorphism @@ -23101,17 +23122,18 @@ def automorphism_group(self, partition=None, verbosity=0, Labeled automorphism group:: - sage: d = digraphs.DeBruijn(3,2) # needs sage.combinat - sage: A = d.automorphism_group(algorithm='sage') # needs sage.combinat + sage: # needs sage.combinat sage.groups + sage: d = digraphs.DeBruijn(3,2) + sage: A = d.automorphism_group(algorithm='sage') sage: A_target = PermutationGroup(["('02','10','21')('00','11','22')('01','12','20')", ....: "('02','01')('10','20')('21','12')('22','11')"]) - sage: A.is_isomorphic(A_target) # needs sage.combinat + sage: A.is_isomorphic(A_target) True - sage: d.allow_multiple_edges(True) # needs sage.combinat - sage: d.add_edge(('00', '00', '0')) # needs sage.combinat - sage: A = d.automorphism_group(algorithm='sage') # needs sage.combinat + sage: d.allow_multiple_edges(True) + sage: d.add_edge(('00', '00', '0')) + sage: A = d.automorphism_group(algorithm='sage') sage: A_target = PermutationGroup(["('01','02')('10','20')('11','22')('12','21')"]) - sage: A.is_isomorphic(A_target) # needs sage.combinat + sage: A.is_isomorphic(A_target) True The labeling is correct:: @@ -23142,19 +23164,21 @@ def automorphism_group(self, partition=None, verbosity=0, We check that the representations of the groups returned with ``'sage'`` and ``'bliss'`` are the same (:trac:`27571`):: - sage: G = graphs.PaleyGraph(9) # needs sage.libs.pari - sage: a1 = G.automorphism_group(algorithm='sage') # needs sage.groups + sage: # needs sage.groups sage.libs.pari + sage: G = graphs.PaleyGraph(9) + sage: a1 = G.automorphism_group(algorithm='sage') sage: V = sorted(G, reverse=True) - sage: a2 = G.automorphism_group(algorithm='sage', partition=[V]) # needs sage.groups - sage: a1.is_isomorphic(a2) # needs sage.groups + sage: a2 = G.automorphism_group(algorithm='sage', partition=[V]) + sage: a1.is_isomorphic(a2) True - sage: str(a1) == str(a2) # needs sage.groups + sage: str(a1) == str(a2) False sage: b1 = G.automorphism_group(algorithm='bliss') # optional - bliss - sage: str(a1) == str(b1) # optional - bliss # needs sage.groups + sage: str(a1) == str(b1) # optional - bliss True - sage: b2 = G.automorphism_group(algorithm='bliss', partition=[V]) # optional - bliss - sage: str(a2) == str(b2) # optional - bliss # needs sage.groups + sage: b2 = G.automorphism_group(algorithm='bliss', # optional - bliss + ....: partition=[V]) + sage: str(a2) == str(b2) # optional - bliss True """ from sage.features.bliss import Bliss diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 0f207ffb1ee..30a63bff8a7 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -3869,13 +3869,15 @@ def coloring(self, algorithm="DLX", hex_colors=False, solver=None, verbose=0, True sage: are_equal_colorings(P, Q) True - sage: G.plot(partition=P) # needs sage.plot + + sage: # needs sage.plot + sage: G.plot(partition=P) Graphics object consisting of 16 graphics primitives - sage: G.coloring(hex_colors=True, algorithm="MILP") # needs sage.plot + sage: G.coloring(hex_colors=True, algorithm="MILP") {'#0000ff': [4], '#00ff00': [0, 6, 5], '#ff0000': [2, 1, 3]} - sage: H = G.coloring(hex_colors=True, algorithm="DLX"); H # needs sage.plot + sage: H = G.coloring(hex_colors=True, algorithm="DLX"); H {'#0000ff': [4], '#00ff00': [1, 2, 3], '#ff0000': [0, 5, 6]} - sage: G.plot(vertex_colors=H) # needs sage.plot + sage: G.plot(vertex_colors=H) Graphics object consisting of 16 graphics primitives .. PLOT:: @@ -7486,20 +7488,22 @@ def cliques_vertex_clique_number(self, algorithm="cliquer", vertices=None, EXAMPLES:: sage: C = Graph('DJ{') - sage: C.cliques_vertex_clique_number() # needs sage.plot + sage: C.cliques_vertex_clique_number() {0: 2, 1: 4, 2: 4, 3: 4, 4: 4} sage: E = C.cliques_maximal(); E [[0, 4], [1, 2, 3, 4]] - sage: C.cliques_vertex_clique_number(cliques=E, algorithm="networkx") # needs networkx sage.plot + sage: C.cliques_vertex_clique_number(cliques=E, algorithm="networkx") # needs networkx {0: 2, 1: 4, 2: 4, 3: 4, 4: 4} + sage: F = graphs.Grid2dGraph(2,3) - sage: F.cliques_vertex_clique_number(algorithm="networkx") # needs networkx sage.plot + sage: F.cliques_vertex_clique_number(algorithm="networkx") # needs networkx {(0, 0): 2, (0, 1): 2, (0, 2): 2, (1, 0): 2, (1, 1): 2, (1, 2): 2} - sage: F.cliques_vertex_clique_number(vertices=[(0, 1), (1, 2)]) # needs sage.plot + sage: F.cliques_vertex_clique_number(vertices=[(0, 1), (1, 2)]) {(0, 1): 2, (1, 2): 2} + sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]}) sage: G.show(figsize=[2,2]) # needs sage.plot - sage: G.cliques_vertex_clique_number() # needs sage.plot + sage: G.cliques_vertex_clique_number() {0: 3, 1: 3, 2: 3, 3: 3} """ if algorithm == "cliquer": diff --git a/src/sage/graphs/graph_coloring.pyx b/src/sage/graphs/graph_coloring.pyx index 8360f71bfca..f11bc3c4a05 100644 --- a/src/sage/graphs/graph_coloring.pyx +++ b/src/sage/graphs/graph_coloring.pyx @@ -1381,48 +1381,49 @@ def edge_coloring(g, value_only=False, vizing=False, hex_colors=False, solver=No The Petersen graph has chromatic index 4:: - sage: from sage.graphs.graph_coloring import edge_coloring - sage: g = graphs.PetersenGraph() - sage: edge_coloring(g, value_only=True, solver='GLPK') # needs sage.numerical.mip - 4 - sage: color_classes = edge_coloring(g, value_only=False, solver='GLPK') # needs sage.numerical.mip - sage: len(color_classes) # needs sage.numerical.mip - 4 - sage: len(set(frozenset(e) for C in color_classes for e in C)) == g.size() # needs sage.numerical.mip - True - sage: all(g.has_edge(e) for C in color_classes for e in C) # needs sage.numerical.mip - True - sage: all(len(Graph(C).matching()) == len(C) for C in color_classes) # needs networkx sage.numerical.mip - True - sage: color_classes = edge_coloring(g, value_only=False, # needs sage.numerical.mip - ....: hex_colors=True, solver='GLPK') - sage: sorted(color_classes.keys()) # needs sage.numerical.mip - ['#00ffff', '#7f00ff', '#7fff00', '#ff0000'] + sage: # needs sage.numerical.mip + sage: from sage.graphs.graph_coloring import edge_coloring + sage: g = graphs.PetersenGraph() + sage: edge_coloring(g, value_only=True, solver='GLPK') + 4 + sage: color_classes = edge_coloring(g, value_only=False, solver='GLPK') + sage: len(color_classes) + 4 + sage: len(set(frozenset(e) for C in color_classes for e in C)) == g.size() + True + sage: all(g.has_edge(e) for C in color_classes for e in C) + True + sage: all(len(Graph(C).matching()) == len(C) for C in color_classes) # needs networkx + True + sage: color_classes = edge_coloring(g, value_only=False, + ....: hex_colors=True, solver='GLPK') + sage: sorted(color_classes.keys()) + ['#00ffff', '#7f00ff', '#7fff00', '#ff0000'] Complete graphs are colored using the linear-time round-robin coloring:: - sage: from sage.graphs.graph_coloring import edge_coloring - sage: len(edge_coloring(graphs.CompleteGraph(20))) # needs sage.numerical.mip - 19 + sage: from sage.graphs.graph_coloring import edge_coloring + sage: len(edge_coloring(graphs.CompleteGraph(20))) # needs sage.numerical.mip + 19 The chromatic index of a non connected graph is the maximum over its connected components:: - sage: g = graphs.CompleteGraph(4) + graphs.CompleteGraph(10) - sage: edge_coloring(g, value_only=True) # needs sage.numerical.mip - 9 + sage: g = graphs.CompleteGraph(4) + graphs.CompleteGraph(10) + sage: edge_coloring(g, value_only=True) # needs sage.numerical.mip + 9 TESTS: Graph without edge:: - sage: g = Graph(2) - sage: edge_coloring(g) # needs sage.numerical.mip - [] - sage: edge_coloring(g, value_only=True) # needs sage.numerical.mip - 0 - sage: edge_coloring(g, hex_colors=True) # needs sage.numerical.mip - {} + sage: g = Graph(2) + sage: edge_coloring(g) # needs sage.numerical.mip + [] + sage: edge_coloring(g, value_only=True) # needs sage.numerical.mip + 0 + sage: edge_coloring(g, hex_colors=True) # needs sage.numerical.mip + {} """ g._scream_if_not_simple() diff --git a/src/sage/graphs/graph_decompositions/vertex_separation.pyx b/src/sage/graphs/graph_decompositions/vertex_separation.pyx index c3e2948e9d6..19a1e07ba2e 100644 --- a/src/sage/graphs/graph_decompositions/vertex_separation.pyx +++ b/src/sage/graphs/graph_decompositions/vertex_separation.pyx @@ -766,13 +766,16 @@ 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) # needs sage.combinat - sage: vs,L = vertex_separation(G, algorithm="BAB"); vs # needs sage.combinat + + sage: # needs sage.combinat + sage: G = digraphs.DeBruijn(2,3) + sage: vs,L = vertex_separation(G, algorithm="BAB"); vs 2 - sage: vs,L = vertex_separation(G, algorithm="exponential"); vs # needs sage.combinat + sage: vs,L = vertex_separation(G, algorithm="exponential"); vs 2 - sage: vs,L = vertex_separation(G, algorithm="MILP"); vs # needs sage.combinat sage.numerical.mip + sage: vs,L = vertex_separation(G, algorithm="MILP"); vs # needs sage.numerical.mip 2 + sage: G = graphs.Grid2dGraph(3,3) sage: vs,L = vertex_separation(G, algorithm="BAB"); vs 3 diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index 12e80870fc2..f1d53f31e95 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -1239,12 +1239,13 @@ def cospectral_graphs(self, vertices, matrix_function=lambda g: g.adjacency_matr There are two sets of cospectral graphs on six vertices with no isolated vertices:: - sage: g = graphs.cospectral_graphs(6, graphs=lambda x: min(x.degree())>0) # needs sage.modules - sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) # needs sage.modules + sage: # needs sage.modules + sage: g = graphs.cospectral_graphs(6, graphs=lambda x: min(x.degree())>0) + sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) [['Ep__', 'Er?G'], ['ExGg', 'ExoG']] - sage: g[0][1].am().charpoly()==g[0][1].am().charpoly() # needs sage.modules + sage: g[0][1].am().charpoly()==g[0][1].am().charpoly() True - sage: g[1][1].am().charpoly()==g[1][1].am().charpoly() # needs sage.modules + sage: g[1][1].am().charpoly()==g[1][1].am().charpoly() True There is one pair of cospectral trees on eight vertices:: @@ -1258,12 +1259,13 @@ def cospectral_graphs(self, vertices, matrix_function=lambda g: g.adjacency_matr There are two sets of cospectral graphs (with respect to the Laplacian matrix) on six vertices:: - sage: g = graphs.cospectral_graphs(6, matrix_function=lambda g: g.laplacian_matrix()) # needs sage.modules - sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) # needs sage.modules + sage: # needs sage.modules + sage: g = graphs.cospectral_graphs(6, matrix_function=lambda g: g.laplacian_matrix()) + sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) [['Edq_', 'ErcG'], ['Exoo', 'EzcG']] - sage: g[0][1].laplacian_matrix().charpoly()==g[0][1].laplacian_matrix().charpoly() # needs sage.modules + sage: g[0][1].laplacian_matrix().charpoly()==g[0][1].laplacian_matrix().charpoly() True - sage: g[1][1].laplacian_matrix().charpoly()==g[1][1].laplacian_matrix().charpoly() # needs sage.modules + sage: g[1][1].laplacian_matrix().charpoly()==g[1][1].laplacian_matrix().charpoly() True To find cospectral graphs with respect to the normalized @@ -1463,11 +1465,12 @@ def fullerenes(self, order, ipr=False): The unique fullerene graph on 20 vertices is isomorphic to the dodecahedron graph. :: - sage: gen = graphs.fullerenes(20) # optional buckygen - sage: g = next(gen) # optional buckygen - sage: g.is_isomorphic(graphs.DodecahedralGraph()) # optional buckygen + sage: # optional - buckygen + sage: gen = graphs.fullerenes(20) + sage: g = next(gen) + sage: g.is_isomorphic(graphs.DodecahedralGraph()) True - sage: g.get_embedding() # optional buckygen + sage: g.get_embedding() {1: [2, 3, 4], 2: [1, 5, 6], 3: [1, 7, 8], @@ -1488,7 +1491,7 @@ def fullerenes(self, order, ipr=False): 18: [12, 20, 13], 19: [14, 20, 15], 20: [17, 19, 18]} - sage: g.plot3d(layout='spring') # optional buckygen + sage: g.plot3d(layout='spring') Graphics3d Object """ # number of vertices should be positive @@ -1741,12 +1744,13 @@ def plantri_gen(self, options=""): (usually inside a loop). Or it can be used to create an entire list all at once if there is sufficient memory to contain it:: - sage: gen = graphs.plantri_gen("6") # optional plantri - sage: next(gen) # optional plantri + sage: # optional - plantri + sage: gen = graphs.plantri_gen("6") + sage: next(gen) Graph on 6 vertices - sage: next(gen) # optional plantri + sage: next(gen) Graph on 6 vertices - sage: next(gen) # optional plantri + sage: next(gen) Traceback (most recent call last): ... StopIteration @@ -1915,13 +1919,14 @@ def planar_graphs(self, order, minimum_degree=None, Specifying lower and upper bounds on the number of edges:: - sage: len(list(graphs.planar_graphs(4))) # optional plantri + sage: # optional - plantri + sage: len(list(graphs.planar_graphs(4))) 6 - sage: len(list(graphs.planar_graphs(4, minimum_edges=4))) # optional plantri + sage: len(list(graphs.planar_graphs(4, minimum_edges=4))) 4 - sage: len(list(graphs.planar_graphs(4, maximum_edges=4))) # optional plantri + sage: len(list(graphs.planar_graphs(4, maximum_edges=4))) 4 - sage: len(list(graphs.planar_graphs(4, minimum_edges=4, maximum_edges=4))) # optional plantri + sage: len(list(graphs.planar_graphs(4, minimum_edges=4, maximum_edges=4))) 2 Specifying the maximum size of a face:: @@ -1936,11 +1941,12 @@ def planar_graphs(self, order, minimum_degree=None, The number of edges in a planar graph is equal to the number of edges in its dual:: - sage: planar = list(graphs.planar_graphs(5,dual=True)) # optional -- plantri - sage: dual_planar = list(graphs.planar_graphs(5,dual=False)) # optional -- plantri - sage: planar_sizes = [g.size() for g in planar] # optional -- plantri - sage: dual_planar_sizes = [g.size() for g in dual_planar] # optional -- plantri - sage: planar_sizes == dual_planar_sizes # optional -- plantri + sage: # optional - plantri + sage: planar = list(graphs.planar_graphs(5,dual=True)) + sage: dual_planar = list(graphs.planar_graphs(5,dual=False)) + sage: planar_sizes = [g.size() for g in planar] + sage: dual_planar_sizes = [g.size() for g in dual_planar] + sage: planar_sizes == dual_planar_sizes True """ if order < 0: @@ -2262,11 +2268,12 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None The cube is the only 3-connected planar quadrangulation on 8 vertices:: - sage: gen = graphs.quadrangulations(8, minimum_connectivity=3) # optional plantri - sage: g = next(gen) # optional plantri - sage: g.is_isomorphic(graphs.CubeGraph(3)) # optional plantri + sage: # optional - plantri + sage: gen = graphs.quadrangulations(8, minimum_connectivity=3) + sage: g = next(gen) + sage: g.is_isomorphic(graphs.CubeGraph(3)) True - sage: next(gen) # optional plantri + sage: next(gen) Traceback (most recent call last): ... StopIteration diff --git a/src/sage/graphs/graph_input.py b/src/sage/graphs/graph_input.py index e46a2156809..193afc9c4eb 100644 --- a/src/sage/graphs/graph_input.py +++ b/src/sage/graphs/graph_input.py @@ -613,113 +613,121 @@ def from_networkx_graph(G, gnx, weighted=None, loops=None, multiedges=None, Feeding a :class:`Graph` with a NetworkX ``Graph``:: + sage: # needs networkx sage: from sage.graphs.graph_input import from_networkx_graph - sage: import networkx # needs networkx + sage: import networkx sage: G = Graph() - sage: _ = gnx = networkx.Graph() # needs networkx - sage: _ = gnx.add_edge(0, 1) # needs networkx - sage: _ = gnx.add_edge(1, 2) # needs networkx - sage: from_networkx_graph(G, gnx) # needs networkx - sage: G.edges(sort=True, labels=False) # needs networkx + sage: _ = gnx = networkx.Graph() + sage: _ = gnx.add_edge(0, 1) + sage: _ = gnx.add_edge(1, 2) + sage: from_networkx_graph(G, gnx) + sage: G.edges(sort=True, labels=False) [(0, 1), (1, 2)] Feeding a :class:`Graph` with a NetworkX ``MultiGraph``:: + sage: # needs networkx sage: G = Graph() - sage: gnx = networkx.MultiGraph() # needs networkx - sage: _ = gnx.add_edge(0, 1) # needs networkx - sage: _ = gnx.add_edge(0, 1) # needs networkx - sage: from_networkx_graph(G, gnx) # needs networkx - sage: G.edges(sort=True, labels=False) # needs networkx + sage: gnx = networkx.MultiGraph() + sage: _ = gnx.add_edge(0, 1) + sage: _ = gnx.add_edge(0, 1) + sage: from_networkx_graph(G, gnx) + sage: G.edges(sort=True, labels=False) [(0, 1), (0, 1)] sage: G = Graph() - sage: from_networkx_graph(G, gnx, multiedges=False) # needs networkx - sage: G.edges(sort=True, labels=False) # needs networkx + sage: from_networkx_graph(G, gnx, multiedges=False) + sage: G.edges(sort=True, labels=False) [(0, 1)] When feeding a :class:`Graph` `G` with a NetworkX ``DiGraph`` `D`, `G` has one edge `(u, v)` whenever `D` has arc `(u, v)` or `(v, u)` or both:: + sage: # needs networkx sage: G = Graph() - sage: D = networkx.DiGraph() # needs networkx - sage: _ = D.add_edge(0, 1) # needs networkx - sage: from_networkx_graph(G, D) # needs networkx - sage: G.edges(sort=True, labels=False) # needs networkx + sage: D = networkx.DiGraph() + sage: _ = D.add_edge(0, 1) + sage: from_networkx_graph(G, D) + sage: G.edges(sort=True, labels=False) [(0, 1)] sage: G = Graph() - sage: _ = D.add_edge(1, 0) # needs networkx - sage: from_networkx_graph(G, D) # needs networkx - sage: G.edges(sort=True, labels=False) # needs networkx + sage: _ = D.add_edge(1, 0) + sage: from_networkx_graph(G, D) + sage: G.edges(sort=True, labels=False) [(0, 1)] When feeding a :class:`Graph` `G` with a NetworkX ``MultiDiGraph`` `D`, the number of edges between `u` and `v` in `G` is the maximum between the number of arcs `(u, v)` and the number of arcs `(v, u)` in D`:: + sage: # needs networkx sage: G = Graph() - sage: D = networkx.MultiDiGraph() # needs networkx - sage: _ = D.add_edge(0, 1) # needs networkx - sage: _ = D.add_edge(1, 0) # needs networkx - sage: _ = D.add_edge(1, 0) # needs networkx - sage: D.edges() # needs networkx + sage: D = networkx.MultiDiGraph() + sage: _ = D.add_edge(0, 1) + sage: _ = D.add_edge(1, 0) + sage: _ = D.add_edge(1, 0) + sage: D.edges() OutMultiEdgeDataView([(0, 1), (1, 0), (1, 0)]) - sage: from_networkx_graph(G, D) # needs networkx - sage: G.edges(sort=True, labels=False) # needs networkx + sage: from_networkx_graph(G, D) + sage: G.edges(sort=True, labels=False) [(0, 1), (0, 1)] Feeding a :class:`DiGraph` with a NetworkX ``DiGraph``:: + sage: # needs networkx sage: from sage.graphs.graph_input import from_networkx_graph - sage: import networkx # needs networkx + sage: import networkx sage: G = DiGraph() - sage: _ = gnx = networkx.DiGraph() # needs networkx - sage: _ = gnx.add_edge(0, 1) # needs networkx - sage: _ = gnx.add_edge(1, 2) # needs networkx - sage: from_networkx_graph(G, gnx) # needs networkx - sage: G.edges(sort=True, labels=False) # needs networkx + sage: _ = gnx = networkx.DiGraph() + sage: _ = gnx.add_edge(0, 1) + sage: _ = gnx.add_edge(1, 2) + sage: from_networkx_graph(G, gnx) + sage: G.edges(sort=True, labels=False) [(0, 1), (1, 2)] Feeding a :class:`DiGraph` with a NetworkX ``MultiDiGraph``:: + sage: # needs networkx sage: G = DiGraph() - sage: gnx = networkx.MultiDiGraph() # needs networkx - sage: _ = gnx.add_edge(0, 1) # needs networkx - sage: _ = gnx.add_edge(0, 1) # needs networkx - sage: from_networkx_graph(G, gnx) # needs networkx - sage: G.edges(sort=True, labels=False) # needs networkx + sage: gnx = networkx.MultiDiGraph() + sage: _ = gnx.add_edge(0, 1) + sage: _ = gnx.add_edge(0, 1) + sage: from_networkx_graph(G, gnx) + sage: G.edges(sort=True, labels=False) [(0, 1), (0, 1)] sage: G = DiGraph() - sage: from_networkx_graph(G, gnx, multiedges=False) # needs networkx - sage: G.edges(sort=True, labels=False) # needs networkx + sage: from_networkx_graph(G, gnx, multiedges=False) + sage: G.edges(sort=True, labels=False) [(0, 1)] When feeding a :class:`DiGraph` `G` with a NetworkX ``Graph`` `H`, `G` has both arcs `(u, v)` and `(v, u)` if `G` has edge `(u, v)`:: + sage: # needs networkx sage: G = DiGraph() - sage: H = networkx.Graph() # needs networkx - sage: _ = H.add_edge(0, 1) # needs networkx - sage: from_networkx_graph(G, H) # needs networkx - sage: G.edges(labels=False, sort=True) # needs networkx + sage: H = networkx.Graph() + sage: _ = H.add_edge(0, 1) + sage: from_networkx_graph(G, H) + sage: G.edges(labels=False, sort=True) [(0, 1), (1, 0)] When feeding a :class:`DiGraph` `G` with a NetworkX ``MultiGraph`` `H`, `G` has `k` arcs `(u, v)` and `k` arcs `(v, u)` if `H` has `k` edges `(u, v)`, unless parameter ``multiedges`` is set to ``False``:: + sage: # needs networkx sage: G = DiGraph() - sage: H = networkx.MultiGraph() # needs networkx - sage: _ = H.add_edge(0, 1) # needs networkx - sage: _ = H.add_edge(0, 1) # needs networkx - sage: _ = H.add_edge(0, 1) # needs networkx - sage: H.edges() # needs networkx + sage: H = networkx.MultiGraph() + sage: _ = H.add_edge(0, 1) + sage: _ = H.add_edge(0, 1) + sage: _ = H.add_edge(0, 1) + sage: H.edges() MultiEdgeDataView([(0, 1), (0, 1), (0, 1)]) - sage: from_networkx_graph(G, H) # needs networkx - sage: G.edges(labels=False, sort=True) # needs networkx + sage: from_networkx_graph(G, H) + sage: G.edges(labels=False, sort=True) [(0, 1), (0, 1), (0, 1), (1, 0), (1, 0), (1, 0)] sage: G = DiGraph() - sage: from_networkx_graph(G, H, multiedges=False) # needs networkx - sage: G.edges(labels=False, sort=True) # needs networkx + sage: from_networkx_graph(G, H, multiedges=False) + sage: G.edges(labels=False, sort=True) [(0, 1), (1, 0)] TESTS: diff --git a/src/sage/graphs/graph_latex.py b/src/sage/graphs/graph_latex.py index 7988f6e3518..e495ca160a4 100644 --- a/src/sage/graphs/graph_latex.py +++ b/src/sage/graphs/graph_latex.py @@ -84,12 +84,12 @@ sage: H = graphs.HeawoodGraph() sage: H.set_latex_options( - ....: graphic_size=(5,5), - ....: vertex_size=0.2, - ....: edge_thickness=0.04, - ....: edge_color='green', - ....: vertex_color='green', - ....: vertex_label_color='red' + ....: graphic_size=(5,5), + ....: vertex_size=0.2, + ....: edge_thickness=0.04, + ....: edge_color='green', + ....: vertex_color='green', + ....: vertex_label_color='red' ....: ) At this point, ``view(H)`` should call ``pdflatex`` to process the string @@ -265,49 +265,50 @@ package. So it is worth viewing this in the notebook to see the effects of various defaults and choices.:: - sage: var('x y u w') # needs sage.symbolic + sage: # needs sage.symbolic + sage: var('x y u w') (x, y, u, w) sage: G = Graph(loops=True) - sage: for i in range(5): # needs sage.symbolic + sage: for i in range(5): ....: for j in range(i+1, 5): ....: G.add_edge((i, j), label=(x^i*y^j).expand()) - sage: G.add_edge((0,0), label=sin(u)) # needs sage.symbolic - sage: G.add_edge((4,4), label=w^5) # needs sage.symbolic + sage: G.add_edge((0,0), label=sin(u)) + sage: G.add_edge((4,4), label=w^5) sage: G.set_pos(G.layout_circular()) sage: G.set_latex_options( - ....: units='in', - ....: graphic_size=(8,8), - ....: margins=(1,2,2,1), - ....: scale=0.5, - ....: vertex_color='0.8', - ....: vertex_colors={1:'aqua', 3:'y', 4:'#0000FF'}, - ....: vertex_fill_color='blue', - ....: vertex_fill_colors={1:'green', 3:'b', 4:'#FF00FF'}, - ....: vertex_label_color='brown', - ....: vertex_label_colors={0:'g',1:'purple',2:'#007F00'}, - ....: vertex_shape='diamond', - ....: vertex_shapes={1:'rectangle', 2:'sphere', 3:'sphere', 4:'circle'}, - ....: vertex_size=0.3, - ....: vertex_sizes={0:1.0, 2:0.3, 4:1.0}, - ....: vertex_label_placements = {2:(0.6, 180), 4:(0,45)}, - ....: edge_color='purple', - ....: edge_colors={(0,2):'g',(3,4):'red'}, - ....: edge_fills=True, - ....: edge_fill_color='green', - ....: edge_label_colors={(2,3):'y',(0,4):'blue'}, - ....: edge_thickness=0.05, - ....: edge_thicknesses={(3,4):0.2, (0,4):0.02}, - ....: edge_labels=True, - ....: edge_label_sloped=True, - ....: edge_label_slopes={(0,3):False, (2,4):False}, - ....: edge_label_placement=0.50, - ....: edge_label_placements={(0,4):'above', (2,3):'left', (0,0):'above', (4,4):'below'}, - ....: loop_placement=(2.0, 'NO'), - ....: loop_placements={4:(8.0, 'EA')} + ....: units='in', + ....: graphic_size=(8,8), + ....: margins=(1,2,2,1), + ....: scale=0.5, + ....: vertex_color='0.8', + ....: vertex_colors={1:'aqua', 3:'y', 4:'#0000FF'}, + ....: vertex_fill_color='blue', + ....: vertex_fill_colors={1:'green', 3:'b', 4:'#FF00FF'}, + ....: vertex_label_color='brown', + ....: vertex_label_colors={0:'g',1:'purple',2:'#007F00'}, + ....: vertex_shape='diamond', + ....: vertex_shapes={1:'rectangle', 2:'sphere', 3:'sphere', 4:'circle'}, + ....: vertex_size=0.3, + ....: vertex_sizes={0:1.0, 2:0.3, 4:1.0}, + ....: vertex_label_placements = {2:(0.6, 180), 4:(0,45)}, + ....: edge_color='purple', + ....: edge_colors={(0,2):'g',(3,4):'red'}, + ....: edge_fills=True, + ....: edge_fill_color='green', + ....: edge_label_colors={(2,3):'y',(0,4):'blue'}, + ....: edge_thickness=0.05, + ....: edge_thicknesses={(3,4):0.2, (0,4):0.02}, + ....: edge_labels=True, + ....: edge_label_sloped=True, + ....: edge_label_slopes={(0,3):False, (2,4):False}, + ....: edge_label_placement=0.50, + ....: edge_label_placements={(0,4):'above', (2,3):'left', (0,0):'above', (4,4):'below'}, + ....: loop_placement=(2.0, 'NO'), + ....: loop_placements={4:(8.0, 'EA')} ....: ) sage: from sage.graphs.graph_latex import check_tkz_graph sage: check_tkz_graph() # random - depends on TeX installation - sage: print(latex(G)) # needs sage.symbolic + sage: print(latex(G)) \begin{tikzpicture} \definecolor{cv0}{rgb}{0.8,0.8,0.8} \definecolor{cfv0}{rgb}{0.0,0.0,1.0} diff --git a/src/sage/graphs/graph_plot_js.py b/src/sage/graphs/graph_plot_js.py index a29e7293df8..3bcabb58152 100644 --- a/src/sage/graphs/graph_plot_js.py +++ b/src/sage/graphs/graph_plot_js.py @@ -164,15 +164,15 @@ def gen_html_code(G, EXAMPLES:: - sage: graphs.RandomTree(50).show(method="js") # optional -- internet sage.plot + sage: graphs.RandomTree(50).show(method="js") # optional - internet, needs sage.plot sage: g = graphs.PetersenGraph() - sage: g.show(method="js", vertex_partition=g.coloring()) # optional -- internet sage.plot + sage: g.show(method="js", vertex_partition=g.coloring()) # optional - internet, needs sage.plot - sage: graphs.DodecahedralGraph().show(method="js", # optional -- internet sage.plot + sage: graphs.DodecahedralGraph().show(method="js", # optional - internet, needs sage.plot ....: force_spring_layout=True) - sage: graphs.DodecahedralGraph().show(method="js") # optional -- internet sage.plot + sage: graphs.DodecahedralGraph().show(method="js") # optional - internet, needs sage.plot sage: # needs sage.combinat sage: g = digraphs.DeBruijn(2, 2) @@ -182,7 +182,7 @@ def gen_html_code(G, 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, + sage: g.show(method="js", vertex_labels=True, edge_labels=True, # optional - internet, needs 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/path_enumeration.pyx b/src/sage/graphs/path_enumeration.pyx index 50836ffdcb9..5709d2b87c4 100644 --- a/src/sage/graphs/path_enumeration.pyx +++ b/src/sage/graphs/path_enumeration.pyx @@ -346,41 +346,49 @@ def shortest_simple_paths(self, source, target, weight_function=None, EXAMPLES:: - sage: g = DiGraph([(1, 2, 20), (1, 3, 10), (1, 4, 30), (2, 5, 20), (3, 5, 10), (4, 5, 30)]) + sage: g = DiGraph([(1, 2, 20), (1, 3, 10), (1, 4, 30), + ....: (2, 5, 20), (3, 5, 10), (4, 5, 30)]) sage: list(g.shortest_simple_paths(1, 5, by_weight=True, algorithm="Yen")) [[1, 3, 5], [1, 2, 5], [1, 4, 5]] sage: list(g.shortest_simple_paths(1, 5, algorithm="Yen")) [[1, 2, 5], [1, 3, 5], [1, 4, 5]] sage: list(g.shortest_simple_paths(1, 1)) [[1]] - sage: list(g.shortest_simple_paths(1, 5, by_weight=True, report_edges=True, report_weight=True, labels=True)) + sage: list(g.shortest_simple_paths(1, 5, by_weight=True, + ....: report_edges=True, report_weight=True, labels=True)) [(20, [(1, 3, 10), (3, 5, 10)]), (40, [(1, 2, 20), (2, 5, 20)]), (60, [(1, 4, 30), (4, 5, 30)])] - sage: list(g.shortest_simple_paths(1, 5, by_weight=True, algorithm="Feng", report_edges=True, report_weight=True)) + sage: list(g.shortest_simple_paths(1, 5, by_weight=True, algorithm="Feng", + ....: report_edges=True, report_weight=True)) [(20, [(1, 3), (3, 5)]), (40, [(1, 2), (2, 5)]), (60, [(1, 4), (4, 5)])] sage: list(g.shortest_simple_paths(1, 5, report_edges=True, report_weight=True)) [(2, [(1, 4), (4, 5)]), (2, [(1, 3), (3, 5)]), (2, [(1, 2), (2, 5)])] sage: list(g.shortest_simple_paths(1, 5, by_weight=True, report_edges=True)) [[(1, 3), (3, 5)], [(1, 2), (2, 5)], [(1, 4), (4, 5)]] - sage: list(g.shortest_simple_paths(1, 5, by_weight=True, algorithm="Feng", report_edges=True, labels=True)) + sage: list(g.shortest_simple_paths(1, 5, by_weight=True, algorithm="Feng", + ....: report_edges=True, labels=True)) [[(1, 3, 10), (3, 5, 10)], [(1, 2, 20), (2, 5, 20)], [(1, 4, 30), (4, 5, 30)]] - sage: g = Graph([(1, 2, 20), (1, 3, 10), (1, 4, 30), (2, 5, 20), (3, 5, 10), (4, 5, 30), (1, 6, 100), (5, 6, 5)]) + sage: g = Graph([(1, 2, 20), (1, 3, 10), (1, 4, 30), (2, 5, 20), + ....: (3, 5, 10), (4, 5, 30), (1, 6, 100), (5, 6, 5)]) sage: list(g.shortest_simple_paths(1, 6, by_weight = True)) [[1, 3, 5, 6], [1, 2, 5, 6], [1, 4, 5, 6], [1, 6]] sage: list(g.shortest_simple_paths(1, 6, algorithm="Yen")) [[1, 6], [1, 2, 5, 6], [1, 3, 5, 6], [1, 4, 5, 6]] - sage: list(g.shortest_simple_paths(1, 6, report_edges=True, report_weight=True, labels=True)) + sage: list(g.shortest_simple_paths(1, 6, + ....: report_edges=True, report_weight=True, labels=True)) [(1, [(1, 6, 100)]), (3, [(1, 2, 20), (2, 5, 20), (5, 6, 5)]), (3, [(1, 3, 10), (3, 5, 10), (5, 6, 5)]), (3, [(1, 4, 30), (4, 5, 30), (5, 6, 5)])] - sage: list(g.shortest_simple_paths(1, 6, report_edges=True, report_weight=True, labels=True, by_weight=True)) + sage: list(g.shortest_simple_paths(1, 6, by_weight=True, + ....: report_edges=True, report_weight=True, labels=True)) [(25, [(1, 3, 10), (3, 5, 10), (5, 6, 5)]), (45, [(1, 2, 20), (2, 5, 20), (5, 6, 5)]), (65, [(1, 4, 30), (4, 5, 30), (5, 6, 5)]), (100, [(1, 6, 100)])] - sage: list(g.shortest_simple_paths(1, 6, report_edges=True, labels=True, by_weight=True)) + sage: list(g.shortest_simple_paths(1, 6, by_weight=True, + ....: report_edges=True, labels=True)) [[(1, 3, 10), (3, 5, 10), (5, 6, 5)], [(1, 2, 20), (2, 5, 20), (5, 6, 5)], [(1, 4, 30), (4, 5, 30), (5, 6, 5)], @@ -432,6 +440,8 @@ def shortest_simple_paths(self, source, target, weight_function=None, [1, 2, 3, 4, 5], [1, 6, 9, 3, 4, 5], [1, 6, 9, 11, 10, 5]] + + sage: # needs sage.combinat sage: G = digraphs.DeBruijn(2, 3) # needs sage.combinat sage: for u,v in G.edges(sort=True, labels=False): # needs sage.combinat ....: G.set_edge_label(u, v, 1) @@ -470,6 +480,7 @@ def shortest_simple_paths(self, source, target, weight_function=None, Check for consistency of results of Yen's and Feng's:: + sage: # needs sage.combinat sage: G = digraphs.DeBruijn(2, 4) # needs sage.combinat sage: s = set() sage: for p in G.shortest_simple_paths('0000', '1111', by_weight=False, algorithm='Yen'): # needs sage.combinat diff --git a/src/sage/graphs/strongly_regular_db.pyx b/src/sage/graphs/strongly_regular_db.pyx index 1c9e8699905..338d469e383 100644 --- a/src/sage/graphs/strongly_regular_db.pyx +++ b/src/sage/graphs/strongly_regular_db.pyx @@ -1428,19 +1428,20 @@ def is_GQqmqp(int v, int k, int l, int mu): TESTS:: + sage: # needs sage.libs.pari sage: (S,T) = (127,129) - sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t # needs sage.libs.pari + sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t (, 128, False) sage: (S,T) = (129,127) - sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t # needs sage.libs.pari + sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t (, 128, True) sage: (S,T) = (124,126) - sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t # needs sage.libs.pari + sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t (, 125, False) sage: (S,T) = (126,124) - sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t # needs sage.libs.pari + sage: t = is_GQqmqp((S+1)*(S*T+1), S*(T+1), S-1, T+1); t (, 125, True) - sage: t = is_GQqmqp(5,5,5,5); t # needs sage.libs.pari + sage: t = is_GQqmqp(5,5,5,5); t """ # do we have GQ(s,t)? we must have mu=t+1, s=l+1, # v=(s+1)(st+1), k=s(t+1) From abdcae83dd7aef72ba6f71ecfe82e3db05801b71 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 2 Aug 2023 17:54:16 -0700 Subject: [PATCH 09/10] sage.graphs: Use yet more block # needs --- .../graphs/generators/classical_geometries.py | 47 ++-- .../graphs/generators/distance_regular.pyx | 74 ++++--- src/sage/graphs/generators/families.py | 200 ++++++++++-------- src/sage/graphs/generators/intersection.py | 13 +- src/sage/graphs/generators/platonic_solids.py | 47 ++-- src/sage/graphs/generic_graph.py | 15 +- src/sage/graphs/path_enumeration.pyx | 22 +- 7 files changed, 224 insertions(+), 194 deletions(-) diff --git a/src/sage/graphs/generators/classical_geometries.py b/src/sage/graphs/generators/classical_geometries.py index 48481b3b240..ab928c67713 100644 --- a/src/sage/graphs/generators/classical_geometries.py +++ b/src/sage/graphs/generators/classical_geometries.py @@ -67,14 +67,8 @@ def SymplecticPolarGraph(d, q, algorithm=None): (40, 12, 2, 4) sage: O.is_isomorphic(G) False - sage: O.is_isomorphic(G) # optional - GOT (with --distribution 'sagemath-graphs[modules]') - Traceback (most recent call last): - ... - File "", line 1, in - O.is_isomorphic(G) - AttributeError: 'function' object has no attribute 'is_isomorphic' - sage: S = graphs.SymplecticPolarGraph(6,4,algorithm="gap") # not tested (long time), needs sage.libs.gap - sage: S.is_strongly_regular(parameters=True) # not tested (long time) # needs sage.libs.gap + sage: S = graphs.SymplecticPolarGraph(6, 4, algorithm="gap") # not tested (long time) + sage: S.is_strongly_regular(parameters=True) # not tested (long time) (1365, 340, 83, 85) TESTS:: @@ -273,7 +267,7 @@ def _orthogonal_polar_graph(m, q, sign="+", point_type=[0]): `NO^{-,\perp}(5,5)`:: sage: g = _orthogonal_polar_graph(5,5,point_type=[2,3]) # long time, needs sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # long time # needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # long time, needs sage.libs.gap (300, 65, 10, 15) `NO^{+,\perp}(5,5)`:: @@ -487,19 +481,22 @@ def NonisotropicOrthogonalPolarGraph(m, q, sign="+", perp=None): NO^-,perp(3, 5): Graph on 10 vertices sage: g.is_strongly_regular(parameters=True) (10, 3, 0, 1) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'+') # long time, needs sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # long time # needs sage.libs.gap + + sage: # long time, needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'+') + sage: g.is_strongly_regular(parameters=True) (117, 36, 15, 9) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'-'); g # long time + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,3,'-'); g NO^-(6, 3): Graph on 126 vertices - sage: g.is_strongly_regular(parameters=True) # long time # needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) (126, 45, 12, 18) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'-') # long time, needs sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # long time # needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'-') + sage: g.is_strongly_regular(parameters=True) (300, 104, 28, 40) - sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'+') # long time, needs sage.libs.gap - sage: g.is_strongly_regular(parameters=True) # long time # needs sage.libs.gap + sage: g = graphs.NonisotropicOrthogonalPolarGraph(5,5,'+') + sage: g.is_strongly_regular(parameters=True) (325, 144, 68, 60) + sage: g = graphs.NonisotropicOrthogonalPolarGraph(6,4,'+') Traceback (most recent call last): ... @@ -871,11 +868,11 @@ def TaylorTwographDescendantSRG(q, clique_partition=False): sage: g.is_strongly_regular(parameters=True) (27, 10, 1, 5) sage: from sage.combinat.designs.twographs import taylor_twograph - sage: T = taylor_twograph(3) # long time # needs sage.rings.finite_rings - sage: g.is_isomorphic(T.descendant(T.ground_set()[1])) # long time # needs sage.rings.finite_rings + sage: T = taylor_twograph(3) # long time + sage: g.is_isomorphic(T.descendant(T.ground_set()[1])) # long time 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:: @@ -1198,7 +1195,7 @@ def HaemersGraph(q, hyperoval=None, hyperoval_matching=None, field=None, check_h ... RuntimeError: incorrect hyperoval - sage: g = graphs.HaemersGraph(8); g # not tested (long time) # needs sage.rings.finite_rings + sage: g = graphs.HaemersGraph(8); g # not tested (long time) # needs sage.rings.finite_rings Haemers(8): Graph on 640 vertices sage: g.is_strongly_regular(parameters=True) # not tested (long time) # needs sage.rings.finite_rings (640, 71, 6, 8) @@ -1498,9 +1495,9 @@ def OrthogonalDualPolarGraph(e, d, q): sage: G.is_distance_regular(True) ([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.is_distance_regular(True) # long time ([39, 36, 27, None], [None, 1, 4, 13]) - sage: G.order() # long time + sage: G.order() # long time 1120 REFERENCES: @@ -1514,7 +1511,7 @@ def OrthogonalDualPolarGraph(e, d, q): sage: G.is_distance_regular(True) ([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.is_distance_regular(True) # long time ([28, 24, 16, None], [None, 1, 3, 7]) sage: G = graphs.OrthogonalDualPolarGraph(1,3,4) sage: G.is_distance_regular(True) diff --git a/src/sage/graphs/generators/distance_regular.pyx b/src/sage/graphs/generators/distance_regular.pyx index edcb9ad4cfa..15bd3594185 100644 --- a/src/sage/graphs/generators/distance_regular.pyx +++ b/src/sage/graphs/generators/distance_regular.pyx @@ -1418,15 +1418,16 @@ def GeneralisedOctagonGraph(const int s, const int t): EXAMPLES:: - sage: G = graphs.GeneralisedOctagonGraph(1, 4) # needs sage.libs.gap - sage: G.is_distance_regular(True) # needs sage.libs.gap - ([5, 4, 4, 4, None], [None, 1, 1, 1, 5]) - sage: G = graphs.GeneralisedOctagonGraph(2, 4) # optional - gap_packages internet - sage: G.is_distance_regular(True) # optional - gap_packages internet - ([10, 8, 8, 8, None], [None, 1, 1, 1, 5]) - sage: G = graphs.GeneralisedOctagonGraph(5, 1) # needs sage.libs.gap - sage: G.is_distance_regular(True) # needs sage.libs.gap - ([10, 5, 5, 5, None], [None, 1, 1, 1, 2]) + sage: # needs sage.libs.gap + sage: G = graphs.GeneralisedOctagonGraph(1, 4) + sage: G.is_distance_regular(True) + ([5, 4, 4, 4, None], [None, 1, 1, 1, 5]) + sage: G = graphs.GeneralisedOctagonGraph(2, 4) # optional - gap_packages internet + sage: G.is_distance_regular(True) # optional - gap_packages internet + ([10, 8, 8, 8, None], [None, 1, 1, 1, 5]) + sage: G = graphs.GeneralisedOctagonGraph(5, 1) + sage: G.is_distance_regular(True) + ([10, 5, 5, 5, None], [None, 1, 1, 1, 2]) .. NOTE:: @@ -1528,13 +1529,14 @@ def GeneralisedHexagonGraph(const int s, const int t): EXAMPLES:: + sage: # needs sage.libs.gap sage: G = graphs.GeneralisedHexagonGraph(5, 5) # optional - gap_packages internet sage: G.is_distance_regular(True) # optional - gap_packages internet ([30, 25, 25, None], [None, 1, 1, 6]) - sage: G = graphs.GeneralisedHexagonGraph(7, 1) # needs sage.libs.gap - sage: G.is_distance_regular(True) # needs sage.libs.gap + sage: G = graphs.GeneralisedHexagonGraph(7, 1) + sage: G.is_distance_regular(True) ([14, 7, 7, None], [None, 1, 1, 2]) - sage: graphs.GeneralisedHexagonGraph(1, 1) # needs sage.libs.gap + sage: graphs.GeneralisedHexagonGraph(1, 1) Cycle graph: Graph on 6 vertices .. NOTE:: @@ -1752,16 +1754,17 @@ def _line_graph_generalised_polygon(H): EXAMPLES:: - sage: from sage.graphs.generators.distance_regular import \ - ....: _line_graph_generalised_polygon - sage: G = graphs.GeneralisedHexagonGraph(1, 8) # needs sage.libs.gap - sage: H = _line_graph_generalised_polygon(G) # needs sage.libs.gap - sage: H.is_distance_regular(True) # needs sage.libs.gap - ([16, 8, 8, None], [None, 1, 1, 2]) - sage: G = graphs.GeneralisedHexagonGraph(3, 3) # optional - gap_packages internet - sage: H = _line_graph_generalised_polygon(G) # optional - gap_packages internet - sage: G.is_isomorphic(H) # optional - gap_packages internet - True + sage: # needs sage.libs.gap + sage: from sage.graphs.generators.distance_regular import \ + ....: _line_graph_generalised_polygon + sage: G = graphs.GeneralisedHexagonGraph(1, 8) + sage: H = _line_graph_generalised_polygon(G) + sage: H.is_distance_regular(True) + ([16, 8, 8, None], [None, 1, 1, 2]) + sage: G = graphs.GeneralisedHexagonGraph(3, 3) # optional - gap_packages internet + sage: H = _line_graph_generalised_polygon(G) # optional - gap_packages internet + sage: G.is_isomorphic(H) # optional - gap_packages internet + True REFERENCES: @@ -2416,19 +2419,20 @@ def is_near_polygon(array): TESTS:: + sage: # needs sage.combinat sage.libs.pari sage: from sage.graphs.generators.distance_regular import ( ....: is_near_polygon, near_polygon_graph) - sage: is_near_polygon([7, 6, 6, 4, 4, 1, 1, 3, 3, 7]) # needs sage.combinat sage.libs.pari + sage: is_near_polygon([7, 6, 6, 4, 4, 1, 1, 3, 3, 7]) (4, (2, 2)) sage: near_polygon_graph(4, (2, 2)) Double Grassmann graph (5, 2, 2): Graph on 310 vertices - sage: near_polygon_graph(*is_near_polygon([3, 2, 2, 1, 1, 3])) # needs sage.combinat sage.rings.finite_rings + sage: near_polygon_graph(*is_near_polygon([3, 2, 2, 1, 1, 3])) # needs sage.rings.finite_rings Generalised hexagon of order (1, 2): Graph on 14 vertices - sage: is_near_polygon([16, 12, 8, 4, 1, 2, 3, 4]) # needs sage.combinat sage.libs.pari + sage: is_near_polygon([16, 12, 8, 4, 1, 2, 3, 4]) (6, (4, 5)) - sage: is_near_polygon([]) # needs sage.combinat sage.libs.pari + sage: is_near_polygon([]) False - sage: is_near_polygon([25, 16, 9, 4, 1, 1, 4, 9, 16, 25]) # JohnsonGraph # needs sage.combinat sage.libs.pari + sage: is_near_polygon([25, 16, 9, 4, 1, 1, 4, 9, 16, 25]) # JohnsonGraph False """ from sage.arith.misc import is_prime_power @@ -2719,21 +2723,23 @@ def distance_regular_graph(list arr, existence=False, check=True): TESTS:: sage: graphs.distance_regular_graph([3, 2, 2, 1, 1, 1, 1, 2, 2, 3], # needs sage.combinat - ....: existence=True) + ....: existence=True) True sage: graphs.distance_regular_graph([3, 2, 2, 1, 2, 1, 1, 2, 2, 3], - ....: existence=True) + ....: existence=True) False sage: graphs.distance_regular_graph([18, 16, 16, 1, 1, 9]) # optional - internet gap_packages Generalised hexagon of order (2, 8): Graph on 819 vertices - sage: graphs.distance_regular_graph([14, 12, 10, 8, 6, 4, 2, # needs sage.combinat - ....: 1, 2, 3, 4, 5, 6, 7]) + + sage: # needs sage.combinat + sage: graphs.distance_regular_graph([14, 12, 10, 8, 6, 4, 2, + ....: 1, 2, 3, 4, 5, 6, 7]) Hamming Graph with parameters 7,3: Graph on 2187 vertices - sage: graphs.distance_regular_graph([66, 45, 28, 1, 6, 30]) # needs sage.combinat + sage: graphs.distance_regular_graph([66, 45, 28, 1, 6, 30]) Graph on 1024 vertices - sage: graphs.distance_regular_graph([6,5,5,5,1,1,1,6]) # needs sage.combinat + sage: graphs.distance_regular_graph([6,5,5,5,1,1,1,6]) Generalised octagon of order (1, 5): Graph on 312 vertices - sage: graphs.distance_regular_graph([64, 60, 1, 1, 15, 64], check=True) # needs sage.combinat + sage: graphs.distance_regular_graph([64, 60, 1, 1, 15, 64], check=True) Graph on 325 vertices """ from sage.misc.unknown import Unknown diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index dba8ec3d5c9..3ef2c3a5556 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -544,16 +544,17 @@ def BalancedTree(r, h): A tree is bipartite. If its vertex set is finite, then it is planar. :: + sage: # needs networkx sage: r = randint(2, 5); h = randint(1, 7) - sage: T = graphs.BalancedTree(r, h) # needs networkx - sage: T.is_bipartite() # needs networkx + sage: T = graphs.BalancedTree(r, h) + sage: T.is_bipartite() True - sage: T.is_planar() # needs networkx + sage: T.is_planar() True - sage: v = (r^(h + 1) - 1) / (r - 1) # needs networkx - sage: T.order() == v # needs networkx + sage: v = (r^(h + 1) - 1) / (r - 1) + sage: T.order() == v True - sage: T.size() == v - 1 # needs networkx + sage: T.size() == v - 1 True TESTS: @@ -627,11 +628,13 @@ 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) # needs sage.modules - sage: s_P = g.subgraph_search(P_n2, induced=True) # needs sage.modules - sage: K_n1.is_isomorphic(s_K) # needs sage.modules + + sage: # needs sage.modules + 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) True - sage: P_n2.is_isomorphic(s_P) # needs sage.modules + sage: P_n2.is_isomorphic(s_P) True TESTS:: @@ -1076,51 +1079,54 @@ def CirculantGraph(n, adjacency): EXAMPLES: Compare plotting using the predefined layout and networkx:: - sage: import networkx # needs networkx - sage: n = networkx.cycle_graph(23) # needs networkx - sage: spring23 = Graph(n) # needs networkx + sage: # needs networkx + sage: import networkx + sage: n = networkx.cycle_graph(23) + sage: spring23 = Graph(n) sage: posdict23 = graphs.CirculantGraph(23,2) - sage: spring23.show() # long time # needs networkx + sage: spring23.show() # long time sage: posdict23.show() # long time We next view many cycle graphs as a Sage graphics array. First we use the ``CirculantGraph`` constructor, which fills in the position dictionary:: + sage: # needs sage.plot sage: g = [] sage: j = [] sage: for i in range(9): ....: k = graphs.CirculantGraph(i+4, i+1) ....: g.append(k) - sage: for i in range(3): # needs sage.plot + sage: for i in range(3): ....: 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) # needs sage.plot - sage: G.show() # long time # needs sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time Compare to plotting with the spring-layout algorithm:: + sage: # needs networkx sage.plot sage: g = [] sage: j = [] - sage: for i in range(9): # needs networkx + sage: for i in range(9): ....: spr = networkx.cycle_graph(i+3) ....: k = Graph(spr) ....: g.append(k) - sage: for i in range(3): # needs networkx sage.plot + sage: for i in range(3): ....: 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) # needs networkx sage.plot - sage: G.show() # long time # needs networkx sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time Passing a 1 into adjacency should give the cycle. :: - sage: graphs.CirculantGraph(6,1)==graphs.CycleGraph(6) + sage: graphs.CirculantGraph(6,1) == graphs.CycleGraph(6) True sage: graphs.CirculantGraph(7,[1,3]).edges(sort=True, labels=false) [(0, 1), @@ -1187,20 +1193,21 @@ def CubeGraph(n, embedding=1): Plot several `n`-cubes in a Sage Graphics Array:: + sage: # needs sage.plot sage: g = [] sage: j = [] sage: for i in range(6): ....: k = graphs.CubeGraph(i+1) ....: g.append(k) ... - sage: for i in range(2): # needs sage.plot + sage: for i in range(2): ....: 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) # needs sage.plot - sage: G.show(figsize=[6,4]) # long time # needs sage.plot + sage: G = graphics_array(j) + sage: G.show(figsize=[6,4]) # long time Use the plot options to display larger `n`-cubes:: @@ -1438,17 +1445,18 @@ def FriendshipGraph(n): The first few friendship graphs. :: + sage: # needs sage.plot sage: A = []; B = [] sage: for i in range(9): ....: g = graphs.FriendshipGraph(i + 1) ....: A.append(g) - sage: for i in range(3): # needs sage.plot + sage: for i in range(3): ....: n = [] ....: for j in range(3): ....: n.append(A[3*i + j].plot(vertex_size=20, vertex_labels=False)) ....: B.append(n) - sage: G = graphics_array(B) # needs sage.plot - sage: G.show() # long time # needs sage.plot + sage: G = graphics_array(B) + sage: G.show() # long time For `n = 1`, the friendship graph `F_1` is isomorphic to the cycle graph `C_3`, whose visual representation is a triangle. :: @@ -2225,13 +2233,14 @@ def LCFGraph(n, shift_list, repeats): The largest cubic nonplanar graph of diameter three:: - sage: G = graphs.LCFGraph(20, [-10,-7,-5,4,7,-10,-7,-4,5,7, # needs networkx + sage: # needs networkx + 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() # needs networkx + sage: G.degree() [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3] - sage: G.diameter() # needs networkx + sage: G.diameter() 3 - sage: G.show() # long time # needs networkx sage.plot + sage: G.show() # long time # needs sage.plot PLOTTING: LCF Graphs are plotted as an n-cycle with edges in the middle, as described above. @@ -2630,14 +2639,15 @@ def SquaredSkewHadamardMatrixGraph(n): EXAMPLES:: - sage: G = graphs.SquaredSkewHadamardMatrixGraph(4) # needs sage.modules - sage: G.is_strongly_regular(parameters=True) # needs sage.modules + sage: # needs sage.modules + sage: G = graphs.SquaredSkewHadamardMatrixGraph(4) + sage: G.is_strongly_regular(parameters=True) (225, 112, 55, 56) - sage: G = graphs.SquaredSkewHadamardMatrixGraph(5) # needs sage.modules - sage: G.is_strongly_regular(parameters=True) # long time # needs sage.modules + sage: G = graphs.SquaredSkewHadamardMatrixGraph(5) + sage: G.is_strongly_regular(parameters=True) # long time (361, 180, 89, 90) - sage: G = graphs.SquaredSkewHadamardMatrixGraph(9) # needs sage.modules - sage: G.is_strongly_regular(parameters=True) # not tested # needs sage.modules + sage: G = graphs.SquaredSkewHadamardMatrixGraph(9) + sage: G.is_strongly_regular(parameters=True) # not tested (1225, 612, 305, 306) TESTS:: @@ -3187,13 +3197,14 @@ def SierpinskiGasketGraph(n): EXAMPLES:: - sage: s4 = graphs.SierpinskiGasketGraph(4); s4 # needs sage.modules + sage: # needs sage.modules + sage: s4 = graphs.SierpinskiGasketGraph(4); s4 Graph on 42 vertices - sage: s4.size() # needs sage.modules + sage: s4.size() 81 - sage: s4.degree_histogram() # needs sage.modules + sage: s4.degree_histogram() [0, 0, 3, 0, 39] - sage: s4.is_hamiltonian() # needs sage.modules + sage: s4.is_hamiltonian() True REFERENCES: @@ -3284,20 +3295,21 @@ def GeneralizedSierpinskiGraph(G, k, stretch=None): The generalized Sierpinski graph of dimension `k` of any graph `G` with `n` vertices and `m` edges has `n^k` vertices and `m\sum_{i=0}^{k-1}n^i` edges:: + sage: # needs sage.modules sage: n = randint(2, 6) sage: k = randint(1, 5) sage: G = graphs.RandomGNP(n, .5) sage: m = G.size() - sage: S = graphs.GeneralizedSierpinskiGraph(G, k) # needs sage.modules - sage: S.order() == n**k # needs sage.modules + sage: S = graphs.GeneralizedSierpinskiGraph(G, k) + sage: S.order() == n**k True - sage: S.size() == m*sum([n**i for i in range(k)]) # needs sage.modules + sage: S.size() == m*sum([n**i for i in range(k)]) True sage: G = graphs.CompleteGraph(n) - sage: S = graphs.GeneralizedSierpinskiGraph(G, k) # needs sage.modules - sage: S.order() == n**k # needs sage.modules + sage: S = graphs.GeneralizedSierpinskiGraph(G, k) + sage: S.order() == n**k True - sage: S.size() == (n*(n - 1)/2)*sum([n**i for i in range(k)]) # needs sage.modules + sage: S.size() == (n*(n - 1)/2)*sum([n**i for i in range(k)]) True The positions of the vertices of the output graph are determined from the @@ -3322,18 +3334,19 @@ def GeneralizedSierpinskiGraph(G, k, stretch=None): TESTS:: - sage: graphs.GeneralizedSierpinskiGraph(Graph(), 3) # needs sage.modules + sage: # needs sage.modules + sage: graphs.GeneralizedSierpinskiGraph(Graph(), 3) Generalized Sierpinski Graph of Graph on 0 vertices of dimension 3: Graph on 0 vertices - sage: graphs.GeneralizedSierpinskiGraph(Graph(1), 3).vertices(sort=False) # needs sage.modules + sage: graphs.GeneralizedSierpinskiGraph(Graph(1), 3).vertices(sort=False) [(0, 0, 0)] - sage: G = graphs.GeneralizedSierpinskiGraph(Graph(2), 3) # needs sage.modules - sage: G.order(), G.size() # needs sage.modules + sage: G = graphs.GeneralizedSierpinskiGraph(Graph(2), 3) + sage: G.order(), G.size() (8, 0) - sage: graphs.GeneralizedSierpinskiGraph("foo", 1) # needs sage.modules + sage: graphs.GeneralizedSierpinskiGraph("foo", 1) Traceback (most recent call last): ... ValueError: parameter G must be a Graph - sage: graphs.GeneralizedSierpinskiGraph(Graph(), 0) # needs sage.modules + sage: graphs.GeneralizedSierpinskiGraph(Graph(), 0) Traceback (most recent call last): ... ValueError: parameter k must be >= 1 @@ -3401,46 +3414,49 @@ def WheelGraph(n): We view many wheel graphs with a Sage Graphics Array, first with this constructor (i.e., the position dictionary filled):: + sage: # needs sage.plot sage: g = [] sage: j = [] sage: for i in range(9): ....: k = graphs.WheelGraph(i+3) ....: g.append(k) ... - sage: for i in range(3): # needs sage.plot + sage: for i in range(3): ....: 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) # needs sage.plot - sage: G.show() # long time # needs sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time Next, using the spring-layout algorithm:: - sage: import networkx # needs networkx + sage: # needs networkx sage.plot + sage: import networkx sage: g = [] sage: j = [] - sage: for i in range(9): # needs networkx + sage: for i in range(9): ....: spr = networkx.wheel_graph(i+3) ....: k = Graph(spr) ....: g.append(k) ... - sage: for i in range(3): # needs networkx sage.plot + sage: for i in range(3): ....: 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) # needs networkx sage.plot - sage: G.show() # long time # needs networkx sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time Compare the plotting:: - sage: n = networkx.wheel_graph(23) # needs networkx - sage: spring23 = Graph(n) # needs networkx + sage: # needs networkx sage.plot + sage: n = networkx.wheel_graph(23) + sage: spring23 = Graph(n) sage: posdict23 = graphs.WheelGraph(23) - sage: spring23.show() # long time # needs networkx + sage: spring23.show() # long time sage: posdict23.show() # long time """ from sage.graphs.generators.basic import CycleGraph @@ -3744,10 +3760,11 @@ def RingedTree(k, vertex_labels=True): EXAMPLES:: - sage: G = graphs.RingedTree(5) # needs networkx - sage: P = G.plot(vertex_labels=False, vertex_size=10) # needs networkx sage.plot - sage: P.show() # long time # needs networkx sage.plot - sage: G.vertices(sort=True) # needs networkx + sage: # needs networkx + sage: G = graphs.RingedTree(5) + sage: P = G.plot(vertex_labels=False, vertex_size=10) # needs sage.plot + sage: P.show() # long time # needs sage.plot + sage: G.vertices(sort=True) ['', '0', '00', '000', '0000', '0001', '001', '0010', '0011', '01', '010', '0100', '0101', '011', '0110', '0111', '1', '10', '100', '1000', '1001', '101', '1010', '1011', '11', '110', '1100', '1101', @@ -3900,15 +3917,16 @@ def MathonPseudocyclicStronglyRegularGraph(t, G=None, L=None): Supplying ``G`` and ``L`` (constructed from the automorphism group of ``G``). :: - sage: G = graphs.PaleyGraph(9) # needs sage.rings.finite_rings - sage: a = G.automorphism_group(partition=[sorted(G)]) # needs sage.groups sage.rings.finite_rings - sage: it = (x for x in a.normal_subgroups() if x.order() == 9) # needs sage.groups sage.rings.finite_rings - sage: subg = next(iter(it)) # needs sage.groups sage.rings.finite_rings - sage: r = [matrix(libgap.PermutationMat(libgap(z), 9).sage()) # needs sage.groups sage.libs.gap sage.rings.finite_rings + sage: # needs sage.groups sage.libs.gap sage.rings.finite_rings + sage: G = graphs.PaleyGraph(9) + sage: a = G.automorphism_group(partition=[sorted(G)]) + sage: it = (x for x in a.normal_subgroups() if x.order() == 9) + sage: subg = next(iter(it)) + sage: r = [matrix(libgap.PermutationMat(libgap(z), 9).sage()) ....: for z in subg] - sage: ff = list(map(lambda y: (y[0]-1,y[1]-1), # needs sage.groups sage.libs.gap sage.rings.finite_rings + sage: ff = list(map(lambda y: (y[0]-1,y[1]-1), ....: Permutation(map(lambda x: 1+r.index(x^-1), r)).cycle_tuples()[1:])) - sage: L = sum(i*(r[a]-r[b]) for i,(a,b) in zip(range(1,len(ff)+1), ff)); L # needs sage.groups sage.libs.gap sage.rings.finite_rings + sage: L = sum(i*(r[a]-r[b]) for i,(a,b) in zip(range(1,len(ff)+1), ff)); L [ 0 1 -1 -3 -2 -4 3 4 2] [-1 0 1 -4 -3 -2 2 3 4] [ 1 -1 0 -2 -4 -3 4 2 3] @@ -3919,16 +3937,17 @@ def MathonPseudocyclicStronglyRegularGraph(t, G=None, L=None): [-4 -3 -2 2 3 4 -1 0 1] [-2 -4 -3 4 2 3 1 -1 0] - sage: G.relabel(range(9)) # needs sage.rings.finite_rings - sage: G3x3 = graphs.MathonPseudocyclicStronglyRegularGraph(2, G=G, L=L) # needs sage.modules sage.rings.finite_rings - sage: G3x3.is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings + sage: # needs sage.modules sage.rings.finite_rings + sage: G.relabel(range(9)) + sage: G3x3 = graphs.MathonPseudocyclicStronglyRegularGraph(2, G=G, L=L) # needs sage.groups sage.libs.gap + sage: G3x3.is_strongly_regular(parameters=True) (441, 220, 109, 110) - sage: G3x3.automorphism_group(algorithm="bliss").order() # optional - bliss, needs sage.modules sage.rings.finite_rings + sage: G3x3.automorphism_group(algorithm="bliss").order() # optional - bliss 27 - sage: G9 = graphs.MathonPseudocyclicStronglyRegularGraph(2) # needs sage.modules sage.rings.finite_rings - sage: G9.is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings + sage: G9 = graphs.MathonPseudocyclicStronglyRegularGraph(2) + sage: G9.is_strongly_regular(parameters=True) (441, 220, 109, 110) - sage: G9.automorphism_group(algorithm="bliss").order() # optional - bliss, needs sage.modules sage.rings.finite_rings + sage: G9.automorphism_group(algorithm="bliss").order() # optional - bliss 9 TESTS:: @@ -4137,27 +4156,28 @@ def MuzychukS6Graph(n, d, Phi='fixed', Sigma='fixed', verbose=False): TESTS:: - sage: graphs.MuzychukS6Graph(2,2,Phi='random',Sigma='random').is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings + sage: # needs sage.modules + sage: graphs.MuzychukS6Graph(2,2,Phi='random',Sigma='random').is_strongly_regular(parameters=True) # needs sage.rings.finite_rings (16, 5, 0, 2) - sage: graphs.MuzychukS6Graph(3,3,Phi='random',Sigma='random').is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings + sage: graphs.MuzychukS6Graph(3,3,Phi='random',Sigma='random').is_strongly_regular(parameters=True) # needs sage.rings.finite_rings (378, 116, 34, 36) - sage: graphs.MuzychukS6Graph(3,2) # needs sage.modules + sage: graphs.MuzychukS6Graph(3,2) Traceback (most recent call last): ... AssertionError: n must be even or d must be odd - sage: graphs.MuzychukS6Graph(6,2) # needs sage.modules + sage: graphs.MuzychukS6Graph(6,2) Traceback (most recent call last): ... AssertionError: n must be a prime power - sage: graphs.MuzychukS6Graph(3,1) # needs sage.modules + sage: graphs.MuzychukS6Graph(3,1) Traceback (most recent call last): ... AssertionError: d must be at least 2 - sage: graphs.MuzychukS6Graph(3,3,Phi=42) # needs sage.modules sage.rings.finite_rings + sage: graphs.MuzychukS6Graph(3,3,Phi=42) # needs sage.rings.finite_rings Traceback (most recent call last): ... AssertionError: Phi must be a dictionary or 'random' or 'fixed' - sage: graphs.MuzychukS6Graph(3,3,Sigma=42) # needs sage.modules sage.rings.finite_rings + sage: graphs.MuzychukS6Graph(3,3,Sigma=42) # needs sage.rings.finite_rings Traceback (most recent call last): ... ValueError: Sigma must be 'random' or 'fixed' diff --git a/src/sage/graphs/generators/intersection.py b/src/sage/graphs/generators/intersection.py index 06368795029..0de3715e0e1 100644 --- a/src/sage/graphs/generators/intersection.py +++ b/src/sage/graphs/generators/intersection.py @@ -429,14 +429,15 @@ def OrthogonalArrayBlockGraph(k, n, OA=None): Two graphs built from different orthogonal arrays are also different:: + sage: # needs sage.modules sage: k = 4; n = 10 - sage: OAa = designs.orthogonal_arrays.build(k,n) # needs sage.modules - sage: OAb = [[(x+1)%n for x in R] for R in OAa] # needs sage.modules - sage: set(map(tuple,OAa)) == set(map(tuple,OAb)) # needs sage.modules + sage: OAa = designs.orthogonal_arrays.build(k,n) + sage: OAb = [[(x+1)%n for x in R] for R in OAa] + sage: set(map(tuple,OAa)) == set(map(tuple,OAb)) False - sage: Ga = graphs.OrthogonalArrayBlockGraph(k, n, OAa) # needs sage.modules - sage: Gb = graphs.OrthogonalArrayBlockGraph(k, n, OAb) # needs sage.modules - sage: Ga == Gb # needs sage.modules + sage: Ga = graphs.OrthogonalArrayBlockGraph(k, n, OAa) + sage: Gb = graphs.OrthogonalArrayBlockGraph(k, n, OAb) + sage: Ga == Gb False As ``OAb`` was obtained from ``OAa`` by a relabelling the two graphs are diff --git a/src/sage/graphs/generators/platonic_solids.py b/src/sage/graphs/generators/platonic_solids.py index b0f97da83fa..38e070a054a 100644 --- a/src/sage/graphs/generators/platonic_solids.py +++ b/src/sage/graphs/generators/platonic_solids.py @@ -39,7 +39,7 @@ def TetrahedralGraph(): Construct and show a Tetrahedral graph:: sage: g = graphs.TetrahedralGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot The following example requires networkx:: @@ -48,19 +48,20 @@ def TetrahedralGraph(): Compare this Tetrahedral, Wheel(4), Complete(4), and the Tetrahedral plotted with the spring-layout algorithm below in a Sage graphics array:: + sage: # needs networkx sage.plot sage: tetra_pos = graphs.TetrahedralGraph() - sage: tetra_spring = Graph(NX.tetrahedral_graph()) # needs networkx + sage: tetra_spring = Graph(NX.tetrahedral_graph()) sage: wheel = graphs.WheelGraph(4) sage: complete = graphs.CompleteGraph(4) - sage: g = [tetra_pos, tetra_spring, wheel, complete] # needs networkx + sage: g = [tetra_pos, tetra_spring, wheel, complete] sage: j = [] - sage: for i in range(2): # needs networkx sage.plot + sage: for i in range(2): ....: n = [] ....: for m in range(2): ....: n.append(g[i + m].plot(vertex_size=50, vertex_labels=False)) ....: j.append(n) - sage: G = graphics_array(j) # needs networkx sage.plot - sage: G.show() # long time # needs networkx sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time """ edges = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] pos = {0: (0, 0), @@ -88,23 +89,24 @@ def HexahedralGraph(): Construct and show a Hexahedral graph:: sage: g = graphs.HexahedralGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot Create several hexahedral graphs in a Sage graphics array. They will be drawn differently due to the use of the spring-layout algorithm:: + sage: # needs sage.plot sage: g = [] sage: j = [] sage: for i in range(9): ....: k = graphs.HexahedralGraph() ....: g.append(k) - sage: for i in range(3): # needs sage.plot + sage: for i in range(3): ....: 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) # needs sage.plot - sage: G.show() # long time # needs sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time """ adj = {0: [1, 3, 4], 1: [2, 5], 2: [3, 6], 3: [7], 4: [5, 7], 5: [6], 6: [7]} pos = { @@ -145,18 +147,19 @@ def OctahedralGraph(): Create several octahedral graphs in a Sage graphics array They will be drawn differently due to the use of the spring-layout algorithm:: + sage: # needs sage.plot sage: g = [] sage: j = [] sage: for i in range(9): ....: k = graphs.OctahedralGraph() ....: g.append(k) - sage: for i in range(3): # needs sage.plot + sage: for i in range(3): ....: 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) # needs sage.plot - sage: G.show() # long time # needs sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time """ adj = {0: [1, 2, 3, 4], 1: [2, 3, 5], 2: [4, 5], 3: [4, 5], 4: [5]} G = Graph(adj, format='dict_of_lists', name="Octahedron") @@ -184,23 +187,24 @@ def IcosahedralGraph(): Construct and show an Octahedral graph:: sage: g = graphs.IcosahedralGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot Create several icosahedral graphs in a Sage graphics array. They will be drawn differently due to the use of the spring-layout algorithm:: + sage: # needs sage.plot sage: g = [] sage: j = [] sage: for i in range(9): ....: k = graphs.IcosahedralGraph() ....: g.append(k) - sage: for i in range(3): # needs sage.plot + sage: for i in range(3): ....: 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) # needs sage.plot - sage: G.show() # long time # needs sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time """ adj = {0: [1, 5, 7, 8, 11], 1: [2, 5, 6, 8], 2: [3, 6, 8, 9], 3: [4, 6, 9, 10], 4: [5, 6, 10, 11], 5: [6, 11], @@ -228,23 +232,24 @@ def DodecahedralGraph(): Construct and show a Dodecahedral graph:: sage: g = graphs.DodecahedralGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot Create several dodecahedral graphs in a Sage graphics array They will be drawn differently due to the use of the spring-layout algorithm:: + sage: # needs sage.plot sage: g = [] sage: j = [] sage: for i in range(9): ....: k = graphs.DodecahedralGraph() ....: g.append(k) - sage: for i in range(3): # needs sage.plot + sage: for i in range(3): ....: 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) # needs sage.plot - sage: G.show() # long time # needs sage.plot + sage: G = graphics_array(j) + sage: G.show() # long time """ adj = {0: [1, 10, 19], 1: [2, 8], 2: [3, 6], 3: [4, 19], 4: [5, 17], 5: [6, 15], 6: [7], 7: [8, 14], 8: [9], 9: [10, 13], 10: [11], diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index afae6f5de21..0c2dc0a79df 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -16400,8 +16400,8 @@ def triangles_count(self, algorithm=None): The 2-dimensional DeBruijn graph of 2 symbols has 2 directed `C_3`:: - sage: G = digraphs.DeBruijn(2,2) # needs sage.combinat - sage: G.triangles_count() # needs sage.combinat + sage: G = digraphs.DeBruijn(2,2) # needs sage.combinat + sage: G.triangles_count() # needs sage.combinat 2 The directed `n`-cycle is trivially triangle free for `n > 3`:: @@ -20779,15 +20779,16 @@ def plot(self, **options): :: - sage: from sage.plot.colors import rainbow # needs sage.plot + sage: # needs sage.plot + sage: from sage.plot.colors import rainbow sage: C = graphs.CubeGraph(5) - sage: R = rainbow(5) # needs sage.plot - sage: edge_colors = {R[i]: [] for i in range(5)} # needs sage.plot - sage: for u, v, l in C.edges(sort=False): # needs sage.plot + sage: R = rainbow(5) + sage: edge_colors = {R[i]: [] for i in range(5)} + sage: for u, v, l in C.edges(sort=False): ....: for i in range(5): ....: if u[i] != v[i]: ....: edge_colors[R[i]].append((u, v, l)) - sage: C.plot(vertex_labels=False, vertex_size=0, # needs sage.plot + sage: C.plot(vertex_labels=False, vertex_size=0, ....: edge_colors=edge_colors).show() :: diff --git a/src/sage/graphs/path_enumeration.pyx b/src/sage/graphs/path_enumeration.pyx index 5709d2b87c4..0e5304bcae4 100644 --- a/src/sage/graphs/path_enumeration.pyx +++ b/src/sage/graphs/path_enumeration.pyx @@ -442,20 +442,20 @@ def shortest_simple_paths(self, source, target, weight_function=None, [1, 6, 9, 11, 10, 5]] sage: # needs sage.combinat - sage: G = digraphs.DeBruijn(2, 3) # needs sage.combinat - sage: for u,v in G.edges(sort=True, labels=False): # needs sage.combinat + sage: G = digraphs.DeBruijn(2, 3) + sage: for u,v in G.edges(sort=True, labels=False): ....: G.set_edge_label(u, v, 1) - sage: G.allow_multiple_edges(True) # needs sage.combinat - sage: for u,v in G.edges(sort=True, labels=False): # needs sage.combinat + sage: G.allow_multiple_edges(True) + sage: for u,v in G.edges(sort=True, labels=False): ....: G.add_edge(u, v, 2) - sage: list(G.shortest_simple_paths('000', '111')) # needs sage.combinat + sage: list(G.shortest_simple_paths('000', '111')) [['000', '001', '011', '111'], ['000', '001', '010', '101', '011', '111']] - sage: list(G.shortest_simple_paths('000', '111', by_weight=True)) # needs sage.combinat + sage: list(G.shortest_simple_paths('000', '111', by_weight=True)) [['000', '001', '011', '111'], ['000', '001', '010', '101', '011', '111']] - sage: list(G.shortest_simple_paths('000', '111', by_weight=True, report_weight=True)) # needs sage.combinat + sage: list(G.shortest_simple_paths('000', '111', by_weight=True, report_weight=True)) [(3, ['000', '001', '011', '111']), (5, ['000', '001', '010', '101', '011', '111'])] - sage: list(G.shortest_simple_paths('000', '111', by_weight=True, report_weight=True, report_edges=True, labels=True)) # needs sage.combinat + sage: list(G.shortest_simple_paths('000', '111', by_weight=True, report_weight=True, report_edges=True, labels=True)) [(3, [('000', '001', 1), ('001', '011', 1), ('011', '111', 1)]), (5, [('000', '001', 1), @@ -481,12 +481,12 @@ def shortest_simple_paths(self, source, target, weight_function=None, Check for consistency of results of Yen's and Feng's:: sage: # needs sage.combinat - sage: G = digraphs.DeBruijn(2, 4) # needs sage.combinat + sage: G = digraphs.DeBruijn(2, 4) sage: s = set() - sage: for p in G.shortest_simple_paths('0000', '1111', by_weight=False, algorithm='Yen'): # needs sage.combinat + sage: for p in G.shortest_simple_paths('0000', '1111', by_weight=False, algorithm='Yen'): ....: s.add(tuple(p)) sage: k = set() - sage: for p in G.shortest_simple_paths('0000', '1111', by_weight=False, algorithm='Feng'): # needs sage.combinat + sage: for p in G.shortest_simple_paths('0000', '1111', by_weight=False, algorithm='Feng'): ....: k.add(tuple(p)) sage: k == s True From 4d259d440db55d7065bc5e8109112b75bee4acbe Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 4 Aug 2023 17:03:12 -0700 Subject: [PATCH 10/10] src/sage/graphs/generators/smallgraphs.py: Fix up merge --- src/sage/graphs/generators/smallgraphs.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index ccc4610bb8c..e58248f05c8 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -4664,7 +4664,6 @@ def WienerArayaGraph(): False sage: g.delete_vertex(g.random_vertex()) sage: g.is_hamiltonian() # needs sage.numerical.mip ->>>>>>> 85d4a8d443 (./sage -fixdoctests --probe all --distribution 'sagemath-graphs[modules]' src/sage/graphs/generators/smallgraphs.py; ./sage -fixdoctests src/sage/graphs/generators/smallgraphs.py) True """ g = Graph(name="Wiener-Araya Graph")