Fast compiled graphs - Graph Theory

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

# Fast compiled graphs

This is a Cython implementation of the base class for sparse and dense graphs in Sage. It is not intended for use on its own. Specific graph types should extend this base class and implement missing functionalities. Whenever possible, specific methods should also be overridden with implementations that suit the graph type under consideration.

For an overview of graph data structures in sage, see `overview`.

## Data structure

The class `CGraph` maintains the following variables:

- `cdef int num_verts`

- `cdef int num_arcs`

- `cdef int *in_degrees`

- `cdef int *out_degrees`

- `cdef bitset_t active_vertices`

The bitset `active_vertices` is a list of all available vertices for use, but only the ones which are set are considered to actually be in the graph. The variables `num_verts` and `num_arcs` are self-explanatory. Note that `num_verts` is the number of bits set in `active_vertices`, not the full length of the bitset. The arrays `in_degrees` and `out_degrees` are of the same length as the bitset.

For more information about active vertices, see the documentation for the method `realloc`.

class sage.graphs.base.c_graph.CGraph

  Bases: `object`

  Compiled sparse and dense graphs.

  add_arc(u, v)

    Add arc `(u, v)` to the graph.

    INPUT:

    - `u`, `v` – nonnegative integers; must be in self

    EXAMPLES:

    On the `CGraph` level, this always produces an error, as there are no vertices:

    Sage

        sage: from sage.graphs.base.c_graph import CGraph
        sage: G = CGraph()
        sage: G.add_arc(0, 1)
        Traceback (most recent call last):
        ...
        LookupError: vertex (0) is not a vertex of the graph

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.c_graph import CGraph
        >>> G = CGraph()
        >>> G.add_arc(Integer(0), Integer(1))
        Traceback (most recent call last):
        ...
        LookupError: vertex (0) is not a vertex of the graph

    It works, once there are vertices and `add_arc_unsafe()` is implemented:

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: G = DenseGraph(5)
        sage: G.add_arc(0, 1)
        sage: G.add_arc(4, 7)
        Traceback (most recent call last):
        ...
        LookupError: vertex (7) is not a vertex of the graph
        sage: G.has_arc(1, 0)
        False
        sage: G.has_arc(0, 1)
        True

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: G = SparseGraph(5)
        sage: G.add_arc(0,1)
        sage: G.add_arc(4,7)
        Traceback (most recent call last):
        ...
        LookupError: vertex (7) is not a vertex of the graph
        sage: G.has_arc(1,0)
        False
        sage: G.has_arc(0,1)
        True

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> G = DenseGraph(Integer(5))
        >>> G.add_arc(Integer(0), Integer(1))
        >>> G.add_arc(Integer(4), Integer(7))
        Traceback (most recent call last):
        ...
        LookupError: vertex (7) is not a vertex of the graph
        >>> G.has_arc(Integer(1), Integer(0))
        False
        >>> G.has_arc(Integer(0), Integer(1))
        True

        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> G = SparseGraph(Integer(5))
        >>> G.add_arc(Integer(0),Integer(1))
        >>> G.add_arc(Integer(4),Integer(7))
        Traceback (most recent call last):
        ...
        LookupError: vertex (7) is not a vertex of the graph
        >>> G.has_arc(Integer(1),Integer(0))
        False
        >>> G.has_arc(Integer(0),Integer(1))
        True

  add_vertex(k=-1)

    Add vertex `k` to the graph.

    INPUT:

    - `k` – nonnegative integer or `-1` (default: `-1`); if \(k = -1\), a new vertex is added and the integer used is returned. That is, for \(k = -1\), this function will find the first available vertex that is not in `self` and add that vertex to this graph.

    OUTPUT:

    - `-1` – indicates that no vertex was added because the current allocation is already full or the vertex is out of range

    - nonnegative integer – this vertex is now guaranteed to be in the graph

    See also

    - `add_vertex_unsafe` – add a vertex to a graph. This method is potentially unsafe. You should instead use `add_vertex()`

    - `add_vertices` – add a bunch of vertices to a graph

    EXAMPLES:

    Adding vertices to a sparse graph:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: G = SparseGraph(3, extra_vertices=3)
        sage: G.add_vertex(3)
        3
        sage: G.add_arc(2, 5)
        Traceback (most recent call last):
        ...
        LookupError: vertex (5) is not a vertex of the graph
        sage: G.add_arc(1, 3)
        sage: G.has_arc(1, 3)
        True
        sage: G.has_arc(2, 3)
        False

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> G = SparseGraph(Integer(3), extra_vertices=Integer(3))
        >>> G.add_vertex(Integer(3))
        3
        >>> G.add_arc(Integer(2), Integer(5))
        Traceback (most recent call last):
        ...
        LookupError: vertex (5) is not a vertex of the graph
        >>> G.add_arc(Integer(1), Integer(3))
        >>> G.has_arc(Integer(1), Integer(3))
        True
        >>> G.has_arc(Integer(2), Integer(3))
        False

    Adding vertices to a dense graph:

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: G = DenseGraph(3, extra_vertices=3)
        sage: G.add_vertex(3)
        3
        sage: G.add_arc(2,5)
        Traceback (most recent call last):
        ...
        LookupError: vertex (5) is not a vertex of the graph
        sage: G.add_arc(1, 3)
        sage: G.has_arc(1, 3)
        True
        sage: G.has_arc(2, 3)
        False

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> G = DenseGraph(Integer(3), extra_vertices=Integer(3))
        >>> G.add_vertex(Integer(3))
        3
        >>> G.add_arc(Integer(2),Integer(5))
        Traceback (most recent call last):
        ...
        LookupError: vertex (5) is not a vertex of the graph
        >>> G.add_arc(Integer(1), Integer(3))
        >>> G.has_arc(Integer(1), Integer(3))
        True
        >>> G.has_arc(Integer(2), Integer(3))
        False

    Repeatedly adding a vertex using \(k = -1\) will allocate more memory as required:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: G = SparseGraph(3, extra_vertices=0)
        sage: G.verts()
        [0, 1, 2]
        sage: for i in range(10):
        ....:     _ = G.add_vertex(-1);
        ...
        sage: G.verts()
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> G = SparseGraph(Integer(3), extra_vertices=Integer(0))
        >>> G.verts()
        [0, 1, 2]
        >>> for i in range(Integer(10)):
        ...     _ = G.add_vertex(-Integer(1));
        ...
        >>> G.verts()
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: G = DenseGraph(3, extra_vertices=0)
        sage: G.verts()
        [0, 1, 2]
        sage: for i in range(12):
        ....:     _ = G.add_vertex(-1);
        ...
        sage: G.verts()
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> G = DenseGraph(Integer(3), extra_vertices=Integer(0))
        >>> G.verts()
        [0, 1, 2]
        >>> for i in range(Integer(12)):
        ...     _ = G.add_vertex(-Integer(1));
        ...
        >>> G.verts()
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

  add_vertices(verts)

    Add vertices from the iterable `verts`.

    INPUT:

    - `verts` – an iterable of vertices; value -1 has a special meaning – for each such value an unused vertex name is found, used to create a new vertex and returned.

    OUTPUT:

    List of generated labels if there is any -1 in `verts`. `None` otherwise.

    See also

    - `add_vertex()` – add a vertex to a graph

    EXAMPLES:

    Adding vertices for sparse graphs:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: S = SparseGraph(nverts=4, extra_vertices=4)
        sage: S.verts()
        [0, 1, 2, 3]
        sage: S.add_vertices([3, -1, 4, 9])
        [5]
        sage: S.verts()
        [0, 1, 2, 3, 4, 5, 9]
        sage: S.realloc(20)
        sage: S.verts()
        [0, 1, 2, 3, 4, 5, 9]

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> S = SparseGraph(nverts=Integer(4), extra_vertices=Integer(4))
        >>> S.verts()
        [0, 1, 2, 3]
        >>> S.add_vertices([Integer(3), -Integer(1), Integer(4), Integer(9)])
        [5]
        >>> S.verts()
        [0, 1, 2, 3, 4, 5, 9]
        >>> S.realloc(Integer(20))
        >>> S.verts()
        [0, 1, 2, 3, 4, 5, 9]

    Adding vertices for dense graphs:

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: D = DenseGraph(nverts=4, extra_vertices=4)
        sage: D.verts()
        [0, 1, 2, 3]
        sage: D.add_vertices([3, -1, 4, 9])
        [5]
        sage: D.verts()
        [0, 1, 2, 3, 4, 5, 9]
        sage: D.realloc(20)
        sage: D.verts()
        [0, 1, 2, 3, 4, 5, 9]

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> D = DenseGraph(nverts=Integer(4), extra_vertices=Integer(4))
        >>> D.verts()
        [0, 1, 2, 3]
        >>> D.add_vertices([Integer(3), -Integer(1), Integer(4), Integer(9)])
        [5]
        >>> D.verts()
        [0, 1, 2, 3, 4, 5, 9]
        >>> D.realloc(Integer(20))
        >>> D.verts()
        [0, 1, 2, 3, 4, 5, 9]

  all_arcs(u, v)

    Give the labels of all arcs `(u, v)`. An unlabeled arc is interpreted as having label 0.

    EXAMPLES:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: G = SparseGraph(5)
        sage: G.add_arc_label(1,2,1)
        sage: G.add_arc_label(1,2,2)
        sage: G.add_arc_label(1,2,2)
        sage: G.add_arc_label(1,2,2)
        sage: G.add_arc_label(1,2,3)
        sage: G.add_arc_label(1,2,3)
        sage: G.add_arc_label(1,2,4)
        sage: G.all_arcs(1,2)
        [4, 3, 3, 2, 2, 2, 1]

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> G = SparseGraph(Integer(5))
        >>> G.add_arc_label(Integer(1),Integer(2),Integer(1))
        >>> G.add_arc_label(Integer(1),Integer(2),Integer(2))
        >>> G.add_arc_label(Integer(1),Integer(2),Integer(2))
        >>> G.add_arc_label(Integer(1),Integer(2),Integer(2))
        >>> G.add_arc_label(Integer(1),Integer(2),Integer(3))
        >>> G.add_arc_label(Integer(1),Integer(2),Integer(3))
        >>> G.add_arc_label(Integer(1),Integer(2),Integer(4))
        >>> G.all_arcs(Integer(1),Integer(2))
        [4, 3, 3, 2, 2, 2, 1]

  arc_label(u, v)

    Retrieves the first label found associated with `(u, v)`.

    INPUT:

    - `u`, `v` – nonnegative integers; must be in self

    OUTPUT: one of

    - positive integer – indicates that there is a label on `(u, v)`

    - `0` – either the arc `(u, v)` is unlabeled, or there is no arc at all

    EXAMPLES:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: G = SparseGraph(5)
        sage: G.add_arc_label(3,4,7)
        sage: G.arc_label(3,4)
        7

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> G = SparseGraph(Integer(5))
        >>> G.add_arc_label(Integer(3),Integer(4),Integer(7))
        >>> G.arc_label(Integer(3),Integer(4))
        7

    To this function, an unlabeled arc is indistinguishable from a non-arc:

    Sage

        sage: G.add_arc_label(1,0)
        sage: G.arc_label(1,0)
        0
        sage: G.arc_label(1,1)
        0

    [Python]

        >>> from sage.all import *
        >>> G.add_arc_label(Integer(1),Integer(0))
        >>> G.arc_label(Integer(1),Integer(0))
        0
        >>> G.arc_label(Integer(1),Integer(1))
        0

    This function only returns the first label it finds from `u` to `v`:

    Sage

        sage: G.add_arc_label(1,2,1)
        sage: G.add_arc_label(1,2,2)
        sage: G.arc_label(1,2)
        2

    Python

        >>> from sage.all import *
        >>> G.add_arc_label(Integer(1),Integer(2),Integer(1))
        >>> G.add_arc_label(Integer(1),Integer(2),Integer(2))
        >>> G.arc_label(Integer(1),Integer(2))
        2

  check_vertex(n)

    Check that \(n\) is a vertex of `self`.

    This method is different from `has_vertex()`. The current method raises an error if \(n\) is not a vertex of this graph. On the other hand, `has_vertex()` returns a boolean to signify whether or not \(n\) is a vertex of this graph.

    INPUT:

    - `n` – nonnegative integer representing a vertex

    OUTPUT: raise an error if \(n\) is not a vertex of this graph

    See also

    - `has_vertex()` – determine whether this graph has a specific vertex

    EXAMPLES:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: S = SparseGraph(nverts=10, expected_degree=3, extra_vertices=10)
        sage: S.check_vertex(4)
        sage: S.check_vertex(12)
        Traceback (most recent call last):
        ...
        LookupError: vertex (12) is not a vertex of the graph
        sage: S.check_vertex(24)
        Traceback (most recent call last):
        ...
        LookupError: vertex (24) is not a vertex of the graph
        sage: S.check_vertex(-19)
        Traceback (most recent call last):
        ...
        LookupError: vertex (-19) is not a vertex of the graph

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> S = SparseGraph(nverts=Integer(10), expected_degree=Integer(3), extra_vertices=Integer(10))
        >>> S.check_vertex(Integer(4))
        >>> S.check_vertex(Integer(12))
        Traceback (most recent call last):
        ...
        LookupError: vertex (12) is not a vertex of the graph
        >>> S.check_vertex(Integer(24))
        Traceback (most recent call last):
        ...
        LookupError: vertex (24) is not a vertex of the graph
        >>> S.check_vertex(-Integer(19))
        Traceback (most recent call last):
        ...
        LookupError: vertex (-19) is not a vertex of the graph

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: D = DenseGraph(nverts=10, extra_vertices=10)
        sage: D.check_vertex(4)
        sage: D.check_vertex(12)
        Traceback (most recent call last):
        ...
        LookupError: vertex (12) is not a vertex of the graph
        sage: D.check_vertex(24)
        Traceback (most recent call last):
        ...
        LookupError: vertex (24) is not a vertex of the graph
        sage: D.check_vertex(-19)
        Traceback (most recent call last):
        ...
        LookupError: vertex (-19) is not a vertex of the graph

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> D = DenseGraph(nverts=Integer(10), extra_vertices=Integer(10))
        >>> D.check_vertex(Integer(4))
        >>> D.check_vertex(Integer(12))
        Traceback (most recent call last):
        ...
        LookupError: vertex (12) is not a vertex of the graph
        >>> D.check_vertex(Integer(24))
        Traceback (most recent call last):
        ...
        LookupError: vertex (24) is not a vertex of the graph
        >>> D.check_vertex(-Integer(19))
        Traceback (most recent call last):
        ...
        LookupError: vertex (-19) is not a vertex of the graph

  current_allocation()

    Report the number of vertices allocated.

    OUTPUT:

    - The number of vertices allocated. This number is usually different from the order of a graph. We may have allocated enough memory for a graph to hold \(n > 0\) vertices, but the order (actual number of vertices) of the graph could be less than \(n\).

    EXAMPLES:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: S = SparseGraph(nverts=4, extra_vertices=4)
        sage: S.current_allocation()
        8
        sage: S.add_vertex(6)
        6
        sage: S.current_allocation()
        8
        sage: S.add_vertex(10)
        10
        sage: S.current_allocation()
        16
        sage: S.add_vertex(40)
        Traceback (most recent call last):
        ...
        RuntimeError: requested vertex is past twice the allocated range: use realloc
        sage: S.realloc(50)
        sage: S.add_vertex(40)
        40
        sage: S.current_allocation()
        50
        sage: S.realloc(30)
        -1
        sage: S.current_allocation()
        50
        sage: S.del_vertex(40)
        sage: S.realloc(30)
        sage: S.current_allocation()
        30

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> S = SparseGraph(nverts=Integer(4), extra_vertices=Integer(4))
        >>> S.current_allocation()
        8
        >>> S.add_vertex(Integer(6))
        6
        >>> S.current_allocation()
        8
        >>> S.add_vertex(Integer(10))
        10
        >>> S.current_allocation()
        16
        >>> S.add_vertex(Integer(40))
        Traceback (most recent call last):
        ...
        RuntimeError: requested vertex is past twice the allocated range: use realloc
        >>> S.realloc(Integer(50))
        >>> S.add_vertex(Integer(40))
        40
        >>> S.current_allocation()
        50
        >>> S.realloc(Integer(30))
        -1
        >>> S.current_allocation()
        50
        >>> S.del_vertex(Integer(40))
        >>> S.realloc(Integer(30))
        >>> S.current_allocation()
        30

    The actual number of vertices in a graph might be less than the number of vertices allocated for the graph:

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: G = DenseGraph(nverts=3, extra_vertices=2)
        sage: order = len(G.verts())
        sage: order
        3
        sage: G.current_allocation()
        5
        sage: order < G.current_allocation()
        True

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> G = DenseGraph(nverts=Integer(3), extra_vertices=Integer(2))
        >>> order = len(G.verts())
        >>> order
        3
        >>> G.current_allocation()
        5
        >>> order < G.current_allocation()
        True

  del_all_arcs(u, v)

    Delete all arcs from `u` to `v`.

    INPUT:

    - `u` – integer; the tail of an arc

    - `v` – integer; the head of an arc

    EXAMPLES:

    On the `CGraph` level, this always produces an error, as there are no vertices:

    Sage

        sage: from sage.graphs.base.c_graph import CGraph
        sage: G = CGraph()
        sage: G.del_all_arcs(0,1)
        Traceback (most recent call last):
        ...
        LookupError: vertex (0) is not a vertex of the graph

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.c_graph import CGraph
        >>> G = CGraph()
        >>> G.del_all_arcs(Integer(0),Integer(1))
        Traceback (most recent call last):
        ...
        LookupError: vertex (0) is not a vertex of the graph

    It works, once there are vertices and `del_arc_unsafe()` is implemented:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: G = SparseGraph(5)
        sage: G.add_arc_label(0,1,0)
        sage: G.add_arc_label(0,1,1)
        sage: G.add_arc_label(0,1,2)
        sage: G.add_arc_label(0,1,3)
        sage: G.del_all_arcs(0,1)
        sage: G.has_arc(0,1)
        False
        sage: G.arc_label(0,1)
        0
        sage: G.del_all_arcs(0,1)

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: G = DenseGraph(5)
        sage: G.add_arc(0, 1)
        sage: G.has_arc(0, 1)
        True
        sage: G.del_all_arcs(0, 1)
        sage: G.has_arc(0, 1)
        False

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> G = SparseGraph(Integer(5))
        >>> G.add_arc_label(Integer(0),Integer(1),Integer(0))
        >>> G.add_arc_label(Integer(0),Integer(1),Integer(1))
        >>> G.add_arc_label(Integer(0),Integer(1),Integer(2))
        >>> G.add_arc_label(Integer(0),Integer(1),Integer(3))
        >>> G.del_all_arcs(Integer(0),Integer(1))
        >>> G.has_arc(Integer(0),Integer(1))
        False
        >>> G.arc_label(Integer(0),Integer(1))
        0
        >>> G.del_all_arcs(Integer(0),Integer(1))

        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> G = DenseGraph(Integer(5))
        >>> G.add_arc(Integer(0), Integer(1))
        >>> G.has_arc(Integer(0), Integer(1))
        True
        >>> G.del_all_arcs(Integer(0), Integer(1))
        >>> G.has_arc(Integer(0), Integer(1))
        False

  del_arc_label(u, v, l)

    Delete an arc `(u, v)` with label `l`.

    INPUT:

    - `u`, `v` – nonnegative integers; must be in self

    - `l` – positive integer label, or zero for no label

    EXAMPLES:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: G = SparseGraph(5)
        sage: G.add_arc_label(0,1,0)
        sage: G.add_arc_label(0,1,1)
        sage: G.add_arc_label(0,1,2)
        sage: G.add_arc_label(0,1,2)
        sage: G.add_arc_label(0,1,3)
        sage: G.del_arc_label(0,1,2)
        sage: G.all_arcs(0,1)
        [0, 3, 2, 1]
        sage: G.del_arc_label(0,1,0)
        sage: G.all_arcs(0,1)
        [3, 2, 1]

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> G = SparseGraph(Integer(5))
        >>> G.add_arc_label(Integer(0),Integer(1),Integer(0))
        >>> G.add_arc_label(Integer(0),Integer(1),Integer(1))
        >>> G.add_arc_label(Integer(0),Integer(1),Integer(2))
        >>> G.add_arc_label(Integer(0),Integer(1),Integer(2))
        >>> G.add_arc_label(Integer(0),Integer(1),Integer(3))
        >>> G.del_arc_label(Integer(0),Integer(1),Integer(2))
        >>> G.all_arcs(Integer(0),Integer(1))
        [0, 3, 2, 1]
        >>> G.del_arc_label(Integer(0),Integer(1),Integer(0))
        >>> G.all_arcs(Integer(0),Integer(1))
        [3, 2, 1]

  del_vertex(v)

    Delete the vertex \(v\), along with all edges incident to it.

    If \(v\) is not in `self`, fails silently.

    INPUT:

    - `v` – nonnegative integer representing a vertex

    See also

    - `del_vertex_unsafe` – delete a vertex from a graph. This method is potentially unsafe. Use `del_vertex()` instead

    EXAMPLES:

    Deleting vertices of sparse graphs:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: G = SparseGraph(3)
        sage: G.add_arc(0, 1)
        sage: G.add_arc(0, 2)
        sage: G.add_arc(1, 2)
        sage: G.add_arc(2, 0)
        sage: G.del_vertex(2)
        sage: for i in range(2):
        ....:     for j in range(2):
        ....:         if G.has_arc(i, j):
        ....:             print("{} {}".format(i,j))
        0 1
        sage: G = SparseGraph(3)
        sage: G.add_arc(0, 1)
        sage: G.add_arc(0, 2)
        sage: G.add_arc(1, 2)
        sage: G.add_arc(2, 0)
        sage: G.del_vertex(1)
        sage: for i in range(3):
        ....:     for j in range(3):
        ....:         if G.has_arc(i, j):
        ....:             print("{} {}".format(i,j))
        0 2
        2 0

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> G = SparseGraph(Integer(3))
        >>> G.add_arc(Integer(0), Integer(1))
        >>> G.add_arc(Integer(0), Integer(2))
        >>> G.add_arc(Integer(1), Integer(2))
        >>> G.add_arc(Integer(2), Integer(0))
        >>> G.del_vertex(Integer(2))
        >>> for i in range(Integer(2)):
        ...     for j in range(Integer(2)):
        ...         if G.has_arc(i, j):
        ...             print("{} {}".format(i,j))
        0 1
        >>> G = SparseGraph(Integer(3))
        >>> G.add_arc(Integer(0), Integer(1))
        >>> G.add_arc(Integer(0), Integer(2))
        >>> G.add_arc(Integer(1), Integer(2))
        >>> G.add_arc(Integer(2), Integer(0))
        >>> G.del_vertex(Integer(1))
        >>> for i in range(Integer(3)):
        ...     for j in range(Integer(3)):
        ...         if G.has_arc(i, j):
        ...             print("{} {}".format(i,j))
        0 2
        2 0

    Deleting vertices of dense graphs:

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: G = DenseGraph(4)
        sage: G.add_arc(0, 1); G.add_arc(0, 2)
        sage: G.add_arc(3, 1); G.add_arc(3, 2)
        sage: G.add_arc(1, 2)
        sage: G.verts()
        [0, 1, 2, 3]
        sage: G.del_vertex(3); G.verts()
        [0, 1, 2]
        sage: for i in range(3):
        ....:     for j in range(3):
        ....:         if G.has_arc(i, j):
        ....:             print("{} {}".format(i,j))
        0 1
        0 2
        1 2

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> G = DenseGraph(Integer(4))
        >>> G.add_arc(Integer(0), Integer(1)); G.add_arc(Integer(0), Integer(2))
        >>> G.add_arc(Integer(3), Integer(1)); G.add_arc(Integer(3), Integer(2))
        >>> G.add_arc(Integer(1), Integer(2))
        >>> G.verts()
        [0, 1, 2, 3]
        >>> G.del_vertex(Integer(3)); G.verts()
        [0, 1, 2]
        >>> for i in range(Integer(3)):
        ...     for j in range(Integer(3)):
        ...         if G.has_arc(i, j):
        ...             print("{} {}".format(i,j))
        0 1
        0 2
        1 2

    If the vertex to be deleted is not in this graph, then fail silently:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: G = SparseGraph(3)
        sage: G.verts()
        [0, 1, 2]
        sage: G.has_vertex(3)
        False
        sage: G.del_vertex(3)
        sage: G.verts()
        [0, 1, 2]

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> G = SparseGraph(Integer(3))
        >>> G.verts()
        [0, 1, 2]
        >>> G.has_vertex(Integer(3))
        False
        >>> G.del_vertex(Integer(3))
        >>> G.verts()
        [0, 1, 2]

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: G = DenseGraph(5)
        sage: G.verts()
        [0, 1, 2, 3, 4]
        sage: G.has_vertex(6)
        False
        sage: G.del_vertex(6)
        sage: G.verts()
        [0, 1, 2, 3, 4]

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> G = DenseGraph(Integer(5))
        >>> G.verts()
        [0, 1, 2, 3, 4]
        >>> G.has_vertex(Integer(6))
        False
        >>> G.del_vertex(Integer(6))
        >>> G.verts()
        [0, 1, 2, 3, 4]

  has_arc(u, v)

    Check if the arc `(u, v)` is in this graph.

    INPUT:

    - `u` – integer; the tail of an arc

    - `v` – integer; the head of an arc

    OUTPUT:

    - Print a `Not Implemented!` message. This method is not implemented at the `CGraph` level. A child class should provide a suitable implementation.

    EXAMPLES:

    On the `CGraph` this always returns `False`:

    Sage

        sage: from sage.graphs.base.c_graph import CGraph
        sage: G = CGraph()
        sage: G.has_arc(0, 1)
        False

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.c_graph import CGraph
        >>> G = CGraph()
        >>> G.has_arc(Integer(0), Integer(1))
        False

    It works once `has_arc_unsafe` is implemented:

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: G = DenseGraph(5)
        sage: G.add_arc(0, 1)
        sage: G.has_arc(1, 0)
        False
        sage: G.has_arc(0, 1)
        True

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: G = SparseGraph(5)
        sage: G.add_arc_label(0,1)
        sage: G.has_arc(1,0)
        False
        sage: G.has_arc(0,1)
        True

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> G = DenseGraph(Integer(5))
        >>> G.add_arc(Integer(0), Integer(1))
        >>> G.has_arc(Integer(1), Integer(0))
        False
        >>> G.has_arc(Integer(0), Integer(1))
        True

        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> G = SparseGraph(Integer(5))
        >>> G.add_arc_label(Integer(0),Integer(1))
        >>> G.has_arc(Integer(1),Integer(0))
        False
        >>> G.has_arc(Integer(0),Integer(1))
        True

  has_arc_label(u, v, l)

    Indicates whether there is an arc `(u, v)` with label `l`.

    INPUT:

    - `u`, `v` – nonnegative integers; must be in self

    - `l` – positive integer label, or zero for no label

    EXAMPLES:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: G = SparseGraph(5)
        sage: G.add_arc_label(0,1,0)
        sage: G.add_arc_label(0,1,1)
        sage: G.add_arc_label(0,1,2)
        sage: G.add_arc_label(0,1,2)
        sage: G.has_arc_label(0,1,1)
        True
        sage: G.has_arc_label(0,1,2)
        True
        sage: G.has_arc_label(0,1,3)
        False

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> G = SparseGraph(Integer(5))
        >>> G.add_arc_label(Integer(0),Integer(1),Integer(0))
        >>> G.add_arc_label(Integer(0),Integer(1),Integer(1))
        >>> G.add_arc_label(Integer(0),Integer(1),Integer(2))
        >>> G.add_arc_label(Integer(0),Integer(1),Integer(2))
        >>> G.has_arc_label(Integer(0),Integer(1),Integer(1))
        True
        >>> G.has_arc_label(Integer(0),Integer(1),Integer(2))
        True
        >>> G.has_arc_label(Integer(0),Integer(1),Integer(3))
        False

  has_vertex(n)

    Determine whether the vertex \(n\) is in `self`.

    This method is different from `check_vertex()`. The current method returns a boolean to signify whether or not \(n\) is a vertex of this graph. On the other hand, `check_vertex()` raises an error if \(n\) is not a vertex of this graph.

    INPUT:

    - `n` – nonnegative integer representing a vertex

    OUTPUT: `True` if \(n\) is a vertex of this graph; `False` otherwise

    See also

    - `check_vertex()` – raise an error if this graph does not contain a specific vertex.

    EXAMPLES:

    Upon initialization, a `SparseGraph` or `DenseGraph` has the first `nverts` vertices:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: S = SparseGraph(nverts=10, expected_degree=3, extra_vertices=10)
        sage: S.has_vertex(6)
        True
        sage: S.has_vertex(12)
        False
        sage: S.has_vertex(24)
        False
        sage: S.has_vertex(-19)
        False

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> S = SparseGraph(nverts=Integer(10), expected_degree=Integer(3), extra_vertices=Integer(10))
        >>> S.has_vertex(Integer(6))
        True
        >>> S.has_vertex(Integer(12))
        False
        >>> S.has_vertex(Integer(24))
        False
        >>> S.has_vertex(-Integer(19))
        False

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: D = DenseGraph(nverts=10, extra_vertices=10)
        sage: D.has_vertex(6)
        True
        sage: D.has_vertex(12)
        False
        sage: D.has_vertex(24)
        False
        sage: D.has_vertex(-19)
        False

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> D = DenseGraph(nverts=Integer(10), extra_vertices=Integer(10))
        >>> D.has_vertex(Integer(6))
        True
        >>> D.has_vertex(Integer(12))
        False
        >>> D.has_vertex(Integer(24))
        False
        >>> D.has_vertex(-Integer(19))
        False

  in_neighbors(v)

    Return the list of in-neighbors of the vertex `v`.

    INPUT:

    - `v` – integer representing a vertex of this graph

    OUTPUT:

    - Raise `NotImplementedError`. This method is not implemented at the `CGraph` level. A child class should provide a suitable implementation.

    Note

    Due to the implementation of SparseGraph, this method is much more expensive than out_neighbors_unsafe for SparseGraph’s.

    EXAMPLES:

    On the `CGraph` level, this always produces an error, as there are no vertices:

    Sage

        sage: from sage.graphs.base.c_graph import CGraph
        sage: G = CGraph()
        sage: G.in_neighbors(0)
        Traceback (most recent call last):
        ...
        LookupError: vertex (0) is not a vertex of the graph

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.c_graph import CGraph
        >>> G = CGraph()
        >>> G.in_neighbors(Integer(0))
        Traceback (most recent call last):
        ...
        LookupError: vertex (0) is not a vertex of the graph

    It works, once there are vertices and `out_neighbors_unsafe()` is implemented:

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: G = DenseGraph(5)
        sage: G.add_arc(0, 1)
        sage: G.add_arc(3, 1)
        sage: G.add_arc(1, 3)
        sage: G.in_neighbors(1)
        [0, 3]
        sage: G.in_neighbors(3)
        [1]

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: G = SparseGraph(5)
        sage: G.add_arc(0,1)
        sage: G.add_arc(3,1)
        sage: G.add_arc(1,3)
        sage: G.in_neighbors(1)
        [0, 3]
        sage: G.in_neighbors(3)
        [1]

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> G = DenseGraph(Integer(5))
        >>> G.add_arc(Integer(0), Integer(1))
        >>> G.add_arc(Integer(3), Integer(1))
        >>> G.add_arc(Integer(1), Integer(3))
        >>> G.in_neighbors(Integer(1))
        [0, 3]
        >>> G.in_neighbors(Integer(3))
        [1]

        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> G = SparseGraph(Integer(5))
        >>> G.add_arc(Integer(0),Integer(1))
        >>> G.add_arc(Integer(3),Integer(1))
        >>> G.add_arc(Integer(1),Integer(3))
        >>> G.in_neighbors(Integer(1))
        [0, 3]
        >>> G.in_neighbors(Integer(3))
        [1]

  out_neighbors(u)

    Return the list of out-neighbors of the vertex `u`.

    INPUT:

    - `u` – integer representing a vertex of this graph

    EXAMPLES:

    On the `CGraph` level, this always produces an error, as there are no vertices:

    Sage

        sage: from sage.graphs.base.c_graph import CGraph
        sage: G = CGraph()
        sage: G.out_neighbors(0)
        Traceback (most recent call last):
        ...
        LookupError: vertex (0) is not a vertex of the graph

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.c_graph import CGraph
        >>> G = CGraph()
        >>> G.out_neighbors(Integer(0))
        Traceback (most recent call last):
        ...
        LookupError: vertex (0) is not a vertex of the graph

    It works, once there are vertices and `out_neighbors_unsafe()` is implemented:

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: G = DenseGraph(5)
        sage: G.add_arc(0, 1)
        sage: G.add_arc(1, 2)
        sage: G.add_arc(1, 3)
        sage: G.out_neighbors(0)
        [1]
        sage: G.out_neighbors(1)
        [2, 3]

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: G = SparseGraph(5)
        sage: G.add_arc(0,1)
        sage: G.add_arc(1,2)
        sage: G.add_arc(1,3)
        sage: G.out_neighbors(0)
        [1]
        sage: G.out_neighbors(1)
        [2, 3]

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> G = DenseGraph(Integer(5))
        >>> G.add_arc(Integer(0), Integer(1))
        >>> G.add_arc(Integer(1), Integer(2))
        >>> G.add_arc(Integer(1), Integer(3))
        >>> G.out_neighbors(Integer(0))
        [1]
        >>> G.out_neighbors(Integer(1))
        [2, 3]

        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> G = SparseGraph(Integer(5))
        >>> G.add_arc(Integer(0),Integer(1))
        >>> G.add_arc(Integer(1),Integer(2))
        >>> G.add_arc(Integer(1),Integer(3))
        >>> G.out_neighbors(Integer(0))
        [1]
        >>> G.out_neighbors(Integer(1))
        [2, 3]

  realloc(total)

    Reallocate the number of vertices to use, without actually adding any.

    INPUT:

    - `total` – integer; the total size to make the array of vertices

    OUTPUT:

    - Raise a `NotImplementedError`. This method is not implemented in this base class. A child class should provide a suitable implementation.

    See also

    - `realloc` – a `realloc` implementation for sparse graphs.

    - `realloc` – a `realloc` implementation for dense graphs.

    EXAMPLES:

    First, note that `realloc()` is implemented for `SparseGraph` and `DenseGraph` differently, and is not implemented at the `CGraph` level:

    Sage

        sage: from sage.graphs.base.c_graph import CGraph
        sage: G = CGraph()
        sage: G.realloc(20)
        Traceback (most recent call last):
        ...
        NotImplementedError

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.c_graph import CGraph
        >>> G = CGraph()
        >>> G.realloc(Integer(20))
        Traceback (most recent call last):
        ...
        NotImplementedError

    The `realloc` implementation for sparse graphs:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: S = SparseGraph(nverts=4, extra_vertices=4)
        sage: S.current_allocation()
        8
        sage: S.add_vertex(6)
        6
        sage: S.current_allocation()
        8
        sage: S.add_vertex(10)
        10
        sage: S.current_allocation()
        16
        sage: S.add_vertex(40)
        Traceback (most recent call last):
        ...
        RuntimeError: requested vertex is past twice the allocated range: use realloc
        sage: S.realloc(50)
        sage: S.add_vertex(40)
        40
        sage: S.current_allocation()
        50
        sage: S.realloc(30)
        -1
        sage: S.current_allocation()
        50
        sage: S.del_vertex(40)
        sage: S.realloc(30)
        sage: S.current_allocation()
        30

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> S = SparseGraph(nverts=Integer(4), extra_vertices=Integer(4))
        >>> S.current_allocation()
        8
        >>> S.add_vertex(Integer(6))
        6
        >>> S.current_allocation()
        8
        >>> S.add_vertex(Integer(10))
        10
        >>> S.current_allocation()
        16
        >>> S.add_vertex(Integer(40))
        Traceback (most recent call last):
        ...
        RuntimeError: requested vertex is past twice the allocated range: use realloc
        >>> S.realloc(Integer(50))
        >>> S.add_vertex(Integer(40))
        40
        >>> S.current_allocation()
        50
        >>> S.realloc(Integer(30))
        -1
        >>> S.current_allocation()
        50
        >>> S.del_vertex(Integer(40))
        >>> S.realloc(Integer(30))
        >>> S.current_allocation()
        30

    The `realloc` implementation for dense graphs:

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: D = DenseGraph(nverts=4, extra_vertices=4)
        sage: D.current_allocation()
        8
        sage: D.add_vertex(6)
        6
        sage: D.current_allocation()
        8
        sage: D.add_vertex(10)
        10
        sage: D.current_allocation()
        16
        sage: D.add_vertex(40)
        Traceback (most recent call last):
        ...
        RuntimeError: requested vertex is past twice the allocated range: use realloc
        sage: D.realloc(50)
        sage: D.add_vertex(40)
        40
        sage: D.current_allocation()
        50
        sage: D.realloc(30)
        -1
        sage: D.current_allocation()
        50
        sage: D.del_vertex(40)
        sage: D.realloc(30)
        sage: D.current_allocation()
        30

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> D = DenseGraph(nverts=Integer(4), extra_vertices=Integer(4))
        >>> D.current_allocation()
        8
        >>> D.add_vertex(Integer(6))
        6
        >>> D.current_allocation()
        8
        >>> D.add_vertex(Integer(10))
        10
        >>> D.current_allocation()
        16
        >>> D.add_vertex(Integer(40))
        Traceback (most recent call last):
        ...
        RuntimeError: requested vertex is past twice the allocated range: use realloc
        >>> D.realloc(Integer(50))
        >>> D.add_vertex(Integer(40))
        40
        >>> D.current_allocation()
        50
        >>> D.realloc(Integer(30))
        -1
        >>> D.current_allocation()
        50
        >>> D.del_vertex(Integer(40))
        >>> D.realloc(Integer(30))
        >>> D.current_allocation()
        30

  verts()

    Return a list of the vertices in `self`.

    EXAMPLES:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraph
        sage: S = SparseGraph(nverts=4, extra_vertices=4)
        sage: S.verts()
        [0, 1, 2, 3]
        sage: S.add_vertices([3,5,7,9])
        sage: S.verts()
        [0, 1, 2, 3, 5, 7, 9]
        sage: S.realloc(20)
        sage: S.verts()
        [0, 1, 2, 3, 5, 7, 9]

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraph
        >>> S = SparseGraph(nverts=Integer(4), extra_vertices=Integer(4))
        >>> S.verts()
        [0, 1, 2, 3]
        >>> S.add_vertices([Integer(3),Integer(5),Integer(7),Integer(9)])
        >>> S.verts()
        [0, 1, 2, 3, 5, 7, 9]
        >>> S.realloc(Integer(20))
        >>> S.verts()
        [0, 1, 2, 3, 5, 7, 9]

    Sage

        sage: from sage.graphs.base.dense_graph import DenseGraph
        sage: G = DenseGraph(3, extra_vertices=2)
        sage: G.verts()
        [0, 1, 2]
        sage: G.del_vertex(0)
        sage: G.verts()
        [1, 2]

    [Python]

        >>> from sage.all import *
        >>> from sage.graphs.base.dense_graph import DenseGraph
        >>> G = DenseGraph(Integer(3), extra_vertices=Integer(2))
        >>> G.verts()
        [0, 1, 2]
        >>> G.del_vertex(Integer(0))
        >>> G.verts()
        [1, 2]

class sage.graphs.base.c_graph.CGraphBackend

  Bases: `GenericGraphBackend`

  Base class for sparse and dense graph backends.

  Sage

      sage: from sage.graphs.base.c_graph import CGraphBackend

  Python

      >>> from sage.all import *
      >>> from sage.graphs.base.c_graph import CGraphBackend

  This class is extended by `SparseGraphBackend` and `DenseGraphBackend`, which are fully functional backends. This class is mainly just for vertex functions, which are the same for both. A `CGraphBackend` will not work on its own:

  Sage

      sage: from sage.graphs.base.c_graph import CGraphBackend
      sage: CGB = CGraphBackend()
      sage: CGB.degree(0, True)
      Traceback (most recent call last):
      ...
      NotImplementedError: a derived class must return ``self._cg``

  [Python]

      >>> from sage.all import *
      >>> from sage.graphs.base.c_graph import CGraphBackend
      >>> CGB = CGraphBackend()
      >>> CGB.degree(Integer(0), True)
      Traceback (most recent call last):
      ...
      NotImplementedError: a derived class must return ``self._cg``

  The appropriate way to use these backends is via Sage graphs:

  Sage

      sage: G = Graph(30)
      sage: G.add_edges([(0,1), (0,3), (4,5), (9, 23)])
      sage: G.edges(sort=True, labels=False)
      [(0, 1), (0, 3), (4, 5), (9, 23)]

  Python

      >>> from sage.all import *
      >>> G = Graph(Integer(30))
      >>> G.add_edges([(Integer(0),Integer(1)), (Integer(0),Integer(3)), (Integer(4),Integer(5)), (Integer(9), Integer(23))])
      >>> G.edges(sort=True, labels=False)
      [(0, 1), (0, 3), (4, 5), (9, 23)]

  This class handles the labels of vertices and edges. For vertices it uses two dictionaries `vertex_labels` and `vertex_ints`. They are just opposite of each other: `vertex_ints` makes a translation from label to integers (that are internally used) and `vertex_labels` make the translation from internally used integers to actual labels. This class tries hard to avoid translation if possible. This will work only if the graph is built on integers from \(0\) to \(n-1\) and the vertices are basically added in increasing order.

  See also

  - `SparseGraphBackend` – backend for sparse graphs.

  - `DenseGraphBackend` – backend for dense graphs.

  add_edge(u, v, l, directed)

    Add the edge `(u,v)` to `self`.

    INPUT:

    - `u`, `v` – the vertices of the edge

    - `l` – the edge label

    - `directed` – if `False`, also add `(v,u)`

    Note

    The input `l` is ignored if the backend does not support labels.

    EXAMPLES:

    Sage

        sage: D = sage.graphs.base.sparse_graph.SparseGraphBackend(9)
        sage: D.add_edge(0,1,None,False)
        sage: list(D.iterator_edges(range(9), True))
        [(0, 1, None)]

    Python

        >>> from sage.all import *
        >>> D = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(9))
        >>> D.add_edge(Integer(0),Integer(1),None,False)
        >>> list(D.iterator_edges(range(Integer(9)), True))
        [(0, 1, None)]

    Sage

        sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)
        sage: D.add_edge(0, 1, None, False)
        sage: list(D.iterator_edges(range(9), True))
        [(0, 1, None)]

    [Python]

        >>> from sage.all import *
        >>> D = sage.graphs.base.dense_graph.DenseGraphBackend(Integer(9))
        >>> D.add_edge(Integer(0), Integer(1), None, False)
        >>> list(D.iterator_edges(range(Integer(9)), True))
        [(0, 1, None)]

  add_edges(edges, directed, remove_loops=False)

    Add edges from a list.

    INPUT:

    - `edges` – the edges to be added; can either be of the form `(u,v)` or `(u,v,l)`

    - `directed` – if `False`, add `(v,u)` as well as `(u,v)`

    - `remove_loops` – if `True`, remove loops

    EXAMPLES:

    Sage

        sage: D = sage.graphs.base.sparse_graph.SparseGraphBackend(9)
        sage: D.add_edges([(0,1), (2,3), (4,5), (5,6)], False)
        sage: list(D.iterator_edges(range(9), True))
        [(0, 1, None),
         (2, 3, None),
         (4, 5, None),
         (5, 6, None)]

    Python

        >>> from sage.all import *
        >>> D = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(9))
        >>> D.add_edges([(Integer(0),Integer(1)), (Integer(2),Integer(3)), (Integer(4),Integer(5)), (Integer(5),Integer(6))], False)
        >>> list(D.iterator_edges(range(Integer(9)), True))
        [(0, 1, None),
         (2, 3, None),
         (4, 5, None),
         (5, 6, None)]

  add_vertex(name)

    Add a vertex to `self`.

    INPUT:

    - `name` – the vertex to be added (must be hashable). If `None`, a new name is created

    OUTPUT:

    - If `name = None`, the new vertex name is returned. `None` otherwise.

    See also

    - `add_vertices()` – add a bunch of vertices of this graph

    - `has_vertex()` – returns whether or not this graph has a specific vertex

    EXAMPLES:

    Sage

        sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)
        sage: D.add_vertex(10)
        sage: D.add_vertex([])
        Traceback (most recent call last):
        ...
        TypeError: ...unhashable type: 'list'...

    Python

        >>> from sage.all import *
        >>> D = sage.graphs.base.dense_graph.DenseGraphBackend(Integer(9))
        >>> D.add_vertex(Integer(10))
        >>> D.add_vertex([])
        Traceback (most recent call last):
        ...
        TypeError: ...unhashable type: 'list'...

    Sage

        sage: S = sage.graphs.base.sparse_graph.SparseGraphBackend(9)
        sage: S.add_vertex(10)
        sage: S.add_vertex([])
        Traceback (most recent call last):
        ...
        TypeError: ...unhashable type: 'list'...

    [Python]

        >>> from sage.all import *
        >>> S = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(9))
        >>> S.add_vertex(Integer(10))
        >>> S.add_vertex([])
        Traceback (most recent call last):
        ...
        TypeError: ...unhashable type: 'list'...

  add_vertices(vertices)

    Add vertices to `self`.

    INPUT:

    - `vertices` – iterator of vertex labels; a new name is created, used and returned in the output list for all `None` values in `vertices`

    OUTPUT:

    Generated names of new vertices if there is at least one `None` value present in `vertices`. `None` otherwise.

    See also

    - `add_vertex()` – add a vertex to this graph

    EXAMPLES:

    Sage

        sage: D = sage.graphs.base.sparse_graph.SparseGraphBackend(1)
        sage: D.add_vertices([1, 2, 3])
        sage: D.add_vertices([None] * 4)
        [4, 5, 6, 7]

    Python

        >>> from sage.all import *
        >>> D = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(1))
        >>> D.add_vertices([Integer(1), Integer(2), Integer(3)])
        >>> D.add_vertices([None] * Integer(4))
        [4, 5, 6, 7]

    Sage

        sage: G = sage.graphs.base.sparse_graph.SparseGraphBackend(0)
        sage: G.add_vertices([0, 1])
        sage: list(G.iterator_verts(None))
        [0, 1]
        sage: list(G.iterator_edges([0, 1], True))
        []

    [Python]

        >>> from sage.all import *
        >>> G = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(0))
        >>> G.add_vertices([Integer(0), Integer(1)])
        >>> list(G.iterator_verts(None))
        [0, 1]
        >>> list(G.iterator_edges([Integer(0), Integer(1)], True))
        []

    Sage

        sage: import sage.graphs.base.dense_graph
        sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)
        sage: D.add_vertices([10, 11, 12])

    Python

        >>> from sage.all import *
        >>> import sage.graphs.base.dense_graph
        >>> D = sage.graphs.base.dense_graph.DenseGraphBackend(Integer(9))
        >>> D.add_vertices([Integer(10), Integer(11), Integer(12)])

  bidirectional_dijkstra(x, y, weight_function=None, distance_flag=False)

    Return the shortest path or distance from `x` to `y` using a bidirectional version of Dijkstra’s algorithm.

    INPUT:

    - `x` – the starting vertex in the shortest path from `x` to `y`

    - `y` – the end vertex in the shortest path from `x` to `y`

    - `weight_function` – function (default: `None`); a function that inputs an edge `(u, v, l)` and outputs its weight. If `None`, we use the edge label `l` as a weight, if `l` is not `None`, else `1` as a weight.

    - `distance_flag` – boolean (default: `False`); when set to `True`, the shortest path distance from `x` to `y` is returned instead of the path.

    OUTPUT:

    - A list of vertices in the shortest path from `x` to `y` or distance from `x` to `y` is returned depending upon the value of parameter `distance_flag`

    EXAMPLES:

    Sage

        sage: G = Graph(graphs.PetersenGraph())
        sage: for (u, v) in G.edges(sort=True, labels=None):
        ....:     G.set_edge_label(u, v, 1)
        sage: G.shortest_path(0, 1, by_weight=True)
        [0, 1]
        sage: G.shortest_path_length(0, 1, by_weight=True)
        1
        sage: G = DiGraph([(1, 2, {'weight':1}), (1, 3, {'weight':5}), (2, 3, {'weight':1})])
        sage: G.shortest_path(1, 3, weight_function=lambda e:e[2]['weight'])
        [1, 2, 3]
        sage: G.shortest_path_length(1, 3, weight_function=lambda e:e[2]['weight'])
        2

    Python

        >>> from sage.all import *
        >>> G = Graph(graphs.PetersenGraph())
        >>> for (u, v) in G.edges(sort=True, labels=None):
        ...     G.set_edge_label(u, v, Integer(1))
        >>> G.shortest_path(Integer(0), Integer(1), by_weight=True)
        [0, 1]
        >>> G.shortest_path_length(Integer(0), Integer(1), by_weight=True)
        1
        >>> G = DiGraph([(Integer(1), Integer(2), {'weight':Integer(1)}), (Integer(1), Integer(3), {'weight':Integer(5)}), (Integer(2), Integer(3), {'weight':Integer(1)})])
        >>> G.shortest_path(Integer(1), Integer(3), weight_function=lambda e:e[Integer(2)]['weight'])
        [1, 2, 3]
        >>> G.shortest_path_length(Integer(1), Integer(3), weight_function=lambda e:e[Integer(2)]['weight'])
        2

  bidirectional_dijkstra_special(x, y, weight_function=None, exclude_vertices=None, exclude_edges=None, include_vertices=None, distance_flag=False, reduced_weight=None)

    Return the shortest path or distance from `x` to `y` using a bidirectional version of Dijkstra’s algorithm.

    This method is an extension of `bidirectional_dijkstra()` method enabling to exclude vertices and/or edges from the search for the shortest path between `x` and `y`.

    This method also has `include_vertices` option enabling to include the vertices which will be used to search for the shortest path between `x` and `y`.

    INPUT:

    - `x` – the starting vertex in the shortest path from `x` to `y`

    - `y` – the end vertex in the shortest path from `x` to `y`

    - `exclude_vertices` – iterable container (default: `None`); iterable of vertices to exclude from the graph while calculating the shortest path from `x` to `y`

    - `exclude_edges` – iterable container (default: `None`); iterable of edges to exclude from the graph while calculating the shortest path from `x` to `y`

    - `include_vertices` – iterable container (default: `None`); iterable of vertices to consider in the graph while calculating the shortest path from `x` to `y`

    - `weight_function` – function (default: `None`); a function that inputs an edge `(u, v, l)` and outputs its weight. If `None`, we use the edge label `l` as a weight, if `l` is not `None`, else `1` as a weight.

    - `distance_flag` – boolean (default: `False`); when set to `True`, the shortest path distance from `x` to `y` is returned instead of the path.

    - `reduced_weight` – dictionary (default: `None`); a dictionary that takes as input an edge `(u, v)` and outputs its reduced weight

    OUTPUT:

    - A list of vertices in the shortest path from `x` to `y` or distance from `x` to `y` is returned depending upon the value of parameter `distance_flag`

    EXAMPLES:

    Sage

        sage: G = Graph([(1, 2, 20), (2, 3, 10), (3, 4, 30), (1, 5, 20), (5, 6, 10), (6, 4, 50), (4, 7, 5)])
        sage: G._backend.bidirectional_dijkstra_special(1, 4, weight_function=lambda e:e[2])
        [1, 2, 3, 4]
        sage: G._backend.bidirectional_dijkstra_special(1, 4, weight_function=lambda e:e[2], exclude_vertices=[2], exclude_edges=[(3, 4)])
        [1, 5, 6, 4]
        sage: G._backend.bidirectional_dijkstra_special(1, 4, weight_function=lambda e:e[2], exclude_vertices=[2, 7])
        [1, 5, 6, 4]
        sage: G._backend.bidirectional_dijkstra_special(1, 4, weight_function=lambda e:e[2],  exclude_edges=[(5, 6)])
        [1, 2, 3, 4]
        sage: G._backend.bidirectional_dijkstra_special(1, 4, weight_function=lambda e:e[2],  include_vertices=[1, 5, 6, 4])
        [1, 5, 6, 4]

    Python

        >>> from sage.all import *
        >>> G = Graph([(Integer(1), Integer(2), Integer(20)), (Integer(2), Integer(3), Integer(10)), (Integer(3), Integer(4), Integer(30)), (Integer(1), Integer(5), Integer(20)), (Integer(5), Integer(6), Integer(10)), (Integer(6), Integer(4), Integer(50)), (Integer(4), Integer(7), Integer(5))])
        >>> G._backend.bidirectional_dijkstra_special(Integer(1), Integer(4), weight_function=lambda e:e[Integer(2)])
        [1, 2, 3, 4]
        >>> G._backend.bidirectional_dijkstra_special(Integer(1), Integer(4), weight_function=lambda e:e[Integer(2)], exclude_vertices=[Integer(2)], exclude_edges=[(Integer(3), Integer(4))])
        [1, 5, 6, 4]
        >>> G._backend.bidirectional_dijkstra_special(Integer(1), Integer(4), weight_function=lambda e:e[Integer(2)], exclude_vertices=[Integer(2), Integer(7)])
        [1, 5, 6, 4]
        >>> G._backend.bidirectional_dijkstra_special(Integer(1), Integer(4), weight_function=lambda e:e[Integer(2)],  exclude_edges=[(Integer(5), Integer(6))])
        [1, 2, 3, 4]
        >>> G._backend.bidirectional_dijkstra_special(Integer(1), Integer(4), weight_function=lambda e:e[Integer(2)],  include_vertices=[Integer(1), Integer(5), Integer(6), Integer(4)])
        [1, 5, 6, 4]

  breadth_first_search(v, reverse=False, ignore_direction=False, report_distance=False, edges=False, forbidden_vertices=None)

    Return a breadth-first search from vertex `v`.

    INPUT:

    - `v` – a vertex from which to start the breadth-first search

    - `reverse` – boolean (default: `False`); this is only relevant to digraphs. If this is a digraph, consider the reversed graph in which the out-neighbors become the in-neighbors and vice versa.

    - `ignore_direction` – boolean (default: `False`); this is only relevant to digraphs. If this is a digraph, ignore all orientations and consider the graph as undirected.

    - `report_distance` – boolean (default: `False`); if `True`, reports pairs `(vertex, distance)` where `distance` is the distance from the `start` nodes. If `False` only the vertices are reported.

    - `edges` – boolean (default: `False`); whether to return the edges of the BFS tree in the order of visit or the vertices (default). Edges are directed in root to leaf orientation of the tree.

      Note that parameters `edges` and `report_distance` cannot be `True` simultaneously.

    - `forbidden_vertices` – list (default: `None`); set of vertices to avoid during the search. The start vertex `v` cannot be in this set.

    ALGORITHM:

    Below is a general template for breadth-first search.

    - Input: A directed or undirected graph \(G = (V, E)\) of order \(n > 0\). A vertex \(s\) from which to start the search. The vertices are numbered from 1 to \(n = |V|\), i.e. \(V = \{1, 2, \dots, n\}\).

    - Output: A list \(D\) of distances of all vertices from \(s\). A tree \(T\) rooted at \(s\).

    1. \(Q \leftarrow [s]\) # a queue of nodes to visit

    2. \(D \leftarrow [\infty, \infty, \dots, \infty]\) # \(n\) copies of \(\infty\)

    3. \(D[s] \leftarrow 0\)

    4. \(T \leftarrow [\,]\)

    5. while \(\text{length}(Q) > 0\) do

       1. \(v \leftarrow \text{dequeue}(Q)\)

       2. for each \(w \in \text{adj}(v)\) do # for digraphs, use out-neighbor set \(\text{oadj}(v)\)

          1. if \(D[w] = \infty\) then

             1. \(D[w] \leftarrow D[v] + 1\)

             2. \(\text{enqueue}(Q, w)\)

             3. \(\text{append}(T, vw)\)

    6. return \((D, T)\)

    See also

    - `breadth_first_search` – breadth-first search for generic graphs.

    - `depth_first_search` – depth-first search for generic graphs.

    - `depth_first_search()` – depth-first search for fast compiled graphs.

    EXAMPLES:

    Breadth-first search of the Petersen graph starting at vertex 0:

    Sage

        sage: G = Graph(graphs.PetersenGraph())
        sage: list(G.breadth_first_search(0))
        [0, 1, 4, 5, 2, 6, 3, 9, 7, 8]

    Python

        >>> from sage.all import *
        >>> G = Graph(graphs.PetersenGraph())
        >>> list(G.breadth_first_search(Integer(0)))
        [0, 1, 4, 5, 2, 6, 3, 9, 7, 8]

    Visiting European countries using breadth-first search:

    Sage

        sage: G = graphs.EuropeMap(continental=True)
        sage: list(G.breadth_first_search("Portugal"))
        ['Portugal', 'Spain', ..., 'Greece']

    [Python]

        >>> from sage.all import *
        >>> G = graphs.EuropeMap(continental=True)
        >>> list(G.breadth_first_search("Portugal"))
        ['Portugal', 'Spain', ..., 'Greece']

    Avoiding some countries:

    > sage: list(G.breadth_first_search(“Portugal”, ….: forbidden_vertices=[“Germany”,”Italy”])) [‘Portugal’, ‘Spain’, …, ‘Sweden’]

  c_graph()

    Return the `._cg` and `._cg_rev` attributes.

    Note

    The `._cg_rev` attribute has been removed and hence `None` is returned.

    EXAMPLES:

    Sage

        sage: cg,cg_rev = graphs.PetersenGraph()._backend.c_graph()
        sage: cg
        <sage.graphs.base.sparse_graph.SparseGraph object at ...>

    Python

        >>> from sage.all import *
        >>> cg,cg_rev = graphs.PetersenGraph()._backend.c_graph()
        >>> cg
        <sage.graphs.base.sparse_graph.SparseGraph object at ...>

  degree(v, directed)

    Return the degree of the vertex `v`.

    INPUT:

    - `v` – a vertex of the graph

    - `directed` – boolean; whether to take into account the orientation of this graph in counting the degree of `v`

    OUTPUT: the degree of vertex `v`

    EXAMPLES:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraphBackend
        sage: B = SparseGraphBackend(7)
        sage: B.degree(3, False)
        0

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraphBackend
        >>> B = SparseGraphBackend(Integer(7))
        >>> B.degree(Integer(3), False)
        0

  del_edge(u, v, l, directed)

    Delete edge `(u, v, l)`.

    INPUT:

    - `u`, `v` – the vertices of the edge

    - `l` – the edge label

    - `directed` – if `False`, also delete `(v, u, l)`

    Note

    The input `l` is ignored if the backend does not support labels.

    EXAMPLES:

    Sage

        sage: D = sage.graphs.base.sparse_graph.SparseGraphBackend(9)
        sage: D.add_edges([(0,1), (2,3), (4,5), (5,6)], False)
        sage: list(D.iterator_edges(range(9), True))
        [(0, 1, None),
         (2, 3, None),
         (4, 5, None),
         (5, 6, None)]
        sage: D.del_edge(0,1,None,True)
        sage: list(D.iterator_out_edges(range(9), True))
        [(1, 0, None),
         (2, 3, None),
         (3, 2, None),
         (4, 5, None),
         (5, 4, None),
         (5, 6, None),
         (6, 5, None)]

    Python

        >>> from sage.all import *
        >>> D = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(9))
        >>> D.add_edges([(Integer(0),Integer(1)), (Integer(2),Integer(3)), (Integer(4),Integer(5)), (Integer(5),Integer(6))], False)
        >>> list(D.iterator_edges(range(Integer(9)), True))
        [(0, 1, None),
         (2, 3, None),
         (4, 5, None),
         (5, 6, None)]
        >>> D.del_edge(Integer(0),Integer(1),None,True)
        >>> list(D.iterator_out_edges(range(Integer(9)), True))
        [(1, 0, None),
         (2, 3, None),
         (3, 2, None),
         (4, 5, None),
         (5, 4, None),
         (5, 6, None),
         (6, 5, None)]

    Sage

        sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)
        sage: D.add_edges([(0, 1), (2, 3), (4, 5), (5, 6)], False)
        sage: list(D.iterator_edges(range(9), True))
        [(0, 1, None),
         (2, 3, None),
         (4, 5, None),
         (5, 6, None)]
        sage: D.del_edge(0, 1, None, True)
        sage: list(D.iterator_out_edges(range(9), True))
        [(1, 0, None),
         (2, 3, None),
         (3, 2, None),
         (4, 5, None),
         (5, 4, None),
         (5, 6, None),
         (6, 5, None)]

    [Python]

        >>> from sage.all import *
        >>> D = sage.graphs.base.dense_graph.DenseGraphBackend(Integer(9))
        >>> D.add_edges([(Integer(0), Integer(1)), (Integer(2), Integer(3)), (Integer(4), Integer(5)), (Integer(5), Integer(6))], False)
        >>> list(D.iterator_edges(range(Integer(9)), True))
        [(0, 1, None),
         (2, 3, None),
         (4, 5, None),
         (5, 6, None)]
        >>> D.del_edge(Integer(0), Integer(1), None, True)
        >>> list(D.iterator_out_edges(range(Integer(9)), True))
        [(1, 0, None),
         (2, 3, None),
         (3, 2, None),
         (4, 5, None),
         (5, 4, None),
         (5, 6, None),
         (6, 5, None)]

  del_edges(edges, directed)

    Delete edges from a list.

    INPUT:

    - `edges` – the edges to be added; can either be of the form `(u,v)` or `(u,v,l)`

    - `directed` – if `False`, remove``(v,u)`` as well as `(u,v)`

    EXAMPLES:

    Sage

        sage: D = sage.graphs.base.sparse_graph.SparseGraphBackend(9)
        sage: D.add_edges([(0,1), (2,3), (4,5), (5,6)], False)
        sage: D.del_edges([(0,1), (2,3), (4,5), (5,6)], False)
        sage: list(D.iterator_edges(range(9), True))
        []

    Python

        >>> from sage.all import *
        >>> D = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(9))
        >>> D.add_edges([(Integer(0),Integer(1)), (Integer(2),Integer(3)), (Integer(4),Integer(5)), (Integer(5),Integer(6))], False)
        >>> D.del_edges([(Integer(0),Integer(1)), (Integer(2),Integer(3)), (Integer(4),Integer(5)), (Integer(5),Integer(6))], False)
        >>> list(D.iterator_edges(range(Integer(9)), True))
        []

  del_vertex(v)

    Delete a vertex in `self`, failing silently if the vertex is not in the graph.

    INPUT:

    - `v` – vertex to be deleted

    See also

    - `del_vertices()` – delete a bunch of vertices from this graph

    EXAMPLES:

    Sage

        sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)
        sage: D.del_vertex(0)
        sage: D.has_vertex(0)
        False

    Python

        >>> from sage.all import *
        >>> D = sage.graphs.base.dense_graph.DenseGraphBackend(Integer(9))
        >>> D.del_vertex(Integer(0))
        >>> D.has_vertex(Integer(0))
        False

    Sage

        sage: S = sage.graphs.base.sparse_graph.SparseGraphBackend(9)
        sage: S.del_vertex(0)
        sage: S.has_vertex(0)
        False

    [Python]

        >>> from sage.all import *
        >>> S = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(9))
        >>> S.del_vertex(Integer(0))
        >>> S.has_vertex(Integer(0))
        False

  del_vertices(vertices)

    Delete vertices from an iterable container.

    INPUT:

    - `vertices` – iterator of vertex labels

    OUTPUT: same as for `del_vertex()`

    See also

    - `del_vertex()` – delete a vertex of this graph

    EXAMPLES:

    Sage

        sage: import sage.graphs.base.dense_graph
        sage: D = sage.graphs.base.dense_graph.DenseGraphBackend(9)
        sage: D.del_vertices([7, 8])
        sage: D.has_vertex(7)
        False
        sage: D.has_vertex(6)
        True

    Python

        >>> from sage.all import *
        >>> import sage.graphs.base.dense_graph
        >>> D = sage.graphs.base.dense_graph.DenseGraphBackend(Integer(9))
        >>> D.del_vertices([Integer(7), Integer(8)])
        >>> D.has_vertex(Integer(7))
        False
        >>> D.has_vertex(Integer(6))
        True

    Sage

        sage: D = sage.graphs.base.sparse_graph.SparseGraphBackend(9)
        sage: D.del_vertices([1, 2, 3])
        sage: D.has_vertex(1)
        False
        sage: D.has_vertex(0)
        True

    [Python]

        >>> from sage.all import *
        >>> D = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(9))
        >>> D.del_vertices([Integer(1), Integer(2), Integer(3)])
        >>> D.has_vertex(Integer(1))
        False
        >>> D.has_vertex(Integer(0))
        True

  depth_first_search(v, reverse=False, ignore_direction=False, forbidden_vertices=None)

    Return a depth-first search from vertex `v`.

    INPUT:

    - `v` – a vertex from which to start the depth-first search

    - `reverse` – boolean (default: `False`); this is only relevant to digraphs. If this is a digraph, consider the reversed graph in which the out-neighbors become the in-neighbors and vice versa.

    - `ignore_direction` – boolean (default: `False`); this is only relevant to digraphs. If this is a digraph, ignore all orientations and consider the graph as undirected.

    - `forbidden_vertices` – list (default: `None`); set of vertices to avoid during the search. The start vertex `v` cannot be in this set.

    ALGORITHM:

    Below is a general template for depth-first search.

    - Input: A directed or undirected graph \(G = (V, E)\) of order \(n > 0\). A vertex \(s\) from which to start the search. The vertices are numbered from 1 to \(n = |V|\), i.e. \(V = \{1, 2, \dots, n\}\).

    - Output: A list \(D\) of distances of all vertices from \(s\). A tree \(T\) rooted at \(s\).

    1. \(S \leftarrow [s]\) # a stack of nodes to visit

    2. \(D \leftarrow [\infty, \infty, \dots, \infty]\) # \(n\) copies of \(\infty\)

    3. \(D[s] \leftarrow 0\)

    4. \(T \leftarrow [\,]\)

    5. while \(\text{length}(S) > 0\) do

       1. \(v \leftarrow \text{pop}(S)\)

       2. for each \(w \in \text{adj}(v)\) do # for digraphs, use out-neighbor set \(\text{oadj}(v)\)

          1. if \(D[w] = \infty\) then

             1. \(D[w] \leftarrow D[v] + 1\)

             2. \(\text{push}(S, w)\)

             3. \(\text{append}(T, vw)\)

    6. return \((D, T)\)

    See also

    - `breadth_first_search()` – breadth-first search for fast compiled graphs.

    - `breadth_first_search` – breadth-first search for generic graphs.

    - `depth_first_search` – depth-first search for generic graphs.

    EXAMPLES:

    Traversing the Petersen graph using depth-first search:

    Sage

        sage: G = graphs.PetersenGraph()
        sage: list(G.depth_first_search(0))
        [0, 5, 8, 6, 9, 7, 2, 3, 4, 1]

    Python

        >>> from sage.all import *
        >>> G = graphs.PetersenGraph()
        >>> list(G.depth_first_search(Integer(0)))
        [0, 5, 8, 6, 9, 7, 2, 3, 4, 1]

    Visiting German cities using depth-first search:

    Sage

        sage: G = Graph({"Mannheim": ["Frankfurt","Karlsruhe"],
        ....: "Frankfurt": ["Mannheim","Wurzburg","Kassel"],
        ....: "Kassel": ["Frankfurt","Munchen"],
        ....: "Munchen": ["Kassel","Nurnberg","Augsburg"],
        ....: "Augsburg": ["Munchen","Karlsruhe"],
        ....: "Karlsruhe": ["Mannheim","Augsburg"],
        ....: "Wurzburg": ["Frankfurt","Erfurt","Nurnberg"],
        ....: "Nurnberg": ["Wurzburg","Stuttgart","Munchen"],
        ....: "Stuttgart": ["Nurnberg"], "Erfurt": ["Wurzburg"]})
        sage: list(G.depth_first_search("Stuttgart"))
        ['Stuttgart', 'Nurnberg', ...]

    [Python]

        >>> from sage.all import *
        >>> G = Graph({"Mannheim": ["Frankfurt","Karlsruhe"],
        ... "Frankfurt": ["Mannheim","Wurzburg","Kassel"],
        ... "Kassel": ["Frankfurt","Munchen"],
        ... "Munchen": ["Kassel","Nurnberg","Augsburg"],
        ... "Augsburg": ["Munchen","Karlsruhe"],
        ... "Karlsruhe": ["Mannheim","Augsburg"],
        ... "Wurzburg": ["Frankfurt","Erfurt","Nurnberg"],
        ... "Nurnberg": ["Wurzburg","Stuttgart","Munchen"],
        ... "Stuttgart": ["Nurnberg"], "Erfurt": ["Wurzburg"]})
        >>> list(G.depth_first_search("Stuttgart"))
        ['Stuttgart', 'Nurnberg', ...]

    Avoiding some cities:

    > sage: list(G.depth_first_search(“Stuttgart”, ….: forbidden_vertices=[“Frankfurt”, “Munchen”])) [‘Stuttgart’, ‘Nurnberg’, ‘Wurzburg’, ‘Erfurt’]

  has_vertex(v)

    Check whether `v` is a vertex of `self`.

    INPUT:

    - `v` – any object

    OUTPUT: `True` if `v` is a vertex of this graph; `False` otherwise

    EXAMPLES:

    Sage

        sage: from sage.graphs.base.sparse_graph import SparseGraphBackend
        sage: B = SparseGraphBackend(7)
        sage: B.has_vertex(6)
        True
        sage: B.has_vertex(7)
        False

    Python

        >>> from sage.all import *
        >>> from sage.graphs.base.sparse_graph import SparseGraphBackend
        >>> B = SparseGraphBackend(Integer(7))
        >>> B.has_vertex(Integer(6))
        True
        >>> B.has_vertex(Integer(7))
        False

  in_degree(v)

    Return the in-degree of `v`.

    INPUT:

    - `v` – a vertex of the graph

    EXAMPLES:

    Sage

        sage: D = DiGraph( { 0: [1,2,3], 1: [0,2], 2: [3], 3: [4], 4: [0,5], 5: [1] } )
        sage: D.out_degree(1)
        2

    Python

        >>> from sage.all import *
        >>> D = DiGraph( { Integer(0): [Integer(1),Integer(2),Integer(3)], Integer(1): [Integer(0),Integer(2)], Integer(2): [Integer(3)], Integer(3): [Integer(4)], Integer(4): [Integer(0),Integer(5)], Integer(5): [Integer(1)] } )
        >>> D.out_degree(Integer(1))
        2

  is_connected(forbidden_vertices=None)

    Check whether the graph is connected.

    INPUT:

    - `forbidden_vertices` – list (default: `None`); set of vertices to avoid during the search

    EXAMPLES:

    Petersen’s graph is connected:

    Sage

        sage: DiGraph(graphs.PetersenGraph()).is_connected()
        True

    Python

        >>> from sage.all import *
        >>> DiGraph(graphs.PetersenGraph()).is_connected()
        True

    While the disjoint union of two of them is not:

    Sage

        sage: DiGraph(2*graphs.PetersenGraph()).is_connected()
        False

    [Python]

        >>> from sage.all import *
        >>> DiGraph(Integer(2)*graphs.PetersenGraph()).is_connected()
        False

    A graph with non-integer vertex labels:

    Sage

        sage: Graph(graphs.CubeGraph(3)).is_connected()
        True

    Python

        >>> from sage.all import *
        >>> Graph(graphs.CubeGraph(Integer(3))).is_connected()
        True

    A graph with forbidden vertices:

    Sage

        sage: G = graphs.PathGraph(5)
        sage: G._backend.is_connected()
        True
        sage: G._backend.is_connected(forbidden_vertices=[1])
        False
        sage: G._backend.is_connected(forbidden_vertices=[0, 1])
        True

    [Python]

        >>> from sage.all import *
        >>> G = graphs.PathGraph(Integer(5))
        >>> G._backend.is_connected()
        True
        >>> G._backend.is_connected(forbidden_vertices=[Integer(1)])
        False
        >>> G._backend.is_connected(forbidden_vertices=[Integer(0), Integer(1)])
        True

  is_directed_acyclic(certificate=False)

    Check whether the graph is both directed and acyclic (possibly with a certificate)

    INPUT:

    - `certificate` – boolean (default: `False`); whether to return a certificate

    OUTPUT:

    When `certificate=False`, returns a boolean value. When `certificate=True` :

    - If the graph is acyclic, returns a pair `(True, ordering)` where `ordering` is a list of the vertices such that `u` appears before `v` in `ordering` if `u, v` is an edge.

    - Else, returns a pair `(False, cycle)` where `cycle` is a list of vertices representing a circuit in the graph.

    ALGORITHM:

    We pick a vertex at random, think hard and find out that if we are to remove the vertex from the graph we must remove all of its out-neighbors in the first place. So we put all of its out-neighbours in a stack, and repeat the same procedure with the vertex on top of the stack (when a vertex on top of the stack has no out-neighbors, we remove it immediately). Of course, for each vertex we only add its outneighbors to the end of the stack once : if for some reason the previous algorithm leads us to do it twice, it means we have found a circuit.

    We keep track of the vertices whose out-neighborhood has been added to the stack once with a variable named `tried`.

    There is no reason why the graph should be empty at the end of this procedure, so we run it again on the remaining vertices until none are left or a circuit is found.

    Note

    The graph is assumed to be directed. An exception is raised if it is not.

    EXAMPLES:

    At first, the following graph is acyclic:

    Sage

        sage: D = DiGraph({ 0:[1,2,3], 4:[2,5], 1:[8], 2:[7], 3:[7], 5:[6,7], 7:[8], 6:[9], 8:[10], 9:[10] })
        sage: D.plot(layout='circular').show()                                      # needs sage.plot
        sage: D.is_directed_acyclic()
        True

    Python

        >>> from sage.all import *
        >>> D = DiGraph({ Integer(0):[Integer(1),Integer(2),Integer(3)], Integer(4):[Integer(2),Integer(5)], Integer(1):[Integer(8)], Integer(2):[Integer(7)], Integer(3):[Integer(7)], Integer(5):[Integer(6),Integer(7)], Integer(7):[Integer(8)], Integer(6):[Integer(9)], Integer(8):[Integer(10)], Integer(9):[Integer(10)] })
        >>> D.plot(layout='circular').show()                                      # needs sage.plot
        >>> D.is_directed_acyclic()
        True

    Adding an edge from \(9\) to \(7\) does not change it:

    Sage

        sage: D.add_edge(9,7)
        sage: D.is_directed_acyclic()
        True

    [Python]

        >>> from sage.all import *
        >>> D.add_edge(Integer(9),Integer(7))
        >>> D.is_directed_acyclic()
        True

    We can obtain as a proof an ordering of the vertices such that \(u\) appears before \(v\) if \(uv\) is an edge of the graph:

    Sage

        sage: D.is_directed_acyclic(certificate = True)
        (True, [4, 5, 6, 9, 0, 1, 2, 3, 7, 8, 10])

    Python

        >>> from sage.all import *
        >>> D.is_directed_acyclic(certificate = True)
        (True, [4, 5, 6, 9, 0, 1, 2, 3, 7, 8, 10])

    Adding an edge from 7 to 4, though, makes a difference:

    Sage

        sage: D.add_edge(7,4)
        sage: D.is_directed_acyclic()
        False

    [Python]

        >>> from sage.all import *
        >>> D.add_edge(Integer(7),Integer(4))
        >>> D.is_directed_acyclic()
        False

    Indeed, it creates a circuit \(7, 4, 5\):

    Sage

        sage: D.is_directed_acyclic(certificate = True)
        (False, [7, 4, 5])

    Python

        >>> from sage.all import *
        >>> D.is_directed_acyclic(certificate = True)
        (False, [7, 4, 5])

    Checking acyclic graphs are indeed acyclic

    Sage

        sage: def random_acyclic(n, p):
        ....:  g = graphs.RandomGNP(n, p)
        ....:  h = DiGraph()
        ....:  h.add_edges([ ((u,v) if u<v else (v,u)) for u,v,_ in g.edges(sort=True) ])
        ....:  return h
        ...
        sage: all( random_acyclic(100, .2).is_directed_acyclic()    # long time
        ....:      for i in range(50))
        True

    [Python]

        >>> from sage.all import *
        >>> def random_acyclic(n, p):
        ...  g = graphs.RandomGNP(n, p)
        ...  h = DiGraph()
        ...  h.add_edges([ ((u,v) if u<v else (v,u)) for u,v,_ in g.edges(sort=True) ])
        ...  return h
        ...
        >>> all( random_acyclic(Integer(100), RealNumber('.2')).is_directed_acyclic()    # long time
        ...      for i in range(Integer(50)))
        True

  is_strongly_connected()

    Check whether the graph is strongly connected.

    EXAMPLES:

    The circuit on 3 vertices is obviously strongly connected:

    Sage

        sage: g = DiGraph({0: [1], 1: [2], 2: [0]})
        sage: g.is_strongly_connected()
        True

    Python

        >>> from sage.all import *
        >>> g = DiGraph({Integer(0): [Integer(1)], Integer(1): [Integer(2)], Integer(2): [Integer(0)]})
        >>> g.is_strongly_connected()
        True

    But a transitive triangle is not:

    Sage

        sage: g = DiGraph({0: [1,2], 1: [2]})
        sage: g.is_strongly_connected()
        False

    [Python]

        >>> from sage.all import *
        >>> g = DiGraph({Integer(0): [Integer(1),Integer(2)], Integer(1): [Integer(2)]})
        >>> g.is_strongly_connected()
        False

  is_subgraph(other, vertices, ignore_labels=False)

    Return whether the subgraph of `self` induced by `vertices` is a subgraph of `other`.

    If `vertices` are the vertices of `self`, return whether `self` is a subgraph of `other`.

    INPUT:

    > - `other` – a subclass of `CGraphBackend`

    > - `vertices` – a iterable over the vertex labels

    > - `ignore_labels` – boolean (default: `False`); whether to ignore the labels

    EXAMPLES:

    Sage

        sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(4, directed=True)
        sage: H = sage.graphs.base.dense_graph.DenseGraphBackend(4, directed=True)
        sage: G.add_edges([[0,1],[0,2],[0,3],[1,2]], True)
        sage: H.add_edges([[0,1],[0,2],[0,3]], True)
        sage: G.is_subgraph(H, range(4))
        False
        sage: H.is_subgraph(G, range(4))
        True
        sage: G.is_subgraph(H, [0,1,3])
        True

    Python

        >>> from sage.all import *
        >>> G = sage.graphs.base.dense_graph.DenseGraphBackend(Integer(4), directed=True)
        >>> H = sage.graphs.base.dense_graph.DenseGraphBackend(Integer(4), directed=True)
        >>> G.add_edges([[Integer(0),Integer(1)],[Integer(0),Integer(2)],[Integer(0),Integer(3)],[Integer(1),Integer(2)]], True)
        >>> H.add_edges([[Integer(0),Integer(1)],[Integer(0),Integer(2)],[Integer(0),Integer(3)]], True)
        >>> G.is_subgraph(H, range(Integer(4)))
        False
        >>> H.is_subgraph(G, range(Integer(4)))
        True
        >>> G.is_subgraph(H, [Integer(0),Integer(1),Integer(3)])
        True

    Ignore the labels or not:

    Sage

        sage: G = sage.graphs.base.sparse_graph.SparseGraphBackend(3, directed=True)
        sage: G.multiple_edges(True)
        sage: H = sage.graphs.base.sparse_graph.SparseGraphBackend(3, directed=True)
        sage: H.multiple_edges(True)
        sage: G.add_edges([[0,1,'a'], [0,1,'b'], [0,2,'c'], [0,2,'d'], [0,2,'e']], True)
        sage: H.add_edges([[0,1,'a'], [0,1,'foo'], [0,2,'c'], [0,2,'d'], [0,2,'e'], [0,2,'e']], True)
        sage: G.is_subgraph(H, range(3))
        False
        sage: G.is_subgraph(H, range(3), ignore_labels=True)
        True

    [Python]

        >>> from sage.all import *
        >>> G = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(3), directed=True)
        >>> G.multiple_edges(True)
        >>> H = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(3), directed=True)
        >>> H.multiple_edges(True)
        >>> G.add_edges([[Integer(0),Integer(1),'a'], [Integer(0),Integer(1),'b'], [Integer(0),Integer(2),'c'], [Integer(0),Integer(2),'d'], [Integer(0),Integer(2),'e']], True)
        >>> H.add_edges([[Integer(0),Integer(1),'a'], [Integer(0),Integer(1),'foo'], [Integer(0),Integer(2),'c'], [Integer(0),Integer(2),'d'], [Integer(0),Integer(2),'e'], [Integer(0),Integer(2),'e']], True)
        >>> G.is_subgraph(H, range(Integer(3)))
        False
        >>> G.is_subgraph(H, range(Integer(3)), ignore_labels=True)
        True

    Multiplicities of edges are considered:

    Sage

        sage: G.is_subgraph(H, [0,2])
        True
        sage: H.is_subgraph(G, [0,2])
        False

    Python

        >>> from sage.all import *
        >>> G.is_subgraph(H, [Integer(0),Integer(2)])
        True
        >>> H.is_subgraph(G, [Integer(0),Integer(2)])
        False

  iterator_edges(vertices, labels)

    Iterate over the edges incident to a sequence of vertices.

    Edges are assumed to be undirected.

    Warning

    This will try to sort the two ends of every edge.

    INPUT:

    - `vertices` – list of vertex labels

    - `labels` – boolean, whether to return labels as well

    EXAMPLES:

    Sage

        sage: G = sage.graphs.base.sparse_graph.SparseGraphBackend(9)
        sage: G.add_edge(1,2,3,False)
        sage: list(G.iterator_edges(range(9), False))
        [(1, 2)]
        sage: list(G.iterator_edges(range(9), True))
        [(1, 2, 3)]

    Python

        >>> from sage.all import *
        >>> G = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(9))
        >>> G.add_edge(Integer(1),Integer(2),Integer(3),False)
        >>> list(G.iterator_edges(range(Integer(9)), False))
        [(1, 2)]
        >>> list(G.iterator_edges(range(Integer(9)), True))
        [(1, 2, 3)]

  iterator_in_edges(vertices, labels)

    Iterate over the incoming edges incident to a sequence of vertices.

    INPUT:

    - `vertices` – list of vertex labels

    - `labels` – boolean, whether to return labels as well

    EXAMPLES:

    Sage

        sage: G = sage.graphs.base.sparse_graph.SparseGraphBackend(9)
        sage: G.add_edge(1,2,3,True)
        sage: list(G.iterator_in_edges([1], False))
        []
        sage: list(G.iterator_in_edges([2], False))
        [(1, 2)]
        sage: list(G.iterator_in_edges([2], True))
        [(1, 2, 3)]

    Python

        >>> from sage.all import *
        >>> G = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(9))
        >>> G.add_edge(Integer(1),Integer(2),Integer(3),True)
        >>> list(G.iterator_in_edges([Integer(1)], False))
        []
        >>> list(G.iterator_in_edges([Integer(2)], False))
        [(1, 2)]
        >>> list(G.iterator_in_edges([Integer(2)], True))
        [(1, 2, 3)]

  iterator_in_nbrs(v)

    Iterate over the incoming neighbors of `v`.

    INPUT:

    - `v` – a vertex of this graph

    OUTPUT: an iterator over the in-neighbors of the vertex `v`

    See also

    - `iterator_nbrs()` – returns an iterator over the neighbors of a vertex

    - `iterator_out_nbrs()` – returns an iterator over the out-neighbors of a vertex

    EXAMPLES:

    Sage

        sage: P = DiGraph(graphs.PetersenGraph().to_directed())
        sage: list(P._backend.iterator_in_nbrs(0))
        [1, 4, 5]

    Python

        >>> from sage.all import *
        >>> P = DiGraph(graphs.PetersenGraph().to_directed())
        >>> list(P._backend.iterator_in_nbrs(Integer(0)))
        [1, 4, 5]

  iterator_nbrs(v)

    Iterate over the neighbors of `v`.

    INPUT:

    - `v` – a vertex of this graph

    OUTPUT: an iterator over the neighbors the vertex `v`

    See also

    - `iterator_in_nbrs()` – returns an iterator over the in-neighbors of a vertex

    - `iterator_out_nbrs()` – returns an iterator over the out-neighbors of a vertex

    - `iterator_verts()` – returns an iterator over a given set of vertices

    EXAMPLES:

    Sage

        sage: P = Graph(graphs.PetersenGraph())
        sage: list(P._backend.iterator_nbrs(0))
        [1, 4, 5]
        sage: Q = DiGraph(P)
        sage: list(Q._backend.iterator_nbrs(0))
        [1, 4, 5]

    Python

        >>> from sage.all import *
        >>> P = Graph(graphs.PetersenGraph())
        >>> list(P._backend.iterator_nbrs(Integer(0)))
        [1, 4, 5]
        >>> Q = DiGraph(P)
        >>> list(Q._backend.iterator_nbrs(Integer(0)))
        [1, 4, 5]

  iterator_out_edges(vertices, labels)

    Iterate over the outbound edges incident to a sequence of vertices.

    INPUT:

    - `vertices` – list of vertex labels

    - `labels` – boolean, whether to return labels as well

    EXAMPLES:

    Sage

        sage: G = sage.graphs.base.sparse_graph.SparseGraphBackend(9)
        sage: G.add_edge(1,2,3,True)
        sage: list(G.iterator_out_edges([2], False))
        []
        sage: list(G.iterator_out_edges([1], False))
        [(1, 2)]
        sage: list(G.iterator_out_edges([1], True))
        [(1, 2, 3)]

    Python

        >>> from sage.all import *
        >>> G = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(9))
        >>> G.add_edge(Integer(1),Integer(2),Integer(3),True)
        >>> list(G.iterator_out_edges([Integer(2)], False))
        []
        >>> list(G.iterator_out_edges([Integer(1)], False))
        [(1, 2)]
        >>> list(G.iterator_out_edges([Integer(1)], True))
        [(1, 2, 3)]

  iterator_out_nbrs(v)

    Iterate over the outgoing neighbors of `v`.

    INPUT:

    - `v` – a vertex of this graph

    OUTPUT: an iterator over the out-neighbors of the vertex `v`

    See also

    - `iterator_nbrs()` – returns an iterator over the neighbors of a vertex

    - `iterator_in_nbrs()` – returns an iterator over the in-neighbors of a vertex

    EXAMPLES:

    Sage

        sage: P = DiGraph(graphs.PetersenGraph().to_directed())
        sage: list(P._backend.iterator_out_nbrs(0))
        [1, 4, 5]

    Python

        >>> from sage.all import *
        >>> P = DiGraph(graphs.PetersenGraph().to_directed())
        >>> list(P._backend.iterator_out_nbrs(Integer(0)))
        [1, 4, 5]

  iterator_unsorted_edges(vertices, labels)

    Iterate over the edges incident to a sequence of vertices.

    Edges are assumed to be undirected.

    This does not sort the ends of each edge.

    INPUT:

    - `vertices` – list of vertex labels

    - `labels` – boolean, whether to return labels as well

    EXAMPLES:

    Sage

        sage: G = sage.graphs.base.sparse_graph.SparseGraphBackend(9)
        sage: G.add_edge(1,2,3,False)
        sage: list(G.iterator_unsorted_edges(range(9), False))
        [(2, 1)]
        sage: list(G.iterator_unsorted_edges(range(9), True))
        [(2, 1, 3)]

    Python

        >>> from sage.all import *
        >>> G = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(9))
        >>> G.add_edge(Integer(1),Integer(2),Integer(3),False)
        >>> list(G.iterator_unsorted_edges(range(Integer(9)), False))
        [(2, 1)]
        >>> list(G.iterator_unsorted_edges(range(Integer(9)), True))
        [(2, 1, 3)]

  iterator_verts(verts=None)

    Iterate over the vertices of `self` intersected with `verts`.

    INPUT:

    - `verts` – an iterable container of objects (default: `None`)

    OUTPUT:

    - If `verts=None`, return an iterator over all vertices of this graph

    - If `verts` is a single vertex of the graph, treat it as the container `[verts]`

    - If `verts` is a iterable container of vertices, find the intersection of `verts` with the vertex set of this graph and return an iterator over the resulting intersection

    See also

    - `iterator_nbrs()` – returns an iterator over the neighbors of a vertex.

    EXAMPLES:

    Sage

        sage: P = Graph(graphs.PetersenGraph())
        sage: list(P._backend.iterator_verts(P))
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        sage: list(P._backend.iterator_verts())
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        sage: list(P._backend.iterator_verts([1, 2, 3]))
        [1, 2, 3]
        sage: list(P._backend.iterator_verts([1, 2, 10]))
        [1, 2]

    Python

        >>> from sage.all import *
        >>> P = Graph(graphs.PetersenGraph())
        >>> list(P._backend.iterator_verts(P))
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        >>> list(P._backend.iterator_verts())
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        >>> list(P._backend.iterator_verts([Integer(1), Integer(2), Integer(3)]))
        [1, 2, 3]
        >>> list(P._backend.iterator_verts([Integer(1), Integer(2), Integer(10)]))
        [1, 2]

  loops(new=None)

    Check whether loops are allowed in this graph.

    INPUT:

    - `new` – boolean (default: `None`); to set or `None` to get

    OUTPUT:

    - If `new=None`, return `True` if this graph allows self-loops or `False` if self-loops are not allowed

    - If `new` is a boolean, set the self-loop permission of this graph according to the boolean value of `new`

    EXAMPLES:

    Sage

        sage: G = Graph()
        sage: G._backend.loops()
        False
        sage: G._backend.loops(True)
        sage: G._backend.loops()
        True

    Python

        >>> from sage.all import *
        >>> G = Graph()
        >>> G._backend.loops()
        False
        >>> G._backend.loops(True)
        >>> G._backend.loops()
        True

  n_edges(directed)

    Return the number of edges in `self`.

    INPUT:

    - `directed` – boolean; whether to count `(u, v)` and `(v, u)` as one or two edges

    OUTPUT:

    - If `directed=True`, counts the number of directed edges in this graph. Otherwise, return the size of this graph.

    See also

    - `n_vertices()` – return the order of this graph.

    EXAMPLES:

    Sage

        sage: G = Graph(graphs.PetersenGraph())
        sage: G._backend.n_edges(False)
        15

    Python

        >>> from sage.all import *
        >>> G = Graph(graphs.PetersenGraph())
        >>> G._backend.n_edges(False)
        15

  n_vertices()

    Return the number of vertices in `self`.

    OUTPUT: the order of this graph

    See also

    - `n_edges()` – return the number of (directed) edges in this graph.

    EXAMPLES:

    Sage

        sage: G = Graph(graphs.PetersenGraph())
        sage: G._backend.n_vertices()
        10

    Python

        >>> from sage.all import *
        >>> G = Graph(graphs.PetersenGraph())
        >>> G._backend.n_vertices()
        10

  num_edges(directed)

    alias of `n_edges()`.

  num_verts()

    alias of `n_vertices()`.

  out_degree(v)

    Return the out-degree of `v`.

    INPUT:

    - `v` – a vertex of the graph

    EXAMPLES:

    Sage

        sage: D = DiGraph( { 0: [1,2,3], 1: [0,2], 2: [3], 3: [4], 4: [0,5], 5: [1] } )
        sage: D.out_degree(1)
        2

    Python

        >>> from sage.all import *
        >>> D = DiGraph( { Integer(0): [Integer(1),Integer(2),Integer(3)], Integer(1): [Integer(0),Integer(2)], Integer(2): [Integer(3)], Integer(3): [Integer(4)], Integer(4): [Integer(0),Integer(5)], Integer(5): [Integer(1)] } )
        >>> D.out_degree(Integer(1))
        2

  relabel(perm, directed)

    Relabel the graph according to `perm`.

    INPUT:

    - `perm` – anything which represents a permutation as `v --> perm[v]`, for example a dict or a list

    - `directed` – ignored (this is here for compatibility with other backends)

    EXAMPLES:

    Sage

        sage: G = Graph(graphs.PetersenGraph())
        sage: G._backend.relabel(range(9,-1,-1), False)
        sage: G.edges(sort=True)
        [(0, 2, None),
         (0, 3, None),
         (0, 5, None),
         (1, 3, None),
         (1, 4, None),
         (1, 6, None),
         (2, 4, None),
         (2, 7, None),
         (3, 8, None),
         (4, 9, None),
         (5, 6, None),
         (5, 9, None),
         (6, 7, None),
         (7, 8, None),
         (8, 9, None)]

    Python

        >>> from sage.all import *
        >>> G = Graph(graphs.PetersenGraph())
        >>> G._backend.relabel(range(Integer(9),-Integer(1),-Integer(1)), False)
        >>> G.edges(sort=True)
        [(0, 2, None),
         (0, 3, None),
         (0, 5, None),
         (1, 3, None),
         (1, 4, None),
         (1, 6, None),
         (2, 4, None),
         (2, 7, None),
         (3, 8, None),
         (4, 9, None),
         (5, 6, None),
         (5, 9, None),
         (6, 7, None),
         (7, 8, None),
         (8, 9, None)]

  shortest_path(x, y, distance_flag=False)

    Return the shortest path or distance from `x` to `y`.

    INPUT:

    - `x` – the starting vertex in the shortest path from `x` to `y`

    - `y` – the end vertex in the shortest path from `x` to `y`

    - `distance_flag` – boolean (default: `False`); when set to `True`, the shortest path distance from `x` to `y` is returned instead of the path

    OUTPUT:

    - A list of vertices in the shortest path from `x` to `y` or distance from `x` to `y` is returned depending upon the value of parameter `distance_flag`

    EXAMPLES:

    Sage

        sage: G = Graph(graphs.PetersenGraph())
        sage: G.shortest_path(0, 1)
        [0, 1]
        sage: G.shortest_path_length(0, 1)
        1

    Python

        >>> from sage.all import *
        >>> G = Graph(graphs.PetersenGraph())
        >>> G.shortest_path(Integer(0), Integer(1))
        [0, 1]
        >>> G.shortest_path_length(Integer(0), Integer(1))
        1

  shortest_path_all_vertices(v, cutoff=None, distance_flag=False)

    Return for each reachable vertex `u` a shortest `v-u` path or distance from `v` to `u`.

    INPUT:

    - `v` – a starting vertex in the shortest path

    - `cutoff` – integer (default: `None`); maximal distance of returned paths (longer paths will not be returned), ignored when set to `None`

    - `distance_flag` – boolean (default: `False`); when set to `True`, each vertex `u` connected to `v` is mapped to shortest path distance from `v` to `u` instead of the shortest path in the output dictionary.

    OUTPUT:

    - A dictionary which maps each vertex `u` connected to `v` to the shortest path list or distance from `v` to `u` depending upon the value of parameter `distance_flag`

    Note

    The weight of edges is not taken into account.

    ALGORITHM:

    This is just a breadth-first search.

    EXAMPLES:

    On the Petersen Graph:

    Sage

        sage: g = graphs.PetersenGraph()
        sage: paths = g._backend.shortest_path_all_vertices(0)
        sage: all((not paths[v] or len(paths[v])-1 == g.distance(0,v)) for v in g)
        True
        sage: g._backend.shortest_path_all_vertices(0, distance_flag=True)
        {0: 0, 1: 1, 2: 2, 3: 2, 4: 1, 5: 1, 6: 2, 7: 2, 8: 2, 9: 2}

    Python

        >>> from sage.all import *
        >>> g = graphs.PetersenGraph()
        >>> paths = g._backend.shortest_path_all_vertices(Integer(0))
        >>> all((not paths[v] or len(paths[v])-Integer(1) == g.distance(Integer(0),v)) for v in g)
        True
        >>> g._backend.shortest_path_all_vertices(Integer(0), distance_flag=True)
        {0: 0, 1: 1, 2: 2, 3: 2, 4: 1, 5: 1, 6: 2, 7: 2, 8: 2, 9: 2}

    On a disconnected graph:

    Sage

        sage: g = 2 * graphs.RandomGNP(20, .3)
        sage: paths = g._backend.shortest_path_all_vertices(0)
        sage: all((v not in paths and g.distance(0, v) == +Infinity) or len(paths[v]) - 1 == g.distance(0, v) for v in g)
        True

    [Python]

        >>> from sage.all import *
        >>> g = Integer(2) * graphs.RandomGNP(Integer(20), RealNumber('.3'))
        >>> paths = g._backend.shortest_path_all_vertices(Integer(0))
        >>> all((v not in paths and g.distance(Integer(0), v) == +Infinity) or len(paths[v]) - Integer(1) == g.distance(Integer(0), v) for v in g)
        True

  shortest_path_special(x, y, exclude_vertices=None, exclude_edges=None, distance_flag=False)

    Return the shortest path or distance from `x` to `y`.

    This method is an extension of `shortest_path()` method enabling to exclude vertices and/or edges from the search for the shortest path between `x` and `y`.

    INPUT:

    - `x` – the starting vertex in the shortest path from `x` to `y`

    - `y` – the end vertex in the shortest path from `x` to `y`

    - `exclude_vertices` – iterable container (default: `None`); iterable of vertices to exclude from the graph while calculating the shortest path from `x` to `y`

    - `exclude_edges` – iterable container (default: `None`); iterable of edges to exclude from the graph while calculating the shortest path from `x` to `y`

    - `distance_flag` – boolean (default: `False`); when set to `True`, the shortest path distance from `x` to `y` is returned instead of the path

    OUTPUT:

    - A list of vertices in the shortest path from `x` to `y` or distance from `x` to `y` is returned depending upon the value of parameter `distance_flag`

    EXAMPLES:

    Sage

        sage: G = Graph([(1, 2), (2, 3), (3, 4), (1, 5), (5, 6), (6, 7), (7, 4)])
        sage: G._backend.shortest_path_special(1, 4)
        [1, 2, 3, 4]
        sage: G._backend.shortest_path_special(1, 4, exclude_vertices=[5,7])
        [1, 2, 3, 4]
        sage: G._backend.shortest_path_special(1, 4, exclude_vertices=[2, 3])
        [1, 5, 6, 7, 4]
        sage: G._backend.shortest_path_special(1, 4, exclude_vertices=[2], exclude_edges=[(5, 6)])
        []
        sage: G._backend.shortest_path_special(1, 4, exclude_vertices=[2], exclude_edges=[(2, 3)])
        [1, 5, 6, 7, 4]

    Python

        >>> from sage.all import *
        >>> G = Graph([(Integer(1), Integer(2)), (Integer(2), Integer(3)), (Integer(3), Integer(4)), (Integer(1), Integer(5)), (Integer(5), Integer(6)), (Integer(6), Integer(7)), (Integer(7), Integer(4))])
        >>> G._backend.shortest_path_special(Integer(1), Integer(4))
        [1, 2, 3, 4]
        >>> G._backend.shortest_path_special(Integer(1), Integer(4), exclude_vertices=[Integer(5),Integer(7)])
        [1, 2, 3, 4]
        >>> G._backend.shortest_path_special(Integer(1), Integer(4), exclude_vertices=[Integer(2), Integer(3)])
        [1, 5, 6, 7, 4]
        >>> G._backend.shortest_path_special(Integer(1), Integer(4), exclude_vertices=[Integer(2)], exclude_edges=[(Integer(5), Integer(6))])
        []
        >>> G._backend.shortest_path_special(Integer(1), Integer(4), exclude_vertices=[Integer(2)], exclude_edges=[(Integer(2), Integer(3))])
        [1, 5, 6, 7, 4]

  shortest_path_to_set(source, targets, by_weight=False, edge_weight=None, exclude_vertices=None, report_weight=False)

    Return the shortest path from `source` to any vertex in `targets`.

    INPUT:

    - `source` – the starting vertex.

    - `targets` – iterable container; the set of end vertices.

    - `edge_weight` – dictionary (default: `None`); a dictionary that takes as input an edge `(u, v)` and outputs its weight. If not `None`, `by_weight` is automatically set to `True`. If `None` and `by_weight` is `True`, we use the edge label `l` as a weight.

    - `by_weight` – boolean (default: `False`); if `True`, the edges in the graph are weighted, otherwise all edges have weight 1.

    - `exclude_vertices` – iterable container (default: `None`); iterable of vertices to exclude from the graph while calculating the shortest path from `source` to any vertex in `targets`.

    - `report_weight` – boolean (default: `False`); if `False`, just a path is returned. Otherwise a tuple of path length and path is returned.

    OUTPUT:

    - A list of vertices in the shortest path from `source` to any vertex in `targets` or a tuple of path lengh and path is returned depending upon the value of parameter `report_weight`.

    EXAMPLES:

    Sage

        sage: g = Graph([(1, 2, 10), (1, 3, 20), (1, 4, 30)])
        sage: g._backend.shortest_path_to_set(1, {3, 4}, by_weight=True)
        [1, 3]
        sage: g = Graph([(1, 2, 10), (2, 3, 10), (1, 4, 20), (4, 5, 20), (1, 6, 30), (6, 7, 30)])
        sage: g._backend.shortest_path_to_set(1, {5, 7}, by_weight=True, exclude_vertices=[4], report_weight=True)
        (60.0, [1, 6, 7])

    Python

        >>> from sage.all import *
        >>> g = Graph([(Integer(1), Integer(2), Integer(10)), (Integer(1), Integer(3), Integer(20)), (Integer(1), Integer(4), Integer(30))])
        >>> g._backend.shortest_path_to_set(Integer(1), {Integer(3), Integer(4)}, by_weight=True)
        [1, 3]
        >>> g = Graph([(Integer(1), Integer(2), Integer(10)), (Integer(2), Integer(3), Integer(10)), (Integer(1), Integer(4), Integer(20)), (Integer(4), Integer(5), Integer(20)), (Integer(1), Integer(6), Integer(30)), (Integer(6), Integer(7), Integer(30))])
        >>> g._backend.shortest_path_to_set(Integer(1), {Integer(5), Integer(7)}, by_weight=True, exclude_vertices=[Integer(4)], report_weight=True)
        (60.0, [1, 6, 7])

  strongly_connected_component_containing_vertex(v)

    Return the strongly connected component containing the given vertex.

    INPUT:

    - `v` – a vertex

    EXAMPLES:

    The digraph obtained from the `PetersenGraph` has an unique strongly connected component:

    Sage

        sage: g = DiGraph(graphs.PetersenGraph())
        sage: g.strongly_connected_component_containing_vertex(0)
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    Python

        >>> from sage.all import *
        >>> g = DiGraph(graphs.PetersenGraph())
        >>> g.strongly_connected_component_containing_vertex(Integer(0))
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    In the Butterfly DiGraph, each vertex is a strongly connected component:

    Sage

        sage: g = digraphs.ButterflyGraph(3)
        sage: all([v] == g.strongly_connected_component_containing_vertex(v) for v in g)
        True

    [Python]

        >>> from sage.all import *
        >>> g = digraphs.ButterflyGraph(Integer(3))
        >>> all([v] == g.strongly_connected_component_containing_vertex(v) for v in g)
        True

  subgraph_given_vertices(other, vertices)

    Initialize `other` to be the subgraph of `self` with given vertices.

    INPUT:

    - `other` – a (mutable) subclass of `CGraphBackend`

    - `vertices` – list of vertex labels

    Note

    `other` is assumed to be the empty graph.

    EXAMPLES:

    Make a dense copy:

    Sage

        sage: G = sage.graphs.base.dense_graph.DenseGraphBackend(9, directed=True)
        sage: G.loops(True)
        sage: G.add_edges([[0,1], [1,2], [2,3], [3,4], [4,5], [5,6], [7,8], [3,3]], True)
        sage: H = sage.graphs.base.dense_graph.DenseGraphBackend(0, directed=True)
        sage: H.loops(True)
        sage: G.subgraph_given_vertices(H, range(9))
        sage: list(H.iterator_out_edges(list(range(9)), False)) == list(G.iterator_out_edges(list(range(9)), False))
        True

    Python

        >>> from sage.all import *
        >>> G = sage.graphs.base.dense_graph.DenseGraphBackend(Integer(9), directed=True)
        >>> G.loops(True)
        >>> G.add_edges([[Integer(0),Integer(1)], [Integer(1),Integer(2)], [Integer(2),Integer(3)], [Integer(3),Integer(4)], [Integer(4),Integer(5)], [Integer(5),Integer(6)], [Integer(7),Integer(8)], [Integer(3),Integer(3)]], True)
        >>> H = sage.graphs.base.dense_graph.DenseGraphBackend(Integer(0), directed=True)
        >>> H.loops(True)
        >>> G.subgraph_given_vertices(H, range(Integer(9)))
        >>> list(H.iterator_out_edges(list(range(Integer(9))), False)) == list(G.iterator_out_edges(list(range(Integer(9))), False))
        True

    Make a sparse copy:

    Sage

        sage: H = sage.graphs.base.sparse_graph.SparseGraphBackend(0, directed=True)
        sage: H.loops(True)
        sage: G.subgraph_given_vertices(H, range(9))
        sage: sorted(list(H.iterator_out_edges(list(range(9)), False))) == sorted(list(G.iterator_out_edges(list(range(9)), False)))
        True

    [Python]

        >>> from sage.all import *
        >>> H = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(0), directed=True)
        >>> H.loops(True)
        >>> G.subgraph_given_vertices(H, range(Integer(9)))
        >>> sorted(list(H.iterator_out_edges(list(range(Integer(9))), False))) == sorted(list(G.iterator_out_edges(list(range(Integer(9))), False)))
        True

    Initialize a proper subgraph:

    Sage

        sage: H = sage.graphs.base.sparse_graph.SparseGraphBackend(0, directed=True)
        sage: H.loops(True)
        sage: G.subgraph_given_vertices(H, [2,3,4,5])
        sage: list(H.iterator_out_edges(list(range(9)), False))
        [(2, 3), (3, 3), (3, 4), (4, 5)]

    Python

        >>> from sage.all import *
        >>> H = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(0), directed=True)
        >>> H.loops(True)
        >>> G.subgraph_given_vertices(H, [Integer(2),Integer(3),Integer(4),Integer(5)])
        >>> list(H.iterator_out_edges(list(range(Integer(9))), False))
        [(2, 3), (3, 3), (3, 4), (4, 5)]

    Loops are removed, if the other graph does not allow loops:

    Sage

        sage: H = sage.graphs.base.sparse_graph.SparseGraphBackend(0, directed=True)
        sage: H.loops(False)
        sage: G.subgraph_given_vertices(H, [2,3,4,5])
        sage: list(H.iterator_out_edges(list(range(9)), False))
        [(2, 3), (3, 4), (4, 5)]

    [Python]

        >>> from sage.all import *
        >>> H = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(0), directed=True)
        >>> H.loops(False)
        >>> G.subgraph_given_vertices(H, [Integer(2),Integer(3),Integer(4),Integer(5)])
        >>> list(H.iterator_out_edges(list(range(Integer(9))), False))
        [(2, 3), (3, 4), (4, 5)]

    Multiple edges and labels are copied:

    Sage

        sage: G = sage.graphs.base.sparse_graph.SparseGraphBackend(4, directed=False)
        sage: G.multiple_edges(True)
        sage: G.add_edges([[0,1,'a'], [1,2,'b'], [2,3,'c'], [0,1,'d']], False)
        sage: H = sage.graphs.base.sparse_graph.SparseGraphBackend(0, directed=False)
        sage: H.multiple_edges(True)
        sage: G.subgraph_given_vertices(H, [0,1,2])
        sage: list(H.iterator_edges(list(range(4)), True))
        [(0, 1, 'a'), (0, 1, 'd'), (1, 2, 'b')]

    Python

        >>> from sage.all import *
        >>> G = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(4), directed=False)
        >>> G.multiple_edges(True)
        >>> G.add_edges([[Integer(0),Integer(1),'a'], [Integer(1),Integer(2),'b'], [Integer(2),Integer(3),'c'], [Integer(0),Integer(1),'d']], False)
        >>> H = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(0), directed=False)
        >>> H.multiple_edges(True)
        >>> G.subgraph_given_vertices(H, [Integer(0),Integer(1),Integer(2)])
        >>> list(H.iterator_edges(list(range(Integer(4))), True))
        [(0, 1, 'a'), (0, 1, 'd'), (1, 2, 'b')]

    Multiple edges are removed, if the other graph does not allow them:

    Sage

        sage: H = sage.graphs.base.sparse_graph.SparseGraphBackend(0, directed=False)
        sage: H.multiple_edges(False)
        sage: G.subgraph_given_vertices(H, [0,1,2])
        sage: list(H.iterator_edges(list(range(4)), True))
        [(0, 1, 'd'), (1, 2, 'b')]

    [Python]

        >>> from sage.all import *
        >>> H = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(0), directed=False)
        >>> H.multiple_edges(False)
        >>> G.subgraph_given_vertices(H, [Integer(0),Integer(1),Integer(2)])
        >>> list(H.iterator_edges(list(range(Integer(4))), True))
        [(0, 1, 'd'), (1, 2, 'b')]

    Labels are removed, if the other graph does not allow them:

    Sage

        sage: H = sage.graphs.base.dense_graph.DenseGraphBackend(0, directed=False)
        sage: G.subgraph_given_vertices(H, [0,1,2])
        sage: list(H.iterator_edges(list(range(4)), True))
        [(0, 1, None), (1, 2, None)]

    Python

        >>> from sage.all import *
        >>> H = sage.graphs.base.dense_graph.DenseGraphBackend(Integer(0), directed=False)
        >>> G.subgraph_given_vertices(H, [Integer(0),Integer(1),Integer(2)])
        >>> list(H.iterator_edges(list(range(Integer(4))), True))
        [(0, 1, None), (1, 2, None)]

    A directed subgraph of an undirected graph is taken by initializing with edges in both directions:

    Sage

        sage: G = sage.graphs.base.sparse_graph.SparseGraphBackend(4, directed=True)
        sage: G.loops(True)
        sage: G.multiple_edges(True)
        sage: G.add_edges([[0,1,'a'], [1,2,'b'], [2,3,'c'], [0,1,'d'], [2,2,'e']], False)
        sage: H = sage.graphs.base.sparse_graph.SparseGraphBackend(0, directed=True)
        sage: H.multiple_edges(True)
        sage: H.loops(True)
        sage: G.subgraph_given_vertices(H, [0,1,2])
        sage: list(H.iterator_out_edges(list(range(4)), True))
        [(0, 1, 'a'),
         (0, 1, 'd'),
         (1, 0, 'a'),
         (1, 0, 'd'),
         (1, 2, 'b'),
         (2, 1, 'b'),
         (2, 2, 'e')]

    [Python]

        >>> from sage.all import *
        >>> G = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(4), directed=True)
        >>> G.loops(True)
        >>> G.multiple_edges(True)
        >>> G.add_edges([[Integer(0),Integer(1),'a'], [Integer(1),Integer(2),'b'], [Integer(2),Integer(3),'c'], [Integer(0),Integer(1),'d'], [Integer(2),Integer(2),'e']], False)
        >>> H = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(0), directed=True)
        >>> H.multiple_edges(True)
        >>> H.loops(True)
        >>> G.subgraph_given_vertices(H, [Integer(0),Integer(1),Integer(2)])
        >>> list(H.iterator_out_edges(list(range(Integer(4))), True))
        [(0, 1, 'a'),
         (0, 1, 'd'),
         (1, 0, 'a'),
         (1, 0, 'd'),
         (1, 2, 'b'),
         (2, 1, 'b'),
         (2, 2, 'e')]

    An undirected subgraph of a directeed graph is not defined:

    Sage

        sage: G = sage.graphs.base.sparse_graph.SparseGraphBackend(4, directed=True)
        sage: G.add_edges([[0,1,'a'], [1,2,'b'], [2,3,'c']], False)
        sage: H = sage.graphs.base.sparse_graph.SparseGraphBackend(0, directed=False)
        sage: G.subgraph_given_vertices(H, [0,1,2])
        Traceback (most recent call last):
        ...
        ValueError: cannot obtain an undirected subgraph of a directed graph

    Python

        >>> from sage.all import *
        >>> G = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(4), directed=True)
        >>> G.add_edges([[Integer(0),Integer(1),'a'], [Integer(1),Integer(2),'b'], [Integer(2),Integer(3),'c']], False)
        >>> H = sage.graphs.base.sparse_graph.SparseGraphBackend(Integer(0), directed=False)
        >>> G.subgraph_given_vertices(H, [Integer(0),Integer(1),Integer(2)])
        Traceback (most recent call last):
        ...
        ValueError: cannot obtain an undirected subgraph of a directed graph

class sage.graphs.base.c_graph.Search_iterator

  Bases: `object`

  An iterator for traversing a (di)graph.

  This class is commonly used to perform a depth-first or breadth-first search. The class does not build all at once in memory the whole list of visited vertices. The class maintains the following variables:

  - `graph` – a graph whose vertices are to be iterated over

  - `direction` – integer; this determines the position at which vertices to be visited are removed from the list. For breadth-first search (BFS), element removal follow a first-in first-out (FIFO) protocol, as signified by the value `direction=0`. We use a queue to maintain the list of vertices to visit in this case. For depth-first search (DFS), element removal follow a last-in first-out (LIFO) protocol, as signified by the value `direction=-1`. In this case, we use a stack to maintain the list of vertices to visit.

  - `stack` – list of vertices to visit, used only when `direction=-1`

  - `queue` – a queue of vertices to visit, used only when `direction=0`

  - `seen` – list of vertices that are already visited

  - `test_out` – boolean; whether we want to consider the out-neighbors of the graph to be traversed. For undirected graphs, we consider both the in- and out-neighbors. However, for digraphs we only traverse along out-neighbors.

  - `test_in` – boolean; whether we want to consider the in-neighbors of the graph to be traversed. For undirected graphs, we consider both the in- and out-neighbors.

  EXAMPLES:

  Sage

      sage: g = graphs.PetersenGraph()
      sage: list(g.breadth_first_search(0))
      [0, 1, 4, 5, 2, 6, 3, 9, 7, 8]

  Python

      >>> from sage.all import *
      >>> g = graphs.PetersenGraph()
      >>> list(g.breadth_first_search(Integer(0)))
      [0, 1, 4, 5, 2, 6, 3, 9, 7, 8]