Common graphs - Graph Theory

Skip to content
Back to top
View this page
Edit this page

# Common graphs

All graphs in Sage can be built through the `graphs` object. In order to build a complete graph on 15 elements, one can do:

Sage

    sage: g = graphs.CompleteGraph(15)

Python

    >>> from sage.all import *
    >>> g = graphs.CompleteGraph(Integer(15))

To get a path with 4 vertices, and the house graph:

Sage

    sage: p = graphs.PathGraph(4)
    sage: h = graphs.HouseGraph()

[Python]

    >>> from sage.all import *
    >>> p = graphs.PathGraph(Integer(4))
    >>> h = graphs.HouseGraph()

More interestingly, one can get the list of all graphs that Sage knows how to build by typing `graphs.` in Sage and then hitting `Tab`.

Basic structures

`BullGraph` | `DiamondGraph` | `HouseXGraph`
`ButterflyGraph` | `GemGraph` | `LadderGraph`
`CircularLadderGraph` | `DartGraph` | `LollipopGraph`
`ClawGraph` | `ForkGraph` | `MoebiusLadderGraph`
`CycleGraph` | `DipoleGraph` | `PathGraph`
`CompleteBipartiteGraph` | `EmptyGraph` | `StarGraph`
`CompleteGraph` | `Grid2dGraph` | `TadpoleGraph`
`CompleteMultipartiteGraph` | `GridGraph` | `ToroidalGrid2dGraph`
`CorrelationGraph` | `HouseGraph` | `Toroidal6RegularGrid2dGraph`

Small Graphs

A small graph is just a single graph and has no parameter influencing the number of edges or vertices.

`Balaban10Cage` | `GossetGraph` | `MeredithGraph`
`Balaban11Cage` | `graph_3O73` | `MoebiusKantorGraph`
`BidiakisCube` | `GrayGraph` | `MoserSpindle`
`BiggsSmithGraph` | `GritsenkoGraph` | `MurtyGraph`
`BlanusaFirstSnarkGraph` | `GrotzschGraph` | `NauruGraph`
`BlanusaSecondSnarkGraph` | `HallJankoGraph` | `PappusGraph`
`BrinkmannGraph` | `HarborthGraph` | `PoussinGraph`
`BrouwerHaemersGraph` | `HarriesGraph` | `PerkelGraph`
`BuckyBall` | `HarriesWongGraph` | `PetersenGraph`
`CameronGraph` | `HeawoodGraph` | `RobertsonGraph`
`Cell600` | `HerschelGraph` | `SchlaefliGraph`
`Cell120` | `HigmanSimsGraph` | `shortened_00_11_binary_Golay_code_graph`
`ChvatalGraph` | `HoffmanGraph` | `shortened_000_111_extended_binary_Golay_code_graph`
`ClebschGraph` | `HoffmanSingletonGraph` | `ShrikhandeGraph`
`cocliques_HoffmannSingleton` | `HoltGraph` | `SimsGewirtzGraph`
`ConwaySmith_for_3S7` | `HortonGraph` | `SousselierGraph`
`CoxeterGraph` | `IoninKharaghani765Graph` | `SylvesterGraph`
`CubeplexGraph` | `IvanovIvanovFaradjevGraph` | `SzekeresSnarkGraph`
`DesarguesGraph` | `J2Graph` | `ThomsenGraph`
`DejterGraph` | `JankoKharaghaniGraph` | `TietzeGraph`
`distance_3_doubly_truncated_Golay_code_graph` | `JankoKharaghaniTonchevGraph` | `TricornGraph`
`DoubleStarSnark` | `KittellGraph` | `TruncatedIcosidodecahedralGraph`
`DoublyTruncatedWittGraph` | `KrackhardtKiteGraph` | `TruncatedTetrahedralGraph`
`DurerGraph` | `Klein3RegularGraph` | `TruncatedWittGraph`
`DyckGraph` | `Klein7RegularGraph` | `Tutte12Cage`
`EllinghamHorton54Graph` | `LargeWittGraph` | `TutteCoxeterGraph`
`EllinghamHorton78Graph` | `LeonardGraph` | `TutteGraph`
`ErreraGraph` | `LjubljanaGraph` | `TwinplexGraph`
`F26AGraph` | `vanLintSchrijverGraph` | `U42Graph216`
`FlowerSnark` | `LivingstoneGraph` | `U42Graph540`
`FolkmanGraph` | `locally_GQ42_distance_transitive_graph` | `WagnerGraph`
`FosterGraph` | `LocalMcLaughlinGraph` | `WatkinsSnarkGraph`
`FosterGraph3S6` | `M22Graph` | `WellsGraph`
`FranklinGraph` | `MarkstroemGraph` | `WienerArayaGraph`
`FruchtGraph` | `MathonStronglyRegularGraph` | `SuzukiGraph`
`GoldnerHararyGraph` | `McGeeGraph` |
`GolombGraph` | `McLaughlinGraph` |

Platonic solids (ordered ascending by number of vertices)

`TetrahedralGraph` | `HexahedralGraph` | `DodecahedralGraph`
`OctahedralGraph` | `IcosahedralGraph` |

Families of graphs

A family of graphs is a set of graphs, which can be indexed by fixed number of parameters, e.g. two integer parameters. (A method whose name starts with a small letter does not return a single graph object but a graph iterator or a list of graphs or …)

`AlternatingFormsGraph` | `GeneralisedDodecagonGraph` | `NKStarGraph`
`AztecDiamondGraph` | `GeneralisedHexagonGraph` | `NStarGraph`
`BarbellGraph` | `GeneralisedOctagonGraph` | `OddGraph`
`BilinearFormsGraph` | `GeneralizedPetersenGraph` | `PaleyGraph`
`BiwheelGraph` | `GeneralizedSierpinskiGraph` | `PasechnikGraph`
`BubbleSortGraph` | `GoethalsSeidelGraph` | `petersen_family`
`CaiFurerImmermanGraph` | `GrassmannGraph` | `p2_forbidden_minors`
`chang_graphs` | `HalfCube` | `planar_graphs`
`CirculantGraph` | `HammingGraph` | `plantri_gen`
`cographs` | `HanoiTowerGraph` | `quadrangulations`
`cospectral_graphs` | `HararyGraph` | `RingedTree`
`CubeGraph` | `HermitianFormsGraph` | `SierpinskiGasketGraph`
`CubeConnectedCycle` | `HyperStarGraph` | `SquaredSkewHadamardMatrixGraph`
`distance_regular_graph` | `JohnsonGraph` | `SwitchedSquaredSkewHadamardMatrixGraph`
`DorogovtsevGoltsevMendesGraph` | `KneserGraph` | `StaircaseGraph`
`DoubleGrassmannGraph` | `LCFGraph` | `strongly_regular_graph`
`DoubleOddGraph` | `line_graph_forbidden_subgraphs` | `TruncatedBiwheelGraph`
`EgawaGraph` | `MathonPseudocyclicMergingGraph` | `triangulations`
`FoldedCubeGraph` | `MathonPseudocyclicStronglyRegularGraph` | `TuranGraph`
`FriendshipGraph` | `MuzychukS6Graph` | `UstimenkoGraph`
`fullerenes` | `MycielskiGraph` | `WheelGraph`
`FurerGadget` | `MycielskiStep` | `WindmillGraph`
`fusenes` | `nauty_geng` |
`FuzzyBallGraph` | `nauty_genbg` |

Graphs from classical geometries over finite fields

A number of classes of graphs related to geometries over finite fields and quadrics and Hermitean varieties there.

`AffineOrthogonalPolarGraph` | `SymplecticDualPolarGraph` | `HaemersGraph`
`AhrensSzekeresGeneralizedQuadrangleGraph` | `SymplecticPolarGraph` | `CossidentePenttilaGraph`
`NonisotropicOrthogonalPolarGraph` | `TaylorTwographDescendantSRG` | `UnitaryDualPolarGraph`
`NonisotropicUnitaryPolarGraph` | `TaylorTwographSRG` | `UnitaryPolarGraph`
`OrthogonalDualPolarGraph` | `T2starGeneralizedQuadrangleGraph` |
`OrthogonalPolarGraph` | `Nowhere0WordsTwoWeightCodeGraph` |

Chessboard Graphs

`BishopGraph` | `KnightGraph` | `RookGraph`
`KingGraph` | `QueenGraph` |

Intersection graphs

These graphs are generated by geometric representations. The objects of the representation correspond to the graph vertices and the intersections of objects yield the graph edges.

`IntersectionGraph` | `OrthogonalArrayBlockGraph` | `ToleranceGraph`
`IntervalGraph` | `PermutationGraph` |

Random graphs

`RandomBarabasiAlbert` | `RandomGNM` | `RandomProperIntervalGraph`
`RandomBicubicPlanar` | `RandomGNP` | `RandomRegular`
`RandomBipartite` | `RandomHolmeKim` | `RandomShell`
`RandomRegularBipartite` | `RandomIntervalGraph` | `RandomToleranceGraph`
`RandomBlockGraph` | `RandomKTree` | `RandomTriangulation`
`RandomBoundedToleranceGraph` | `RandomPartialKTree` | `RandomUnitDiskGraph`
`RandomChordalGraph` | `RandomNewmanWattsStrogatz` |

Trees

`BalancedTree` | `RandomLobster` | `trees`
`FibonacciTree` | `RandomTree` | `nauty_gentreeg`
`Caterpillar` | `RandomTreePowerlaw` |

Graphs with a given degree sequence

`DegreeSequence` | `DegreeSequenceConfigurationModel` | `DegreeSequenceTree`
`DegreeSequenceBipartite` | `DegreeSequenceExpected` |

Miscellaneous

`WorldMap` | `AfricaMap` |
`EuropeMap` | `USAMap` |

AUTHORS:

- Robert Miller (2006-11-05): initial version, empty, random, petersen

- Emily Kirkman (2006-11-12): basic structures, node positioning for all constructors

- Emily Kirkman (2006-11-19): docstrings, examples

- William Stein (2006-12-05): Editing.

- Robert Miller (2007-01-16): Cube generation and plotting

- Emily Kirkman (2007-01-16): more basic structures, docstrings

- Emily Kirkman (2007-02-14): added more named graphs

- Robert Miller (2007-06-08-11): Platonic solids, random graphs, graphs with a given degree sequence, random directed graphs

- Robert Miller (2007-10-24): Isomorph free exhaustive generation

- Nathann Cohen (2009-08-12): WorldMap

- Michael Yurko (2009-9-01): added hyperstar, (n,k)-star, n-star, and bubblesort graphs

- Anders Jonsson (2009-10-15): added generalized Petersen graphs

- Harald Schilly and Yann Laigle-Chapuy (2010-03-24): added Fibonacci Tree

- Jason Grout (2010-06-04): cospectral_graphs

- Edward Scheinerman (2010-08-11): RandomTree

- Ed Scheinerman (2010-08-21): added Grotzsch graph and Mycielski graphs

- Ed Scheinerman (2010-11-15): added RandomTriangulation

- Minh Van Nguyen (2010-11-26): added more named graphs

- Keshav Kini (2011-02-16): added Shrikhande and Dyck graphs

- David Coudert (2012-02-10): new RandomGNP generator

- David Coudert (2012-08-02): added chessboard graphs: Queen, King, Knight, Bishop, and Rook graphs

- Nico Van Cleemput (2013-05-26): added fullerenes

- Nico Van Cleemput (2013-07-01): added benzenoids

- Birk Eisermann (2013-07-29): new section ‘intersection graphs’, added (random, bounded) tolerance graphs

- Marco Cognetta (2016-03-03): added TuranGraph

- Janmenjaya Panda (2024-05-26): added MoebiusLadderGraph

- Janmenjaya Panda (2024-06-09): added StaircaseGraph, BiwheelGraph and TruncatedBiwheelGraph

## Functions and methods

class sage.graphs.graph_generators.GraphGenerators

  Bases: `object`

  A class consisting of constructors for several common graphs, as well as orderly generation of isomorphism class representatives. See the `module's help` for a list of supported constructors.

  A list of all graphs and graph structures (other than isomorphism class representatives) in this database is available via tab completion. Type “graphs.” and then hit the `Tab` key to see which graphs are available.

  The docstrings include educational information about each named graph with the hopes that this class can be used as a reference.

  For all the constructors in this class (except the octahedral, dodecahedral, random and empty graphs), the position dictionary is filled to override the spring-layout algorithm.

  ORDERLY GENERATION:

      graphs(vertices, property=lambda x: True, augment='edges', size=None)

  This syntax accesses the generator of isomorphism class representatives. Iterates over distinct, exhaustive representatives.

  Also: see the use of the nauty package for generating graphs at the `nauty_geng()` method.

  INPUT:

  - `vertices` – a natural number or `None` to infinitely generate bigger and bigger graphs

  - `property` – (default: `lambda x: True`) any property to be tested on graphs before generation, but note that in general the graphs produced are not the same as those produced by using the property function to filter a list of graphs produced by using the `lambda x: True` default. The generation process assumes the property has certain characteristics set by the `augment` argument, and only in the case of inherited properties such that all subgraphs of the relevant kind (for `augment='edges'` or `augment='vertices'`) of a graph with the property also possess the property will there be no missing graphs. (The `property` argument is ignored if `degree_sequence` is specified.)

  - `augment` – (default: `'edges'`) possible values:

    - `'edges'` – augments a fixed number of vertices by adding one edge. In this case, all graphs on exactly `n=vertices` are generated. If for any graph G satisfying the property, every subgraph, obtained from G by deleting one edge but not the vertices incident to that edge, satisfies the property, then this will generate all graphs with that property. If this does not hold, then all the graphs generated will satisfy the property, but there will be some missing.

    - `'vertices'` – augments by adding a vertex and edges incident to that vertex. In this case, all graphs up to `n=vertices` are generated. If for any graph G satisfying the property, every subgraph, obtained from G by deleting one vertex and only edges incident to that vertex, satisfies the property, then this will generate all graphs with that property. If this does not hold, then all the graphs generated will satisfy the property, but there will be some missing.

  - `size` – (default: `None`) the size of the graph to be generated

  - `degree_sequence` – (default: `None`) a sequence of nonnegative integers, or `None`. If specified, the generated graphs will have these integers for degrees. In this case, property and size are both ignored.

  - `loops` – boolean (default: `False`); whether to allow loops in the graph or not

  - `sparse` – (default: `True`) whether to use a sparse or dense data structure. See the documentation of `Graph`.

  - `copy` – boolean (default: `True`); whether to return copies. If set to `False` the method returns the graph it is working on. The second alternative is faster, but modifying any of the graph instances returned by the method may break the function’s behaviour, as it is using these graphs to compute the next ones: only use `copy=False` when you stick to reading the graphs returned.

    This parameter is ignored when `immutable` is set to `True`, in which case returned graphs are always copies.

  - `immutable` – boolean (default: `False`); whether to return immutable or mutable graphs. When set to `True`, this parameter implies `copy=True`.

  EXAMPLES:

  Print graphs on 3 or less vertices:

  Sage

      sage: for G in graphs(3, augment='vertices'):
      ....:     print(G)
      Graph on 0 vertices
      Graph on 1 vertex
      Graph on 2 vertices
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 2 vertices
      Graph on 3 vertices

  Python

      >>> from sage.all import *
      >>> for G in graphs(Integer(3), augment='vertices'):
      ...     print(G)
      Graph on 0 vertices
      Graph on 1 vertex
      Graph on 2 vertices
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 2 vertices
      Graph on 3 vertices

  Print graphs on 3 vertices.

  Sage

      sage: for G in graphs(3):
      ....:    print(G)
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 3 vertices

  [Python]

      >>> from sage.all import *
      >>> for G in graphs(Integer(3)):
      ...    print(G)
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 3 vertices

  Generate all graphs with 5 vertices and 4 edges.

  Sage

      sage: L = graphs(5, size=4)
      sage: len(list(L))
      6

  Python

      >>> from sage.all import *
      >>> L = graphs(Integer(5), size=Integer(4))
      >>> len(list(L))
      6

  Generate all graphs with 5 vertices and up to 4 edges.

  Sage

      sage: L = list(graphs(5, lambda G: G.size() <= 4))
      sage: len(L)
      14
      sage: graphs_list.show_graphs(L)        # long time                             # needs sage.plot

  [Python]

      >>> from sage.all import *
      >>> L = list(graphs(Integer(5), lambda G: G.size() <= Integer(4)))
      >>> len(L)
      14
      >>> graphs_list.show_graphs(L)        # long time                             # needs sage.plot

  Generate all graphs with up to 5 vertices and up to 4 edges.

  Sage

      sage: L = list(graphs(5, lambda G: G.size() <= 4, augment='vertices'))
      sage: len(L)
      31
      sage: graphs_list.show_graphs(L)        # long time                             # needs sage.plot

  Python

      >>> from sage.all import *
      >>> L = list(graphs(Integer(5), lambda G: G.size() <= Integer(4), augment='vertices'))
      >>> len(L)
      31
      >>> graphs_list.show_graphs(L)        # long time                             # needs sage.plot

  Generate all graphs with degree at most 2, up to 6 vertices.

  Sage

      sage: property = lambda G: ( max([G.degree(v) for v in G] + [0]) <= 2 )
      sage: L = list(graphs(6, property, augment='vertices'))
      sage: len(L)
      45

  [Python]

      >>> from sage.all import *
      >>> property = lambda G: ( max([G.degree(v) for v in G] + [Integer(0)]) <= Integer(2) )
      >>> L = list(graphs(Integer(6), property, augment='vertices'))
      >>> len(L)
      45

  Generate all bipartite graphs on up to 7 vertices: (see OEIS sequence A033995)

  Sage

      sage: L = list( graphs(7, lambda G: G.is_bipartite(), augment='vertices') )
      sage: [len([g for g in L if g.order() == i]) for i in [1..7]]
      [1, 2, 3, 7, 13, 35, 88]

  Python

      >>> from sage.all import *
      >>> L = list( graphs(Integer(7), lambda G: G.is_bipartite(), augment='vertices') )
      >>> [len([g for g in L if g.order() == i]) for i in (ellipsis_range(Integer(1),Ellipsis,Integer(7)))]
      [1, 2, 3, 7, 13, 35, 88]

  Generate all bipartite graphs on exactly 7 vertices:

  Sage

      sage: L = list( graphs(7, lambda G: G.is_bipartite()) )
      sage: len(L)
      88

  [Python]

      >>> from sage.all import *
      >>> L = list( graphs(Integer(7), lambda G: G.is_bipartite()) )
      >>> len(L)
      88

  Generate all bipartite graphs on exactly 8 vertices:

  Sage

      sage: L = list( graphs(8, lambda G: G.is_bipartite()) ) # long time
      sage: len(L)                                            # long time
      303

  Python

      >>> from sage.all import *
      >>> L = list( graphs(Integer(8), lambda G: G.is_bipartite()) ) # long time
      >>> len(L)                                            # long time
      303

  Remember that the property argument does not behave as a filter, except for appropriately inheritable properties:

  Sage

      sage: property = lambda G: G.is_vertex_transitive()
      sage: len(list(graphs(4, property)))                                            # needs sage.groups
      1
      sage: sum(1 for g in graphs(4) if property(g))                                  # needs sage.groups
      4

      sage: property = lambda G: G.is_bipartite()
      sage: len(list(graphs(4, property)))
      7
      sage: sum(1 for g in graphs(4) if property(g))
      7

  [Python]

      >>> from sage.all import *
      >>> property = lambda G: G.is_vertex_transitive()
      >>> len(list(graphs(Integer(4), property)))                                            # needs sage.groups
      1
      >>> sum(Integer(1) for g in graphs(Integer(4)) if property(g))                                  # needs sage.groups
      4

      >>> property = lambda G: G.is_bipartite()
      >>> len(list(graphs(Integer(4), property)))
      7
      >>> sum(Integer(1) for g in graphs(Integer(4)) if property(g))
      7

  Generate graphs on the fly: (see OEIS sequence A000088)

  Sage

      sage: for i in range(7):
      ....:     print(len(list(graphs(i))))
      1
      1
      2
      4
      11
      34
      156

  Python

      >>> from sage.all import *
      >>> for i in range(Integer(7)):
      ...     print(len(list(graphs(i))))
      1
      1
      2
      4
      11
      34
      156

  Generate all simple graphs, allowing loops: (see OEIS sequence A000666)

  Sage

      sage: L = list(graphs(5,augment='vertices',loops=True))               # long time
      sage: for i in [0..5]:  # long time
      ....:     print((i, len([g for g in L if g.order() == i])))
      (0, 1)
      (1, 2)
      (2, 6)
      (3, 20)
      (4, 90)
      (5, 544)

  [Python]

      >>> from sage.all import *
      >>> L = list(graphs(Integer(5),augment='vertices',loops=True))               # long time
      >>> for i in (ellipsis_range(Integer(0),Ellipsis,Integer(5))):  # long time
      ...     print((i, len([g for g in L if g.order() == i])))
      (0, 1)
      (1, 2)
      (2, 6)
      (3, 20)
      (4, 90)
      (5, 544)

  Generate all graphs with a specified degree sequence (see OEIS sequence A002851):

  Sage

      sage: for i in [4,6,8]:  # long time (4s on sage.math, 2012)
      ....:     print((i, len([g for g in graphs(i, degree_sequence=[3]*i) if g.is_connected()])))
      (4, 1)
      (6, 2)
      (8, 5)
      sage: for i in [4,6,8]:  # long time (7s on sage.math, 2012)
      ....:     print((i, len([g for g in graphs(i, augment='vertices', degree_sequence=[3]*i) if g.is_connected()])))
      (4, 1)
      (6, 2)
      (8, 5)

  Python

      >>> from sage.all import *
      >>> for i in [Integer(4),Integer(6),Integer(8)]:  # long time (4s on sage.math, 2012)
      ...     print((i, len([g for g in graphs(i, degree_sequence=[Integer(3)]*i) if g.is_connected()])))
      (4, 1)
      (6, 2)
      (8, 5)
      >>> for i in [Integer(4),Integer(6),Integer(8)]:  # long time (7s on sage.math, 2012)
      ...     print((i, len([g for g in graphs(i, augment='vertices', degree_sequence=[Integer(3)]*i) if g.is_connected()])))
      (4, 1)
      (6, 2)
      (8, 5)

  Sage

      sage: print((10, len([g for g in graphs(10,degree_sequence=[3]*10) if g.is_connected()]))) # not tested
      (10, 19)

  [Python]

      >>> from sage.all import *
      >>> print((Integer(10), len([g for g in graphs(Integer(10),degree_sequence=[Integer(3)]*Integer(10)) if g.is_connected()]))) # not tested
      (10, 19)

  Make sure that the graphs are really independent and the generator survives repeated vertex removal (Issue #8458):

  Sage

      sage: for G in graphs(3):
      ....:     G.delete_vertex(0)
      ....:     print(G.order())
      2
      2
      2
      2

  Python

      >>> from sage.all import *
      >>> for G in graphs(Integer(3)):
      ...     G.delete_vertex(Integer(0))
      ...     print(G.order())
      2
      2
      2
      2

  Returned graphs can be mutable or immutable:

  Sage

      sage: G = next(graphs(3, immutable=False))
      sage: G.delete_vertex(0)
      sage: G = next(graphs(3, immutable=True))
      sage: G.delete_vertex(0)
      Traceback (most recent call last):
      ...
      TypeError: this graph is immutable and so cannot be changed
      sage: G = next(graphs(4, degree_sequence=[3]*4))
      sage: G.delete_vertex(0)
      sage: G = next(graphs(4, degree_sequence=[3]*4, immutable=True))
      sage: G.delete_vertex(0)
      Traceback (most recent call last):
      ...
      TypeError: this graph is immutable and so cannot be changed

  [Python]

      >>> from sage.all import *
      >>> G = next(graphs(Integer(3), immutable=False))
      >>> G.delete_vertex(Integer(0))
      >>> G = next(graphs(Integer(3), immutable=True))
      >>> G.delete_vertex(Integer(0))
      Traceback (most recent call last):
      ...
      TypeError: this graph is immutable and so cannot be changed
      >>> G = next(graphs(Integer(4), degree_sequence=[Integer(3)]*Integer(4)))
      >>> G.delete_vertex(Integer(0))
      >>> G = next(graphs(Integer(4), degree_sequence=[Integer(3)]*Integer(4), immutable=True))
      >>> G.delete_vertex(Integer(0))
      Traceback (most recent call last):
      ...
      TypeError: this graph is immutable and so cannot be changed

  REFERENCE:

  - Brendan D. McKay, Isomorph-Free Exhaustive generation. Journal of Algorithms, Volume 26, Issue 2, February 1998, pages 306-324.

  static AffineOrthogonalPolarGraph(d, q, sign='+')

    Return the affine polar graph \(VO^+(d,q),VO^-(d,q)\) or \(VO(d,q)\).

    Affine Polar graphs are built from a \(d\)-dimensional vector space over \(F_q\), and a quadratic form which is hyperbolic, elliptic or parabolic according to the value of `sign`.

    Note that \(VO^+(d,q),VO^-(d,q)\) are strongly regular graphs, while \(VO(d,q)\) is not.

    For more information on Affine Polar graphs, see Affine Polar Graphs page of Andries Brouwer’s website.

    INPUT:

    - `d` – integer; `d` must be even if `sign is not None`, and odd otherwise

    - `q` – integer; a power of a prime number, as \(F_q\) must exist

    - `sign` – string (default: `'+'`); must be equal to `'+'`, `'-'`, or `None` to compute (respectively) \(VO^+(d,q),VO^-(d,q)\) or \(VO(d,q)\)

    Note

    The graph \(VO^\epsilon(d,q)\) is the graph induced by the non-neighbors of a vertex in an `Orthogonal Polar Graph` \(O^\epsilon(d+2,q)\).

    EXAMPLES:

    The `Brouwer-Haemers graph` is isomorphic to \(VO^-(4,3)\):

    Sage

        sage: g = graphs.AffineOrthogonalPolarGraph(4,3,"-")                            # needs sage.libs.gap
        sage: g.is_isomorphic(graphs.BrouwerHaemersGraph())                             # needs sage.libs.gap
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.AffineOrthogonalPolarGraph(Integer(4),Integer(3),"-")                            # needs sage.libs.gap
        >>> g.is_isomorphic(graphs.BrouwerHaemersGraph())                             # needs sage.libs.gap
        True

    Some examples from Brouwer’s table or strongly regular graphs:

    Sage

        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)
        (64, 27, 10, 12)
        sage: g = graphs.AffineOrthogonalPolarGraph(6,2,"+"); g
        Affine Polar Graph VO^+(6,2): Graph on 64 vertices
        sage: g.is_strongly_regular(parameters=True)
        (64, 35, 18, 20)

    [Python]

        >>> from sage.all import *
        >>> # needs sage.libs.gap
        >>> g = graphs.AffineOrthogonalPolarGraph(Integer(6),Integer(2),"-"); g
        Affine Polar Graph VO^-(6,2): Graph on 64 vertices
        >>> g.is_strongly_regular(parameters=True)
        (64, 27, 10, 12)
        >>> g = graphs.AffineOrthogonalPolarGraph(Integer(6),Integer(2),"+"); g
        Affine Polar Graph VO^+(6,2): Graph on 64 vertices
        >>> g.is_strongly_regular(parameters=True)
        (64, 35, 18, 20)

    When `sign is None`:

    Sage

        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)
        False
        sage: g.is_regular()
        True
        sage: g.is_vertex_transitive()
        True

    Python

        >>> from sage.all import *
        >>> # needs sage.libs.gap
        >>> g = graphs.AffineOrthogonalPolarGraph(Integer(5),Integer(2),None); g
        Affine Polar Graph VO^-(5,2): Graph on 32 vertices
        >>> g.is_strongly_regular(parameters=True)
        False
        >>> g.is_regular()
        True
        >>> g.is_vertex_transitive()
        True

  static AfricaMap(continental=False, year=2018)

    Return African states as a graph of common border.

    “African state” here is defined as an independent state having the capital city in Africa. The graph has an edge between those countries that have common land border.

    INPUT:

    - `continental` – boolean (default: `False`); whether to only return states in the continental Africa or all African states

    - `year` – integer (default: 2018); reserved for future use

    EXAMPLES:

    Sage

        sage: Africa = graphs.AfricaMap(); Africa
        Africa Map: Graph on 54 vertices
        sage: sorted(Africa.neighbors('Libya'))
        ['Algeria', 'Chad', 'Egypt', 'Niger', 'Sudan', 'Tunisia']

        sage: cont_Africa = graphs.AfricaMap(continental=True)
        sage: cont_Africa.order()
        48
        sage: 'Madagaskar' in cont_Africa
        False

    Python

        >>> from sage.all import *
        >>> Africa = graphs.AfricaMap(); Africa
        Africa Map: Graph on 54 vertices
        >>> sorted(Africa.neighbors('Libya'))
        ['Algeria', 'Chad', 'Egypt', 'Niger', 'Sudan', 'Tunisia']

        >>> cont_Africa = graphs.AfricaMap(continental=True)
        >>> cont_Africa.order()
        48
        >>> 'Madagaskar' in cont_Africa
        False

  static AhrensSzekeresGeneralizedQuadrangleGraph(q, dual=False)

    Return the collinearity graph of the generalized quadrangle \(AS(q)\), or of its dual

    Let \(q\) be an odd prime power. \(AS(q)\) is a generalized quadrangle (Wikipedia article Generalized_quadrangle) of order \((q-1,q+1)\), see 3.1.5 in [PT2009]. Its points are elements of \(F_q^3\), and lines are sets of size \(q\) of the form

    - \(\{ (\sigma, a, b) \mid \sigma\in F_q \}\)

    - \(\{ (a, \sigma, b) \mid \sigma\in F_q \}\)

    - \(\{ (c \sigma^2 - b \sigma + a, -2 c \sigma + b, \sigma) \mid \sigma\in F_q \}\),

    where \(a\), \(b\), \(c\) are arbitrary elements of \(F_q\).

    INPUT:

    - `q` – a power of an odd prime number

    - `dual` – boolean (default: `False`); whether to return the collinearity graph of \(AS(q)\) or of the dual \(AS(q)\) (when `True`)

    EXAMPLES:

    Sage

        sage: g = graphs.AhrensSzekeresGeneralizedQuadrangleGraph(5); g
        AS(5); GQ(4, 6): Graph on 125 vertices
        sage: g.is_strongly_regular(parameters=True)
        (125, 28, 3, 7)
        sage: g = graphs.AhrensSzekeresGeneralizedQuadrangleGraph(5, dual=True); g
        AS(5)*; GQ(6, 4): Graph on 175 vertices
        sage: g.is_strongly_regular(parameters=True)
        (175, 30, 5, 5)

    Python

        >>> from sage.all import *
        >>> g = graphs.AhrensSzekeresGeneralizedQuadrangleGraph(Integer(5)); g
        AS(5); GQ(4, 6): Graph on 125 vertices
        >>> g.is_strongly_regular(parameters=True)
        (125, 28, 3, 7)
        >>> g = graphs.AhrensSzekeresGeneralizedQuadrangleGraph(Integer(5), dual=True); g
        AS(5)*; GQ(6, 4): Graph on 175 vertices
        >>> g.is_strongly_regular(parameters=True)
        (175, 30, 5, 5)

  static AlternatingFormsGraph(n, q)

    Return the alternating forms graph with the given parameters.

    This builds a graph whose vertices are all \(n`x`n\) skew-symmetric matrices over \(GF(q)\) with zero diagonal. Two vertices are adjacent if and only if the difference of the two matrices has rank 2.

    This graph is distance-regular with classical parameters \((\lfloor \frac n 2 \rfloor, q^2, q^2 - 1, q^{2 \lceil \frac n 2 \rceil -1})\).

    INPUT:

    - `n` – integer

    - `q` – a prime power

    EXAMPLES:

    Sage

        sage: G = graphs.AlternatingFormsGraph(5, 2)  # long time
        sage: G.is_distance_regular(True)  # long time
        ([155, 112, None], [None, 1, 20])

    Python

        >>> from sage.all import *
        >>> G = graphs.AlternatingFormsGraph(Integer(5), Integer(2))  # long time
        >>> G.is_distance_regular(True)  # long time
        ([155, 112, None], [None, 1, 20])

    REFERENCES:

    See [BCN1989] pp. 282-284 for a rather detailed discussion, otherwise see [VDKT2016] p. 22.

  static AztecDiamondGraph(n)

    Return the Aztec Diamond graph of order `n`.

    See the Wikipedia article Aztec_diamond for more information.

    EXAMPLES:

    Sage

        sage: graphs.AztecDiamondGraph(2)
        Aztec Diamond graph of order 2

        sage: [graphs.AztecDiamondGraph(i).n_vertices() for i in range(8)]
        [0, 4, 12, 24, 40, 60, 84, 112]

        sage: [graphs.AztecDiamondGraph(i).n_edges() for i in range(8)]
        [0, 4, 16, 36, 64, 100, 144, 196]

        sage: G = graphs.AztecDiamondGraph(3)
        sage: sum(1 for p in G.perfect_matchings())
        64

    Python

        >>> from sage.all import *
        >>> graphs.AztecDiamondGraph(Integer(2))
        Aztec Diamond graph of order 2

        >>> [graphs.AztecDiamondGraph(i).n_vertices() for i in range(Integer(8))]
        [0, 4, 12, 24, 40, 60, 84, 112]

        >>> [graphs.AztecDiamondGraph(i).n_edges() for i in range(Integer(8))]
        [0, 4, 16, 36, 64, 100, 144, 196]

        >>> G = graphs.AztecDiamondGraph(Integer(3))
        >>> sum(Integer(1) for p in G.perfect_matchings())
        64

  static Balaban10Cage(embedding=1)

    Return the Balaban 10-cage.

    The Balaban 10-cage is a 3-regular graph with 70 vertices and 105 edges. See the Wikipedia article Balaban_10-cage.

    The default embedding gives a deeper understanding of the graph’s automorphism group. It is divided into 4 layers (each layer being a set of points at equal distance from the drawing’s center). From outside to inside:

    - L1: The outer layer (vertices which are the furthest from the origin) is actually the disjoint union of two cycles of length 10.

    - L2: The second layer is an independent set of 20 vertices.

    - L3: The third layer is a matching on 10 vertices.

    - L4: The inner layer (vertices which are the closest from the origin) is also the disjoint union of two cycles of length 10.

    This graph is not vertex-transitive, and its vertices are partitioned into 3 orbits: L2, L3, and the union of L1 of L4 whose elements are equivalent.

    INPUT:

    - `embedding` – integer (default: \(1\)); two embeddings are available, and can be selected by setting `embedding` to be either 1 or 2

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.Balaban10Cage()
        sage: g.girth()
        10
        sage: g.chromatic_number()
        2
        sage: g.diameter()
        6
        sage: g.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        sage: g.show(figsize=[10,10])           # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.Balaban10Cage()
        >>> g.girth()
        10
        >>> g.chromatic_number()
        2
        >>> g.diameter()
        6
        >>> g.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        >>> g.show(figsize=[Integer(10),Integer(10)])           # long time                             # needs sage.plot

  static Balaban11Cage(embedding=1)

    Return the Balaban 11-cage.

    For more information, see the Wikipedia article Balaban_11-cage.

    INPUT:

    - `embedding` – integer (default: \(1\)); three embeddings are available, and can be selected by setting `embedding` to be 1, 2, or 3

      - The first embedding is the one appearing on page 9 of the Fifth Annual Graph Drawing Contest report [EMMN1998]. It separates vertices based on their eccentricity (see `eccentricity()`).

      - The second embedding has been produced just for Sage and is meant to emphasize the automorphism group’s 6 orbits.

      - The last embedding is the default one produced by the `LCFGraph()` constructor.

    Note

    The vertex labeling changes according to the value of `embedding=1`.

    EXAMPLES:

    Basic properties:

    Sage

        sage: g = graphs.Balaban11Cage()
        sage: g.order()
        112
        sage: g.size()
        168
        sage: g.girth()
        11
        sage: g.diameter()
        8
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        64

    Python

        >>> from sage.all import *
        >>> g = graphs.Balaban11Cage()
        >>> g.order()
        112
        >>> g.size()
        168
        >>> g.girth()
        11
        >>> g.diameter()
        8
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        64

    Our many embeddings:

    Sage

        sage: g1 = graphs.Balaban11Cage(embedding=1)
        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 networkx sage.plot

    [Python]

        >>> from sage.all import *
        >>> g1 = graphs.Balaban11Cage(embedding=Integer(1))
        >>> g2 = graphs.Balaban11Cage(embedding=Integer(2))                                    # needs networkx
        >>> g3 = graphs.Balaban11Cage(embedding=Integer(3))                                    # needs networkx
        >>> g1.show(figsize=[Integer(10),Integer(10)])          # long time                             # needs sage.plot
        >>> g2.show(figsize=[Integer(10),Integer(10)])          # long time                             # needs networkx sage.plot
        >>> g3.show(figsize=[Integer(10),Integer(10)])          # long time                             # needs networkx sage.plot

    Proof that the embeddings are the same graph:

    Sage

        sage: g1.is_isomorphic(g2)  # g2 and g3 are obviously isomorphic                # needs networkx
        True

    Python

        >>> from sage.all import *
        >>> g1.is_isomorphic(g2)  # g2 and g3 are obviously isomorphic                # needs networkx
        True

  static BalancedTree(r, h)

    Return the perfectly balanced tree of height \(h \geq 1\), whose root has degree \(r \geq 2\).

    The number of vertices of this graph is \(1 + r + r^2 + \cdots + r^h\), that is, \(\frac{r^{h+1} - 1}{r - 1}\). The number of edges is one less than the number of vertices.

    INPUT:

    - `r` – positive integer \(\geq 2\); the degree of the root node

    - `h` – positive integer \(\geq 1\); the height of the balanced tree

    OUTPUT:

    The perfectly balanced tree of height \(h \geq 1\) and whose root has degree \(r \geq 2\).

    EXAMPLES:

    A balanced tree whose root node has degree \(r = 2\), and of height \(h = 1\), has order 3 and size 2:

    Sage

        sage: G = graphs.BalancedTree(2, 1); G
        Balanced tree: Graph on 3 vertices
        sage: G.order()
        3
        sage: G.size()
        2
        sage: r = 2; h = 1
        sage: v = 1 + r
        sage: v; v - 1
        3
        2

    Python

        >>> from sage.all import *
        >>> G = graphs.BalancedTree(Integer(2), Integer(1)); G
        Balanced tree: Graph on 3 vertices
        >>> G.order()
        3
        >>> G.size()
        2
        >>> r = Integer(2); h = Integer(1)
        >>> v = Integer(1) + r
        >>> v; v - Integer(1)
        3
        2

    Plot a balanced tree of height 5, whose root node has degree \(r = 3\):

    Sage

        sage: G = graphs.BalancedTree(3, 5)
        sage: G.plot()                          # long time                             # needs sage.plot
        Graphics object consisting of 728 graphics primitives

    [Python]

        >>> from sage.all import *
        >>> G = graphs.BalancedTree(Integer(3), Integer(5))
        >>> G.plot()                          # long time                             # needs sage.plot
        Graphics object consisting of 728 graphics primitives

    A tree is bipartite. If its vertex set is finite, then it is planar:

    Sage

        sage: # needs networkx
        sage: r = randint(2, 5); h = randint(1, 7)
        sage: T = graphs.BalancedTree(r, h)
        sage: T.is_bipartite()
        True
        sage: T.is_planar()
        True
        sage: v = (r^(h + 1) - 1) / (r - 1)
        sage: T.order() == v
        True
        sage: T.size() == v - 1
        True

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> r = randint(Integer(2), Integer(5)); h = randint(Integer(1), Integer(7))
        >>> T = graphs.BalancedTree(r, h)
        >>> T.is_bipartite()
        True
        >>> T.is_planar()
        True
        >>> v = (r**(h + Integer(1)) - Integer(1)) / (r - Integer(1))
        >>> T.order() == v
        True
        >>> T.size() == v - Integer(1)
        True

  static BarbellGraph(n1, n2)

    Return a barbell graph with \(2 n_1 + n_2\) nodes.

    The argument \(n_1\) must be greater than or equal to 2.

    A barbell graph is a basic structure that consists of a path graph of order \(n_2\) connecting two complete graphs of order \(n_1\) each.

    INPUT:

    - `n1` – integer \(\geq 2\); the order of each of the two complete graphs

    - `n2` – nonnegative integer; the order of the path graph connecting the two complete graphs

    OUTPUT:

    A barbell graph of order \(2*n_1 + n_2\). A `ValueError` is returned if \(n_1 < 2\) or \(n_2 < 0\).

    PLOTTING:

    Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each barbell graph will be displayed with the two complete graphs in the lower-left and upper-right corners, with the path graph connecting diagonally between the two. Thus the \(n_1\)-th node will be drawn at a 45 degree angle from the horizontal right center of the first complete graph, and the \(n_1 + n_2 + 1\)-th node will be drawn 45 degrees below the left horizontal center of the second complete graph.

    EXAMPLES:

    Construct and show a barbell graph `Bar = 4`, `Bells = 9`:

    Sage

        sage: g = graphs.BarbellGraph(9, 4); g
        Barbell graph: Graph on 22 vertices
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.BarbellGraph(Integer(9), Integer(4)); g
        Barbell graph: Graph on 22 vertices
        >>> g.show()                          # long time                             # needs sage.plot

    An \(n_1 \geq 2\), \(n_2 \geq 0\) barbell graph has order \(2*n_1 + n_2\). It has the complete graph on \(n_1\) vertices as a subgraph. It also has the path graph on \(n_2\) vertices as a subgraph.

    Sage

        sage: n1 = randint(2, 2*10^2)
        sage: n2 = randint(0, 2*10^2)
        sage: g = graphs.BarbellGraph(n1, n2)
        sage: v = 2*n1 + n2
        sage: g.order() == v
        True
        sage: K_n1 = graphs.CompleteGraph(n1)
        sage: P_n2 = graphs.PathGraph(n2)

        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)
        True

    [Python]

        >>> from sage.all import *
        >>> n1 = randint(Integer(2), Integer(2)*Integer(10)**Integer(2))
        >>> n2 = randint(Integer(0), Integer(2)*Integer(10)**Integer(2))
        >>> g = graphs.BarbellGraph(n1, n2)
        >>> v = Integer(2)*n1 + n2
        >>> g.order() == v
        True
        >>> K_n1 = graphs.CompleteGraph(n1)
        >>> P_n2 = graphs.PathGraph(n2)

        >>> # needs sage.modules
        >>> s_K = g.subgraph_search(K_n1, induced=True)
        >>> s_P = g.subgraph_search(P_n2, induced=True)
        >>> K_n1.is_isomorphic(s_K)
        True
        >>> P_n2.is_isomorphic(s_P)
        True

  static BidiakisCube()

    Return the Bidiakis cube.

    For more information, see the Wikipedia article Bidiakis_cube.

    EXAMPLES:

    The Bidiakis cube is a 3-regular graph having 12 vertices and 18 edges. This means that each vertex has a degree of 3:

    Sage

        sage: g = graphs.BidiakisCube(); g
        Bidiakis cube: Graph on 12 vertices
        sage: g.show()                          # long time                             # needs sage.plot
        sage: g.order()
        12
        sage: g.size()
        18
        sage: g.is_regular(3)
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.BidiakisCube(); g
        Bidiakis cube: Graph on 12 vertices
        >>> g.show()                          # long time                             # needs sage.plot
        >>> g.order()
        12
        >>> g.size()
        18
        >>> g.is_regular(Integer(3))
        True

    It is a Hamiltonian graph with diameter 3 and girth 4:

    Sage

        sage: g.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        sage: g.diameter()
        3
        sage: g.girth()
        4

    [Python]

        >>> from sage.all import *
        >>> g.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        >>> g.diameter()
        3
        >>> g.girth()
        4

    It is a planar graph with characteristic polynomial \((x - 3) (x - 2) (x^4) (x + 1) (x + 2) (x^2 + x - 4)^2\) and chromatic number 3:

    Sage

        sage: g.is_planar()
        True
        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()                                                      # needs sage.modules
        3

    Python

        >>> from sage.all import *
        >>> g.is_planar()
        True
        >>> char_poly = g.characteristic_polynomial()                                 # needs sage.modules
        >>> x = char_poly.parent()('x')                                               # needs sage.modules
        >>> char_poly == (x - Integer(3)) * (x - Integer(2)) * (x**Integer(4)) * (x + Integer(1)) * (x + Integer(2)) * (x**Integer(2) + x - Integer(4))**Integer(2)          # needs sage.modules
        True
        >>> g.chromatic_number()                                                      # needs sage.modules
        3

  static BiggsSmithGraph(embedding=1)

    Return the Biggs-Smith graph.

    For more information, see the Wikipedia article Biggs-Smith_graph.

    INPUT:

    - `embedding` – integer (default: \(1\)); two embeddings are available, and can be selected by setting `embedding` to be 1 or 2

    EXAMPLES:

    Basic properties:

    Sage

        sage: # needs networkx
        sage: g = graphs.BiggsSmithGraph()
        sage: g.order()
        102
        sage: g.size()
        153
        sage: g.girth()
        9
        sage: g.diameter()
        7
        sage: g.automorphism_group().cardinality()      # long time
        2448
        sage: g.show(figsize=[10, 10])          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.BiggsSmithGraph()
        >>> g.order()
        102
        >>> g.size()
        153
        >>> g.girth()
        9
        >>> g.diameter()
        7
        >>> g.automorphism_group().cardinality()      # long time
        2448
        >>> g.show(figsize=[Integer(10), Integer(10)])          # long time                             # needs sage.plot

    The other embedding:

    Sage

        sage: graphs.BiggsSmithGraph(embedding=2).show()        # long time             # needs networkx

    [Python]

        >>> from sage.all import *
        >>> graphs.BiggsSmithGraph(embedding=Integer(2)).show()        # long time             # needs networkx

  static BilinearFormsGraph(d, e, q)

    Return a bilinear forms graph with the given parameters.

    This builds a graph whose vertices are all \(d`x`e\) matrices over \(GF(q)\). Two vertices are adjacent if the difference of the two matrices has rank 1.

    The graph is distance-regular with classical parameters \((\min(d, e), q, q-1 , q^{\max(d, e)}-1)\).

    INPUT:

    - `d`, `e` – integers; dimension of the matrices

    - `q` – integer; a prime power

    EXAMPLES:

    Sage

        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)             # 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                     # 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])

    Python

        >>> from sage.all import *
        >>> # needs sage.modules
        >>> G = graphs.BilinearFormsGraph(Integer(3), Integer(3), Integer(2))
        >>> G.is_distance_regular(True)
        ([49, 36, 16, None], [None, 1, 6, 28])
        >>> G = graphs.BilinearFormsGraph(Integer(3),Integer(3),Integer(3))      # not tested (20 s)             # needs sage.rings.finite_rings
        >>> G.order()                         # not tested (due to above)             # needs sage.rings.finite_rings
        19683
        >>> G = graphs.BilinearFormsGraph(Integer(3), Integer(4), Integer(2))    # long time                     # needs sage.rings.finite_rings
        >>> G.is_distance_regular(True)       # long time                             # needs sage.rings.finite_rings
        ([105, 84, 48, None], [None, 1, 6, 28])

    REFERENCES:

    See [BCN1989] pp. 280-282 for a rather detailed discussion, otherwise see [VDKT2016] p. 21.

  static BishopGraph(dim_list, radius=None, relabel=False)

    Return the \(d\)-dimensional Bishop Graph with prescribed dimensions.

    The 2-dimensional Bishop Graph of parameters \(n\) and \(m\) is a graph with \(nm\) vertices in which each vertex represents a square in an \(n \times m\) chessboard, and each edge corresponds to a legal move by a bishop.

    The \(d\)-dimensional Bishop Graph with \(d >= 2\) has for vertex set the cells of a \(d\)-dimensional grid with prescribed dimensions, and each edge corresponds to a legal move by a bishop in any pairs of dimensions.

    The Bishop Graph is not connected.

    INPUT:

    - `dim_list` – iterable (list, set, dict); provides the dimensions \(n_1, n_2, \ldots, n_d\), with \(n_i \geq 1\), of the chessboard

    - `radius` – integer (default: `None`); by setting the radius to a positive integer, one may decrease the power of the bishop to at most `radius` steps.

    - `relabel` – boolean (default: `False`); indicates whether the vertices must be relabeled as integers

    EXAMPLES:

    The (n,m)-Bishop Graph is not connected:

    Sage

        sage: G = graphs.BishopGraph( [3, 4] )
        sage: G.is_connected()
        False

    Python

        >>> from sage.all import *
        >>> G = graphs.BishopGraph( [Integer(3), Integer(4)] )
        >>> G.is_connected()
        False

    The Bishop Graph can be obtained from Knight Graphs:

    Sage

        sage: for d in range(3,12):   # long time
        ....:     H = Graph()
        ....:     for r in range(1,d+1):
        ....:         B = graphs.BishopGraph([d,d],radius=r)
        ....:         H.add_edges( graphs.KnightGraph([d,d],one=r,two=r).edges(sort=False) )
        ....:         if not B.is_isomorphic(H):
        ....:            print("that's not good!")

    [Python]

        >>> from sage.all import *
        >>> for d in range(Integer(3),Integer(12)):   # long time
        ...     H = Graph()
        ...     for r in range(Integer(1),d+Integer(1)):
        ...         B = graphs.BishopGraph([d,d],radius=r)
        ...         H.add_edges( graphs.KnightGraph([d,d],one=r,two=r).edges(sort=False) )
        ...         if not B.is_isomorphic(H):
        ...            print("that's not good!")

  static BiwheelGraph(n)

    Return a biwheel graph with \(2n\) nodes

    For \(n \geq 4\), the biwheel graph of order \(2n\) is the planar bipartite graph obtained from the cycle graph of order \(2n - 2\), i.e., `graphs.CycleGraph(2*n - 2)` (called the \(rim\) of the biwheel graph) by introducing two new nodes \(2n - 2\) and \(2n - 1\) (called the hubs of the biwheel graph), and then joining the node \(2n - 2\) with the odd indexed nodes up to \(2n - 3\) and joining the node \(2n - 1\) with the even indexed nodes up to \(2n - 4\).

    PLOTTING:

    Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each biwheel graph will be displayed with the first (0) node at the right if \(n\) is even or otherwise at an angle \(\pi / (2n - 2)\) with respect to the origin, with the rest of the nodes up to \(2n - 3\) following in a counterclockwise manner. Note that the last two nodes, i.e., the hubs \(2n - 2\) and \(2n - 1\) will be displayed at the coordinates \((-1/3, 0)\) and \((1/3, 0)\) respectively.

    INPUT:

    - `n` – an integer at least 4; number of nodes is \(2n\)

    OUTPUT:

    - `G` – a biwheel graph of order \(2n\); note that a `ValueError` is returned if \(n < 4\)

    EXAMPLES:

    Construct and show a biwheel graph with 10 nodes:

    Sage

        sage: g = graphs.BiwheelGraph(5)
        sage: g.show()                          # long time                             # needs sage.plot
        sage: g.is_planar()
        True
        sage: g.is_bipartite()
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.BiwheelGraph(Integer(5))
        >>> g.show()                          # long time                             # needs sage.plot
        >>> g.is_planar()
        True
        >>> g.is_bipartite()
        True

    Create several biwheel graphs in a Sage graphics array:

    Sage

        sage: # needs sage.plots
        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:    k = graphs.BiwheelGraph(i+4)
        ....:    g.append(k)
        sage: for i in range(3):
        ....:    n = []
        ....:    for m in range(3):
        ....:        n.append(g[3*i + m].plot(vertex_size=50 - 4*(3*i+m), vertex_labels=False))
        ....:    j.append(n)
        sage: G = graphics_array(j)
        sage: G.show()                          # long time

    [Python]

        >>> from sage.all import *
        >>> # needs sage.plots
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...    k = graphs.BiwheelGraph(i+Integer(4))
        ...    g.append(k)
        >>> for i in range(Integer(3)):
        ...    n = []
        ...    for m in range(Integer(3)):
        ...        n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50) - Integer(4)*(Integer(3)*i+m), vertex_labels=False))
        ...    j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    REFERENCES:

    - [LM2024]

    See also

    `WheelGraph()`, `TruncatedBiwheelGraph()`

    AUTHORS:

    - Janmenjaya Panda (2024-06-09)

  static BlanusaFirstSnarkGraph()

    Return the first Blanusa Snark Graph.

    The Blanusa graphs are two snarks on 18 vertices and 27 edges. For more information on them, see the Wikipedia article Blanusa_snarks.

    See also

    - `BlanusaSecondSnarkGraph()`.

    EXAMPLES:

    Sage

        sage: g = graphs.BlanusaFirstSnarkGraph()
        sage: g.order()
        18
        sage: g.size()
        27
        sage: g.diameter()
        4
        sage: g.girth()
        5
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        8

    Python

        >>> from sage.all import *
        >>> g = graphs.BlanusaFirstSnarkGraph()
        >>> g.order()
        18
        >>> g.size()
        27
        >>> g.diameter()
        4
        >>> g.girth()
        5
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        8

  static BlanusaSecondSnarkGraph()

    Return the second Blanusa Snark Graph.

    The Blanusa graphs are two snarks on 18 vertices and 27 edges. For more information on them, see the Wikipedia article Blanusa_snarks.

    See also

    - `BlanusaFirstSnarkGraph()`.

    EXAMPLES:

    Sage

        sage: g = graphs.BlanusaSecondSnarkGraph()
        sage: g.order()
        18
        sage: g.size()
        27
        sage: g.diameter()
        4
        sage: g.girth()
        5
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        4

    Python

        >>> from sage.all import *
        >>> g = graphs.BlanusaSecondSnarkGraph()
        >>> g.order()
        18
        >>> g.size()
        27
        >>> g.diameter()
        4
        >>> g.girth()
        5
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        4

  static BrinkmannGraph()

    Return the Brinkmann graph.

    For more information, see the Wikipedia article Brinkmann_graph.

    EXAMPLES:

    The Brinkmann graph is a 4-regular graph having 21 vertices and 42 edges. This means that each vertex has degree 4:

    Sage

        sage: G = graphs.BrinkmannGraph(); G
        Brinkmann graph: Graph on 21 vertices
        sage: G.show()                          # long time                             # needs sage.plot
        sage: G.order()
        21
        sage: G.size()
        42
        sage: G.is_regular(4)
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.BrinkmannGraph(); G
        Brinkmann graph: Graph on 21 vertices
        >>> G.show()                          # long time                             # needs sage.plot
        >>> G.order()
        21
        >>> G.size()
        42
        >>> G.is_regular(Integer(4))
        True

    It is an Eulerian graph with radius 3, diameter 3, and girth 5:

    Sage

        sage: G.is_eulerian()
        True
        sage: G.radius()
        3
        sage: G.diameter()
        3
        sage: G.girth()
        5

    [Python]

        >>> from sage.all import *
        >>> G.is_eulerian()
        True
        >>> G.radius()
        3
        >>> G.diameter()
        3
        >>> G.girth()
        5

    The Brinkmann graph is also Hamiltonian with chromatic number 4:

    Sage

        sage: G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        sage: G.chromatic_number()
        4

    Python

        >>> from sage.all import *
        >>> G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        >>> G.chromatic_number()
        4

    Its automorphism group is isomorphic to \(D_7\):

    Sage

        sage: ag = G.automorphism_group()                                               # needs sage.groups
        sage: ag.is_isomorphic(DihedralGroup(7))                                        # needs sage.groups
        True

    [Python]

        >>> from sage.all import *
        >>> ag = G.automorphism_group()                                               # needs sage.groups
        >>> ag.is_isomorphic(DihedralGroup(Integer(7)))                                        # needs sage.groups
        True

  static BrouwerHaemersGraph()

    Return the Brouwer-Haemers Graph.

    The Brouwer-Haemers is the only strongly regular graph of parameters \((81,20,1,6)\). It is build in Sage as the Affine Orthogonal graph \(VO^-(6,3)\). For more information on this graph, see its corresponding page on Andries Brouwer’s website.

    EXAMPLES:

    Sage

        sage: g = graphs.BrouwerHaemersGraph(); g                                       # needs sage.modules
        Brouwer-Haemers: Graph on 81 vertices

    Python

        >>> from sage.all import *
        >>> 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

        sage: g.is_strongly_regular(parameters=True)    # long time                     # needs sage.modules sage.rings.finite_rings
        (81, 20, 1, 6)

    [Python]

        >>> from sage.all import *
        >>> 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

        sage: set(g.spectrum()) == {20,2,-7}                                            # needs sage.modules sage.rings.finite_rings
        True

    Python

        >>> from sage.all import *
        >>> set(g.spectrum()) == {Integer(20),Integer(2),-Integer(7)}                                            # needs sage.modules sage.rings.finite_rings
        True

  static BubbleSortGraph(n)

    Return the bubble sort graph \(B(n)\).

    The vertices of the bubble sort graph are the set of permutations on \(n\) symbols. Two vertices are adjacent if one can be obtained from the other by swapping the labels in the \(i\)-th and \((i+1)\)-th positions for \(1 \leq i \leq n-1\). In total, \(B(n)\) has order \(n!\). Swapping two labels as described previously corresponds to multiplying on the right the permutation corresponding to the node by an elementary transposition in the `SymmetricGroup`.

    The bubble sort graph is the underlying graph of the `permutahedron()`.

    INPUT:

    - `n` – positive integer. The number of symbols to permute

    OUTPUT:

    The bubble sort graph \(B(n)\) on \(n\) symbols. If \(n < 1\), a `ValueError` is returned.

    EXAMPLES:

    Sage

        sage: g = graphs.BubbleSortGraph(4); g
        Bubble sort: Graph on 24 vertices
        sage: g.plot()                          # long time                             # needs sage.plot
        Graphics object consisting of 61 graphics primitives

    Python

        >>> from sage.all import *
        >>> g = graphs.BubbleSortGraph(Integer(4)); g
        Bubble sort: Graph on 24 vertices
        >>> g.plot()                          # long time                             # needs sage.plot
        Graphics object consisting of 61 graphics primitives

    The bubble sort graph on \(n = 1\) symbol is the trivial graph \(K_1\):

    Sage

        sage: graphs.BubbleSortGraph(1)
        Bubble sort: Graph on 1 vertex

    [Python]

        >>> from sage.all import *
        >>> graphs.BubbleSortGraph(Integer(1))
        Bubble sort: Graph on 1 vertex

    If \(n \geq 1\), then the order of \(B(n)\) is \(n!\):

    Sage

        sage: n = randint(1, 8)
        sage: g = graphs.BubbleSortGraph(n)
        sage: g.order() == factorial(n)
        True

    Python

        >>> from sage.all import *
        >>> n = randint(Integer(1), Integer(8))
        >>> g = graphs.BubbleSortGraph(n)
        >>> g.order() == factorial(n)
        True

    See also

    - `permutahedron()`

    AUTHORS:

    - Michael Yurko (2009-09-01)

  static BuckyBall()

    Return the Bucky Ball graph.

    This graph is a 3-regular 60-vertex planar graph. Its vertices and edges correspond precisely to the carbon atoms and bonds in buckminsterfullerene. When embedded on a sphere, its 12 pentagon and 20 hexagon faces are arranged exactly as the sections of a soccer ball.

    EXAMPLES:

    The Bucky Ball is planar:

    Sage

        sage: g = graphs.BuckyBall()
        sage: g.is_planar()
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.BuckyBall()
        >>> g.is_planar()
        True

    The Bucky Ball can also be created by extracting the 1-skeleton of the Bucky Ball polyhedron, but this is much slower:

    Sage

        sage: # needs sage.geometry.polyhedron sage.groups sage.rings.number_field
        sage: g = polytopes.buckyball().vertex_graph()
        sage: g.remove_loops()
        sage: h = graphs.BuckyBall()
        sage: g.is_isomorphic(h)
        True

    [Python]

        >>> from sage.all import *
        >>> # needs sage.geometry.polyhedron sage.groups sage.rings.number_field
        >>> g = polytopes.buckyball().vertex_graph()
        >>> g.remove_loops()
        >>> h = graphs.BuckyBall()
        >>> g.is_isomorphic(h)
        True

    The graph is returned along with an attractive embedding:

    Sage

        sage: g = graphs.BuckyBall()  # long time
        sage: g.plot(vertex_labels=False, vertex_size=10).show()        # long time, needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.BuckyBall()  # long time
        >>> g.plot(vertex_labels=False, vertex_size=Integer(10)).show()        # long time, needs sage.plot

  static BullGraph(immutable=False)

    Return a bull graph with 5 nodes.

    A bull graph is named for its shape. It’s a triangle with horns. See the Wikipedia article Bull_graph for more information.

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    PLOTTING:

    Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the bull graph is drawn as a triangle with the first node (0) on the bottom. The second and third nodes (1 and 2) complete the triangle. Node 3 is the horn connected to 1 and node 4 is the horn connected to node 2.

    EXAMPLES:

    Construct and show a bull graph:

    Sage

        sage: g = graphs.BullGraph(); g
        Bull graph: Graph on 5 vertices
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.BullGraph(); g
        Bull graph: Graph on 5 vertices
        >>> g.show()                          # long time                             # needs sage.plot

    The bull graph has 5 vertices and 5 edges. Its radius is 2, its diameter 3, and its girth 3. The bull graph is planar with chromatic number 3 and chromatic index also 3:

    Sage

        sage: g.order(); g.size()
        5
        5
        sage: g.radius(); g.diameter(); g.girth()
        2
        3
        3
        sage: g.chromatic_number()
        3

    [Python]

        >>> from sage.all import *
        >>> g.order(); g.size()
        5
        5
        >>> g.radius(); g.diameter(); g.girth()
        2
        3
        3
        >>> g.chromatic_number()
        3

    The bull graph has chromatic polynomial \(x(x - 2)(x - 1)^3\) and Tutte polynomial \(x^4 + x^3 + x^2 y\). Its characteristic polynomial is \(x(x^2 - x - 3)(x^2 + x - 1)\), which follows from the definition of characteristic polynomials for graphs, i.e. \(\det(xI - A)\), where \(x\) is a variable, \(A\) the adjacency matrix of the graph, and \(I\) the identity matrix of the same dimensions as \(A\):

    Sage

        sage: # needs sage.libs.flint
        sage: chrompoly = g.chromatic_polynomial()
        sage: x = chrompoly.parent()('x')
        sage: x * (x - 2) * (x - 1)^3 == chrompoly
        True

        sage: # needs sage.libs.flint sage.modules
        sage: charpoly = g.characteristic_polynomial()
        sage: M = g.adjacency_matrix(); M
        [0 1 1 0 0]
        [1 0 1 1 0]
        [1 1 0 0 1]
        [0 1 0 0 0]
        [0 0 1 0 0]
        sage: Id = identity_matrix(ZZ, M.nrows())
        sage: D = x*Id - M
        sage: D.determinant() == charpoly                                               # needs sage.symbolic
        True
        sage: x * (x^2 - x - 3) * (x^2 + x - 1) == charpoly
        True

    Python

        >>> from sage.all import *
        >>> # needs sage.libs.flint
        >>> chrompoly = g.chromatic_polynomial()
        >>> x = chrompoly.parent()('x')
        >>> x * (x - Integer(2)) * (x - Integer(1))**Integer(3) == chrompoly
        True

        >>> # needs sage.libs.flint sage.modules
        >>> charpoly = g.characteristic_polynomial()
        >>> M = g.adjacency_matrix(); M
        [0 1 1 0 0]
        [1 0 1 1 0]
        [1 1 0 0 1]
        [0 1 0 0 0]
        [0 0 1 0 0]
        >>> Id = identity_matrix(ZZ, M.nrows())
        >>> D = x*Id - M
        >>> D.determinant() == charpoly                                               # needs sage.symbolic
        True
        >>> x * (x**Integer(2) - x - Integer(3)) * (x**Integer(2) + x - Integer(1)) == charpoly
        True

  static ButterflyGraph(immutable=False)

    Return the butterfly graph.

    Let \(C_3\) be the cycle graph on 3 vertices. The butterfly or bowtie graph is obtained by joining two copies of \(C_3\) at a common vertex, resulting in a graph that is isomorphic to the friendship graph \(F_2\). See the Wikipedia article Butterfly_graph for more information.

    See also

    - `FriendshipGraph()`

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    The butterfly graph is a planar graph on 5 vertices and having 6 edges:

    Sage

        sage: G = graphs.ButterflyGraph(); G
        Butterfly graph: Graph on 5 vertices
        sage: G.show()                          # long time                             # needs sage.plot
        sage: G.is_planar()
        True
        sage: G.order()
        5
        sage: G.size()
        6

    Python

        >>> from sage.all import *
        >>> G = graphs.ButterflyGraph(); G
        Butterfly graph: Graph on 5 vertices
        >>> G.show()                          # long time                             # needs sage.plot
        >>> G.is_planar()
        True
        >>> G.order()
        5
        >>> G.size()
        6

    It has diameter 2, girth 3, and radius 1:

    Sage

        sage: G.diameter()
        2
        sage: G.girth()
        3
        sage: G.radius()
        1

    [Python]

        >>> from sage.all import *
        >>> G.diameter()
        2
        >>> G.girth()
        3
        >>> G.radius()
        1

    The butterfly graph is Eulerian, with chromatic number 3:

    Sage

        sage: G.is_eulerian()
        True
        sage: G.chromatic_number()
        3

    Python

        >>> from sage.all import *
        >>> G.is_eulerian()
        True
        >>> G.chromatic_number()
        3

  static CaiFurerImmermanGraph(G, twisted=False)

    Return the a Cai-Furer-Immerman graph from \(G\), possibly a twisted one, and a partition of its nodes.

    A Cai-Furer-Immerman graph from/on \(G\) is a graph created by applying the transformation described in [CFI1992] on a graph \(G\), that is substituting every vertex v in \(G\) with a Furer gadget \(F(v)\) of order d equal to the degree of the vertex, and then substituting every edge \((v,u)\) in \(G\) with a pair of edges, one connecting the two “a” nodes of \(F(v)\) and \(F(u)\) and the other their two “b” nodes. The returned coloring of the vertices is made by the union of the colorings of each single Furer gadget, individualised for each vertex of \(G\). To understand better what these “a” and “b” nodes are, see the documentation on Furer gadgets.

    Furthermore, this method can apply what is described in the paper mentioned above as a “twist” on an edge, that is taking only one of the pairs of edges introduced in the new graph and swap two of their extremes, making each edge go from an “a” node to a “b” node. This is only doable if the original graph G is connected.

    A CaiFurerImmerman graph on a graph with no balanced vertex separators smaller than s and its twisted version cannot be distinguished by k-WL for any k < s.

    INPUT:

    - `G` – an undirected graph on which to construct the Cai-Furer-Immerman graph

    - `twisted` – a boolean indicating if the version to construct is a twisted one or not

    OUTPUT:

    - `H` – the Cai-Furer-Immerman graph on `G`

    - `coloring` – list of list of vertices, representing the partition induced by the coloring on `H`

    EXAMPLES:

    CaiFurerImmerman graph with no balanced vertex separator smaller than 2

    Sage

        sage: G = graphs.CycleGraph(4)
        sage: CFI, p = graphs.CaiFurerImmermanGraph(G)
        sage: sorted(CFI, key=str)
        [(0, ()), (0, (0, 'a')), (0, (0, 'b')), (0, (0, 1)), (0, (1, 'a')),
         (0, (1, 'b')), (1, ()), (1, (0, 'a')), (1, (0, 'b')), (1, (0, 1)),
         (1, (1, 'a')), (1, (1, 'b')), (2, ()), (2, (0, 'a')), (2, (0, 'b')),
         (2, (0, 1)), (2, (1, 'a')), (2, (1, 'b')), (3, ()), (3, (0, 'a')),
         (3, (0, 'b')), (3, (0, 1)), (3, (1, 'a')), (3, (1, 'b'))]
        sage: sorted(CFI.edge_iterator(), key=str)
        [((0, ()), (0, (0, 'b')), None),
         ((0, ()), (0, (1, 'b')), None),
         ((0, (0, 'a')), (1, (0, 'a')), None),
         ((0, (0, 'b')), (1, (0, 'b')), None),
         ((0, (0, 1)), (0, (0, 'a')), None),
         ((0, (0, 1)), (0, (1, 'a')), None),
         ((0, (1, 'a')), (3, (0, 'a')), None),
         ((0, (1, 'b')), (3, (0, 'b')), None),
         ((1, ()), (1, (0, 'b')), None),
         ((1, ()), (1, (1, 'b')), None),
         ((1, (0, 1)), (1, (0, 'a')), None),
         ((1, (0, 1)), (1, (1, 'a')), None),
         ((1, (1, 'a')), (2, (0, 'a')), None),
         ((1, (1, 'b')), (2, (0, 'b')), None),
         ((2, ()), (2, (0, 'b')), None),
         ((2, ()), (2, (1, 'b')), None),
         ((2, (0, 1)), (2, (0, 'a')), None),
         ((2, (0, 1)), (2, (1, 'a')), None),
         ((2, (1, 'a')), (3, (1, 'a')), None),
         ((2, (1, 'b')), (3, (1, 'b')), None),
         ((3, ()), (3, (0, 'b')), None),
         ((3, ()), (3, (1, 'b')), None),
         ((3, (0, 1)), (3, (0, 'a')), None),
         ((3, (0, 1)), (3, (1, 'a')), None)]

    Python

        >>> from sage.all import *
        >>> G = graphs.CycleGraph(Integer(4))
        >>> CFI, p = graphs.CaiFurerImmermanGraph(G)
        >>> sorted(CFI, key=str)
        [(0, ()), (0, (0, 'a')), (0, (0, 'b')), (0, (0, 1)), (0, (1, 'a')),
         (0, (1, 'b')), (1, ()), (1, (0, 'a')), (1, (0, 'b')), (1, (0, 1)),
         (1, (1, 'a')), (1, (1, 'b')), (2, ()), (2, (0, 'a')), (2, (0, 'b')),
         (2, (0, 1)), (2, (1, 'a')), (2, (1, 'b')), (3, ()), (3, (0, 'a')),
         (3, (0, 'b')), (3, (0, 1)), (3, (1, 'a')), (3, (1, 'b'))]
        >>> sorted(CFI.edge_iterator(), key=str)
        [((0, ()), (0, (0, 'b')), None),
         ((0, ()), (0, (1, 'b')), None),
         ((0, (0, 'a')), (1, (0, 'a')), None),
         ((0, (0, 'b')), (1, (0, 'b')), None),
         ((0, (0, 1)), (0, (0, 'a')), None),
         ((0, (0, 1)), (0, (1, 'a')), None),
         ((0, (1, 'a')), (3, (0, 'a')), None),
         ((0, (1, 'b')), (3, (0, 'b')), None),
         ((1, ()), (1, (0, 'b')), None),
         ((1, ()), (1, (1, 'b')), None),
         ((1, (0, 1)), (1, (0, 'a')), None),
         ((1, (0, 1)), (1, (1, 'a')), None),
         ((1, (1, 'a')), (2, (0, 'a')), None),
         ((1, (1, 'b')), (2, (0, 'b')), None),
         ((2, ()), (2, (0, 'b')), None),
         ((2, ()), (2, (1, 'b')), None),
         ((2, (0, 1)), (2, (0, 'a')), None),
         ((2, (0, 1)), (2, (1, 'a')), None),
         ((2, (1, 'a')), (3, (1, 'a')), None),
         ((2, (1, 'b')), (3, (1, 'b')), None),
         ((3, ()), (3, (0, 'b')), None),
         ((3, ()), (3, (1, 'b')), None),
         ((3, (0, 1)), (3, (0, 'a')), None),
         ((3, (0, 1)), (3, (1, 'a')), None)]

  static CameronGraph()

    Return the Cameron graph.

    The Cameron graph is strongly regular with parameters \(v = 231, k = 30, \lambda = 9, \mu = 3\).

    For more information on the Cameron graph, see https://www.win.tue.nl/~aeb/graphs/Cameron.html.

    EXAMPLES:

    Sage

        sage: # needs sage.groups
        sage: g = graphs.CameronGraph()
        sage: g.order()
        231
        sage: g.size()
        3465
        sage: g.is_strongly_regular(parameters=True)    # long time
        (231, 30, 9, 3)

    Python

        >>> from sage.all import *
        >>> # needs sage.groups
        >>> g = graphs.CameronGraph()
        >>> g.order()
        231
        >>> g.size()
        3465
        >>> g.is_strongly_regular(parameters=True)    # long time
        (231, 30, 9, 3)

  static Caterpillar(spine)

    Return the caterpillar tree with given spine sequence.

    A caterpillar tree consists of leaves attached to a path (the “spine”).

    INPUT:

    - `spine` – list of nonnegative integers in the form

        \([a_1, a_2, \dots, a_n]\), where \(a_i\) is the number of leaves adjacent to the \(i\)-th vertex on the spine (except for the first and last vertex, which have \(a_1 + 1\) and \(a_n + 1\) leaf-neighbors, respectively)

    OUTPUT:

    A caterpillar tree of diameter \(n+1\) on \(n + 2 + \sum_{i=1}^n a_i\) vertices, \(n\) of which are not leaves.

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm if the returned graph does not have too many vertices. The spine vertices are positioned on a straight line together with two leaves at its ends. Every edge in the drawing has unit length.

    EXAMPLES:

    Caterpillars with all-zero spine sequence are paths:

    Sage

        sage: graphs.Caterpillar([]).is_isomorphic(graphs.PathGraph(2))
        True
        sage: graphs.Caterpillar([0]).is_isomorphic(graphs.PathGraph(3))
        True
        sage: graphs.Caterpillar([0, 0]).is_isomorphic(graphs.PathGraph(4))
        True

    Python

        >>> from sage.all import *
        >>> graphs.Caterpillar([]).is_isomorphic(graphs.PathGraph(Integer(2)))
        True
        >>> graphs.Caterpillar([Integer(0)]).is_isomorphic(graphs.PathGraph(Integer(3)))
        True
        >>> graphs.Caterpillar([Integer(0), Integer(0)]).is_isomorphic(graphs.PathGraph(Integer(4)))
        True

    Caterpillars with singleton spine are stars:

    Sage

        sage: graphs.Caterpillar([1]).is_isomorphic(graphs.StarGraph(3))
        True
        sage: graphs.Caterpillar([2]).is_isomorphic(graphs.StarGraph(4))
        True
        sage: graphs.Caterpillar([3]).is_isomorphic(graphs.StarGraph(5))
        True

    [Python]

        >>> from sage.all import *
        >>> graphs.Caterpillar([Integer(1)]).is_isomorphic(graphs.StarGraph(Integer(3)))
        True
        >>> graphs.Caterpillar([Integer(2)]).is_isomorphic(graphs.StarGraph(Integer(4)))
        True
        >>> graphs.Caterpillar([Integer(3)]).is_isomorphic(graphs.StarGraph(Integer(5)))
        True

    Distinct spine sequences can yield isomorphic caterpillars:

    Sage

        sage: graphs.Caterpillar([1,1,2]).is_isomorphic(graphs.Caterpillar([2,1,1]))
        True

    Python

        >>> from sage.all import *
        >>> graphs.Caterpillar([Integer(1),Integer(1),Integer(2)]).is_isomorphic(graphs.Caterpillar([Integer(2),Integer(1),Integer(1)]))
        True

  static Cell120()

    Return the 120-Cell graph.

    This is the adjacency graph of the 120-cell. It has 600 vertices and 1200 edges. For more information, see the Wikipedia article 120-cell.

    EXAMPLES:

    Sage

        sage: # long time, needs sage.rings.number_field
        sage: g = graphs.Cell120()
        sage: g.size()
        1200
        sage: g.is_regular(4)
        True
        sage: g.is_vertex_transitive()
        True

    Python

        >>> from sage.all import *
        >>> # long time, needs sage.rings.number_field
        >>> g = graphs.Cell120()
        >>> g.size()
        1200
        >>> g.is_regular(Integer(4))
        True
        >>> g.is_vertex_transitive()
        True

  static Cell600(embedding=1)

    Return the 600-Cell graph.

    This is the adjacency graph of the 600-cell. It has 120 vertices and 720 edges. For more information, see the Wikipedia article 600-cell.

    INPUT:

    - `embedding` – integer (default: \(1\)); two different embeddings for a plot

    EXAMPLES:

    Sage

        sage: # long time, needs sage.rings.number_field
        sage: g = graphs.Cell600()
        sage: g.size()
        720
        sage: g.is_regular(12)
        True
        sage: g.is_vertex_transitive()
        True

    Python

        >>> from sage.all import *
        >>> # long time, needs sage.rings.number_field
        >>> g = graphs.Cell600()
        >>> g.size()
        720
        >>> g.is_regular(Integer(12))
        True
        >>> g.is_vertex_transitive()
        True

  static ChessboardGraphGenerator(dim_list, rook=True, rook_radius=None, bishop=True, bishop_radius=None, knight=True, knight_x=1, knight_y=2, relabel=False)

    Return a Graph built on a \(d\)-dimensional chessboard with prescribed dimensions and interconnections.

    This function allows to generate many kinds of graphs corresponding to legal movements on a \(d\)-dimensional chessboard: Queen Graph, King Graph, Knight Graphs, Bishop Graph, and many generalizations. It also allows to avoid redundant code.

    INPUT:

    - `dim_list` – iterable (list, set, dict); provides the dimensions \(n_1, n_2, \ldots, n_d\), with \(n_i \geq 1\), of the chessboard

    - `rook` – boolean (default: `True`); indicates whether the chess piece is able to move as a rook, that is at any distance along a dimension

    - `rook_radius` – integer (default: `None`); restriction on the rook-like movements to distance at most `rook_radius`

    - `bishop` – boolean (default: `True`); indicates whether the chess piece is able to move like a bishop, that is along diagonals

    - `bishop_radius` – integer (default: `None`); restriction on the bishop-like movements to distance at most `bishop_radius`

    - `knight` – boolean (default: `True`); indicating whether the chess piece is able to move like a knight

    - `knight_x` – integer (default: \(1\)); indicates the number on steps the chess piece moves in one dimension when moving like a knight

    - `knight_y` – integer (default: \(2\)); indicates the number on steps the chess piece moves in the second dimension when moving like a knight

    - `relabel` – boolean (default: `False`); indicates whether the vertices must be relabeled as integers

    OUTPUT:

    - A Graph build on a \(d\)-dimensional chessboard with prescribed dimensions, and with edges according given parameters.

    - A string encoding the dimensions. This is mainly useful for providing names to graphs.

    EXAMPLES:

    A \((2,2)\)-King Graph is isomorphic to the complete graph on 4 vertices:

    Sage

        sage: G, _ = graphs.ChessboardGraphGenerator( [2,2] )
        sage: G.is_isomorphic( graphs.CompleteGraph(4) )
        True

    Python

        >>> from sage.all import *
        >>> G, _ = graphs.ChessboardGraphGenerator( [Integer(2),Integer(2)] )
        >>> G.is_isomorphic( graphs.CompleteGraph(Integer(4)) )
        True

    A Rook’s Graph in 2 dimensions is isomorphic to the Cartesian product of 2 complete graphs:

    Sage

        sage: G, _ = graphs.ChessboardGraphGenerator([3,4], rook=True, rook_radius=None, bishop=False, knight=False)
        sage: H = (graphs.CompleteGraph(3)).cartesian_product(graphs.CompleteGraph(4))
        sage: G.is_isomorphic(H)
        True

    [Python]

        >>> from sage.all import *
        >>> G, _ = graphs.ChessboardGraphGenerator([Integer(3),Integer(4)], rook=True, rook_radius=None, bishop=False, knight=False)
        >>> H = (graphs.CompleteGraph(Integer(3))).cartesian_product(graphs.CompleteGraph(Integer(4)))
        >>> G.is_isomorphic(H)
        True

  static ChvatalGraph()

    Return the Chvatal graph.

    Chvatal graph is one of the few known graphs to satisfy Grunbaum’s conjecture that for every \(m\), \(n\), there is an \(m\)-regular, \(m\)-chromatic graph of girth at least \(n\). For more information, see the Wikipedia article Chv%C3%A1tal_graph.

    EXAMPLES:

    The Chvatal graph has 12 vertices and 24 edges. It is a 4-regular, 4-chromatic graph with radius 2, diameter 2, and girth 4:

    Sage

        sage: G = graphs.ChvatalGraph(); G
        Chvatal graph: Graph on 12 vertices
        sage: G.order(); G.size()
        12
        24
        sage: G.degree()
        [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
        sage: G.chromatic_number()
        4
        sage: G.radius(); G.diameter(); G.girth()
        2
        2
        4

    Python

        >>> from sage.all import *
        >>> G = graphs.ChvatalGraph(); G
        Chvatal graph: Graph on 12 vertices
        >>> G.order(); G.size()
        12
        24
        >>> G.degree()
        [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
        >>> G.chromatic_number()
        4
        >>> G.radius(); G.diameter(); G.girth()
        2
        2
        4

  static CirculantGraph(n, adjacency)

    Return a circulant graph with \(n\) nodes.

    A circulant graph has the property that the vertex \(i\) is connected with the vertices \(i+j\) and \(i-j\) for each \(j\) in `adjacency`.

    INPUT:

    - `n` – number of vertices in the graph

    - `adjacency` – the list of \(j\) values

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each circulant graph will be displayed with the first (0) node at the top, with the rest following in a counterclockwise manner.

    Filling the position dictionary in advance adds \(O(n)\) to the constructor.

    See also

    - `is_circulant()` – checks whether a (di)graph is circulant, and/or returns all possible sets of parameters.

    EXAMPLES: Compare plotting using the predefined layout and networkx:

    Sage

        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
        sage: posdict23.show()  # long time

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> import networkx
        >>> n = networkx.cycle_graph(Integer(23))
        >>> spring23 = Graph(n)
        >>> posdict23 = graphs.CirculantGraph(Integer(23),Integer(2))
        >>> spring23.show()                   # long time
        >>> 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

        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):
        ....:     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)
        sage: G.show()                          # long time

    [Python]

        >>> from sage.all import *
        >>> # needs sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     k = graphs.CirculantGraph(i+Integer(4), i+Integer(1))
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    Compare to plotting with the spring-layout algorithm:

    Sage

        sage: # needs networkx sage.plot
        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     spr = networkx.cycle_graph(i+3)
        ....:     k = Graph(spr)
        ....:     g.append(k)
        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)
        sage: G.show()                          # long time

    Python

        >>> from sage.all import *
        >>> # needs networkx sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     spr = networkx.cycle_graph(i+Integer(3))
        ...     k = Graph(spr)
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...  n = []
        ...  for m in range(Integer(3)):
        ...      n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...  j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    Passing a 1 into adjacency should give the cycle.

    Sage

        sage: graphs.CirculantGraph(6,1) == graphs.CycleGraph(6)
        True
        sage: graphs.CirculantGraph(7,[1,3]).edges(sort=True, labels=false)
        [(0, 1),
        (0, 3),
        (0, 4),
        (0, 6),
        (1, 2),
        (1, 4),
        (1, 5),
        (2, 3),
        (2, 5),
        (2, 6),
        (3, 4),
        (3, 6),
        (4, 5),
        (5, 6)]

    [Python]

        >>> from sage.all import *
        >>> graphs.CirculantGraph(Integer(6),Integer(1)) == graphs.CycleGraph(Integer(6))
        True
        >>> graphs.CirculantGraph(Integer(7),[Integer(1),Integer(3)]).edges(sort=True, labels=false)
        [(0, 1),
        (0, 3),
        (0, 4),
        (0, 6),
        (1, 2),
        (1, 4),
        (1, 5),
        (2, 3),
        (2, 5),
        (2, 6),
        (3, 4),
        (3, 6),
        (4, 5),
        (5, 6)]

  static CircularLadderGraph(n, immutable=False)

    Return a circular ladder graph with \(2 * n\) nodes.

    A Circular ladder graph is a ladder graph that is connected at the ends, i.e.: a ladder bent around so that top meets bottom. Thus it can be described as two parallel cycle graphs connected at each corresponding node pair.

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the circular ladder graph is displayed as an inner and outer cycle pair, with the first \(n\) nodes drawn on the inner circle. The first (0) node is drawn at the top of the inner-circle, moving clockwise after that. The outer circle is drawn with the \((n+1)\)-th node at the top, then counterclockwise as well. When \(n == 2\), we rotate the outer circle by an angle of \(\pi/8\) to ensure that all edges are visible (otherwise the 4 vertices of the graph would be placed on a single line).

    INPUT:

    - `n` – nonnegative integer

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Construct and show a circular ladder graph with 26 nodes:

    Sage

        sage: g = graphs.CircularLadderGraph(13)
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.CircularLadderGraph(Integer(13))
        >>> g.show()                          # long time                             # needs sage.plot

    Create several circular ladder graphs in a Sage graphics array:

    Sage

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:    k = graphs.CircularLadderGraph(i+3)
        ....:    g.append(k)
        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)                                                     # needs sage.plot
        sage: G.show()                          # long time                             # needs sage.plot

    [Python]

        >>> from sage.all import *
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...    k = graphs.CircularLadderGraph(i+Integer(3))
        ...    g.append(k)
        >>> for i in range(Integer(3)):                                                        # needs sage.plot
        ...    n = []
        ...    for m in range(Integer(3)):
        ...        n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...    j.append(n)
        >>> G = graphics_array(j)                                                     # needs sage.plot
        >>> G.show()                          # long time                             # needs sage.plot

  static ClawGraph(immutable=False)

    Return a claw graph.

    A claw graph is named for its shape. It is actually a complete bipartite graph with `(n1, n2) = (1, 3)`.

    PLOTTING: See `CompleteBipartiteGraph()`.

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Show a Claw graph:

    Sage

        sage: (graphs.ClawGraph()).show()       # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> (graphs.ClawGraph()).show()       # long time                             # needs sage.plot

    Inspect a Claw graph:

    Sage

        sage: G = graphs.ClawGraph()
        sage: G
        Claw graph: Graph on 4 vertices

    [Python]

        >>> from sage.all import *
        >>> G = graphs.ClawGraph()
        >>> G
        Claw graph: Graph on 4 vertices

  static ClebschGraph()

    Return the Clebsch graph.

    See the Wikipedia article Clebsch_graph for more information.

    EXAMPLES:

    Sage

        sage: g = graphs.ClebschGraph()
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        1920
        sage: g.girth()
        4
        sage: g.chromatic_number()
        4
        sage: g.diameter()
        2
        sage: g.show(figsize=[10, 10])          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.ClebschGraph()
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        1920
        >>> g.girth()
        4
        >>> g.chromatic_number()
        4
        >>> g.diameter()
        2
        >>> g.show(figsize=[Integer(10), Integer(10)])          # long time                             # needs sage.plot

  static CompleteBipartiteGraph(p, q, set_position=True, immutable=False, name=None)

    Return a Complete Bipartite Graph on \(p + q\) vertices.

    A Complete Bipartite Graph is a graph with its vertices partitioned into two groups, \(V_1 = \{0,...,p-1\}\) and \(V_2 = \{p,...,p+q-1\}\). Each \(u \in V_1\) is connected to every \(v \in V_2\).

    INPUT:

    - `p`, `q` – number of vertices in each side

    - `set_position` – boolean (default: `True`); if set to `True`, we assign positions to the vertices so that the set of cardinality \(p\) is on the line \(y=1\) and the set of cardinality \(q\) is on the line \(y=0\).

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    - `name` – string (default: `None`); used as the name of the returned graph when set

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each complete bipartite graph will be displayed with the first \(p\) nodes on the top row (at \(y=1\)) from left to right. The remaining \(q\) nodes appear at \(y=0\), also from left to right. The shorter row (partition with fewer nodes) is stretched to the same length as the longer row, unless the shorter row has 1 node; in which case it is centered. The \(x\) values in the plot are in domain \([0, \max(p, q)]\).

    In the Complete Bipartite graph, there is a visual difference in using the spring-layout algorithm vs. the position dictionary used in this constructor. The position dictionary flattens the graph and separates the partitioned nodes, making it clear which nodes an edge is connected to. The Complete Bipartite graph plotted with the spring-layout algorithm tends to center the nodes in \(p\) (see `spring_med` in examples below), thus overlapping its nodes and edges, making it typically hard to decipher.

    Filling the position dictionary in advance adds \(O(n)\) to the constructor. Feel free to race the constructors below in the examples section. The much larger difference is the time added by the spring-layout algorithm when plotting. (Also shown in the example below). The spring model is typically described as \(O(n^3)\), as appears to be the case in the NetworkX source code.

    EXAMPLES:

    Two ways of constructing the complete bipartite graph, using different layout algorithms:

    Sage

        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

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> import networkx
        >>> n = networkx.complete_bipartite_graph(Integer(389), Integer(157))   # long time
        >>> spring_big = Graph(n)             # long time
        >>> posdict_big = graphs.CompleteBipartiteGraph(Integer(389), Integer(157))        # long time

    Compare the plotting:

    Sage

        sage: n = networkx.complete_bipartite_graph(11, 17)                             # needs networkx
        sage: spring_med = Graph(n)                                                     # needs networkx
        sage: posdict_med = graphs.CompleteBipartiteGraph(11, 17)

    [Python]

        >>> from sage.all import *
        >>> n = networkx.complete_bipartite_graph(Integer(11), Integer(17))                             # needs networkx
        >>> spring_med = Graph(n)                                                     # needs networkx
        >>> posdict_med = graphs.CompleteBipartiteGraph(Integer(11), Integer(17))

    Notice here how the spring-layout tends to center the nodes of \(n1\):

    Sage

        sage: spring_med.show()                 # long time                             # needs networkx
        sage: posdict_med.show()                # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> spring_med.show()                 # long time                             # needs networkx
        >>> posdict_med.show()                # long time                             # needs sage.plot

    View many complete bipartite graphs with a Sage Graphics Array, with this constructor (i.e., the position dictionary filled):

    Sage

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     k = graphs.CompleteBipartiteGraph(i+1,4)
        ....:     g.append(k)
        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)                                                     # needs sage.plot
        sage: G.show()                          # long time                             # needs sage.plot

    [Python]

        >>> from sage.all import *
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     k = graphs.CompleteBipartiteGraph(i+Integer(1),Integer(4))
        ...     g.append(k)
        >>> for i in range(Integer(3)):                                                        # needs sage.plot
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)                                                     # needs sage.plot
        >>> G.show()                          # long time                             # needs sage.plot

    We compare to plotting with the spring-layout algorithm:

    Sage

        sage: # needs networkx sage.plot
        sage: g = []
        sage: j = []
        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):
        ....:     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)
        sage: G.show()                          # long time

    Python

        >>> from sage.all import *
        >>> # needs networkx sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     spr = networkx.complete_bipartite_graph(i+Integer(1),Integer(4))
        ...     k = Graph(spr)
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    Issue #12155:

    Sage

        sage: graphs.CompleteBipartiteGraph(5,6).complement()
        complement(Complete bipartite graph of order 5+6): Graph on 11 vertices

    [Python]

        >>> from sage.all import *
        >>> graphs.CompleteBipartiteGraph(Integer(5),Integer(6)).complement()
        complement(Complete bipartite graph of order 5+6): Graph on 11 vertices

  static CompleteGraph(n, immutable=False)

    Return a complete graph on \(n\) nodes.

    A Complete Graph is a graph in which all nodes are connected to all other nodes.

    INPUT:

    - `n` – nonnegative integer; the number of vertices of the complete graph

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each complete graph will be displayed with the first (0) node at the top, with the rest following in a counterclockwise manner.

    In the complete graph, there is a big difference visually in using the spring-layout algorithm vs. the position dictionary used in this constructor. The position dictionary flattens the graph, making it clear which nodes an edge is connected to. But the complete graph offers a good example of how the spring-layout works. The edges push outward (everything is connected), causing the graph to appear as a 3-dimensional pointy ball. (See examples below).

    EXAMPLES:

    We view many Complete graphs with a Sage Graphics Array, first with this constructor (i.e., the position dictionary filled):

    Sage

        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):
        ....:     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)
        sage: G.show()                          # long time

    Python

        >>> from sage.all import *
        >>> # needs sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     k = graphs.CompleteGraph(i+Integer(3))
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    We compare to plotting with the spring-layout algorithm:

    Sage

        sage: # needs networkx sage.plot
        sage: import networkx
        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     spr = networkx.complete_graph(i+3)
        ....:     k = Graph(spr)
        ....:     g.append(k)
        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)
        sage: G.show()                          # long time

    [Python]

        >>> from sage.all import *
        >>> # needs networkx sage.plot
        >>> import networkx
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     spr = networkx.complete_graph(i+Integer(3))
        ...     k = Graph(spr)
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    Compare the constructors (results will vary):

    Sage

        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)
        sage: cputime(t)  # random
        0.6680419999999998

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> import networkx
        >>> t = cputime()
        >>> n = networkx.complete_graph(Integer(389)); spring389 = Graph(n)
        >>> cputime(t)  # random
        0.59203700000000126
        >>> t = cputime()
        >>> posdict389 = graphs.CompleteGraph(Integer(389))
        >>> cputime(t)  # random
        0.6680419999999998

    We compare plotting:

    Sage

        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 sage.plot
        sage: posdict23.show()                  # long time                             # needs sage.plot

    [Python]

        >>> from sage.all import *
        >>> # needs networkx
        >>> import networkx
        >>> n = networkx.complete_graph(Integer(23))
        >>> spring23 = Graph(n)
        >>> posdict23 = graphs.CompleteGraph(Integer(23))
        >>> spring23.show()                   # long time                             # needs sage.plot
        >>> posdict23.show()                  # long time                             # needs sage.plot

  static CompleteMultipartiteGraph(L, immutable=False)

    Return a complete multipartite graph.

    INPUT:

    - `L` – list of integers; the respective sizes of the components

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    PLOTTING: Produce a layout of the vertices so that vertices in the same vertex set are adjacent and clearly separated from vertices in other vertex sets.

    This is done by calculating the vertices of an \(r\)-gon then calculating the slope between adjacent vertices. We then ‘walk’ around the \(r\)-gon placing graph vertices in regular intervals between adjacent vertices of the \(r\)-gon.

    Makes a nicely organized graph like in this picture: https://commons.wikimedia.org/wiki/File:Turan_13-4.svg

    EXAMPLES:

    A complete tripartite graph with sets of sizes \(5, 6, 8\):

    Sage

        sage: g = graphs.CompleteMultipartiteGraph([5, 6, 8]); g
        Multipartite Graph with set sizes [5, 6, 8]: Graph on 19 vertices

    Python

        >>> from sage.all import *
        >>> g = graphs.CompleteMultipartiteGraph([Integer(5), Integer(6), Integer(8)]); g
        Multipartite Graph with set sizes [5, 6, 8]: Graph on 19 vertices

    It clearly has a chromatic number of 3:

    Sage

        sage: g.chromatic_number()
        3

    [Python]

        >>> from sage.all import *
        >>> g.chromatic_number()
        3

  static ConwaySmith_for_3S7(immutable=False)

    Return the Conway-Smith graph related to \(3 Sym(7)\).

    This is a distance-regular graph with intersection array \([10, 6, 4, 1; 1, 2, 6, 10]\).

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Sage

        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])

    Python

        >>> from sage.all import *
        >>> G = graphs.ConwaySmith_for_3S7()                                          # needs sage.modules sage.rings.finite_rings sage.rings.number_field
        >>> 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:

    A description and construction of this graph can be found in [BCN1989] p. 399.

  static CorrelationGraph(seqs, alpha, include_anticorrelation, immutable=False)

    Return a correlation graph with a node per sequence in `seqs`.

    Edges are added between nodes where the corresponding sequences have a correlation coefficient greater than alpha.

    If `include_anticorrelation` is `True`, then edges are also added between nodes with correlation coefficient less than `-alpha`.

    INPUT:

    - `seqs` – list of sequences, that is a list of lists

    - `alpha` – float; threshold on the correlation coefficient between two sequences for adding an edge

    - `include_anticorrelation` – boolean; whether to add edges between nodes with correlation coefficient less than `-alpha` or not

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Sage

        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)
        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)
        [(0, 0, None), (0, 1, None), (1, 1, None), (2, 2, None)]
        sage: CG3.edges(sort=False)
        [(0, 0, None), (0, 1, None), (0, 2, None), (1, 1, None), (1, 2, None), (2, 2, None)]

    Python

        >>> from sage.all import *
        >>> # needs numpy
        >>> from sage.graphs.generators.basic import CorrelationGraph
        >>> data = [[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9999)]]
        >>> CG1 = CorrelationGraph(data, RealNumber('0.9'), False)
        >>> CG2 = CorrelationGraph(data, RealNumber('0.9'), True)
        >>> CG3 = CorrelationGraph(data, RealNumber('0.1'), True)
        >>> CG1.edges(sort=False)
        [(0, 0, None), (0, 1, None), (1, 1, None), (2, 2, None)]
        >>> CG2.edges(sort=False)
        [(0, 0, None), (0, 1, None), (1, 1, None), (2, 2, None)]
        >>> CG3.edges(sort=False)
        [(0, 0, None), (0, 1, None), (0, 2, None), (1, 1, None), (1, 2, None), (2, 2, None)]

  static CossidentePenttilaGraph(q)

    Return the Cossidente-Penttila \(((q^3+1)(q+1)/2,(q^2+1)(q-1)/2,(q-3)/2,(q-1)^2/2)\)-strongly regular graph

    For each odd prime power \(q\), one can partition the points of the \(O_6^-(q)\)-generalized quadrangle \(GQ(q,q^2)\) into two parts, so that on any of them the induced subgraph of the point graph of the GQ has parameters as above [CP2005].

    Directly following the construction in [CP2005] is not efficient, as one then needs to construct the dual \(GQ(q^2,q)\). Thus we describe here a more efficient approach that we came up with, following a suggestion by T.Penttila. Namely, this partition is invariant under the subgroup \(H=\Omega_3(q^2)<O_6^-(q)\). We build the appropriate \(H\), which leaves the form \(B(X,Y,Z)=XY+Z^2\) invariant, and pick up two orbits of \(H\) on the \(F_q\)-points. One them is \(B\)-isotropic, and we take the representative \((1:0:0)\). The other one corresponds to the points of \(PG(2,q^2)\) that have all the lines on them either missing the conic specified by \(B\), or intersecting the conic in two points. We take \((1:1:e)\) as the representative. It suffices to pick \(e\) so that \(e^2+1\) is not a square in \(F_{q^2}\). Indeed, The conic can be viewed as the union of \(\{(0:1:0)\}\) and \(\{(1:-t^2:t) | t \in F_{q^2}\}\). The coefficients of a generic line on \((1:1:e)\) are \([1:-1-eb:b]\), for \(-1\neq eb\). Thus, to make sure the intersection with the conic is always even, we need that the discriminant of \(1+(1+eb)t^2+tb=0\) never vanishes, and this is if and only if \(e^2+1\) is not a square. Further, we need to adjust \(B\), by multiplying it by appropriately chosen \(\nu\), so that \((1:1:e)\) becomes isotropic under the relative trace norm \(\nu B(X,Y,Z)+(\nu B(X,Y,Z))^q\). The latter is used then to define the graph.

    INPUT:

    - `q` – an odd prime power

    EXAMPLES:

    For \(q=3\) one gets Sims-Gewirtz graph.

    Sage

        sage: G = graphs.CossidentePenttilaGraph(3)     # optional - gap_package_grape
        sage: G.is_strongly_regular(parameters=True)    # optional - gap_package_grape
        (56, 10, 0, 2)

    Python

        >>> from sage.all import *
        >>> G = graphs.CossidentePenttilaGraph(Integer(3))     # optional - gap_package_grape
        >>> G.is_strongly_regular(parameters=True)    # optional - gap_package_grape
        (56, 10, 0, 2)

    For \(q>3\) one gets new graphs.

    Sage

        sage: G = graphs.CossidentePenttilaGraph(5)     # optional - gap_package_grape
        sage: G.is_strongly_regular(parameters=True)    # optional - gap_package_grape
        (378, 52, 1, 8)

    [Python]

        >>> from sage.all import *
        >>> G = graphs.CossidentePenttilaGraph(Integer(5))     # optional - gap_package_grape
        >>> G.is_strongly_regular(parameters=True)    # optional - gap_package_grape
        (378, 52, 1, 8)

  static CoxeterGraph()

    Return the Coxeter graph.

    See the Wikipedia article Coxeter_graph.

    EXAMPLES:

    Sage

        sage: g = graphs.CoxeterGraph()
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        336
        sage: g.girth()
        7
        sage: g.chromatic_number()
        3
        sage: g.diameter()
        4
        sage: g.show(figsize=[10, 10])          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.CoxeterGraph()
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        336
        >>> g.girth()
        7
        >>> g.chromatic_number()
        3
        >>> g.diameter()
        4
        >>> g.show(figsize=[Integer(10), Integer(10)])          # long time                             # needs sage.plot

  static CubeConnectedCycle(d)

    Return the cube-connected cycle of dimension \(d\).

    The cube-connected cycle of order \(d\) is the \(d\)-dimensional hypercube with each of its vertices replaced by a cycle of length \(d\). This graph has order \(d \times 2^d\). The construction is as follows: Construct vertex \((x,y)\) for \(0 \leq x < 2^d\), \(0 \leq y < d\). For each vertex, \((x,y)\), add an edge between it and \((x, (y-1) \mod d))\), \((x,(y+1) \mod d)\), and \((x \oplus 2^y, y)\), where \(\oplus\) is the bitwise xor operator.

    For \(d=1\) and \(2\), the cube-connected cycle graph contains self-loops or multiple edges between a pair of vertices, but for all other \(d\), it is simple.

    INPUT:

    - `d` – positive integer; the dimension of the desired hypercube as well as the length of the cycle to be placed at each vertex of the \(d\)-dimensional hypercube

    EXAMPLES:

    The order of the graph is \(d \times 2^d\)

    Sage

        sage: d = 3
        sage: g = graphs.CubeConnectedCycle(d)
        sage: len(g) == d*2**d
        True

    Python

        >>> from sage.all import *
        >>> d = Integer(3)
        >>> g = graphs.CubeConnectedCycle(d)
        >>> len(g) == d*Integer(2)**d
        True

    The diameter of cube-connected cycles for \(d > 3\) is \(2d + \lfloor \frac{d}{2} \rfloor - 2\)

    Sage

        sage: d = 4
        sage: g = graphs.CubeConnectedCycle(d)
        sage: g.diameter() == 2*d+d//2-2
        True

    [Python]

        >>> from sage.all import *
        >>> d = Integer(4)
        >>> g = graphs.CubeConnectedCycle(d)
        >>> g.diameter() == Integer(2)*d+d//Integer(2)-Integer(2)
        True

    All vertices have degree \(3\) when \(d > 1\)

    Sage

        sage: g = graphs.CubeConnectedCycle(5)
        sage: all(g.degree(v) == 3 for v in g)
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.CubeConnectedCycle(Integer(5))
        >>> all(g.degree(v) == Integer(3) for v in g)
        True

  static CubeGraph(n, embedding=1)

    Return the \(n\)-cube graph, also called the hypercube in \(n\) dimensions.

    The hypercube in \(n\) dimension is build upon the binary strings on \(n\) bits, two of them being adjacent if they differ in exactly one bit. Hence, the distance between two vertices in the hypercube is the Hamming distance.

    INPUT:

    - `n` – integer; the dimension of the cube graph

    - `embedding` – integer (default: \(1\)); two embeddings of the \(n\)-cube are available:

      - `1` – the \(n\)-cube is projected inside a regular \(2n\)-gonal polygon by a skew orthogonal projection. See the Wikipedia article Hypercube for more details.

      - `2` – orthogonal projection of the \(n\)-cube. This orientation shows columns of independent vertices such that the neighbors of a vertex are located in the columns on the left and on the right. The number of vertices in each column represents rows in Pascal’s triangle. See for instance the Wikipedia article 10-cube for more details.

      - `3` – oblique projection of the \(n\)-cube. Oblique projection involves aligning one face parallel to the viewer and projecting at a specified angle, maintaining equal size for edges parallel to one axis while applying fixed foreshortening to others. This method simplifies the representation of a four-dimensional hypercube onto a two-dimensional plane, offering a geometrically consistent visualization.

      - `None` or `O` – no embedding is provided

    EXAMPLES:

    The distance between \(0100110\) and \(1011010\) is \(5\), as expected:

    Sage

        sage: g = graphs.CubeGraph(7)
        sage: g.distance('0100110','1011010')
        5

    Python

        >>> from sage.all import *
        >>> g = graphs.CubeGraph(Integer(7))
        >>> g.distance('0100110','1011010')
        5

    Plot several \(n\)-cubes in a Sage Graphics Array:

    Sage

        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):
        ....:  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)
        sage: G.show(figsize=[6,4])             # long time

    [Python]

        >>> from sage.all import *
        >>> # needs sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(6)):
        ...  k = graphs.CubeGraph(i+Integer(1))
        ...  g.append(k)
        ...
        >>> for i in range(Integer(2)):
        ...  n = []
        ...  for m in range(Integer(3)):
        ...      n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...  j.append(n)
        ...
        >>> G = graphics_array(j)
        >>> G.show(figsize=[Integer(6),Integer(4)])             # long time

    Use the plot options to display larger \(n\)-cubes:

    Sage

        sage: g = graphs.CubeGraph(9, embedding=1)
        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, needs sage.plot
        sage: g = graphs.CubeGraph(9, embedding=3)
        sage: g.show(figsize=[12,12],vertex_labels=False, vertex_size=20)       # long time, needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.CubeGraph(Integer(9), embedding=Integer(1))
        >>> g.show(figsize=[Integer(12),Integer(12)],vertex_labels=False, vertex_size=Integer(20))       # long time, needs sage.plot
        >>> g = graphs.CubeGraph(Integer(9), embedding=Integer(2))
        >>> g.show(figsize=[Integer(12),Integer(12)],vertex_labels=False, vertex_size=Integer(20))       # long time, needs sage.plot
        >>> g = graphs.CubeGraph(Integer(9), embedding=Integer(3))
        >>> g.show(figsize=[Integer(12),Integer(12)],vertex_labels=False, vertex_size=Integer(20))       # long time, needs sage.plot

    AUTHORS:

    - Robert Miller

    - David Coudert

  static CubeplexGraph(embedding='LM')

    Return the Cubeplex graph.

    The Cubeplex graph is the cubic hamiltonian graph of order 12 that corresponds to the graph labeled as \(\Gamma_1\) in Fischer and Little [FiLi2001]. It has LCF notation \([-6, -5, -3, -6, 3, 5, -6, -3, 5, -6, -5, 3]\).

    The Fischer-Little Theorem [FiLi2001] may be stated as follows [LM2024]:

    A near-bipartite graph is non-Pfaffian if and only if it contains one of the graphs \(K_{3, 3}\), \(\Gamma_1\) and \(\Gamma_2\) as an \(S\)-minor.

    Norine and Thomas [NT2007] use the term `Cubeplex` to describe one of the 12-vertex cubic graphs, \(\Gamma_1\) and \(\Gamma_2\), as defined by Fischer and Little [FiLi2001]. However, the figure in their paper that supposedly provides embeddings for the graphs labeled Cubeplex and Twinplex actually shows both embeddings corresponding to Fischer and Little’s \(\Gamma_1\), which is the Cubeplex graph. Followingly, for `embedding='NT'`, we present only the embedding that is shown by the labeling `Cubeplex` in the paper of Norine and Thomas [NT2007].

    PLOTTING:

    Upon construction, the position dictionary is filled to override the spring-layout algorithm. For different values of the parameter `embedding`, the Cubeplex graph is displayed as it is mentioned in the respective paper/ book.

    INPUT:

    - `embedding` – string (default: `'LM'`)

      - `'LM'` displays the embedding as shown for \(\Gamma_1\) by Lucchesi and Murty [LM2024]

      - `'FL'` displays the embedding as shown for \(\Gamma_1\) by Fischer and Little [FiLi2001]

      - `'NT'` displays the embedding as shown for the `Cubeplex` by Norine and Thomas [NT2007]

    OUTPUT:

    - `G` – the Cubeplex graph; note that a `ValueError` is returned if `embedding` is none of `'FT'`, `'NT'` or `'LM'`

    EXAMPLES:

    Construct and show the Cubeplex graph:

    Sage

        sage: g = graphs.CubeplexGraph()
        sage: g.name()
        'Cubeplex Graph'
        sage: g.order()
        12
        sage: g.size()
        18
        sage: g.girth()
        4
        sage: g.diameter()
        3
        sage: g.is_hamiltonian()
        True
        sage: g.crossing_number()
        1
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.CubeplexGraph()
        >>> g.name()
        'Cubeplex Graph'
        >>> g.order()
        12
        >>> g.size()
        18
        >>> g.girth()
        4
        >>> g.diameter()
        3
        >>> g.is_hamiltonian()
        True
        >>> g.crossing_number()
        1
        >>> g.show()                          # long time                             # needs sage.plot

    See also

    `TwinplexGraph()`

    AUTHORS:

    - Janmenjaya Panda (2024-08-03)

  static CycleGraph(n, immutable=False)

    Return a cycle graph with \(n\) nodes.

    A cycle graph is a basic structure which is also typically called an \(n\)-gon.

    INPUT:

    - `n` – nonnegative integer; the number of vertices of the cycle graph

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each cycle graph will be displayed with the first (0) node at the top, with the rest following in a counterclockwise manner.

    The cycle graph is a good opportunity to compare efficiency of filling a position dictionary vs. using the spring-layout algorithm for plotting. Because the cycle graph is very symmetric, the resulting plots should be similar (in cases of small \(n\)).

    Filling the position dictionary in advance adds \(O(n)\) to the constructor.

    EXAMPLES:

    Compare plotting using the predefined layout and networkx:

    Sage

        sage: # needs networkx sage.plot
        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

    Python

        >>> from sage.all import *
        >>> # needs networkx sage.plot
        >>> import networkx
        >>> n = networkx.cycle_graph(Integer(23))
        >>> spring23 = Graph(n)
        >>> posdict23 = graphs.CycleGraph(Integer(23))
        >>> spring23.show()                   # long time
        >>> 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:

    Sage

        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):
        ....:     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)
        sage: G.show()                          # long time

    [Python]

        >>> from sage.all import *
        >>> # needs networkx sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     k = graphs.CycleGraph(i+Integer(3))
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    Compare to plotting with the spring-layout algorithm:

    Sage

        sage: # needs networkx sage.plot
        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     spr = networkx.cycle_graph(i+3)
        ....:     k = Graph(spr)
        ....:     g.append(k)
        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)
        sage: G.show()                          # long time

    Python

        >>> from sage.all import *
        >>> # needs networkx sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     spr = networkx.cycle_graph(i+Integer(3))
        ...     k = Graph(spr)
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

  static DartGraph(immutable=False)

    Return a dart graph with 5 nodes.

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the dart graph is drawn as a dart, with the sharp part on the bottom.

    EXAMPLES:

    Construct and show a dart graph:

    Sage

        sage: g = graphs.DartGraph()
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.DartGraph()
        >>> g.show()                          # long time                             # needs sage.plot

  static DegreeSequence(deg_sequence)

    Return a graph with the given degree sequence.

    This method raises a NetworkX error if the proposed degree sequence cannot be that of a graph.

    Graph returned is the one returned by the Havel-Hakimi algorithm, which constructs a simple graph by connecting vertices of highest degree to other vertices of highest degree, resorting the remaining vertices by degree and repeating the process. See Theorem 1.4 in [CL1996].

    INPUT:

    - `deg_sequence` – list of integers with each entry corresponding to the degree of a different vertex

    EXAMPLES:

    Sage

        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                             # needs networkx sage.plot

    Python

        >>> from sage.all import *
        >>> G = graphs.DegreeSequence([Integer(3),Integer(3),Integer(3),Integer(3)])                                      # needs networkx
        >>> G.edges(sort=True, labels=False)                                          # needs networkx
        [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
        >>> G.show()                          # long time                             # needs networkx sage.plot

    Sage

        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

    [Python]

        >>> from sage.all import *
        >>> G = graphs.DegreeSequence([Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3)])  # needs networkx
        >>> G.show()                          # long time                             # needs networkx sage.plot

    Sage

        sage: G = graphs.DegreeSequence([4,4,4,4,4,4,4,4])                              # needs networkx
        sage: G.show()                          # long time                             # needs networkx sage.plot

    Python

        >>> from sage.all import *
        >>> G = graphs.DegreeSequence([Integer(4),Integer(4),Integer(4),Integer(4),Integer(4),Integer(4),Integer(4),Integer(4)])                              # needs networkx
        >>> G.show()                          # long time                             # needs networkx sage.plot

    Sage

        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

    [Python]

        >>> from sage.all import *
        >>> G = graphs.DegreeSequence([Integer(1),Integer(2),Integer(3),Integer(4),Integer(3),Integer(4),Integer(3),Integer(2),Integer(3),Integer(2),Integer(1)])                        # needs networkx
        >>> G.show()                          # long time                             # needs networkx sage.plot

  static DegreeSequenceBipartite(s1, s2)

    Return a bipartite graph whose two sets have the given degree sequences.

    Given two different sequences of degrees \(s_1\) and \(s_2\), this functions returns ( if possible ) a bipartite graph on sets \(A\) and \(B\) such that the vertices in \(A\) have \(s_1\) as their degree sequence, while \(s_2\) is the degree sequence of the vertices in \(B\).

    INPUT:

    - `s_1` – list of integers corresponding to the degree sequence of the first set of vertices

    - `s_2` – list of integers corresponding to the degree sequence of the second set of vertices

    ALGORITHM:

    This function works through the computation of the matrix given by the Gale-Ryser theorem, which is in this case the adjacency matrix of the bipartite graph.

    EXAMPLES:

    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

        sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5])                     # needs sage.combinat sage.modules
        sage: g.is_isomorphic(graphs.CompleteBipartiteGraph(5,2))                       # needs sage.combinat sage.modules
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.DegreeSequenceBipartite([Integer(2),Integer(2),Integer(2),Integer(2),Integer(2)],[Integer(5),Integer(5)])                     # needs sage.combinat sage.modules
        >>> g.is_isomorphic(graphs.CompleteBipartiteGraph(Integer(5),Integer(2)))                       # needs sage.combinat 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

        sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,1],[5,5])                     # needs sage.combinat sage.modules
        Traceback (most recent call last):
        ...
        ValueError: there exists no bipartite graph corresponding to the given degree sequences

    [Python]

        >>> from sage.all import *
        >>> g = graphs.DegreeSequenceBipartite([Integer(2),Integer(2),Integer(2),Integer(2),Integer(1)],[Integer(5),Integer(5)])                     # needs sage.combinat sage.modules
        Traceback (most recent call last):
        ...
        ValueError: there exists no bipartite graph corresponding to the given degree sequences

  static DegreeSequenceConfigurationModel(deg_sequence, seed=None)

    Return a random pseudograph with the given degree sequence.

    This method raises a NetworkX error if the proposed degree sequence cannot be that of a graph with multiple edges and loops.

    One requirement is that the sum of the degrees must be even, since every edge must be incident with two vertices.

    INPUT:

    - `deg_sequence` – list of integers with each entry corresponding to the expected degree of a different vertex

    - `seed` – (optional) a `random.Random` seed or a Python `int` for the random number generator

    EXAMPLES:

    Sage

        sage: G = graphs.DegreeSequenceConfigurationModel([1,1])                        # needs networkx
        sage: G.adjacency_matrix()                                                      # needs networkx sage.modules
        [0 1]
        [1 0]

    Python

        >>> from sage.all import *
        >>> G = graphs.DegreeSequenceConfigurationModel([Integer(1),Integer(1)])                        # needs networkx
        >>> G.adjacency_matrix()                                                      # needs networkx sage.modules
        [0 1]
        [1 0]

    The output is allowed to contain both loops and multiple edges:

    Sage

        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
        True
        sage: G.show()                          # long time                             # needs sage.plot

    [Python]

        >>> from sage.all import *
        >>> # needs networkx
        >>> deg_sequence = [Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3),Integer(3)]
        >>> G = graphs.DegreeSequenceConfigurationModel(deg_sequence)
        >>> G.order(), G.size()
        (20, 30)
        >>> G.has_loops() or G.has_multiple_edges()  # random
        True
        >>> G.show()                          # long time                             # needs sage.plot

    REFERENCE:

    [New2003]

  static DegreeSequenceExpected(deg_sequence, seed=None)

    Return a random graph with expected given degree sequence.

    This method raises a NetworkX error if the proposed degree sequence cannot be that of a graph.

    One requirement is that the sum of the degrees must be even, since every edge must be incident with two vertices.

    INPUT:

    - `deg_sequence` – list of integers with each entry corresponding to the expected degree of a different vertex

    - `seed` – (optional) a `random.Random` seed or a Python `int` for the random number generator

    EXAMPLES:

    Sage

        sage: G = graphs.DegreeSequenceExpected([1,2,3,2,3]); G                         # needs networkx
        Looped graph on 5 vertices
        sage: G.show()                          # long time                             # needs networkx sage.plot

    Python

        >>> from sage.all import *
        >>> G = graphs.DegreeSequenceExpected([Integer(1),Integer(2),Integer(3),Integer(2),Integer(3)]); G                         # needs networkx
        Looped graph on 5 vertices
        >>> G.show()                          # long time                             # needs networkx sage.plot

    REFERENCE:

    [CL2002]

  static DegreeSequenceTree(deg_sequence)

    Return a tree with the given degree sequence.

    This method raises a NetworkX error if the proposed degree sequence cannot be that of a tree.

    Since every tree has one more vertex than edge, the degree sequence must satisfy `len(deg_sequence) - sum(deg_sequence)/2 == 1`.

    INPUT:

    - `deg_sequence` – list of integers with each entry corresponding to the expected degree of a different vertex

    EXAMPLES:

    Sage

        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                             # needs networkx sage.plot

    Python

        >>> from sage.all import *
        >>> G = graphs.DegreeSequenceTree([Integer(3),Integer(1),Integer(3),Integer(3),Integer(1),Integer(1),Integer(1),Integer(2),Integer(1)]); G                     # needs networkx
        Graph on 9 vertices
        >>> G.show()                          # long time                             # needs networkx sage.plot

  static DejterGraph()

    Return the Dejter graph.

    The Dejter graph is obtained from the binary 7-cube by deleting a copy of the Hamming code of length 7. It is 6-regular, with 112 vertices and 336 edges. For more information, see the Wikipedia article Dejter_graph.

    EXAMPLES:

    Sage

        sage: g = graphs.DejterGraph(); g                                               # needs sage.rings.finite_rings
        Dejter Graph: Graph on 112 vertices
        sage: g.is_regular(k=6)                                                         # needs sage.rings.finite_rings
        True
        sage: g.girth()                                                                 # needs sage.rings.finite_rings
        4

    Python

        >>> from sage.all import *
        >>> g = graphs.DejterGraph(); g                                               # needs sage.rings.finite_rings
        Dejter Graph: Graph on 112 vertices
        >>> g.is_regular(k=Integer(6))                                                         # needs sage.rings.finite_rings
        True
        >>> g.girth()                                                                 # needs sage.rings.finite_rings
        4

  static DesarguesGraph()

    Return the Desargues graph.

    PLOTTING: The layout chosen is the same as on the cover of [Har1969].

    EXAMPLES:

    Sage

        sage: D = graphs.DesarguesGraph()
        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                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> D = graphs.DesarguesGraph()
        >>> L = graphs.LCFGraph(Integer(20),[Integer(5),-Integer(5),Integer(9),-Integer(9)],Integer(5))                                     # needs networkx
        >>> D.is_isomorphic(L)                                                        # needs networkx
        True
        >>> D.show()                          # long time                             # needs sage.plot

  static DiamondGraph(immutable=False)

    Return a diamond graph with 4 nodes.

    A diamond graph is a square with one pair of diagonal nodes connected.

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the diamond graph is drawn as a diamond, with the first node on top, second on the left, third on the right, and fourth on the bottom; with the second and third node connected.

    EXAMPLES:

    Construct and show a diamond graph:

    Sage

        sage: g = graphs.DiamondGraph()
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.DiamondGraph()
        >>> g.show()                          # long time                             # needs sage.plot

  static DipoleGraph(n)

    Return a dipole graph with \(n\) edges.

    A dipole graph is a multigraph consisting of 2 vertices connected with \(n\) parallel edges.

    EXAMPLES:

    Construct and show a dipole graph with 13 edges:

    Sage

        sage: g = graphs.DipoleGraph(13); g
        Dipole graph: Multi-graph on 2 vertices
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.DipoleGraph(Integer(13)); g
        Dipole graph: Multi-graph on 2 vertices
        >>> g.show()                          # long time                             # needs sage.plot

  static DodecahedralGraph()

    Return a Dodecahedral graph (with 20 nodes).

    The dodecahedral graph is cubic symmetric, so the spring-layout algorithm will be very effective for display. It is dual to the icosahedral graph.

    PLOTTING: The Dodecahedral graph should be viewed in 3 dimensions. We choose to use a planar embedding of the graph. We hope to add rotatable, 3-dimensional viewing in the future. In such a case, an argument will be added to select the desired layout.

    EXAMPLES:

    Construct and show a Dodecahedral graph:

    Sage

        sage: g = graphs.DodecahedralGraph()
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.DodecahedralGraph()
        >>> 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

        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):
        ....:     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)
        sage: G.show()                          # long time

    [Python]

        >>> from sage.all import *
        >>> # needs sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     k = graphs.DodecahedralGraph()
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

  static DorogovtsevGoltsevMendesGraph(n)

    Construct the \(n\)-th generation of the Dorogovtsev-Goltsev-Mendes graph.

    EXAMPLES:

    Sage

        sage: G = graphs.DorogovtsevGoltsevMendesGraph(8)                               # needs networkx
        sage: G.size()                                                                  # needs networkx
        6561

    Python

        >>> from sage.all import *
        >>> G = graphs.DorogovtsevGoltsevMendesGraph(Integer(8))                               # needs networkx
        >>> G.size()                                                                  # needs networkx
        6561

    REFERENCE:

    - [1] Dorogovtsev, S. N., Goltsev, A. V., and Mendes, J. F. F., Pseudofractal scale-free web, Phys. Rev. E 066122 (2002).

  static DoubleGeneralizedPetersenGraph(n, k)

    Return a double generalized Petersen graph with \(4n\) nodes.

    The double generalized Petersen graphs is a family of graphs proposed in [ZF2012] as a variant of generalized Petersen graphs. The variables \(n\), \(k\) are integers such that \(n > 2\) and \(0 < k \leq \lfloor (n-1) / 2 \rfloor\).

    INPUT:

    - `n` – the number of nodes is \(4 * n\)

    - `k` – integer such that \(0 < k \leq \lfloor (n-1) / 2 \rfloor\) determining how vertices on second and third inner rims are connected

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the double generalized Petersen graphs are displayed as 4 concentric cycles, with the first n nodes drawn on the outer circle. The first (0) node is drawn at the top of the outer-circle, moving counterclockwise after that. The second circle is drawn with the (n)th node at the top, then counterclockwise as well. The tird cycle is drawn with the (2n)th node at the top, then counterclockwise. And the fourth cycle is drawn with the (3n)th node at the top, then again counterclockwise.

    EXAMPLES:

    When \(n\) is even the resulting graph will be isomorphic to a double generalized Petersen graph with \(k' = n / 2 - k\):

    Sage

        sage: g = graphs.DoubleGeneralizedPetersenGraph(10, 2)
        sage: g2 = graphs.DoubleGeneralizedPetersenGraph(10, 3)
        sage: g.is_isomorphic(g2)
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.DoubleGeneralizedPetersenGraph(Integer(10), Integer(2))
        >>> g2 = graphs.DoubleGeneralizedPetersenGraph(Integer(10), Integer(3))
        >>> g.is_isomorphic(g2)
        True

  static DoubleGrassmannGraph(q, e)

    Return the bipartite double of the distance-\(e\) graph of the Grassmann graph \(J_q(n,e)\).

    This graph can also be described as follows: Let \(V\) be the vector space of dimension \(n\) over \(GF(q)\). The vertex set is the set of \(e+1\) or \(e\) subspaces of \(V\). Two vertices are adjacent if one subspace is contained in the other.

    This graph is distance-transitive.

    INPUT:

    - `q` – a prime power

    - `e` – integer

    EXAMPLES:

    Sage

        sage: G = graphs.DoubleGrassmannGraph(2,1)                                      # needs sage.modules
        sage: G.diameter()                                                              # needs sage.modules
        3
        sage: G.is_distance_regular(True)                                               # needs sage.modules
        ([3, 2, 2, None], [None, 1, 1, 3])

    Python

        >>> from sage.all import *
        >>> G = graphs.DoubleGrassmannGraph(Integer(2),Integer(1))                                      # needs sage.modules
        >>> G.diameter()                                                              # needs sage.modules
        3
        >>> G.is_distance_regular(True)                                               # needs sage.modules
        ([3, 2, 2, None], [None, 1, 1, 3])

    REFERENCES:

    See [BCN1989] pp. 272, 273 or [VDKT2016] p. 25.

  static DoubleOddGraph(n)

    Return the double odd graph on \(2n+1\) points.

    The graph is obtained using the subsets of size \(n\) and \(n+1\) of \({1, 2, ..., 2n+1}\) as vertices. Two vertices are adjacent if one is included in the other.

    The graph is distance-transitive.

    INPUT:

    - `n` – integer; must be greater than 0

    EXAMPLES:

    Sage

        sage: G = graphs.DoubleOddGraph(5)
        sage: G.is_distance_regular(True)
        ([6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, None],
         [None, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6])
        sage: G = graphs.DoubleOddGraph(3)
        sage: G.diameter()
        7
        sage: G.is_distance_regular(True)
        ([4, 3, 3, 2, 2, 1, 1, None], [None, 1, 1, 2, 2, 3, 3, 4])

    Python

        >>> from sage.all import *
        >>> G = graphs.DoubleOddGraph(Integer(5))
        >>> G.is_distance_regular(True)
        ([6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, None],
         [None, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6])
        >>> G = graphs.DoubleOddGraph(Integer(3))
        >>> G.diameter()
        7
        >>> G.is_distance_regular(True)
        ([4, 3, 3, 2, 2, 1, 1, None], [None, 1, 1, 2, 2, 3, 3, 4])

    REFERENCES:

    See [BCN1989] pp. 259-261 or [VDKT2016] p. 25.

  static DoubleStarSnark()

    Return the double star snark.

    The double star snark is a 3-regular graph on 30 vertices. See the Wikipedia article Double-star_snark.

    EXAMPLES:

    Sage

        sage: g = graphs.DoubleStarSnark()
        sage: g.order()
        30
        sage: g.size()
        45
        sage: g.chromatic_number()
        3
        sage: g.is_hamiltonian()                                                        # needs sage.numerical.mip
        False
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        80
        sage: g.show()                                                                  # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.DoubleStarSnark()
        >>> g.order()
        30
        >>> g.size()
        45
        >>> g.chromatic_number()
        3
        >>> g.is_hamiltonian()                                                        # needs sage.numerical.mip
        False
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        80
        >>> g.show()                                                                  # needs sage.plot

  static DoublyTruncatedWittGraph(immutable=False)

    Return the doubly truncated Witt graph.

    This builds the truncated Witt graph, then removes all vertices whose codeword start with a 1.

    The graph is distance-regular with intersection array \([7,6,4,4;1,1,1,6]\).

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Sage

        sage: G = graphs.DoublyTruncatedWittGraph()                                     # needs sage.libs.pari sage.modules
        sage: G.is_distance_regular(True)                                               # needs sage.libs.pari sage.modules
        ([7, 6, 4, 4, None], [None, 1, 1, 1, 6])

    Python

        >>> from sage.all import *
        >>> G = graphs.DoublyTruncatedWittGraph()                                     # needs sage.libs.pari sage.modules
        >>> G.is_distance_regular(True)                                               # needs sage.libs.pari sage.modules
        ([7, 6, 4, 4, None], [None, 1, 1, 1, 6])

    REFERENCES:

    A description and construction of this graph can be found in [BCN1989] p. 368.

  static DurerGraph()

    Return the Dürer graph.

    For more information, see the Wikipedia article D%C3%BCrer_graph.

    EXAMPLES:

    The Dürer graph is named after Albrecht Dürer. It is a planar graph with 12 vertices and 18 edges:

    Sage

        sage: G = graphs.DurerGraph(); G
        Durer graph: Graph on 12 vertices
        sage: G.is_planar()
        True
        sage: G.order()
        12
        sage: G.size()
        18

    Python

        >>> from sage.all import *
        >>> G = graphs.DurerGraph(); G
        Durer graph: Graph on 12 vertices
        >>> G.is_planar()
        True
        >>> G.order()
        12
        >>> G.size()
        18

    The Dürer graph has chromatic number 3, diameter 4, and girth 3:

    Sage

        sage: G.chromatic_number()
        3
        sage: G.diameter()
        4
        sage: G.girth()
        3

    [Python]

        >>> from sage.all import *
        >>> G.chromatic_number()
        3
        >>> G.diameter()
        4
        >>> G.girth()
        3

    Its automorphism group is isomorphic to \(D_6\):

    Sage

        sage: ag = G.automorphism_group()                                               # needs sage.groups
        sage: ag.is_isomorphic(DihedralGroup(6))                                        # needs sage.groups
        True

    Python

        >>> from sage.all import *
        >>> ag = G.automorphism_group()                                               # needs sage.groups
        >>> ag.is_isomorphic(DihedralGroup(Integer(6)))                                        # needs sage.groups
        True

  static DyckGraph()

    Return the Dyck graph.

    For more information, see the MathWorld article on the Dyck graph or the Wikipedia article Dyck_graph.

    EXAMPLES:

    The Dyck graph was defined by Walther von Dyck in 1881. It has \(32\) vertices and \(48\) edges, and is a cubic graph (regular of degree \(3\)):

    Sage

        sage: G = graphs.DyckGraph(); G
        Dyck graph: Graph on 32 vertices
        sage: G.order()
        32
        sage: G.size()
        48
        sage: G.is_regular()
        True
        sage: G.is_regular(3)
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.DyckGraph(); G
        Dyck graph: Graph on 32 vertices
        >>> G.order()
        32
        >>> G.size()
        48
        >>> G.is_regular()
        True
        >>> G.is_regular(Integer(3))
        True

    It is non-planar and Hamiltonian, as well as bipartite (making it a bicubic graph):

    Sage

        sage: G.is_planar()
        False
        sage: G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        sage: G.is_bipartite()
        True

    [Python]

        >>> from sage.all import *
        >>> G.is_planar()
        False
        >>> G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        >>> G.is_bipartite()
        True

    It has radius \(5\), diameter \(5\), and girth \(6\):

    Sage

        sage: G.radius()
        5
        sage: G.diameter()
        5
        sage: G.girth()
        6

    Python

        >>> from sage.all import *
        >>> G.radius()
        5
        >>> G.diameter()
        5
        >>> G.girth()
        6

    Its chromatic number is \(2\) and its automorphism group is of order \(192\):

    Sage

        sage: G.chromatic_number()
        2
        sage: G.automorphism_group().cardinality()                                      # needs sage.groups
        192

    [Python]

        >>> from sage.all import *
        >>> G.chromatic_number()
        2
        >>> G.automorphism_group().cardinality()                                      # needs sage.groups
        192

    It is a non-integral graph as it has irrational eigenvalues:

    Sage

        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

    Python

        >>> from sage.all import *
        >>> 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 of the Shrikhande graph (`ShrikhandeGraph`).

  static EgawaGraph(p, s)

    Return the Egawa graph with parameters \(p\), \(s\).

    Egawa graphs are a peculiar family of graphs devised by Yoshimi Egawa in [Ega1981] . The Shrikhande graph is a special case of this family of graphs, with parameters \((1,0)\). All the graphs in this family are not recognizable by 1-WL (Weisfeiler Lehamn algorithm of the first order) and 2-WL, that is their orbits are not correctly returned by k-WL for k lower than 3.

    Furthermore, all the graphs in this family are distance-regular, but they are not distance-transitive if \(p \neq 0\).

    The Egawa graph with parameters \((0, s)\) is isomorphic to the Hamming graph with parameters \((s, 4)\), when the underlying set of the Hamming graph is \([0,1,2,3]\)

    INPUT:

    - `p` – power to which the graph named \(Y\) in the reference provided above will be raised

    - `s` – power to which the graph named \(X\) in the reference provided above will be raised

    OUTPUT:

    - `G` – the Egawa graph with parameters (p,s)

    EXAMPLES:

    Every Egawa graph is distance regular.

    Sage

        sage: g = graphs.EgawaGraph(1, 2)
        sage: g.is_distance_regular()
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.EgawaGraph(Integer(1), Integer(2))
        >>> g.is_distance_regular()
        True

    An Egawa graph with parameters (0,s) is isomorphic to the Hamming graph with parameters (s, 4).

    Sage

        sage: g = graphs.EgawaGraph(0, 4)
        sage: g.is_isomorphic(graphs.HammingGraph(4,4))
        True

    [Python]

        >>> from sage.all import *
        >>> g = graphs.EgawaGraph(Integer(0), Integer(4))
        >>> g.is_isomorphic(graphs.HammingGraph(Integer(4),Integer(4)))
        True

  static EllinghamHorton54Graph()

    Return the Ellingham-Horton 54-graph.

    For more information, see the Wikipedia article Ellingham-Horton_graph.

    EXAMPLES:

    This graph is 3-regular:

    Sage

        sage: g = graphs.EllinghamHorton54Graph()
        sage: g.is_regular(k=3)
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.EllinghamHorton54Graph()
        >>> g.is_regular(k=Integer(3))
        True

    It is 3-connected and bipartite:

    Sage

        sage: g.vertex_connectivity()   # not tested - too long
        3
        sage: g.is_bipartite()
        True

    [Python]

        >>> from sage.all import *
        >>> g.vertex_connectivity()   # not tested - too long
        3
        >>> g.is_bipartite()
        True

    It is not Hamiltonian:

    Sage

        sage: g.is_hamiltonian()                # not tested                            # needs sage.numerical.mip
        False

    Python

        >>> from sage.all import *
        >>> g.is_hamiltonian()                # not tested                            # needs sage.numerical.mip
        False

    … and it has a nice drawing

    Sage

        sage: g.show(figsize=[10, 10])  # not tested - too long

    [Python]

        >>> from sage.all import *
        >>> g.show(figsize=[Integer(10), Integer(10)])  # not tested - too long

  static EllinghamHorton78Graph()

    Return the Ellingham-Horton 78-graph.

    For more information, see the Wikipedia article Ellingham%E2%80%93Horton_graph

    EXAMPLES:

    This graph is 3-regular:

    Sage

        sage: g = graphs.EllinghamHorton78Graph()
        sage: g.is_regular(k=3)
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.EllinghamHorton78Graph()
        >>> g.is_regular(k=Integer(3))
        True

    It is 3-connected and bipartite:

    Sage

        sage: g.vertex_connectivity()   # not tested (too long)
        3
        sage: g.is_bipartite()
        True

    [Python]

        >>> from sage.all import *
        >>> g.vertex_connectivity()   # not tested (too long)
        3
        >>> g.is_bipartite()
        True

    It is not Hamiltonian:

    Sage

        sage: g.is_hamiltonian()                # not tested                            # needs sage.numerical.mip
        False

    Python

        >>> from sage.all import *
        >>> g.is_hamiltonian()                # not tested                            # needs sage.numerical.mip
        False

    … and it has a nice drawing

    Sage

        sage: g.show(figsize=[10,10])   # not tested (too long)

    [Python]

        >>> from sage.all import *
        >>> g.show(figsize=[Integer(10),Integer(10)])   # not tested (too long)

  static EmptyGraph(immutable=False)

    Return an empty graph (0 nodes and 0 edges).

    This is useful for constructing graphs by adding edges and vertices individually or in a loop.

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    PLOTTING: When plotting, this graph will use the default spring-layout algorithm, unless a position dictionary is specified.

    EXAMPLES:

    Add one vertex to an empty graph and then show:

    Sage

        sage: empty1 = graphs.EmptyGraph()
        sage: empty1.add_vertex()
        0
        sage: empty1.show()                     # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> empty1 = graphs.EmptyGraph()
        >>> empty1.add_vertex()
        0
        >>> empty1.show()                     # long time                             # needs sage.plot

    Use for loops to build a graph from an empty graph:

    Sage

        sage: empty2 = graphs.EmptyGraph()
        sage: for i in range(5):
        ....:     empty2.add_vertex()  # add 5 nodes, labeled 0-4
        0
        1
        2
        3
        4
        sage: for i in range(3):
        ....:     empty2.add_edge(i,i+1)  # add edges {[0:1],[1:2],[2:3]}
        sage: for i in range(1, 4):
        ....:     empty2.add_edge(4,i)  # add edges {[1:4],[2:4],[3:4]}
        sage: empty2.show()                     # long time                             # needs sage.plot

    [Python]

        >>> from sage.all import *
        >>> empty2 = graphs.EmptyGraph()
        >>> for i in range(Integer(5)):
        ...     empty2.add_vertex()  # add 5 nodes, labeled 0-4
        0
        1
        2
        3
        4
        >>> for i in range(Integer(3)):
        ...     empty2.add_edge(i,i+Integer(1))  # add edges {[0:1],[1:2],[2:3]}
        >>> for i in range(Integer(1), Integer(4)):
        ...     empty2.add_edge(Integer(4),i)  # add edges {[1:4],[2:4],[3:4]}
        >>> empty2.show()                     # long time                             # needs sage.plot

  static ErreraGraph()

    Return the Errera graph.

    For more information, see the Wikipedia article Errera_graph.

    EXAMPLES:

    The Errera graph is named after Alfred Errera. It is a planar graph on 17 vertices and having 45 edges:

    Sage

        sage: G = graphs.ErreraGraph(); G
        Errera graph: Graph on 17 vertices
        sage: G.is_planar()
        True
        sage: G.order()
        17
        sage: G.size()
        45

    Python

        >>> from sage.all import *
        >>> G = graphs.ErreraGraph(); G
        Errera graph: Graph on 17 vertices
        >>> G.is_planar()
        True
        >>> G.order()
        17
        >>> G.size()
        45

    The Errera graph is Hamiltonian with radius 3, diameter 4, girth 3, and chromatic number 4:

    Sage

        sage: G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        sage: G.radius()
        3
        sage: G.diameter()
        4
        sage: G.girth()
        3
        sage: G.chromatic_number()
        4

    [Python]

        >>> from sage.all import *
        >>> G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        >>> G.radius()
        3
        >>> G.diameter()
        4
        >>> G.girth()
        3
        >>> G.chromatic_number()
        4

    Each vertex degree is either 5 or 6. That is, if \(f\) counts the number of vertices of degree 5 and \(s\) counts the number of vertices of degree 6, then \(f + s\) is equal to the order of the Errera graph:

    Sage

        sage: D = G.degree_sequence()
        sage: D.count(5) + D.count(6) == G.order()
        True

    Python

        >>> from sage.all import *
        >>> D = G.degree_sequence()
        >>> D.count(Integer(5)) + D.count(Integer(6)) == G.order()
        True

    The automorphism group of the Errera graph is isomorphic to the dihedral group of order 20:

    Sage

        sage: ag = G.automorphism_group()                                               # needs sage.groups
        sage: ag.is_isomorphic(DihedralGroup(10))                                       # needs sage.groups
        True

    [Python]

        >>> from sage.all import *
        >>> ag = G.automorphism_group()                                               # needs sage.groups
        >>> ag.is_isomorphic(DihedralGroup(Integer(10)))                                       # needs sage.groups
        True

  static EuropeMap(continental=False, year=2018)

    Return European states as a graph of common border.

    “European state” here is defined as an independent state having the capital city in Europe. The graph has an edge between those countries that have common land border.

    INPUT:

    - `continental` – boolean (default: `False`); whether to only return states in the continental Europe or all European states

    - `year` – integer (default: 2018); reserved for future use

    EXAMPLES:

    Sage

        sage: Europe = graphs.EuropeMap(); Europe
        Europe Map: Graph on 44 vertices
        sage: Europe.neighbors('Ireland')
        ['United Kingdom']

        sage: cont_Europe = graphs.EuropeMap(continental=True)
        sage: cont_Europe.order()
        40
        sage: 'Iceland' in cont_Europe
        False

    Python

        >>> from sage.all import *
        >>> Europe = graphs.EuropeMap(); Europe
        Europe Map: Graph on 44 vertices
        >>> Europe.neighbors('Ireland')
        ['United Kingdom']

        >>> cont_Europe = graphs.EuropeMap(continental=True)
        >>> cont_Europe.order()
        40
        >>> 'Iceland' in cont_Europe
        False

  static F26AGraph()

    Return the F26A graph.

    The F26A graph is a symmetric bipartite cubic graph with 26 vertices and 39 edges. For more information, see the Wikipedia article F26A_graph.

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.F26AGraph(); g
        F26A Graph: Graph on 26 vertices
        sage: g.order(), g.size()
        (26, 39)
        sage: g.automorphism_group().cardinality()
        78
        sage: g.girth()
        6
        sage: g.is_bipartite()
        True
        sage: g.characteristic_polynomial().factor()
        (x - 3) * (x + 3) * (x^4 - 5*x^2 + 3)^6

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.F26AGraph(); g
        F26A Graph: Graph on 26 vertices
        >>> g.order(), g.size()
        (26, 39)
        >>> g.automorphism_group().cardinality()
        78
        >>> g.girth()
        6
        >>> g.is_bipartite()
        True
        >>> g.characteristic_polynomial().factor()
        (x - 3) * (x + 3) * (x^4 - 5*x^2 + 3)^6

  static FibonacciTree(n)

    Return the graph of the Fibonacci Tree \(F_{n}\).

    The Fibonacci tree \(F_{n}\) is recursively defined as the tree with a root vertex and two attached child trees \(F_{n-1}\) and \(F_{n-2}\), where \(F_{1}\) is just one vertex and \(F_{0}\) is empty.

    INPUT:

    - `n` – the recursion depth of the Fibonacci Tree

    EXAMPLES:

    Sage

        sage: g = graphs.FibonacciTree(3)                                               # needs sage.libs.pari
        sage: g.is_tree()                                                               # needs sage.libs.pari
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.FibonacciTree(Integer(3))                                               # needs sage.libs.pari
        >>> g.is_tree()                                                               # needs sage.libs.pari
        True

    Sage

        sage: l1 = [graphs.FibonacciTree(_).order() + 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

    [Python]

        >>> from sage.all import *
        >>> l1 = [graphs.FibonacciTree(_).order() + Integer(1) for _ in range(Integer(6))]              # needs sage.libs.pari
        >>> l2 = list(fibonacci_sequence(Integer(2),Integer(8)))                                        # needs sage.libs.pari
        >>> l1 == l2                                                                  # needs sage.libs.pari
        True

    AUTHORS:

    - Harald Schilly and Yann Laigle-Chapuy (2010-03-25)

  static FlowerSnark()

    Return a Flower Snark.

    A flower snark has 20 vertices. It is part of the class of biconnected cubic graphs with edge chromatic number = 4, known as snarks. (i.e.: the Petersen graph). All snarks are not Hamiltonian, non-planar and have Petersen graph graph minors. See the Wikipedia article Flower_snark.

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the nodes are drawn 0-14 on the outer circle, and 15-19 in an inner pentagon.

    EXAMPLES: Inspect a flower snark:

    Sage

        sage: F = graphs.FlowerSnark()
        sage: F
        Flower Snark: Graph on 20 vertices
        sage: F.graph6_string()
        'ShCGHC@?GGg@?@?Gp?K??C?CA?G?_G?Cc'

    Python

        >>> from sage.all import *
        >>> F = graphs.FlowerSnark()
        >>> F
        Flower Snark: Graph on 20 vertices
        >>> F.graph6_string()
        'ShCGHC@?GGg@?@?Gp?K??C?CA?G?_G?Cc'

    Now show it:

    Sage

        sage: F.show()                          # long time                             # needs sage.plot

    [Python]

        >>> from sage.all import *
        >>> F.show()                          # long time                             # needs sage.plot

  static FoldedCubeGraph(n)

    Return the folded cube graph of order \(2^{n-1}\).

    The folded cube graph on \(2^{n-1}\) vertices can be obtained from a cube graph on \(2^n\) vertices by merging together opposed vertices. Alternatively, it can be obtained from a cube graph on \(2^{n-1}\) vertices by adding an edge between opposed vertices. This second construction is the one produced by this method.

    See the Wikipedia article Folded_cube_graph for more information.

    EXAMPLES:

    The folded cube graph of order five is the Clebsch graph:

    Sage

        sage: fc = graphs.FoldedCubeGraph(5)
        sage: clebsch = graphs.ClebschGraph()
        sage: fc.is_isomorphic(clebsch)
        True

    Python

        >>> from sage.all import *
        >>> fc = graphs.FoldedCubeGraph(Integer(5))
        >>> clebsch = graphs.ClebschGraph()
        >>> fc.is_isomorphic(clebsch)
        True

  static FolkmanGraph()

    Return the Folkman graph.

    See the Wikipedia article Folkman_graph.

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.FolkmanGraph()
        sage: g.order()
        20
        sage: g.size()
        40
        sage: g.diameter()
        4
        sage: g.girth()
        4
        sage: g.charpoly().factor()
        (x - 4) * (x + 4) * x^10 * (x^2 - 6)^4
        sage: g.chromatic_number()
        2
        sage: g.is_eulerian()
        True
        sage: g.is_hamiltonian()                                                        # needs sage.numerical_mip
        True
        sage: g.is_vertex_transitive()
        False
        sage: g.is_bipartite()
        True

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.FolkmanGraph()
        >>> g.order()
        20
        >>> g.size()
        40
        >>> g.diameter()
        4
        >>> g.girth()
        4
        >>> g.charpoly().factor()
        (x - 4) * (x + 4) * x^10 * (x^2 - 6)^4
        >>> g.chromatic_number()
        2
        >>> g.is_eulerian()
        True
        >>> g.is_hamiltonian()                                                        # needs sage.numerical_mip
        True
        >>> g.is_vertex_transitive()
        False
        >>> g.is_bipartite()
        True

  static ForkGraph(immutable=False)

    Return a fork graph with 5 nodes.

    A fork graph, sometimes also called chair graph, is 5 vertex tree.

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the fork graph is drawn as a fork, with the sharp part on the bottom.

    EXAMPLES:

    Construct and show a fork graph:

    Sage

        sage: g = graphs.ForkGraph()
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.ForkGraph()
        >>> g.show()                          # long time                             # needs sage.plot

  static FosterGraph()

    Return the Foster graph.

    See the Wikipedia article Foster_graph.

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.FosterGraph()
        sage: g.order()
        90
        sage: g.size()
        135
        sage: g.diameter()
        8
        sage: g.girth()
        10
        sage: g.automorphism_group().cardinality()
        4320
        sage: g.is_hamiltonian()                                                        # needs sage.numerical_mip
        True

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.FosterGraph()
        >>> g.order()
        90
        >>> g.size()
        135
        >>> g.diameter()
        8
        >>> g.girth()
        10
        >>> g.automorphism_group().cardinality()
        4320
        >>> g.is_hamiltonian()                                                        # needs sage.numerical_mip
        True

  static FosterGraph3S6(immutable=False)

    Return the Foster graph for \(3.Sym(6)\).

    This graph is distance-regular with intersection array \([6, 4, 2, 1; 1, 1, 4, 6]\).

    The graph is also distance transitive.

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Sage

        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])

    Python

        >>> from sage.all import *
        >>> G = graphs.FosterGraph3S6()                                               # needs sage.libs.gap
        >>> G.is_distance_regular(True)                                               # needs sage.libs.gap
        ([6, 4, 2, 1, None], [None, 1, 1, 4, 6])

    REFERENCES:

    A description and construction of this graph can be found in [BCN1989] p. 397.

  static FranklinGraph()

    Return the Franklin graph.

    For more information, see the Wikipedia article Franklin_graph.

    EXAMPLES:

    The Franklin graph is named after Philip Franklin. It is a 3-regular graph on 12 vertices and having 18 edges:

    Sage

        sage: G = graphs.FranklinGraph(); G
        Franklin graph: Graph on 12 vertices
        sage: G.is_regular(3)
        True
        sage: G.order()
        12
        sage: G.size()
        18

    Python

        >>> from sage.all import *
        >>> G = graphs.FranklinGraph(); G
        Franklin graph: Graph on 12 vertices
        >>> G.is_regular(Integer(3))
        True
        >>> G.order()
        12
        >>> G.size()
        18

    The Franklin graph is a Hamiltonian, bipartite graph with radius 3, diameter 3, and girth 4:

    Sage

        sage: G.is_hamiltonian()                                                        # needs sage.numerical_mip
        True
        sage: G.is_bipartite()
        True
        sage: G.radius()
        3
        sage: G.diameter()
        3
        sage: G.girth()
        4

    [Python]

        >>> from sage.all import *
        >>> G.is_hamiltonian()                                                        # needs sage.numerical_mip
        True
        >>> G.is_bipartite()
        True
        >>> G.radius()
        3
        >>> G.diameter()
        3
        >>> G.girth()
        4

    It is a perfect, triangle-free graph having chromatic number 2:

    Sage

        sage: G.is_perfect()
        True
        sage: G.is_triangle_free()
        True
        sage: G.chromatic_number()
        2

    Python

        >>> from sage.all import *
        >>> G.is_perfect()
        True
        >>> G.is_triangle_free()
        True
        >>> G.chromatic_number()
        2

  static FriendshipGraph(n)

    Return the friendship graph \(F_n\).

    The friendship graph is also known as the Dutch windmill graph. Let \(C_3\) be the cycle graph on 3 vertices. Then \(F_n\) is constructed by joining \(n \geq 1\) copies of \(C_3\) at a common vertex. If \(n = 1\), then \(F_1\) is isomorphic to \(C_3\) (the triangle graph). If \(n = 2\), then \(F_2\) is the butterfly graph, otherwise known as the bowtie graph. For more information, see the Wikipedia article Friendship_graph.

    INPUT:

    - `n` – positive integer; the number of copies of \(C_3\) to use in constructing \(F_n\)

    OUTPUT:

    - The friendship graph \(F_n\) obtained from \(n\) copies of the cycle graph \(C_3\).

    See also

    - `GraphGenerators.ButterflyGraph()`

    EXAMPLES:

    The first few friendship graphs.

    Sage

        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):
        ....:     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)
        sage: G.show()                          # long time

    Python

        >>> from sage.all import *
        >>> # needs sage.plot
        >>> A = []; B = []
        >>> for i in range(Integer(9)):
        ...     g = graphs.FriendshipGraph(i + Integer(1))
        ...     A.append(g)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for j in range(Integer(3)):
        ...         n.append(A[Integer(3)*i + j].plot(vertex_size=Integer(20), vertex_labels=False))
        ...     B.append(n)
        >>> G = graphics_array(B)
        >>> 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.

    Sage

        sage: G = graphs.FriendshipGraph(1); G
        Friendship graph: Graph on 3 vertices
        sage: G.show()                          # long time                             # needs sage.plot
        sage: G.is_isomorphic(graphs.CycleGraph(3))
        True

    [Python]

        >>> from sage.all import *
        >>> G = graphs.FriendshipGraph(Integer(1)); G
        Friendship graph: Graph on 3 vertices
        >>> G.show()                          # long time                             # needs sage.plot
        >>> G.is_isomorphic(graphs.CycleGraph(Integer(3)))
        True

    For \(n = 2\), the friendship graph \(F_2\) is isomorphic to the butterfly graph, otherwise known as the bowtie graph.

    Sage

        sage: G = graphs.FriendshipGraph(2); G
        Friendship graph: Graph on 5 vertices
        sage: G.is_isomorphic(graphs.ButterflyGraph())
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.FriendshipGraph(Integer(2)); G
        Friendship graph: Graph on 5 vertices
        >>> G.is_isomorphic(graphs.ButterflyGraph())
        True

    If \(n \geq 2\), then the friendship graph \(F_n\) has \(2n + 1\) vertices and \(3n\) edges. It has radius 1, diameter 2, girth 3, and chromatic number 3. Furthermore, \(F_n\) is planar and Eulerian.

    Sage

        sage: n = randint(2, 10^3)
        sage: G = graphs.FriendshipGraph(n)
        sage: G.order() == 2*n + 1
        True
        sage: G.size() == 3*n
        True
        sage: G.radius()
        1
        sage: G.diameter()
        2
        sage: G.girth()
        3
        sage: G.chromatic_number()
        3
        sage: G.is_planar()
        True
        sage: G.is_eulerian()
        True

    [Python]

        >>> from sage.all import *
        >>> n = randint(Integer(2), Integer(10)**Integer(3))
        >>> G = graphs.FriendshipGraph(n)
        >>> G.order() == Integer(2)*n + Integer(1)
        True
        >>> G.size() == Integer(3)*n
        True
        >>> G.radius()
        1
        >>> G.diameter()
        2
        >>> G.girth()
        3
        >>> G.chromatic_number()
        3
        >>> G.is_planar()
        True
        >>> G.is_eulerian()
        True

  static FruchtGraph()

    Return a Frucht Graph.

    A Frucht graph has 12 nodes and 18 edges. It is the smallest cubic identity graph. It is planar and Hamiltonian. See the Wikipedia article Frucht_graph.

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the first seven nodes are on the outer circle, with the next four on an inner circle and the last in the center.

    EXAMPLES:

    Sage

        sage: FRUCHT = graphs.FruchtGraph()
        sage: FRUCHT
        Frucht graph: Graph on 12 vertices
        sage: FRUCHT.graph6_string()
        'KhCKM?_EGK?L'
        sage: (graphs.FruchtGraph()).show()     # long time                             # needs networkx

    Python

        >>> from sage.all import *
        >>> FRUCHT = graphs.FruchtGraph()
        >>> FRUCHT
        Frucht graph: Graph on 12 vertices
        >>> FRUCHT.graph6_string()
        'KhCKM?_EGK?L'
        >>> (graphs.FruchtGraph()).show()     # long time                             # needs networkx

  static FurerGadget(k, prefix=None)

    Return a Furer gadget of order `k` and their coloring.

    Construct the Furer gadget described in [CFI1992], a graph composed by a middle layer of \(2^(k-1)\) nodes and two sets of nodes \((a_0, ... , a_{k-1})\) and \((b_0, ... , b_{k-1})\). Each node in the middle is connected to either \(a_i\) or \(b_i\), for each i in [0,k[. To read about the complete construction, see [CFI1992]. The returned coloring colors the middle section with one color, and then each pair \((a_i, b_i)\) with another color. Since this method is mainly used to create Furer gadgets for the Cai-Furer-Immerman construction, returning gadgets that don’t always have the same vertex labels is important, that’s why there is a parameter to manually set a prefix to be appended to each vertex label.

    INPUT:

    - `k` – the order of the returned Furer gadget, greater than 0

    - `prefix` – prefix of to be appended to each vertex label, so as to individualise the returned Furer gadget; must be comparable for equality and hashable

    OUTPUT:

    - `G` – the Furer gadget of order `k`

    - `coloring` – list of list of vertices, representing the partition induced by the coloring of `G`’s vertices

    EXAMPLES:

    Furer gadget of order 3, without any prefix.

    Sage

        sage: G, p = graphs.FurerGadget(3)
        sage: sorted(G, key=str)
        [(), (0, 'a'), (0, 'b'), (0, 1), (0, 2),
         (1, 'a'), (1, 'b'), (1, 2), (2, 'a'), (2, 'b')]
        sage: sorted(G.edge_iterator(), key=str)
        [((), (0, 'b'), None), ((), (1, 'b'), None),
         ((), (2, 'b'), None), ((0, 'b'), (1, 2), None),
         ((0, 1), (0, 'a'), None), ((0, 1), (1, 'a'), None),
         ((0, 1), (2, 'b'), None), ((0, 2), (0, 'a'), None),
         ((0, 2), (1, 'b'), None), ((0, 2), (2, 'a'), None),
         ((1, 2), (1, 'a'), None), ((1, 2), (2, 'a'), None)]

    Python

        >>> from sage.all import *
        >>> G, p = graphs.FurerGadget(Integer(3))
        >>> sorted(G, key=str)
        [(), (0, 'a'), (0, 'b'), (0, 1), (0, 2),
         (1, 'a'), (1, 'b'), (1, 2), (2, 'a'), (2, 'b')]
        >>> sorted(G.edge_iterator(), key=str)
        [((), (0, 'b'), None), ((), (1, 'b'), None),
         ((), (2, 'b'), None), ((0, 'b'), (1, 2), None),
         ((0, 1), (0, 'a'), None), ((0, 1), (1, 'a'), None),
         ((0, 1), (2, 'b'), None), ((0, 2), (0, 'a'), None),
         ((0, 2), (1, 'b'), None), ((0, 2), (2, 'a'), None),
         ((1, 2), (1, 'a'), None), ((1, 2), (2, 'a'), None)]

    Furer gadget of order 3, with a prefix.

    Sage

        sage: G, p = graphs.FurerGadget(3, 'Prefix')
        sage: sorted(G, key=str)
        [('Prefix', ()), ('Prefix', (0, 'a')), ('Prefix', (0, 'b')),
         ('Prefix', (0, 1)), ('Prefix', (0, 2)), ('Prefix', (1, 'a')),
         ('Prefix', (1, 'b')), ('Prefix', (1, 2)), ('Prefix', (2, 'a')),
         ('Prefix', (2, 'b'))]
        sage: sorted(G.edge_iterator(), key=str)
        [(('Prefix', ()), ('Prefix', (0, 'b')), None),
         (('Prefix', ()), ('Prefix', (1, 'b')), None),
         (('Prefix', ()), ('Prefix', (2, 'b')), None),
         (('Prefix', (0, 'b')), ('Prefix', (1, 2)), None),
         (('Prefix', (0, 1)), ('Prefix', (0, 'a')), None),
         (('Prefix', (0, 1)), ('Prefix', (1, 'a')), None),
         (('Prefix', (0, 1)), ('Prefix', (2, 'b')), None),
         (('Prefix', (0, 2)), ('Prefix', (0, 'a')), None),
         (('Prefix', (0, 2)), ('Prefix', (1, 'b')), None),
         (('Prefix', (0, 2)), ('Prefix', (2, 'a')), None),
         (('Prefix', (1, 2)), ('Prefix', (1, 'a')), None),
         (('Prefix', (1, 2)), ('Prefix', (2, 'a')), None)]

    [Python]

        >>> from sage.all import *
        >>> G, p = graphs.FurerGadget(Integer(3), 'Prefix')
        >>> sorted(G, key=str)
        [('Prefix', ()), ('Prefix', (0, 'a')), ('Prefix', (0, 'b')),
         ('Prefix', (0, 1)), ('Prefix', (0, 2)), ('Prefix', (1, 'a')),
         ('Prefix', (1, 'b')), ('Prefix', (1, 2)), ('Prefix', (2, 'a')),
         ('Prefix', (2, 'b'))]
        >>> sorted(G.edge_iterator(), key=str)
        [(('Prefix', ()), ('Prefix', (0, 'b')), None),
         (('Prefix', ()), ('Prefix', (1, 'b')), None),
         (('Prefix', ()), ('Prefix', (2, 'b')), None),
         (('Prefix', (0, 'b')), ('Prefix', (1, 2)), None),
         (('Prefix', (0, 1)), ('Prefix', (0, 'a')), None),
         (('Prefix', (0, 1)), ('Prefix', (1, 'a')), None),
         (('Prefix', (0, 1)), ('Prefix', (2, 'b')), None),
         (('Prefix', (0, 2)), ('Prefix', (0, 'a')), None),
         (('Prefix', (0, 2)), ('Prefix', (1, 'b')), None),
         (('Prefix', (0, 2)), ('Prefix', (2, 'a')), None),
         (('Prefix', (1, 2)), ('Prefix', (1, 'a')), None),
         (('Prefix', (1, 2)), ('Prefix', (2, 'a')), None)]

  static FuzzyBallGraph(partition, q)

    Construct a Fuzzy Ball graph with the integer partition `partition` and `q` extra vertices.

    Let \(q\) be an integer and let \(m_1,m_2,...,m_k\) be a set of positive integers. Let \(n=q+m_1+...+m_k\). The Fuzzy Ball graph with partition \(m_1,m_2,...,m_k\) and \(q\) extra vertices is the graph constructed from the graph \(G=K_n\) by attaching, for each \(i=1,2,...,k\), a new vertex \(a_i\) to \(m_i\) distinct vertices of \(G\).

    For given positive integers \(k\) and \(m\) and nonnegative integer \(q\), the set of graphs `FuzzyBallGraph(p, q)` for all partitions \(p\) of \(m\) with \(k\) parts are cospectral with respect to the normalized Laplacian.

    EXAMPLES:

    Sage

        sage: F = graphs.FuzzyBallGraph([3,1],2)
        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]
        [1 0 1 0 1 1 1 1]
        [1 0 1 1 0 1 1 1]
        [0 1 1 1 1 0 1 1]
        [0 0 1 1 1 1 0 1]
        [0 0 1 1 1 1 1 0]

    Python

        >>> from sage.all import *
        >>> F = graphs.FuzzyBallGraph([Integer(3),Integer(1)],Integer(2))
        >>> 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]
        [1 0 1 0 1 1 1 1]
        [1 0 1 1 0 1 1 1]
        [0 1 1 1 1 0 1 1]
        [0 0 1 1 1 1 0 1]
        [0 0 1 1 1 1 1 0]

    Pick positive integers \(m\) and \(k\) and a nonnegative integer \(q\). All the FuzzyBallGraphs constructed from partitions of \(m\) with \(k\) parts should be cospectral with respect to the normalized Laplacian:

    Sage

        sage: m = 4; q = 2; k = 2
        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), 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
          - 120877/3240*x^3 + 1351/100*x^2 - 931/450*x}

    [Python]

        >>> from sage.all import *
        >>> m = Integer(4); q = Integer(2); k = Integer(2)
        >>> g_list = [graphs.FuzzyBallGraph(p,q)                                      # needs sage.combinat sage.modules
        ...           for p in Partitions(m, length=k)]
        >>> 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
          - 120877/3240*x^3 + 1351/100*x^2 - 931/450*x}

  static GemGraph(immutable=False)

    Return a gem graph with 5 nodes.

    A gem graph is a fan graph (4,1).

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the gem graph is drawn as a gem, with the sharp part on the bottom.

    EXAMPLES:

    Construct and show a gem graph:

    Sage

        sage: g = graphs.GemGraph()
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.GemGraph()
        >>> g.show()                          # long time                             # needs sage.plot

  static GeneralisedDodecagonGraph(s, t)

    Return the point-graph of a generalised dodecagon of order \((s,t)\).

    INPUT:

    - `s`, `t` – integers; order of the generalised dodecagon

    EXAMPLES:

    Sage

        sage: # optional - gap_package_atlasrep 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)
        sage: H.order()
        23436
        sage: H.is_distance_regular(True)       # not tested (6 min)
        ([10, 5, 5, 5, 5, 5, None], [None, 1, 1, 1, 1, 1, 2])

    Python

        >>> from sage.all import *
        >>> # optional - gap_package_atlasrep internet
        >>> G = graphs.GeneralisedDodecagonGraph(Integer(1), Integer(5))
        >>> G.is_distance_regular(True)
        ([6, 5, 5, 5, 5, 5, None], [None, 1, 1, 1, 1, 1, 6])
        >>> H = graphs.GeneralisedDodecagonGraph(Integer(5), Integer(1))
        >>> H.order()
        23436
        >>> H.is_distance_regular(True)       # not tested (6 min)
        ([10, 5, 5, 5, 5, 5, None], [None, 1, 1, 1, 1, 1, 2])

    Note

    This function indirectly uses the GAP’s AtlasRep package. Thus you may need an internet connection and the optional Sage’s package `gap_packages`.

    REFERENCES:

    See [BCN1989] pp. 200-205 for a discussion of distance-regular graphs from generalised polygons.

  static GeneralisedHexagonGraph(s, t)

    Return the point-graph of a generalised hexagon of order \((s,t)\).

    INPUT:

    - `s`, `t` – integers; order of the generalised hexagon

    EXAMPLES:

    Sage

        sage: # needs sage.libs.gap
        sage: G = graphs.GeneralisedHexagonGraph(5, 5)          # optional - gap_package_atlasrep internet
        sage: G.is_distance_regular(True)                       # optional - gap_package_atlasrep internet
        ([30, 25, 25, None], [None, 1, 1, 6])
        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)
        Cycle graph: Graph on 6 vertices

    Python

        >>> from sage.all import *
        >>> # needs sage.libs.gap
        >>> G = graphs.GeneralisedHexagonGraph(Integer(5), Integer(5))          # optional - gap_package_atlasrep internet
        >>> G.is_distance_regular(True)                       # optional - gap_package_atlasrep internet
        ([30, 25, 25, None], [None, 1, 1, 6])
        >>> G = graphs.GeneralisedHexagonGraph(Integer(7), Integer(1))
        >>> G.is_distance_regular(True)
        ([14, 7, 7, None], [None, 1, 1, 2])
        >>> graphs.GeneralisedHexagonGraph(Integer(1), Integer(1))
        Cycle graph: Graph on 6 vertices

    Note

    This function uses the GAP’s AtlasRep package to build GHs of order \((q, q)\), \((q, q^3)\) or \((q^3, q)\). For those graphs you need an internet connection and Sage’s optional package `gap_packages`.

    REFERENCES:

    See [BCN1989] pp. 200-205 for a discussion of distance-regular graphs from generalised polygons.

  static GeneralisedOctagonGraph(s, t)

    Return the point-graph of a generalised octagon of order \((s,t)\).

    INPUT:

    - `s`, `t` – integers; order of the generalised octagon

    EXAMPLES:

    Sage

        sage: # needs sage.libs.gap
        sage: G = graphs.GeneralisedOctagonGraph(1, 4)          # optional - database_graphs
        sage: G.is_distance_regular(True)                       # optional - database_graphs
        ([5, 4, 4, 4, None], [None, 1, 1, 1, 5])
        sage: G = graphs.GeneralisedOctagonGraph(2, 4)          # optional - gap_package_atlasrep internet
        sage: G.is_distance_regular(True)                       # optional - gap_package_atlasrep internet
        ([10, 8, 8, 8, None], [None, 1, 1, 1, 5])
        sage: G = graphs.GeneralisedOctagonGraph(5, 1)          # optional - database_graphs
        sage: G.is_distance_regular(True)                       # optional - database_graphs
        ([10, 5, 5, 5, None], [None, 1, 1, 1, 2])

    Python

        >>> from sage.all import *
        >>> # needs sage.libs.gap
        >>> G = graphs.GeneralisedOctagonGraph(Integer(1), Integer(4))          # optional - database_graphs
        >>> G.is_distance_regular(True)                       # optional - database_graphs
        ([5, 4, 4, 4, None], [None, 1, 1, 1, 5])
        >>> G = graphs.GeneralisedOctagonGraph(Integer(2), Integer(4))          # optional - gap_package_atlasrep internet
        >>> G.is_distance_regular(True)                       # optional - gap_package_atlasrep internet
        ([10, 8, 8, 8, None], [None, 1, 1, 1, 5])
        >>> G = graphs.GeneralisedOctagonGraph(Integer(5), Integer(1))          # optional - database_graphs
        >>> G.is_distance_regular(True)                       # optional - database_graphs
        ([10, 5, 5, 5, None], [None, 1, 1, 1, 2])

    Note

    This function uses the GAP’s AtlasRep package to build the graphs of order \((2, 4)\) or \((4, 2)\). For those graphs you need an internet connection and Sage’s optional package `gap_packages`.

    REFERENCES:

    See [BCN1989] pp. 200-205 for a discussion of distance-regular graphs from generalised polygons.

  static GeneralizedPetersenGraph(n, k)

    Return a generalized Petersen graph with \(2n\) nodes. The variables \(n\), \(k\) are integers such that \(n>2\) and \(0<k\leq\lfloor(n-1)\)/\(2\rfloor\)

    For \(k=1\) the result is a graph isomorphic to the circular ladder graph with the same \(n\). The regular Petersen Graph has \(n=5\) and \(k=2\). Other named graphs that can be described using this notation include the Desargues graph and the Möbius-Kantor graph.

    INPUT:

    - `n` – the number of nodes is \(2*n\)

    - `k` – integer (\(0<k\leq\lfloor(n-1)\)/\(2\rfloor\)); decides how inner vertices are connected

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the generalized Petersen graphs are displayed as an inner and outer cycle pair, with the first n nodes drawn on the outer circle. The first (0) node is drawn at the top of the outer-circle, moving counterclockwise after that. The inner circle is drawn with the (n)th node at the top, then counterclockwise as well.

    EXAMPLES: For \(k=1\) the resulting graph will be isomorphic to a circular ladder graph.

    Sage

        sage: g = graphs.GeneralizedPetersenGraph(13,1)
        sage: g2 = graphs.CircularLadderGraph(13)
        sage: g.is_isomorphic(g2)
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.GeneralizedPetersenGraph(Integer(13),Integer(1))
        >>> g2 = graphs.CircularLadderGraph(Integer(13))
        >>> g.is_isomorphic(g2)
        True

    The Desargues graph:

    Sage

        sage: g = graphs.GeneralizedPetersenGraph(10,3)
        sage: g.girth()
        6
        sage: g.is_bipartite()
        True

    [Python]

        >>> from sage.all import *
        >>> g = graphs.GeneralizedPetersenGraph(Integer(10),Integer(3))
        >>> g.girth()
        6
        >>> g.is_bipartite()
        True

    AUTHORS:

    - Anders Jonsson (2009-10-15)

  static GeneralizedSierpinskiGraph(G, k, stretch=None)

    Return the generalized Sierpinski graph of \(G\) of dimension \(k\).

    Generalized Sierpinski graphs have been introduced in [GKP2011] to generalize the notion of Sierpinski graphs [KM1997].

    Given a graph \(G = (V, E)\) of order \(n\) and a parameter \(k\), the generalized Sierpinski graph of \(G\) of dimension \(k\), denoted by \(S(G, k)\), can be constructed recursively from \(G\) as follows. \(S(G, 1)\) is isomorphic to \(G\). To construct \(S(G, k)\) for \(k > 1\), copy \(n\) times \(S(G, k - 1)\), once per vertex \(u \in V\), and add \(u\) at the beginning of the labels of each vertex in the copy of \(S(G, k - 1)\) corresponding to vertex \(u\). Then for any edge \(\{u, v\} \in E\), add an edge between vertex \((u, v, \ldots, v)\) and vertex \((v, u, \ldots, u)\).

    INPUT:

    - `G` – a sage Graph

    - `k` – integer; the dimension

    - `stretch` – integer (default: `None`); stretching factor used to determine the positions of the vertices of the output graph. By default (`None`), this value is set to twice the maximum Euclidean distance between the vertices of \(G\). This parameter is used only when the vertices of \(G\) have positions.

    See also

    - `SierpinskiGasketGraph()`

    - `HanoiTowerGraph()`

    EXAMPLES:

    The generalized Sierpinski graph of dimension 1 of any graph \(G\) is isomorphic to \(G\):

    Sage

        sage: G = graphs.RandomGNP(10, .5)
        sage: S = graphs.GeneralizedSierpinskiGraph(G, 1)
        sage: S.is_isomorphic(G)
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.RandomGNP(Integer(10), RealNumber('.5'))
        >>> S = graphs.GeneralizedSierpinskiGraph(G, Integer(1))
        >>> S.is_isomorphic(G)
        True

    When \(G\) is a clique of order 3, the generalized Sierpinski graphs of \(G\) are isomorphic to Hanoi Tower graphs:

    Sage

        sage: k = randint(1, 5)
        sage: S = graphs.GeneralizedSierpinskiGraph(graphs.CompleteGraph(3), k)         # needs sage.modules
        sage: H = graphs.HanoiTowerGraph(3, k)
        sage: S.is_isomorphic(H)                                                        # needs sage.modules
        True

    [Python]

        >>> from sage.all import *
        >>> k = randint(Integer(1), Integer(5))
        >>> S = graphs.GeneralizedSierpinskiGraph(graphs.CompleteGraph(Integer(3)), k)         # needs sage.modules
        >>> H = graphs.HanoiTowerGraph(Integer(3), k)
        >>> S.is_isomorphic(H)                                                        # needs sage.modules
        True

    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

        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)
        sage: S.order() == n**k
        True
        sage: S.size() == m*sum([n**i for i in range(k)])
        True
        sage: G = graphs.CompleteGraph(n)
        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)])
        True

    Python

        >>> from sage.all import *
        >>> # needs sage.modules
        >>> n = randint(Integer(2), Integer(6))
        >>> k = randint(Integer(1), Integer(5))
        >>> G = graphs.RandomGNP(n, RealNumber('.5'))
        >>> m = G.size()
        >>> S = graphs.GeneralizedSierpinskiGraph(G, k)
        >>> S.order() == n**k
        True
        >>> S.size() == m*sum([n**i for i in range(k)])
        True
        >>> G = graphs.CompleteGraph(n)
        >>> S = graphs.GeneralizedSierpinskiGraph(G, k)
        >>> S.order() == n**k
        True
        >>> S.size() == (n*(n - Integer(1))/Integer(2))*sum([n**i for i in range(k)])
        True

    The positions of the vertices of the output graph are determined from the positions of the vertices of \(G\), if any:

    Sage

        sage: G = graphs.HouseGraph()
        sage: G.get_pos() is not None
        True
        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)                               # needs sage.symbolic
        sage: H.get_pos() is not None                                                   # needs sage.symbolic
        False

    [Python]

        >>> from sage.all import *
        >>> G = graphs.HouseGraph()
        >>> G.get_pos() is not None
        True
        >>> H = graphs.GeneralizedSierpinskiGraph(G, Integer(2))                               # needs sage.symbolic
        >>> H.get_pos() is not None                                                   # needs sage.symbolic
        True
        >>> G = Graph([(Integer(0), Integer(1))])
        >>> G.get_pos() is not None
        False
        >>> H = graphs.GeneralizedSierpinskiGraph(G, Integer(2))                               # needs sage.symbolic
        >>> H.get_pos() is not None                                                   # needs sage.symbolic
        False

  static GoethalsSeidelGraph(k, r)

    Return the graph \(\text{Goethals-Seidel}(k,r)\).

    The graph \(\text{Goethals-Seidel}(k,r)\) comes from a construction presented in Theorem 2.4 of [GS1970]. It relies on a `(v,k)-BIBD` with \(r\) blocks and a `hadamard_matrix()` of order \(r+1\). The result is a `sage.graphs.strongly_regular_db.strongly_regular_graph()` on \(v(r+1)\) vertices with degree \(k=(n+r-1)/2\).

    It appears under this name in Andries Brouwer’s database of strongly regular graphs.

    INPUT:

    - `k`, `r` – integers

    See also

    - `is_goethals_seidel()`

    EXAMPLES:

    Sage

        sage: graphs.GoethalsSeidelGraph(3,3)                                           # needs sage.combinat sage.modules
        Graph on 28 vertices
        sage: graphs.GoethalsSeidelGraph(3,3).is_strongly_regular(parameters=True)      # needs sage.combinat sage.modules
        (28, 15, 6, 10)

    Python

        >>> from sage.all import *
        >>> graphs.GoethalsSeidelGraph(Integer(3),Integer(3))                                           # needs sage.combinat sage.modules
        Graph on 28 vertices
        >>> graphs.GoethalsSeidelGraph(Integer(3),Integer(3)).is_strongly_regular(parameters=True)      # needs sage.combinat sage.modules
        (28, 15, 6, 10)

  static GoldnerHararyGraph()

    Return the Goldner-Harary graph.

    For more information, see the Wikipedia article Goldner%E2%80%93Harary_graph.

    EXAMPLES:

    The Goldner-Harary graph is named after A. Goldner and Frank Harary. It is a planar graph having 11 vertices and 27 edges:

    Sage

        sage: G = graphs.GoldnerHararyGraph(); G
        Goldner-Harary graph: Graph on 11 vertices
        sage: G.is_planar()
        True
        sage: G.order()
        11
        sage: G.size()
        27

    Python

        >>> from sage.all import *
        >>> G = graphs.GoldnerHararyGraph(); G
        Goldner-Harary graph: Graph on 11 vertices
        >>> G.is_planar()
        True
        >>> G.order()
        11
        >>> G.size()
        27

    The Goldner-Harary graph is chordal with radius 2, diameter 2, and girth 3:

    Sage

        sage: G.is_chordal()
        True
        sage: G.radius()
        2
        sage: G.diameter()
        2
        sage: G.girth()
        3

    [Python]

        >>> from sage.all import *
        >>> G.is_chordal()
        True
        >>> G.radius()
        2
        >>> G.diameter()
        2
        >>> G.girth()
        3

    Its chromatic number is 4 and its automorphism group is isomorphic to the dihedral group \(D_6\):

    Sage

        sage: G.chromatic_number()
        4
        sage: ag = G.automorphism_group()                                               # needs sage.groups
        sage: ag.is_isomorphic(DihedralGroup(6))                                        # needs sage.groups
        True

    Python

        >>> from sage.all import *
        >>> G.chromatic_number()
        4
        >>> ag = G.automorphism_group()                                               # needs sage.groups
        >>> ag.is_isomorphic(DihedralGroup(Integer(6)))                                        # needs sage.groups
        True

  static GolombGraph()

    Return the Golomb graph.

    See the Wikipedia article Golomb_graph for more information.

    EXAMPLES:

    The Golomb graph is a planar and Hamiltonian graph with 10 vertices 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

        sage: G = graphs.GolombGraph(); G                                               # needs sage.symbolic
        Golomb graph: Graph on 10 vertices
        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))  # needs sage.symbolic
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.GolombGraph(); G                                               # needs sage.symbolic
        Golomb graph: Graph on 10 vertices
        >>> pos = G.get_pos()                                                         # needs sage.symbolic
        >>> def dist2(u, v):
        ...     return (u[Integer(0)]-v[Integer(0)])**Integer(2) + (u[Integer(1)]-v[Integer(1)])**Integer(2)
        >>> all(dist2(pos[u], pos[v]) == Integer(1) for u, v in G.edge_iterator(labels=None))  # needs sage.symbolic
        True

  static GossetGraph()

    Return the Gosset graph.

    The Gosset graph is the skeleton of the `Gosset_3_21()` polytope. It has with 56 vertices and degree 27. For more information, see the Wikipedia article Gosset_graph.

    EXAMPLES:

    Sage

        sage: g = graphs.GossetGraph(); g
        Gosset Graph: Graph on 56 vertices
        sage: g.order(), g.size()
        (56, 756)

    Python

        >>> from sage.all import *
        >>> g = graphs.GossetGraph(); g
        Gosset Graph: Graph on 56 vertices
        >>> g.order(), g.size()
        (56, 756)

  static GrassmannGraph(q, n, input_e)

    Return the Grassmann graph with parameters \((q, n, e)\).

    This builds the Grassmann graph \(J_q(n,e)\). That is, for a vector space \(V = \mathbb F(q)^n\) the output is the graph on the subspaces of dimension \(e\) where two subspaces are adjacent if their intersection has dimension \(e-1\).

    This graph is distance-regular with classical parameters \((\min(e, n-e), q, q, \genfrac {[}{]} {0pt} {} {n-e+1} 1 _q -1)\)

    INPUT:

    - `q` – a prime power

    - `n`, `e` – integers with \(n > e+1\)

    EXAMPLES:

    Sage

        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])

    Python

        >>> from sage.all import *
        >>> G = graphs.GrassmannGraph(Integer(2), Integer(4), Integer(2))                                        # needs sage.modules sage.rings.finite_rings
        >>> G.is_distance_regular(True)                                               # needs sage.modules sage.rings.finite_rings
        ([18, 8, None], [None, 1, 9])

    REFERENCES:

    See [BCN1989] pp. 268-272 or [VDKT2016] p. 21.

  static GrayGraph(embedding=1)

    Return the Gray graph.

    See the Wikipedia article Gray_graph.

    INPUT:

    - `embedding` – integer (default: \(1\)); two embeddings are available, and can be selected by setting `embedding` to 1 or 2

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.GrayGraph()
        sage: g.order()
        54
        sage: g.size()
        81
        sage: g.girth()
        8
        sage: g.diameter()
        6
        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

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.GrayGraph()
        >>> g.order()
        54
        >>> g.size()
        81
        >>> g.girth()
        8
        >>> g.diameter()
        6
        >>> g.show(figsize=[Integer(10), Integer(10)])          # long time                             # needs sage.plot
        >>> graphs.GrayGraph(embedding=Integer(2)).show(figsize=[Integer(10), Integer(10)])      # long time, needs sage.plot

  static Grid2dGraph(p, q, set_positions=True, immutable=False, name=None)

    Return a \(2\)-dimensional grid graph with \(p \times q\) nodes (\(p\) rows and \(q\) columns).

    A 2d grid graph resembles a \(2\) dimensional grid. All inner nodes are connected to their \(4\) neighbors. Outer (non-corner) nodes are connected to their \(3\) neighbors. Corner nodes are connected to their 2 neighbors.

    INPUT:

    - `p`, `q` – two positive integers

    - `set_positions` – boolean (default: `True`); whether to set the position of the nodes

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    - `name` – string (default: `None`); used as the name of the returned graph when set

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, nodes are labelled in (row, column) pairs with \((0, 0)\) in the top left corner. Edges will always be horizontal and vertical - another advantage of filling the position dictionary.

    EXAMPLES:

    Construct and show a grid 2d graph Rows = \(5\), Columns = \(7\):

    Sage

        sage: g = graphs.Grid2dGraph(5,7)
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.Grid2dGraph(Integer(5),Integer(7))
        >>> g.show()                          # long time                             # needs sage.plot

  static GridGraph(dim_list, immutable=False)

    Return an \(n\)-dimensional grid graph.

    INPUT:

    - `dim_list` – list of integers representing the number of nodes to extend in each dimension

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    PLOTTING: When plotting, this graph will use the default spring-layout algorithm, unless a position dictionary is specified.

    EXAMPLES:

    Sage

        sage: G = graphs.GridGraph([2,3,4])
        sage: G.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> G = graphs.GridGraph([Integer(2),Integer(3),Integer(4)])
        >>> G.show()                          # long time                             # needs sage.plot

    Sage

        sage: C = graphs.CubeGraph(4)
        sage: G = graphs.GridGraph([2,2,2,2])
        sage: C.show()                          # long time                             # needs sage.plot
        sage: G.show()                          # long time                             # needs sage.plot

    [Python]

        >>> from sage.all import *
        >>> C = graphs.CubeGraph(Integer(4))
        >>> G = graphs.GridGraph([Integer(2),Integer(2),Integer(2),Integer(2)])
        >>> C.show()                          # long time                             # needs sage.plot
        >>> G.show()                          # long time                             # needs sage.plot

  static GritsenkoGraph()

    Return SRG(65, 32, 15, 16) constructed by Gritsenko.

    We took the adjacency matrix from O. Gritsenko’s [Gri2021] and extracted orbits of the automorphism group on the edges.

    EXAMPLES:

    Sage

        sage: H = graphs.GritsenkoGraph(); H                                            # needs sage.groups
        Gritsenko strongly regular graph: Graph on 65 vertices
        sage: H.is_strongly_regular(parameters=True)                                    # needs sage.groups
        (65, 32, 15, 16)

    Python

        >>> from sage.all import *
        >>> H = graphs.GritsenkoGraph(); H                                            # needs sage.groups
        Gritsenko strongly regular graph: Graph on 65 vertices
        >>> H.is_strongly_regular(parameters=True)                                    # needs sage.groups
        (65, 32, 15, 16)

  static GrotzschGraph()

    Return the Grötzsch graph.

    The Grötzsch graph is an example of a triangle-free graph with chromatic number equal to 4. For more information, see the Wikipedia article Gr%C3%B6tzsch_graph.

    EXAMPLES:

    The Grötzsch graph is named after Herbert Grötzsch. It is a Hamiltonian graph with 11 vertices and 20 edges:

    Sage

        sage: G = graphs.GrotzschGraph(); G
        Grotzsch graph: Graph on 11 vertices
        sage: G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        sage: G.order()
        11
        sage: G.size()
        20

    Python

        >>> from sage.all import *
        >>> G = graphs.GrotzschGraph(); G
        Grotzsch graph: Graph on 11 vertices
        >>> G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        >>> G.order()
        11
        >>> G.size()
        20

    The Grötzsch graph is triangle-free and having radius 2, diameter 2, and girth 4:

    Sage

        sage: G.is_triangle_free()
        True
        sage: G.radius()
        2
        sage: G.diameter()
        2
        sage: G.girth()
        4

    [Python]

        >>> from sage.all import *
        >>> G.is_triangle_free()
        True
        >>> G.radius()
        2
        >>> G.diameter()
        2
        >>> G.girth()
        4

    Its chromatic number is 4 and its automorphism group is isomorphic to the dihedral group \(D_5\):

    Sage

        sage: G.chromatic_number()
        4
        sage: ag = G.automorphism_group()                                               # needs sage.groups
        sage: ag.is_isomorphic(DihedralGroup(5))                                        # needs sage.groups
        True

    Python

        >>> from sage.all import *
        >>> G.chromatic_number()
        4
        >>> ag = G.automorphism_group()                                               # needs sage.groups
        >>> ag.is_isomorphic(DihedralGroup(Integer(5)))                                        # needs sage.groups
        True

  static HaemersGraph(q, hyperoval=None, hyperoval_matching=None, field=None, check_hyperoval=True)

    Return the Haemers graph obtained from \(T_2^*(q)^*\).

    Let \(q\) be a power of 2. In Sect. 8.A of [BL1984] one finds a construction of a strongly regular graph with parameters \((q^2(q+2),q^2+q-1,q-2,q)\) from the graph of \(T_2^*(q)^*\), constructed by `T2starGeneralizedQuadrangleGraph()`, by redefining adjacencies in the way specified by an arbitrary `hyperoval_matching` of the points (i.e. partitioning into size two parts) of `hyperoval` defining \(T_2^*(q)^*\).

    While [BL1984] gives the construction in geometric terms, it can be formulated, and is implemented, in graph-theoretic ones, of re-adjusting the edges. Namely, \(G=T_2^*(q)^*\) has a partition into \(q+2\) independent sets \(I_k\) of size \(q^2\) each. Each vertex in \(I_j\) is adjacent to \(q\) vertices from \(I_k\). Each \(I_k\) is paired to some \(I_{k'}\), according to `hyperoval_matching`. One adds edges \((s,t)\) for \(s,t \in I_k\) whenever \(s\) and \(t\) are adjacent to some \(u \in I_{k'}\), and removes all the edges between \(I_k\) and \(I_{k'}\).

    INPUT:

    - `q` – a power of two

    - `hyperoval_matching` – if `None` (default), pair each \(i\)-th point of `hyperoval` with \((i+1)\)-th. Otherwise, specifies the pairing in the format \(((i_1,i'_1),(i_2,i'_2),...)\).

    - `hyperoval` – a hyperoval defining \(T_2^*(q)^*\). If `None` (default), the classical hyperoval obtained from a conic is used. See the documentation of `T2starGeneralizedQuadrangleGraph()`, for more information.

    - `field` – an instance of a finite field of order \(q\), must be provided if `hyperoval` is provided

    - `check_hyperoval` – boolean (default: `True`); whether to check `hyperoval` for correctness or not

    EXAMPLES:

    using the built-in constructions:

    Sage

        sage: # needs sage.combinat sage.rings.finite_rings
        sage: g = graphs.HaemersGraph(4); g
        Haemers(4): Graph on 96 vertices
        sage: g.is_strongly_regular(parameters=True)
        (96, 19, 2, 4)

    Python

        >>> from sage.all import *
        >>> # needs sage.combinat sage.rings.finite_rings
        >>> g = graphs.HaemersGraph(Integer(4)); g
        Haemers(4): Graph on 96 vertices
        >>> g.is_strongly_regular(parameters=True)
        (96, 19, 2, 4)

    supplying your own hyperoval_matching:

    Sage

        sage: # needs sage.combinat sage.rings.finite_rings
        sage: g = graphs.HaemersGraph(4, hyperoval_matching=((0,5),(1,4),(2,3))); g
        Haemers(4): Graph on 96 vertices
        sage: g.is_strongly_regular(parameters=True)
        (96, 19, 2, 4)

    [Python]

        >>> from sage.all import *
        >>> # needs sage.combinat sage.rings.finite_rings
        >>> g = graphs.HaemersGraph(Integer(4), hyperoval_matching=((Integer(0),Integer(5)),(Integer(1),Integer(4)),(Integer(2),Integer(3)))); g
        Haemers(4): Graph on 96 vertices
        >>> g.is_strongly_regular(parameters=True)
        (96, 19, 2, 4)

  static HalfCube(n)

    Return the halved cube in \(n\) dimensions.

    The graph is distance-regular with classical parameters \((\lfloor \frac n 2 \rfloor, 1, 2, 2 \lceil \frac n 2 \rceil -1)\).

    INPUT:

    - `n` – integer; must be greater than 2

    EXAMPLES:

    Sage

        sage: G = graphs.HalfCube(8)
        sage: G.is_distance_regular(True)
        ([28, 15, 6, 1, None], [None, 1, 6, 15, 28])
        sage: G = graphs.HalfCube(4)
        sage: G.is_distance_regular(True)
        ([6, 1, None], [None, 1, 6])

    Python

        >>> from sage.all import *
        >>> G = graphs.HalfCube(Integer(8))
        >>> G.is_distance_regular(True)
        ([28, 15, 6, 1, None], [None, 1, 6, 15, 28])
        >>> G = graphs.HalfCube(Integer(4))
        >>> G.is_distance_regular(True)
        ([6, 1, None], [None, 1, 6])

    REFERENCES:

    See [BCN1989] pp. 264, 265 or [VDKT2016] p. 21. This construction can be found on Wikipedia article Halved_cube_graph#Equivalent_constructions

  static HallJankoGraph(from_string=True)

    Return the Hall-Janko graph.

    For more information on the Hall-Janko graph, see the Wikipedia article Hall-Janko_graph.

    The construction used to generate this graph in Sage is by a 100-point permutation representation of the Janko group \(J_2\), as described in version 3 of the ATLAS of Finite Group representations, in particular on the page ATLAS: J2 – Permutation representation on 100 points.

    INPUT:

    - `from_string` – boolean (default: `True`); whether to build the graph from its sparse6 string or through GAP. The two methods return the same graph though doing it through GAP takes more time.

    EXAMPLES:

    Sage

        sage: g = graphs.HallJankoGraph()
        sage: g.is_regular(36)
        True
        sage: g.is_vertex_transitive()                                                  # needs sage.groups
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.HallJankoGraph()
        >>> g.is_regular(Integer(36))
        True
        >>> g.is_vertex_transitive()                                                  # needs sage.groups
        True

    Is it really strongly regular with parameters 14, 12?

    Sage

        sage: nu = set(g.neighbors(0))
        sage: for v in range(1, 100):
        ....:     if v in nu:
        ....:         expected = 14
        ....:     else:
        ....:         expected = 12
        ....:     nv = set(g.neighbors(v))
        ....:     nv.discard(0)
        ....:     if len(nu & nv) != expected:
        ....:         print("Something is wrong here!!!")
        ....:         break

    [Python]

        >>> from sage.all import *
        >>> nu = set(g.neighbors(Integer(0)))
        >>> for v in range(Integer(1), Integer(100)):
        ...     if v in nu:
        ...         expected = Integer(14)
        ...     else:
        ...         expected = Integer(12)
        ...     nv = set(g.neighbors(v))
        ...     nv.discard(Integer(0))
        ...     if len(nu & nv) != expected:
        ...         print("Something is wrong here!!!")
        ...         break

    Some other properties that we know how to check:

    Sage

        sage: g.diameter()
        2
        sage: g.girth()
        3
        sage: factor(g.characteristic_polynomial())                                     # needs sage.libs.pari sage.modules
        (x - 36) * (x - 6)^36 * (x + 4)^63

    Python

        >>> from sage.all import *
        >>> g.diameter()
        2
        >>> g.girth()
        3
        >>> factor(g.characteristic_polynomial())                                     # needs sage.libs.pari sage.modules
        (x - 36) * (x - 6)^36 * (x + 4)^63

  static HammingGraph(n, q, X=None)

    Return the Hamming graph with parameters \(n\), \(q\) over \(X\).

    Hamming graphs are graphs over the cartesian product of n copies of \(X\), where \(q = |X|\), where the vertices, labelled with the corresponding tuple in \(X^n\), are connected if the Hamming distance between their labels is 1. All Hamming graphs are regular, vertex-transitive and distance-regular.

    Hamming graphs with parameters \((1,q)\) represent the complete graph with q vertices over the set \(X\).

    INPUT:

    - `n` – power to which `X` will be raised to provide vertices for the Hamming graph

    - `q` – cardinality of `X`

    - `X` – list of labels representing the vertices of the underlying graph the Hamming graph will be based on; if `None` (or left unused), the list \([0, ... , q-1]\) will be used

    OUTPUT:

    - `G` – the Hamming graph with parameters \((n,q,X)\)

    EXAMPLES:

    Every Hamming graph is distance-regular, regular and vertex-transitive:

    Sage

        sage: g = graphs.HammingGraph(3, 7)
        sage: g.is_distance_regular()
        True
        sage: g.is_regular()
        True
        sage: g.is_vertex_transitive()                                                  # needs sage.groups
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.HammingGraph(Integer(3), Integer(7))
        >>> g.is_distance_regular()
        True
        >>> g.is_regular()
        True
        >>> g.is_vertex_transitive()                                                  # needs sage.groups
        True

    A Hamming graph with parameters \((1,q)\) is isomorphic to the Complete graph with parameter \(q\):

    Sage

        sage: g = graphs.HammingGraph(1, 23)
        sage: g.is_isomorphic(graphs.CompleteGraph(23))
        True

    [Python]

        >>> from sage.all import *
        >>> g = graphs.HammingGraph(Integer(1), Integer(23))
        >>> g.is_isomorphic(graphs.CompleteGraph(Integer(23)))
        True

    If a parameter \(q\) is provided which is not equal to \(X\)’s cardinality, an exception is raised:

    Sage

        sage: X = ['a','b','c','d','e']
        sage: g = graphs.HammingGraph(2, 3, X)
        Traceback (most recent call last):
        ...
        ValueError: q must be the cardinality of X

    Python

        >>> from sage.all import *
        >>> X = ['a','b','c','d','e']
        >>> g = graphs.HammingGraph(Integer(2), Integer(3), X)
        Traceback (most recent call last):
        ...
        ValueError: q must be the cardinality of X

    REFERENCES:

    For a more accurate description, see the following wikipedia page: Wikipedia article Hamming_graph

  static HanoiTowerGraph(pegs, disks, labels=True, positions=True)

    Return the graph whose vertices are the states of the Tower of Hanoi puzzle, with edges representing legal moves between states.

    INPUT:

    - `pegs` – the number of pegs in the puzzle, 2 or greater

    - `disks` – the number of disks in the puzzle, 1 or greater

    - `labels` – (default: `True`) if `True` the graph contains more meaningful labels, see explanation below. For large instances, turn off labels for much faster creation of the graph.

    - `positions` – (default: `True`) if `True` the graph contains layout information. This creates a planar layout for the case of three pegs. For large instances, turn off layout information for much faster creation of the graph.

    OUTPUT:

    The Tower of Hanoi puzzle has a certain number of identical pegs and a certain number of disks, each of a different radius. Initially the disks are all on a single peg, arranged in order of their radii, with the largest on the bottom.

    The goal of the puzzle is to move the disks to any other peg, arranged in the same order. The one constraint is that the disks resident on any one peg must always be arranged with larger radii lower down.

    The vertices of this graph represent all the possible states of this puzzle. Each state of the puzzle is a tuple with length equal to the number of disks, ordered by largest disk first. The entry of the tuple is the peg where that disk resides. Since disks on a given peg must go down in size as we go up the peg, this totally describes the state of the puzzle.

    For example `(2,0,0)` means the large disk is on peg 2, the medium disk is on peg 0, and the small disk is on peg 0 (and we know the small disk must be above the medium disk). We encode these tuples as integers with a base equal to the number of pegs, and low-order digits to the right.

    Two vertices are adjacent if we can change the puzzle from one state to the other by moving a single disk. For example, `(2,0,0)` is adjacent to `(2,0,1)` since we can move the small disk off peg 0 and onto (the empty) peg 1. So the solution to a 3-disk puzzle (with at least two pegs) can be expressed by the shortest path between `(0,0,0)` and `(1,1,1)`. For more on this representation of the graph, or its properties, see [AD2010].

    For greatest speed we create graphs with integer vertices, where we encode the tuples as integers with a base equal to the number of pegs, and low-order digits to the right. So for example, in a 3-peg puzzle with 5 disks, the state `(1,2,0,1,1)` is encoded as \(1\ast 3^4 + 2\ast 3^3 + 0\ast 3^2 + 1\ast 3^1 + 1\ast 3^0 = 139\).

    For smaller graphs, the labels that are the tuples are informative, but slow down creation of the graph. Likewise computing layout information also incurs a significant speed penalty. For maximum speed, turn off labels and layout and decode the vertices explicitly as needed. The `sage.rings.integer.Integer.digits()` with the `padsto` option is a quick way to do this, though you may want to reverse the list that is output.

    See also

    - `GeneralizedSierpinskiGraph()`

    PLOTTING:

    The layout computed when `positions = True` will look especially good for the three-peg case, when the graph is known to be planar. Except for two small cases on 4 pegs, the graph is otherwise not planar, and likely there is a better way to layout the vertices.

    EXAMPLES:

    A classic puzzle uses 3 pegs. We solve the 5 disk puzzle using integer labels and report the minimum number of moves required. Note that \(3^5-1\) is the state where all 5 disks are on peg 2.

    Sage

        sage: H = graphs.HanoiTowerGraph(3, 5, labels=False, positions=False)
        sage: H.distance(0, 3^5-1)
        31

    Python

        >>> from sage.all import *
        >>> H = graphs.HanoiTowerGraph(Integer(3), Integer(5), labels=False, positions=False)
        >>> H.distance(Integer(0), Integer(3)**Integer(5)-Integer(1))
        31

    A slightly larger instance.

    Sage

        sage: H = graphs.HanoiTowerGraph(4, 6, labels=False, positions=False)
        sage: H.n_vertices()
        4096
        sage: H.distance(0, 4^6-1)
        17

    [Python]

        >>> from sage.all import *
        >>> H = graphs.HanoiTowerGraph(Integer(4), Integer(6), labels=False, positions=False)
        >>> H.n_vertices()
        4096
        >>> H.distance(Integer(0), Integer(4)**Integer(6)-Integer(1))
        17

    For a small graph, labels and layout information can be useful. Here we explicitly list a solution as a list of states.

    Sage

        sage: H = graphs.HanoiTowerGraph(3, 3, labels=True, positions=True)
        sage: H.shortest_path((0,0,0), (1,1,1))
        [(0, 0, 0), (0, 0, 1), (0, 2, 1), (0, 2, 2), (1, 2, 2), (1, 2, 0), (1, 1, 0), (1, 1, 1)]

    Python

        >>> from sage.all import *
        >>> H = graphs.HanoiTowerGraph(Integer(3), Integer(3), labels=True, positions=True)
        >>> H.shortest_path((Integer(0),Integer(0),Integer(0)), (Integer(1),Integer(1),Integer(1)))
        [(0, 0, 0), (0, 0, 1), (0, 2, 1), (0, 2, 2), (1, 2, 2), (1, 2, 0), (1, 1, 0), (1, 1, 1)]

    Some facts about this graph with \(p\) pegs and \(d\) disks:

    - only automorphisms are the “obvious” ones – renumber the pegs

    - chromatic number is less than or equal to \(p\)

    - independence number is \(p^{d-1}\)

    Sage

        sage: H = graphs.HanoiTowerGraph(3, 4, labels=False, positions=False)
        sage: H.automorphism_group().is_isomorphic(SymmetricGroup(3))                   # needs sage.groups
        True
        sage: H.chromatic_number()
        3
        sage: len(H.independent_set()) == 3^(4-1)
        True

    [Python]

        >>> from sage.all import *
        >>> H = graphs.HanoiTowerGraph(Integer(3), Integer(4), labels=False, positions=False)
        >>> H.automorphism_group().is_isomorphic(SymmetricGroup(Integer(3)))                   # needs sage.groups
        True
        >>> H.chromatic_number()
        3
        >>> len(H.independent_set()) == Integer(3)**(Integer(4)-Integer(1))
        True

    AUTHOR:

    - Rob Beezer, (2009-12-26), with assistance from Su Doree

  static HararyGraph(k, n)

    Return the Harary graph on \(n\) vertices and connectivity \(k\), where \(2 \leq k < n\).

    A \(k\)-connected graph \(G\) on \(n\) vertices requires the minimum degree \(\delta(G)\geq k\), so the minimum number of edges \(G\) should have is \(\lceil kn/2\rceil\). Harary graphs achieve this lower bound, that is, Harary graphs are minimal \(k\)-connected graphs on \(n\) vertices.

    The construction provided uses the method CirculantGraph. For more details, see the book [West2001] or the MathWorld article on Harary graphs.

    EXAMPLES:

    Harary graphs \(H_{k,n}\):

    Sage

        sage: h = graphs.HararyGraph(5,9); h
        Harary graph 5, 9: Graph on 9 vertices
        sage: h.order()
        9
        sage: h.size()
        23
        sage: h.vertex_connectivity()                                                   # needs sage.numerical.mip
        5

    Python

        >>> from sage.all import *
        >>> h = graphs.HararyGraph(Integer(5),Integer(9)); h
        Harary graph 5, 9: Graph on 9 vertices
        >>> h.order()
        9
        >>> h.size()
        23
        >>> h.vertex_connectivity()                                                   # needs sage.numerical.mip
        5

  static HarborthGraph()

    Return the Harborth Graph.

    The Harborth graph has 104 edges and 52 vertices, and is the smallest known example of a 4-regular matchstick graph. For more information, see the Wikipedia article Harborth_graph.

    EXAMPLES:

    Sage

        sage: g = graphs.HarborthGraph(); g
        Harborth Graph: Graph on 52 vertices
        sage: g.is_regular(4)
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.HarborthGraph(); g
        Harborth Graph: Graph on 52 vertices
        >>> g.is_regular(Integer(4))
        True

  static HarriesGraph(embedding=1)

    Return the Harries Graph.

    The Harries graph is a Hamiltonian 3-regular graph on 70 vertices. See the Wikipedia article Harries_graph.

    The default embedding here is to emphasize the graph’s 4 orbits. This graph actually has a funny construction. The following procedure gives an idea of it, though not all the adjacencies are being properly defined.

    1. Take two disjoint copies of a `Petersen graph`. Their vertices will form an orbit of the final graph.

    2. Subdivide all the edges once, to create 15+15=30 new vertices, which together form another orbit.

    3. Create 15 vertices, each of them linked to 2 corresponding vertices of the previous orbit, one in each of the two subdivided Petersen graphs. At the end of this step all vertices from the previous orbit have degree 3, and the only vertices of degree 2 in the graph are those that were just created.

    4. Create 5 vertices connected only to the ones from the previous orbit so that the graph becomes 3-regular.

    INPUT:

    - `embedding` – integer (default: \(1\)); two embeddings are available, and can be selected by setting `embedding` to 1 or 2

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.HarriesGraph()
        sage: g.order()
        70
        sage: g.size()
        105
        sage: g.girth()
        10
        sage: g.diameter()
        6
        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

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.HarriesGraph()
        >>> g.order()
        70
        >>> g.size()
        105
        >>> g.girth()
        10
        >>> g.diameter()
        6
        >>> g.show(figsize=[Integer(10), Integer(10)])          # long time                             # needs sage.plot
        >>> graphs.HarriesGraph(embedding=Integer(2)).show(figsize=[Integer(10), Integer(10)])   # long time, needs sage.plot

  static HarriesWongGraph(embedding=1)

    Return the Harries-Wong Graph.

    See the Wikipedia article Harries-Wong_graph.

    About the default embedding:

    The default embedding is an attempt to emphasize the graph’s 8 (!!!) different orbits. In order to understand this better, one can picture the graph as being built in the following way.

    1. One first creates a 3-dimensional cube (8 vertices, 12 edges), whose vertices define the first orbit of the final graph.

    2. The edges of this graph are subdivided once, to create 12 new vertices which define a second orbit.

    3. The edges of the graph are subdivided once more, to create 24 new vertices giving a third orbit.

    4. 4 vertices are created and made adjacent to the vertices of the second orbit so that they have degree 3. These 4 vertices also define a new orbit.

    5. In order to make the vertices from the third orbit 3-regular (they all miss one edge), one creates a binary tree on 1 + 3 + 6 + 12 vertices. The leaves of this new tree are made adjacent to the 12 vertices of the third orbit, and the graph is now 3-regular. This binary tree contributes 4 new orbits to the Harries-Wong graph.

    INPUT:

    - `embedding` – integer (default: \(1\)); two embeddings are available, and can be selected by setting `embedding` to 1 or 2

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.HarriesWongGraph()
        sage: g.order()
        70
        sage: g.size()
        105
        sage: g.girth()
        10
        sage: g.diameter()
        6
        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

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.HarriesWongGraph()
        >>> g.order()
        70
        >>> g.size()
        105
        >>> g.girth()
        10
        >>> g.diameter()
        6
        >>> orbits = g.automorphism_group(orbits=True)[-Integer(1)]    # long time             # needs sage.groups
        >>> g.show(figsize=[Integer(15), Integer(15)], partition=orbits)        # long time             # needs sage.groups sage.plot

    Alternative embedding:

    Sage

        sage: graphs.HarriesWongGraph(embedding=2).show()       # long time             # needs networkx sage.plot

    [Python]

        >>> from sage.all import *
        >>> graphs.HarriesWongGraph(embedding=Integer(2)).show()       # long time             # needs networkx sage.plot

  static HeawoodGraph()

    Return a Heawood graph.

    The Heawood graph is a cage graph that has 14 nodes. It is a cubic symmetric graph. (See also the Möbius-Kantor graph, `MobiusKantorGraph()`). It is nonplanar and Hamiltonian. It has diameter 3, radius 3, girth 6, and chromatic number 2. It is 4-transitive but not 5-transitive. See the Wikipedia article Heawood_graph.

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the nodes are positioned in a circular layout with the first node appearing at the top, and then continuing counterclockwise.

    EXAMPLES:

    Sage

        sage: H = graphs.HeawoodGraph()
        sage: H
        Heawood graph: Graph on 14 vertices
        sage: H.graph6_string()
        'MhEGHC@AI?_PC@_G_'
        sage: (graphs.HeawoodGraph()).show()    # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> H = graphs.HeawoodGraph()
        >>> H
        Heawood graph: Graph on 14 vertices
        >>> H.graph6_string()
        'MhEGHC@AI?_PC@_G_'
        >>> (graphs.HeawoodGraph()).show()    # long time                             # needs sage.plot

  static HermitianFormsGraph(n, r)

    Return the Hermitian forms graph with the given parameters.

    We build a graph whose vertices are all \(n \times n\) Hermitian matrices over `GF(r^2)`. Two vertices are adjacent if the difference of the two vertices has rank 1.

    This graph is distance-regular with classical parameters \((n, - r, - r - 1, - (- r)^d - 1)\).

    INPUT:

    - `n` – integer

    - `r` – a prime power

    EXAMPLES:

    Sage

        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 (because of the above)
        19683

    Python

        >>> from sage.all import *
        >>> # needs sage.modules sage.rings.finite_rings
        >>> G = graphs.HermitianFormsGraph(Integer(2), Integer(2))
        >>> G.is_distance_regular(True)
        ([5, 4, None], [None, 1, 2])
        >>> G = graphs.HermitianFormsGraph(Integer(3), Integer(3))      # not tested (2 min)
        >>> G.order()                         # not tested (because of the above)
        19683

    REFERENCES:

    See [BCN1989] p. 285 or [VDKT2016] p. 22.

  static HerschelGraph()

    Return the Herschel graph.

    For more information, see the Wikipedia article Herschel_graph.

    EXAMPLES:

    The Herschel graph is named after Alexander Stewart Herschel. It is a planar, bipartite graph with 11 vertices and 18 edges:

    Sage

        sage: G = graphs.HerschelGraph(); G
        Herschel graph: Graph on 11 vertices
        sage: G.is_planar()
        True
        sage: G.is_bipartite()
        True
        sage: G.order()
        11
        sage: G.size()
        18

    Python

        >>> from sage.all import *
        >>> G = graphs.HerschelGraph(); G
        Herschel graph: Graph on 11 vertices
        >>> G.is_planar()
        True
        >>> G.is_bipartite()
        True
        >>> G.order()
        11
        >>> G.size()
        18

    The Herschel graph is a perfect graph with radius 3, diameter 4, and girth 4:

    Sage

        sage: G.is_perfect()
        True
        sage: G.radius()
        3
        sage: G.diameter()
        4
        sage: G.girth()
        4

    [Python]

        >>> from sage.all import *
        >>> G.is_perfect()
        True
        >>> G.radius()
        3
        >>> G.diameter()
        4
        >>> G.girth()
        4

    Its chromatic number is 2 and its automorphism group is isomorphic to the dihedral group \(D_6\):

    Sage

        sage: G.chromatic_number()
        2
        sage: ag = G.automorphism_group()                                               # needs sage.groups
        sage: ag.is_isomorphic(DihedralGroup(6))                                        # needs sage.groups
        True

    Python

        >>> from sage.all import *
        >>> G.chromatic_number()
        2
        >>> ag = G.automorphism_group()                                               # needs sage.groups
        >>> ag.is_isomorphic(DihedralGroup(Integer(6)))                                        # needs sage.groups
        True

  static HexahedralGraph()

    Return a hexahedral graph (with 8 nodes).

    A regular hexahedron is a 6-sided cube. The hexahedral graph corresponds to the connectivity of the vertices of the hexahedron. This graph is equivalent to a 3-cube.

    PLOTTING: The Hexahedral graph should be viewed in 3 dimensions. We choose to use a planar embedding of the graph. We hope to add rotatable, 3-dimensional viewing in the future. In such a case, an argument will be added to select the desired layout.

    EXAMPLES:

    Construct and show a Hexahedral graph:

    Sage

        sage: g = graphs.HexahedralGraph()
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.HexahedralGraph()
        >>> 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

        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):
        ....:     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)
        sage: G.show()                          # long time

    [Python]

        >>> from sage.all import *
        >>> # needs sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     k = graphs.HexahedralGraph()
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

  static HigmanSimsGraph(relabel=True)

    Return the Higman-Sims graph.

    The Higman-Sims graph is a remarkable strongly regular graph of degree 22 on 100 vertices. For example, it can be split into two sets of 50 vertices each, so that each half induces a subgraph isomorphic to the Hoffman-Singleton graph (`HoffmanSingletonGraph()`). This can be done in 352 ways (see Higman-Sims graph by Andries E. Brouwer, accessed 24 October 2009.)

    Its most famous property is that the automorphism group has an index 2 subgroup which is one of the 26 sporadic groups [HS1968].

    The construction used here follows [Haf2004].

    See also the Wikipedia article Higman–Sims_graph.

    INPUT:

    - `relabel` – boolean (default: `True`); whether to relabel the vertices with consecutive integers. If `False` the labels are strings that are three digits long. “xyz” means the vertex is in group \(x\) (zero through three), pentagon or pentagram \(y\) (zero through four), and is vertex \(z\) (zero through four) of that pentagon or pentagram. See [Haf2004] for more.

    OUTPUT: the Higman-Sims graph

    EXAMPLES:

    A split into the first 50 and last 50 vertices will induce two copies of the Hoffman-Singleton graph, and we illustrate another such split, which is obvious based on the construction used:

    Sage

        sage: H = graphs.HigmanSimsGraph()
        sage: A = H.subgraph(range(0,50))
        sage: B = H.subgraph(range(50,100))
        sage: K = graphs.HoffmanSingletonGraph()
        sage: K.is_isomorphic(A) and K.is_isomorphic(B)
        True
        sage: C = H.subgraph(range(25,75))
        sage: D = H.subgraph(list(range(0,25))+list(range(75,100)))
        sage: K.is_isomorphic(C) and K.is_isomorphic(D)
        True

    Python

        >>> from sage.all import *
        >>> H = graphs.HigmanSimsGraph()
        >>> A = H.subgraph(range(Integer(0),Integer(50)))
        >>> B = H.subgraph(range(Integer(50),Integer(100)))
        >>> K = graphs.HoffmanSingletonGraph()
        >>> K.is_isomorphic(A) and K.is_isomorphic(B)
        True
        >>> C = H.subgraph(range(Integer(25),Integer(75)))
        >>> D = H.subgraph(list(range(Integer(0),Integer(25)))+list(range(Integer(75),Integer(100))))
        >>> K.is_isomorphic(C) and K.is_isomorphic(D)
        True

    The automorphism group contains only one nontrivial proper normal subgroup, which is of index 2 and is simple. It is known as the Higman-Sims group:

    Sage

        sage: H = graphs.HigmanSimsGraph()
        sage: G = H.automorphism_group()                                                # needs sage.groups
        sage: g = G.order(); g                                                          # needs sage.groups
        88704000
        sage: K = G.normal_subgroups()[1]                                               # needs sage.groups
        sage: K.is_simple()                                                             # needs sage.groups
        True
        sage: g//K.order()                                                              # needs sage.groups
        2

    [Python]

        >>> from sage.all import *
        >>> H = graphs.HigmanSimsGraph()
        >>> G = H.automorphism_group()                                                # needs sage.groups
        >>> g = G.order(); g                                                          # needs sage.groups
        88704000
        >>> K = G.normal_subgroups()[Integer(1)]                                               # needs sage.groups
        >>> K.is_simple()                                                             # needs sage.groups
        True
        >>> g//K.order()                                                              # needs sage.groups
        2

    AUTHOR:

    > - Rob Beezer (2009-10-24)

  static HoffmanGraph()

    Return the Hoffman Graph.

    See the Wikipedia article Hoffman_graph.

    EXAMPLES:

    Sage

        sage: g = graphs.HoffmanGraph()
        sage: g.is_bipartite()
        True
        sage: g.is_hamiltonian()                # long time                             # needs sage.numerical.mip
        True
        sage: g.radius()
        3
        sage: g.diameter()
        4
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        48

    Python

        >>> from sage.all import *
        >>> g = graphs.HoffmanGraph()
        >>> g.is_bipartite()
        True
        >>> g.is_hamiltonian()                # long time                             # needs sage.numerical.mip
        True
        >>> g.radius()
        3
        >>> g.diameter()
        4
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        48

  static HoffmanSingletonGraph()

    Return the Hoffman-Singleton graph.

    The Hoffman-Singleton graph is the Moore graph of degree 7, diameter 2 and girth 5. The Hoffman-Singleton theorem states that any Moore graph with girth 5 must have degree 2, 3, 7 or 57. The first three respectively are the pentagon, the Petersen graph, and the Hoffman-Singleton graph. The existence of a Moore graph with girth 5 and degree 57 is still open.

    A Moore graph is a graph with diameter \(d\) and girth \(2d + 1\). This implies that the graph is regular, and distance regular.

    For more details, see [GR2001] and the Wikipedia article Hoffman–Singleton_graph.

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. A novel algorithm written by Tom Boothby gives a random layout which is pleasing to the eye.

    EXAMPLES:

    Sage

        sage: HS = graphs.HoffmanSingletonGraph()
        sage: Set(HS.degree())
        {7}
        sage: HS.girth()
        5
        sage: HS.diameter()
        2
        sage: HS.n_vertices()
        50

    Python

        >>> from sage.all import *
        >>> HS = graphs.HoffmanSingletonGraph()
        >>> Set(HS.degree())
        {7}
        >>> HS.girth()
        5
        >>> HS.diameter()
        2
        >>> HS.n_vertices()
        50

    Note that you get a different layout each time you create the graph.

    Sage

        sage: HS.layout()[1]  # random
        (-0.844..., 0.535...)
        sage: HS = graphs.HoffmanSingletonGraph()
        sage: HS.layout()[1]  # random
        (-0.904..., 0.425...)

    [Python]

        >>> from sage.all import *
        >>> HS.layout()[Integer(1)]  # random
        (-0.844..., 0.535...)
        >>> HS = graphs.HoffmanSingletonGraph()
        >>> HS.layout()[Integer(1)]  # random
        (-0.904..., 0.425...)

  static HoltGraph()

    Return the Holt graph (also called the Doyle graph).

    See the Wikipedia article Holt_graph.

    EXAMPLES:

    Sage

        sage: g = graphs.HoltGraph();g
        Holt graph: Graph on 27 vertices
        sage: g.is_regular()
        True
        sage: g.is_vertex_transitive()                                                  # needs sage.groups
        True
        sage: g.chromatic_number()
        3
        sage: g.is_hamiltonian()                # long time                             # needs sage.numerical.mip
        True
        sage: g.radius()
        3
        sage: g.diameter()
        3
        sage: g.girth()
        5
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        54

    Python

        >>> from sage.all import *
        >>> g = graphs.HoltGraph();g
        Holt graph: Graph on 27 vertices
        >>> g.is_regular()
        True
        >>> g.is_vertex_transitive()                                                  # needs sage.groups
        True
        >>> g.chromatic_number()
        3
        >>> g.is_hamiltonian()                # long time                             # needs sage.numerical.mip
        True
        >>> g.radius()
        3
        >>> g.diameter()
        3
        >>> g.girth()
        5
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        54

  static HortonGraph()

    Return the Horton Graph.

    The Horton graph is a cubic 3-connected non-hamiltonian graph. For more information, see the Wikipedia article Horton_graph.

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.HortonGraph()
        sage: g.order()
        96
        sage: g.size()
        144
        sage: g.radius()
        10
        sage: g.diameter()
        10
        sage: g.girth()
        6
        sage: g.automorphism_group().cardinality()
        96
        sage: g.chromatic_number()
        2
        sage: g.is_hamiltonian()                # not tested (veeeery long)             # needs sage.numerical.mip
        False

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.HortonGraph()
        >>> g.order()
        96
        >>> g.size()
        144
        >>> g.radius()
        10
        >>> g.diameter()
        10
        >>> g.girth()
        6
        >>> g.automorphism_group().cardinality()
        96
        >>> g.chromatic_number()
        2
        >>> g.is_hamiltonian()                # not tested (veeeery long)             # needs sage.numerical.mip
        False

  static HouseGraph(immutable=False)

    Return a house graph with 5 nodes.

    A house graph is named for its shape. It is a triangle (roof) over a square (walls).

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the house graph is drawn with the first node in the lower-left corner of the house, the second in the lower-right corner of the house. The third node is in the upper-left corner connecting the roof to the wall, and the fourth is in the upper-right corner connecting the roof to the wall. The fifth node is the top of the roof, connected only to the third and fourth.

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Construct and show a house graph:

    Sage

        sage: g = graphs.HouseGraph()
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.HouseGraph()
        >>> g.show()                          # long time                             # needs sage.plot

  static HouseXGraph(immutable=False)

    Return a house X graph with 5 nodes.

    A house X graph is a house graph with two additional edges. The upper-right corner is connected to the lower-left. And the upper-left corner is connected to the lower-right.

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the house X graph is drawn with the first node in the lower-left corner of the house, the second in the lower-right corner of the house. The third node is in the upper-left corner connecting the roof to the wall, and the fourth is in the upper-right corner connecting the roof to the wall. The fifth node is the top of the roof, connected only to the third and fourth.

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Construct and show a house X graph:

    Sage

        sage: g = graphs.HouseXGraph()
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.HouseXGraph()
        >>> g.show()                          # long time                             # needs sage.plot

  static HyperStarGraph(n, k)

    Return the hyper-star graph \(HS(n, k)\).

    The vertices of the hyper-star graph are the set of binary strings of length \(n\) which contain \(k\) 1s. Two vertices, \(u\) and \(v\), are adjacent only if \(u\) can be obtained from \(v\) by swapping the first bit with a different symbol in another position. For instance, vertex `'011100'` of \(HS(6, 3)\) is adjacent to vertices `'101100'`, `'110100'` and `'111000'`. See [LKOL2002] for more details.

    INPUT:

    - `n` – nonnegative integer; length of the binary strings

    - `k` – nonnegative integer; number of 1s per binary string

    EXAMPLES:

    Sage

        sage: g = graphs.HyperStarGraph(6,3)
        sage: sorted(g.neighbors('011100'))
        ['101100', '110100', '111000']
        sage: g.plot()                          # long time                             # needs sage.plot
        Graphics object consisting of 51 graphics primitives

    Python

        >>> from sage.all import *
        >>> g = graphs.HyperStarGraph(Integer(6),Integer(3))
        >>> sorted(g.neighbors('011100'))
        ['101100', '110100', '111000']
        >>> g.plot()                          # long time                             # needs sage.plot
        Graphics object consisting of 51 graphics primitives

    AUTHORS:

    - Michael Yurko (2009-09-01)

  static IGraph(n, j, k)

    Return an I-graph with \(2n\) nodes.

    The I-Graph family as been proposed in [BCMS1988] as a generalization of the generalized Petersen graphs. The variables \(n\), \(j\), \(k\) are integers such that \(n > 2\) and \(0 < j, k \leq \lfloor (n - 1) / 2 \rfloor\). When \(j = 1\) the resulting graph is isomorphic to the generalized Petersen graph with the same \(n\) and \(k\).

    INPUT:

    - `n` – the number of nodes is \(2 * n\)

    - `j` – integer such that \(0 < j \leq \lfloor (n-1) / 2 \rfloor\) determining how outer vertices are connected

    - `k` – integer such that \(0 < k \leq \lfloor (n-1) / 2 \rfloor\) determining how inner vertices are connected

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the I-graphs are displayed as an inner and outer cycle pair, with the first n nodes drawn on the outer circle. The first (0) node is drawn at the top of the outer-circle, moving counterclockwise after that. The inner circle is drawn with the (n)th node at the top, then counterclockwise as well.

    EXAMPLES:

    When \(j = 1\) the resulting graph will be isomorphic to a generalized Petersen graph:

    Sage

        sage: g = graphs.IGraph(7,1,2)
        sage: g2 = graphs.GeneralizedPetersenGraph(7,2)
        sage: g.is_isomorphic(g2)
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.IGraph(Integer(7),Integer(1),Integer(2))
        >>> g2 = graphs.GeneralizedPetersenGraph(Integer(7),Integer(2))
        >>> g.is_isomorphic(g2)
        True

    The IGraph with parameters \((n, j, k)\) is isomorphic to the IGraph with parameters \((n, k, j)\):

    Sage

        sage: g = graphs.IGraph(7, 2, 3)
        sage: h = graphs.IGraph(7, 3, 2)
        sage: g.is_isomorphic(h)
        True

    [Python]

        >>> from sage.all import *
        >>> g = graphs.IGraph(Integer(7), Integer(2), Integer(3))
        >>> h = graphs.IGraph(Integer(7), Integer(3), Integer(2))
        >>> g.is_isomorphic(h)
        True

  static IcosahedralGraph()

    Return an Icosahedral graph (with 12 nodes).

    The regular icosahedron is a 20-sided triangular polyhedron. The icosahedral graph corresponds to the connectivity of the vertices of the icosahedron. It is dual to the dodecahedral graph. The icosahedron is symmetric, so the spring-layout algorithm will be very effective for display.

    PLOTTING: The Icosahedral graph should be viewed in 3 dimensions. We choose to use a planar embedding of the graph. We hope to add rotatable, 3-dimensional viewing in the future. In such a case, an argument will be added to select the desired layout.

    EXAMPLES:

    Construct and show an Octahedral graph:

    Sage

        sage: g = graphs.IcosahedralGraph()
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.IcosahedralGraph()
        >>> 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

        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):
        ....:     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)
        sage: G.show()                          # long time

    [Python]

        >>> from sage.all import *
        >>> # needs sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     k = graphs.IcosahedralGraph()
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

  static IntersectionGraph(S)

    Return the intersection graph of the family \(S\).

    The intersection graph of a family \(S\) is a graph \(G\) with \(V(G)=S\) such that two elements \(s_1,s_2\in S\) are adjacent in \(G\) if and only if \(s_1\cap s_2\neq \emptyset\).

    INPUT:

    - `S` – list of sets/tuples/iterables

      > Note

      > The elements of \(S\) must be finite, hashable, and the elements of any \(s\in S\) must be hashable too.

    EXAMPLES:

    Sage

        sage: graphs.IntersectionGraph([(1,2,3),(3,4,5),(5,6,7)])
        Intersection Graph: Graph on 3 vertices

    Python

        >>> from sage.all import *
        >>> graphs.IntersectionGraph([(Integer(1),Integer(2),Integer(3)),(Integer(3),Integer(4),Integer(5)),(Integer(5),Integer(6),Integer(7))])
        Intersection Graph: Graph on 3 vertices

  static IntervalGraph(intervals, points_ordered=False)

    Return the graph corresponding to the given intervals.

    An interval graph is built from a list \((a_i,b_i)_{1\leq i \leq n}\) of intervals : to each interval of the list is associated one vertex, two vertices being adjacent if the two corresponding (closed) intervals intersect.

    INPUT:

    - `intervals` – the list of pairs \((a_i,b_i)\) defining the graph

    - `points_ordered` – states whether every interval \((a_i,b_i)\) of \(intervals\) satisfies \(a_i<b_i\). If satisfied then setting `points_ordered` to `True` will speed up the creation of the graph.

    Note

    - The vertices are named 0, 1, 2, and so on. The intervals used to create the graph are saved with the graph and can be recovered using `get_vertex()` or `get_vertices()`.

    EXAMPLES:

    The following line creates the sequence of intervals \((i, i+2)\) for i in \([0, ..., 8]\):

    Sage

        sage: intervals = [(i,i+2) for i in range(9)]

    Python

        >>> from sage.all import *
        >>> intervals = [(i,i+Integer(2)) for i in range(Integer(9))]

    In the corresponding graph

    Sage

        sage: g = graphs.IntervalGraph(intervals)
        sage: g.get_vertex(3)
        (3, 5)
        sage: neigh = g.neighbors(3)
        sage: for v in neigh: print(g.get_vertex(v))
        (1, 3)
        (2, 4)
        (4, 6)
        (5, 7)

    [Python]

        >>> from sage.all import *
        >>> g = graphs.IntervalGraph(intervals)
        >>> g.get_vertex(Integer(3))
        (3, 5)
        >>> neigh = g.neighbors(Integer(3))
        >>> for v in neigh: print(g.get_vertex(v))
        (1, 3)
        (2, 4)
        (4, 6)
        (5, 7)

    The is_interval() method verifies that this graph is an interval graph.

    Sage

        sage: g.is_interval()
        True

    Python

        >>> from sage.all import *
        >>> g.is_interval()
        True

    The intervals in the list need not be distinct.

    Sage

        sage: intervals = [ (1,2), (1,2), (1,2), (2,3), (3,4) ]
        sage: g = graphs.IntervalGraph(intervals,True)
        sage: g.clique_maximum()
        [0, 1, 2, 3]
        sage: g.get_vertices()
        {0: (1, 2), 1: (1, 2), 2: (1, 2), 3: (2, 3), 4: (3, 4)}

    [Python]

        >>> from sage.all import *
        >>> intervals = [ (Integer(1),Integer(2)), (Integer(1),Integer(2)), (Integer(1),Integer(2)), (Integer(2),Integer(3)), (Integer(3),Integer(4)) ]
        >>> g = graphs.IntervalGraph(intervals,True)
        >>> g.clique_maximum()
        [0, 1, 2, 3]
        >>> g.get_vertices()
        {0: (1, 2), 1: (1, 2), 2: (1, 2), 3: (2, 3), 4: (3, 4)}

    The endpoints of the intervals are not ordered we get the same graph (except for the vertex labels).

    Sage

        sage: rev_intervals = [ (2,1), (2,1), (2,1), (3,2), (4,3) ]
        sage: h = graphs.IntervalGraph(rev_intervals,False)
        sage: h.get_vertices()
        {0: (2, 1), 1: (2, 1), 2: (2, 1), 3: (3, 2), 4: (4, 3)}
        sage: g.edges(sort=True) == h.edges(sort=True)
        True

    Python

        >>> from sage.all import *
        >>> rev_intervals = [ (Integer(2),Integer(1)), (Integer(2),Integer(1)), (Integer(2),Integer(1)), (Integer(3),Integer(2)), (Integer(4),Integer(3)) ]
        >>> h = graphs.IntervalGraph(rev_intervals,False)
        >>> h.get_vertices()
        {0: (2, 1), 1: (2, 1), 2: (2, 1), 3: (3, 2), 4: (4, 3)}
        >>> g.edges(sort=True) == h.edges(sort=True)
        True

  static IoninKharaghani765Graph()

    Return a \((765, 192, 48, 48)\)-strongly regular graph.

    Existence of a strongly regular graph with these parameters was claimed in [IK2003]. Implementing the construction in the latter did not work, however. This function implements the following instructions, shared by Yury Ionin and Hadi Kharaghani.

    > Let \(A\) be the affine plane over the field \(GF(3)=\{-1,0,1\}\). Let

    > \[\begin{split}\phi_1(x,y) &= x\\ \phi_2(x,y) &= y\\ \phi_3(x,y) &= x+y\\ \phi_4(x,y) &= x-y\\\end{split}\]

    > For \(i=1,2,3,4\) and \(j\in GF(3)\), let \(L_{i,j}\) be the line in \(A\) defined by \(\phi_i(x,y)=j\). Let \(\mathcal M\) be the set of all 12 lines \(L_{i,j}\), plus the empty set. Let \(\pi\) be the permutation defined on \(\mathcal M\) by \(\pi(L_{i,j}) = L_{i,j+1}\) and \(\pi(\emptyset) = \emptyset\), so that \(\pi\) has three orbits of cardinality 3 and one of cardinality 1.

    > Let \(A=(p_1,...,p_9)\) with \(p_1=(-1,1)\), \(p_2=(-1,0)\), \(p_3=(-1,1)\), \(p_4=(0,-1)\), \(p_5=(0,0)\), \(p_6=(0,1)\), \(p_7=(1,-1)\), \(p_8=(1,0)\), \(p_9=(1,1)\). Note that \(p_i+p_{10-i}=(0,0)\). For any subset \(X\) of \(A\), let \(M(X)\) be the \((0,1)\)-matrix of order 9 whose \((i,j)\)-entry equals 1 if and only if \(p_{10-i}-p_j\in X\). Note that \(M\) is a symmetric matrix.

    > An \(MF\)-tuple is an ordered quintuple \((X_1, X_2, X_3, X_4, X_5)\) of subsets of \(A\), of which one is the empty set and the other four are pairwise non-parallel lines. Such a quintuple generates the following block matrix:

    > \[\begin{split}N(X_1, X_2, X_3, X_4, X_5) = \left( \begin{array}{ccccc} M(X_1) & M(X_2) & M(X_3) & M(X_4) & M(X_5)\\ M(X_2) & M(X_3) & M(X_4) & M(X_5) & M(X_1)\\ M(X_3) & M(X_4) & M(X_5) & M(X_1) & M(X_2)\\ M(X_4) & M(X_5) & M(X_1) & M(X_2) & M(X_3)\\ M(X_5) & M(X_1) & M(X_2) & M(X_3) & M(X_4) \end{array}\right)\end{split}\]

    > Observe that if \((X_1, X_2, X_3, X_4, X_5)\) is an \(MF\)-tuple, then \(N(X_1, X_2, X_3, X_4, X_5)\) is the symmetric incidence matrix of a symmetric \((45, 12, 3)\)-design.

    > Let \(\mathcal F\) be the set of all \(MF\)-tuples and let \(\sigma\) be the following permutation of \(\mathcal F\):

    > \[\begin{split}\sigma(X_1, X_2, X_3, X_4, X_5) & = (X_2, X_3, X_4, X_5, X_1)\\ \pi(X_1, X_2, X_3, X_4, X_5) & = (\pi(X_1), \pi(X_2), \pi(X_3), \pi(X_4), \pi(X_5))\\\end{split}\]

    > Observe that \(\sigma\) and \(\pi\) commute, and generate a (cyclic) group \(G\) of order 15. We will from now on identify \(G\) with the (cyclic) multiplicative group of the field \(GF(16)\) equal to \(\{\omega^0,...,\omega^{14}\}\). Let \(W=[w_{ij}]\) be the following matrix of order 17 over \(GF(16)=\{a_1,...,a_16\}\):

    > \[\begin{split}w_{ij}=\left\{\begin{array}{ll} a_i+a_j & \text{if }1\leq i\leq 16, 1\leq j\leq 16,\\ 1 & \text{if }i=17, j\neq 17,\\ 1 & \text{if }i\neq 17, j= 17,\\ 0 & \text{if }i=j=17 \end{array}\right.\end{split}\]

    > The diagonal entries of \(W\) are equal to 0, each off-diagonal entry can be represented as \(\omega^k\) with \(0\leq k\leq 14\). Matrix \(W\) is a symmetric \(BGW(17,16,15; G)\).

    > Fix an \(MF\)-tuple \((X_1, X_2, X_3, X_4, X_5)\) and let \(S\) be the block matrix obtained from \(W\) by replacing every diagonal entry of \(W\) by the zero matrix of order 45, and every off-diagonal entry \(\omega^k\) by the matrix \(N(\sigma^k(X_1, X_2, X_3, X_4, X_5))\) (through the association of \(\omega^k\) with an element of \(G\)). Then \(S\) is a symmetric incidence matrix of a symmetric \((765, 192, 48)\)-design with zero diagonal, and therefore \(S\) is an adjacency matrix of a strongly regular graph with parameters \((765, 192, 48, 48)\).

    EXAMPLES:

    Sage

        sage: g = graphs.IoninKharaghani765Graph(); g                                   # needs sage.modules sage.rings.finite_rings
        Ionin-Kharaghani: Graph on 765 vertices

    Python

        >>> from sage.all import *
        >>> g = graphs.IoninKharaghani765Graph(); g                                   # needs sage.modules sage.rings.finite_rings
        Ionin-Kharaghani: Graph on 765 vertices

    Todo

    An update to [IK2003] meant to fix the problem encountered became available 2016/02/24, see http://www.cs.uleth.ca/~hadi/research/IoninKharaghani.pdf

  static IvanovIvanovFaradjevGraph(immutable=False)

    Return the IvanovIvanovFaradjev graph.

    The graph is distance-transitive with automorphism group \(3.M_{22}\).

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Sage

        sage: G = graphs.IvanovIvanovFaradjevGraph()            # optional - internet gap_package_atlasrep
        sage: G.is_distance_regular(True)                       # optional - internet gap_package_atlasrep
        ([7, 6, 4, 4, 4, 1, 1, 1, None], [None, 1, 1, 1, 2, 4, 4, 6, 7])

    Python

        >>> from sage.all import *
        >>> G = graphs.IvanovIvanovFaradjevGraph()            # optional - internet gap_package_atlasrep
        >>> G.is_distance_regular(True)                       # optional - internet gap_package_atlasrep
        ([7, 6, 4, 4, 4, 1, 1, 1, None], [None, 1, 1, 1, 2, 4, 4, 6, 7])

    REFERENCES:

    A description and construction of this graph can be found in [BCN1989] p. 369.

  static J2Graph(immutable=False)

    Return the distance-transitive graph with automorphism group \(J_2\).

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Sage

        sage: G = graphs.J2Graph()                              # optional - internet gap_package_atlasrep
        sage: G.is_distance_regular(True)                       # optional - internet gap_package_atlasrep
        ([10, 8, 8, 2, None], [None, 1, 1, 4, 5])

    Python

        >>> from sage.all import *
        >>> G = graphs.J2Graph()                              # optional - internet gap_package_atlasrep
        >>> G.is_distance_regular(True)                       # optional - internet gap_package_atlasrep
        ([10, 8, 8, 2, None], [None, 1, 1, 4, 5])

    REFERENCES:

    A description and construction of this graph can be found in [BCN1989] p. 408.

  static JankoKharaghaniGraph(v)

    Return a \((936, 375, 150, 150)\)-srg or a \((1800, 1029, 588, 588)\)-srg.

    This functions returns a strongly regular graph for the two sets of parameters shown to be realizable in [JK2002]. The paper also uses a construction from [GM1987].

    INPUT:

    - `v` – integer; one of 936 or 1800

    EXAMPLES:

    Sage

        sage: g = graphs.JankoKharaghaniGraph(936)      # long time                     # needs sage.libs.pari
        sage: g.is_strongly_regular(parameters=True)    # long time                     # needs sage.libs.pari
        (936, 375, 150, 150)

        sage: g = graphs.JankoKharaghaniGraph(1800)     # not tested (30s)
        sage: g.is_strongly_regular(parameters=True)    # not tested (30s)
        (1800, 1029, 588, 588)

    Python

        >>> from sage.all import *
        >>> g = graphs.JankoKharaghaniGraph(Integer(936))      # long time                     # needs sage.libs.pari
        >>> g.is_strongly_regular(parameters=True)    # long time                     # needs sage.libs.pari
        (936, 375, 150, 150)

        >>> g = graphs.JankoKharaghaniGraph(Integer(1800))     # not tested (30s)
        >>> g.is_strongly_regular(parameters=True)    # not tested (30s)
        (1800, 1029, 588, 588)

  static JankoKharaghaniTonchevGraph()

    Return a \((324,153,72,72)\)-strongly regular graph from [JKT2001].

    Build the graph using the description given in [JKT2001], taking sets B1 and B163 in the text as adjacencies of vertices 1 and 163, respectively, and taking the edge orbits of the group \(G\) provided.

    EXAMPLES:

    Sage

        sage: Gamma = graphs.JankoKharaghaniTonchevGraph()      # long time             # needs sage.libs.gap
        sage: Gamma.is_strongly_regular(parameters=True)        # long time             # needs sage.libs.gap
        (324, 153, 72, 72)

    Python

        >>> from sage.all import *
        >>> Gamma = graphs.JankoKharaghaniTonchevGraph()      # long time             # needs sage.libs.gap
        >>> Gamma.is_strongly_regular(parameters=True)        # long time             # needs sage.libs.gap
        (324, 153, 72, 72)

  static JohnsonGraph(n, k)

    Return the Johnson graph with parameters \(n, k\).

    Johnson graphs are a special class of undirected graphs defined from systems of sets. The vertices of the Johnson graph \(J(n,k)\) are the \(k\)-element subsets of an \(n\)-element set; two vertices are adjacent when they meet in a \((k-1)\)-element set. See the Wikipedia article Johnson_graph for more information.

    EXAMPLES:

    The Johnson graph is a Hamiltonian graph:

    Sage

        sage: g = graphs.JohnsonGraph(7, 3)
        sage: g.is_hamiltonian()                                                        # needs sage.numerical.mip
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.JohnsonGraph(Integer(7), Integer(3))
        >>> g.is_hamiltonian()                                                        # needs sage.numerical.mip
        True

    Every Johnson graph is vertex transitive:

    Sage

        sage: g = graphs.JohnsonGraph(6, 4)
        sage: g.is_vertex_transitive()                                                  # needs sage.groups
        True

    [Python]

        >>> from sage.all import *
        >>> g = graphs.JohnsonGraph(Integer(6), Integer(4))
        >>> g.is_vertex_transitive()                                                  # needs sage.groups
        True

    The complement of the Johnson graph \(J(n,2)\) is isomorphic to the Kneser Graph \(K(n,2)\). In particular the complement of \(J(5,2)\) is isomorphic to the Petersen graph.:

    Sage

        sage: g = graphs.JohnsonGraph(5,2)
        sage: g.complement().is_isomorphic(graphs.PetersenGraph())
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.JohnsonGraph(Integer(5),Integer(2))
        >>> g.complement().is_isomorphic(graphs.PetersenGraph())
        True

  static KingGraph(dim_list, radius=None, relabel=False)

    Return the \(d\)-dimensional King Graph with prescribed dimensions.

    The 2-dimensional King Graph of parameters \(n\) and \(m\) is a graph with \(nm\) vertices in which each vertex represents a square in an \(n \times m\) chessboard, and each edge corresponds to a legal move by a king.

    The d-dimensional King Graph with \(d >= 2\) has for vertex set the cells of a d-dimensional grid with prescribed dimensions, and each edge corresponds to a legal move by a king in either one or two dimensions.

    All 2-dimensional King Graphs are Hamiltonian, biconnected, and have chromatic number 4 as soon as both dimensions are larger or equal to 2.

    INPUT:

    - `dim_list` – iterable (list, set, dict); provides the dimensions \(n_1, n_2, \ldots, n_d\), with \(n_i \geq 1\), of the chessboard

    - `radius` – integer (default: `None`); by setting the radius to a positive integer, one may increase the power of the king to at least `radius` steps. When the radius equals the higher size of the dimensions, the resulting graph is a Queen Graph.

    - `relabel` – boolean (default: `False`); indicates whether the vertices must be relabeled as integers

    EXAMPLES:

    The \((2,2)\)-King Graph is isomorphic to the complete graph on 4 vertices:

    Sage

        sage: G = graphs.QueenGraph( [2, 2] )
        sage: G.is_isomorphic( graphs.CompleteGraph(4) )
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.QueenGraph( [Integer(2), Integer(2)] )
        >>> G.is_isomorphic( graphs.CompleteGraph(Integer(4)) )
        True

    The King Graph with large enough radius is isomorphic to a Queen Graph:

    Sage

        sage: G = graphs.KingGraph( [5, 4], radius=5 )
        sage: H = graphs.QueenGraph( [4, 5] )
        sage: G.is_isomorphic( H )
        True

    [Python]

        >>> from sage.all import *
        >>> G = graphs.KingGraph( [Integer(5), Integer(4)], radius=Integer(5) )
        >>> H = graphs.QueenGraph( [Integer(4), Integer(5)] )
        >>> G.is_isomorphic( H )
        True

    Also `True` in higher dimensions:

    Sage

        sage: G = graphs.KingGraph( [2, 5, 4], radius=5 )
        sage: H = graphs.QueenGraph( [4, 5, 2] )
        sage: G.is_isomorphic( H )
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.KingGraph( [Integer(2), Integer(5), Integer(4)], radius=Integer(5) )
        >>> H = graphs.QueenGraph( [Integer(4), Integer(5), Integer(2)] )
        >>> G.is_isomorphic( H )
        True

  static KittellGraph()

    Return the Kittell Graph.

    For more information, see the Wolfram page about the Kittel Graph.

    EXAMPLES:

    Sage

        sage: g = graphs.KittellGraph()
        sage: g.order()
        23
        sage: g.size()
        63
        sage: g.radius()
        3
        sage: g.diameter()
        4
        sage: g.girth()
        3
        sage: g.chromatic_number()
        4

    Python

        >>> from sage.all import *
        >>> g = graphs.KittellGraph()
        >>> g.order()
        23
        >>> g.size()
        63
        >>> g.radius()
        3
        >>> g.diameter()
        4
        >>> g.girth()
        3
        >>> g.chromatic_number()
        4

  static Klein3RegularGraph()

    Return the Klein 3-regular graph.

    The cubic Klein graph has 56 vertices and can be embedded on a surface of genus 3. It is the dual of `Klein7RegularGraph()`. For more information, see the Wikipedia article Klein_graphs.

    EXAMPLES:

    Sage

        sage: g = graphs.Klein3RegularGraph(); g
        Klein 3-regular Graph: Graph on 56 vertices
        sage: g.order(), g.size()
        (56, 84)
        sage: g.girth()
        7
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        336
        sage: g.chromatic_number()
        3

    Python

        >>> from sage.all import *
        >>> g = graphs.Klein3RegularGraph(); g
        Klein 3-regular Graph: Graph on 56 vertices
        >>> g.order(), g.size()
        (56, 84)
        >>> g.girth()
        7
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        336
        >>> g.chromatic_number()
        3

  static Klein7RegularGraph()

    Return the Klein 7-regular graph.

    The 7-valent Klein graph has 24 vertices and can be embedded on a surface of genus 3. It is the dual of `Klein3RegularGraph()`. For more information, see the Wikipedia article Klein_graphs.

    EXAMPLES:

    Sage

        sage: g = graphs.Klein7RegularGraph(); g
        Klein 7-regular Graph: Graph on 24 vertices
        sage: g.order(), g.size()
        (24, 84)
        sage: g.girth()
        3
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        336
        sage: g.chromatic_number()
        4

    Python

        >>> from sage.all import *
        >>> g = graphs.Klein7RegularGraph(); g
        Klein 7-regular Graph: Graph on 24 vertices
        >>> g.order(), g.size()
        (24, 84)
        >>> g.girth()
        3
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        336
        >>> g.chromatic_number()
        4

  static KneserGraph(n, k)

    Return the Kneser Graph with parameters \(n, k\).

    The Kneser Graph with parameters \(n,k\) is the graph whose vertices are the \(k\)-subsets of \([0,1,\dots,n-1]\), and such that two vertices are adjacent if their corresponding sets are disjoint.

    For example, the Petersen Graph can be defined as the Kneser Graph with parameters \(5,2\).

    EXAMPLES:

    Sage

        sage: KG = graphs.KneserGraph(5,2)
        sage: sorted(KG.vertex_iterator(), key=str)
        [{1, 2}, {1, 3}, {1, 4}, {1, 5}, {2, 3}, {2, 4}, {2, 5},
         {3, 4}, {3, 5}, {4, 5}]
        sage: P = graphs.PetersenGraph()
        sage: P.is_isomorphic(KG)
        True

    Python

        >>> from sage.all import *
        >>> KG = graphs.KneserGraph(Integer(5),Integer(2))
        >>> sorted(KG.vertex_iterator(), key=str)
        [{1, 2}, {1, 3}, {1, 4}, {1, 5}, {2, 3}, {2, 4}, {2, 5},
         {3, 4}, {3, 5}, {4, 5}]
        >>> P = graphs.PetersenGraph()
        >>> P.is_isomorphic(KG)
        True

  static KnightGraph(dim_list, one=1, two=2, relabel=False)

    Return the d-dimensional Knight Graph with prescribed dimensions.

    The 2-dimensional Knight Graph of parameters \(n\) and \(m\) is a graph with \(nm\) vertices in which each vertex represents a square in an \(n \times m\) chessboard, and each edge corresponds to a legal move by a knight.

    The d-dimensional Knight Graph with \(d >= 2\) has for vertex set the cells of a d-dimensional grid with prescribed dimensions, and each edge corresponds to a legal move by a knight in any pairs of dimensions.

    The \((n,n)\)-Knight Graph is Hamiltonian for even \(n > 4\).

    INPUT:

    - `dim_list` – iterable (list, set, dict); provides the dimensions \(n_1, n_2, \ldots, n_d\), with \(n_i \geq 1\), of the chessboard

    - `one` – integer (default: \(1\)); indicates the number of steps in the first dimension

    - `two` – integer (default: \(2\)); indicates the number of steps in the second dimension

    - `relabel` – boolean (default: `False`); indicates whether the vertices must be relabeled as integers

    EXAMPLES:

    The \((3,3)\)-Knight Graph has an isolated vertex:

    Sage

        sage: G = graphs.KnightGraph( [3, 3] )
        sage: G.degree( (1,1) )
        0

    Python

        >>> from sage.all import *
        >>> G = graphs.KnightGraph( [Integer(3), Integer(3)] )
        >>> G.degree( (Integer(1),Integer(1)) )
        0

    The \((3,3)\)-Knight Graph minus vertex (1,1) is a cycle of order 8:

    Sage

        sage: G = graphs.KnightGraph( [3, 3] )
        sage: G.delete_vertex( (1,1) )
        sage: G.is_isomorphic( graphs.CycleGraph(8) )
        True

    [Python]

        >>> from sage.all import *
        >>> G = graphs.KnightGraph( [Integer(3), Integer(3)] )
        >>> G.delete_vertex( (Integer(1),Integer(1)) )
        >>> G.is_isomorphic( graphs.CycleGraph(Integer(8)) )
        True

    The \((6,6)\)-Knight Graph is Hamiltonian:

    Sage

        sage: G = graphs.KnightGraph( [6, 6] )
        sage: G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.KnightGraph( [Integer(6), Integer(6)] )
        >>> G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True

  static KrackhardtKiteGraph()

    Return a Krackhardt kite graph with 10 nodes.

    The Krackhardt kite graph was originally developed by David Krackhardt for the purpose of studying social networks (see [Kre2002] and the Wikipedia article Krackhardt_kite_graph). It is used to show the distinction between degree centrality, betweenness centrality, and closeness centrality. For more information read the plotting section below in conjunction with the example.

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the graph is drawn left to right, in top to bottom row sequence of [2, 3, 2, 1, 1, 1] nodes on each row. This places the fourth node (3) in the center of the kite, with the highest degree. But the fourth node only connects nodes that are otherwise connected, or those in its clique (i.e.: Degree Centrality). The eighth (7) node is where the kite meets the tail. It has degree = 3, less than the average, but is the only connection between the kite and tail (i.e.: Betweenness Centrality). The sixth and seventh nodes (5 and 6) are drawn in the third row and have degree = 5. These nodes have the shortest path to all other nodes in the graph (i.e.: Closeness Centrality). Please execute the example for visualization.

    EXAMPLES:

    Construct and show a Krackhardt kite graph

    Sage

        sage: g = graphs.KrackhardtKiteGraph()
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.KrackhardtKiteGraph()
        >>> g.show()                          # long time                             # needs sage.plot

  static LCFGraph(n, shift_list, repeats)

    Return the cubic graph specified in LCF notation.

    LCF (Lederberg-Coxeter-Fruchte) notation is a concise way of describing cubic Hamiltonian graphs. The way a graph is constructed is as follows. Since there is a Hamiltonian cycle, we first create a cycle on \(n\) nodes. The variable `shift_list` = \([s_0, s_1, ..., s_{k-1}]\) describes edges to be created by the following scheme: for each \(i \in \{0, 1, \dots, k-1\}\), connect vertex \(i\) to vertex \((i + s_i) \pmod{n}\). Then, `repeats` specifies the number of times to repeat this process, where on the \(j\)-th repeat we connect vertex \((i + j k) \pmod{n}\) to vertex \((i + j k + s_i) \pmod{n}\).

    For more details, see the Wikipedia article LCF_notation and [Fru1977], [Gru2003] pp. 357-365, and [Led1965].

    INPUT:

    - `n` – the number of nodes

    - `shift_list` – a list of integer shifts mod \(n\)

    - `repeats` – the number of times to repeat the process

    EXAMPLES:

    Sage

        sage: G = graphs.LCFGraph(4, [2,-2], 2)                                         # needs networkx
        sage: G.is_isomorphic(graphs.TetrahedralGraph())                                # needs networkx
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.LCFGraph(Integer(4), [Integer(2),-Integer(2)], Integer(2))                                         # needs networkx
        >>> G.is_isomorphic(graphs.TetrahedralGraph())                                # needs networkx
        True

    Sage

        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

    [Python]

        >>> from sage.all import *
        >>> G = graphs.LCFGraph(Integer(20), [Integer(10),Integer(7),Integer(4),-Integer(4),-Integer(7),Integer(10),-Integer(4),Integer(7),-Integer(7),Integer(4)], Integer(2))                   # needs networkx
        >>> G.is_isomorphic(graphs.DodecahedralGraph())                               # needs networkx
        True

    Sage

        sage: G = graphs.LCFGraph(14, [5,-5], 7)                                        # needs networkx
        sage: G.is_isomorphic(graphs.HeawoodGraph())                                    # needs networkx
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.LCFGraph(Integer(14), [Integer(5),-Integer(5)], Integer(7))                                        # needs networkx
        >>> G.is_isomorphic(graphs.HeawoodGraph())                                    # needs networkx
        True

    The largest cubic nonplanar graph of diameter three:

    Sage

        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()
        [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
        sage: G.diameter()
        3
        sage: G.show()                          # long time                             # needs sage.plot

    [Python]

        >>> from sage.all import *
        >>> # needs networkx
        >>> G = graphs.LCFGraph(Integer(20), [-Integer(10),-Integer(7),-Integer(5),Integer(4),Integer(7),-Integer(10),-Integer(7),-Integer(4),Integer(5),Integer(7),
        ...                          -Integer(10),-Integer(7),Integer(6),-Integer(5),Integer(7),-Integer(10),-Integer(7),Integer(5),-Integer(6),Integer(7)], Integer(1))
        >>> G.degree()
        [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
        >>> G.diameter()
        3
        >>> G.show()                          # long time                             # needs sage.plot

    PLOTTING: LCF Graphs are plotted as an \(n\)-cycle with edges in the middle, as described above.

  static LadderGraph(n, immutable=False)

    Return a ladder graph with \(2 * n\) nodes.

    A ladder graph is a basic structure that is typically displayed as a ladder, i.e.: two parallel path graphs connected at each corresponding node pair.

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each ladder graph will be displayed horizontally, with the first n nodes displayed left to right on the top horizontal line.

    INPUT:

    - `n` – a nonnegative integer; number of nodes is \(2n\)

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Construct and show a ladder graph with 14 nodes:

    Sage

        sage: g = graphs.LadderGraph(7)
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.LadderGraph(Integer(7))
        >>> g.show()                          # long time                             # needs sage.plot

    Create several ladder graphs in a Sage graphics array:

    Sage

        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):
        ....:     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)
        sage: G.show()                          # long time

    [Python]

        >>> from sage.all import *
        >>> # needs sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     k = graphs.LadderGraph(i+Integer(2))
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

  static LargeWittGraph(immutable=False)

    Return the large Witt graph.

    This is a distance-regular graph with intersection array \([30,28,24;1,3,15]\).

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Sage

        sage: g = graphs.LargeWittGraph()                                               # needs sage.libs.pari sage.modules
        sage: g.is_distance_regular(True)                                               # needs sage.libs.pari sage.modules
        ([30, 28, 24, None], [None, 1, 3, 15])

    Python

        >>> from sage.all import *
        >>> g = graphs.LargeWittGraph()                                               # needs sage.libs.pari sage.modules
        >>> g.is_distance_regular(True)                                               # needs sage.libs.pari sage.modules
        ([30, 28, 24, None], [None, 1, 3, 15])

    REFERENCES:

    A description of this graph can be found in [BCN1989] p. 366. This construction is taken from http://mathworld.wolfram.com/LargeWittGraph.html

  static LeonardGraph()

    Return the Leonard graph.

    The graph is distance-regular with intersection array \([12, 11, 10, 7; 1, 2, 5, 12]\).

    EXAMPLES:

    Sage

        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])

    Python

        >>> from sage.all import *
        >>> G = graphs.LeonardGraph()                                                # needs sage.combinat sage.modules
        >>> G.is_distance_regular(True)                                              # needs sage.combinat sage.modules
        ([12, 11, 10, 7, None], [None, 1, 2, 5, 12])

    REFERENCES:

    For a description of this graph see [BCN1989] p. 371.

  static LivingstoneGraph()

    Return the Livingstone Graph.

    The Livingstone graph is a distance-transitive graph on 266 vertices whose automorphism group is the `J1 group`. For more information, see the Wikipedia article Livingstone_graph.

    EXAMPLES:

    Sage

        sage: # optional - internet
        sage: g = graphs.LivingstoneGraph()
        sage: g.order()
        266
        sage: g.size()
        1463
        sage: g.girth()
        5
        sage: g.is_vertex_transitive()
        True
        sage: g.is_distance_regular()
        True

    Python

        >>> from sage.all import *
        >>> # optional - internet
        >>> g = graphs.LivingstoneGraph()
        >>> g.order()
        266
        >>> g.size()
        1463
        >>> g.girth()
        5
        >>> g.is_vertex_transitive()
        True
        >>> g.is_distance_regular()
        True

  static LjubljanaGraph(embedding=1)

    Return the Ljubljana Graph.

    The Ljubljana graph is a bipartite 3-regular graph on 112 vertices and 168 edges. It is not vertex-transitive as it has two orbits which are also independent sets of size 56. See the Wikipedia article Ljubljana_graph.

    The default embedding is obtained from the Heawood graph.

    INPUT:

    - `embedding` – integer (default: \(1\)); two embeddings are available, and can be selected by setting `embedding` to 1 or 2

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.LjubljanaGraph()
        sage: g.order()
        112
        sage: g.size()
        168
        sage: g.girth()
        10
        sage: g.diameter()
        8
        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

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.LjubljanaGraph()
        >>> g.order()
        112
        >>> g.size()
        168
        >>> g.girth()
        10
        >>> g.diameter()
        8
        >>> g.show(figsize=[Integer(10), Integer(10)])          # long time                             # needs sage.plot
        >>> graphs.LjubljanaGraph(embedding=Integer(2)).show(figsize=[Integer(10), Integer(10)])         # long time, needs sage.plot

  static LocalMcLaughlinGraph()

    Return the local McLaughlin graph.

    The local McLaughlin graph is a strongly regular graph with parameters \((162,56,10,24)\). It can be obtained from `McLaughlinGraph()` by considering the stabilizer of a point: one of its orbits has cardinality 162.

    EXAMPLES:

    Sage

        sage: g = graphs.LocalMcLaughlinGraph(); g      # long time, optional - gap_package_design
        Local McLaughlin Graph: Graph on 162 vertices
        sage: g.is_strongly_regular(parameters=True)    # long time, optional - gap_package_design
        (162, 56, 10, 24)

    Python

        >>> from sage.all import *
        >>> g = graphs.LocalMcLaughlinGraph(); g      # long time, optional - gap_package_design
        Local McLaughlin Graph: Graph on 162 vertices
        >>> g.is_strongly_regular(parameters=True)    # long time, optional - gap_package_design
        (162, 56, 10, 24)

  static LollipopGraph(n1, n2)

    Return a lollipop graph with \(n_1 + n_2\) nodes.

    A lollipop graph is a path graph (order \(n_2\)) connected to a complete graph (order \(n_1\)). (A barbell graph minus one of the bells).

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the complete graph will be drawn in the lower-left corner with the \(n_1\)-th node at a 45 degree angle above the right horizontal center of the complete graph, leading directly into the path graph.

    EXAMPLES:

    Construct and show a lollipop graph Candy = 13, Stick = 4:

    Sage

        sage: g = graphs.LollipopGraph(13,4); g
        Lollipop graph: Graph on 17 vertices
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.LollipopGraph(Integer(13),Integer(4)); g
        Lollipop graph: Graph on 17 vertices
        >>> g.show()                          # long time                             # needs sage.plot

  static M22Graph()

    Return the M22 graph.

    The \(M_{22}\) graph is the unique strongly regular graph with parameters \(v = 77, k = 16, \lambda = 0, \mu = 4\).

    For more information on the \(M_{22}\) graph, see https://www.win.tue.nl/~aeb/graphs/M22.html.

    EXAMPLES:

    Sage

        sage: # needs sage.groups
        sage: g = graphs.M22Graph()
        sage: g.order()
        77
        sage: g.size()
        616
        sage: g.is_strongly_regular(parameters=True)
        (77, 16, 0, 4)

    Python

        >>> from sage.all import *
        >>> # needs sage.groups
        >>> g = graphs.M22Graph()
        >>> g.order()
        77
        >>> g.size()
        616
        >>> g.is_strongly_regular(parameters=True)
        (77, 16, 0, 4)

  static MarkstroemGraph()

    Return the Markström Graph.

    The Markström Graph is a cubic planar graph with no cycles of length 4 nor 8, but containing cycles of length 16. For more information, see the Wolfram page about the Markström Graph.

    EXAMPLES:

    Sage

        sage: g = graphs.MarkstroemGraph()
        sage: g.order()
        24
        sage: g.size()
        36
        sage: g.is_planar()
        True
        sage: g.is_regular(3)
        True
        sage: g.subgraph_search(graphs.CycleGraph(4)) is None                           # needs sage.modules
        True
        sage: g.subgraph_search(graphs.CycleGraph(8)) is None                           # needs sage.modules
        True
        sage: g.subgraph_search(graphs.CycleGraph(16))                                  # needs sage.modules
        Subgraph of (Markstroem Graph): Graph on 16 vertices

    Python

        >>> from sage.all import *
        >>> g = graphs.MarkstroemGraph()
        >>> g.order()
        24
        >>> g.size()
        36
        >>> g.is_planar()
        True
        >>> g.is_regular(Integer(3))
        True
        >>> g.subgraph_search(graphs.CycleGraph(Integer(4))) is None                           # needs sage.modules
        True
        >>> g.subgraph_search(graphs.CycleGraph(Integer(8))) is None                           # needs sage.modules
        True
        >>> g.subgraph_search(graphs.CycleGraph(Integer(16)))                                  # needs sage.modules
        Subgraph of (Markstroem Graph): Graph on 16 vertices

  static MathonPseudocyclicMergingGraph(M, t)

    Mathon’s merging of classes in a pseudo-cyclic 3-class association scheme.

    Construct strongly regular graphs from p.97 of [BL1984].

    INPUT:

    - `M` – the list of matrices in a pseudo-cyclic 3-class association scheme; the identity matrix must be the first entry

    - `t` – integer; the number of the graph, from 0 to 2

    See also

    - `is_muzychuk_S6()`

  static MathonPseudocyclicStronglyRegularGraph(t, G=None, L=None)

    Return a strongly regular graph on \((4t+1)(4t-1)^2\) vertices from [Mat1978].

    Let \(4t-1\) be a prime power, and \(4t+1\) be such that there exists a strongly regular graph \(G\) with parameters \((4t+1,2t,t-1,t)\). In particular, \(4t+1\) must be a sum of two squares [Mat1978]. With this input, Mathon [Mat1978] gives a construction of a strongly regular graph with parameters \((4 \mu + 1, 2 \mu, \mu-1, \mu)\), where \(\mu = t(4t(4t-1)-1)\). The construction is optionally parametrised by an a skew-symmetric Latin square of order \(4t+1\), with entries in \(-2t,...,-1,0,1,...,2t\).

    Our implementation follows a description given in [ST1981].

    INPUT:

    - `t` – positive integer

    - `G` – if `None` (default), try to construct the necessary graph with parameters \((4t+1,2t,t-1,t)\), otherwise use the user-supplied one, with vertices labelled from \(0\) to \(4t\).

    - `L` – if `None` (default), construct a necessary skew Latin square, otherwise use the user-supplied one. Here non-isomorphic Latin squares – one constructed from \(Z/9Z\), and the other from \((Z/3Z)^2\) – lead to non-isomorphic graphs.

    See also

    - `is_mathon_PC_srg()`

    EXAMPLES:

    Using default `G` and `L`.

    Sage

        sage: from sage.graphs.generators.families import MathonPseudocyclicStronglyRegularGraph
        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)                                    # needs sage.modules sage.rings.finite_rings
        (45, 22, 10, 11)

    Python

        >>> from sage.all import *
        >>> from sage.graphs.generators.families import MathonPseudocyclicStronglyRegularGraph
        >>> G = MathonPseudocyclicStronglyRegularGraph(Integer(1)); G                          # needs sage.modules sage.rings.finite_rings
        Mathon's PC SRG on 45 vertices: Graph on 45 vertices
        >>> 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`). The entries of L can’t be tested directly because there’s some unpredictability in the way that GAP chooses a representative in `NormalSubgroups()`, the function that underlies our own `normal_subgroups()` method:

    Sage

        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),
        ....:          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))
        sage: G.relabel(range(9))
        sage: G3x3 = graphs.MathonPseudocyclicStronglyRegularGraph(2, G=G, L=L)
        sage: G3x3.is_strongly_regular(parameters=True)
        (441, 220, 109, 110)
        sage: G3x3.automorphism_group(algorithm='bliss').order()  # optional - bliss
        27
        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
        9

    [Python]

        >>> from sage.all import *
        >>> # needs sage.groups sage.libs.gap sage.rings.finite_rings
        >>> G = graphs.PaleyGraph(Integer(9))
        >>> a = G.automorphism_group(partition=[sorted(G)])
        >>> it = (x for x in a.normal_subgroups() if x.order() == Integer(9))
        >>> subg = next(iter(it))
        >>> r = [matrix(libgap.PermutationMat(libgap(z), Integer(9)).sage())
        ...      for z in subg]
        >>> ff = list(map(lambda y: (y[Integer(0)]-Integer(1),y[Integer(1)]-Integer(1)),
        ...          Permutation(map(lambda x: Integer(1)+r.index(x**-Integer(1)), r)).cycle_tuples()[Integer(1):]))
        >>> L = sum(i*(r[a]-r[b]) for i,(a,b) in zip(range(Integer(1),len(ff)+Integer(1)), ff))
        >>> G.relabel(range(Integer(9)))
        >>> G3x3 = graphs.MathonPseudocyclicStronglyRegularGraph(Integer(2), G=G, L=L)
        >>> G3x3.is_strongly_regular(parameters=True)
        (441, 220, 109, 110)
        >>> G3x3.automorphism_group(algorithm='bliss').order()  # optional - bliss
        27
        >>> G9 = graphs.MathonPseudocyclicStronglyRegularGraph(Integer(2))
        >>> G9.is_strongly_regular(parameters=True)
        (441, 220, 109, 110)
        >>> G9.automorphism_group(algorithm='bliss').order()  # optional - bliss
        9

  static MathonStronglyRegularGraph(t)

    Return one of Mathon’s graphs on 784 vertices.

    INPUT:

    - `t` – integer; the number of the graph, from 0 to 2

    EXAMPLES:

    Sage

        sage: # long time, needs sage.libs.gap
        sage: from sage.graphs.generators.smallgraphs import MathonStronglyRegularGraph
        sage: G = MathonStronglyRegularGraph(0)
        sage: G.is_strongly_regular(parameters=True)
        (784, 243, 82, 72)

    Python

        >>> from sage.all import *
        >>> # long time, needs sage.libs.gap
        >>> from sage.graphs.generators.smallgraphs import MathonStronglyRegularGraph
        >>> G = MathonStronglyRegularGraph(Integer(0))
        >>> G.is_strongly_regular(parameters=True)
        (784, 243, 82, 72)

  static McGeeGraph(embedding=2)

    Return the McGee Graph.

    See the Wikipedia article McGee_graph.

    INPUT:

    - `embedding` – integer (default: \(2\)); two embeddings are available, and can be selected by setting `embedding` to 1 or 2

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.McGeeGraph()
        sage: g.order()
        24
        sage: g.size()
        36
        sage: g.girth()
        7
        sage: g.diameter()
        4
        sage: g.show()                                                                  # needs sage.plot
        sage: graphs.McGeeGraph(embedding=1).show()     # long time                     # needs sage.plot

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.McGeeGraph()
        >>> g.order()
        24
        >>> g.size()
        36
        >>> g.girth()
        7
        >>> g.diameter()
        4
        >>> g.show()                                                                  # needs sage.plot
        >>> graphs.McGeeGraph(embedding=Integer(1)).show()     # long time                     # needs sage.plot

  static McLaughlinGraph()

    Return the McLaughlin Graph.

    The McLaughlin Graph is the unique strongly regular graph of parameters \((275, 112, 30, 56)\).

    For more information on the McLaughlin Graph, see its web page on Andries Brouwer’s website which gives the definition that this method implements.

    Note

    To create this graph you must have the gap_packages spkg installed.

    EXAMPLES:

    Sage

        sage: g = graphs.McLaughlinGraph()              # optional - gap_package_design
        sage: g.is_strongly_regular(parameters=True)    # optional - gap_package_design
        (275, 112, 30, 56)
        sage: set(g.spectrum()) == {112, 2, -28}        # optional - gap_package_design
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.McLaughlinGraph()              # optional - gap_package_design
        >>> g.is_strongly_regular(parameters=True)    # optional - gap_package_design
        (275, 112, 30, 56)
        >>> set(g.spectrum()) == {Integer(112), Integer(2), -Integer(28)}        # optional - gap_package_design
        True

  static MeredithGraph()

    Return the Meredith Graph.

    The Meredith Graph is a 4-regular 4-connected non-hamiltonian graph. For more information on the Meredith Graph, see the Wikipedia article Meredith_graph.

    EXAMPLES:

    Sage

        sage: g = graphs.MeredithGraph()
        sage: g.is_regular(4)
        True
        sage: g.order()
        70
        sage: g.size()
        140
        sage: g.radius()
        7
        sage: g.diameter()
        8
        sage: g.girth()
        4
        sage: g.chromatic_number()
        3
        sage: g.is_hamiltonian()                # long time                             # needs sage.numerical.mip
        False

    Python

        >>> from sage.all import *
        >>> g = graphs.MeredithGraph()
        >>> g.is_regular(Integer(4))
        True
        >>> g.order()
        70
        >>> g.size()
        140
        >>> g.radius()
        7
        >>> g.diameter()
        8
        >>> g.girth()
        4
        >>> g.chromatic_number()
        3
        >>> g.is_hamiltonian()                # long time                             # needs sage.numerical.mip
        False

  static MoebiusKantorGraph()

    Return a Möbius-Kantor Graph.

    A Möbius-Kantor graph is a cubic symmetric graph. (See also the Heawood graph). It has 16 nodes and 24 edges. It is nonplanar and Hamiltonian. It has diameter 4, girth 6, and chromatic number 2. It is identical to the Generalized Petersen graph, P[8, 3].

    For more details, see Möbius-Kantor Graph - from Wolfram MathWorld.

    PLOTTING: See the plotting section for the generalized Petersen graphs.

    EXAMPLES:

    Sage

        sage: MK = graphs.MoebiusKantorGraph()
        sage: MK
        Moebius-Kantor Graph: Graph on 16 vertices
        sage: MK.graph6_string()
        'OhCGKE?O@?ACAC@I?Q_AS'
        sage: (graphs.MoebiusKantorGraph()).show()      # long time                     # needs sage.plot

    Python

        >>> from sage.all import *
        >>> MK = graphs.MoebiusKantorGraph()
        >>> MK
        Moebius-Kantor Graph: Graph on 16 vertices
        >>> MK.graph6_string()
        'OhCGKE?O@?ACAC@I?Q_AS'
        >>> (graphs.MoebiusKantorGraph()).show()      # long time                     # needs sage.plot

  static MoebiusLadderGraph(n, immutable=False)

    Return a Möbius ladder graph with \(2n\) nodes

    A Möbius ladder graph of order \(2n\) is a ladder graph of the same order that is connected at the ends with a single twist, i.e., a ladder graph bent around so that top meets bottom with a single twist. Alternatively, it can be described as a single cycle graph (of order \(2n\)) with the addition of edges (called \(rungs\)) joining the antipodal pairs of nodes. Also, note that the Möbius ladder graph `graphs.MoebiusLadderGraph(n)` is precisely the same graph as the circulant graph `graphs.CirculantGraph(2 * n, [1, n])`.

    PLOTTING:

    Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each Möbius ladder graph will be displayed with the first (0) node at the top, with the rest following in a counterclockwise manner.

    INPUT:

    - `n` – a nonnegative integer; number of nodes is \(2n\)

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    OUTPUT:

    - `G` – a Möbius ladder graph of order \(2n\); note that a `ValueError` is returned if \(n < 0\)

    EXAMPLES:

    Construct and show a Möbius ladder graph with 26 nodes:

    Sage

        sage: g = graphs.MoebiusLadderGraph(13)
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.MoebiusLadderGraph(Integer(13))
        >>> g.show()                          # long time                             # needs sage.plot

    Create several Möbius ladder graphs in a Sage graphics array:

    Sage

        sage: # needs sage.plots
        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:    k = graphs.MoebiusLadderGraph(i+3)
        ....:    g.append(k)
        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)
        sage: G.show()                          # long time

    [Python]

        >>> from sage.all import *
        >>> # needs sage.plots
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...    k = graphs.MoebiusLadderGraph(i+Integer(3))
        ...    g.append(k)
        >>> for i in range(Integer(3)):
        ...    n = []
        ...    for m in range(Integer(3)):
        ...        n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...    j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    REFERENCES:

    - Wikipedia article Möbius_ladder

    See also

    `LadderGraph()`, `CircularLadderGraph()`, `CirculantGraph()`

    AUTHORS:

    - Janmenjaya Panda (2024-05-26)

  static MoserSpindle()

    Return the Moser spindle.

    For more information, see the Wikipedia article Moser_spindle.

    EXAMPLES:

    The Moser spindle is a planar graph having 7 vertices and 11 edges:

    Sage

        sage: # needs sage.symbolic
        sage: G = graphs.MoserSpindle(); G
        Moser spindle: Graph on 7 vertices
        sage: G.is_planar()
        True
        sage: G.order()
        7
        sage: G.size()
        11

    Python

        >>> from sage.all import *
        >>> # needs sage.symbolic
        >>> G = graphs.MoserSpindle(); G
        Moser spindle: Graph on 7 vertices
        >>> G.is_planar()
        True
        >>> G.order()
        7
        >>> G.size()
        11

    It is a Hamiltonian graph with radius 2, diameter 2, and girth 3:

    Sage

        sage: # needs sage.symbolic
        sage: G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        sage: G.radius()
        2
        sage: G.diameter()
        2
        sage: G.girth()
        3

    [Python]

        >>> from sage.all import *
        >>> # needs sage.symbolic
        >>> G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        >>> G.radius()
        2
        >>> G.diameter()
        2
        >>> 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

        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()
        4
        sage: ag = G.automorphism_group()
        sage: ag.is_isomorphic(DihedralGroup(4))
        True

    Python

        >>> from sage.all import *
        >>> # needs sage.symbolic
        >>> pos = G.get_pos()
        >>> all(sum((ui-vi)**Integer(2) for ui, vi in zip(pos[u], pos[v])) == Integer(1)
        ...         for u, v in G.edge_iterator(labels=None))
        True
        >>> G.chromatic_number()
        4
        >>> ag = G.automorphism_group()
        >>> ag.is_isomorphic(DihedralGroup(Integer(4)))
        True

  static MurtyGraph()

    Return the Murty graph.

    Consider the complete bipartite graph \(K_{3, 3}\). There is a set of three black vertices and a set of three white vertices. Now, consider splicing the complete graph \(K_4\) with one of the black vertices, this generates the graph \(K_4 \odot K_{3, 3}\). The Murty graph is obtained from \(K_4 \odot K_{3, 3}\) with the addition of an edge joining the remaining two black vertices. The Murty graph is free of conformal bicycles; in other words, the Murty graph is an example of a graph that is Birkhoff-von Neumann as well as PM-compact.

    This is the smallest brick that is Birkhoff-von Neumann, aka a solid brick, but is not odd-intercyclic. It is in this context that Prof. U.S.R. Murty first stumbled upon this graph, and it also appears in the work of Carvalho, Lucchesi, and Murty [CLM2006].

    PLOTTING:

    Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the Murty graph is displayed as mentioned in the paper [CKWL2019], with the first two (noncubic) vertices on the top row, the second three vertices (that form a stable set) in the middle row, and the remaining three vertices (that form a triangle) at the bottom.

    OUTPUT:

    - `G` – the Murty graph

    EXAMPLES:

    Construct and show the Murty graph:

    Sage

        sage: g = graphs.MurtyGraph()
        sage: g.name()
        'Murty Graph'
        sage: g.order()
        8
        sage: g.size()
        13
        sage: g.girth()
        3
        sage: g.diameter()
        2
        sage: g.is_hamiltonian()
        True
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.MurtyGraph()
        >>> g.name()
        'Murty Graph'
        >>> g.order()
        8
        >>> g.size()
        13
        >>> g.girth()
        3
        >>> g.diameter()
        2
        >>> g.is_hamiltonian()
        True
        >>> g.show()                          # long time                             # needs sage.plot

    REFERENCES:

    - [CKWL2019]

    - [CLM2006]

    - [LM2024]

    AUTHORS:

    - Janmenjaya Panda (2024-08-03)

  static MuzychukS6Graph(n, d, Phi='fixed', Sigma='fixed', verbose=False)

    Return a strongly regular graph of S6 type from [Muz2007] on \(n^d((n^d-1)/(n-1)+1)\) vertices.

    The construction depends upon a number of parameters, two of them, \(n\) and \(d\), mandatory, and \(\Phi\) and \(\Sigma\) mappings defined in [Muz2007]. These graphs have parameters \((mn^d, n^{d-1}(m-1) - 1,\mu - 2,\mu)\), where \(\mu=\frac{n^{d-1}-1}{n-1}n^{d-1}\) and \(m:=\frac{n^d-1}{n-1}+1\).

    Some details on \(\Phi\) and \(\Sigma\) are as follows. Let \(L\) be the complete graph on \(M:=\{0,..., m-1\}\) with the matching \(\{(2i,2i+1) | i=0,...,m/2\}\) removed. Then one arbitrarily chooses injections \(\Phi_i\) from the edges of \(L\) on \(i \in M\) into sets of parallel classes of affine \(d\)-dimensional designs; our implementation uses the designs of hyperplanes in \(d\)-dimensional affine geometries over \(GF(n)\). Finally, for each edge \(ij\) of \(L\) one arbitrarily chooses bijections \(\Sigma_{ij}\) between \(\Phi_i\) and \(\Phi_j\). More details, in particular how these choices lead to non-isomorphic graphs, are in [Muz2007].

    INPUT:

    - `n` – integer; a prime power

    - `d` – integer; must be odd if \(n\) is odd

    - `Phi` is an optional parameter of the construction; it must be either

      - `'fixed'` – this will generate fixed default \(\Phi_i\), for \(i \in M\), or

      - `'random'` – \(\Phi_i\) are generated at random, or

      - A dictionary describing the functions \(\Phi_i\); for \(i \in M\), Phi[(i, T)] in \(M\), for each edge T of \(L\) on \(i\). Also, each \(\Phi_i\) must be injective.

    - `Sigma` is an optional parameter of the construction; it must be either

      - `'fixed'` – this will generate a fixed default \(\Sigma\), or

      - `'random'` – \(\Sigma\) is generated at random

    - `verbose` – boolean (default: `False`); if `True`, print progress information

    See also

    - `is_muzychuk_S6()`

    Todo

    Implement the possibility to explicitly supply the parameter \(\Sigma\) of the construction.

    EXAMPLES:

    Sage

        sage: # needs sage.combinat sage.modules sage.rings.finite_rings
        sage: graphs.MuzychukS6Graph(3, 3).is_strongly_regular(parameters=True)
        (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)
        (16, 5, 0, 2)

    Python

        >>> from sage.all import *
        >>> # needs sage.combinat sage.modules sage.rings.finite_rings
        >>> graphs.MuzychukS6Graph(Integer(3), Integer(3)).is_strongly_regular(parameters=True)
        (378, 116, 34, 36)
        >>> phi = {(Integer(2),(Integer(0),Integer(2))):Integer(0), (Integer(1),(Integer(1),Integer(3))):Integer(1), (Integer(0),(Integer(0),Integer(3))):Integer(1), (Integer(2),(Integer(1),Integer(2))):Integer(1),
        ...        (Integer(1),(Integer(1),Integer(2))):Integer(0), (Integer(0),(Integer(0),Integer(2))):Integer(0), (Integer(3),(Integer(0),Integer(3))):Integer(0), (Integer(3),(Integer(1),Integer(3))):Integer(1)}
        >>> graphs.MuzychukS6Graph(Integer(2), Integer(2), Phi=phi).is_strongly_regular(parameters=True)
        (16, 5, 0, 2)

  static MycielskiGraph(k=1, relabel=True)

    Return the \(k\)-th Mycielski Graph.

    The graph \(M_k\) is triangle-free and has chromatic number equal to \(k\). These graphs show, constructively, that there are triangle-free graphs with arbitrarily high chromatic number.

    The Mycielski graphs are built recursively starting with \(M_0\), an empty graph; \(M_1\), a single vertex graph; and \(M_2\) is the graph \(K_2\). \(M_{k+1}\) is then built from \(M_k\) as follows:

    If the vertices of \(M_k\) are \(v_1,\ldots,v_n\), then the vertices of \(M_{k+1}\) are \(v_1,\ldots,v_n,w_1,\ldots,w_n,z\). Vertices \(v_1,\ldots,v_n\) induce a copy of \(M_k\). Vertices \(w_1,\ldots,w_n\) are an independent set. Vertex \(z\) is adjacent to all the \(w_i\)-vertices. Finally, vertex \(w_i\) is adjacent to vertex \(v_j\) iff \(v_i\) is adjacent to \(v_j\).

    For more details, see the Wikipedia article Mycielskian.

    INPUT:

    - `k` – number of steps in the construction process

    - `relabel` – relabel the vertices so their names are the integers `range(n)` where `n` is the number of vertices in the graph

    EXAMPLES:

    The Mycielski graph \(M_k\) is triangle-free and has chromatic number equal to \(k\).

    Sage

        sage: g = graphs.MycielskiGraph(5)
        sage: g.is_triangle_free()
        True
        sage: g.chromatic_number()
        5

    Python

        >>> from sage.all import *
        >>> g = graphs.MycielskiGraph(Integer(5))
        >>> g.is_triangle_free()
        True
        >>> g.chromatic_number()
        5

    The graphs \(M_4\) is (isomorphic to) the Grotzsch graph.

    Sage

        sage: g = graphs.MycielskiGraph(4)
        sage: g.is_isomorphic(graphs.GrotzschGraph())
        True

    [Python]

        >>> from sage.all import *
        >>> g = graphs.MycielskiGraph(Integer(4))
        >>> g.is_isomorphic(graphs.GrotzschGraph())
        True

  static MycielskiStep(g)

    Perform one iteration of the Mycielski construction.

    See the documentation for `MycielskiGraph` which uses this method. We expose it to all users in case they may find it useful.

    EXAMPLE. One iteration of the Mycielski step applied to the 5-cycle yields a graph isomorphic to the Grotzsch graph

    Sage

        sage: g = graphs.CycleGraph(5)
        sage: h = graphs.MycielskiStep(g)
        sage: h.is_isomorphic(graphs.GrotzschGraph())
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.CycleGraph(Integer(5))
        >>> h = graphs.MycielskiStep(g)
        >>> h.is_isomorphic(graphs.GrotzschGraph())
        True

  static NKStarGraph(n, k)

    Return the \((n,k)\)-star graph.

    The vertices of the \((n,k)\)-star graph are the set of all arrangements of \(n\) symbols into labels of length \(k\). There are two adjacency rules for the \((n,k)\)-star graph. First, two vertices are adjacent if one can be obtained from the other by swapping the first symbol with another symbol. Second, two vertices are adjacent if one can be obtained from the other by swapping the first symbol with an external symbol (a symbol not used in the original label).

    INPUT:

    - `n` – integer; number of symbols

    - `k` – integer; length of the labels of the vertices

    EXAMPLES:

    Sage

        sage: g = graphs.NKStarGraph(4,2)
        sage: g.plot()                          # long time                             # needs sage.plot
        Graphics object consisting of 31 graphics primitives

    Python

        >>> from sage.all import *
        >>> g = graphs.NKStarGraph(Integer(4),Integer(2))
        >>> g.plot()                          # long time                             # needs sage.plot
        Graphics object consisting of 31 graphics primitives

    REFERENCES:

    [CC1995]

    AUTHORS:

    - Michael Yurko (2009-09-01)

  static NStarGraph(n)

    Return the \(n\)-star graph.

    The vertices of the \(n\)-star graph are the set of permutations on \(n\) symbols. There is an edge between two vertices if their labels differ only in the first and one other position.

    INPUT:

    - `n` – integer; number of symbols

    EXAMPLES:

    Sage

        sage: g = graphs.NStarGraph(4)
        sage: g.plot()                          # long time                             # needs sage.plot
        Graphics object consisting of 61 graphics primitives

    Python

        >>> from sage.all import *
        >>> g = graphs.NStarGraph(Integer(4))
        >>> g.plot()                          # long time                             # needs sage.plot
        Graphics object consisting of 61 graphics primitives

    REFERENCES:

    [AHK1994]

    AUTHORS:

    - Michael Yurko (2009-09-01)

  static NauruGraph(embedding=2)

    Return the Nauru Graph.

    See the Wikipedia article Nauru_graph.

    INPUT:

    - `embedding` – integer (default: \(2\)); two embeddings are available, and can be selected by setting `embedding` to 1 or 2

    EXAMPLES:

    Sage

        sage: g = graphs.NauruGraph()
        sage: g.order()
        24
        sage: g.size()
        36
        sage: g.girth()
        6
        sage: g.diameter()
        4
        sage: g.show()                                                                  # needs sage.plot
        sage: graphs.NauruGraph(embedding=1).show()     # long time                     # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.NauruGraph()
        >>> g.order()
        24
        >>> g.size()
        36
        >>> g.girth()
        6
        >>> g.diameter()
        4
        >>> g.show()                                                                  # needs sage.plot
        >>> graphs.NauruGraph(embedding=Integer(1)).show()     # long time                     # needs sage.plot

  static NonisotropicOrthogonalPolarGraph(m, q, sign='+', perp=None)

    Return the Graph \(NO^{\epsilon,\perp}_{m}(q)\).

    Let the vectorspace of dimension \(m\) over \(F_q\) be endowed with a nondegenerate quadratic form \(F\), of type `sign` for \(m\) even.

    - \(m\) even: assume further that \(q=2\) or \(3\). Returns the graph of the points (in the underlying projective space) \(x\) satisfying \(F(x)=1\), with adjacency given by orthogonality w.r.t. \(F\). Parameter `perp` is ignored.

    - \(m\) odd: if `perp` is not `None`, then we assume that \(q=5\) and return the graph of the points \(x\) satisfying \(F(x)=\pm 1\) if `sign="+"`, respectively \(F(x) \in \{2,3\}\) if `sign="-"`, with adjacency given by orthogonality w.r.t. \(F\) (cf. Sect 7.D of [BL1984]). Otherwise return the graph of nongenerate hyperplanes of type `sign`, adjacent whenever the intersection is degenerate (cf. Sect. 7.C of [BL1984]). Note that for \(q=2\) one will get a complete graph.

    For more information, see Sect. 9.9 of [BH2012] and [BL1984]. Note that the page of Andries Brouwer’s website uses different notation.

    INPUT:

    - `m` – integer; half the dimension of the underlying vectorspace

    - `q` – a power of a prime number, the size of the underlying field

    - `sign` – string (default: `'+'`); must be either `'+'` or `'-'`

    EXAMPLES:

    \(NO^-(4,2)\) is isomorphic to Petersen graph:

    Sage

        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)                                    # needs sage.libs.gap
        (10, 3, 0, 1)

    Python

        >>> from sage.all import *
        >>> g = graphs.NonisotropicOrthogonalPolarGraph(Integer(4),Integer(2),'-'); g                   # needs sage.libs.gap
        NO^-(4, 2): Graph on 10 vertices
        >>> g.is_strongly_regular(parameters=True)                                    # needs sage.libs.gap
        (10, 3, 0, 1)

    \(NO^-(6,2)\) and \(NO^+(6,2)\):

    Sage

        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
        NO^+(6, 2): Graph on 28 vertices
        sage: g.is_strongly_regular(parameters=True)
        (28, 15, 6, 10)

    [Python]

        >>> from sage.all import *
        >>> # needs sage.libs.gap
        >>> g = graphs.NonisotropicOrthogonalPolarGraph(Integer(6),Integer(2),'-')
        >>> g.is_strongly_regular(parameters=True)
        (36, 15, 6, 6)
        >>> g = graphs.NonisotropicOrthogonalPolarGraph(Integer(6),Integer(2),'+'); g
        NO^+(6, 2): Graph on 28 vertices
        >>> g.is_strongly_regular(parameters=True)
        (28, 15, 6, 10)

    \(NO^+(8,2)\):

    Sage

        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)

    Python

        >>> from sage.all import *
        >>> g = graphs.NonisotropicOrthogonalPolarGraph(Integer(8),Integer(2),'+')                      # needs sage.libs.gap
        >>> g.is_strongly_regular(parameters=True)                                    # needs sage.libs.gap
        (120, 63, 30, 36)

    Wilbrink’s graphs for \(q=5\):

    Sage

        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)
        sage: g.is_strongly_regular(parameters=True)    # long time
        (300, 65, 10, 15)

    [Python]

        >>> from sage.all import *
        >>> # needs sage.libs.gap
        >>> g = graphs.NonisotropicOrthogonalPolarGraph(Integer(5),Integer(5),perp=Integer(1))
        >>> g.is_strongly_regular(parameters=True)    # long time
        (325, 60, 15, 10)
        >>> g = graphs.NonisotropicOrthogonalPolarGraph(Integer(5),Integer(5),'-',perp=Integer(1))
        >>> g.is_strongly_regular(parameters=True)    # long time
        (300, 65, 10, 15)

    Wilbrink’s graphs:

    Sage

        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,'-')
        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
        sage: g.is_strongly_regular(parameters=True)                         # not tested (long time)
        (2080, 1071, 558, 544)

    Python

        >>> from sage.all import *
        >>> # needs sage.libs.gap
        >>> g = graphs.NonisotropicOrthogonalPolarGraph(Integer(5),Integer(4),'+')
        >>> g.is_strongly_regular(parameters=True)
        (136, 75, 42, 40)
        >>> g = graphs.NonisotropicOrthogonalPolarGraph(Integer(5),Integer(4),'-')
        >>> g.is_strongly_regular(parameters=True)
        (120, 51, 18, 24)
        >>> g = graphs.NonisotropicOrthogonalPolarGraph(Integer(7),Integer(4),'+'); g        # not tested (long time)
        NO^+(7, 4): Graph on 2080 vertices
        >>> g.is_strongly_regular(parameters=True)                         # not tested (long time)
        (2080, 1071, 558, 544)

  static NonisotropicUnitaryPolarGraph(m, q)

    Return the Graph \(NU(m,q)\).

    This returns the graph on nonisotropic, with respect to a nondegenerate Hermitean form, points of the \((m-1)\)-dimensional projective space over \(F_q\), with points adjacent whenever they lie on a tangent (to the set of isotropic points) line. For more information, see Sect. 9.9 of [BH2012] and series C14 in [Hub1975].

    INPUT:

    - `m`, `q` – integers; \(q\) must be a prime power

    EXAMPLES:

    Sage

        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)                                    # needs sage.libs.gap
        (176, 135, 102, 108)

    Python

        >>> from sage.all import *
        >>> g = graphs.NonisotropicUnitaryPolarGraph(Integer(5),Integer(2)); g                          # needs sage.libs.gap
        NU(5, 2): Graph on 176 vertices
        >>> g.is_strongly_regular(parameters=True)                                    # needs sage.libs.gap
        (176, 135, 102, 108)

  static Nowhere0WordsTwoWeightCodeGraph(q, hyperoval=None, field=None, check_hyperoval=True)

    Return the subgraph of nowhere 0 words from two-weight code of projective plane hyperoval.

    Let \(q=2^k\) and \(\Pi=PG(2,q)\). Fix a hyperoval \(O \subset \Pi\). Let \(V=F_q^3\) and \(C\) the two-weight 3-dimensional linear code over \(F_q\) with words \(c(v)\) obtained from \(v\in V\) by computing

    \[c(v)=(\langle v,o_1 \rangle,...,\langle v,o_{q+2} \rangle), o_j \in O.\]

    \(C\) contains \(q(q-1)^2/2\) words without 0 entries. The subgraph of the strongly regular graph of \(C\) induced on the latter words is also strongly regular, assuming \(q>4\). This is a construction due to A.E.Brouwer [Bro2016], and leads to graphs with parameters also given by a construction in [HHL2009]. According to [Bro2016], these two constructions are likely to produce isomorphic graphs.

    INPUT:

    - `q` – a power of two

    - `hyperoval` – a hyperoval (i.e. a complete 2-arc; a set of points in the plane meeting every line in 0 or 2 points) in \(PG(2,q)\) over the field `field`. Each point of `hyperoval` must be a length 3 vector over `field` with 1st non-0 coordinate equal to 1. By default, `hyperoval` and `field` are not specified, and constructed on the fly. In particular, `hyperoval` we build is the classical one, i.e. a conic with the point of intersection of its tangent lines.

    - `field` – an instance of a finite field of order \(q\); must be provided if `hyperoval` is provided

    - `check_hyperoval` – boolean (default: `True`); whether to check `hyperoval` for correctness or not

    See also

    - `is_nowhere0_twoweight()`

    EXAMPLES:

    using the built-in construction:

    Sage

        sage: # needs sage.combinat sage.rings.finite_rings
        sage: g = graphs.Nowhere0WordsTwoWeightCodeGraph(8); g
        Nowhere0WordsTwoWeightCodeGraph(8): Graph on 196 vertices
        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)
        (1800, 728, 268, 312)

    Python

        >>> from sage.all import *
        >>> # needs sage.combinat sage.rings.finite_rings
        >>> g = graphs.Nowhere0WordsTwoWeightCodeGraph(Integer(8)); g
        Nowhere0WordsTwoWeightCodeGraph(8): Graph on 196 vertices
        >>> g.is_strongly_regular(parameters=True)
        (196, 60, 14, 20)
        >>> g = graphs.Nowhere0WordsTwoWeightCodeGraph(Integer(16))  # not tested (long time)
        >>> g.is_strongly_regular(parameters=True)          # not tested (long time)
        (1800, 728, 268, 312)

    supplying your own hyperoval:

    Sage

        sage: # needs sage.combinat 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))
        ....:                                              for x in F]
        sage: g = graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F); g
        Nowhere0WordsTwoWeightCodeGraph(8): Graph on 196 vertices
        sage: g.is_strongly_regular(parameters=True)
        (196, 60, 14, 20)

    [Python]

        >>> from sage.all import *
        >>> # needs sage.combinat sage.rings.finite_rings
        >>> F = GF(Integer(8))
        >>> O = [vector(F,(Integer(0),Integer(0),Integer(1))),vector(F,(Integer(0),Integer(1),Integer(0)))] + [vector(F, (Integer(1),x**Integer(2),x))
        ...                                              for x in F]
        >>> g = graphs.Nowhere0WordsTwoWeightCodeGraph(Integer(8),hyperoval=O,field=F); g
        Nowhere0WordsTwoWeightCodeGraph(8): Graph on 196 vertices
        >>> g.is_strongly_regular(parameters=True)
        (196, 60, 14, 20)

  static OctahedralGraph()

    Return an Octahedral graph (with 6 nodes).

    The regular octahedron is an 8-sided polyhedron with triangular faces. The octahedral graph corresponds to the connectivity of the vertices of the octahedron. It is the line graph of the tetrahedral graph. The octahedral is symmetric, so the spring-layout algorithm will be very effective for display.

    PLOTTING: The Octahedral graph should be viewed in 3 dimensions. We choose to use a planar embedding of the graph. We hope to add rotatable, 3-dimensional viewing in the future. In such a case, an argument will be added to select the desired layout.

    EXAMPLES:

    Construct and show an Octahedral graph:

    Sage

        sage: g = graphs.OctahedralGraph()
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.OctahedralGraph()
        >>> g.show()                          # long time                             # needs sage.plot

    Create several octahedral graphs in a Sage graphics array They will be drawn differently due to the use of the spring-layout algorithm:

    Sage

        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):
        ....:     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)
        sage: G.show()                          # long time

    [Python]

        >>> from sage.all import *
        >>> # needs sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     k = graphs.OctahedralGraph()
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

  static OddGraph(n)

    Return the Odd Graph with parameter \(n\).

    The Odd Graph with parameter \(n\) is defined as the Kneser Graph with parameters \(2n-1,n-1\). Equivalently, the Odd Graph is the graph whose vertices are the \(n-1\)-subsets of \([0,1,\dots,2(n-1)]\), and such that two vertices are adjacent if their corresponding sets are disjoint.

    For example, the Petersen Graph can be defined as the Odd Graph with parameter \(3\).

    EXAMPLES:

    Sage

        sage: OG = graphs.OddGraph(3)
        sage: sorted(OG.vertex_iterator(), key=str)
        [{1, 2}, {1, 3}, {1, 4}, {1, 5}, {2, 3}, {2, 4}, {2, 5},
         {3, 4}, {3, 5}, {4, 5}]
        sage: P = graphs.PetersenGraph()
        sage: P.is_isomorphic(OG)
        True

    Python

        >>> from sage.all import *
        >>> OG = graphs.OddGraph(Integer(3))
        >>> sorted(OG.vertex_iterator(), key=str)
        [{1, 2}, {1, 3}, {1, 4}, {1, 5}, {2, 3}, {2, 4}, {2, 5},
         {3, 4}, {3, 5}, {4, 5}]
        >>> P = graphs.PetersenGraph()
        >>> P.is_isomorphic(OG)
        True

  static OrthogonalArrayBlockGraph(k, n, OA=None)

    Return the graph of an \(OA(k,n)\).

    The intersection graph of the blocks of a transversal design with parameters \((k,n)\), or \(TD(k,n)\) for short, is a strongly regular graph (unless it is a complete graph). Its parameters \((v,k',\lambda,\mu)\) are determined by the parameters \(k,n\) via:

    \[v=n^2, k'=k(n-1), \lambda=(k-1)(k-2)+n-2, \mu=k(k-1)\]

    As transversal designs and orthogonal arrays (OA for short) are equivalent objects, this graph can also be built from the blocks of an \(OA(k,n)\), two of them being adjacent if one of their coordinates match.

    For more information on these graphs, see Andries Brouwer’s page on Orthogonal Array graphs.

    Warning

    - Brouwer’s website uses the notation \(OA(n,k)\) instead of \(OA(k,n)\)

    - For given parameters \(k\) and \(n\) there can be many \(OA(k,n)\) : the graphs returned are not uniquely defined by their parameters (see the examples below).

    - If the function is called only with the parameter `k` and `n` the results might be different with two versions of Sage, or even worse : some could not be available anymore.

    See also

    `sage.combinat.designs.orthogonal_arrays`

    INPUT:

    - `k`, `n` – integers

    - `OA` – an orthogonal array; if set to `None` (default) then `orthogonal_array()` is called to compute an \(OA(k,n)\)

    EXAMPLES:

    Sage

        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)                                    # needs sage.schemes
        (25, 20, 15, 20)
        sage: G = graphs.OrthogonalArrayBlockGraph(4,10); G
        OA(4,10): Graph on 100 vertices
        sage: G.is_strongly_regular(parameters=True)
        (100, 36, 14, 12)

    Python

        >>> from sage.all import *
        >>> # needs sage.modules
        >>> G = graphs.OrthogonalArrayBlockGraph(Integer(5),Integer(5)); G                              # needs sage.schemes
        OA(5,5): Graph on 25 vertices
        >>> G.is_strongly_regular(parameters=True)                                    # needs sage.schemes
        (25, 20, 15, 20)
        >>> G = graphs.OrthogonalArrayBlockGraph(Integer(4),Integer(10)); G
        OA(4,10): Graph on 100 vertices
        >>> G.is_strongly_regular(parameters=True)
        (100, 36, 14, 12)

    Two graphs built from different orthogonal arrays are also different:

    Sage

        sage: # needs sage.modules
        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))
        False
        sage: Ga = graphs.OrthogonalArrayBlockGraph(k, n, OAa)
        sage: Gb = graphs.OrthogonalArrayBlockGraph(k, n, OAb)
        sage: Ga == Gb
        False

    [Python]

        >>> from sage.all import *
        >>> # needs sage.modules
        >>> k = Integer(4); n = Integer(10)
        >>> OAa = designs.orthogonal_arrays.build(k,n)
        >>> OAb = [[(x+Integer(1))%n for x in R] for R in OAa]
        >>> set(map(tuple,OAa)) == set(map(tuple,OAb))
        False
        >>> Ga = graphs.OrthogonalArrayBlockGraph(k, n, OAa)
        >>> Gb = graphs.OrthogonalArrayBlockGraph(k, n, OAb)
        >>> Ga == Gb
        False

    As `OAb` was obtained from `OAa` by a relabelling the two graphs are isomorphic:

    Sage

        sage: Ga.is_isomorphic(Gb)                                                      # needs sage.modules
        True

    Python

        >>> from sage.all import *
        >>> Ga.is_isomorphic(Gb)                                                      # needs sage.modules
        True

    But there are examples of \(OA(k,n)\) for which the resulting graphs are not isomorphic:

    Sage

        sage: oa0 = [[0, 0, 1], [0, 1, 3], [0, 2, 0], [0, 3, 2],
        ....:        [1, 0, 3], [1, 1, 1], [1, 2, 2], [1, 3, 0],
        ....:        [2, 0, 0], [2, 1, 2], [2, 2, 1], [2, 3, 3],
        ....:        [3, 0, 2], [3, 1, 0], [3, 2, 3], [3, 3, 1]]
        sage: oa1 = [[0, 0, 1], [0, 1, 0], [0, 2, 3], [0, 3, 2],
        ....:        [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)                          # needs sage.modules
        sage: g1 = graphs.OrthogonalArrayBlockGraph(3, 4, oa1)                          # needs sage.modules
        sage: g0.is_isomorphic(g1)                                                      # needs sage.modules
        False

    [Python]

        >>> from sage.all import *
        >>> oa0 = [[Integer(0), Integer(0), Integer(1)], [Integer(0), Integer(1), Integer(3)], [Integer(0), Integer(2), Integer(0)], [Integer(0), Integer(3), Integer(2)],
        ...        [Integer(1), Integer(0), Integer(3)], [Integer(1), Integer(1), Integer(1)], [Integer(1), Integer(2), Integer(2)], [Integer(1), Integer(3), Integer(0)],
        ...        [Integer(2), Integer(0), Integer(0)], [Integer(2), Integer(1), Integer(2)], [Integer(2), Integer(2), Integer(1)], [Integer(2), Integer(3), Integer(3)],
        ...        [Integer(3), Integer(0), Integer(2)], [Integer(3), Integer(1), Integer(0)], [Integer(3), Integer(2), Integer(3)], [Integer(3), Integer(3), Integer(1)]]
        >>> oa1 = [[Integer(0), Integer(0), Integer(1)], [Integer(0), Integer(1), Integer(0)], [Integer(0), Integer(2), Integer(3)], [Integer(0), Integer(3), Integer(2)],
        ...        [Integer(1), Integer(0), Integer(3)], [Integer(1), Integer(1), Integer(2)], [Integer(1), Integer(2), Integer(0)], [Integer(1), Integer(3), Integer(1)],
        ...        [Integer(2), Integer(0), Integer(0)], [Integer(2), Integer(1), Integer(1)], [Integer(2), Integer(2), Integer(2)], [Integer(2), Integer(3), Integer(3)],
        ...        [Integer(3), Integer(0), Integer(2)], [Integer(3), Integer(1), Integer(3)], [Integer(3), Integer(2), Integer(1)], [Integer(3), Integer(3), Integer(0)]]
        >>> g0 = graphs.OrthogonalArrayBlockGraph(Integer(3), Integer(4), oa0)                          # needs sage.modules
        >>> g1 = graphs.OrthogonalArrayBlockGraph(Integer(3), Integer(4), oa1)                          # needs sage.modules
        >>> g0.is_isomorphic(g1)                                                      # needs sage.modules
        False

    But nevertheless isospectral:

    Sage

        sage: g0.spectrum()                                                             # needs sage.modules sage.rings.number_field
        [9, 1, 1, 1, 1, 1, 1, 1, 1, 1, -3, -3, -3, -3, -3, -3]
        sage: g1.spectrum()                                                             # needs sage.modules sage.rings.number_field
        [9, 1, 1, 1, 1, 1, 1, 1, 1, 1, -3, -3, -3, -3, -3, -3]

    Python

        >>> from sage.all import *
        >>> g0.spectrum()                                                             # needs sage.modules sage.rings.number_field
        [9, 1, 1, 1, 1, 1, 1, 1, 1, 1, -3, -3, -3, -3, -3, -3]
        >>> g1.spectrum()                                                             # needs sage.modules sage.rings.number_field
        [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

        sage: graphs.AffineOrthogonalPolarGraph(4,2,'+').is_isomorphic(g0)              # needs sage.libs.gap sage.modules
        True

    [Python]

        >>> from sage.all import *
        >>> graphs.AffineOrthogonalPolarGraph(Integer(4),Integer(2),'+').is_isomorphic(g0)              # needs sage.libs.gap sage.modules
        True

  static OrthogonalDualPolarGraph(e, d, q)

    Return the dual polar graph on \(GO^e(n,q)\) of diameter \(d\).

    The value of \(n\) is determined by \(d\) and \(e\).

    The graph is distance-regular with classical parameters \((d, q, 0, q^e)\).

    INPUT:

    - `e` – integer; type of the orthogonal polar space to consider; must be \(-1, 0\) or \(1\)

    - `d` – integer; diameter of the graph

    - `q` – integer; prime power; order of the finite field over which to build the polar space

    EXAMPLES:

    Sage

        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
        sage: G.is_distance_regular(True)                       # long time
        ([39, 36, 27, None], [None, 1, 4, 13])
        sage: G.order()                                         # long time
        1120

    Python

        >>> from sage.all import *
        >>> # needs sage.libs.gap
        >>> G = graphs.OrthogonalDualPolarGraph(Integer(1),Integer(3),Integer(2))
        >>> G.is_distance_regular(True)
        ([7, 6, 4, None], [None, 1, 3, 7])
        >>> G = graphs.OrthogonalDualPolarGraph(Integer(0),Integer(3),Integer(3))        # long time
        >>> G.is_distance_regular(True)                       # long time
        ([39, 36, 27, None], [None, 1, 4, 13])
        >>> G.order()                                         # long time
        1120

    REFERENCES:

    See [BCN1989] pp. 274-279 or [VDKT2016] p. 22.

  static OrthogonalPolarGraph(m, q, sign='+')

    Return the Orthogonal Polar Graph \(O^{\epsilon}(m,q)\).

    For more information on Orthogonal Polar graphs, see the page of Andries Brouwer’s website.

    INPUT:

    - `m`, `q` – integers; \(q\) must be a prime power

    - `sign` – string (default: `'+'`); must be `'+'` or `'-'` if \(m\) is even, `'+'` (default) otherwise

    EXAMPLES:

    Sage

        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)
        (130, 48, 20, 16)
        sage: G = graphs.OrthogonalPolarGraph(6,3,"-"); G
        Orthogonal Polar Graph O^-(6, 3): Graph on 112 vertices
        sage: G.is_strongly_regular(parameters=True)
        (112, 30, 2, 10)
        sage: G = graphs.OrthogonalPolarGraph(5,3); G
        Orthogonal Polar Graph O(5, 3): Graph on 40 vertices
        sage: G.is_strongly_regular(parameters=True)
        (40, 12, 2, 4)
        sage: G = graphs.OrthogonalPolarGraph(8,2,"+"); G
        Orthogonal Polar Graph O^+(8, 2): Graph on 135 vertices
        sage: G.is_strongly_regular(parameters=True)
        (135, 70, 37, 35)
        sage: G = graphs.OrthogonalPolarGraph(8,2,"-"); G
        Orthogonal Polar Graph O^-(8, 2): Graph on 119 vertices
        sage: G.is_strongly_regular(parameters=True)
        (119, 54, 21, 27)

    Python

        >>> from sage.all import *
        >>> # needs sage.libs.gap
        >>> G = graphs.OrthogonalPolarGraph(Integer(6),Integer(3),"+"); G
        Orthogonal Polar Graph O^+(6, 3): Graph on 130 vertices
        >>> G.is_strongly_regular(parameters=True)
        (130, 48, 20, 16)
        >>> G = graphs.OrthogonalPolarGraph(Integer(6),Integer(3),"-"); G
        Orthogonal Polar Graph O^-(6, 3): Graph on 112 vertices
        >>> G.is_strongly_regular(parameters=True)
        (112, 30, 2, 10)
        >>> G = graphs.OrthogonalPolarGraph(Integer(5),Integer(3)); G
        Orthogonal Polar Graph O(5, 3): Graph on 40 vertices
        >>> G.is_strongly_regular(parameters=True)
        (40, 12, 2, 4)
        >>> G = graphs.OrthogonalPolarGraph(Integer(8),Integer(2),"+"); G
        Orthogonal Polar Graph O^+(8, 2): Graph on 135 vertices
        >>> G.is_strongly_regular(parameters=True)
        (135, 70, 37, 35)
        >>> G = graphs.OrthogonalPolarGraph(Integer(8),Integer(2),"-"); G
        Orthogonal Polar Graph O^-(8, 2): Graph on 119 vertices
        >>> G.is_strongly_regular(parameters=True)
        (119, 54, 21, 27)

  static PaleyGraph(q)

    Paley graph with \(q\) vertices.

    Parameter \(q\) must be the power of a prime number and congruent to 1 mod 4.

    EXAMPLES:

    Sage

        sage: G = graphs.PaleyGraph(9); G                                               # needs sage.rings.finite_rings
        Paley graph with parameter 9: Graph on 9 vertices
        sage: G.is_regular()                                                            # needs sage.rings.finite_rings
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.PaleyGraph(Integer(9)); G                                               # needs sage.rings.finite_rings
        Paley graph with parameter 9: Graph on 9 vertices
        >>> G.is_regular()                                                            # needs sage.rings.finite_rings
        True

    A Paley graph is always self-complementary:

    Sage

        sage: G.is_self_complementary()                                                 # needs sage.rings.finite_rings
        True

    [Python]

        >>> from sage.all import *
        >>> G.is_self_complementary()                                                 # needs sage.rings.finite_rings
        True

  static PappusGraph()

    Return the Pappus graph, a graph on 18 vertices.

    The Pappus graph is cubic, symmetric, and distance-regular.

    EXAMPLES:

    Sage

        sage: G = graphs.PappusGraph()
        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

    Python

        >>> from sage.all import *
        >>> G = graphs.PappusGraph()
        >>> G.show()                          # long time                             # needs sage.plot
        >>> L = graphs.LCFGraph(Integer(18), [Integer(5),Integer(7),-Integer(7),Integer(7),-Integer(7),-Integer(5)], Integer(3))                              # needs networkx
        >>> L.show()                          # long time                             # needs networkx sage.plot
        >>> G.is_isomorphic(L)                                                        # needs networkx
        True

  static PasechnikGraph(n)

    Pasechnik strongly regular graph on \((4n-1)^2\) vertices.

    A strongly regular graph with parameters of the orthogonal array graph `OrthogonalArrayBlockGraph()`, also known as pseudo Latin squares graph \(L_{2n-1}(4n-1)\), constructed from a skew Hadamard matrix of order \(4n\) following [Pas1992].

    See also

    - `is_orthogonal_array_block_graph()`

    EXAMPLES:

    Sage

        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, needs sage.combinat sage.modules
        (361, 162, 73, 72)
        sage: graphs.PasechnikGraph(9).is_strongly_regular(parameters=True)  # not tested
        (1225, 578, 273, 272)

    Python

        >>> from sage.all import *
        >>> graphs.PasechnikGraph(Integer(4)).is_strongly_regular(parameters=True)             # needs sage.combinat sage.modules
        (225, 98, 43, 42)
        >>> graphs.PasechnikGraph(Integer(5)).is_strongly_regular(parameters=True)     # long time, needs sage.combinat sage.modules
        (361, 162, 73, 72)
        >>> graphs.PasechnikGraph(Integer(9)).is_strongly_regular(parameters=True)  # not tested
        (1225, 578, 273, 272)

  static PathGraph(n, pos=None, immutable=False, name=None)

    Return a path graph with \(n\) nodes.

    A path graph is a graph where all inner nodes are connected to their two neighbors and the two end-nodes are connected to their one inner neighbors (i.e.: a cycle graph without the first and last node connected).

    INPUT:

    - `n` – nonnegative integer; number of nodes of the path graph

    - `pos` – string (default: `None`); indicates the embedding to use between ‘circle’, ‘line’ or the default algorithm. See the plotting section below for more detail.

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    - `name` – string (default: `None`); used as the name of the returned graph when set

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the graph may be drawn in one of two ways: The ‘line’ argument will draw the graph in a horizontal line (left to right) if there are less than 11 nodes. Otherwise the ‘line’ argument will append horizontal lines of length 10 nodes below, alternating left to right and right to left. The ‘circle’ argument will cause the graph to be drawn in a cycle-shape, with the first node at the top and then about the circle in a clockwise manner. By default (without an appropriate string argument) the graph will be drawn as a ‘circle’ if \(10 < n < 41\) and as a ‘line’ for all other \(n\).

    EXAMPLES:

    Show default drawing by size: ‘line’: \(n \leq 10\):

    Sage

        sage: p = graphs.PathGraph(10)
        sage: p.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> p = graphs.PathGraph(Integer(10))
        >>> p.show()                          # long time                             # needs sage.plot

    ‘circle’: \(10 < n < 41\):

    Sage

        sage: q = graphs.PathGraph(25)
        sage: q.show()                          # long time                             # needs sage.plot

    [Python]

        >>> from sage.all import *
        >>> q = graphs.PathGraph(Integer(25))
        >>> q.show()                          # long time                             # needs sage.plot

    ‘line’: \(n \geq 41\):

    Sage

        sage: r = graphs.PathGraph(55)
        sage: r.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> r = graphs.PathGraph(Integer(55))
        >>> r.show()                          # long time                             # needs sage.plot

    Override the default drawing:

    Sage

        sage: s = graphs.PathGraph(5,'circle')
        sage: s.show()                          # long time                             # needs sage.plot

    [Python]

        >>> from sage.all import *
        >>> s = graphs.PathGraph(Integer(5),'circle')
        >>> s.show()                          # long time                             # needs sage.plot

  static PerkelGraph()

    Return the Perkel Graph.

    The Perkel Graph is a 6-regular graph with \(57\) vertices and \(171\) edges. It is the unique distance-regular graph with intersection array \((6,5,2;1,1,3)\). For more information, see the Wikipedia article Perkel_graph or https://www.win.tue.nl/~aeb/graphs/Perkel.html.

    EXAMPLES:

    Sage

        sage: g = graphs.PerkelGraph(); g
        Perkel Graph: Graph on 57 vertices
        sage: g.is_distance_regular(parameters=True)
        ([6, 5, 2, None], [None, 1, 1, 3])

    Python

        >>> from sage.all import *
        >>> g = graphs.PerkelGraph(); g
        Perkel Graph: Graph on 57 vertices
        >>> g.is_distance_regular(parameters=True)
        ([6, 5, 2, None], [None, 1, 1, 3])

  static PermutationGraph(second_permutation, first_permutation=None)

    Build a permutation graph from one permutation or from two lists.

    Definition:

    If \(\sigma\) is a permutation of \(\{ 1, 2, \ldots, n \}\), then the permutation graph of \(\sigma\) is the graph on vertex set \(\{ 1, 2, \ldots, n \}\) in which two vertices \(i\) and \(j\) satisfying \(i < j\) are connected by an edge if and only if \(\sigma^{-1}(i) > \sigma^{-1}(j)\). A visual way to construct this graph is as follows:

    > Take two horizontal lines in the euclidean plane, and mark points \(1, ..., n\) from left to right on the first of them. On the second one, still from left to right, mark \(n\) points \(\sigma(1), \sigma(2), \ldots, \sigma(n)\). Now, link by a segment the two points marked with \(1\), then link together the points marked with \(2\), and so on. The permutation graph of \(\sigma\) is the intersection graph of those segments: there exists a vertex in this graph for each element from \(1\) to \(n\), two vertices \(i, j\) being adjacent if the segments \(i\) and \(j\) cross each other.

    The set of edges of the permutation graph can thus be identified with the set of inversions of the inverse of the given permutation \(\sigma\).

    A more general notion of permutation graph can be defined as follows: If \(S\) is a set, and \((a_1, a_2, \ldots, a_n)\) and \((b_1, b_2, \ldots, b_n)\) are two lists of elements of \(S\), each of which lists contains every element of \(S\) exactly once, then the permutation graph defined by these two lists is the graph on the vertex set \(S\) in which two vertices \(i\) and \(j\) are connected by an edge if and only if the order in which these vertices appear in the list \((a_1, a_2, \ldots, a_n)\) is the opposite of the order in which they appear in the list \((b_1, b_2, \ldots, b_n)\). When \((a_1, a_2, \ldots, a_n) = (1, 2, \ldots, n)\), this graph is the permutation graph of the permutation \((b_1, b_2, \ldots, b_n) \in S_n\). Notice that \(S\) does not have to be a set of integers here, but can be a set of strings, tuples, or anything else. We can still use the above visual description to construct the permutation graph, but now we have to mark points \(a_1, a_2, \ldots, a_n\) from left to right on the first horizontal line and points \(b_1, b_2, \ldots, b_n\) from left to right on the second horizontal line.

    INPUT:

    - `second_permutation` – the unique permutation/list defining the graph, or the second of the two (if the graph is to be built from two permutations/lists)

    - `first_permutation` – (optional) the first of the two permutations/lists from which the graph should be built, if it is to be built from two permutations/lists

      When `first_permutation is None` (default), it is set to be equal to `sorted(second_permutation)`, which yields the expected ordering when the elements of the graph are integers.

    See also

    - Recognition of Permutation graphs in the `comparability module`.

    - Drawings of permutation graphs as intersection graphs of segments is possible through the `show()` method of `Permutation` objects.

      The correct argument to use in this case is `show(representation = "braid")`.

    - `inversions()`

    EXAMPLES:

    Sage

        sage: p = Permutations(5).random_element()
        sage: PG = graphs.PermutationGraph(p)
        sage: edges = PG.edges(sort=True, labels=False)
        sage: set(edges) == set(p.inverse().inversions())
        True

        sage: PG = graphs.PermutationGraph([3,4,5,1,2])
        sage: sorted(PG.edges(sort=True))
        [(1, 3, None),
         (1, 4, None),
         (1, 5, None),
         (2, 3, None),
         (2, 4, None),
         (2, 5, None)]
        sage: PG = graphs.PermutationGraph([3,4,5,1,2], [1,4,2,5,3])
        sage: sorted(PG.edges(sort=True))
        [(1, 3, None),
         (1, 4, None),
         (1, 5, None),
         (2, 3, None),
         (2, 5, None),
         (3, 4, None),
         (3, 5, None)]
        sage: PG = graphs.PermutationGraph([1,4,2,5,3], [3,4,5,1,2])
        sage: sorted(PG.edges(sort=True))
        [(1, 3, None),
         (1, 4, None),
         (1, 5, None),
         (2, 3, None),
         (2, 5, None),
         (3, 4, None),
         (3, 5, None)]

        sage: PG = graphs.PermutationGraph(Permutation([1,3,2]), Permutation([1,2,3]))
        sage: sorted(PG.edges(sort=True))
        [(2, 3, None)]

        sage: graphs.PermutationGraph([]).edges(sort=True)
        []
        sage: graphs.PermutationGraph([], []).edges(sort=True)
        []

        sage: PG = graphs.PermutationGraph("graph", "phrag")
        sage: sorted(PG.edges(sort=True))
        [('a', 'g', None),
         ('a', 'h', None),
         ('a', 'p', None),
         ('g', 'h', None),
         ('g', 'p', None),
         ('g', 'r', None),
         ('h', 'r', None),
         ('p', 'r', None)]

    Python

        >>> from sage.all import *
        >>> p = Permutations(Integer(5)).random_element()
        >>> PG = graphs.PermutationGraph(p)
        >>> edges = PG.edges(sort=True, labels=False)
        >>> set(edges) == set(p.inverse().inversions())
        True

        >>> PG = graphs.PermutationGraph([Integer(3),Integer(4),Integer(5),Integer(1),Integer(2)])
        >>> sorted(PG.edges(sort=True))
        [(1, 3, None),
         (1, 4, None),
         (1, 5, None),
         (2, 3, None),
         (2, 4, None),
         (2, 5, None)]
        >>> PG = graphs.PermutationGraph([Integer(3),Integer(4),Integer(5),Integer(1),Integer(2)], [Integer(1),Integer(4),Integer(2),Integer(5),Integer(3)])
        >>> sorted(PG.edges(sort=True))
        [(1, 3, None),
         (1, 4, None),
         (1, 5, None),
         (2, 3, None),
         (2, 5, None),
         (3, 4, None),
         (3, 5, None)]
        >>> PG = graphs.PermutationGraph([Integer(1),Integer(4),Integer(2),Integer(5),Integer(3)], [Integer(3),Integer(4),Integer(5),Integer(1),Integer(2)])
        >>> sorted(PG.edges(sort=True))
        [(1, 3, None),
         (1, 4, None),
         (1, 5, None),
         (2, 3, None),
         (2, 5, None),
         (3, 4, None),
         (3, 5, None)]

        >>> PG = graphs.PermutationGraph(Permutation([Integer(1),Integer(3),Integer(2)]), Permutation([Integer(1),Integer(2),Integer(3)]))
        >>> sorted(PG.edges(sort=True))
        [(2, 3, None)]

        >>> graphs.PermutationGraph([]).edges(sort=True)
        []
        >>> graphs.PermutationGraph([], []).edges(sort=True)
        []

        >>> PG = graphs.PermutationGraph("graph", "phrag")
        >>> sorted(PG.edges(sort=True))
        [('a', 'g', None),
         ('a', 'h', None),
         ('a', 'p', None),
         ('g', 'h', None),
         ('g', 'p', None),
         ('g', 'r', None),
         ('h', 'r', None),
         ('p', 'r', None)]

  static PetersenGraph()

    Return the Petersen Graph.

    The Petersen Graph is a named graph that consists of 10 vertices and 15 edges, usually drawn as a five-point star embedded in a pentagon.

    The Petersen Graph is a common counterexample. For example, it is not Hamiltonian.

    PLOTTING: See the plotting section for the generalized Petersen graphs.

    EXAMPLES: We compare below the Petersen graph with the default spring-layout versus a planned position dictionary of \((x, y)\) tuples:

    Sage

        sage: petersen_spring = Graph({0:[1,4,5], 1:[0,2,6], 2:[1,3,7],
        ....:                          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                             # needs sage.plot
        sage: petersen_database = graphs.PetersenGraph()
        sage: petersen_database.show()          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> petersen_spring = Graph({Integer(0):[Integer(1),Integer(4),Integer(5)], Integer(1):[Integer(0),Integer(2),Integer(6)], Integer(2):[Integer(1),Integer(3),Integer(7)],
        ...                          Integer(3):[Integer(2),Integer(4),Integer(8)], Integer(4):[Integer(0),Integer(3),Integer(9)], Integer(5):[Integer(0),Integer(7),Integer(8)],
        ...                          Integer(6):[Integer(1),Integer(8),Integer(9)], Integer(7):[Integer(2),Integer(5),Integer(9)], Integer(8):[Integer(3),Integer(5),Integer(6)],
        ...                          Integer(9):[Integer(4),Integer(6),Integer(7)]})
        >>> petersen_spring.show()            # long time                             # needs sage.plot
        >>> petersen_database = graphs.PetersenGraph()
        >>> petersen_database.show()          # long time                             # needs sage.plot

  static PoussinGraph()

    Return the Poussin Graph.

    For more information on the Poussin Graph, see its corresponding Wolfram page.

    EXAMPLES:

    Sage

        sage: g = graphs.PoussinGraph()
        sage: g.order()
        15
        sage: g.is_planar()
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.PoussinGraph()
        >>> g.order()
        15
        >>> g.is_planar()
        True

  static QueenGraph(dim_list, radius=None, relabel=False)

    Return the \(d\)-dimensional Queen Graph with prescribed dimensions.

    The 2-dimensional Queen Graph of parameters \(n\) and \(m\) is a graph with \(nm\) vertices in which each vertex represents a square in an \(n \times m\) chessboard, and each edge corresponds to a legal move by a queen.

    The \(d\)-dimensional Queen Graph with \(d >= 2\) has for vertex set the cells of a \(d\)-dimensional grid with prescribed dimensions, and each edge corresponds to a legal move by a queen in either one or two dimensions.

    All 2-dimensional Queen Graphs are Hamiltonian and biconnected. The chromatic number of a \((n,n)\)-Queen Graph is at least \(n\), and it is exactly \(n\) when \(n\equiv 1,5 \bmod{6}\).

    INPUT:

    - `dim_list` – iterable (list, set, dict); provides the dimensions \(n_1, n_2, \ldots, n_d\), with \(n_i \geq 1\), of the chessboard

    - `radius` – integer (default: `None`); by setting the radius to a positive integer, one may reduce the visibility of the queen to at most `radius` steps. When radius is 1, the resulting graph is a King Graph.

    - `relabel` – boolean (default: `False`); indicates whether the vertices must be relabeled as integers

    EXAMPLES:

    The \((2,2)\)-Queen Graph is isomorphic to the complete graph on 4 vertices:

    Sage

        sage: G = graphs.QueenGraph([2, 2])
        sage: G.is_isomorphic(graphs.CompleteGraph(4))
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.QueenGraph([Integer(2), Integer(2)])
        >>> G.is_isomorphic(graphs.CompleteGraph(Integer(4)))
        True

    The Queen Graph with radius 1 is isomorphic to the King Graph:

    Sage

        sage: G = graphs.QueenGraph([4, 5], radius=1)
        sage: H = graphs.KingGraph([5, 4])
        sage: G.is_isomorphic(H)
        True

    [Python]

        >>> from sage.all import *
        >>> G = graphs.QueenGraph([Integer(4), Integer(5)], radius=Integer(1))
        >>> H = graphs.KingGraph([Integer(5), Integer(4)])
        >>> G.is_isomorphic(H)
        True

    Also `True` in higher dimensions:

    Sage

        sage: G = graphs.QueenGraph([3, 4, 5], radius=1)
        sage: H = graphs.KingGraph([5, 3, 4])
        sage: G.is_isomorphic(H)
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.QueenGraph([Integer(3), Integer(4), Integer(5)], radius=Integer(1))
        >>> H = graphs.KingGraph([Integer(5), Integer(3), Integer(4)])
        >>> G.is_isomorphic(H)
        True

    The Queen Graph can be obtained from the Rook Graph and the Bishop Graph:

    Sage

        sage: for d in range(3,12):   # long time
        ....:     for r in range(1,d+1):
        ....:         G = graphs.QueenGraph([d,d],radius=r)
        ....:         H = graphs.RookGraph([d,d],radius=r)
        ....:         B = graphs.BishopGraph([d,d],radius=r)
        ....:         H.add_edges(B.edges(sort=False))
        ....:         if not G.is_isomorphic(H):
        ....:             print("that's not good!")

    [Python]

        >>> from sage.all import *
        >>> for d in range(Integer(3),Integer(12)):   # long time
        ...     for r in range(Integer(1),d+Integer(1)):
        ...         G = graphs.QueenGraph([d,d],radius=r)
        ...         H = graphs.RookGraph([d,d],radius=r)
        ...         B = graphs.BishopGraph([d,d],radius=r)
        ...         H.add_edges(B.edges(sort=False))
        ...         if not G.is_isomorphic(H):
        ...             print("that's not good!")

  static RandomBarabasiAlbert(n, m, seed=None)

    Return a random graph created using the Barabasi-Albert preferential attachment model.

    A graph with \(m\) vertices and no edges is initialized, and a graph of \(n\) vertices is grown by attaching new vertices each with \(m\) edges that are attached to existing vertices, preferentially with high degree.

    INPUT:

    - `n` – number of vertices in the graph

    - `m` – number of edges to attach from each new node

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    We show the edge list of a random graph on 6 nodes with \(m = 2\):

    Sage

        sage: G = graphs.RandomBarabasiAlbert(6,2)                                      # needs networkx
        sage: G.order(), G.size()                                                       # needs networkx
        (6, 8)
        sage: G.degree_sequence()  # random                                             # needs networkx
        [4, 3, 3, 2, 2, 2]

    Python

        >>> from sage.all import *
        >>> G = graphs.RandomBarabasiAlbert(Integer(6),Integer(2))                                      # needs networkx
        >>> G.order(), G.size()                                                       # needs networkx
        (6, 8)
        >>> G.degree_sequence()  # random                                             # needs networkx
        [4, 3, 3, 2, 2, 2]

    We plot a random graph on 12 nodes with \(m = 3\):

    Sage

        sage: ba = graphs.RandomBarabasiAlbert(12,3)                                    # needs networkx
        sage: ba.show()                         # long time                             # needs networkx sage.plot

    [Python]

        >>> from sage.all import *
        >>> ba = graphs.RandomBarabasiAlbert(Integer(12),Integer(3))                                    # needs networkx
        >>> ba.show()                         # long time                             # needs networkx sage.plot

    We view many random graphs using a graphics array:

    Sage

        sage: # needs networkx sage.plot
        sage: g = []
        sage: j = []
        sage: for i in range(1,10):
        ....:     k = graphs.RandomBarabasiAlbert(i+3, 3)
        ....:     g.append(k)
        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)
        sage: G.show()                          # long time

    Python

        >>> from sage.all import *
        >>> # needs networkx sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(1),Integer(10)):
        ...     k = graphs.RandomBarabasiAlbert(i+Integer(3), Integer(3))
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    When \(m = 1\), the generated graph is a tree:

    Sage

        sage: graphs.RandomBarabasiAlbert(6, 1).is_tree()                               # needs networkx
        True

    [Python]

        >>> from sage.all import *
        >>> graphs.RandomBarabasiAlbert(Integer(6), Integer(1)).is_tree()                               # needs networkx
        True

  static RandomBicubicPlanar(n, seed=None)

    Return the graph of a random bipartite cubic map with \(3 n\) edges.

    INPUT:

    - `n` – integer (at least \(1\))

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    OUTPUT:

    a graph with multiple edges (no embedding is provided)

    The algorithm used is described in [Sch1999]. This samples a random rooted bipartite cubic map, chosen uniformly at random.

    First one creates a random binary tree with \(n\) vertices. Next one turns this into a blossoming tree (at random) and reads the contour word of this blossoming tree.

    Then one performs a rotation on this word so that this becomes a balanced word. There are three ways to do that, one is picked at random. Then a graph is build from the balanced word by iterated closure (adding edges).

    In the returned graph, the three edges incident to any given vertex are colored by the integers 0, 1 and 2.

    See also

    the auxiliary method `blossoming_contour()`

    EXAMPLES:

    Sage

        sage: # needs sage.combinat
        sage: n = randint(200, 300)
        sage: G = graphs.RandomBicubicPlanar(n)
        sage: G.order() == 2*n
        True
        sage: G.size() == 3*n
        True
        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'],
        ....:        '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.plot
        Graphics object consisting of ... graphics primitives

    Python

        >>> from sage.all import *
        >>> # needs sage.combinat
        >>> n = randint(Integer(200), Integer(300))
        >>> G = graphs.RandomBicubicPlanar(n)
        >>> G.order() == Integer(2)*n
        True
        >>> G.size() == Integer(3)*n
        True
        >>> G.is_bipartite() and G.is_planar() and G.is_regular(Integer(3))
        True
        >>> dic = {'red': [v for v in G.vertices(sort=False) if v[Integer(0)] == 'n'],
        ...        'blue': [v for v in G.vertices(sort=False) if v[Integer(0)] != 'n']}
        >>> G.plot(vertex_labels=False, vertex_size=Integer(20), vertex_colors=dic)            # needs sage.plot
        Graphics object consisting of ... graphics primitives

  static RandomBipartite(n1, n2, p, set_position=False, seed=None)

    Return a bipartite graph with \(n1+n2\) vertices such that any edge from \([n1]\) to \([n2]\) exists with probability \(p\).

    INPUT:

    - `n1`, `n2` – cardinalities of the two sets

    - `p` – probability for an edge to exist

    - `set_position` – boolean (default: `False`); if set to `True`, we assign positions to the vertices so that the set of cardinality \(n1\) is on the line \(y=1\) and the set of cardinality \(n2\) is on the line \(y=0\)

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    Sage

        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)]

    Python

        >>> from sage.all import *
        >>> g = graphs.RandomBipartite(Integer(5), Integer(2), RealNumber('0.5'))                                     # needs numpy
        >>> g.vertices(sort=True)                                                     # needs numpy
        [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1)]

  static RandomBlockGraph(m, k, kmax=None, incidence_structure=False, seed=None)

    Return a Random Block Graph.

    A block graph is a connected graph in which every biconnected component (block) is a clique.

    See also

    - Wikipedia article Block_graph for more details on these graphs

    - `is_block_graph()` – test if a graph is a block graph

    - `blocks_and_cut_vertices()`

    - `blocks_and_cuts_tree()`

    - `IncidenceStructure()`

    INPUT:

    - `m` – integer; number of blocks (at least one)

    - `k` – integer; minimum number of vertices of a block (at least two)

    - `kmax` – integer (default: `None`); by default, each block has \(k\) vertices. When the parameter \(kmax\) is specified (with \(kmax \geq k\)), the number of vertices of each block is randomly chosen between \(k\) and \(kmax\).

    - `incidence_structure` – boolean (default: `False`); when set to `True`, the incidence structure of the graphs is returned instead of the graph itself, that is the list of the lists of vertices in each block. This is useful for the creation of some hypergraphs.

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    OUTPUT:

    A Graph when `incidence_structure==False` (default), and otherwise an incidence structure.

    EXAMPLES:

    A block graph with a single block is a clique:

    Sage

        sage: B = graphs.RandomBlockGraph(1, 4)
        sage: B.is_clique()
        True

    Python

        >>> from sage.all import *
        >>> B = graphs.RandomBlockGraph(Integer(1), Integer(4))
        >>> B.is_clique()
        True

    A block graph with blocks of order 2 is a tree:

    Sage

        sage: B = graphs.RandomBlockGraph(10, 2)
        sage: B.is_tree()
        True

    [Python]

        >>> from sage.all import *
        >>> B = graphs.RandomBlockGraph(Integer(10), Integer(2))
        >>> B.is_tree()
        True

    Every biconnected component of a block graph is a clique:

    Sage

        sage: B = graphs.RandomBlockGraph(5, 3, kmax=6)
        sage: blocks,cuts = B.blocks_and_cut_vertices()
        sage: all(B.is_clique(block) for block in blocks)
        True

    Python

        >>> from sage.all import *
        >>> B = graphs.RandomBlockGraph(Integer(5), Integer(3), kmax=Integer(6))
        >>> blocks,cuts = B.blocks_and_cut_vertices()
        >>> all(B.is_clique(block) for block in blocks)
        True

    A block graph with blocks of order \(k\) has \(m*(k-1)+1\) vertices:

    Sage

        sage: m, k = 6, 4
        sage: B = graphs.RandomBlockGraph(m, k)
        sage: B.order() == m*(k-1)+1
        True

    [Python]

        >>> from sage.all import *
        >>> m, k = Integer(6), Integer(4)
        >>> B = graphs.RandomBlockGraph(m, k)
        >>> B.order() == m*(k-Integer(1))+Integer(1)
        True

    Test recognition methods:

    Sage

        sage: B = graphs.RandomBlockGraph(6, 2, kmax=6)
        sage: B.is_block_graph()
        True
        sage: B in graph_classes.Block
        True

    Python

        >>> from sage.all import *
        >>> B = graphs.RandomBlockGraph(Integer(6), Integer(2), kmax=Integer(6))
        >>> B.is_block_graph()
        True
        >>> B in graph_classes.Block
        True

    Asking for the incidence structure:

    Sage

        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)                                                    # needs sage.modules
        Incidence structure with 19 points and 6 blocks
        sage: m*(k-1)+1
        19

    [Python]

        >>> from sage.all import *
        >>> m, k = Integer(6), Integer(4)
        >>> IS = graphs.RandomBlockGraph(m, k, incidence_structure=True)
        >>> from sage.combinat.designs.incidence_structures import IncidenceStructure
        >>> IncidenceStructure(IS)                                                    # needs sage.modules
        Incidence structure with 19 points and 6 blocks
        >>> m*(k-Integer(1))+Integer(1)
        19

  static RandomBoundedToleranceGraph(n, seed=None)

    Return a random bounded tolerance graph.

    The random tolerance graph is built from a random bounded tolerance representation by using the function \(ToleranceGraph\). This representation is a list \(((l_0,r_0,t_0), (l_1,r_1,t_1), ..., (l_k,r_k,t_k))\) where \(k = n-1\) and \(I_i = (l_i,r_i)\) denotes a random interval and \(t_i\) a random positive value less than or equal to the length of the interval \(I_i\). The width of the representation is limited to \(n^2 * 2^n\).

    Note

    The tolerance representation used to create the graph can be recovered using `get_vertex()` or `get_vertices()`.

    INPUT:

    - `n` – number of vertices of the random graph

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    Every (bounded) tolerance graph is perfect. Hence, the chromatic number is equal to the clique number

    Sage

        sage: g = graphs.RandomBoundedToleranceGraph(8)
        sage: g.clique_number() == g.chromatic_number()
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.RandomBoundedToleranceGraph(Integer(8))
        >>> g.clique_number() == g.chromatic_number()
        True

  static RandomChordalGraph(n, algorithm='growing', k=None, l=None, f=None, s=None, seed=None)

    Return a random chordal graph of order `n`.

    A Graph \(G\) is said to be chordal if it contains no induced hole (a cycle of length at least 4). Equivalently, \(G\) is chordal if it has a perfect elimination orderings, if each minimal separator is a clique, or if it is the intersection graphs of subtrees of a tree. See the Wikipedia article Chordal_graph.

    This generator implements the algorithms proposed in [SHET2018] for generating random chordal graphs as the intersection graph of \(n\) subtrees of a tree of order \(n\).

    The returned graph is not necessarily connected.

    INPUT:

    - `n` – integer; the number of nodes of the graph

    - `algorithm` – string (default: `'growing'`); the choice of the algorithm for randomly selecting \(n\) subtrees of a random tree of order \(n\). Possible choices are:

      - `'growing'` – for each subtree \(T_i\), the algorithm picks a size \(k_i\) randomly from \([1,k]\). Then a random node of \(T\) is chosen as the first node of \(T_i\). In each of the subsequent \(k_i - 1\) iterations, it picks a random node in the neighborhood of \(T_i\) and adds it to \(T_i\).

      - `'connecting'` – for each subtree \(T_i\), it first selects \(k_i\) nodes of \(T\), where \(k_i\) is a random integer from a Poisson distribution with mean \(l\). \(T_i\) is then generated to be the minimal subtree containing the selected \(k_i\) nodes. This implies that a subtree will most likely have many more nodes than those selected initially, and this must be taken into consideration when choosing \(l\).

      - `'pruned'` – for each subtree \(T_i\), it randomly selects a fraction \(f\) of the edges on the tree and removes them. The number of edges to delete, say \(l\), is calculated as \(\lfloor (n - 1) f \rfloor\), which will leave \(l + 1\) subtrees in total. Then, it determines the sizes of the \(l + 1\) subtrees and stores the distinct values. Finally, it picks a random size \(k_i\) from the set of largest \(100(1-s)\%\) of distinct values, and randomly chooses a subtree with size \(k_i\).

    - `k` – integer (default: `None`); maximum size of a subtree. If not specified (`None`), the maximum size is set to \(\sqrt{n}\). This parameter is used only when `algorithm="growing"`. See `growing_subtrees()` for more details.

    - `l` – a strictly positive real number (default: `None`); mean of a Poisson distribution. If not specified, the mean in set to \(\log_2{n}\). This parameter is used only when `algorithm="connecting"`. See `connecting_nodes()` for more details.

    - `f` – a rational number (default: `None`); the edge deletion fraction. This value must be chosen in \([0..1]\). If not specified, this parameter is set to \(\frac{1}{n-1}\). This parameter is used only when `algorithm="pruned"`. See `pruned_tree()` for more details.

    - `s` – a real number between 0 and 1 (default: `None`); selection barrier for the size of trees. If not specified, this parameter is set to \(0.5\). This parameter is used only when `algorithm="pruned"`. See `pruned_tree()` for more details.

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    Sage

        sage: from sage.graphs.generators.random import RandomChordalGraph
        sage: T = RandomChordalGraph(20, algorithm='growing', k=5)
        sage: T.is_chordal()
        True
        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()
        True

    Python

        >>> from sage.all import *
        >>> from sage.graphs.generators.random import RandomChordalGraph
        >>> T = RandomChordalGraph(Integer(20), algorithm='growing', k=Integer(5))
        >>> T.is_chordal()
        True
        >>> T = RandomChordalGraph(Integer(20), algorithm='connecting', l=Integer(3))                   # needs numpy
        >>> T.is_chordal()                                                            # needs numpy
        True
        >>> T = RandomChordalGraph(Integer(20), algorithm='pruned', f=Integer(1)/Integer(3), s=RealNumber('.5'))
        >>> T.is_chordal()
        True

    See also

    - `growing_subtrees()`

    - `connecting_nodes()`

    - `pruned_tree()`

    - Wikipedia article Chordal_graph

    - `is_chordal()`

    - `IntersectionGraph()`

  static RandomGNM(n, m, dense=False, seed=None)

    Return a graph randomly picked out of all graphs on \(n\) vertices with \(m\) edges.

    INPUT:

    - `n` – number of vertices

    - `m` – number of edges

    - `dense` – whether to use NetworkX’s `dense_gnm_random_graph()` or `gnm_random_graph()`

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    We show the edge list of a random graph on 5 nodes with 10 edges:

    Sage

        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)]

    Python

        >>> from sage.all import *
        >>> graphs.RandomGNM(Integer(5), Integer(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 and 12 edges:

    Sage

        sage: gnm = graphs.RandomGNM(12, 12)                                            # needs networkx
        sage: gnm.show()                        # long time                             # needs networkx sage.plot

    [Python]

        >>> from sage.all import *
        >>> gnm = graphs.RandomGNM(Integer(12), Integer(12))                                            # needs networkx
        >>> gnm.show()                        # long time                             # needs networkx sage.plot

    We view many random graphs using a graphics array:

    Sage

        sage: # needs networkx sage.plot
        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     k = graphs.RandomGNM(i+3, i^2-i)
        ....:     g.append(k)
        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)
        sage: G.show()                          # long time

    Python

        >>> from sage.all import *
        >>> # needs networkx sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     k = graphs.RandomGNM(i+Integer(3), i**Integer(2)-i)
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

  static RandomGNP(n, p, seed=None, fast=True, algorithm='Sage')

    Return a random graph on \(n\) nodes. Each edge is inserted independently with probability \(p\).

    INPUT:

    - `n` – number of nodes of the graph

    - `p` – probability of an edge

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    - `fast` – boolean (default: `True`) to use the algorithm with time complexity in \(O(n+m)\) proposed in [BB2005a]. It is designed for generating large sparse graphs. It is faster than other algorithms for LARGE instances (try it to know whether it is useful for you).

    - `algorithm` – (default: `'Sage'`) this function uses the algorithm implemented in `sage.graphs.graph_generators_pyx.pyx`. When `algorithm='networkx'`, this function calls the NetworkX function `fast_gnp_random_graph`, unless `fast=False`, then `gnp_random_graph`. Try them to know which algorithm is the best for you. The `fast` parameter is not taken into account by the ‘Sage’ algorithm so far.

    REFERENCES:

    - [ER1959]

    - [Gil1959]

    PLOTTING: When plotting, this graph will use the default spring-layout algorithm, unless a position dictionary is specified.

    EXAMPLES: We show the edge list of a random graph on 6 nodes with probability \(p = .4\):

    Sage

        sage: set_random_seed(0)
        sage: graphs.RandomGNP(6, .4).edges(sort=true, labels=False)
        [(0, 3), (1, 2), (2, 3), (2, 4)]

    Python

        >>> from sage.all import *
        >>> set_random_seed(Integer(0))
        >>> graphs.RandomGNP(Integer(6), RealNumber('.4')).edges(sort=true, labels=False)
        [(0, 3), (1, 2), (2, 3), (2, 4)]

    We plot a random graph on 12 nodes with probability \(p = .71\):

    Sage

        sage: gnp = graphs.RandomGNP(12,.71)
        sage: gnp.show()                        # long time                             # needs sage.plot

    [Python]

        >>> from sage.all import *
        >>> gnp = graphs.RandomGNP(Integer(12),RealNumber('.71'))
        >>> gnp.show()                        # long time                             # needs sage.plot

    We view many random graphs using a graphics array:

    Sage

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     k = graphs.RandomGNP(i+3,.43)
        ....:     g.append(k)
        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)                                                     # needs sage.plot
        sage: G.show()                          # long time                             # needs sage.plot
        sage: graphs.RandomGNP(4,1)
        Complete graph: Graph on 4 vertices

    Python

        >>> from sage.all import *
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     k = graphs.RandomGNP(i+Integer(3),RealNumber('.43'))
        ...     g.append(k)
        >>> for i in range(Integer(3)):                                                        # needs sage.plot
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)                                                     # needs sage.plot
        >>> G.show()                          # long time                             # needs sage.plot
        >>> graphs.RandomGNP(Integer(4),Integer(1))
        Complete graph: Graph on 4 vertices

  static RandomHolmeKim(n, m, p, seed=None)

    Return a random graph generated by the Holme and Kim algorithm for graphs with power law degree distribution and approximate average clustering.

    INPUT:

    - `n` – number of vertices

    - `m` – number of random edges to add for each new node

    - `p` – probability of adding a triangle after adding a random edge

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    From the NetworkX documentation: the average clustering has a hard time getting above a certain cutoff that depends on \(m\). This cutoff is often quite low. Note that the transitivity (fraction of triangles to possible triangles) seems to go down with network size. It is essentially the Barabasi-Albert growth model with an extra step that each random edge is followed by a chance of making an edge to one of its neighbors too (and thus a triangle). This algorithm improves on B-A in the sense that it enables a higher average clustering to be attained if desired. It seems possible to have a disconnected graph with this algorithm since the initial \(m\) nodes may not be all linked to a new node on the first iteration like the BA model.

    EXAMPLES:

    Sage

        sage: G = graphs.RandomHolmeKim(12, 3, .3)                                      # needs networkx
        sage: G.show()                          # long time                             # needs networkx sage.plot

    Python

        >>> from sage.all import *
        >>> G = graphs.RandomHolmeKim(Integer(12), Integer(3), RealNumber('.3'))                                      # needs networkx
        >>> G.show()                          # long time                             # needs networkx sage.plot

    REFERENCE:

    [HK2002a]

  static RandomIntervalGraph(n, seed=None)

    Return a random interval graph.

    An interval graph is built from a list \((a_i,b_i)_{1\leq i \leq n}\) of intervals : to each interval of the list is associated one vertex, two vertices being adjacent if the two corresponding intervals intersect.

    A random interval graph of order \(n\) is generated by picking random values for the \((a_i,b_j)\), each of the two coordinates being generated from the uniform distribution on the interval \([0,1]\).

    This definitions follows [BF2001].

    Note

    The vertices are named 0, 1, 2, and so on. The intervals used to create the graph are saved with the graph and can be recovered using `get_vertex()` or `get_vertices()`.

    See also

    - `sage.graphs.generators.intersection.IntervalGraph()`

    - `sage.graphs.generators.random.RandomProperIntervalGraph()`

    INPUT:

    - `n` – integer; the number of vertices in the random graph

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    As for any interval graph, the chromatic number is equal to the clique number

    Sage

        sage: g = graphs.RandomIntervalGraph(8)
        sage: g.clique_number() == g.chromatic_number()
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.RandomIntervalGraph(Integer(8))
        >>> g.clique_number() == g.chromatic_number()
        True

  static RandomKTree(n, k, seed=None)

    Return a random \(k\)-tree on \(n\) nodes numbered \(0\) through \(n-1\).

    ALGORITHM:

    The algorithm first generates a complete graph on \(k + 1\) vertices. Vertices are subsequently generated by randomly choosing one of the existing cliques in the graph, and creating a new clique by replacing one of the vertices in the selected clique with a newly created one.

    INPUT:

    - `n` – number of vertices in the \(k\)-tree

    - `k` – within a clique each vertex is connected to \(k\) vertices. \(k\) also corresponds to the treewidth of the \(k\)-tree

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    Sage

        sage: G = graphs.RandomKTree(50, 5)
        sage: G.treewidth()
        5
        sage: G.show()  # not tested

    Python

        >>> from sage.all import *
        >>> G = graphs.RandomKTree(Integer(50), Integer(5))
        >>> G.treewidth()
        5
        >>> G.show()  # not tested

  static RandomLobster(n, p, q, seed=None)

    Return a random lobster.

    A lobster is a tree that reduces to a caterpillar when pruning all leaf vertices. A caterpillar is a tree that reduces to a path when pruning all leaf vertices (\(q=0\)).

    INPUT:

    - `n` – expected number of vertices in the backbone

    - `p` – probability of adding an edge to the backbone

    - `q` – probability of adding an edge (claw) to the arms

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    We check a random graph with 12 backbone nodes and probabilities \(p = 0.7\) and \(q = 0.3\):

    Sage

        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.n_vertices() == 1:
        ....:         assert s == [0]
        ....:     else:
        ....:         assert s[-2:] == [1, 1]
        ....:     assert all(d == 2 for d in s[:-2])

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> G = graphs.RandomLobster(Integer(12), RealNumber('0.7'), RealNumber('0.3'))
        >>> leaves = [v for v in G.vertices(sort=False) if G.degree(v) == Integer(1)]
        >>> G.delete_vertices(leaves)                                 # caterpillar
        >>> leaves = [v for v in G.vertices(sort=False) if G.degree(v) == Integer(1)]
        >>> G.delete_vertices(leaves)                                 # path
        >>> s = G.degree_sequence()
        >>> if G:
        ...     if G.n_vertices() == Integer(1):
        ...         assert s == [Integer(0)]
        ...     else:
        ...         assert s[-Integer(2):] == [Integer(1), Integer(1)]
        ...     assert all(d == Integer(2) for d in s[:-Integer(2)])

    Sage

        sage: G = graphs.RandomLobster(9, .6, .3)                                       # needs networkx
        sage: G.show()                          # long time                             # needs networkx sage.plot

    [Python]

        >>> from sage.all import *
        >>> G = graphs.RandomLobster(Integer(9), RealNumber('.6'), RealNumber('.3'))                                       # needs networkx
        >>> G.show()                          # long time                             # needs networkx sage.plot

  static RandomNewmanWattsStrogatz(n, k, p, seed=None)

    Return a Newman-Watts-Strogatz small world random graph on \(n\) vertices.

    From the NetworkX documentation: first create a ring over \(n\) nodes. Then each node in the ring is connected with its \(k\) nearest neighbors. Then shortcuts are created by adding new edges as follows: for each edge \(u-v\) in the underlying “\(n\)-ring with \(k\) nearest neighbors”; with probability \(p\) add a new edge \(u-w\) with randomly-chosen existing node \(w\). In contrast with `networkx.watts_strogatz_graph()`, no edges are removed.

    INPUT:

    - `n` – number of vertices

    - `k` – each vertex is connected to its \(k\) nearest neighbors

    - `p` – the probability of adding a new edge for each edge

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    We check that the generated graph contains a cycle of order \(n\):

    Sage

        sage: # needs networkx
        sage: G = graphs.RandomNewmanWattsStrogatz(7, 2, 0.2)
        sage: G.order()
        7
        sage: C7 = graphs.CycleGraph(7)
        sage: G.subgraph_search(C7)
        Subgraph of (): Graph on 7 vertices
        sage: G.diameter() <= C7.diameter()
        True

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> G = graphs.RandomNewmanWattsStrogatz(Integer(7), Integer(2), RealNumber('0.2'))
        >>> G.order()
        7
        >>> C7 = graphs.CycleGraph(Integer(7))
        >>> G.subgraph_search(C7)
        Subgraph of (): Graph on 7 vertices
        >>> G.diameter() <= C7.diameter()
        True

    Sage

        sage: G = graphs.RandomNewmanWattsStrogatz(12, 2, .3)                           # needs networkx
        sage: G.show()                          # long time                             # needs networkx sage.plot

    [Python]

        >>> from sage.all import *
        >>> G = graphs.RandomNewmanWattsStrogatz(Integer(12), Integer(2), RealNumber('.3'))                           # needs networkx
        >>> G.show()                          # long time                             # needs networkx sage.plot

    REFERENCE:

    [NWS2002]

  static RandomPartialKTree(n, k, x, seed=None)

    Return a random partial \(k\)-tree on \(n\) nodes.

    A partial \(k\)-tree is defined as a subgraph of a \(k\)-tree. This can also be described as a graph with treewidth at most \(k\).

    INPUT:

    - `n` – number of vertices in the \(k\)-tree

    - `k` – within a clique each vertex is connected to \(k\) vertices. \(k\) also corresponds to the treewidth of the \(k\)-tree

    - `x` – how many edges are deleted from the \(k\)-tree

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    Sage

        sage: G = graphs.RandomPartialKTree(50,5,2)
        sage: G.treewidth()
        5
        sage: G.show()  # not tested

    Python

        >>> from sage.all import *
        >>> G = graphs.RandomPartialKTree(Integer(50),Integer(5),Integer(2))
        >>> G.treewidth()
        5
        >>> G.show()  # not tested

  static RandomProperIntervalGraph(n, seed=None)

    Return a random proper interval graph.

    An interval graph is built from a list \((a_i,b_i)_{1\leq i \leq n}\) of intervals : to each interval of the list is associated one vertex, two vertices being adjacent if the two corresponding (closed) intervals intersect. An interval graph is proper if no interval of the list properly contains another interval. Observe that proper interval graphs coincide with unit interval graphs. See the Wikipedia article Interval_graph for more details.

    This method implements the random proper interval graph generator proposed in [SYKU2010] which outputs graphs with uniform probability. The time complexity of this generator is in \(O(n^3)\).

    Note

    The vertices are named 0, 1, 2, and so on. The intervals used to create the graph are saved with the graph and can be recovered using `get_vertex()` or `get_vertices()`.

    See also

    - `sage.graphs.generators.intersection.IntervalGraph()`

    - `sage.graphs.generators.random.RandomIntervalGraph()`

    INPUT:

    - `n` – positive integer; the number of vertices of the graph

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    Sage

        sage: from sage.graphs.generators.random import RandomProperIntervalGraph
        sage: G = RandomProperIntervalGraph(10)
        sage: G.is_interval()
        True

    Python

        >>> from sage.all import *
        >>> from sage.graphs.generators.random import RandomProperIntervalGraph
        >>> G = RandomProperIntervalGraph(Integer(10))
        >>> G.is_interval()
        True

  static RandomRegular(d, n, seed=None)

    Return a random \(d\)-regular graph on \(n\) vertices, or `False` on failure.

    Since every edge is incident to two vertices, \(n\times d\) must be even.

    INPUT:

    - `d` – degree

    - `n` – number of vertices

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    We check that a random graph with 8 nodes each of degree 3 is 3-regular:

    Sage

        sage: G = graphs.RandomRegular(3, 8)                                            # needs networkx
        sage: G.is_regular(k=3)                                                         # needs networkx
        True
        sage: G.degree_histogram()                                                      # needs networkx
        [0, 0, 0, 8]

    Python

        >>> from sage.all import *
        >>> G = graphs.RandomRegular(Integer(3), Integer(8))                                            # needs networkx
        >>> G.is_regular(k=Integer(3))                                                         # needs networkx
        True
        >>> G.degree_histogram()                                                      # needs networkx
        [0, 0, 0, 8]

    Sage

        sage: G = graphs.RandomRegular(3, 20)                                           # needs networkx
        sage: if G:                             # random output         # long time, needs networkx sage.plot
        ....:     G.show()

    [Python]

        >>> from sage.all import *
        >>> G = graphs.RandomRegular(Integer(3), Integer(20))                                           # needs networkx
        >>> if G:                             # random output         # long time, needs networkx sage.plot
        ...     G.show()

    REFERENCES:

    - [KV2003]

    - [SW1999]

  static RandomRegularBipartite(n1, n2, d1, set_position=False, seed=None)

    Return a random regular bipartite graph on \(n1 + n2\) vertices.

    The bipartite graph has \(n1 * d1\) edges. Hence, \(n2\) must divide \(n1 * d1\). Each vertex of the set of cardinality \(n1\) has degree \(d1\) (which can be at most \(n2\)) and each vertex in the set of cardinality \(n2\) has degree \((n1 * d1) / n2\). The bipartite graph has no multiple edges.

    This generator implements an algorithm inspired by that of [MW1990] for the uniform generation of random regular bipartite graphs. It performs well when \(d1 = o(n2^{1/3})\) or (\(n2 - d1 = o(n2^{1/3})\)). In other cases, the running time can be huge. Note that the currently implemented algorithm does not generate uniformly random graphs.

    INPUT:

    - `n1`, `n2` – number of vertices in each side

    - `d1` – degree of the vertices in the set of cardinality \(n1\)

    - `set_position` – boolean (default: `False`); if set to `True`, we assign positions to the vertices so that the set of cardinality \(n1\) is on the line \(y=1\) and the set of cardinality \(n2\) is on the line \(y=0\).

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    Sage

        sage: g = graphs.RandomRegularBipartite(4, 6, 3)
        sage: g.order(), g.size()
        (10, 12)
        sage: set(g.degree())
        {2, 3}

        sage: graphs.RandomRegularBipartite(1, 2, 2, set_position=True).get_pos()
        {0: (1, 1.0), 1: (0, 0), 2: (2.0, 0.0)}
        sage: graphs.RandomRegularBipartite(2, 1, 1, set_position=True).get_pos()
        {0: (0, 1), 1: (2.0, 1.0), 2: (1, 0.0)}
        sage: graphs.RandomRegularBipartite(2, 3, 3, set_position=True).get_pos()
        {0: (0, 1), 1: (3.0, 1.0), 2: (0, 0), 3: (1.5, 0.0), 4: (3.0, 0.0)}
        sage: graphs.RandomRegularBipartite(2, 3, 3, set_position=False).get_pos()

    Python

        >>> from sage.all import *
        >>> g = graphs.RandomRegularBipartite(Integer(4), Integer(6), Integer(3))
        >>> g.order(), g.size()
        (10, 12)
        >>> set(g.degree())
        {2, 3}

        >>> graphs.RandomRegularBipartite(Integer(1), Integer(2), Integer(2), set_position=True).get_pos()
        {0: (1, 1.0), 1: (0, 0), 2: (2.0, 0.0)}
        >>> graphs.RandomRegularBipartite(Integer(2), Integer(1), Integer(1), set_position=True).get_pos()
        {0: (0, 1), 1: (2.0, 1.0), 2: (1, 0.0)}
        >>> graphs.RandomRegularBipartite(Integer(2), Integer(3), Integer(3), set_position=True).get_pos()
        {0: (0, 1), 1: (3.0, 1.0), 2: (0, 0), 3: (1.5, 0.0), 4: (3.0, 0.0)}
        >>> graphs.RandomRegularBipartite(Integer(2), Integer(3), Integer(3), set_position=False).get_pos()

  static RandomShell(constructor, seed=None)

    Return a random shell graph for the constructor given.

    INPUT:

    - `constructor` – list of 3-tuples \((n, m, d)\), each representing a shell, where:

      - `n` – the number of vertices in the shell

      - `m` – the number of edges in the shell

      - `d` – the ratio of inter (next) shell edges to intra shell edges

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    Sage

        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                             # needs networkx sage.plot

    Python

        >>> from sage.all import *
        >>> G = graphs.RandomShell([(Integer(10),Integer(20),RealNumber('0.8')),(Integer(20),Integer(40),RealNumber('0.8'))])                         # needs networkx
        >>> G.order(), G.size()                                                       # needs networkx
        (30, 52)
        >>> G.show()                          # long time                             # needs networkx sage.plot

  static RandomToleranceGraph(n, seed=None)

    Return a random tolerance graph.

    The random tolerance graph is built from a random tolerance representation by using the function `ToleranceGraph()`. This representation is a list \(((l_0,r_0,t_0), (l_1,r_1,t_1), ..., (l_k,r_k,t_k))\) where \(k = n-1\) and \(I_i = (l_i,r_i)\) denotes a random interval and \(t_i\) a random positive value. The width of the representation is limited to \(n^2 * 2^n\).

    Note

    The vertices are named \(0, 1, \cdots, n-1\). The tolerance representation used to create the graph is saved with the graph and can be recovered using `get_vertex()` or `get_vertices()`.

    INPUT:

    - `n` – number of vertices of the random graph

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    Every tolerance graph is perfect. Hence, the chromatic number is equal to the clique number

    Sage

        sage: g = graphs.RandomToleranceGraph(8)
        sage: g.clique_number() == g.chromatic_number()
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.RandomToleranceGraph(Integer(8))
        >>> g.clique_number() == g.chromatic_number()
        True

  static RandomTree(n, seed=None)

    Return a random tree on \(n\) nodes numbered \(0\) through \(n-1\).

    By Cayley’s theorem, there are \(n^{n-2}\) trees with vertex set \(\{0,1,\dots,n-1\}\). This constructor chooses one of these uniformly at random.

    ALGORITHM:

    The algorithm works by generating an \((n-2)\)-long random sequence of numbers chosen independently and uniformly from \(\{0,1,\dots,n-1\}\) and then applies an inverse Prufer transformation.

    INPUT:

    - `n` – number of vertices in the tree

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    Sage

        sage: G = graphs.RandomTree(10)
        sage: G.is_tree()
        True
        sage: G.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> G = graphs.RandomTree(Integer(10))
        >>> G.is_tree()
        True
        >>> G.show()                          # long time                             # needs sage.plot

  static RandomTreePowerlaw(n, gamma=3, tries=1000, seed=None)

    Return a tree with a power law degree distribution, or `False` on failure.

    From the NetworkX documentation: a trial power law degree sequence is chosen and then elements are swapped with new elements from a power law distribution until the sequence makes a tree (size = order - 1).

    INPUT:

    - `n` – number of vertices

    - `gamma` – exponent of power law distribution

    - `tries` – number of attempts to adjust sequence to make a tree

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    EXAMPLES:

    We check that the generated graph is a tree:

    Sage

        sage: G = graphs.RandomTreePowerlaw(10, 3)                                      # needs networkx
        sage: G.is_tree()                                                               # needs networkx
        True
        sage: G.order(), G.size()                                                       # needs networkx
        (10, 9)

    Python

        >>> from sage.all import *
        >>> G = graphs.RandomTreePowerlaw(Integer(10), Integer(3))                                      # needs networkx
        >>> G.is_tree()                                                               # needs networkx
        True
        >>> G.order(), G.size()                                                       # needs networkx
        (10, 9)

    Sage

        sage: G = graphs.RandomTreePowerlaw(15, 2)                                      # needs networkx
        sage: if G:                             # random output         # long time, needs networkx sage.plot
        ....:     G.show()

    [Python]

        >>> from sage.all import *
        >>> G = graphs.RandomTreePowerlaw(Integer(15), Integer(2))                                      # needs networkx
        >>> if G:                             # random output         # long time, needs networkx sage.plot
        ...     G.show()

  static RandomTriangulation(n, set_position=False, k=3, seed=None)

    Return a random inner triangulation of an outer face of degree `k` with `n` vertices in total.

    An inner triangulation is a plane graph all of whose faces (except the outer/unbounded face) are triangles (3-cycles).

    INPUT:

    - `n` – the number of vertices of the graph

    - `k` – the size of the outer face

    - `set_position` – boolean (default: `False`); if set to `True`, this will compute coordinates for a planar drawing of the graph

    - `seed` – a `random.Random` seed or a Python `int` for the random number generator (default: `None`)

    OUTPUT:

    A random graph chosen uniformly among the inner triangulations of a rooted \(k\)-gon with \(n\) vertices (including the \(k\) vertices from the outer face). This is a planar graph and comes with a combinatorial embedding. The vertices of the root edge are labelled `-1` and `-2` and the outer face is the face returned by `Graph.faces()` in which `-1` and `-2` are consecutive vertices in this order.

    Because some triangulations have nontrivial automorphism groups, this may not be equal to the uniform distribution among inner triangulations of unrooted \(k\)-gons.

    ALGORITHM:

    The algorithm is taken from [PS2006], Section 5.

    Starting from a planar \(k\)-gonal forest (represented by its contour as a sequence of vertices), one performs local closures, until no one is possible. A local closure amounts to replace in the cyclic contour word a sequence `in1, in2, in3, lf, in3` by `in1, in3`.

    At every step of the algorithm, newly created edges are recorded in a graph, which will be returned at the end. The combinatorial embedding is also computed and recorded in the output graph.

    See also

    `triangulations()`, `RandomTwoSphere()`.

    EXAMPLES:

    Sage

        sage: G = graphs.RandomTriangulation(6, True); G
        Graph on 6 vertices
        sage: G.is_planar()
        True
        sage: G.girth()
        3
        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)
        sage: sorted(len(f) for f in H.faces())
        [3, 3, 3, 3, 3, 3, 3, 5]

    Python

        >>> from sage.all import *
        >>> G = graphs.RandomTriangulation(Integer(6), True); G
        Graph on 6 vertices
        >>> G.is_planar()
        True
        >>> G.girth()
        3
        >>> G.plot(vertex_size=Integer(0), vertex_labels=False)                                # needs sage.plot
        Graphics object consisting of 13 graphics primitives

        >>> H = graphs.RandomTriangulation(Integer(7), k=Integer(5))
        >>> sorted(len(f) for f in H.faces())
        [3, 3, 3, 3, 3, 3, 3, 5]

  static RandomUnitDiskGraph(n, radius=0.1, side=1, seed=None)

    Return a random unit disk graph of order \(n\).

    A unit disk graph is the intersection graph of a family of unit disks in the Euclidean plane. That is a graph with one vertex per disk of the family and an edge between two vertices whenever they lie within a unit distance of each other. See the Wikipedia article Unit_disk_graph for more details.

    INPUT:

    - `n` – number of nodes

    - `radius` – float (default: \(0.1\)); two vertices at distance less than `radius` are connected by an edge

    - `side` – float (default: `1`); indicate the side of the area in which the points are drawn

    - `seed` – seed of the random number generator

    EXAMPLES:

    When using twice the same seed, the vertices get the same positions:

    Sage

        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)
        sage: H = graphs.RandomUnitDiskGraph(20, radius=.2, side=1, seed=seed)
        sage: H.is_subgraph(G, induced=False)
        True
        sage: H.size() <= G.size()
        True
        sage: Gpos = G.get_pos()
        sage: Hpos = H.get_pos()
        sage: all(Gpos[u] == Hpos[u] for u in G)
        True

    Python

        >>> from sage.all import *
        >>> # needs scipy
        >>> from sage.misc.randstate import current_randstate
        >>> seed = current_randstate().seed()
        >>> G = graphs.RandomUnitDiskGraph(Integer(20), radius=RealNumber('.5'), side=Integer(1), seed=seed)
        >>> H = graphs.RandomUnitDiskGraph(Integer(20), radius=RealNumber('.2'), side=Integer(1), seed=seed)
        >>> H.is_subgraph(G, induced=False)
        True
        >>> H.size() <= G.size()
        True
        >>> Gpos = G.get_pos()
        >>> Hpos = H.get_pos()
        >>> 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:

    Sage

        sage: G = graphs.RandomUnitDiskGraph(10, radius=2, side=1)                      # needs scipy
        sage: G.is_clique()                                                             # needs scipy
        True

    [Python]

        >>> from sage.all import *
        >>> G = graphs.RandomUnitDiskGraph(Integer(10), radius=Integer(2), side=Integer(1))                      # needs scipy
        >>> G.is_clique()                                                             # needs scipy
        True

  static RingedTree(k, vertex_labels=True)

    Return the ringed tree on k-levels.

    A ringed tree of level \(k\) is a binary tree with \(k\) levels (counting the root as a level), in which all vertices at the same level are connected by a ring.

    More precisely, in each layer of the binary tree (i.e. a layer is the set of vertices \([2^i...2^{i+1}-1]\)) two vertices \(u,v\) are adjacent if \(u=v+1\) or if \(u=2^i\) and \(v=2^{i+1}-1\).

    Ringed trees are defined in [CFHM2013].

    INPUT:

    - `k` – the number of levels of the ringed tree

    - `vertex_labels` – boolean; whether to label vertices as binary words (default) or as integers

    EXAMPLES:

    Sage

        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',
         '111', '1110', '1111']

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> G = graphs.RingedTree(Integer(5))
        >>> P = G.plot(vertex_labels=False, vertex_size=Integer(10))                           # needs sage.plot
        >>> P.show()                          # long time                             # needs sage.plot
        >>> 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',
         '111', '1110', '1111']

  static RobertsonGraph()

    Return the Robertson graph.

    See the Wikipedia article Robertson_graph.

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.RobertsonGraph()
        sage: g.order()
        19
        sage: g.size()
        38
        sage: g.diameter()
        3
        sage: g.girth()
        5
        sage: g.charpoly().factor()
        (x - 4) * (x - 1)^2 * (x^2 + x - 5) * (x^2 + x - 1)
         * (x^2 - 3)^2 * (x^2 + x - 4)^2 * (x^2 + x - 3)^2
        sage: g.chromatic_number()
        3
        sage: g.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        sage: g.is_vertex_transitive()
        False

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.RobertsonGraph()
        >>> g.order()
        19
        >>> g.size()
        38
        >>> g.diameter()
        3
        >>> g.girth()
        5
        >>> 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
        >>> g.chromatic_number()
        3
        >>> g.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        >>> g.is_vertex_transitive()
        False

  static RookGraph(dim_list, radius=None, relabel=False)

    Return the \(d\)-dimensional Rook’s Graph with prescribed dimensions.

    The 2-dimensional Rook’s Graph of parameters \(n\) and \(m\) is a graph with \(nm\) vertices in which each vertex represents a square in an \(n \times m\) chessboard, and each edge corresponds to a legal move by a rook.

    The \(d\)-dimensional Rook Graph with \(d >= 2\) has for vertex set the cells of a \(d\)-dimensional grid with prescribed dimensions, and each edge corresponds to a legal move by a rook in any of the dimensions.

    The Rook’s Graph for an \(n\times m\) chessboard may also be defined as the Cartesian product of two complete graphs \(K_n \square K_m\).

    INPUT:

    - `dim_list` – iterable (list, set, dict); provides the dimensions \(n_1, n_2, \ldots, n_d\), with \(n_i \geq 1\), of the chessboard

    - `radius` – integer (default: `None`); by setting the radius to a positive integer, one may decrease the power of the rook to at most `radius` steps. When the radius is 1, the resulting graph is a \(d\)-dimensional grid.

    - `relabel` – boolean (default: `False`); indicates whether the vertices must be relabeled as integers

    EXAMPLES:

    The \((n,m)\)-Rook’s Graph is isomorphic to the Cartesian product of two complete graphs:

    Sage

        sage: G = graphs.RookGraph( [3, 4] )
        sage: H = ( graphs.CompleteGraph(3) ).cartesian_product( graphs.CompleteGraph(4) )
        sage: G.is_isomorphic( H )
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.RookGraph( [Integer(3), Integer(4)] )
        >>> H = ( graphs.CompleteGraph(Integer(3)) ).cartesian_product( graphs.CompleteGraph(Integer(4)) )
        >>> G.is_isomorphic( H )
        True

    When the radius is 1, the Rook’s Graph is a grid:

    Sage

        sage: G = graphs.RookGraph( [3, 3, 4], radius=1 )
        sage: H = graphs.GridGraph( [3, 4, 3] )
        sage: G.is_isomorphic( H )
        True

    [Python]

        >>> from sage.all import *
        >>> G = graphs.RookGraph( [Integer(3), Integer(3), Integer(4)], radius=Integer(1) )
        >>> H = graphs.GridGraph( [Integer(3), Integer(4), Integer(3)] )
        >>> G.is_isomorphic( H )
        True

  static RoseWindowGraph(n, a, r)

    Return a rose window graph with \(2n\) nodes.

    The rose window graphs is a family of tetravalent graphs introduced in [Wilson2008]. The parameters \(n\), \(a\) and \(r\) are integers such that \(n > 2\), \(1 \leq a, r < n\), and \(r \neq n / 2\).

    INPUT:

    - `n` – the number of nodes is \(2 * n\)

    - `a` – integer such that \(1 \leq a < n\) determining a-spoke edges

    - `r` – integer such that \(1 \leq r < n\) and \(r \neq n / 2\) determining how inner vertices are connected

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the rose window graphs are displayed as an inner and outer cycle pair, with the first \(n\) nodes drawn on the outer circle. The first (0) node is drawn at the top of the outer-circle, moving counterclockwise after that. The inner circle is drawn with the (\(n\))th node at the top, then counterclockwise as well. Vertices in the outer circle are connected in the circular manner, vertices in the inner circle are connected when their label have difference \(r \pmod{n}\). Vertices on the outer rim are connected with the vertices on the inner rim when they are at the same position and when they are \(a\) apart.

    EXAMPLES:

    The vertices of a rose window graph have all degree 4:

    Sage

        sage: G = graphs.RoseWindowGraph(5, 1, 2)
        sage: all(G.degree(u) == 4 for u in G)
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.RoseWindowGraph(Integer(5), Integer(1), Integer(2))
        >>> all(G.degree(u) == Integer(4) for u in G)
        True

    The smallest rose window graph as parameters \((3, 2, 1)\):

    Sage

        sage: G = graphs.RoseWindowGraph(3, 2, 1)
        sage: all(G.degree(u) == 4 for u in G)
        True

    [Python]

        >>> from sage.all import *
        >>> G = graphs.RoseWindowGraph(Integer(3), Integer(2), Integer(1))
        >>> all(G.degree(u) == Integer(4) for u in G)
        True

  static SchlaefliGraph()

    Return the Schläfli graph.

    The Schläfli graph is the only strongly regular graphs of parameters \((27,16,10,8)\) (see [GR2001]).

    For more information, see the Wikipedia article Schläfli_graph.

    See also

    `Graph.is_strongly_regular()` – tests whether a graph is strongly regular and/or returns its parameters.

    Todo

    Find a beautiful layout for this beautiful graph.

    EXAMPLES:

    Checking that the method actually returns the Schläfli graph:

    Sage

        sage: S = graphs.SchlaefliGraph()
        sage: S.is_strongly_regular(parameters=True)
        (27, 16, 10, 8)

    Python

        >>> from sage.all import *
        >>> S = graphs.SchlaefliGraph()
        >>> S.is_strongly_regular(parameters=True)
        (27, 16, 10, 8)

    The graph is vertex-transitive:

    Sage

        sage: S.is_vertex_transitive()                                                  # needs sage.groups
        True

    [Python]

        >>> from sage.all import *
        >>> S.is_vertex_transitive()                                                  # needs sage.groups
        True

    The neighborhood of each vertex is isomorphic to the complement of the Clebsch graph:

    Sage

        sage: neighborhood = S.subgraph(vertices=S.neighbors(0))
        sage: graphs.ClebschGraph().complement().is_isomorphic(neighborhood)
        True

    Python

        >>> from sage.all import *
        >>> neighborhood = S.subgraph(vertices=S.neighbors(Integer(0)))
        >>> graphs.ClebschGraph().complement().is_isomorphic(neighborhood)
        True

  static ShrikhandeGraph()

    Return the Shrikhande graph.

    For more information, see the MathWorld article on the Shrikhande graph or the Wikipedia article Shrikhande_graph.

    See also

    `Graph.is_strongly_regular()` – tests whether a graph is strongly regular and/or returns its parameters.

    EXAMPLES:

    The Shrikhande graph was defined by S. S. Shrikhande in 1959. It has \(16\) vertices and \(48\) edges, and is strongly regular of degree \(6\) with parameters \((2,2)\):

    Sage

        sage: G = graphs.ShrikhandeGraph(); G
        Shrikhande graph: Graph on 16 vertices
        sage: G.order()
        16
        sage: G.size()
        48
        sage: G.is_regular(6)
        True
        sage: set([ len([x for x in G.neighbors(i) if x in G.neighbors(j)])
        ....:     for i in range(G.order())
        ....:     for j in range(i) ])
        {2}

    Python

        >>> from sage.all import *
        >>> G = graphs.ShrikhandeGraph(); G
        Shrikhande graph: Graph on 16 vertices
        >>> G.order()
        16
        >>> G.size()
        48
        >>> G.is_regular(Integer(6))
        True
        >>> set([ len([x for x in G.neighbors(i) if x in G.neighbors(j)])
        ...     for i in range(G.order())
        ...     for j in range(i) ])
        {2}

    It is non-planar, and both Hamiltonian and Eulerian:

    Sage

        sage: G.is_planar()
        False
        sage: G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        sage: G.is_eulerian()
        True

    [Python]

        >>> from sage.all import *
        >>> G.is_planar()
        False
        >>> G.is_hamiltonian()                                                        # needs sage.numerical.mip
        True
        >>> G.is_eulerian()
        True

    It has radius \(2\), diameter \(2\), and girth \(3\):

    Sage

        sage: G.radius()
        2
        sage: G.diameter()
        2
        sage: G.girth()
        3

    Python

        >>> from sage.all import *
        >>> G.radius()
        2
        >>> G.diameter()
        2
        >>> G.girth()
        3

    Its chromatic number is \(4\) and its automorphism group is of order \(192\):

    Sage

        sage: G.chromatic_number()
        4
        sage: G.automorphism_group().cardinality()                                      # needs sage.groups
        192

    [Python]

        >>> from sage.all import *
        >>> G.chromatic_number()
        4
        >>> G.automorphism_group().cardinality()                                      # needs sage.groups
        192

    It is an integral graph since it has only integral eigenvalues:

    Sage

        sage: G.characteristic_polynomial().factor()                                    # needs sage.libs.pari sage.modules
        (x - 6) * (x - 2)^6 * (x + 2)^9

    Python

        >>> from sage.all import *
        >>> 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 embedding of the Dyck graph (`DyckGraph`).

  static SierpinskiGasketGraph(n)

    Return the Sierpinski Gasket graph of generation \(n\).

    All vertices but 3 have valence 4.

    INPUT:

    - `n` – integer

    OUTPUT:

    a graph \(S_n\) with \(3 (3^{n-1}+1)/2\) vertices and \(3^n\) edges, closely related to the famous Sierpinski triangle fractal.

    All these graphs have a triangular shape, and three special vertices at top, bottom left and bottom right. These are the only vertices of valence 2, all the other ones having valence 4.

    The graph \(S_1\) (generation \(1\)) is a triangle.

    The graph \(S_{n+1}\) is obtained from the disjoint union of three copies A,B,C of \(S_n\) by identifying pairs of vertices: the top vertex of A with the bottom left vertex of B, the bottom right vertex of B with the top vertex of C, and the bottom left vertex of C with the bottom right vertex of A.

    See also

    - `HanoiTowerGraph()`. There is another family of graphs called Sierpinski graphs, where all vertices but 3 have valence 3. They are available using `graphs.HanoiTowerGraph(3, n)`.

    - `GeneralizedSierpinskiGraph()`

    EXAMPLES:

    Sage

        sage: # needs sage.modules
        sage: s4 = graphs.SierpinskiGasketGraph(4); s4
        Graph on 42 vertices
        sage: s4.size()
        81
        sage: s4.degree_histogram()
        [0, 0, 3, 0, 39]
        sage: s4.is_hamiltonian()
        True

    Python

        >>> from sage.all import *
        >>> # needs sage.modules
        >>> s4 = graphs.SierpinskiGasketGraph(Integer(4)); s4
        Graph on 42 vertices
        >>> s4.size()
        81
        >>> s4.degree_histogram()
        [0, 0, 3, 0, 39]
        >>> s4.is_hamiltonian()
        True

    REFERENCES:

    [LLWC2011]

  static SimsGewirtzGraph()

    Return the Sims-Gewirtz Graph.

    This graph is obtained from the Higman Sims graph by considering the graph induced by the vertices at distance two from the vertices of an (any) edge. It is the only strongly regular graph with parameters \(v = 56\), \(k = 10\), \(\lambda = 0\), \(\mu = 2\)

    For more information on the Sylvester graph, see https://www.win.tue.nl/~aeb/graphs/Sims-Gewirtz.html or its Wikipedia article Gewirtz_graph.

    See also

    - `HigmanSimsGraph()`.

    EXAMPLES:

    Sage

        sage: g = graphs.SimsGewirtzGraph(); g
        Sims-Gewirtz Graph: Graph on 56 vertices
        sage: g.order()
        56
        sage: g.size()
        280
        sage: g.is_strongly_regular(parameters = True)
        (56, 10, 0, 2)

    Python

        >>> from sage.all import *
        >>> g = graphs.SimsGewirtzGraph(); g
        Sims-Gewirtz Graph: Graph on 56 vertices
        >>> g.order()
        56
        >>> g.size()
        280
        >>> g.is_strongly_regular(parameters = True)
        (56, 10, 0, 2)

  static SousselierGraph()

    Return the Sousselier Graph.

    The Sousselier graph is a hypohamiltonian graph on 16 vertices and 27 edges. For more information, see Wikipedia article Sousselier_graph or the corresponding French Wikipedia page.

    EXAMPLES:

    Sage

        sage: g = graphs.SousselierGraph()
        sage: g.order()
        16
        sage: g.size()
        27
        sage: g.radius()
        2
        sage: g.diameter()
        3
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        2
        sage: g.is_hamiltonian()                                                        # needs sage.numerical.mip
        False
        sage: g.delete_vertex(g.random_vertex())
        sage: g.is_hamiltonian()                                                        # needs sage.numerical.mip
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.SousselierGraph()
        >>> g.order()
        16
        >>> g.size()
        27
        >>> g.radius()
        2
        >>> g.diameter()
        3
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        2
        >>> g.is_hamiltonian()                                                        # needs sage.numerical.mip
        False
        >>> g.delete_vertex(g.random_vertex())
        >>> g.is_hamiltonian()                                                        # needs sage.numerical.mip
        True

  static SquaredSkewHadamardMatrixGraph(n)

    Pseudo-\(OA(2n,4n-1)\)-graph from a skew Hadamard matrix of order \(4n\).

    A strongly regular graph with parameters of the orthogonal array graph `OrthogonalArrayBlockGraph()`, also known as pseudo Latin squares graph \(L_{2n}(4n-1)\), constructed from a skew Hadamard matrix of order \(4n\), due to Goethals and Seidel, see [BL1984].

    See also

    - `is_orthogonal_array_block_graph()`

    EXAMPLES:

    Sage

        sage: # needs sage.combinat sage.modules
        sage: G = graphs.SquaredSkewHadamardMatrixGraph(4)
        sage: G.is_strongly_regular(parameters=True)
        (225, 112, 55, 56)
        sage: G = graphs.SquaredSkewHadamardMatrixGraph(5)
        sage: G.is_strongly_regular(parameters=True)    # long time
        (361, 180, 89, 90)
        sage: G = graphs.SquaredSkewHadamardMatrixGraph(9)
        sage: G.is_strongly_regular(parameters=True)    # not tested
        (1225, 612, 305, 306)

    Python

        >>> from sage.all import *
        >>> # needs sage.combinat sage.modules
        >>> G = graphs.SquaredSkewHadamardMatrixGraph(Integer(4))
        >>> G.is_strongly_regular(parameters=True)
        (225, 112, 55, 56)
        >>> G = graphs.SquaredSkewHadamardMatrixGraph(Integer(5))
        >>> G.is_strongly_regular(parameters=True)    # long time
        (361, 180, 89, 90)
        >>> G = graphs.SquaredSkewHadamardMatrixGraph(Integer(9))
        >>> G.is_strongly_regular(parameters=True)    # not tested
        (1225, 612, 305, 306)

  static StaircaseGraph(n)

    Return a staircase graph with \(2n\) nodes

    For \(n \geq 3\), the staircase graph of order \(2n\) is the graph obtained from the ladder graph of order \(2n - 2\), i.e., `graphs.LadderGraph(n - 1)` by introducing two new nodes \(2n - 2\) and \(2n - 1\), and then joining the node \(2n - 2\) with \(0\) and \(n - 1\), the node \(2n - 1\) with \(n - 2\) and \(2n - 3\), and the nodes \(2n - 2\) and \(2n - 1\) with each other.

    Note that `graphs.StaircaseGraph(4)` is also known as the `Bicorn graph`. It is the only brick that has a unique \(b\)-invariant edge.

    PLOTTING:

    Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each staircase graph will be displayed horizontally, with the first \(n - 1\) nodes displayed from left to right on the top horizontal line, the second \(n - 1\) nodes displayed from left to right on the middle horizontal line, and the last two nodes displayed at the bottom two corners.

    INPUT:

    - `n` – an integer at least 3; number of nodes is \(2n\)

    OUTPUT:

    - `G` – a staircase graph of order \(2n\); note that a `ValueError` is returned if \(n < 3\)

    EXAMPLES:

    Construct and show a staircase graph with 10 nodes:

    Sage

        sage: g = graphs.StaircaseGraph(5)
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.StaircaseGraph(Integer(5))
        >>> g.show()                          # long time                             # needs sage.plot

    Construct and show the Bicorn graph. Note that the edge \((1, 4)\) is the unique \(b\)-invariant edge:

    Sage

        sage: bicornGraph = graphs.StaircaseGraph(4)
        sage: bicornGraph.show()                # long time                             # needs sage.plot

    [Python]

        >>> from sage.all import *
        >>> bicornGraph = graphs.StaircaseGraph(Integer(4))
        >>> bicornGraph.show()                # long time                             # needs sage.plot

    Create several staircase graphs in a Sage graphics array:

    Sage

        sage: # needs sage.plots
        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:    k = graphs.StaircaseGraph(i+3)
        ....:    g.append(k)
        sage: for i in range(3):
        ....:    n = []
        ....:    for m in range(3):
        ....:        n.append(g[3*i + m].plot(vertex_size=50 - 4*(3*i+m), vertex_labels=False))
        ....:    j.append(n)
        sage: G = graphics_array(j)
        sage: G.show()                          # long time

    Python

        >>> from sage.all import *
        >>> # needs sage.plots
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...    k = graphs.StaircaseGraph(i+Integer(3))
        ...    g.append(k)
        >>> for i in range(Integer(3)):
        ...    n = []
        ...    for m in range(Integer(3)):
        ...        n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50) - Integer(4)*(Integer(3)*i+m), vertex_labels=False))
        ...    j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    REFERENCES:

    - [LM2024]

    See also

    `LadderGraph()`

    AUTHORS:

    - Janmenjaya Panda (2024-06-09)

  static StarGraph(n, immutable=False)

    Return a star graph with \(n + 1\) nodes.

    A Star graph is a basic structure where one node is connected to all other nodes.

    INPUT:

    - `n` – a nonnegative integer; number of nodes is \(n + 1\)

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each star graph will be displayed with the first (0) node in the center, the second node (1) at the top, with the rest following in a counterclockwise manner. (0) is the node connected to all other nodes.

    The star graph is a good opportunity to compare efficiency of filling a position dictionary vs. using the spring-layout algorithm for plotting. As far as display, the spring-layout should push all other nodes away from the (0) node, and thus look very similar to this constructor’s positioning.

    EXAMPLES:

    Sage

        sage: import networkx                                                           # needs networkx

    Python

        >>> from sage.all import *
        >>> import networkx                                                           # needs networkx

    Compare the plots:

    Sage

        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
        sage: posdict23.show()  # long time

    [Python]

        >>> from sage.all import *
        >>> # needs networkx sage.plot
        >>> n = networkx.star_graph(Integer(23))
        >>> spring23 = Graph(n)
        >>> posdict23 = graphs.StarGraph(Integer(23))
        >>> spring23.show()                   # long time
        >>> posdict23.show()  # long time

    View many star graphs as a Sage Graphics Array

    With this constructor (i.e., the position dictionary filled)

    Sage

        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):
        ....:     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)
        sage: G.show()                          # long time

    Python

        >>> from sage.all import *
        >>> # needs sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     k = graphs.StarGraph(i+Integer(3))
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    Compared to plotting with the spring-layout algorithm

    Sage

        sage: # needs networkx sage.plot
        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     spr = networkx.star_graph(i+3)
        ....:     k = Graph(spr)
        ....:     g.append(k)
        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)
        sage: G.show()                          # long time

    [Python]

        >>> from sage.all import *
        >>> # needs networkx sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...     spr = networkx.star_graph(i+Integer(3))
        ...     k = Graph(spr)
        ...     g.append(k)
        >>> for i in range(Integer(3)):
        ...     n = []
        ...     for m in range(Integer(3)):
        ...         n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

  static SuzukiGraph()

    Return the Suzuki Graph.

    The Suzuki graph has 1782 vertices, and is strongly regular with parameters \((1782,416,100,96)\). Known as S.15 in [Hub1975].

    Note

    It takes approximately 50 seconds to build this graph. Do not be too impatient.

    EXAMPLES:

    Sage

        sage: g = graphs.SuzukiGraph(); g  # optional internet # not tested
        Suzuki graph: Graph on 1782 vertices
        sage: g.is_strongly_regular(parameters=True)  # optional internet # not tested
        (1782, 416, 100, 96)

    Python

        >>> from sage.all import *
        >>> g = graphs.SuzukiGraph(); g  # optional internet # not tested
        Suzuki graph: Graph on 1782 vertices
        >>> g.is_strongly_regular(parameters=True)  # optional internet # not tested
        (1782, 416, 100, 96)

  static SwitchedSquaredSkewHadamardMatrixGraph(n)

    A strongly regular graph in Seidel switching class of `SquaredSkewHadamardMatrixGraph()`.

    A strongly regular graph in the `Seidel switching` class of the disjoint union of a 1-vertex graph and the one produced by `Pseudo-L_{2n}(4n-1)`

    In this case, the other possible parameter set of a strongly regular graph in the Seidel switching class of the latter graph (see [BH2012]) coincides with the set of parameters of the complement of the graph returned by this function.

    See also

    - `is_switch_skewhad()`

    EXAMPLES:

    Sage

        sage: # needs sage.combinat sage.modules
        sage: g = graphs.SwitchedSquaredSkewHadamardMatrixGraph(4)
        sage: g.is_strongly_regular(parameters=True)
        (226, 105, 48, 49)
        sage: from sage.combinat.designs.twographs import twograph_descendant
        sage: twograph_descendant(g, 0).is_strongly_regular(parameters=True)
        (225, 112, 55, 56)
        sage: gc = g.complement()
        sage: twograph_descendant(gc, 0).is_strongly_regular(parameters=True)
        (225, 112, 55, 56)

    Python

        >>> from sage.all import *
        >>> # needs sage.combinat sage.modules
        >>> g = graphs.SwitchedSquaredSkewHadamardMatrixGraph(Integer(4))
        >>> g.is_strongly_regular(parameters=True)
        (226, 105, 48, 49)
        >>> from sage.combinat.designs.twographs import twograph_descendant
        >>> twograph_descendant(g, Integer(0)).is_strongly_regular(parameters=True)
        (225, 112, 55, 56)
        >>> gc = g.complement()
        >>> twograph_descendant(gc, Integer(0)).is_strongly_regular(parameters=True)
        (225, 112, 55, 56)

  static SylvesterGraph()

    Return the Sylvester Graph.

    This graph is obtained from the Hoffman Singleton graph by considering the graph induced by the vertices at distance two from the vertices of an (any) edge.

    For more information on the Sylvester graph, see https://www.win.tue.nl/~aeb/graphs/Sylvester.html.

    See also

    - `HoffmanSingletonGraph()`.

    EXAMPLES:

    Sage

        sage: g = graphs.SylvesterGraph(); g
        Sylvester Graph: Graph on 36 vertices
        sage: g.order()
        36
        sage: g.size()
        90
        sage: g.is_regular(k=5)
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.SylvesterGraph(); g
        Sylvester Graph: Graph on 36 vertices
        >>> g.order()
        36
        >>> g.size()
        90
        >>> g.is_regular(k=Integer(5))
        True

  static SymplecticDualPolarGraph(m, q)

    Return the Symplectic Dual Polar Graph \(DSp(m,q)\).

    For more information on Symplectic Dual Polar graphs, see [BCN1989] and Sect. 2.3.1 of [Coh1981].

    INPUT:

    - `m`, `q` – integers; \(q\) must be a prime power, and \(m\) must be even

    EXAMPLES:

    Sage

        sage: G = graphs.SymplecticDualPolarGraph(6,3); G       # not tested (long time)
        Symplectic Dual Polar Graph DSp(6, 3): Graph on 1120 vertices
        sage: G.is_distance_regular(parameters=True)            # not tested (long time)
        ([39, 36, 27, None], [None, 1, 4, 13])

    Python

        >>> from sage.all import *
        >>> G = graphs.SymplecticDualPolarGraph(Integer(6),Integer(3)); G       # not tested (long time)
        Symplectic Dual Polar Graph DSp(6, 3): Graph on 1120 vertices
        >>> G.is_distance_regular(parameters=True)            # not tested (long time)
        ([39, 36, 27, None], [None, 1, 4, 13])

  static SymplecticPolarGraph(d, q, algorithm=None)

    Return the Symplectic Polar Graph \(Sp(d,q)\).

    The Symplectic Polar Graph \(Sp(d,q)\) is built from a projective space of dimension \(d-1\) over a field \(F_q\), and a symplectic form \(f\). Two vertices \(u,v\) are made adjacent if \(f(u,v)=0\).

    See the page on symplectic graphs on Andries Brouwer’s website.

    INPUT:

    - `d`, `q` – integers; note that only even values of \(d\) are accepted by the function

    - `algorithm` – string (default: `None`); if set to `'gap'`, then the computation is carried via GAP library interface, computing totally singular subspaces, which is faster for \(q>3\). Otherwise it is done directly.

    EXAMPLES:

    Computation of the spectrum of \(Sp(6,2)\):

    Sage

        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
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.SymplecticPolarGraph(Integer(6), Integer(2))
        >>> g.is_strongly_regular(parameters=True)
        (63, 30, 13, 15)
        >>> set(g.spectrum()) == {-Integer(5), Integer(3), Integer(30)}                                          # needs sage.rings.number_field
        True

    The parameters of \(Sp(4,q)\) are the same as of \(O(5,q)\), but they are not isomorphic if \(q\) is odd:

    Sage

        sage: G = graphs.SymplecticPolarGraph(4, 3)
        sage: G.is_strongly_regular(parameters=True)
        (40, 12, 2, 4)

        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_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)
        (1365, 340, 83, 85)

    [Python]

        >>> from sage.all import *
        >>> G = graphs.SymplecticPolarGraph(Integer(4), Integer(3))
        >>> G.is_strongly_regular(parameters=True)
        (40, 12, 2, 4)

        >>> # needs sage.libs.gap
        >>> O = graphs.OrthogonalPolarGraph(Integer(5), Integer(3))
        >>> O.is_strongly_regular(parameters=True)
        (40, 12, 2, 4)
        >>> O.is_isomorphic(G)
        False
        >>> S = graphs.SymplecticPolarGraph(Integer(6), Integer(4), algorithm='gap')    # not tested (long time)
        >>> S.is_strongly_regular(parameters=True)                    # not tested (long time)
        (1365, 340, 83, 85)

  static SzekeresSnarkGraph()

    Return the Szekeres Snark Graph.

    The Szekeres graph is a snark with 50 vertices and 75 edges. For more information on this graph, see the Wikipedia article Szekeres_snark.

    EXAMPLES:

    Sage

        sage: g = graphs.SzekeresSnarkGraph()
        sage: g.order()
        50
        sage: g.size()
        75
        sage: g.chromatic_number()
        3

    Python

        >>> from sage.all import *
        >>> g = graphs.SzekeresSnarkGraph()
        >>> g.order()
        50
        >>> g.size()
        75
        >>> g.chromatic_number()
        3

  static T2starGeneralizedQuadrangleGraph(q, dual=False, hyperoval=None, field=None, check_hyperoval=True)

    Return the collinearity graph of the generalized quadrangle \(T_2^*(q)\), or of its dual

    Let \(q=2^k\) and \(\Theta=PG(3,q)\). \(T_2^*(q)\) is a generalized quadrangle (Wikipedia article Generalized_quadrangle) of order \((q-1,q+1)\), see 3.1.3 in [PT2009]. Fix a plane \(\Pi \subset \Theta\) and a hyperoval \(O \subset \Pi\). The points of \(T_2^*(q):=T_2^*(O)\) are the points of \(\Theta\) outside \(\Pi\), and the lines are the lines of \(\Theta\) outside \(\Pi\) that meet \(\Pi\) in a point of \(O\).

    INPUT:

    - `q` – a power of two

    - `dual` – boolean (default: `False`); whether to return the graph of \(T_2^*(O)\) or of the dual \(T_2^*(O)\) (when `True`)

    - `hyperoval` – a hyperoval (i.e. a complete 2-arc; a set of points in the plane meeting every line in 0 or 2 points) in the plane of points with 0th coordinate 0 in \(PG(3,q)\) over the field `field`. Each point of `hyperoval` must be a length 4 vector over `field` with 1st non-0 coordinate equal to 1. By default, `hyperoval` and `field` are not specified, and constructed on the fly. In particular, `hyperoval` we build is the classical one, i.e. a conic with the point of intersection of its tangent lines.

    - `field` – an instance of a finite field of order \(q\), must be provided if `hyperoval` is provided

    - `check_hyperoval` – boolean (default: `True`); whether to check `hyperoval` for correctness or not

    EXAMPLES:

    using the built-in construction:

    Sage

        sage: # needs sage.combinat 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)
        (64, 18, 2, 6)
        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)
        (96, 20, 4, 4)

    Python

        >>> from sage.all import *
        >>> # needs sage.combinat sage.rings.finite_rings
        >>> g = graphs.T2starGeneralizedQuadrangleGraph(Integer(4)); g
        T2*(O,4); GQ(3, 5): Graph on 64 vertices
        >>> g.is_strongly_regular(parameters=True)
        (64, 18, 2, 6)
        >>> g = graphs.T2starGeneralizedQuadrangleGraph(Integer(4), dual=True); g
        T2*(O,4)*; GQ(5, 3): Graph on 96 vertices
        >>> g.is_strongly_regular(parameters=True)
        (96, 20, 4, 4)

    supplying your own hyperoval:

    Sage

        sage: # needs sage.combinat 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
        T2*(O,4); GQ(3, 5): Graph on 64 vertices
        sage: g.is_strongly_regular(parameters=True)
        (64, 18, 2, 6)

    [Python]

        >>> from sage.all import *
        >>> # needs sage.combinat sage.rings.finite_rings
        >>> F = GF(Integer(4),'b')
        >>> O = [vector(F,(Integer(0),Integer(0),Integer(0),Integer(1))),vector(F,(Integer(0),Integer(0),Integer(1),Integer(0)))] + [vector(F, (Integer(0),Integer(1),x**Integer(2),x))
        ...                                                  for x in F]
        >>> g = graphs.T2starGeneralizedQuadrangleGraph(Integer(4), hyperoval=O, field=F); g
        T2*(O,4); GQ(3, 5): Graph on 64 vertices
        >>> g.is_strongly_regular(parameters=True)
        (64, 18, 2, 6)

  static TabacjnGraph(n, a, b, r)

    Return a Tabačjn graph with \(2n\) nodes.

    The Tabačjn graphs is a family of pentavalent bicirculants graphs proposed in [AHKOS2014] as a generalization of generalized Petersen graphs. The parameters \(n\), \(a\), \(b\), \(r\) are integers such that \(n \geq 3\), \(1 \leq a, b, r \leq n - 1\), with \(a \neq b\) and \(r \neq n / 2\).

    INPUT:

    - `n` – the number of nodes is \(2 * n\)

    - `a` – integer such that \(0 < a < n\) and \(a \neq b\), that determines a-spoke edges

    - `b` – integer such that \(0 < b < n\) and \(b \neq a\), that determines b-spoke edges

    - `r` – integer such that \(0 < r < n\) and \(r \neq n/2\) determining how inner vertices are connected

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the rose window graphs are displayed as an inner and outer cycle pair, with the first \(n\) nodes drawn on the outer circle. The first (0) node is drawn at the top of the outer-circle, moving counterclockwise after that. The inner circle is drawn with the (\(n\))th node at the top, then counterclockwise as well. Vertices in the outer circle are connected in the circular manner, vertices in the inner circle are connected when their label have difference \(r \pmod{n}\). Vertices on the outer rim are connected with the vertices on the inner rim when they are at the same position and when they are \(a\) and \(b\) apart.

    EXAMPLES:

    Sage

        sage: G = graphs.TabacjnGraph(3, 1, 2, 1)
        sage: G.degree()
        [5, 5, 5, 5, 5, 5]
        sage: G.is_isomorphic(graphs.CompleteGraph(6))
        True
        sage: G = graphs.TabacjnGraph(6, 1, 5, 2)
        sage: I = graphs.IcosahedralGraph()
        sage: G.is_isomorphic(I)
        True

    Python

        >>> from sage.all import *
        >>> G = graphs.TabacjnGraph(Integer(3), Integer(1), Integer(2), Integer(1))
        >>> G.degree()
        [5, 5, 5, 5, 5, 5]
        >>> G.is_isomorphic(graphs.CompleteGraph(Integer(6)))
        True
        >>> G = graphs.TabacjnGraph(Integer(6), Integer(1), Integer(5), Integer(2))
        >>> I = graphs.IcosahedralGraph()
        >>> G.is_isomorphic(I)
        True

  static TadpoleGraph(n1, n2)

    Return a tadpole graph with \(n_1 + n_2\) nodes.

    A tadpole graph is a path graph (order \(n_2\)) connected to a cycle graph (order \(n_1\)).

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the cycle graph will be drawn in the lower-left corner with the \(n_1\)-th node at a 45 degree angle above the right horizontal center of the cycle graph, leading directly into the path graph.

    EXAMPLES:

    Construct and show a tadpole graph Cycle = 13, Stick = 4:

    Sage

        sage: g = graphs.TadpoleGraph(13, 4); g
        Tadpole graph: Graph on 17 vertices
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.TadpoleGraph(Integer(13), Integer(4)); g
        Tadpole graph: Graph on 17 vertices
        >>> g.show()                          # long time                             # needs sage.plot

  static TaylorTwographDescendantSRG(q, clique_partition=False)

    Return the descendant graph of the Taylor’s two-graph for \(U_3(q)\), \(q\) odd.

    This is a strongly regular graph with parameters \((v,k,\lambda,\mu)=(q^3, (q^2+1)(q-1)/2, (q-1)^3/4-1, (q^2+1)(q-1)/4)\) obtained as a two-graph descendant of the `Taylor's two-graph` \(T\). This graph admits a partition into cliques of size \(q\), which are useful in `TaylorTwographSRG()`, a strongly regular graph on \(q^3+1\) vertices in the Seidel switching class of \(T\), for which we need \((q^2+1)/2\) cliques. The cliques are the \(q^2\) lines on \(v_0\) of the projective plane containing the unital for \(U_3(q)\), and intersecting the unital (i.e. the vertices of the graph and the point we remove) in \(q+1\) points. This is all taken from §7E of [BL1984].

    INPUT:

    - `q` – a power of an odd prime number

    - `clique_partition` – boolean (default: `False`); when set to `True`, return \(q^2-1\) cliques of size \(q\) with empty pairwise intersection. (Removing all of them leaves a clique, too), and the point removed from the unital.

    EXAMPLES:

    Sage

        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)
        (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
        True
        sage: g = graphs.TaylorTwographDescendantSRG(5)         # not tested (long time)
        sage: g.is_strongly_regular(parameters=True)            # not tested (long time)
        (125, 52, 15, 26)

    Python

        >>> from sage.all import *
        >>> # needs sage.rings.finite_rings
        >>> g = graphs.TaylorTwographDescendantSRG(Integer(3)); g
        Taylor two-graph descendant SRG: Graph on 27 vertices
        >>> g.is_strongly_regular(parameters=True)
        (27, 10, 1, 5)
        >>> from sage.combinat.designs.twographs import taylor_twograph
        >>> T = taylor_twograph(Integer(3))                            # long time
        >>> g.is_isomorphic(T.descendant(T.ground_set()[Integer(1)]))  # long time
        True
        >>> g = graphs.TaylorTwographDescendantSRG(Integer(5))         # not tested (long time)
        >>> g.is_strongly_regular(parameters=True)            # not tested (long time)
        (125, 52, 15, 26)

  static TaylorTwographSRG(q)

    Return a strongly regular graph from the Taylor’s two-graph for \(U_3(q)\), \(q\) odd

    This is a strongly regular graph with parameters \((v,k,\lambda,\mu)=(q^3+1, q(q^2+1)/2, (q^2+3)(q-1)/4, (q^2+1)(q+1)/4)\) in the Seidel switching class of `Taylor two-graph`. Details are in §7E of [BL1984].

    INPUT:

    - `q` – a power of an odd prime number

    See also

    - `TaylorTwographDescendantSRG()`

    EXAMPLES:

    Sage

        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)                                    # needs sage.rings.finite_rings
        (28, 15, 6, 10)

    Python

        >>> from sage.all import *
        >>> t = graphs.TaylorTwographSRG(Integer(3)); t                                        # needs sage.rings.finite_rings
        Taylor two-graph SRG: Graph on 28 vertices
        >>> t.is_strongly_regular(parameters=True)                                    # needs sage.rings.finite_rings
        (28, 15, 6, 10)

  static TetrahedralGraph()

    Return a tetrahedral graph (with 4 nodes).

    A tetrahedron is a 4-sided triangular pyramid. The tetrahedral graph corresponds to the connectivity of the vertices of the tetrahedron. This graph is equivalent to a wheel graph with 4 nodes and also a complete graph on four nodes. (See examples below).

    PLOTTING: The Tetrahedral graph should be viewed in 3 dimensions. We choose to use a planar embedding of the graph. We hope to add rotatable, 3-dimensional viewing in the future. In such a case, an argument will be added to select the desired layout.

    EXAMPLES:

    Construct and show a Tetrahedral graph:

    Sage

        sage: g = graphs.TetrahedralGraph()
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.TetrahedralGraph()
        >>> g.show()                          # long time                             # needs sage.plot

    The following example requires networkx:

    Sage

        sage: import networkx as NX                                                     # needs networkx

    [Python]

        >>> from sage.all import *
        >>> 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

        sage: # needs networkx sage.plot
        sage: tetra_pos = graphs.TetrahedralGraph()
        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]
        sage: j = []
        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)
        sage: G.show()                          # long time

    Python

        >>> from sage.all import *
        >>> # needs networkx sage.plot
        >>> tetra_pos = graphs.TetrahedralGraph()
        >>> tetra_spring = Graph(NX.tetrahedral_graph())
        >>> wheel = graphs.WheelGraph(Integer(4))
        >>> complete = graphs.CompleteGraph(Integer(4))
        >>> g = [tetra_pos, tetra_spring, wheel, complete]
        >>> j = []
        >>> for i in range(Integer(2)):
        ...     n = []
        ...     for m in range(Integer(2)):
        ...         n.append(g[i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...     j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

  static ThomsenGraph()

    Return the Thomsen Graph.

    The Thomsen Graph is actually a complete bipartite graph with \((n1, n2) = (3, 3)\). It is also called the Utility graph.

    PLOTTING: See CompleteBipartiteGraph.

    EXAMPLES:

    Sage

        sage: T = graphs.ThomsenGraph()
        sage: T
        Thomsen graph: Graph on 6 vertices
        sage: T.graph6_string()
        'EFz_'
        sage: (graphs.ThomsenGraph()).show()    # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> T = graphs.ThomsenGraph()
        >>> T
        Thomsen graph: Graph on 6 vertices
        >>> T.graph6_string()
        'EFz_'
        >>> (graphs.ThomsenGraph()).show()    # long time                             # needs sage.plot

  static TietzeGraph()

    Return the Tietze Graph.

    For more information on the Tietze Graph, see the Wikipedia article Tietze%27s_graph.

    EXAMPLES:

    Sage

        sage: g = graphs.TietzeGraph()
        sage: g.order()
        12
        sage: g.size()
        18
        sage: g.diameter()
        3
        sage: g.girth()
        3
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        12
        sage: g.automorphism_group().is_isomorphic(groups.permutation.Dihedral(6))      # needs sage.groups
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.TietzeGraph()
        >>> g.order()
        12
        >>> g.size()
        18
        >>> g.diameter()
        3
        >>> g.girth()
        3
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        12
        >>> g.automorphism_group().is_isomorphic(groups.permutation.Dihedral(Integer(6)))      # needs sage.groups
        True

  static ToleranceGraph(tolrep)

    Return the graph generated by the tolerance representation `tolrep`.

    The tolerance representation `tolrep` is described by the list \(((l_0,r_0,t_0), (l_1,r_1,t_1), \ldots, (l_k,r_k,t_k))\) where \(I_i = (l_i,r_i)\) denotes a closed interval on the real line with \(l_i < r_i\) and \(t_i\) a strictly positive value, called tolerance. This representation generates the tolerance graph with the vertex set \(\{0,1, \ldots, k\}\) and the edge set \(\{(i,j): |I_i \cap I_j| \ge \min\{t_i, t_j\}\}\) where \(|I_i \cap I_j|\) denotes the length of the intersection of \(I_i\) and \(I_j\).

    INPUT:

    - `tolrep` – list of triples \((l_i,r_i,t_i)\) where \((l_i,r_i)\) denotes a closed interval on the real line and \(t_i\) a positive value

    Note

    The vertices are named \(0, 1, \ldots, k\). The tolerance representation used to create the graph is saved with the graph and can be recovered using `get_vertex()` or `get_vertices()`.

    EXAMPLES:

    The following code creates a tolerance representation `tolrep`, generates its tolerance graph `g`, and applies some checks:

    Sage

        sage: tolrep = [(1,4,3),(1,2,1),(2,3,1),(0,3,3)]
        sage: g = graphs.ToleranceGraph(tolrep)
        sage: g.get_vertex(3)
        (0, 3, 3)
        sage: neigh = g.neighbors(3)
        sage: for v in neigh: print(g.get_vertex(v))
        (1, 2, 1)
        (2, 3, 1)
        sage: g.is_interval()
        False
        sage: g.is_weakly_chordal()
        True

    Python

        >>> from sage.all import *
        >>> tolrep = [(Integer(1),Integer(4),Integer(3)),(Integer(1),Integer(2),Integer(1)),(Integer(2),Integer(3),Integer(1)),(Integer(0),Integer(3),Integer(3))]
        >>> g = graphs.ToleranceGraph(tolrep)
        >>> g.get_vertex(Integer(3))
        (0, 3, 3)
        >>> neigh = g.neighbors(Integer(3))
        >>> for v in neigh: print(g.get_vertex(v))
        (1, 2, 1)
        (2, 3, 1)
        >>> g.is_interval()
        False
        >>> g.is_weakly_chordal()
        True

    The intervals in the list need not be distinct

    Sage

        sage: tolrep2 = [(0,4,5),(1,2,1),(2,3,1),(0,4,5)]
        sage: g2 = graphs.ToleranceGraph(tolrep2)
        sage: g2.get_vertices()
        {0: (0, 4, 5), 1: (1, 2, 1), 2: (2, 3, 1), 3: (0, 4, 5)}
        sage: g2.is_isomorphic(g)
        True

    [Python]

        >>> from sage.all import *
        >>> tolrep2 = [(Integer(0),Integer(4),Integer(5)),(Integer(1),Integer(2),Integer(1)),(Integer(2),Integer(3),Integer(1)),(Integer(0),Integer(4),Integer(5))]
        >>> g2 = graphs.ToleranceGraph(tolrep2)
        >>> g2.get_vertices()
        {0: (0, 4, 5), 1: (1, 2, 1), 2: (2, 3, 1), 3: (0, 4, 5)}
        >>> g2.is_isomorphic(g)
        True

    Real values are also allowed

    Sage

        sage: tolrep = [(0.1,3.3,4.4),(1.1,2.5,1.1),(1.4,4.4,3.3)]
        sage: g = graphs.ToleranceGraph(tolrep)
        sage: g.is_isomorphic(graphs.PathGraph(3))
        True

    Python

        >>> from sage.all import *
        >>> tolrep = [(RealNumber('0.1'),RealNumber('3.3'),RealNumber('4.4')),(RealNumber('1.1'),RealNumber('2.5'),RealNumber('1.1')),(RealNumber('1.4'),RealNumber('4.4'),RealNumber('3.3'))]
        >>> g = graphs.ToleranceGraph(tolrep)
        >>> g.is_isomorphic(graphs.PathGraph(Integer(3)))
        True

  static Toroidal6RegularGrid2dGraph(p, q, immutable=False)

    Return a toroidal 6-regular grid.

    The toroidal 6-regular grid is a 6-regular graph on \(p \times q\) vertices and its elements have coordinates \((i, j)\) for \(i \in \{0...p-1\}\) and \(j \in \{0...q-1\}\).

    Its edges are those of the `ToroidalGrid2dGraph()`, to which are added the edges between \((i, j)\) and \(((i + 1) \% p, (j + 1) \% q)\).

    INPUT:

    - `p`, `q` – integers

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    The toroidal 6-regular grid on \(25\) elements:

    Sage

        sage: g = graphs.Toroidal6RegularGrid2dGraph(5,5)
        sage: g.is_regular(k=6)
        True
        sage: g.is_vertex_transitive()                                                  # needs sage.groups
        True
        sage: g.line_graph().is_vertex_transitive()                                     # needs sage.groups
        True
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        300
        sage: g.is_hamiltonian()                                                        # needs sage.numerical.mip
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.Toroidal6RegularGrid2dGraph(Integer(5),Integer(5))
        >>> g.is_regular(k=Integer(6))
        True
        >>> g.is_vertex_transitive()                                                  # needs sage.groups
        True
        >>> g.line_graph().is_vertex_transitive()                                     # needs sage.groups
        True
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        300
        >>> g.is_hamiltonian()                                                        # needs sage.numerical.mip
        True

  static ToroidalGrid2dGraph(p, q, immutable=False)

    Return a toroidal 2-dimensional grid graph with \(p \times q\) nodes (\(p\) rows and \(q\) columns).

    The toroidal 2-dimensional grid with parameters \(p,q\) is the 2-dimensional grid graph with identical parameters to which are added the edges \(((i, 0), (i, q - 1))\) and \(((0, i), (p - 1, i))\).

    INPUT:

    - `p, q` – nonnegative integers; the sides of the toroidal grid

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    The toroidal 2-dimensional grid is a regular graph, while the usual 2-dimensional grid is not

    Sage

        sage: tgrid = graphs.ToroidalGrid2dGraph(8,9)
        sage: print(tgrid)
        Toroidal 2D Grid Graph with parameters 8,9
        sage: grid = graphs.Grid2dGraph(8,9)
        sage: grid.is_regular()
        False
        sage: tgrid.is_regular()
        True

    Python

        >>> from sage.all import *
        >>> tgrid = graphs.ToroidalGrid2dGraph(Integer(8),Integer(9))
        >>> print(tgrid)
        Toroidal 2D Grid Graph with parameters 8,9
        >>> grid = graphs.Grid2dGraph(Integer(8),Integer(9))
        >>> grid.is_regular()
        False
        >>> tgrid.is_regular()
        True

  static TricornGraph()

    Return the Tricorn graph.

    The Tricorn graph is obtained by splicing a complete graph \(K_4\) with the the triangular circular ladder graph \(\overline{C_6}\). (Note that this generates a unique graph as both of the graphs \(K_4\) and \(\overline{C_6}\) are vertex-transitive). It is a nonsolid brick. This matching covered graph is one of the ten extremal cubic bricks. (A matching covered graph \(G\) is extremal if \(\Phi(G) = dim(\mathcal{Lin}(G))\), where \(\Phi(G)\) denotes the number of perfect matchings of \(G\), and \(dim(\mathcal{Lin}(G))\) stands for the dimension of the linear space of \(G\)).

    The Tricorn graph has no removable doubletons and has precisely three removable edges. The wheel graph \(W_5\) and the complete graph \(K_4\) are matching minors of the Tricorn graph.

    As per a theorem of Lovász [Lov1983], each non bipartite matching covered graph has a conformal subgraph which is either a bi-subdivision of \(K_4\) or of \(\overline{C_6}\) or both. In their paper, Kothari and Murty [KM2015] characterized those planar bricks that are free of \(\overline{C_6}\) (that is, the planar bricks that do not contain a bi-subdivision of \(\overline{C_6}\) as a conformal subgraph). Besides two infinite families of matching covered graphs (odd wheel graphs and staircase graphs of order 4k), the Tricorn graph is the only exception brick that is simple, planar and free of \(\overline{C_6}\).

    PLOTTING:

    Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the Tricorn graph is displayed as mentioned in the book [LM2024], with the central vertex being the \(0\)-th one. Rest of the nine vertices are shown in groups of three, one on the top, rest two on the bottom left and on the bottom right corners respectively.

    OUTPUT:

    - `G` – the Tricorn graph

    EXAMPLES:

    Construct and show the Tricorn graph; note that the edges \((2, 3)\), \((5, 6)\) and \((8, 9)\) are the only removable edges of the Tricorn graph:

    Sage

        sage: g = graphs.TricornGraph()
        sage: g.name()
        'Tricorn Graph'
        sage: g.order()
        10
        sage: g.size()
        15
        sage: g.girth()
        3
        sage: g.diameter()
        3
        sage: g.is_hamiltonian()
        True
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.TricornGraph()
        >>> g.name()
        'Tricorn Graph'
        >>> g.order()
        10
        >>> g.size()
        15
        >>> g.girth()
        3
        >>> g.diameter()
        3
        >>> g.is_hamiltonian()
        True
        >>> g.show()                          # long time                             # needs sage.plot

    REFERENCES:

    - [KM2015]

    - [LM2024]

    - [Lov1983]

    AUTHORS:

    - Janmenjaya Panda (2024-08-02)

  static TruncatedBiwheelGraph(n)

    Return a truncated biwheel graph with \(2n\) nodes

    For \(n \geq 3\), the truncated biwheel graph of order \(2n\) is the graph obtained from the path graph of order \(2n - 2\), i.e., `graphs.PathGraph(2*n - 2)` by introducing two new nodes \(2n - 2\) and \(2n - 1\), and then joining the node \(2n - 2\) with the odd indexed nodes up to \(2n - 3\), joining the node \(2n - 1\) with the even indexed nodes up to \(2n - 4\) and adding the edges \((0, 2n - 2)\) and \((2n - 3, 2n - 1)\).

    PLOTTING:

    Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each truncated biwheel graph will be displayed horizontally, with the first \(2n - 2\) nodes displayed from left to right on the middle horizontal line and the nodes \(2n - 2\) and \(2n - 1\) displayed at the top and the bottom central positions respectively.

    INPUT:

    - `n` – an integer at least 3; number of nodes is \(2n\)

    OUTPUT:

    - `G` – a truncated biwheel graph of order \(2n\); note that a `ValueError` is returned if \(n < 3\)

    EXAMPLES:

    Construct and show a truncated biwheel graph with 10 nodes:

    Sage

        sage: g = graphs.TruncatedBiwheelGraph(5)
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.TruncatedBiwheelGraph(Integer(5))
        >>> g.show()                          # long time                             # needs sage.plot

    Create several truncated biwheel graphs in a Sage graphics array:

    Sage

        sage: # needs sage.plots
        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:    k = graphs.TruncatedBiwheelGraph(i+3)
        ....:    g.append(k)
        sage: for i in range(3):
        ....:    n = []
        ....:    for m in range(3):
        ....:        n.append(g[3*i + m].plot(vertex_size=50 - 4*(3*i+m), vertex_labels=False))
        ....:    j.append(n)
        sage: G = graphics_array(j)
        sage: G.show()                          # long time

    [Python]

        >>> from sage.all import *
        >>> # needs sage.plots
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...    k = graphs.TruncatedBiwheelGraph(i+Integer(3))
        ...    g.append(k)
        >>> for i in range(Integer(3)):
        ...    n = []
        ...    for m in range(Integer(3)):
        ...        n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50) - Integer(4)*(Integer(3)*i+m), vertex_labels=False))
        ...    j.append(n)
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    REFERENCES:

    - [LM2024]

    See also

    `WheelGraph()`, `BiwheelGraph()`

    AUTHORS:

    - Janmenjaya Panda (2024-06-09)

  static TruncatedIcosidodecahedralGraph()

    Return the truncated icosidodecahedron.

    The truncated icosidodecahedron is an Archimedean solid with 30 square faces, 20 regular hexagonal faces, 12 regular decagonal faces, 120 vertices and 180 edges. For more information, see the Wikipedia article Truncated_icosidodecahedron.

    EXAMPLES:

    Unfortunately, this graph can not be constructed currently, due to numerical issues:

    Sage

        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                            # needs sage.geometry.polyhedron sage.groups sage.rings.number_field
        (120, 180)

    Python

        >>> from sage.all import *
        >>> 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.
        >>> g.order(), g.size()               # not tested                            # needs sage.geometry.polyhedron sage.groups sage.rings.number_field
        (120, 180)

  static TruncatedTetrahedralGraph()

    Return the truncated tetrahedron.

    The truncated tetrahedron is an Archimedean solid with 12 vertices and 18 edges. For more information, see the Wikipedia article Truncated_tetrahedron.

    EXAMPLES:

    Sage

        sage: g = graphs.TruncatedTetrahedralGraph(); g
        Truncated Tetrahedron: Graph on 12 vertices
        sage: g.order(), g.size()
        (12, 18)
        sage: g.is_isomorphic(polytopes.simplex(3).truncation().graph())                # needs sage.geometry.polyhedron
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.TruncatedTetrahedralGraph(); g
        Truncated Tetrahedron: Graph on 12 vertices
        >>> g.order(), g.size()
        (12, 18)
        >>> g.is_isomorphic(polytopes.simplex(Integer(3)).truncation().graph())                # needs sage.geometry.polyhedron
        True

  static TruncatedWittGraph(immutable=False)

    Return the truncated Witt graph.

    This builds the large Witt graph, then removes all vertices whose codeword start with a 1.

    The graph is distance-regular with intersection array \([15,14,12;1,1,9]\).

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Sage

        sage: # long time, needs sage.libs.pari sage.modules
        sage: G = graphs.TruncatedWittGraph()
        sage: G.is_distance_regular(True)
        ([15, 14, 12, None], [None, 1, 1, 9])

    Python

        >>> from sage.all import *
        >>> # long time, needs sage.libs.pari sage.modules
        >>> G = graphs.TruncatedWittGraph()
        >>> G.is_distance_regular(True)
        ([15, 14, 12, None], [None, 1, 1, 9])

    REFERENCES:

    A description and construction of this graph can be found in [BCN1989] p. 367.

  static TuranGraph(n, r)

    Return the Turan graph with parameters \(n, r\).

    Turan graphs are complete multipartite graphs with \(n\) vertices and \(r\) subsets, denoted \(T(n,r)\), with the property that the sizes of the subsets are as close to equal as possible. The graph \(T(n,r)\) will have \(n \pmod r\) subsets of size \(\lfloor n/r \rfloor\) and \(r - (n \pmod r)\) subsets of size \(\lceil n/r \rceil\). See the Wikipedia article Turan_graph for more information.

    INPUT:

    - `n` – integer; the number of vertices in the graph

    - `r` – integer; the number of partitions of the graph

    EXAMPLES:

    The Turan graph is a complete multipartite graph:

    Sage

        sage: g = graphs.TuranGraph(13, 4)
        sage: k = graphs.CompleteMultipartiteGraph([3,3,3,4])
        sage: g.is_isomorphic(k)
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.TuranGraph(Integer(13), Integer(4))
        >>> k = graphs.CompleteMultipartiteGraph([Integer(3),Integer(3),Integer(3),Integer(4)])
        >>> g.is_isomorphic(k)
        True

    The Turan graph \(T(n,r)\) has \(\frac{(r-1)(n^2-s^2)}{2r} + \frac{s(s-1)}{2}\) edges, where \(s = n \mod r\) (Issue #34249):

    Sage

        sage: n = 12
        sage: r = 8
        sage: g = graphs.TuranGraph(n, r)
        sage: def count(n, r):
        ....:     s = n % r
        ....:     return (r - 1) * (n**2 - s**2) / (2*r) + s*(s - 1)/2
        sage: g.size() == count(n, r)
        True
        sage: n = randint(3, 100)
        sage: r = randint(2, n - 1)
        sage: g = graphs.TuranGraph(n, r)
        sage: g.size() == count(n, r)
        True

    [Python]

        >>> from sage.all import *
        >>> n = Integer(12)
        >>> r = Integer(8)
        >>> g = graphs.TuranGraph(n, r)
        >>> def count(n, r):
        ...     s = n % r
        ...     return (r - Integer(1)) * (n**Integer(2) - s**Integer(2)) / (Integer(2)*r) + s*(s - Integer(1))/Integer(2)
        >>> g.size() == count(n, r)
        True
        >>> n = randint(Integer(3), Integer(100))
        >>> r = randint(Integer(2), n - Integer(1))
        >>> g = graphs.TuranGraph(n, r)
        >>> g.size() == count(n, r)
        True

  static Tutte12Cage()

    Return the Tutte 12-Cage.

    See the Wikipedia article Tutte_12-cage.

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.Tutte12Cage()
        sage: g.order()
        126
        sage: g.size()
        189
        sage: g.girth()
        12
        sage: g.diameter()
        6
        sage: g.show()                                                                  # needs sage.plot

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.Tutte12Cage()
        >>> g.order()
        126
        >>> g.size()
        189
        >>> g.girth()
        12
        >>> g.diameter()
        6
        >>> g.show()                                                                  # needs sage.plot

  static TutteCoxeterGraph(embedding=2)

    Return the Tutte-Coxeter graph.

    See the Wikipedia article Tutte-Coxeter_graph.

    INPUT:

    - `embedding` – integer (default: \(2\)); two embeddings are available, and can be selected by setting `embedding` to 1 or 2

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.TutteCoxeterGraph()
        sage: g.order()
        30
        sage: g.size()
        45
        sage: g.girth()
        8
        sage: g.diameter()
        4
        sage: g.show()                                                                  # needs sage.plot
        sage: graphs.TutteCoxeterGraph(embedding=1).show()      # long time             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.TutteCoxeterGraph()
        >>> g.order()
        30
        >>> g.size()
        45
        >>> g.girth()
        8
        >>> g.diameter()
        4
        >>> g.show()                                                                  # needs sage.plot
        >>> graphs.TutteCoxeterGraph(embedding=Integer(1)).show()      # long time             # needs sage.plot

  static TutteGraph()

    Return the Tutte Graph.

    The Tutte graph is a 3-regular, 3-connected, and planar non-hamiltonian graph. For more information on the Tutte Graph, see the Wikipedia article Tutte_graph.

    EXAMPLES:

    Sage

        sage: g = graphs.TutteGraph()
        sage: g.order()
        46
        sage: g.size()
        69
        sage: g.is_planar()
        True
        sage: g.vertex_connectivity()           # long time                             # needs sage.numerical.mip
        3
        sage: g.girth()
        4
        sage: g.automorphism_group().cardinality()                                      # needs sage.groups
        3
        sage: g.is_hamiltonian()                                                        # needs sage.numerical.mip
        False

    Python

        >>> from sage.all import *
        >>> g = graphs.TutteGraph()
        >>> g.order()
        46
        >>> g.size()
        69
        >>> g.is_planar()
        True
        >>> g.vertex_connectivity()           # long time                             # needs sage.numerical.mip
        3
        >>> g.girth()
        4
        >>> g.automorphism_group().cardinality()                                      # needs sage.groups
        3
        >>> g.is_hamiltonian()                                                        # needs sage.numerical.mip
        False

  static TwinplexGraph(embedding='LM')

    Return the Twinplex graph.

    The Twinplex graph is a cubic hamiltonian graph of order 12 with the graph crossing number 2 and has a girth 5 (that is the maximal girth among all cubic graphs on 12 vertices [CHNP2020]). It corresponds to the graph labeled as \(\Gamma_2\) by Fischer and Little [FiLi2001]. The Twinplex graph has LCF notation \([-5, -4, 4, -4, 4, 5, -4, 5, -4, 4, -5, 4]\).

    The Fischer-Little Theorem [FiLi2001] may be stated as follows [LM2024]:

    A near-bipartite graph is non-Pfaffian if and only if it contains one of the graphs \(K_{3, 3}\), \(\Gamma_1\) and \(\Gamma_2\) as an \(S\)-minor.

    Norine and Thomas [NT2007] use the term `Twinplex` to describe one of the 12-vertex cubic graphs, \(\Gamma_1\) and \(\Gamma_2\), as defined by Fischer and Little [FiLi2001]. However, the figure in their paper that supposedly provides embeddings for the graphs labeled Cubeplex and Twinplex actually shows both embeddings corresponding to Fischer and Little’s \(\Gamma_1\), which is the Cubeplex graph. Followingly, for `embedding='NT'`, we present a correct version of the Twinplex graph with a slight modification of the embedding that is labeled as `Twinplex` in the paper of Norine and Thomas [NT2007].

    PLOTTING:

    Upon construction, the position dictionary is filled to override the spring-layout algorithm. For different values of the parameter `embedding`, the Twinplex graph is displayed as it is mentioned in the respective paper/ book. Note that for `embedding='NT'`, a correct embedding of the Twinplex graph is displayed with a minor modification to the (incorrect) embedding shown in the paper [NT2007].

    INPUT:

    - `embedding` – string (default: `'LM'`)

      - `'LM'` displays the embedding as shown for \(\Gamma_2\) by Lucchesi and Murty [LM2024]

      - `'FL'` displays the embedding as shown for \(\Gamma_2\) by Fischer and Little [FiLi2001]

      - `'NT'` displays the correct embedding with a minor modification to the one shown as the (incorrect) `Twinplex` by Norine and Thomas [NT2007]

      - `'RST'` displays the embedding as shown for the `Twinplex` by Robertson, Seymour and Thomas [RST2019]

    OUTPUT:

    - `G` – the Twinplex graph; note that a `ValueError` is returned if `embedding` is none of `'FT'`, `'NT'`, `'RST'` or `'LM'`

    EXAMPLES:

    Construct and show the Twinplex graph:

    Sage

        sage: g = graphs.TwinplexGraph()
        sage: g.name()
        'Twinplex Graph'
        sage: g.order()
        12
        sage: g.size()
        18
        sage: g.girth()
        5
        sage: g.diameter()
        3
        sage: g.is_hamiltonian()
        True
        sage: g.crossing_number()
        2
        sage: g.show()                          # long time                             # needs sage.plot

    Python

        >>> from sage.all import *
        >>> g = graphs.TwinplexGraph()
        >>> g.name()
        'Twinplex Graph'
        >>> g.order()
        12
        >>> g.size()
        18
        >>> g.girth()
        5
        >>> g.diameter()
        3
        >>> g.is_hamiltonian()
        True
        >>> g.crossing_number()
        2
        >>> g.show()                          # long time                             # needs sage.plot

    See also

    `CubeplexGraph()`

    AUTHORS:

    - Janmenjaya Panda (2024-08-03)

  static U42Graph216()

    Return a (216,40,4,8)-strongly regular graph from [CRS2016].

    Build the graph, interpreting the \(U_4(2)\)-action considered in [CRS2016] as the one on the hyperbolic lines of the corresponding unitary polar space, and then doing the unique merging of the orbitals leading to a graph with the parameters in question.

    EXAMPLES:

    Sage

        sage: G=graphs.U42Graph216()                    # optional - gap_package_grape
        sage: G.is_strongly_regular(parameters=True)    # optional - gap_package_grape
        (216, 40, 4, 8)

    Python

        >>> from sage.all import *
        >>> G=graphs.U42Graph216()                    # optional - gap_package_grape
        >>> G.is_strongly_regular(parameters=True)    # optional - gap_package_grape
        (216, 40, 4, 8)

  static U42Graph540()

    Return a (540,187,58,68)-strongly regular graph from [CRS2016].

    Build the graph, interpreting the \(U_4(2)\)-action considered in [CRS2016] as the action of \(U_4(2)=Sp_4(3)<U_4(3)\) on the nonsingular, w.r.t. to the Hermitean form stabilised by \(U_4(3)\), points of the 3-dimensional projective space over \(GF(9)\). There are several possible mergings of orbitals, some leading to non-isomorphic graphs with the same parameters. We found the merging here using [FK1991].

    EXAMPLES:

    Sage

        sage: G = graphs.U42Graph540()                  # optional - gap_package_grape
        sage: G.is_strongly_regular(parameters=True)    # optional - gap_package_grape
        (540, 187, 58, 68)

    Python

        >>> from sage.all import *
        >>> G = graphs.U42Graph540()                  # optional - gap_package_grape
        >>> G.is_strongly_regular(parameters=True)    # optional - gap_package_grape
        (540, 187, 58, 68)

  static USAMap(continental=False)

    Return states of USA as a graph of common border.

    The graph has an edge between those states that have common land border line or point. Hence for example Colorado and Arizona are marked as neighbors, but Michigan and Minnesota are not.

    INPUT:

    - `continental` – boolean (default: `False`); whether to exclude Alaska and Hawaii

    EXAMPLES:

    How many states are neighbor’s neighbor for Pennsylvania:

    Sage

        sage: USA = graphs.USAMap()
        sage: distance = USA.shortest_path_lengths('Pennsylvania')
        sage: len([n2 for n2, d in distance.items() if d == 2])
        7

    Python

        >>> from sage.all import *
        >>> USA = graphs.USAMap()
        >>> distance = USA.shortest_path_lengths('Pennsylvania')
        >>> len([n2 for n2, d in distance.items() if d == Integer(2)])
        7

    Diameter for continental USA:

    Sage

        sage: USAcont = graphs.USAMap(continental=True)
        sage: USAcont.diameter()
        11

    [Python]

        >>> from sage.all import *
        >>> USAcont = graphs.USAMap(continental=True)
        >>> USAcont.diameter()
        11

  static UnitaryDualPolarGraph(m, q)

    Return the Dual Unitary Polar Graph \(U(m,q)\).

    For more information on Unitary Dual Polar graphs, see [BCN1989] and Sect. 2.3.1 of [Coh1981].

    INPUT:

    - `m`, `q` – integers; \(q\) must be a prime power

    EXAMPLES:

    The point graph of a generalized quadrangle (see Wikipedia article Generalized_quadrangle, [PT2009]) of order (8,4):

    Sage

        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
        (297, 40, 7, 5)

    Python

        >>> from sage.all import *
        >>> G = graphs.UnitaryDualPolarGraph(Integer(5),Integer(2)); G  # long time                     # needs sage.libs.gap
        Unitary Dual Polar Graph DU(5, 2); GQ(8, 4): Graph on 297 vertices
        >>> 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

        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,'-'))                     # needs sage.libs.gap
        True

    [Python]

        >>> from sage.all import *
        >>> G = graphs.UnitaryDualPolarGraph(Integer(4),Integer(2)); G                                  # needs sage.libs.gap
        Unitary Dual Polar Graph DU(4, 2); GQ(2, 4): Graph on 27 vertices
        >>> G.is_isomorphic(graphs.OrthogonalPolarGraph(Integer(6),Integer(2),'-'))                     # needs sage.libs.gap
        True

    A bigger graph:

    Sage

        sage: G = graphs.UnitaryDualPolarGraph(6,2); G   # not tested (long time)
        Unitary Dual Polar Graph DU(6, 2): Graph on 891 vertices
        sage: G.is_distance_regular(parameters=True)     # not tested (long time)
        ([42, 40, 32, None], [None, 1, 5, 21])

    Python

        >>> from sage.all import *
        >>> G = graphs.UnitaryDualPolarGraph(Integer(6),Integer(2)); G   # not tested (long time)
        Unitary Dual Polar Graph DU(6, 2): Graph on 891 vertices
        >>> G.is_distance_regular(parameters=True)     # not tested (long time)
        ([42, 40, 32, None], [None, 1, 5, 21])

  static UnitaryPolarGraph(m, q, algorithm='gap')

    Return the Unitary Polar Graph \(U(m,q)\).

    For more information on Unitary Polar graphs, see the page of Andries Brouwer’s website.

    INPUT:

    - `m`, `q` – integers; \(q\) must be a prime power

    - `algorithm` – string (default: `'gap'`); if set to `'gap'` then the computation is carried via GAP library interface, computing totally singular subspaces, which is faster for large examples (especially with \(q>2\)). Otherwise it is done directly.

    EXAMPLES:

    Sage

        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)
        (45, 12, 3, 3)
        sage: graphs.UnitaryPolarGraph(5,2).is_strongly_regular(parameters=True)
        (165, 36, 3, 9)
        sage: graphs.UnitaryPolarGraph(6,2)     # not tested (long time)
        Unitary Polar Graph U(6, 2): Graph on 693 vertices

    Python

        >>> from sage.all import *
        >>> # needs sage.libs.gap
        >>> G = graphs.UnitaryPolarGraph(Integer(4),Integer(2)); G
        Unitary Polar Graph U(4, 2); GQ(4, 2): Graph on 45 vertices
        >>> G.is_strongly_regular(parameters=True)
        (45, 12, 3, 3)
        >>> graphs.UnitaryPolarGraph(Integer(5),Integer(2)).is_strongly_regular(parameters=True)
        (165, 36, 3, 9)
        >>> graphs.UnitaryPolarGraph(Integer(6),Integer(2))     # not tested (long time)
        Unitary Polar Graph U(6, 2): Graph on 693 vertices

  static UstimenkoGraph(m, q)

    Return the Ustimenko graph with parameters \((m, q)\).

    This is the distance 1 or 2 graph of the dual polar graph \(C_{m-1}(q)\). The graph is distance-regular with parameters \((d,q^2, \binom{3}{1}_q -1, \binom{m+1}{1}_q -1)\), where \(\binom{n}{k}_q\) is the \(q\)-binomial coefficient.

    INPUT:

    - `m`, `q` – integers; \(q\) must be a prime power and \(m > 1\)

    EXAMPLES:

    Sage

        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])

    Python

        >>> from sage.all import *
        >>> G = graphs.UstimenkoGraph(Integer(4), Integer(2))                                           # needs sage.libs.gap
        >>> G.is_distance_regular(True)                                               # needs sage.libs.gap
        ([70, 32, None], [None, 1, 35])

    REFERENCES:

    See [BCN1989] p. 279 or [VDKT2016] p. 22.

  static WagnerGraph()

    Return the Wagner Graph.

    See the Wikipedia article Wagner_graph.

    EXAMPLES:

    Sage

        sage: # needs networkx
        sage: g = graphs.WagnerGraph()
        sage: g.order()
        8
        sage: g.size()
        12
        sage: g.girth()
        4
        sage: g.diameter()
        2
        sage: g.show()                                                                  # needs sage.plot

    Python

        >>> from sage.all import *
        >>> # needs networkx
        >>> g = graphs.WagnerGraph()
        >>> g.order()
        8
        >>> g.size()
        12
        >>> g.girth()
        4
        >>> g.diameter()
        2
        >>> g.show()                                                                  # needs sage.plot

  static WatkinsSnarkGraph()

    Return the Watkins Snark Graph.

    The Watkins Graph is a snark with 50 vertices and 75 edges. For more information, see the Wikipedia article Watkins_snark.

    EXAMPLES:

    Sage

        sage: g = graphs.WatkinsSnarkGraph()
        sage: g.order()
        50
        sage: g.size()
        75
        sage: g.chromatic_number()
        3

    Python

        >>> from sage.all import *
        >>> g = graphs.WatkinsSnarkGraph()
        >>> g.order()
        50
        >>> g.size()
        75
        >>> g.chromatic_number()
        3

  static WellsGraph()

    Return the Wells graph.

    For more information on the Wells graph (also called Armanios-Wells graph), see this page.

    The implementation follows the construction given on page 266 of [BCN1989]. This requires to create intermediate graphs and run a small isomorphism test, while everything could be replaced by a pre-computed list of edges. I believe that it is better to keep “the recipe” in the code, however, as it is quite unlikely that this could become the most time-consuming operation in any sensible algorithm, and …. “preserves knowledge”, which is what open-source software is meant to do.

    EXAMPLES:

    Sage

        sage: g = graphs.WellsGraph(); g
        Wells graph: Graph on 32 vertices
        sage: g.order()
        32
        sage: g.size()
        80
        sage: g.girth()
        5
        sage: g.diameter()
        4
        sage: g.chromatic_number()
        4
        sage: g.is_regular(k=5)
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.WellsGraph(); g
        Wells graph: Graph on 32 vertices
        >>> g.order()
        32
        >>> g.size()
        80
        >>> g.girth()
        5
        >>> g.diameter()
        4
        >>> g.chromatic_number()
        4
        >>> g.is_regular(k=Integer(5))
        True

  static WheelGraph(n)

    Return a Wheel graph with \(n\) nodes.

    A Wheel graph is a basic structure where one node is connected to all other nodes and those (outer) nodes are connected cyclically.

    PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each wheel graph will be displayed with the first (0) node in the center, the second node at the top, and the rest following in a counterclockwise manner.

    With the wheel graph, we see that it doesn’t take a very large \(n\) at all for the spring-layout to give a counter-intuitive display. (See Graphics Array examples below).

    EXAMPLES:

    We view many wheel graphs with a Sage Graphics Array, first with this constructor (i.e., the position dictionary filled):

    Sage

        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):
        ....:  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)
        sage: G.show()                          # long time

    Python

        >>> from sage.all import *
        >>> # needs sage.plot
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...  k = graphs.WheelGraph(i+Integer(3))
        ...  g.append(k)
        ...
        >>> for i in range(Integer(3)):
        ...  n = []
        ...  for m in range(Integer(3)):
        ...      n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...  j.append(n)
        ...
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    Next, using the spring-layout algorithm:

    Sage

        sage: # needs networkx sage.plot
        sage: import networkx
        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:  spr = networkx.wheel_graph(i+3)
        ....:  k = Graph(spr)
        ....:  g.append(k)
        ...
        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)
        sage: G.show()                          # long time

    [Python]

        >>> from sage.all import *
        >>> # needs networkx sage.plot
        >>> import networkx
        >>> g = []
        >>> j = []
        >>> for i in range(Integer(9)):
        ...  spr = networkx.wheel_graph(i+Integer(3))
        ...  k = Graph(spr)
        ...  g.append(k)
        ...
        >>> for i in range(Integer(3)):
        ...  n = []
        ...  for m in range(Integer(3)):
        ...      n.append(g[Integer(3)*i + m].plot(vertex_size=Integer(50), vertex_labels=False))
        ...  j.append(n)
        ...
        >>> G = graphics_array(j)
        >>> G.show()                          # long time

    Compare the plotting:

    Sage

        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
        sage: posdict23.show()  # long time

    Python

        >>> from sage.all import *
        >>> # needs networkx sage.plot
        >>> n = networkx.wheel_graph(Integer(23))
        >>> spring23 = Graph(n)
        >>> posdict23 = graphs.WheelGraph(Integer(23))
        >>> spring23.show()                   # long time
        >>> posdict23.show()  # long time

  static WienerArayaGraph()

    Return the Wiener-Araya Graph.

    The Wiener-Araya Graph is a planar hypohamiltonian graph on 42 vertices and 67 edges. For more information, see the Wolfram Page on the Wiener-Araya Graph or Wikipedia article Wiener-Araya_graph.

    EXAMPLES:

    Sage

        sage: g = graphs.WienerArayaGraph()
        sage: g.order()
        42
        sage: g.size()
        67
        sage: g.girth()
        4
        sage: g.is_planar()
        True
        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
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.WienerArayaGraph()
        >>> g.order()
        42
        >>> g.size()
        67
        >>> g.girth()
        4
        >>> g.is_planar()
        True
        >>> g.is_hamiltonian()                # not tested (30s)                      # needs sage.numerical.mip
        False
        >>> g.delete_vertex(g.random_vertex())
        >>> g.is_hamiltonian()                                                        # needs sage.numerical.mip
        True

  static WindmillGraph(k, n)

    Return the Windmill graph \(Wd(k, n)\).

    The windmill graph \(Wd(k, n)\) is an undirected graph constructed for \(k \geq 2\) and \(n \geq 2\) by joining \(n\) copies of the complete graph \(K_k\) at a shared vertex. It has \((k-1)n+1\) vertices and \(nk(k-1)/2\) edges, girth 3 (if \(k > 2\)), radius 1 and diameter 2. It has vertex connectivity 1 because its central vertex is an articulation point; however, like the complete graphs from which it is formed, it is \((k-1)\)-edge-connected. It is trivially perfect and a block graph.

    See also

    - Wikipedia article Windmill_graph

    - `GraphGenerators.StarGraph()`

    - `GraphGenerators.FriendshipGraph()`

    EXAMPLES:

    The Windmill graph \(Wd(2, n)\) is a star graph:

    Sage

        sage: n = 5
        sage: W = graphs.WindmillGraph(2, n)
        sage: W.is_isomorphic( graphs.StarGraph(n) )
        True

    Python

        >>> from sage.all import *
        >>> n = Integer(5)
        >>> W = graphs.WindmillGraph(Integer(2), n)
        >>> W.is_isomorphic( graphs.StarGraph(n) )
        True

    The Windmill graph \(Wd(3, n)\) is the Friendship graph \(F_n\):

    Sage

        sage: n = 5
        sage: W = graphs.WindmillGraph(3, n)
        sage: W.is_isomorphic( graphs.FriendshipGraph(n) )
        True

    [Python]

        >>> from sage.all import *
        >>> n = Integer(5)
        >>> W = graphs.WindmillGraph(Integer(3), n)
        >>> W.is_isomorphic( graphs.FriendshipGraph(n) )
        True

    The Windmill graph \(Wd(3, 2)\) is the Butterfly graph:

    Sage

        sage: W = graphs.WindmillGraph(3, 2)
        sage: W.is_isomorphic( graphs.ButterflyGraph() )
        True

    Python

        >>> from sage.all import *
        >>> W = graphs.WindmillGraph(Integer(3), Integer(2))
        >>> W.is_isomorphic( graphs.ButterflyGraph() )
        True

    The Windmill graph \(Wd(k, n)\) has chromatic number \(k\):

    Sage

        sage: n,k = 5,6
        sage: W = graphs.WindmillGraph(k, n)
        sage: W.chromatic_number() == k
        True

    [Python]

        >>> from sage.all import *
        >>> n,k = Integer(5),Integer(6)
        >>> W = graphs.WindmillGraph(k, n)
        >>> W.chromatic_number() == k
        True

  static WorldMap()

    Return the Graph of all the countries, in which two countries are adjacent in the graph if they have a common boundary.

    This graph has been built from the data available in The CIA World Factbook [CIA] (2009-08-21).

    The returned graph `G` has a member `G.gps_coordinates` equal to a dictionary containing the GPS coordinates of each country’s capital city.

    EXAMPLES:

    Sage

        sage: g = graphs.WorldMap()
        sage: g.has_edge("France", "Italy")
        True
        sage: g.gps_coordinates["Bolivia"]
        [[17, 'S'], [65, 'W']]
        sage: g.connected_component_containing_vertex('Ireland', sort=True)
        ['Ireland', 'United Kingdom']

    Python

        >>> from sage.all import *
        >>> g = graphs.WorldMap()
        >>> g.has_edge("France", "Italy")
        True
        >>> g.gps_coordinates["Bolivia"]
        [[17, 'S'], [65, 'W']]
        >>> g.connected_component_containing_vertex('Ireland', sort=True)
        ['Ireland', 'United Kingdom']

  basic = <module 'sage.graphs.generators.basic' from '/usr/lib/python3.13/site-packages/sage/graphs/generators/basic.py'>
  static chang_graphs()

    Return the three Chang graphs.

    Three of the four strongly regular graphs of parameters \((28,12,6,4)\) are called the Chang graphs. The fourth is the line graph of \(K_8\). For more information about the Chang graphs, see the Wikipedia article Chang_graphs or https://www.win.tue.nl/~aeb/graphs/Chang.html.

    EXAMPLES: check that we get 4 non-isomorphic s.r.g.’s with the same parameters:

    Sage

        sage: chang_graphs = graphs.chang_graphs()
        sage: K8 = graphs.CompleteGraph(8)
        sage: T8 = K8.line_graph()
        sage: four_srg = chang_graphs + [T8]
        sage: for g in four_srg:
        ....:     print(g.is_strongly_regular(parameters=True))
        (28, 12, 6, 4)
        (28, 12, 6, 4)
        (28, 12, 6, 4)
        (28, 12, 6, 4)
        sage: from itertools import combinations
        sage: for g1,g2 in combinations(four_srg,2):
        ....:     assert not g1.is_isomorphic(g2)

    Python

        >>> from sage.all import *
        >>> chang_graphs = graphs.chang_graphs()
        >>> K8 = graphs.CompleteGraph(Integer(8))
        >>> T8 = K8.line_graph()
        >>> four_srg = chang_graphs + [T8]
        >>> for g in four_srg:
        ...     print(g.is_strongly_regular(parameters=True))
        (28, 12, 6, 4)
        (28, 12, 6, 4)
        (28, 12, 6, 4)
        (28, 12, 6, 4)
        >>> from itertools import combinations
        >>> for g1,g2 in combinations(four_srg,Integer(2)):
        ...     assert not g1.is_isomorphic(g2)

    Construct the Chang graphs by Seidel switching:

    Sage

        sage: c3c5 = graphs.CycleGraph(3).disjoint_union(graphs.CycleGraph(5))
        sage: c8 = graphs.CycleGraph(8)
        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)                   # needs sage.modules
        ....:  for x, G in zip(s, chang_graphs)]
        [True, True, True]

    [Python]

        >>> from sage.all import *
        >>> c3c5 = graphs.CycleGraph(Integer(3)).disjoint_union(graphs.CycleGraph(Integer(5)))
        >>> c8 = graphs.CycleGraph(Integer(8))
        >>> s = [K8.subgraph_search(c8).edges(sort=False),                            # needs sage.modules
        ...      [(Integer(0),Integer(1),None),(Integer(2),Integer(3),None),(Integer(4),Integer(5),None),(Integer(6),Integer(7),None)],
        ...      K8.subgraph_search(c3c5).edges(sort=False)]
        >>> [T8.seidel_switching(x, inplace=False).is_isomorphic(G)                   # needs sage.modules
        ...  for x, G in zip(s, chang_graphs)]
        [True, True, True]

  chessboard = <module 'sage.graphs.generators.chessboard' from '/usr/lib/python3.13/site-packages/sage/graphs/generators/chessboard.py'>
  classical_geometries = <module 'sage.graphs.generators.classical_geometries' from '/usr/lib/python3.13/site-packages/sage/graphs/generators/classical_geometries.py'>
  static cocliques_HoffmannSingleton(immutable=False)

    Return the graph obtained from the cocliques of the Hoffmann-Singleton graph.

    This is a distance-regular graph with intersection array \([15, 14, 10, 3; 1, 5, 12, 15]\).

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Sage

        sage: G = graphs.cocliques_HoffmannSingleton()
        sage: G.is_distance_regular(True)
        ([15, 14, 10, 3, None], [None, 1, 5, 12, 15])

    Python

        >>> from sage.all import *
        >>> G = graphs.cocliques_HoffmannSingleton()
        >>> G.is_distance_regular(True)
        ([15, 14, 10, 3, None], [None, 1, 5, 12, 15])

    REFERENCES:

    The construction of this graph can be found in [BCN1989] p. 392.

  static cographs(n, as_graph=True, immutable=False)

    Return an iterator over the cographs of order \(n\).

    A cograph is a \(P_4\)-free graph, that is a graph without induced path of order 4. Any cograph may be constructed, starting from the single vertex graph, by a sequence of `sage.graphs.graph.Graph.join()` and `sage.graphs.generic_graph.GenericGraph.disjoint_union()` operations. See the Wikipedia article Cograph for more details.

    This method implements the generator of all cographs of order \(n\) proposed in [JPD2018]. The algorithm generates one by one every cotree with \(n\) nodes, and each cotree is generated by using its previous cotree. The time to construct the first cotree is \(O(n)\) and the time spent between two consecutive outputs is \(O(n)\). Hence, the overall complexity of the algorithm is \(O(n*M_n)\), where \(n\) is the number of nodes and \(M_n\) is the total number of cographs with \(n\) nodes (see OEIS sequence A000084).

    INPUT:

    - `n` – integer larger or equal to 1

    - `as_graph` – boolean (default: `True`); whether to return graphs or the tree data structure encoding the graph

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph. This parameter is used only when `as_graph is True`.

    EXAMPLES:

    The output can be either cotrees or graphs:

    Sage

        sage: for t in graphs.cographs(3, as_graph=False):
        ....:     print(t)
        [ J ( 0 ) ( 1 ) ( 2 ) ]
        [ J [ U ( 0 ) ( 1 ) ( 2 ) ] ]
        [ J ( 0 ) [ U ( 1 ) ( 2 ) ] ]
        [ J [ U ( 0 ) [ J ( 1 ) ( 2 ) ] ] ]
        sage: for g in graphs.cographs(3, as_graph=True):
        ....:     print(g.edges(labels=False, sort=True))
        [(0, 1), (0, 2), (1, 2)]
        []
        [(0, 1), (0, 2)]
        [(1, 2)]

    Python

        >>> from sage.all import *
        >>> for t in graphs.cographs(Integer(3), as_graph=False):
        ...     print(t)
        [ J ( 0 ) ( 1 ) ( 2 ) ]
        [ J [ U ( 0 ) ( 1 ) ( 2 ) ] ]
        [ J ( 0 ) [ U ( 1 ) ( 2 ) ] ]
        [ J [ U ( 0 ) [ J ( 1 ) ( 2 ) ] ] ]
        >>> for g in graphs.cographs(Integer(3), as_graph=True):
        ...     print(g.edges(labels=False, sort=True))
        [(0, 1), (0, 2), (1, 2)]
        []
        [(0, 1), (0, 2)]
        [(1, 2)]

    Check that we agree with OEIS sequence A000084:

    Sage

        sage: [sum(1 for _ in graphs.cographs(n, as_graph=False))
        ....:  for n in range(1, 8)]
        [1, 2, 4, 10, 24, 66, 180]

    [Python]

        >>> from sage.all import *
        >>> [sum(Integer(1) for _ in graphs.cographs(n, as_graph=False))
        ...  for n in range(Integer(1), Integer(8))]
        [1, 2, 4, 10, 24, 66, 180]

  cographs_module = <module 'sage.graphs.cographs' from '/usr/lib/python3.13/site-packages/sage/graphs/cographs.py'>
  cospectral_graphs(vertices, matrix_function=None, graphs=None, immutable=False)

    Find all sets of graphs on `vertices` vertices (with possible restrictions) which are cospectral with respect to a constructed matrix.

    INPUT:

    - `vertices` – the number of vertices in the graphs to be tested

    - `matrix_function` – a function taking a graph and giving back a matrix. This defaults to the adjacency matrix. The spectra examined are the spectra of these matrices.

    - `graphs` – one of three things:

      > - `None` – default; test all graphs having `vertices` vertices

      > - a function taking a graph and returning `True` or `False` - test only the graphs on `vertices` vertices for which the function returns `True`

      > - a list of graphs (or other iterable object) – these graphs are tested for cospectral sets. In this case, `vertices` is ignored.

    - `immutable` – boolean (default: `False`); whether to return immutable or mutable graphs

    OUTPUT:

    > A list of lists of graphs. Each sublist will be a list of cospectral graphs (lists of cardinality 1 being omitted).

    See also

    `Graph.is_strongly_regular()` – tests whether a graph is strongly regular and/or returns its parameters.

    EXAMPLES:

    Sage

        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()                      # needs sage.modules
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.cospectral_graphs(Integer(5))                                       # needs sage.modules
        >>> sorted(sorted(g.graph6_string() for g in glist) for glist in g)       # needs sage.modules
        [['Dr?', 'Ds_']]
        >>> g[Integer(0)][Integer(1)].am().charpoly()==g[Integer(0)][Integer(1)].am().charpoly()                      # needs sage.modules
        True

    There are two sets of cospectral graphs on six vertices with no isolated vertices:

    Sage

        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()
        True
        sage: g[1][1].am().charpoly()==g[1][1].am().charpoly()
        True

    [Python]

        >>> from sage.all import *
        >>> # needs sage.modules
        >>> g = graphs.cospectral_graphs(Integer(6), graphs=lambda x: min(x.degree())>Integer(0))
        >>> sorted(sorted(g.graph6_string() for g in glist) for glist in g)
        [['Ep__', 'Er?G'], ['ExGg', 'ExoG']]
        >>> g[Integer(0)][Integer(1)].am().charpoly()==g[Integer(0)][Integer(1)].am().charpoly()
        True
        >>> g[Integer(1)][Integer(1)].am().charpoly()==g[Integer(1)][Integer(1)].am().charpoly()
        True

    There is one pair of cospectral trees on eight vertices:

    Sage

        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()                      # needs sage.modules
        True

    Python

        >>> from sage.all import *
        >>> g = graphs.cospectral_graphs(Integer(6), graphs=graphs.trees(Integer(8)))               # needs sage.modules
        >>> sorted(sorted(g.graph6_string() for g in glist) for glist in g)       # needs sage.modules
        [['GiPC?C', 'GiQCC?']]
        >>> g[Integer(0)][Integer(1)].am().charpoly()==g[Integer(0)][Integer(1)].am().charpoly()                      # needs sage.modules
        True

    There are two sets of cospectral graphs (with respect to the Laplacian matrix) on six vertices:

    Sage

        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()
        True
        sage: g[1][1].laplacian_matrix().charpoly()==g[1][1].laplacian_matrix().charpoly()
        True

    [Python]

        >>> from sage.all import *
        >>> # needs sage.modules
        >>> g = graphs.cospectral_graphs(Integer(6), matrix_function=lambda g: g.laplacian_matrix())
        >>> sorted(sorted(g.graph6_string() for g in glist) for glist in g)
        [['Edq_', 'ErcG'], ['Exoo', 'EzcG']]
        >>> g[Integer(0)][Integer(1)].laplacian_matrix().charpoly()==g[Integer(0)][Integer(1)].laplacian_matrix().charpoly()
        True
        >>> g[Integer(1)][Integer(1)].laplacian_matrix().charpoly()==g[Integer(1)][Integer(1)].laplacian_matrix().charpoly()
        True

    To find cospectral graphs with respect to the normalized Laplacian, assuming the graphs do not have an isolated vertex, it is enough to check the spectrum of the matrix \(D^{-1}A\), where \(D\) is the diagonal matrix of vertex degrees, and A is the adjacency matrix. We find two such cospectral graphs (for the normalized Laplacian) on five vertices:

    Sage

        sage: def DinverseA(g):
        ....:   A = g.adjacency_matrix().change_ring(QQ)
        ....:   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,            # needs sage.libs.pari 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()                 # needs sage.modules sage.symbolic
        ....:   == g[0][1].laplacian_matrix(normalized=True).charpoly())
        True

    Python

        >>> from sage.all import *
        >>> def DinverseA(g):
        ...   A = g.adjacency_matrix().change_ring(QQ)
        ...   for i in range(g.order()):
        ...       A.rescale_row(i, Integer(1) / len(A.nonzero_positions_in_row(i)))
        ...   return A
        >>> g = graphs.cospectral_graphs(Integer(5), matrix_function=DinverseA,            # needs sage.libs.pari sage.modules
        ...                              graphs=lambda g: min(g.degree()) > Integer(0))
        >>> sorted(sorted(g.graph6_string() for g in glist) for glist in g)       # needs sage.modules
        [['Dlg', 'Ds_']]
        >>> (g[Integer(0)][Integer(1)].laplacian_matrix(normalized=True).charpoly()                 # needs sage.modules sage.symbolic
        ...   == g[Integer(0)][Integer(1)].laplacian_matrix(normalized=True).charpoly())
        True

  degree_sequence = <module 'sage.graphs.generators.degree_sequence' from '/usr/lib/python3.13/site-packages/sage/graphs/generators/degree_sequence.py'>
  static distance_3_doubly_truncated_Golay_code_graph()

    Return a distance-regular graph with intersection array \([9, 8, 6, 3; 1, 1, 3, 8]\).

    EXAMPLES:

    Sage

        sage: # long time, needs sage.modules sage.rings.finite_rings
        sage: G = graphs.distance_3_doubly_truncated_Golay_code_graph()
        sage: G.is_distance_regular(True)       # long time (due to above)
        ([9, 8, 6, 3, None], [None, 1, 1, 3, 8])

    Python

        >>> from sage.all import *
        >>> # long time, needs sage.modules sage.rings.finite_rings
        >>> G = graphs.distance_3_doubly_truncated_Golay_code_graph()
        >>> G.is_distance_regular(True)       # long time (due to above)
        ([9, 8, 6, 3, None], [None, 1, 1, 3, 8])

    ALGORITHM:

    Compute the binary Golay code and truncate it twice. Compute its coset graph. Take a vertex and compute the set of vertices at distance 3 from the vertex chosen. This set constitutes the set of vertices of our distance-regular graph. Moreover we have an edge \((u,v)\) if the coset graph contains such edge.

    REFERENCES:

    Description and construction of this graph are taken from [BCN1989] p. 364.

  distance_regular = <module 'sage.graphs.generators.distance_regular' from '/usr/lib/python3.13/site-packages/sage/graphs/generators/distance_regular.cpython-313-x86_64-linux-gnu.so'>
  static distance_regular_graph(arr, existence=False, check=True)

    Return a distance-regular graph with the intersection array given.

    INPUT:

    - `arr` – list; intersection array of the graph

    - `existence` – boolean (optional); instead of building the graph return:

      - `True` – if a graph with the given intersection array exists;

      - `False` – if there is no graph with the given intersection array;

      - `Unknown` – if Sage doesn’t know if such a graph exists

    - `check` – boolean (default: `True`); if `True`, then checks that the result of this function has the given intersection array

    EXAMPLES:

    Sage

        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)     # 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])

    Python

        >>> from sage.all import *
        >>> graphs.distance_regular_graph([Integer(21),Integer(20),Integer(16),Integer(1),Integer(2),Integer(12)], existence=True)
        True
        >>> G = graphs.distance_regular_graph([Integer(12),Integer(11),Integer(10),Integer(7),Integer(1),Integer(2),Integer(5),Integer(12)], check=False)     # needs sage.combinat sage.modules
        >>> G.is_distance_regular(True)                                               # needs sage.combinat sage.modules
        ([12, 11, 10, 7, None], [None, 1, 2, 5, 12])

    REFERENCES:

    See [BCN1989] and [VDKT2016].

  families = <module 'sage.graphs.generators.families' from '/usr/lib/python3.13/site-packages/sage/graphs/generators/families.py'>
  fullerenes(order, ipr=False, immutable=False)

    Return a generator which creates fullerene graphs using the buckygen generator (see [BGM2012]).

    INPUT:

    - `order` – a positive even integer smaller than or equal to 254 This specifies the number of vertices in the generated fullerenes

    - `ipr` – boolean (default: `False`); if `True` only fullerenes that satisfy the Isolated Pentagon Rule are generated. This means that no pentagonal faces share an edge.

    - `immutable` – boolean (default: `False`); whether to return immutable or mutable graphs

    OUTPUT:

    A generator which will produce the fullerene graphs as Sage graphs with an embedding set. These will be simple graphs: no loops, no multiple edges, no directed edges.

    See also

    - `set_embedding()`, `get_embedding()` – get/set methods for embeddings.

    EXAMPLES:

    There are 1812 isomers of \(\textrm{C}_{60}\), i.e., 1812 fullerene graphs on 60 vertices:

    Sage

        sage: gen = graphs.fullerenes(60)  # optional - buckygen
        sage: len(list(gen))               # optional - buckygen
        1812

    Python

        >>> from sage.all import *
        >>> gen = graphs.fullerenes(Integer(60))  # optional - buckygen
        >>> len(list(gen))               # optional - buckygen
        1812

    However, there is only one IPR fullerene graph on 60 vertices: the famous Buckminster Fullerene:

    Sage

        sage: gen = graphs.fullerenes(60, ipr=True)  # optional - buckygen
        sage: next(gen)                              # optional - buckygen
        Graph on 60 vertices
        sage: next(gen)                              # optional - buckygen
        Traceback (most recent call last):
        ...
        StopIteration

    [Python]

        >>> from sage.all import *
        >>> gen = graphs.fullerenes(Integer(60), ipr=True)  # optional - buckygen
        >>> next(gen)                              # optional - buckygen
        Graph on 60 vertices
        >>> next(gen)                              # optional - buckygen
        Traceback (most recent call last):
        ...
        StopIteration

    The unique fullerene graph on 20 vertices is isomorphic to the dodecahedron graph.

    Sage

        sage: # optional - buckygen
        sage: gen = graphs.fullerenes(20)
        sage: g = next(gen)
        sage: g.is_isomorphic(graphs.DodecahedralGraph())
        True
        sage: g.get_embedding()
        {1: [2, 3, 4],
         2: [1, 5, 6],
         3: [1, 7, 8],
         4: [1, 9, 10],
         5: [2, 10, 11],
         6: [2, 12, 7],
         7: [3, 6, 13],
         8: [3, 14, 9],
         9: [4, 8, 15],
         10: [4, 16, 5],
         11: [5, 17, 12],
         12: [6, 11, 18],
         13: [7, 18, 14],
         14: [8, 13, 19],
         15: [9, 19, 16],
         16: [10, 15, 17],
         17: [11, 16, 20],
         18: [12, 20, 13],
         19: [14, 20, 15],
         20: [17, 19, 18]}
        sage: g.plot3d(layout='spring')
        Graphics3d Object

    Python

        >>> from sage.all import *
        >>> # optional - buckygen
        >>> gen = graphs.fullerenes(Integer(20))
        >>> g = next(gen)
        >>> g.is_isomorphic(graphs.DodecahedralGraph())
        True
        >>> g.get_embedding()
        {1: [2, 3, 4],
         2: [1, 5, 6],
         3: [1, 7, 8],
         4: [1, 9, 10],
         5: [2, 10, 11],
         6: [2, 12, 7],
         7: [3, 6, 13],
         8: [3, 14, 9],
         9: [4, 8, 15],
         10: [4, 16, 5],
         11: [5, 17, 12],
         12: [6, 11, 18],
         13: [7, 18, 14],
         14: [8, 13, 19],
         15: [9, 19, 16],
         16: [10, 15, 17],
         17: [11, 16, 20],
         18: [12, 20, 13],
         19: [14, 20, 15],
         20: [17, 19, 18]}
        >>> g.plot3d(layout='spring')
        Graphics3d Object

  fusenes(hexagon_count, benzenoids=False, immutable=False)

    Return a generator which creates fusenes and benzenoids using the benzene generator (see [BCH2002]). Fusenes are planar polycyclic hydrocarbons with all bounded faces hexagons. Benzenoids are fusenes that are subgraphs of the hexagonal lattice.

    INPUT:

    - `hexagon_count` – positive integer smaller than or equal to 30; this specifies the number of hexagons in the generated benzenoids

    - `benzenoids` – boolean (default: `False`); if `True` only benzenoids are generated

    - `immutable` – boolean (default: `False`); whether to return immutable or mutable graphs

    OUTPUT:

    A generator which will produce the fusenes as Sage graphs with an embedding set. These will be simple graphs: no loops, no multiple edges, no directed edges.

    See also

    - `set_embedding()`, `get_embedding()` – get/set methods for embeddings.

    EXAMPLES:

    There is a unique fusene with 2 hexagons:

    Sage

        sage: gen = graphs.fusenes(2)  # optional - benzene
        sage: len(list(gen))           # optional - benzene
        1

    Python

        >>> from sage.all import *
        >>> gen = graphs.fusenes(Integer(2))  # optional - benzene
        >>> len(list(gen))           # optional - benzene
        1

    This fusene is naphthalene (\(\textrm{C}_{10}\textrm{H}_{8}\)). In the fusene graph the H-atoms are not stored, so this is a graph on just 10 vertices:

    Sage

        sage: gen = graphs.fusenes(2)  # optional - benzene
        sage: next(gen)                # optional - benzene
        Graph on 10 vertices
        sage: next(gen)                # optional - benzene
        Traceback (most recent call last):
        ...
        StopIteration

    [Python]

        >>> from sage.all import *
        >>> gen = graphs.fusenes(Integer(2))  # optional - benzene
        >>> next(gen)                # optional - benzene
        Graph on 10 vertices
        >>> next(gen)                # optional - benzene
        Traceback (most recent call last):
        ...
        StopIteration

    There are 6505 benzenoids with 9 hexagons:

    Sage

        sage: gen = graphs.fusenes(9, benzenoids=True)  # optional - benzene
        sage: len(list(gen))                            # optional - benzene
        6505

    Python

        >>> from sage.all import *
        >>> gen = graphs.fusenes(Integer(9), benzenoids=True)  # optional - benzene
        >>> len(list(gen))                            # optional - benzene
        6505

  gen_trees = <module 'sage.graphs.generators.trees' from '/usr/lib/python3.13/site-packages/sage/graphs/generators/trees.cpython-313-x86_64-linux-gnu.so'>
  static graph_3O73(immutable=False)

    Return the graph related to the group \(3 O(7,3)\).

    This graph is distance-regular with intersection array \([117, 80, 24, 1; 1, 12, 80, 117]\).

    The graph is also distance transitive with \(3.O(7,3)\) as automorphism group

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Sage

        sage: G = graphs.graph_3O73()                           # optional - internet gap_package_atlasrep
        sage: G.is_distance_regular(True)                       # optional - internet gap_package_atlasrep
        ([117, 80, 24, 1, None], [None, 1, 12, 80, 117])

    Python

        >>> from sage.all import *
        >>> G = graphs.graph_3O73()                           # optional - internet gap_package_atlasrep
        >>> G.is_distance_regular(True)                       # optional - internet gap_package_atlasrep
        ([117, 80, 24, 1, None], [None, 1, 12, 80, 117])

    REFERENCES:

    A description and construction of this graph can be found in [BCN1989] p. 400.

  intersection = <module 'sage.graphs.generators.intersection' from '/usr/lib/python3.13/site-packages/sage/graphs/generators/intersection.py'>
  static line_graph_forbidden_subgraphs()

    Return the 9 forbidden subgraphs of a line graph.

    See the Wikipedia article Line_graph for more information.

    The graphs are returned in the ordering given by the Wikipedia drawing, read from left to right and from top to bottom.

    EXAMPLES:

    Sage

        sage: graphs.line_graph_forbidden_subgraphs()
        [Claw graph: Graph on 4 vertices,
        Graph on 6 vertices,
        Graph on 6 vertices,
        Graph on 5 vertices,
        Graph on 6 vertices,
        Graph on 6 vertices,
        Graph on 6 vertices,
        Graph on 6 vertices,
        Graph on 5 vertices]

    Python

        >>> from sage.all import *
        >>> graphs.line_graph_forbidden_subgraphs()
        [Claw graph: Graph on 4 vertices,
        Graph on 6 vertices,
        Graph on 6 vertices,
        Graph on 5 vertices,
        Graph on 6 vertices,
        Graph on 6 vertices,
        Graph on 6 vertices,
        Graph on 6 vertices,
        Graph on 5 vertices]

  static locally_GQ42_distance_transitive_graph(immutable=False)

    Return the unique amply regular graph with \(\mu = 6\) which is locally a generalised quadrangle.

    This graph is distance-regular with intersection array \([45, 32, 12, 1; 1, 6, 32, 45]\).

    This graph is also distance-transitive.

    INPUT:

    - `immutable` – boolean (default: `False`); whether to return an immutable or a mutable graph

    EXAMPLES:

    Sage

        sage: G = graphs.locally_GQ42_distance_transitive_graph()       # optional - internet gap_package_atlasrep
        sage: G.is_distance_regular(True)                               # optional - internet gap_package_atlasrep
        ([45, 32, 12, 1, None], [None, 1, 6, 32, 45])

    Python

        >>> from sage.all import *
        >>> G = graphs.locally_GQ42_distance_transitive_graph()       # optional - internet gap_package_atlasrep
        >>> G.is_distance_regular(True)                               # optional - internet gap_package_atlasrep
        ([45, 32, 12, 1, None], [None, 1, 6, 32, 45])

    REFERENCES:

    A description of this graph can be found in [BCN1989] p.399. This construction is due to Dima Pasechnik.

  nauty_genbg(options='', debug=False, immutable=False)

    Return a generator which creates bipartite graphs from nauty’s `genbgL` program.

    INPUT:

    - `options` – string (default: `""`); a string passed to `genbgL` as if it was run at a system command line. At a minimum, you must pass the number of vertices you desire in each side. Sage expects the bipartite graphs to be in nauty’s “graph6” format, do not set an option to change this default or results will be unpredictable.

    - `debug` – boolean (default: `False`); if `True` the first line of `geng`’s output to standard error is captured and the first call to the generator’s `next()` function will return this line as a string. A line leading with “>A” indicates a successful initiation of the program with some information on the arguments, while a line beginning with “>E” indicates an error with the input.

    - `immutable` – boolean (default: `False`); whether to return immutable or mutable graphs

    The possible options, obtained as output of `genbgL --help`:

            n1       : the number of vertices in the first class.
                       We must have n1=1..30.
            n2       : the number of vertices in the second class.
                       We must have n2=0..64 and n1+n2=1..64.
        mine:maxe    : <int>:<int> a range for the number of edges
                        <int>:0 means '<int> or more' except in the case 0:0
          res/mod    : only generate subset res out of subsets 0..mod-1
            -c       : only write connected graphs
            -z       : all the vertices in the second class must have
                       different neighbourhoods
            -F       : the vertices in the second class must have at least
                       two neighbours of degree at least 2
            -L       : there is no vertex in the first class whose removal
                       leaves the vertices in the second class unreachable
                       from each other
            -Y<int>  : two vertices in the second class must have at least
                       <int> common neighbours
            -Z<int>  : two vertices in the second class must have at most
                       <int> common neighbours
            -A       : no vertex in the second class has a neighbourhood
                       which is a subset of another vertex's neighbourhood
                       in the second class
            -D<int>  : specify an upper bound for the maximum degree
                       Example: -D6. You can also give separate maxima for
                       the two parts, for example: -D5:6
            -d<int>  : specify a lower bound for the minimum degree
                       Again, you can specify it separately for the two parts,
                       for example -d1:2
            -v       : display counts by number of edges to stderr
            -l       : canonically label output graphs

    Options which cause `genbgL` to use an output format different than the `graph6` format are not listed above (`-s`, `-a`) as they will confuse the creation of a Sage graph. Option `-q` which suppress auxiliary output (except from `-v`) should never be used as we are unable to recover the partition of the vertices of the bipartite graph without the auxiliary output. Hence the partition of the vertices of returned bipartite graphs might not respect the requirement.

    The res/mod option can be useful when using the output in a routine run several times in parallel.

    OUTPUT:

    A generator which will produce the graphs as `BipartiteGraph`. These will be simple bipartite graphs: no loops, no multiple edges, no directed edges.

    EXAMPLES:

    The generator can be used to construct bipartite graphs for testing, one at a time (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

        sage: gen = graphs.nauty_genbg("1 1")
        sage: next(gen)
        Bipartite graph on 2 vertices
        sage: next(gen)
        Bipartite graph on 2 vertices
        sage: next(gen)
        Traceback (most recent call last):
        ...
        StopIteration

    Python

        >>> from sage.all import *
        >>> gen = graphs.nauty_genbg("1 1")
        >>> next(gen)
        Bipartite graph on 2 vertices
        >>> next(gen)
        Bipartite graph on 2 vertices
        >>> next(gen)
        Traceback (most recent call last):
        ...
        StopIteration

    Connected bipartite graphs of order 6 with different number of vertices in each side:

    Sage

        sage: gen = graphs.nauty_genbg("1 5 -c")
        sage: len(list(gen))
        1
        sage: gen = graphs.nauty_genbg("2 4 -c")
        sage: len(list(gen))
        6
        sage: gen = graphs.nauty_genbg("3 3 -c")
        sage: len(list(gen))
        13

    [Python]

        >>> from sage.all import *
        >>> gen = graphs.nauty_genbg("1 5 -c")
        >>> len(list(gen))
        1
        >>> gen = graphs.nauty_genbg("2 4 -c")
        >>> len(list(gen))
        6
        >>> gen = graphs.nauty_genbg("3 3 -c")
        >>> len(list(gen))
        13

    Use `nauty_geng()` instead if you want the list of all bipartite graphs of order \(n\). For instance, the list of all connected bipartite graphs of order 6, which agrees with OEIS sequence A005142:

    Sage

        sage: gen = graphs.nauty_geng("-b -c 6")
        sage: len(list(gen))
        17

    Python

        >>> from sage.all import *
        >>> gen = graphs.nauty_geng("-b -c 6")
        >>> len(list(gen))
        17

    The `debug` switch can be used to examine `genbgL`’s reaction to the input in the `options` string. A message starting with “>A” indicates success and a message starting with “>E” indicates a failure:

    Sage

        sage: gen = graphs.nauty_genbg("2 3", debug=True)
        sage: print(next(gen))
        >A ...genbg... n=2+3 e=0:6 d=0:0 D=3:2
        sage: gen = graphs.nauty_genbg("-c2 3", debug=True)
        sage: next(gen)
        '>E Usage: ...genbg... [-c -ugs -vq -lzF] [-Z#] [-D#] [-A] [-d#|-d#:#] [-D#|-D#:#] n1 n2...

    [Python]

        >>> from sage.all import *
        >>> gen = graphs.nauty_genbg("2 3", debug=True)
        >>> print(next(gen))
        >A ...genbg... n=2+3 e=0:6 d=0:0 D=3:2
        >>> gen = graphs.nauty_genbg("-c2 3", debug=True)
        >>> next(gen)
        '>E Usage: ...genbg... [-c -ugs -vq -lzF] [-Z#] [-D#] [-A] [-d#|-d#:#] [-D#|-D#:#] n1 n2...

    Check that the partition of the bipartite graph is consistent:

    Sage

        sage: gen = graphs.nauty_genbg("3 3")
        sage: left = set(range(3))
        sage: for g in gen:
        ....:     if g.left != left:
        ....:         raise ValueError('wrong partition')

    Python

        >>> from sage.all import *
        >>> gen = graphs.nauty_genbg("3 3")
        >>> left = set(range(Integer(3)))
        >>> for g in gen:
        ...     if g.left != left:
        ...         raise ValueError('wrong partition')

  nauty_geng(options='', debug=False, immutable=False)

    Return a generator which creates graphs from nauty’s geng program.

    INPUT:

    - `options` – string (default: `''`); a string passed to `geng` as if it was run at a system command line. At a minimum, you must pass the number of vertices you desire. Sage expects the graphs to be in nauty’s “graph6” format, do not set an option to change this default or results will be unpredictable.

    - `debug` – boolean (default: `False`); if `True` the first line of `geng`’s output to standard error is captured and the first call to the generator’s `next()` function will return this line as a string. A line leading with “>A” indicates a successful initiation of the program with some information on the arguments, while a line beginning with “>E” indicates an error with the input.

    - `immutable` – boolean (default: `False`); whether to return immutable or mutable graphs

    The possible options, obtained as output of `geng --help`:

             n       : the number of vertices
        mine:maxe    : <int>:<int> a range for the number of edges
                        <int>:0 means '<int> or more' except in the case 0:0
          res/mod : only generate subset res out of subsets 0..mod-1

            -c       : only write connected graphs
            -C       : only write biconnected graphs
            -t       : only generate triangle-free graphs
            -f       : only generate 4-cycle-free graphs
            -b       : only generate bipartite graphs
                          (-t, -f and -b can be used in any combination)
            -m       : save memory at the expense of time (only makes a
                          difference in the absence of -b, -t, -f and n <= 28).
            -d<int>  : a lower bound for the minimum degree
            -D<int>  : a upper bound for the maximum degree
            -v       : display counts by number of edges
            -l       : canonically label output graphs

            -q       : suppress auxiliary output (except from -v)

    Options which cause `geng` to use an output format different than the graph6 format are not listed above (-u, -g, -s, -y, -h) as they will confuse the creation of a Sage graph. The res/mod option can be useful when using the output in a routine run several times in parallel.

    OUTPUT:

    A generator which will produce the graphs as Sage graphs. These will be simple graphs: no loops, no multiple edges, no directed edges.

    See also

    `Graph.is_strongly_regular()` – tests whether a graph is strongly regular and/or returns its parameters.

    EXAMPLES:

    The generator can be used to construct graphs for testing, one at a time (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

        sage: gen = graphs.nauty_geng("2")
        sage: next(gen)
        Graph on 2 vertices
        sage: next(gen)
        Graph on 2 vertices
        sage: next(gen)
        Traceback (most recent call last):
        ...
        StopIteration

    Python

        >>> from sage.all import *
        >>> gen = graphs.nauty_geng("2")
        >>> next(gen)
        Graph on 2 vertices
        >>> next(gen)
        Graph on 2 vertices
        >>> next(gen)
        Traceback (most recent call last):
        ...
        StopIteration

    A list of all graphs on 7 vertices. This agrees with OEIS sequence A000088.

    Sage

        sage: gen = graphs.nauty_geng("7")
        sage: len(list(gen))
        1044

    [Python]

        >>> from sage.all import *
        >>> gen = graphs.nauty_geng("7")
        >>> len(list(gen))
        1044

    A list of just the connected graphs on 7 vertices. This agrees with OEIS sequence A001349.

    Sage

        sage: gen = graphs.nauty_geng("7 -c")
        sage: len(list(gen))
        853

    Python

        >>> from sage.all import *
        >>> gen = graphs.nauty_geng("7 -c")
        >>> len(list(gen))
        853

    A list of connected degree exactly 2 graphs on 5 vertices.

    Sage

        sage: gen = graphs.nauty_geng("5 -c -d2 -D2")
        sage: len(list(gen))
        1

    [Python]

        >>> from sage.all import *
        >>> gen = graphs.nauty_geng("5 -c -d2 -D2")
        >>> len(list(gen))
        1

    The `debug` switch can be used to examine `geng`’s reaction to the input in the `options` string. We illustrate success. (A failure will be a string beginning with “>E”.) Passing the “-q” switch to `geng` will suppress the indicator of a successful initiation, and so the first returned value might be an empty string if `debug` is `True`:

    Sage

        sage: gen = graphs.nauty_geng("4", debug=True)
        sage: print(next(gen))
        >A ...geng -d0D3 n=4 e=0-6
        sage: gen = graphs.nauty_geng("4 -q", debug=True)
        sage: next(gen)
        ''

    Python

        >>> from sage.all import *
        >>> gen = graphs.nauty_geng("4", debug=True)
        >>> print(next(gen))
        >A ...geng -d0D3 n=4 e=0-6
        >>> gen = graphs.nauty_geng("4 -q", debug=True)
        >>> next(gen)
        ''

  nauty_genktreeg(options='', debug=False, immutable=False)

    Return a generator which creates all \(k\)-trees using nauty..

    A \(k\)-tree is an undirected graph formed by starting with a complete graph on \(k + 1\) vertices and then repeatedly add vertices in such a way that each added vertex \(v\) has exactly \(k\) neighbors \(U\) such that, together, the \(k + 1\) vertices formed by \(v\) and \(U\) form a clique. See the Wikipedia article K-tree for more details.

    INPUT:

    - `options` – string (default: `""`); a string passed to `genktreeg` as if it was run at a system command line. At a minimum, you must pass the number of vertices you desire. Sage expects the graphs to be in nauty’s “graph6” format, do not set an option to change this default or results will be unpredictable.

    - `debug` – boolean (default: `False`); if `True` the first line of `genktreeg`’s output to standard error is captured and the first call to the generator’s `next()` function will return this line as a string. A line leading with “>A” indicates a successful initiation of the program with some information on the arguments, while a line beginning with “>E” indicates an error with the input.

    - `immutable` – boolean (default: `False`); whether to return immutable or mutable graphs

    The possible options, obtained as output of `genktreeg --help`:

           n       : the number of vertices
          -k<int>  : the value of `k`(default: 2)
        res/mod    : only generate subset res out of subsets 0..mod-1
          -l       : canonically label output graphs

    Options which cause `genktreeg` to use an output format different than the graph6 format are not listed above (-u, -s, -h) as they will confuse the creation of a Sage graph. The res/mod option can be useful when using the output in a routine run several times in parallel.

    OUTPUT:

    A generator which will produce the graphs as Sage graphs. These will be simple graphs: no loops, no multiple edges, no directed edges.

    EXAMPLES:

    A \(k\)-tree is a maximal graph with treewidth \(k\):

    Sage

        sage: # needs nauty
        sage: gen = graphs.nauty_genktreeg("10 -k4")
        sage: G = next(gen); G
        Graph on 10 vertices
        sage: G.treewidth()
        4

    Python

        >>> from sage.all import *
        >>> # needs nauty
        >>> gen = graphs.nauty_genktreeg("10 -k4")
        >>> G = next(gen); G
        Graph on 10 vertices
        >>> G.treewidth()
        4

    A list of all 2-trees with 6, 7 and 8 vertices. This agrees with OEIS sequence A054581:

    Sage

        sage: # needs nauty
        sage: gen = graphs.nauty_genktreeg("6")
        sage: len(list(gen))
        5
        sage: gen = graphs.nauty_genktreeg("7")
        sage: len(list(gen))
        12
        sage: gen = graphs.nauty_genktreeg("8")
        sage: len(list(gen))
        39

    [Python]

        >>> from sage.all import *
        >>> # needs nauty
        >>> gen = graphs.nauty_genktreeg("6")
        >>> len(list(gen))
        5
        >>> gen = graphs.nauty_genktreeg("7")
        >>> len(list(gen))
        12
        >>> gen = graphs.nauty_genktreeg("8")
        >>> len(list(gen))
        39

    The `debug` switch can be used to examine `geng`’s reaction to the input in the `options` string. We illustrate success. (A failure will be a string beginning with “>E”.) Passing the “-q” switch to `geng` will suppress the indicator of a successful initiation, and so the first returned value might be an empty string if `debug` is `True`:

    Sage

        sage: gen = graphs.nauty_genktreeg("7", debug=True)                         # needs nauty
        sage: print(next(gen))                                                      # needs nauty
        >A ...genktreeg k=2 n=7

    Python

        >>> from sage.all import *
        >>> gen = graphs.nauty_genktreeg("7", debug=True)                         # needs nauty
        >>> print(next(gen))                                                      # needs nauty
        >A ...genktreeg k=2 n=7

  static nauty_gentreeg(options='', debug=False)

    Return a generator which creates non-isomorphic trees from nauty’s gentreeg program.

    INPUT:

    - `options` – string (default: `""`); a string passed to `gentreeg` as if it was run at a system command line. At a minimum, you must pass the number of vertices you desire. Sage expects the graphs to be in nauty’s “sparse6” format, do not set an option to change this default or results will be unpredictable.

    - `debug` – boolean (default: `False`); if `True` the first line of `gentreeg`’s output to standard error is captured and the first call to the generator’s `next()` function will return this line as a string. A line leading with “>A” indicates a successful initiation of the program with some information on the arguments, while a line beginning with “>E” indicates an error with the input.

    The possible options, obtained as output of `gentreeg -help`:

           n            : the number of vertices. Must be in range 1..128
        res/mod         : only generate subset res out of subsets 0..mod-1
          -D<int>       : an upper bound for the maximum degree
          -Z<int>:<int> : bounds on the diameter
          -q            : suppress auxiliary output

    Options which cause `gentreeg` to use an output format different than the sparse6 format are not listed above (-p, -l, -u) as they will confuse the creation of a Sage graph. The res/mod option can be useful when using the output in a routine run several times in parallel.

    OUTPUT:

    A generator which will produce the graphs as Sage graphs. These will be simple graphs: no loops, no multiple edges, no directed edges.

    See also

    `trees()` – another generator of trees

    EXAMPLES:

    The generator can be used to construct trees for testing, one at a time (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

        sage: gen = graphs.nauty_gentreeg("4")
        sage: next(gen)
        Graph on 4 vertices
        sage: next(gen)
        Graph on 4 vertices
        sage: next(gen)
        Traceback (most recent call last):
        ...
        StopIteration

    Python

        >>> from sage.all import *
        >>> gen = graphs.nauty_gentreeg("4")
        >>> next(gen)
        Graph on 4 vertices
        >>> next(gen)
        Graph on 4 vertices
        >>> next(gen)
        Traceback (most recent call last):
        ...
        StopIteration

    The number of trees on the first few vertex counts. This agrees with OEIS sequence A000055:

    Sage

        sage: [len(list(graphs.nauty_gentreeg(str(i)))) for i in range(1, 15)]
        [1, 1, 1, 2, 3, 6, 11, 23, 47, 106, 235, 551, 1301, 3159]

    [Python]

        >>> from sage.all import *
        >>> [len(list(graphs.nauty_gentreeg(str(i)))) for i in range(Integer(1), Integer(15))]
        [1, 1, 1, 2, 3, 6, 11, 23, 47, 106, 235, 551, 1301, 3159]

    The `debug` switch can be used to examine `gentreeg`’s reaction to the input in the `options` string. We illustrate success. (A failure will be a string beginning with “>E”.) Passing the “-q” switch to `gentreeg` will suppress the indicator of a successful initiation, and so the first returned value might be an empty string if `debug` is `True`:

    Sage

        sage: gen = graphs.nauty_gentreeg("4", debug=True)
        sage: print(next(gen))
        >A ...gentreeg ...
        sage: gen = graphs.nauty_gentreeg("4 -q", debug=True)
        sage: next(gen)
        ''

    Python

        >>> from sage.all import *
        >>> gen = graphs.nauty_gentreeg("4", debug=True)
        >>> print(next(gen))
        >A ...gentreeg ...
        >>> gen = graphs.nauty_gentreeg("4 -q", debug=True)
        >>> next(gen)
        ''

  static p2_forbidden_minors()

    Return an array containing the 35 minimal forbidden excluded minors of the projective plane.

    We constructed the graphs given in Theorem 6.5.1 of [MT2001], which is a result of Archdeacon and encoded them in graph6 format. The order of the graphs is the same as they appear in [WA2025].

  static petersen_family(generate=False)

    Return the Petersen family.

    The Petersen family is a collection of 7 graphs which are the forbidden minors of the linklessly embeddable graphs. For more information see the Wikipedia article Petersen_family.

    INPUT:

    - `generate` – boolean; whether to generate the family from the \(\Delta-Y\) transformations. When set to `False` (default) a hardcoded version of the graphs (with a prettier layout) is returned.

    EXAMPLES:

    Sage

        sage: graphs.petersen_family()
        [Petersen graph: Graph on 10 vertices,
         Complete graph: Graph on 6 vertices,
         Multipartite Graph with set sizes [3, 3, 1]: Graph on 7 vertices,
         Graph on 8 vertices,
         Graph on 9 vertices,
         Graph on 7 vertices,
         Graph on 8 vertices]

    Python

        >>> from sage.all import *
        >>> graphs.petersen_family()
        [Petersen graph: Graph on 10 vertices,
         Complete graph: Graph on 6 vertices,
         Multipartite Graph with set sizes [3, 3, 1]: Graph on 7 vertices,
         Graph on 8 vertices,
         Graph on 9 vertices,
         Graph on 7 vertices,
         Graph on 8 vertices]

    The two different inputs generate the same graphs:

    Sage

        sage: F1 = graphs.petersen_family(generate=False)
        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]                    # needs sage.modules
        sage: set(F1) == set(F2)                                                        # needs sage.modules
        True

    [Python]

        >>> from sage.all import *
        >>> F1 = graphs.petersen_family(generate=False)
        >>> F2 = graphs.petersen_family(generate=True)                                # needs sage.modules
        >>> F1 = [g.canonical_label().graph6_string() for g in F1]
        >>> F2 = [g.canonical_label().graph6_string() for g in F2]                    # needs sage.modules
        >>> set(F1) == set(F2)                                                        # needs sage.modules
        True

  planar_graphs(order, minimum_degree=None, minimum_connectivity=None, exact_connectivity=False, minimum_edges=None, maximum_edges=None, maximum_face_size=None, only_bipartite=False, dual=False, immutable=False)

    An iterator over connected planar graphs using the plantri generator.

    This uses the plantri generator (see [BM2007]) which is available through the optional package plantri.

    Note

    The non-3-connected graphs will be returned several times, with all its possible embeddings.

    INPUT:

    - `order` – positive integer smaller than or equal to 64; this specifies the number of vertices in the generated graphs

    - `minimum_degree` – (default: `None`) a value \(\geq 1\) and \(\leq 5\), or `None`. This specifies the minimum degree of the generated graphs. If this is `None` and the order is 1, then this is set to 0. If this is `None` and the minimum connectivity is specified, then this is set to the same value as the minimum connectivity. If the minimum connectivity is also equal to `None`, then this is set to 1.

    - `minimum_connectivity` – (default: `None`) a value \(\geq 1\) and \(\leq 4\), or `None`. This specifies the minimum connectivity of the generated graphs. If this is `None` and the minimum degree is specified, then this is set to the minimum of the minimum degree and 3. If the minimum degree is also equal to `None`, then this is set to 1.

    - `exact_connectivity` – (default: `False`) if `True` only graphs with exactly the specified connectivity will be generated. This option requires `minimum_connectivity` to be set to 1 or 2.

    - `minimum_edges` – integer (default: `None`); lower bound on the number of edges

    - `maximum_edges` – integer (default: `None`); upper bound on the number of edges

    - `maximum_face_size` – integer (default: `None`); upper bound on the size of a face and so on the maximum degree of the dual graph

    - `only_bipartite` – (default: `False`) if `True` only bipartite graphs will be generated. This option cannot be used for graphs with a minimum degree larger than 3.

    - `dual` – (default: `False`) if `True` return instead the planar duals of the generated graphs

    - `immutable` – boolean (default: `False`); whether to return immutable or mutable graphs

    OUTPUT:

    An iterator which will produce all planar graphs with the given number of vertices as Sage graphs with an embedding set. These will be simple graphs (no loops, no multiple edges, no directed edges) unless the option `dual=True` is used.

    See also

    - `set_embedding()`, `get_embedding()` – get/set methods for embeddings.

    EXAMPLES:

    There are 6 planar graphs on 4 vertices:

    Sage

        sage: gen = graphs.planar_graphs(4)  # optional - plantri
        sage: len(list(gen))                 # optional - plantri
        6

    Python

        >>> from sage.all import *
        >>> gen = graphs.planar_graphs(Integer(4))  # optional - plantri
        >>> len(list(gen))                 # optional - plantri
        6

    Three of these planar graphs are bipartite:

    Sage

        sage: gen = graphs.planar_graphs(4, only_bipartite=True)  # optional - plantri
        sage: len(list(gen))                                      # optional - plantri
        3

    [Python]

        >>> from sage.all import *
        >>> gen = graphs.planar_graphs(Integer(4), only_bipartite=True)  # optional - plantri
        >>> len(list(gen))                                      # optional - plantri
        3

    Setting `dual=True` gives the planar dual graphs:

    Sage

        sage: gen = graphs.planar_graphs(4, dual=True)  # optional - plantri
        sage: [u for u in list(gen)]                    # optional - plantri
        [Graph on 4 vertices,
        Multi-graph on 3 vertices,
        Multi-graph on 2 vertices,
        Looped multi-graph on 2 vertices,
        Looped multi-graph on 1 vertex,
        Looped multi-graph on 1 vertex]

    Python

        >>> from sage.all import *
        >>> gen = graphs.planar_graphs(Integer(4), dual=True)  # optional - plantri
        >>> [u for u in list(gen)]                    # optional - plantri
        [Graph on 4 vertices,
        Multi-graph on 3 vertices,
        Multi-graph on 2 vertices,
        Looped multi-graph on 2 vertices,
        Looped multi-graph on 1 vertex,
        Looped multi-graph on 1 vertex]

    The cycle of length 4 is the only 2-connected bipartite planar graph on 4 vertices:

    Sage

        sage: l = list(graphs.planar_graphs(4, minimum_connectivity=2, only_bipartite=True))  # optional - plantri
        sage: l[0].get_embedding()                                                            # optional - plantri
        {1: [2, 3],
         2: [1, 4],
         3: [1, 4],
         4: [2, 3]}

    [Python]

        >>> from sage.all import *
        >>> l = list(graphs.planar_graphs(Integer(4), minimum_connectivity=Integer(2), only_bipartite=True))  # optional - plantri
        >>> l[Integer(0)].get_embedding()                                                            # optional - plantri
        {1: [2, 3],
         2: [1, 4],
         3: [1, 4],
         4: [2, 3]}

    There is one planar graph with one vertex. This graph obviously has minimum degree equal to 0:

    Sage

        sage: list(graphs.planar_graphs(1))                    # optional - plantri
        [Graph on 1 vertex]
        sage: list(graphs.planar_graphs(1, minimum_degree=1))  # optional - plantri
        []

    Python

        >>> from sage.all import *
        >>> list(graphs.planar_graphs(Integer(1)))                    # optional - plantri
        [Graph on 1 vertex]
        >>> list(graphs.planar_graphs(Integer(1), minimum_degree=Integer(1)))  # optional - plantri
        []

    Specifying lower and upper bounds on the number of edges:

    Sage

        sage: # optional - plantri
        sage: len(list(graphs.planar_graphs(4)))
        6
        sage: len(list(graphs.planar_graphs(4, minimum_edges=4)))
        4
        sage: len(list(graphs.planar_graphs(4, maximum_edges=4)))
        4
        sage: len(list(graphs.planar_graphs(4, minimum_edges=4, maximum_edges=4)))
        2

    [Python]

        >>> from sage.all import *
        >>> # optional - plantri
        >>> len(list(graphs.planar_graphs(Integer(4))))
        6
        >>> len(list(graphs.planar_graphs(Integer(4), minimum_edges=Integer(4))))
        4
        >>> len(list(graphs.planar_graphs(Integer(4), maximum_edges=Integer(4))))
        4
        >>> len(list(graphs.planar_graphs(Integer(4), minimum_edges=Integer(4), maximum_edges=Integer(4))))
        2

    Specifying the maximum size of a face:

    Sage

        sage: len(list(graphs.planar_graphs(4, maximum_face_size=3)))  # optional - plantri
        1
        sage: len(list(graphs.planar_graphs(4, maximum_face_size=4)))  # optional - plantri
        3

    Python

        >>> from sage.all import *
        >>> len(list(graphs.planar_graphs(Integer(4), maximum_face_size=Integer(3))))  # optional - plantri
        1
        >>> len(list(graphs.planar_graphs(Integer(4), maximum_face_size=Integer(4))))  # optional - plantri
        3

  plantri_gen(options='', immutable=False)

    Iterator over planar graphs created using the `plantri` generator.

    `plantri` is a (optional) program that generates certain types of graphs that are embedded on the sphere. It outputs exactly one member of each isomorphism class, using an amount of memory almost independent of the number of graphs produced. Isomorphisms are defined with respect to the embeddings, so in some cases outputs may be isomorphic as abstract graphs.

    This method allows for passing command directly to `plantry`, similarly to method `nauty_geng()`, provide that the output format is not changed.

    INPUT:

    - `options` – string (default: `""`); a string passed to `plantri` as if it was run at a system command line. At a minimum, you must pass the number of vertices you desire. Sage expects the output of plantri to be in “planar code” format, so do not set an option to change this default or results will be unpredictable.

    - `immutable` – boolean (default: `False`); whether to return immutable or mutable graphs

    The possible options are:

        n       : the number of vertices (the only compulsory parameter).
                  This number must be in range `3\cdots 64`.
                  It can also be given as "nd", where the suffix "d" means
                  "dual", in which case it is converted by adding 4 then
                  dividing by 2, i.e., `(28+4)/2 = 16`. In the case of
                  triangulations, this calculation yields the number of
                  faces, which is the number of vertices in the dual cubic
                  graph.

        -d      : output the dual instead of the original graph.
                  Note that it is applied only at the output stage. All
                  other switches refer to the original graph before the dual
                  is taken.

        -o      : Normally, one member of each isomorphism class is written.
                  If this switch is given, one member of each O-P
                  isomorphism class is written.

        -V      : output only graphs with non-trivial group. If -o is
                  given the O-P group is used, the full group otherwise.

        -m<int> : lower bound on the minimum degree. The default is -m3.
                  In the dual graph, this means a lower bound on the minimum
                  face size.

        -c<int> : lower bound on the connectivity. The default is -c3.

        -x      : when used in combination with -cN, the connectivity must
                  be exactly N rather than at least N.

        -e      : used to specify bounds on the number of edges.
                  There are four possible forms:
                      -e<int>        exactly <int> edges
                      -e:<int>       at most <int> edges
                      -e<int>:       at least <int> edges
                      -e<int>:<int>  between <int> and <int> edges

        -f<int> : upper bound on the size of a face, and so on the maximum
                  degree of the dual.

        -b but not -p : select eulerian triangulations, where "eulerian"
                        means that every vertex has even degree.
                        This parameter can be used in combination with
                        parameters -c and -x.

        -p but not -b : select general planar simple graphs.
                        This parameter can be used in combination with
                        parameters -m, -c, -x, -e and -f.

        -bp or -pb    : select general planar simple bipartite graphs.
                        This parameter can be used in combination with
                        parameters -m, -c, -x, -e and -f, except -c4, -m4,
                        -m5 and -f3.

        -P<int> : select triangulations of a disk. These are embedded simple
                  graphs with a distinguished "outer" face. The outer face
                  can be of any size (here called the disk size) but the
                  other faces must be triangles.  The argument <int> to -P
                  is the disk size. If no argument (or 0) is given, all disk
                  sizes are permitted.
                  This parameter can be used in combination with
                  parameters -m, -c, and -x.

        -q      : select simple quadrangulations. These are planar simple
                  graphs for which every face has length 4.
                  This parameter can be used in combination with parameters
                  -c and -m.

        -A      : select Appolonian networks. These are simple planar
                  triangulations that can be formed starting with `K_4` then
                  repeatedly dividing a face into three by addition of a new
                  vertex. They all have minimum degree and connectivity
                  equal to 3.

        res/mod : only generate subset res out of subsets 0..mod-1.
                  The set of objects is divided into mod disjoint classes
                  and only the res-th class is generated.

    If -b, -q, -p, -P and -A are absent, the graphs found are triangulations only restricted by connectivity and minimum degree. In this case, there is the possibility of connectivity lower than 3.

    Other options listed in the `plantri` guide might cause unpredictable behavior, in particular those changing the output format of `plantri` as they will confuse the creation of a Sage graph.

    OUTPUT:

    An iterator which yields the graphs generated by `plantri` as Sage `Graph`.

    See also

    - `planar_graphs()` – iterator over connected planar graphs using the `plantri` generator

    - `triangulations()` – iterator over connected planar triangulations using the `plantri` generator

    - `quadrangulations()` – iterator over connected planar quadrangulations using the `plantri` generator

    EXAMPLES:

    The generator can be used to construct graphs for testing, one at a time (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

        sage: # optional - plantri
        sage: gen = graphs.plantri_gen("6")
        sage: next(gen)
        Graph on 6 vertices
        sage: next(gen)
        Graph on 6 vertices
        sage: next(gen)
        Traceback (most recent call last):
        ...
        StopIteration

    Python

        >>> from sage.all import *
        >>> # optional - plantri
        >>> gen = graphs.plantri_gen("6")
        >>> next(gen)
        Graph on 6 vertices
        >>> next(gen)
        Graph on 6 vertices
        >>> next(gen)
        Traceback (most recent call last):
        ...
        StopIteration

    An overview of the number of quadrangulations on up to 12 vertices. This agrees with OEIS sequence A113201:

    Sage

        sage: for i in range(4, 13):                        # optional - plantri
        ....:     cmd = '-qm2c2 {}'.format(i)
        ....:     L = len(list(graphs.plantri_gen(cmd)))
        ....:     print("{:2d}   {:3d}".format(i, L))
         4     1
         5     1
         6     2
         7     3
         8     9
         9    18
        10    62
        11   198
        12   803

    [Python]

        >>> from sage.all import *
        >>> for i in range(Integer(4), Integer(13)):                        # optional - plantri
        ...     cmd = '-qm2c2 {}'.format(i)
        ...     L = len(list(graphs.plantri_gen(cmd)))
        ...     print("{:2d}   {:3d}".format(i, L))
         4     1
         5     1
         6     2
         7     3
         8     9
         9    18
        10    62
        11   198
        12   803

  platonic_solids = <module 'sage.graphs.generators.platonic_solids' from '/usr/lib/python3.13/site-packages/sage/graphs/generators/platonic_solids.py'>
  quadrangulations(order, minimum_degree=None, minimum_connectivity=None, no_nonfacial_quadrangles=False, dual=False, immutable=False)

    An iterator over planar quadrangulations using the plantri generator.

    This uses the plantri generator (see [BM2007]) which is available through the optional package plantri.

    INPUT:

    - `order` – positive integer smaller than or equal to 64; this specifies the number of vertices in the generated quadrangulations

    - `minimum_degree` – (default: `None`) a value \(\geq 2\) and \(\leq 3\), or `None`. This specifies the minimum degree of the generated quadrangulations. If this is `None` and the minimum connectivity is specified, then this is set to the same value as the minimum connectivity. If the minimum connectivity is also equal to `None`, then this is set to 2.

    - `minimum_connectivity` – (default: `None`) a value \(\geq 2\) and \(\leq 3\), or `None`. This specifies the minimum connectivity of the generated quadrangulations. If this is `None` and the option `no_nonfacial_quadrangles` is set to `True`, then this is set to 3. Otherwise if this is `None` and the minimum degree is specified, then this is set to the minimum degree. If the minimum degree is also equal to `None`, then this is set to 3.

    - `no_nonfacial_quadrangles` – (default: `False`) if `True` only quadrangulations with no non-facial quadrangles are generated. This option cannot be used if `minimum_connectivity` is set to 2.

    - `dual` – (default: `False`) if `True` return instead the planar duals of the generated graphs

    - `immutable` – boolean (default: `False`); whether to return immutable or mutable graphs

    OUTPUT:

    An iterator which will produce all planar quadrangulations with the given number of vertices as Sage graphs with an embedding set. These will be simple graphs (no loops, no multiple edges, no directed edges).

    See also

    - `set_embedding()`, `get_embedding()` – get/set methods for embeddings.

    EXAMPLES:

    The cube is the only 3-connected planar quadrangulation on 8 vertices:

    Sage

        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)
        Traceback (most recent call last):
        ...
        StopIteration

    Python

        >>> from sage.all import *
        >>> # optional - plantri
        >>> gen = graphs.quadrangulations(Integer(8), minimum_connectivity=Integer(3))
        >>> g = next(gen)
        >>> g.is_isomorphic(graphs.CubeGraph(Integer(3)))
        True
        >>> next(gen)
        Traceback (most recent call last):
        ...
        StopIteration

    An overview of the number of quadrangulations on up to 12 vertices. This agrees with OEIS sequence A113201:

    Sage

        sage: for i in range(4,13):                          # optional - plantri
        ....:     L =  len(list(graphs.quadrangulations(i)))
        ....:     print("{:2d}   {:3d}".format(i,L))
         4     1
         5     1
         6     2
         7     3
         8     9
         9    18
        10    62
        11   198
        12   803

    [Python]

        >>> from sage.all import *
        >>> for i in range(Integer(4),Integer(13)):                          # optional - plantri
        ...     L =  len(list(graphs.quadrangulations(i)))
        ...     print("{:2d}   {:3d}".format(i,L))
         4     1
         5     1
         6     2
         7     3
         8     9
         9    18
        10    62
        11   198
        12   803

    There are 2 planar quadrangulation on 12 vertices that do not have a non-facial quadrangle:

    Sage

        sage: len([g for g in graphs.quadrangulations(12, no_nonfacial_quadrangles=True)])  # optional - plantri
        2

    Python

        >>> from sage.all import *
        >>> len([g for g in graphs.quadrangulations(Integer(12), no_nonfacial_quadrangles=True)])  # optional - plantri
        2

    Setting `dual=True` gives the planar dual graphs:

    Sage

        sage: [len(g) for g in graphs.quadrangulations(12, no_nonfacial_quadrangles=True, dual=True)]  # optional - plantri
        [10, 10]

    [Python]

        >>> from sage.all import *
        >>> [len(g) for g in graphs.quadrangulations(Integer(12), no_nonfacial_quadrangles=True, dual=True)]  # optional - plantri
        [10, 10]

  random = <module 'sage.graphs.generators.random' from '/usr/lib/python3.13/site-packages/sage/graphs/generators/random.py'>
  static shortened_000_111_extended_binary_Golay_code_graph()

    Return a distance-regular graph with intersection array \([21, 20, 16, 9, 2, 1; 1, 2, 3, 16, 20, 21]\).

    EXAMPLES:

    Sage

        sage: # long time, needs sage.modules sage.rings.finite_rings
        sage: G = graphs.shortened_000_111_extended_binary_Golay_code_graph()
        sage: G.is_distance_regular(True)
        ([21, 20, 16, 9, 2, 1, None], [None, 1, 2, 3, 16, 20, 21])

    Python

        >>> from sage.all import *
        >>> # long time, needs sage.modules sage.rings.finite_rings
        >>> G = graphs.shortened_000_111_extended_binary_Golay_code_graph()
        >>> G.is_distance_regular(True)
        ([21, 20, 16, 9, 2, 1, None], [None, 1, 2, 3, 16, 20, 21])

    ALGORITHM:

    The vertices and edges of this graph have been precomputed and pickled, so truthfully, we just unpickle them and pass them to the Graph constructor. But the algorithm used to compute those vertices and edges in the first place is,

    1. Compute the extended binary Golay code.

    2. Compute its subcode whose codewords start with 000 or 111.

    3. Remove the first 3 entries from all the codewords from the new linear code and compute its coset graph.

    This construction is tested in `generators_test.py`, where the result is compared with the result from this method.

    REFERENCES:

    The description and construction of this graph can be found in [BCN1989], page 365.

  static shortened_00_11_binary_Golay_code_graph()

    Return a distance-regular graph with intersection array \([21, 20, 16, 6, 2, 1; 1, 2, 6, 16, 20, 21]\).

    EXAMPLES:

    Sage

        sage: # long time, needs sage.modules sage.rings.finite_rings
        sage: G = graphs.shortened_00_11_binary_Golay_code_graph()      # 9 s
        sage: G.is_distance_regular(True)
        ([21, 20, 16, 6, 2, 1, None], [None, 1, 2, 6, 16, 20, 21])

    Python

        >>> from sage.all import *
        >>> # long time, needs sage.modules sage.rings.finite_rings
        >>> G = graphs.shortened_00_11_binary_Golay_code_graph()      # 9 s
        >>> G.is_distance_regular(True)
        ([21, 20, 16, 6, 2, 1, None], [None, 1, 2, 6, 16, 20, 21])

    ALGORITHM:

    Compute the binary Golay code. Compute the subcode whose codewords start with 00 or 11. Remove the first two entries from all codewords of the newly found linear code and compute its coset graph.

    REFERENCES:

    Description and construction of this graph can be found in [BCN1989] p. 365.

  smallgraphs = <module 'sage.graphs.generators.smallgraphs' from '/usr/lib/python3.13/site-packages/sage/graphs/generators/smallgraphs.py'>
  strongly_regular_db = <module 'sage.graphs.strongly_regular_db' from '/usr/lib/python3.13/site-packages/sage/graphs/strongly_regular_db.cpython-313-x86_64-linux-gnu.so'>
  static strongly_regular_graph(v, k, l, mu=-1, existence=False, check=True)

    Return a \((v,k,\lambda,\mu)\)-strongly regular graph.

    This function relies partly on Andries Brouwer’s database of strongly regular graphs. See the documentation of `sage.graphs.strongly_regular_db` for more information.

    INPUT:

    - `v`, `k`, `l`, `mu` – `integers` – note that `mu`, if unspecified, is automatically determined from `v`, `k`, `l`

    - `existence` – boolean (default: `False`); instead of building the graph, return:

      > - `True` – meaning that a \((v,k,\lambda,\mu)\)-strongly regular graph exists

      > - `Unknown` – meaning that Sage does not know if such a strongly regular graph exists (see `sage.misc.unknown`)

      > - `False` – meaning that no such strongly regular graph exists

    - `check` – boolean (default: `True`); whether to check that output is correct before returning it. As this is expected to be useless, you may want to disable it whenever you want speed.

    EXAMPLES:

    Petersen’s graph from its set of parameters:

    Sage

        sage: graphs.strongly_regular_graph(10,3,0,1,existence=True)                    # needs sage.libs.pari
        True
        sage: graphs.strongly_regular_graph(10,3,0,1)
        complement(Johnson graph with parameters 5,2): Graph on 10 vertices

    Python

        >>> from sage.all import *
        >>> graphs.strongly_regular_graph(Integer(10),Integer(3),Integer(0),Integer(1),existence=True)                    # needs sage.libs.pari
        True
        >>> graphs.strongly_regular_graph(Integer(10),Integer(3),Integer(0),Integer(1))
        complement(Johnson graph with parameters 5,2): Graph on 10 vertices

    Now without specifying \(\mu\):

    Sage

        sage: graphs.strongly_regular_graph(10,3,0)
        complement(Johnson graph with parameters 5,2): Graph on 10 vertices

    [Python]

        >>> from sage.all import *
        >>> graphs.strongly_regular_graph(Integer(10),Integer(3),Integer(0))
        complement(Johnson graph with parameters 5,2): Graph on 10 vertices

    An obviously infeasible set of parameters:

    Sage

        sage: graphs.strongly_regular_graph(5,5,5,5,existence=True)
        False
        sage: graphs.strongly_regular_graph(5,5,5,5)
        Traceback (most recent call last):
        ...
        ValueError: There exists no (5, 5, 5, 5)-strongly regular graph

    Python

        >>> from sage.all import *
        >>> graphs.strongly_regular_graph(Integer(5),Integer(5),Integer(5),Integer(5),existence=True)
        False
        >>> graphs.strongly_regular_graph(Integer(5),Integer(5),Integer(5),Integer(5))
        Traceback (most recent call last):
        ...
        ValueError: There exists no (5, 5, 5, 5)-strongly regular graph

    A set of parameters proved in a paper to be infeasible:

    Sage

        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)                                # needs sage.combinat sage.modules
        Traceback (most recent call last):
        ...
        EmptySetError: Andries Brouwer's database reports that no (324, 57, 0,
        12)-strongly regular graph exists. Comments: <a
        href="srgtabrefs.html#GavrilyukMakhnev05">Gavrilyuk & Makhnev</a> ...

    [Python]

        >>> from sage.all import *
        >>> graphs.strongly_regular_graph(Integer(324),Integer(57),Integer(0),Integer(12),existence=True)                 # needs sage.combinat sage.modules
        False
        >>> graphs.strongly_regular_graph(Integer(324),Integer(57),Integer(0),Integer(12))                                # needs sage.combinat sage.modules
        Traceback (most recent call last):
        ...
        EmptySetError: Andries Brouwer's database reports that no (324, 57, 0,
        12)-strongly regular graph exists. Comments: <a
        href="srgtabrefs.html#GavrilyukMakhnev05">Gavrilyuk & Makhnev</a> ...

    A set of parameters unknown to be realizable in Andries Brouwer’s database:

    Sage

        sage: graphs.strongly_regular_graph(324,95,22,30,existence=True)                # needs sage.combinat
        Unknown
        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
        (324, 95, 22, 30)-strongly regular graph is known to exist.
        Comments:

    Python

        >>> from sage.all import *
        >>> graphs.strongly_regular_graph(Integer(324),Integer(95),Integer(22),Integer(30),existence=True)                # needs sage.combinat
        Unknown
        >>> graphs.strongly_regular_graph(Integer(324),Integer(95),Integer(22),Integer(30))                               # needs sage.combinat
        Traceback (most recent call last):
        ...
        RuntimeError: Andries Brouwer's database reports that no
        (324, 95, 22, 30)-strongly regular graph is known to exist.
        Comments:

    A large unknown set of parameters (not in Andries Brouwer’s database):

    Sage

        sage: graphs.strongly_regular_graph(1394,175,0,25,existence=True)               # needs sage.combinat
        Unknown
        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
        regular graph exists.

    [Python]

        >>> from sage.all import *
        >>> graphs.strongly_regular_graph(Integer(1394),Integer(175),Integer(0),Integer(25),existence=True)               # needs sage.combinat
        Unknown
        >>> graphs.strongly_regular_graph(Integer(1394),Integer(175),Integer(0),Integer(25))                              # needs sage.combinat
        Traceback (most recent call last):
        ...
        RuntimeError: Sage cannot figure out if a (1394, 175, 0, 25)-strongly
        regular graph exists.

    Test the Claw bound (see 3.D of [BL1984]):

    Sage

        sage: graphs.strongly_regular_graph(2058,242,91,20,existence=True)
        False

    Python

        >>> from sage.all import *
        >>> graphs.strongly_regular_graph(Integer(2058),Integer(242),Integer(91),Integer(20),existence=True)
        False

  static trees(n)

    Return a generator of the distinct trees on a fixed number of vertices.

    INPUT:

    - `n` – integer; the size of the trees created

    OUTPUT:

    A generator which creates an exhaustive, duplicate-free listing of the connected free (unlabeled) trees with `n` vertices. A tree is a graph with no cycles.

    ALGORITHM:

    Uses the algorithm that generates each new tree in constant time described in [WROM1986]. See the documentation for, and implementation of, the `sage.graphs.generators.trees` module.

    EXAMPLES:

    We create an iterator, then loop over its elements:

    Sage

        sage: tree_iterator = graphs.trees(7)
        sage: for T in tree_iterator:
        ....:     print(T.degree_sequence())
        [2, 2, 2, 2, 2, 1, 1]
        [3, 2, 2, 2, 1, 1, 1]
        [3, 2, 2, 2, 1, 1, 1]
        [4, 2, 2, 1, 1, 1, 1]
        [3, 3, 2, 1, 1, 1, 1]
        [3, 3, 2, 1, 1, 1, 1]
        [4, 3, 1, 1, 1, 1, 1]
        [3, 2, 2, 2, 1, 1, 1]
        [4, 2, 2, 1, 1, 1, 1]
        [5, 2, 1, 1, 1, 1, 1]
        [6, 1, 1, 1, 1, 1, 1]

    Python

        >>> from sage.all import *
        >>> tree_iterator = graphs.trees(Integer(7))
        >>> for T in tree_iterator:
        ...     print(T.degree_sequence())
        [2, 2, 2, 2, 2, 1, 1]
        [3, 2, 2, 2, 1, 1, 1]
        [3, 2, 2, 2, 1, 1, 1]
        [4, 2, 2, 1, 1, 1, 1]
        [3, 3, 2, 1, 1, 1, 1]
        [3, 3, 2, 1, 1, 1, 1]
        [4, 3, 1, 1, 1, 1, 1]
        [3, 2, 2, 2, 1, 1, 1]
        [4, 2, 2, 1, 1, 1, 1]
        [5, 2, 1, 1, 1, 1, 1]
        [6, 1, 1, 1, 1, 1, 1]

    The number of trees on the first few vertex counts. This is sequence A000055 in Sloane’s OEIS:

    Sage

        sage: [len(list(graphs.trees(i))) for i in range(15)]
        [1, 1, 1, 1, 2, 3, 6, 11, 23, 47, 106, 235, 551, 1301, 3159]

    [Python]

        >>> from sage.all import *
        >>> [len(list(graphs.trees(i))) for i in range(Integer(15))]
        [1, 1, 1, 1, 2, 3, 6, 11, 23, 47, 106, 235, 551, 1301, 3159]

  triangulations(order, minimum_degree=None, minimum_connectivity=None, exact_connectivity=False, only_eulerian=False, dual=False, immutable=False)

    An iterator over connected planar triangulations using the plantri generator.

    This uses the plantri generator (see [BM2007]) which is available through the optional package plantri.

    INPUT:

    - `order` – positive integer smaller than or equal to 64; this specifies the number of vertices in the generated triangulations

    - `minimum_degree` – (default: `None`) a value \(\geq 3\) and \(\leq 5\), or `None`. This specifies the minimum degree of the generated triangulations. If this is `None` and the minimum connectivity is specified, then this is set to the same value as the minimum connectivity. If the minimum connectivity is also equal to `None`, then this is set to 3.

    - `minimum_connectivity` – (default: `None`) a value \(\geq 3\) and \(\leq 5\), or `None`. This specifies the minimum connectivity of the generated triangulations. If this is `None` and the minimum degree is specified, then this is set to the minimum of the minimum degree and 3. If the minimum degree is also equal to `None`, then this is set to 3.

    - `exact_connectivity` – (default: `False`) if `True` only triangulations with exactly the specified connectivity will be generated. This option cannot be used with `minimum_connectivity=3`, or if the minimum connectivity is not explicitly set.

    - `only_eulerian` – (default: `False`) if `True` only Eulerian triangulations will be generated. This option cannot be used if the minimum degree is explicitly set to anything else than 4.

    - `dual` – (default: `False`) if `True` return instead the planar duals of the generated graphs

    - `immutable` – boolean (default: `False`); whether to return immutable or mutable graphs

    OUTPUT:

    An iterator which will produce all planar triangulations with the given number of vertices as Sage graphs with an embedding set. These will be simple graphs (no loops, no multiple edges, no directed edges).

    See also

    - `set_embedding()`, `get_embedding()` – get/set methods for embeddings.

    - `RandomTriangulation()` – build a random triangulation.

    EXAMPLES:

    The unique planar embedding of the \(K_4\) is the only planar triangulations on 4 vertices:

    Sage

        sage: gen = graphs.triangulations(4)    # optional - plantri
        sage: [g.get_embedding() for g in gen]  # optional - plantri
        [{1: [2, 3, 4], 2: [1, 4, 3], 3: [1, 2, 4], 4: [1, 3, 2]}]

    Python

        >>> from sage.all import *
        >>> gen = graphs.triangulations(Integer(4))    # optional - plantri
        >>> [g.get_embedding() for g in gen]  # optional - plantri
        [{1: [2, 3, 4], 2: [1, 4, 3], 3: [1, 2, 4], 4: [1, 3, 2]}]

    but, of course, this graph is not Eulerian:

    Sage

        sage: gen = graphs.triangulations(4, only_eulerian=True)  # optional - plantri
        sage: len(list(gen))                                      # optional - plantri
        0

    [Python]

        >>> from sage.all import *
        >>> gen = graphs.triangulations(Integer(4), only_eulerian=True)  # optional - plantri
        >>> len(list(gen))                                      # optional - plantri
        0

    The unique Eulerian triangulation on 6 vertices is isomorphic to the octahedral graph.

    Sage

        sage: gen = graphs.triangulations(6, only_eulerian=True)  # optional - plantri
        sage: g = next(gen)                                       # optional - plantri
        sage: g.is_isomorphic(graphs.OctahedralGraph())           # optional - plantri
        True

    Python

        >>> from sage.all import *
        >>> gen = graphs.triangulations(Integer(6), only_eulerian=True)  # optional - plantri
        >>> g = next(gen)                                       # optional - plantri
        >>> g.is_isomorphic(graphs.OctahedralGraph())           # optional - plantri
        True

    The minimum degree of a triangulation is 3, so the method can not output a triangle:

    Sage

        sage: list(graphs.triangulations(3))                      # optional - plantri
        []

    [Python]

        >>> from sage.all import *
        >>> list(graphs.triangulations(Integer(3)))                      # optional - plantri
        []

    An overview of the number of 5-connected triangulations on up to 22 vertices. This agrees with OEIS sequence A081621:

    Sage

        sage: for i in range(12, 23):                                             # optional - plantri
        ....:     L = len(list(graphs.triangulations(i, minimum_connectivity=5)))
        ....:     print("{}   {:3d}".format(i,L))
        12     1
        13     0
        14     1
        15     1
        16     3
        17     4
        18    12
        19    23
        20    71
        21   187
        22   627

    Python

        >>> from sage.all import *
        >>> for i in range(Integer(12), Integer(23)):                                             # optional - plantri
        ...     L = len(list(graphs.triangulations(i, minimum_connectivity=Integer(5))))
        ...     print("{}   {:3d}".format(i,L))
        12     1
        13     0
        14     1
        15     1
        16     3
        17     4
        18    12
        19    23
        20    71
        21   187
        22   627

    The minimum connectivity can be at most the minimum degree:

    Sage

        sage: gen = next(graphs.triangulations(10, minimum_degree=3,     # optional - plantri
        ....:                                  minimum_connectivity=5))
        Traceback (most recent call last):
        ...
        ValueError: Minimum connectivity can be at most the minimum degree.

    [Python]

        >>> from sage.all import *
        >>> gen = next(graphs.triangulations(Integer(10), minimum_degree=Integer(3),     # optional - plantri
        ...                                  minimum_connectivity=Integer(5)))
        Traceback (most recent call last):
        ...
        ValueError: Minimum connectivity can be at most the minimum degree.

    There are 5 triangulations with 9 vertices and minimum degree equal to 4 that are 3-connected, but only one of them is not 4-connected:

    Sage

        sage: len([g for g in graphs.triangulations(9, minimum_degree=4,        # optional - plantri
        ....:                                       minimum_connectivity=3)])
        5
        sage: len([g for g in graphs.triangulations(9, minimum_degree=4,        # optional - plantri
        ....:                                       minimum_connectivity=3,
        ....:                                       exact_connectivity=True)])
        1

    Python

        >>> from sage.all import *
        >>> len([g for g in graphs.triangulations(Integer(9), minimum_degree=Integer(4),        # optional - plantri
        ...                                       minimum_connectivity=Integer(3))])
        5
        >>> len([g for g in graphs.triangulations(Integer(9), minimum_degree=Integer(4),        # optional - plantri
        ...                                       minimum_connectivity=Integer(3),
        ...                                       exact_connectivity=True)])
        1

    Setting `dual=True` gives the planar dual graphs:

    Sage

        sage: [len(g) for g in graphs.triangulations(9, minimum_degree=4,       # optional plantri
        ....:                                        minimum_connectivity=3, dual=True)]
        [14, 14, 14, 14, 14]

    [Python]

        >>> from sage.all import *
        >>> [len(g) for g in graphs.triangulations(Integer(9), minimum_degree=Integer(4),       # optional plantri
        ...                                        minimum_connectivity=Integer(3), dual=True)]
        [14, 14, 14, 14, 14]

  static vanLintSchrijverGraph()

    Return the van Lint-Schrijver graph.

    The graph is distance-regular with intersection array \([6, 5, 5, 4; 1, 1, 2, 6]\).

    EXAMPLES:

    Sage

        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])

    Python

        >>> from sage.all import *
        >>> G = graphs.vanLintSchrijverGraph()                                       # needs sage.modules
        >>> G.is_distance_regular(True)                                              # needs sage.modules
        ([6, 5, 5, 4, None], [None, 1, 1, 2, 6])

    REFERENCES:

    For a description of this graph see [BCN1989] p. 373.

  world_map = <module 'sage.graphs.generators.world_map' from '/usr/lib/python3.13/site-packages/sage/graphs/generators/world_map.py'>

sage.graphs.graph_generators.canaug_traverse_edge(g, aut_gens, property, dig=False, loops=False, sparse=True)

  Main function for exhaustive generation. Recursive traversal of a canonically generated tree of isomorph free graphs satisfying a given property.

  INPUT:

  - `g` – current position on the tree

  - `aut_gens` – list of generators of Aut(g), in list notation

  - `property` – check before traversing below g

  EXAMPLES:

  Sage

      sage: from sage.graphs.graph_generators import canaug_traverse_edge
      sage: G = Graph(3)
      sage: list(canaug_traverse_edge(G, [], lambda x: True))
      [Graph on 3 vertices, ... Graph on 3 vertices]

  Python

      >>> from sage.all import *
      >>> from sage.graphs.graph_generators import canaug_traverse_edge
      >>> G = Graph(Integer(3))
      >>> list(canaug_traverse_edge(G, [], lambda x: True))
      [Graph on 3 vertices, ... Graph on 3 vertices]

  The best way to access this function is through the graphs() iterator:

  Print graphs on 3 or less vertices.

  Sage

      sage: for G in graphs(3):
      ....:     print(G)
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 3 vertices

  [Python]

      >>> from sage.all import *
      >>> for G in graphs(Integer(3)):
      ...     print(G)
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 3 vertices

  Print digraphs on 3 or less vertices.

  Sage

      sage: for G in digraphs(3):
      ....:     print(G)
      Digraph on 3 vertices
      Digraph on 3 vertices
      ...
      Digraph on 3 vertices
      Digraph on 3 vertices

  Python

      >>> from sage.all import *
      >>> for G in digraphs(Integer(3)):
      ...     print(G)
      Digraph on 3 vertices
      Digraph on 3 vertices
      ...
      Digraph on 3 vertices
      Digraph on 3 vertices

sage.graphs.graph_generators.canaug_traverse_vert(g, aut_gens, max_verts, property, dig=False, loops=False, sparse=True)

  Main function for exhaustive generation. Recursive traversal of a canonically generated tree of isomorph free (di)graphs satisfying a given property.

  INPUT:

  - `g` – current position on the tree

  - `aut_gens` – list of generators of Aut(g), in list notation

  - `max_verts` – when to retreat

  - `property` – check before traversing below g

  - `degree_sequence` – specify a degree sequence to try to obtain

  EXAMPLES:

  Sage

      sage: from sage.graphs.graph_generators import canaug_traverse_vert
      sage: list(canaug_traverse_vert(Graph(), [], 3, lambda x: True))
      [Graph on 0 vertices, ... Graph on 3 vertices]

  Python

      >>> from sage.all import *
      >>> from sage.graphs.graph_generators import canaug_traverse_vert
      >>> list(canaug_traverse_vert(Graph(), [], Integer(3), lambda x: True))
      [Graph on 0 vertices, ... Graph on 3 vertices]

  The best way to access this function is through the graphs() iterator:

  Print graphs on 3 or less vertices.

  Sage

      sage: for G in graphs(3, augment='vertices'):
      ....:    print(G)
      Graph on 0 vertices
      Graph on 1 vertex
      Graph on 2 vertices
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 2 vertices
      Graph on 3 vertices

  [Python]

      >>> from sage.all import *
      >>> for G in graphs(Integer(3), augment='vertices'):
      ...    print(G)
      Graph on 0 vertices
      Graph on 1 vertex
      Graph on 2 vertices
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 3 vertices
      Graph on 2 vertices
      Graph on 3 vertices

  Print digraphs on 2 or less vertices.

  Sage

      sage: for D in digraphs(2, augment='vertices'):
      ....:     print(D)
      Digraph on 0 vertices
      Digraph on 1 vertex
      Digraph on 2 vertices
      Digraph on 2 vertices
      Digraph on 2 vertices

  Python

      >>> from sage.all import *
      >>> for D in digraphs(Integer(2), augment='vertices'):
      ...     print(D)
      Digraph on 0 vertices
      Digraph on 1 vertex
      Digraph on 2 vertices
      Digraph on 2 vertices
      Digraph on 2 vertices

sage.graphs.graph_generators.check_aut(aut_gens, cut_vert, n)

  Helper function for exhaustive generation.

  At the start, check_aut is given a set of generators for the automorphism group, aut_gens. We already know we are looking for an element of the auto- morphism group that sends cut_vert to n, and check_aut generates these for the canaug_traverse function.

  EXAMPLES:

  Note that the last two entries indicate that none of the automorphism group has yet been searched - we are starting at the identity [0, 1, 2, 3] and so far that is all we have seen. We return automorphisms mapping 2 to 3:

  Sage

      sage: from sage.graphs.graph_generators import check_aut
      sage: list( check_aut( [ [0, 3, 2, 1], [1, 0, 3, 2], [2, 1, 0, 3] ], 2, 3))
      [[1, 0, 3, 2], [1, 2, 3, 0]]

  Python

      >>> from sage.all import *
      >>> from sage.graphs.graph_generators import check_aut
      >>> list( check_aut( [ [Integer(0), Integer(3), Integer(2), Integer(1)], [Integer(1), Integer(0), Integer(3), Integer(2)], [Integer(2), Integer(1), Integer(0), Integer(3)] ], Integer(2), Integer(3)))
      [[1, 0, 3, 2], [1, 2, 3, 0]]

sage.graphs.graph_generators.check_aut_edge(aut_gens, cut_edge, i, j, n, dig=False)

  Helper function for exhaustive generation.

  At the start, check_aut_edge is given a set of generators for the automorphism group, aut_gens. We already know we are looking for an element of the auto- morphism group that sends cut_edge to {i, j}, and check_aut generates these for the canaug_traverse function.

  EXAMPLES:

  Note that the last two entries indicate that none of the automorphism group has yet been searched - we are starting at the identity [0, 1, 2, 3] and so far that is all we have seen. We return automorphisms mapping 2 to 3:

  Sage

      sage: from sage.graphs.graph_generators import check_aut
      sage: list( check_aut( [ [0, 3, 2, 1], [1, 0, 3, 2], [2, 1, 0, 3] ], 2, 3))
      [[1, 0, 3, 2], [1, 2, 3, 0]]

  Python

      >>> from sage.all import *
      >>> from sage.graphs.graph_generators import check_aut
      >>> list( check_aut( [ [Integer(0), Integer(3), Integer(2), Integer(1)], [Integer(1), Integer(0), Integer(3), Integer(2)], [Integer(2), Integer(1), Integer(0), Integer(3)] ], Integer(2), Integer(3)))
      [[1, 0, 3, 2], [1, 2, 3, 0]]