Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move orientation methods from graph.py to orientations.py #38809

Merged
merged 8 commits into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 0 additions & 105 deletions src/sage/graphs/generic_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@
:widths: 30, 70
:delim: |

:meth:`~GenericGraph.eulerian_orientation` | Return a DiGraph which is an Eulerian orientation of the current graph.
:meth:`~GenericGraph.eulerian_circuit` | Return a list of edges forming an Eulerian circuit if one exists.
:meth:`~GenericGraph.minimum_cycle_basis` | Return a minimum weight cycle basis of the graph.
:meth:`~GenericGraph.cycle_basis` | Return a list of cycles which form a basis of the cycle space of ``self``.
Expand Down Expand Up @@ -4732,110 +4731,6 @@ def size(self):

num_edges = size

# Orientations

def eulerian_orientation(self):
r"""
Return a DiGraph which is an Eulerian orientation of the current graph.

An Eulerian graph being a graph such that any vertex has an even degree,
an Eulerian orientation of a graph is an orientation of its edges such
that each vertex `v` verifies `d^+(v)=d^-(v)=d(v)/2`, where `d^+` and
`d^-` respectively represent the out-degree and the in-degree of a
vertex.

If the graph is not Eulerian, the orientation verifies for any vertex
`v` that `| d^+(v)-d^-(v) | \leq 1`.

ALGORITHM:

This algorithm is a random walk through the edges of the graph, which
orients the edges according to the walk. When a vertex is reached which
has no non-oriented edge (this vertex must have odd degree), the walk
resumes at another vertex of odd degree, if any.

This algorithm has complexity `O(n+m)` for ``SparseGraph`` and `O(n^2)`
for ``DenseGraph``, where `m` is the number of edges in the graph and
`n` is the number of vertices in the graph.

EXAMPLES:

The CubeGraph with parameter 4, which is regular of even degree, has an
Eulerian orientation such that `d^+ = d^-`::

sage: g = graphs.CubeGraph(4)
sage: g.degree()
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
sage: o = g.eulerian_orientation()
sage: o.in_degree()
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
sage: o.out_degree()
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]

Secondly, the Petersen Graph, which is 3 regular has an orientation such
that the difference between `d^+` and `d^-` is at most 1::

sage: g = graphs.PetersenGraph()
sage: o = g.eulerian_orientation()
sage: o.in_degree()
[2, 2, 2, 2, 2, 1, 1, 1, 1, 1]
sage: o.out_degree()
[1, 1, 1, 1, 1, 2, 2, 2, 2, 2]

TESTS::

sage: E0 = Graph(); E4 = Graph(4) # See trac #21741
sage: E0.eulerian_orientation()
Digraph on 0 vertices
sage: E4.eulerian_orientation()
Digraph on 4 vertices
"""
from sage.graphs.digraph import DiGraph

d = DiGraph()
d.add_vertices(self.vertex_iterator())

if not self.size():
return d

g = copy(self)

# list of vertices of odd degree
odd = [x for x in g.vertex_iterator() if g.degree(x) % 2]

# Picks the first vertex, which is preferably an odd one
if odd:
v = odd.pop()
else:
v = next(g.edge_iterator(labels=None))[0]
odd.append(v)
# Stops when there is no edge left
while True:

# If there is an edge adjacent to the current one
if g.degree(v):
e = next(g.edge_iterator(v))
g.delete_edge(e)
if e[0] != v:
e = (e[1], e[0], e[2])
d.add_edge(e)
v = e[1]

# The current vertex is isolated
else:
odd.remove(v)

# jumps to another odd vertex if possible
if odd:
v = odd.pop()
# Else jumps to an even vertex which is not isolated
elif g.size():
v = next(g.edge_iterator())[0]
odd.append(v)
# If there is none, we are done !
else:
return d

def eulerian_circuit(self, return_vertices=False, labels=True, path=False):
r"""
Return a list of edges forming an Eulerian circuit if one exists.
Expand Down
Loading
Loading