Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Orientations
This module implements several methods to compute orientations of undirected graphs subject to specific constraints (e.g., acyclic, strongly connected, etc.). It also implements some iterators over all these orientations.
**This module contains the following methods**
.. csv-table:: :class: contentstable :widths: 30, 70 :delim: |
:meth:`strong_orientations_iterator` | Return an iterator over all strong orientations of a graph `G`
Authors -------
- Kolja Knauer, Petru Valicov (2017-01-10) -- initial version
Methods ------- """
from sage.graphs.spanning_tree import kruskal from sage.graphs.digraph import DiGraph
def strong_orientations_iterator(G): r""" Returns an iterator over all strong orientations of a graph `G`.
A strong orientation of a graph is an orientation of its edges such that the obtained digraph is strongly connected (i.e. there exist a directed path between each pair of vertices).
ALGORITHM:
It is an adaptation of the algorithm published in [CGMRV16]_. It runs in `O(mn)` amortized time, where `m` is the number of edges and `n` is the number of vertices. The amortized time can be improved to `O(m)` with a more involved method. In this function, first the graph is preprocessed and a spanning tree is generated. Then every orientation of the non-tree edges of the graph can be extended to at least one new strong orientation by orienting properly the edges of the spanning tree (this property is proved in [CGMRV16]_). Therefore, this function generates all partial orientations of the non-tree edges and then launches a helper function corresponding to the generation algorithm described in [CGMRV16]_. In order to avoid trivial symetries, the orientation of an arbitrary edge is fixed before the start of the enumeration process.
INPUT:
- ``G`` -- an undirected graph.
OUTPUT:
- an iterator which will produce all strong orientations of this graph.
.. NOTE::
Works only for simple graphs (no multiple edges). In order to avoid symetries an orientation of an arbitrary edge is fixed.
EXAMPLES:
A cycle has one possible (non-symmetric) strong orientation::
sage: g = graphs.CycleGraph(4) sage: it = g.strong_orientations_iterator() sage: len(list(it)) 1
A tree cannot be strongly oriented::
sage: g = graphs.RandomTree(100) sage: len(list(g.strong_orientations_iterator())) 0
Neither can be a disconnected graph::
sage: g = graphs.CompleteGraph(6) sage: g.add_vertex(7) sage: len(list(g.strong_orientations_iterator())) 0
TESTS:
sage: g = graphs.CompleteGraph(2) sage: len(list(g.strong_orientations_iterator())) 0
sage: g = graphs.CubeGraph(3) sage: b = True sage: for orientedGraph in g.strong_orientations_iterator(): ....: if not orientedGraph.is_strongly_connected(): ....: b = False sage: b True
The total number of strong orientations of a graph can be counted using the Tutte polynomial evaluated at points (0,2)::
sage: g = graphs.PetersenGraph() sage: nr1 = len(list(g.strong_orientations_iterator())) sage: nr2 = g.tutte_polynomial()(0,2) sage: nr1 == nr2/2 # The Tutte polynomial counts also the symmetrical orientations True
""" # if the graph has a bridge or is disconnected, # then it cannot be strongly oriented
# compute an arbitrary spanning tree of the undirected graph
# initialization of the first binary word 00...0 # corresponding to the current orientation of the non-tree edges
# Make the edges of the spanning tree doubly oriented else: Dg.add_edge(e)
# Generate all orientations for non-tree edges (using Gray code) # Each of these orientations can be extended to a strong orientation # of G by orienting properly the tree-edges
# the orientation of one edge is fixed so we consider one edge less
else: # launch the algorithm for enumeration of the solutions
def _strong_orientations_of_a_mixed_graph(Dg, V, E): r""" Helper function for the generation of all strong orientations.
Generates all strong orientations of a given partially directed graph (also called mixed graph). The algorithm finds bound edges i.e undirected edges whose orientation is forced and tries all possible orientations for the other edges. See [CGMRV16]_ for more details.
INPUT:
- ``Dg`` -- the mixed graph. The undirected edges are doubly oriented. - ``V`` -- the set of vertices - ``E`` -- the set of undirected edges (they are oriented in both ways); No labels are allowed.
OUTPUT:
- an iterator which will produce all strong orientations of the input partially directed graph.
EXAMPLES:
sage: from sage.graphs.orientations import _strong_orientations_of_a_mixed_graph sage: g = graphs.CycleGraph(5) sage: Dg = DiGraph(g) # all edges of g will be doubly oriented sage: it = _strong_orientations_of_a_mixed_graph(Dg, g.vertices(), g.edges(labels=False)) sage: len(list(it)) # there are two orientations of this multigraph 2 """ else: else:
# if true the obtained orientation is strong else: |