Skip to content
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
2 changes: 1 addition & 1 deletion src/sage/combinat/finite_state_machine_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -1961,7 +1961,7 @@ def f(n):
"Missing initial values for %s." %
sorted(missing_initial_values))

for cycle in recursion_digraph.all_simple_cycles():
for cycle in recursion_digraph.all_simple_cycles(algorithm="A"):
assert cycle[0] is cycle[-1]
cycle_set = set(cycle)
intersection = cycle_set.intersection(initial_values_set)
Expand Down
2 changes: 1 addition & 1 deletion src/sage/dynamics/arithmetic_dynamics/projective_ds.py
Original file line number Diff line number Diff line change
Expand Up @@ -4895,7 +4895,7 @@ def periodic_points(self, n, minimal=True, formal=False, R=None, algorithm='vari
if R in FiniteFields():
g = f.cyclegraph()
points = []
for cycle in g.all_simple_cycles():
for cycle in g.all_simple_cycles(algorithm="A"):
m = len(cycle)-1
if minimal:
if m == n:
Expand Down
148 changes: 80 additions & 68 deletions src/sage/graphs/cycle_enumeration.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,10 @@ def _all_simple_cycles_iterator_edge(self, edge, max_length=None,
sage: g = graphs.Grid2dGraph(2, 5)
sage: it = g._all_simple_cycles_iterator_edge(((0, 0), (0, 1), None), report_weight=True)
sage: for i in range(4): print(next(it))
(4, [(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
(6, [(0, 0), (0, 1), (0, 2), (1, 2), (1, 1), (1, 0), (0, 0)])
(8, [(0, 0), (0, 1), (0, 2), (0, 3), (1, 3), (1, 2), (1, 1), (1, 0), (0, 0)])
(10, [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 4), (1, 3), (1, 2), (1, 1), (1, 0), (0, 0)])
(4.0, [(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
(6.0, [(0, 0), (0, 1), (0, 2), (1, 2), (1, 1), (1, 0), (0, 0)])
(8.0, [(0, 0), (0, 1), (0, 2), (0, 3), (1, 3), (1, 2), (1, 1), (1, 0), (0, 0)])
(10.0, [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 4), (1, 3), (1, 2), (1, 1), (1, 0), (0, 0)])

Each edge must have a positive weight::

Expand Down Expand Up @@ -379,7 +379,6 @@ def _all_simple_cycles_iterator_edge(self, edge, max_length=None,
weight_function=weight_function,
by_weight=by_weight,
check_weight=check_weight,
algorithm=('Feng' if h.is_directed() else 'Yen'),
report_edges=False,
report_weight=True)

Expand Down Expand Up @@ -461,7 +460,8 @@ def all_cycles_iterator(self, starting_vertices=None, simple=False,

- The algorithm ``'B'`` holds cycle iterators starting with each edge,
and output them in increasing length order. It depends on the k-shortest
simple paths algorithm. Thus, it is not available if ``simple=False``.
simple paths algorithm. Thus, it is not available if ``simple=False`` or
``rooted=True`` or ``starting_vertices`` is not ``None``.

OUTPUT: iterator

Expand Down Expand Up @@ -573,15 +573,24 @@ def all_cycles_iterator(self, starting_vertices=None, simple=False,
[0, 1, 2, 0]
[2, 3, 4, 5, 2]

The algorithm ``'B'`` is available only when ``simple=True``::
The algorithm ``'B'`` is unavailable when ``simple=False`` or ``rooted=True``
or ``starting_vertices is not None``::

sage: g = DiGraph()
sage: g.add_edges([('a', 'b', 1), ('b', 'a', 1)])
sage: next(g.all_cycles_iterator(algorithm='B', simple=False))
....:
Traceback (most recent call last):
...
ValueError: The algorithm 'B' is available only when simple=True.
ValueError: The algorithm 'B' is unavailable when simple=False.
sage: next(g.all_cycles_iterator(algorithm='B', simple=True, rooted=True))
Traceback (most recent call last):
...
ValueError: The algorithm 'B' is unavailable when rooted=True.
sage: next(g.all_cycles_iterator(algorithm='B', simple=True, starting_vertices=['a']))
Traceback (most recent call last):
...
ValueError: The algorithm 'B' is unavailable when starting_vertices is not None.

The algorithm ``'A'`` works for undirected graphs as well. Specifically, each cycle is
enumerated exactly once, meaning a cycle and its reverse are not listed separately::
Expand All @@ -591,12 +600,17 @@ def all_cycles_iterator(self, starting_vertices=None, simple=False,
....: print(cycle)
[0, 1, 2, 0]
"""
if algorithm == 'B':
if not simple:
raise ValueError("The algorithm 'B' is unavailable when simple=False.")
if starting_vertices:
raise ValueError("The algorithm 'B' is unavailable when starting_vertices is not None.")
if rooted:
raise ValueError("The algorithm 'B' is unavailable when rooted=True.")

if starting_vertices is None:
starting_vertices = self

if algorithm == 'B' and not simple:
raise ValueError("The algorithm 'B' is available only when simple=True.")

by_weight, weight_function = self._get_weight_function(by_weight=by_weight,
weight_function=weight_function,
check_weight=check_weight)
Expand Down Expand Up @@ -700,7 +714,7 @@ def all_simple_cycles(self, starting_vertices=None, rooted=False,
max_length=None, trivial=False,
weight_function=None, by_weight=False,
check_weight=True, report_weight=False,
algorithm='A'):
algorithm='B'):
r"""
Return a list of all simple cycles of ``self``. The cycles are
enumerated in increasing length order. Each edge must have a
Expand Down Expand Up @@ -741,7 +755,7 @@ def all_simple_cycles(self, starting_vertices=None, rooted=False,
a cycle is returned. Otherwise a tuple of cycle length and cycle is
returned.

- ``algorithm`` -- string (default: ``'A'``); the algorithm used to
- ``algorithm`` -- string (default: ``'B'``); the algorithm used to
enumerate the cycles.

- The algorithm ``'A'`` holds cycle iterators starting with each vertex,
Expand Down Expand Up @@ -773,20 +787,20 @@ def all_simple_cycles(self, starting_vertices=None, rooted=False,
sage: g.all_simple_cycles(max_length=6)
[[0, 1, 0], [0, 4, 0], [0, 5, 0], [1, 2, 1], [1, 6, 1], [2, 3, 2],
[2, 7, 2], [3, 4, 3], [3, 8, 3], [4, 9, 4], [5, 7, 5], [5, 8, 5],
[6, 8, 6], [6, 9, 6], [7, 9, 7], [0, 1, 2, 3, 4, 0],
[0, 1, 2, 7, 5, 0], [0, 1, 6, 8, 5, 0], [0, 1, 6, 9, 4, 0],
[0, 4, 3, 2, 1, 0], [0, 4, 3, 8, 5, 0], [0, 4, 9, 6, 1, 0],
[0, 4, 9, 7, 5, 0], [0, 5, 7, 2, 1, 0], [0, 5, 7, 9, 4, 0],
[0, 5, 8, 3, 4, 0], [0, 5, 8, 6, 1, 0], [1, 2, 3, 8, 6, 1],
[1, 2, 7, 9, 6, 1], [1, 6, 8, 3, 2, 1], [1, 6, 9, 7, 2, 1],
[2, 3, 4, 9, 7, 2], [2, 3, 8, 5, 7, 2], [2, 7, 5, 8, 3, 2],
[2, 7, 9, 4, 3, 2], [3, 4, 9, 6, 8, 3], [3, 8, 6, 9, 4, 3],
[6, 8, 6], [6, 9, 6], [7, 9, 7], [0, 1, 6, 8, 5, 0],
[0, 1, 6, 9, 4, 0], [0, 1, 2, 7, 5, 0], [0, 1, 2, 3, 4, 0],
[0, 4, 9, 7, 5, 0], [0, 4, 9, 6, 1, 0], [0, 4, 3, 8, 5, 0],
[0, 4, 3, 2, 1, 0], [0, 5, 8, 6, 1, 0], [0, 5, 8, 3, 4, 0],
[0, 5, 7, 2, 1, 0], [0, 5, 7, 9, 4, 0], [1, 2, 7, 9, 6, 1],
[1, 2, 3, 8, 6, 1], [1, 6, 9, 7, 2, 1], [1, 6, 8, 3, 2, 1],
[2, 3, 8, 5, 7, 2], [2, 3, 4, 9, 7, 2], [2, 7, 9, 4, 3, 2],
[2, 7, 5, 8, 3, 2], [3, 4, 9, 6, 8, 3], [3, 8, 6, 9, 4, 3],
[5, 7, 9, 6, 8, 5], [5, 8, 6, 9, 7, 5], [0, 1, 2, 3, 8, 5, 0],
[0, 1, 2, 7, 9, 4, 0], [0, 1, 6, 8, 3, 4, 0],
[0, 1, 6, 9, 7, 5, 0], [0, 4, 3, 2, 7, 5, 0],
[0, 1, 2, 7, 9, 4, 0], [0, 1, 6, 9, 7, 5, 0],
[0, 1, 6, 8, 3, 4, 0], [0, 4, 3, 2, 7, 5, 0],
[0, 4, 3, 8, 6, 1, 0], [0, 4, 9, 6, 8, 5, 0],
[0, 4, 9, 7, 2, 1, 0], [0, 5, 7, 2, 3, 4, 0],
[0, 5, 7, 9, 6, 1, 0], [0, 5, 8, 3, 2, 1, 0],
[0, 4, 9, 7, 2, 1, 0], [0, 5, 7, 9, 6, 1, 0],
[0, 5, 7, 2, 3, 4, 0], [0, 5, 8, 3, 2, 1, 0],
[0, 5, 8, 6, 9, 4, 0], [1, 2, 3, 4, 9, 6, 1],
[1, 2, 7, 5, 8, 6, 1], [1, 6, 8, 5, 7, 2, 1],
[1, 6, 9, 4, 3, 2, 1], [2, 3, 8, 6, 9, 7, 2],
Expand All @@ -798,8 +812,8 @@ def all_simple_cycles(self, starting_vertices=None, rooted=False,
sage: g = graphs.CompleteGraph(4).to_directed()
sage: g.all_simple_cycles()
[[0, 1, 0], [0, 2, 0], [0, 3, 0], [1, 2, 1], [1, 3, 1], [2, 3, 2],
[0, 1, 2, 0], [0, 1, 3, 0], [0, 2, 1, 0], [0, 2, 3, 0],
[0, 3, 1, 0], [0, 3, 2, 0], [1, 2, 3, 1], [1, 3, 2, 1],
[0, 1, 3, 0], [0, 1, 2, 0], [0, 2, 3, 0], [0, 2, 1, 0],
[0, 3, 2, 0], [0, 3, 1, 0], [1, 2, 3, 1], [1, 3, 2, 1],
[0, 1, 2, 3, 0], [0, 1, 3, 2, 0], [0, 2, 1, 3, 0],
[0, 2, 3, 1, 0], [0, 3, 1, 2, 0], [0, 3, 2, 1, 0]]

Expand All @@ -810,41 +824,39 @@ def all_simple_cycles(self, starting_vertices=None, rooted=False,
sage: g = graphs.CompleteGraph(20).to_directed()
sage: g.all_simple_cycles(max_length=2)
[[0, 1, 0], [0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], [0, 7, 0],
[0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 0], [0, 12, 0], [0, 13, 0],
[0, 14, 0], [0, 15, 0], [0, 16, 0], [0, 17, 0], [0, 18, 0], [0, 19, 0],
[1, 2, 1], [1, 3, 1], [1, 4, 1], [1, 5, 1], [1, 6, 1], [1, 7, 1], [1, 8, 1],
[1, 9, 1], [1, 10, 1], [1, 11, 1], [1, 12, 1], [1, 13, 1], [1, 14, 1],
[1, 15, 1], [1, 16, 1], [1, 17, 1], [1, 18, 1], [1, 19, 1], [2, 3, 2],
[2, 4, 2], [2, 5, 2], [2, 6, 2], [2, 7, 2], [2, 8, 2], [2, 9, 2], [2, 10, 2],
[2, 11, 2], [2, 12, 2], [2, 13, 2], [2, 14, 2], [2, 15, 2], [2, 16, 2],
[2, 17, 2], [2, 18, 2], [2, 19, 2], [3, 4, 3], [3, 5, 3], [3, 6, 3],
[3, 7, 3], [3, 8, 3], [3, 9, 3], [3, 10, 3], [3, 11, 3], [3, 12, 3],
[3, 13, 3], [3, 14, 3], [3, 15, 3], [3, 16, 3], [3, 17, 3], [3, 18, 3],
[3, 19, 3], [4, 5, 4], [4, 6, 4], [4, 7, 4], [4, 8, 4], [4, 9, 4], [4, 10, 4],
[4, 11, 4], [4, 12, 4], [4, 13, 4], [4, 14, 4], [4, 15, 4], [4, 16, 4],
[4, 17, 4], [4, 18, 4], [4, 19, 4], [5, 6, 5], [5, 7, 5], [5, 8, 5],
[5, 9, 5], [5, 10, 5], [5, 11, 5], [5, 12, 5], [5, 13, 5], [5, 14, 5],
[5, 15, 5], [5, 16, 5], [5, 17, 5], [5, 18, 5], [5, 19, 5], [6, 7, 6],
[6, 8, 6], [6, 9, 6], [6, 10, 6], [6, 11, 6], [6, 12, 6], [6, 13, 6],
[6, 14, 6], [6, 15, 6], [6, 16, 6], [6, 17, 6], [6, 18, 6], [6, 19, 6],
[7, 8, 7], [7, 9, 7], [7, 10, 7], [7, 11, 7], [7, 12, 7], [7, 13, 7],
[7, 14, 7], [7, 15, 7], [7, 16, 7], [7, 17, 7], [7, 18, 7], [7, 19, 7],
[8, 9, 8], [8, 10, 8], [8, 11, 8], [8, 12, 8], [8, 13, 8], [8, 14, 8],
[8, 15, 8], [8, 16, 8], [8, 17, 8], [8, 18, 8], [8, 19, 8], [9, 10, 9],
[9, 11, 9], [9, 12, 9], [9, 13, 9], [9, 14, 9], [9, 15, 9], [9, 16, 9],
[9, 17, 9], [9, 18, 9], [9, 19, 9], [10, 11, 10], [10, 12, 10], [10, 13, 10],
[10, 14, 10], [10, 15, 10], [10, 16, 10], [10, 17, 10], [10, 18, 10],
[10, 19, 10], [11, 12, 11], [11, 13, 11], [11, 14, 11], [11, 15, 11],
[11, 16, 11], [11, 17, 11], [11, 18, 11], [11, 19, 11], [12, 13, 12],
[12, 14, 12], [12, 15, 12], [12, 16, 12], [12, 17, 12], [12, 18, 12],
[12, 19, 12], [13, 14, 13], [13, 15, 13], [13, 16, 13], [13, 17, 13],
[13, 18, 13], [13, 19, 13], [14, 15, 14], [14, 16, 14], [14, 17, 14],
[14, 18, 14], [14, 19, 14], [15, 16, 15], [15, 17, 15], [15, 18, 15],
[15, 19, 15], [16, 17, 16], [16, 18, 16], [16, 19, 16], [17, 18, 17],
[17, 19, 17], [18, 19, 18]]
[0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 0], [0, 12, 0], [0, 13, 0], [0, 14, 0],
[0, 15, 0], [0, 16, 0], [0, 17, 0], [0, 18, 0], [0, 19, 0], [1, 2, 1], [1, 3, 1],
[1, 4, 1], [1, 5, 1], [1, 6, 1], [1, 7, 1], [1, 8, 1], [1, 9, 1], [2, 3, 2],
[2, 4, 2], [2, 5, 2], [2, 6, 2], [2, 7, 2], [2, 8, 2], [2, 9, 2], [3, 4, 3],
[3, 5, 3], [3, 6, 3], [3, 7, 3], [3, 8, 3], [3, 9, 3], [4, 5, 4], [4, 6, 4],
[4, 7, 4], [4, 8, 4], [4, 9, 4], [5, 6, 5], [5, 7, 5], [5, 8, 5], [5, 9, 5],
[6, 7, 6], [6, 8, 6], [6, 9, 6], [7, 8, 7], [7, 9, 7], [8, 9, 8], [10, 1, 10],
[10, 2, 10], [10, 3, 10], [10, 4, 10], [10, 5, 10], [10, 6, 10], [10, 7, 10],
[10, 8, 10], [10, 9, 10], [11, 1, 11], [11, 2, 11], [11, 3, 11], [11, 4, 11],
[11, 5, 11], [11, 6, 11], [11, 7, 11], [11, 8, 11], [11, 9, 11], [11, 10, 11],
[12, 1, 12], [12, 2, 12], [12, 3, 12], [12, 4, 12], [12, 5, 12], [12, 6, 12],
[12, 7, 12], [12, 8, 12], [12, 9, 12], [12, 10, 12], [12, 11, 12], [13, 1, 13],
[13, 2, 13], [13, 3, 13], [13, 4, 13], [13, 5, 13], [13, 6, 13], [13, 7, 13],
[13, 8, 13], [13, 9, 13], [13, 10, 13], [13, 11, 13], [13, 12, 13], [14, 1, 14],
[14, 2, 14], [14, 3, 14], [14, 4, 14], [14, 5, 14], [14, 6, 14], [14, 7, 14],
[14, 8, 14], [14, 9, 14], [14, 10, 14], [14, 11, 14], [14, 12, 14], [14, 13, 14],
[15, 1, 15], [15, 2, 15], [15, 3, 15], [15, 4, 15], [15, 5, 15], [15, 6, 15],
[15, 7, 15], [15, 8, 15], [15, 9, 15], [15, 10, 15], [15, 11, 15], [15, 12, 15],
[15, 13, 15], [15, 14, 15], [16, 1, 16], [16, 2, 16], [16, 3, 16], [16, 4, 16],
[16, 5, 16], [16, 6, 16], [16, 7, 16], [16, 8, 16], [16, 9, 16], [16, 10, 16],
[16, 11, 16], [16, 12, 16], [16, 13, 16], [16, 14, 16], [16, 15, 16], [17, 1, 17],
[17, 2, 17], [17, 3, 17], [17, 4, 17], [17, 5, 17], [17, 6, 17], [17, 7, 17],
[17, 8, 17], [17, 9, 17], [17, 10, 17], [17, 11, 17], [17, 12, 17], [17, 13, 17],
[17, 14, 17], [17, 15, 17], [17, 16, 17], [18, 1, 18], [18, 2, 18], [18, 3, 18],
[18, 4, 18], [18, 5, 18], [18, 6, 18], [18, 7, 18], [18, 8, 18], [18, 9, 18],
[18, 10, 18], [18, 11, 18], [18, 12, 18], [18, 13, 18], [18, 14, 18], [18, 15, 18],
[18, 16, 18], [18, 17, 18], [19, 1, 19], [19, 2, 19], [19, 3, 19], [19, 4, 19],
[19, 5, 19], [19, 6, 19], [19, 7, 19], [19, 8, 19], [19, 9, 19], [19, 10, 19],
[19, 11, 19], [19, 12, 19], [19, 13, 19], [19, 14, 19], [19, 15, 19], [19, 16, 19],
[19, 17, 19], [19, 18, 19]]

sage: g = graphs.CompleteGraph(20).to_directed()
sage: g.all_simple_cycles(max_length=2, starting_vertices=[0])
sage: g.all_simple_cycles(max_length=2, starting_vertices=[0], algorithm='A')
[[0, 1, 0], [0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0],
[0, 6, 0], [0, 7, 0], [0, 8, 0], [0, 9, 0], [0, 10, 0],
[0, 11, 0], [0, 12, 0], [0, 13, 0], [0, 14, 0], [0, 15, 0],
Expand All @@ -854,9 +866,9 @@ def all_simple_cycles(self, starting_vertices=None, rooted=False,
vertices (compare the following examples)::

sage: g = graphs.CompleteGraph(4).to_directed()
sage: g.all_simple_cycles(max_length=2, rooted=False)
sage: g.all_simple_cycles(max_length=2, rooted=False, algorithm='A')
[[0, 1, 0], [0, 2, 0], [0, 3, 0], [1, 2, 1], [1, 3, 1], [2, 3, 2]]
sage: g.all_simple_cycles(max_length=2, rooted=True)
sage: g.all_simple_cycles(max_length=2, rooted=True, algorithm='A')
[[0, 1, 0], [0, 2, 0], [0, 3, 0], [1, 0, 1], [1, 2, 1], [1, 3, 1],
[2, 0, 2], [2, 1, 2], [2, 3, 2], [3, 0, 3], [3, 1, 3], [3, 2, 3]]

Expand All @@ -865,12 +877,12 @@ def all_simple_cycles(self, starting_vertices=None, rooted=False,
sage: cycles = g.all_simple_cycles(weight_function=lambda e:e[0]+e[1],
....: by_weight=True, report_weight=True)
sage: cycles
[(2, [0, 1, 0]), (4, [0, 2, 0]), (6, [0, 1, 2, 0]), (6, [0, 2, 1, 0]),
(6, [0, 3, 0]), (6, [1, 2, 1]), (8, [0, 1, 3, 0]), (8, [0, 3, 1, 0]),
(8, [1, 3, 1]), (10, [0, 2, 3, 0]), (10, [0, 3, 2, 0]), (10, [2, 3, 2]),
(12, [0, 1, 2, 3, 0]), (12, [0, 1, 3, 2, 0]), (12, [0, 2, 1, 3, 0]),
(12, [0, 2, 3, 1, 0]), (12, [0, 3, 1, 2, 0]), (12, [0, 3, 2, 1, 0]),
(12, [1, 2, 3, 1]), (12, [1, 3, 2, 1])]
[(2.0, [0, 1, 0]), (4.0, [0, 2, 0]), (6.0, [0, 1, 2, 0]), (6.0, [0, 2, 1, 0]),
(6.0, [0, 3, 0]), (6.0, [1, 2, 1]), (8.0, [0, 1, 3, 0]), (8.0, [0, 3, 1, 0]),
(8.0, [1, 3, 1]), (10.0, [0, 2, 3, 0]), (10.0, [0, 3, 2, 0]), (10.0, [2, 3, 2]),
(12.0, [0, 1, 3, 2, 0]), (12.0, [0, 1, 2, 3, 0]), (12.0, [0, 2, 3, 1, 0]),
(12.0, [0, 2, 1, 3, 0]), (12.0, [0, 3, 2, 1, 0]), (12.0, [0, 3, 1, 2, 0]),
(12.0, [1, 2, 3, 1]), (12.0, [1, 3, 2, 1])]

The algorithm ``'B'`` can be used::

Expand Down
Loading
Loading