passagemath-graphs 10.5.43__cp312-cp312-macosx_14_0_arm64.whl → 10.6.1rc1__cp312-cp312-macosx_14_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc1.dist-info}/METADATA +5 -6
- {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc1.dist-info}/RECORD +132 -130
- sage/combinat/abstract_tree.py +188 -17
- sage/combinat/cluster_algebra_quiver/interact.py +1 -2
- sage/combinat/cluster_algebra_quiver/mutation_type.py +518 -519
- sage/combinat/cluster_algebra_quiver/quiver.py +233 -205
- sage/combinat/designs/covering_design.py +2 -6
- sage/combinat/designs/database.py +11 -10
- sage/combinat/designs/designs_pyx.cpython-312-darwin.so +0 -0
- sage/combinat/designs/designs_pyx.pyx +2 -2
- sage/combinat/designs/evenly_distributed_sets.cpython-312-darwin.so +0 -0
- sage/combinat/designs/evenly_distributed_sets.pyx +4 -4
- sage/combinat/designs/gen_quadrangles_with_spread.cpython-312-darwin.so +0 -0
- sage/combinat/designs/latin_squares.py +53 -20
- sage/combinat/designs/orthogonal_arrays.py +2 -1
- sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-312-darwin.so +0 -0
- sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +22 -21
- sage/combinat/designs/resolvable_bibd.py +191 -157
- sage/combinat/designs/subhypergraph_search.cpython-312-darwin.so +0 -0
- sage/combinat/designs/subhypergraph_search.pyx +4 -4
- sage/combinat/designs/twographs.py +2 -2
- sage/combinat/finite_state_machine.py +6 -6
- sage/combinat/posets/bubble_shuffle.py +247 -0
- sage/combinat/posets/d_complete.py +3 -3
- sage/combinat/posets/elements.py +3 -3
- sage/combinat/posets/hasse_cython.cpython-312-darwin.so +0 -0
- sage/combinat/posets/hasse_cython.pyx +1 -1
- sage/combinat/posets/hasse_diagram.py +16 -22
- sage/combinat/posets/hochschild_lattice.py +158 -0
- sage/combinat/posets/incidence_algebras.py +14 -16
- sage/combinat/posets/lattices.py +51 -53
- sage/combinat/posets/linear_extension_iterator.cpython-312-darwin.so +0 -0
- sage/combinat/posets/linear_extensions.py +10 -12
- sage/combinat/posets/moebius_algebra.py +4 -4
- sage/combinat/posets/poset_examples.py +70 -23
- sage/combinat/posets/posets.py +294 -103
- sage/databases/knotinfo_db.py +2 -1
- sage/graphs/asteroidal_triples.cpython-312-darwin.so +0 -0
- sage/graphs/asteroidal_triples.pyx +24 -3
- sage/graphs/base/boost_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/boost_graph.pxd +3 -3
- sage/graphs/base/c_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/c_graph.pyx +1 -1
- sage/graphs/base/dense_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/dense_graph.pxd +5 -3
- sage/graphs/base/dense_graph.pyx +44 -0
- sage/graphs/base/graph_backends.cpython-312-darwin.so +0 -0
- sage/graphs/base/sparse_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/static_dense_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/static_sparse_backend.cpython-312-darwin.so +0 -0
- sage/graphs/base/static_sparse_backend.pyx +8 -5
- sage/graphs/base/static_sparse_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/static_sparse_graph.pyx +86 -15
- sage/graphs/bipartite_graph.py +59 -36
- sage/graphs/centrality.cpython-312-darwin.so +0 -0
- sage/graphs/centrality.pyx +82 -9
- sage/graphs/cographs.py +1 -1
- sage/graphs/comparability.cpython-312-darwin.so +0 -0
- sage/graphs/comparability.pyx +64 -26
- sage/graphs/connectivity.cpython-312-darwin.so +0 -0
- sage/graphs/convexity_properties.cpython-312-darwin.so +0 -0
- sage/graphs/convexity_properties.pyx +52 -9
- sage/graphs/digraph.py +439 -95
- sage/graphs/digraph_generators.py +174 -102
- sage/graphs/distances_all_pairs.cpython-312-darwin.so +0 -0
- sage/graphs/dot2tex_utils.py +1 -1
- sage/graphs/edge_connectivity.cpython-312-darwin.so +0 -0
- sage/graphs/generators/basic.py +1 -1
- sage/graphs/generators/distance_regular.cpython-312-darwin.so +0 -0
- sage/graphs/generators/distance_regular.pyx +1 -1
- sage/graphs/generators/families.py +37 -27
- sage/graphs/generators/random.py +2 -2
- sage/graphs/generators/smallgraphs.py +3 -3
- sage/graphs/generic_graph.py +558 -86
- sage/graphs/generic_graph_pyx.cpython-312-darwin.so +0 -0
- sage/graphs/generic_graph_pyx.pyx +58 -11
- sage/graphs/genus.cpython-312-darwin.so +0 -0
- sage/graphs/genus.pyx +3 -4
- sage/graphs/graph.py +291 -8
- sage/graphs/graph_coloring.cpython-312-darwin.so +0 -0
- sage/graphs/graph_database.py +67 -12
- sage/graphs/graph_decompositions/bandwidth.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.pyx +24 -3
- sage/graphs/graph_decompositions/cutwidth.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.pyx +1 -1
- sage/graphs/graph_decompositions/graph_products.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/graph_products.pyx +67 -21
- sage/graphs/graph_decompositions/modular_decomposition.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.pyx +34 -8
- sage/graphs/graph_decompositions/tree_decomposition.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/vertex_separation.cpython-312-darwin.so +0 -0
- sage/graphs/graph_generators.py +45 -32
- sage/graphs/graph_generators_pyx.cpython-312-darwin.so +0 -0
- sage/graphs/graph_generators_pyx.pyx +15 -15
- sage/graphs/graph_latex.py +1 -1
- sage/graphs/graph_list.py +52 -9
- sage/graphs/graph_plot.py +7 -0
- sage/graphs/hyperbolicity.cpython-312-darwin.so +0 -0
- sage/graphs/hyperbolicity.pyx +2 -0
- sage/graphs/independent_sets.cpython-312-darwin.so +0 -0
- sage/graphs/isoperimetric_inequalities.cpython-312-darwin.so +0 -0
- sage/graphs/isoperimetric_inequalities.pyx +42 -6
- sage/graphs/line_graph.cpython-312-darwin.so +0 -0
- sage/graphs/line_graph.pyx +153 -37
- sage/graphs/matching_covered_graph.py +84 -60
- sage/graphs/orientations.py +3 -18
- sage/graphs/path_enumeration.cpython-312-darwin.so +0 -0
- sage/graphs/path_enumeration.pyx +2 -2
- sage/graphs/spanning_tree.cpython-312-darwin.so +0 -0
- sage/graphs/strongly_regular_db.cpython-312-darwin.so +0 -0
- sage/graphs/strongly_regular_db.pyx +15 -15
- sage/graphs/traversals.cpython-312-darwin.so +0 -0
- sage/graphs/traversals.pyx +13 -12
- sage/graphs/trees.cpython-312-darwin.so +0 -0
- sage/graphs/tutte_polynomial.py +1 -1
- sage/graphs/views.cpython-312-darwin.so +0 -0
- sage/graphs/weakly_chordal.cpython-312-darwin.so +0 -0
- sage/graphs/weakly_chordal.pyx +50 -8
- sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-312-darwin.so +0 -0
- sage/knots/free_knotinfo_monoid.py +3 -3
- sage/knots/knotinfo.py +102 -82
- sage/knots/link.py +72 -39
- sage/topology/cubical_complex.py +4 -5
- sage/topology/delta_complex.py +4 -4
- sage/topology/simplicial_complex.py +0 -1
- sage/topology/simplicial_complex_catalog.py +6 -0
- sage/topology/simplicial_complex_examples.py +4 -16
- {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc1.dist-info}/WHEEL +0 -0
- {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc1.dist-info}/top_level.txt +0 -0
sage/graphs/digraph.py
CHANGED
@@ -1088,8 +1088,8 @@ class DiGraph(GenericGraph):
|
|
1088
1088
|
G.add_vertices(self.vertex_iterator())
|
1089
1089
|
G.set_vertices(self.get_vertices())
|
1090
1090
|
G.add_edges(self.edge_iterator())
|
1091
|
-
|
1092
|
-
|
1091
|
+
G._copy_attribute_from(self, '_assoc')
|
1092
|
+
G._copy_attribute_from(self, '_embedding')
|
1093
1093
|
G._weighted = self._weighted
|
1094
1094
|
|
1095
1095
|
if data_structure == "static_sparse":
|
@@ -1851,20 +1851,9 @@ class DiGraph(GenericGraph):
|
|
1851
1851
|
name = ''
|
1852
1852
|
H.name("Reverse of (%s)" % name)
|
1853
1853
|
|
1854
|
-
|
1855
|
-
|
1856
|
-
|
1857
|
-
copy_attr = {}
|
1858
|
-
old_attr = getattr(self, attr)
|
1859
|
-
if isinstance(old_attr, dict):
|
1860
|
-
for v, value in old_attr.items():
|
1861
|
-
try:
|
1862
|
-
copy_attr[v] = value.copy()
|
1863
|
-
except AttributeError:
|
1864
|
-
copy_attr[v] = copy(value)
|
1865
|
-
setattr(H, attr, copy_attr)
|
1866
|
-
else:
|
1867
|
-
setattr(H, attr, copy(old_attr))
|
1854
|
+
# Copy attributes '_assoc' and '_embedding' if set
|
1855
|
+
H._copy_attribute_from(self, '_assoc')
|
1856
|
+
H._copy_attribute_from(self, '_embedding')
|
1868
1857
|
|
1869
1858
|
if immutable or (immutable is None and self.is_immutable()):
|
1870
1859
|
return H.copy(immutable=True)
|
@@ -2789,10 +2778,12 @@ class DiGraph(GenericGraph):
|
|
2789
2778
|
|
2790
2779
|
def _all_cycles_iterator_vertex(self, vertex, starting_vertices=None, simple=False,
|
2791
2780
|
rooted=False, max_length=None, trivial=False,
|
2792
|
-
remove_acyclic_edges=True
|
2781
|
+
remove_acyclic_edges=True,
|
2782
|
+
weight_function=None, by_weight=False,
|
2783
|
+
check_weight=True, report_weight=False):
|
2793
2784
|
r"""
|
2794
2785
|
Return an iterator over the cycles of ``self`` starting with the given
|
2795
|
-
vertex.
|
2786
|
+
vertex in increasing length order. Each edge must have a positive weight.
|
2796
2787
|
|
2797
2788
|
INPUT:
|
2798
2789
|
|
@@ -2823,6 +2814,22 @@ class DiGraph(GenericGraph):
|
|
2823
2814
|
acyclic edges must be removed from the graph. Used to avoid
|
2824
2815
|
recomputing it for each vertex
|
2825
2816
|
|
2817
|
+
- ``weight_function`` -- function (default: ``None``); a function that
|
2818
|
+
takes as input an edge ``(u, v, l)`` and outputs its weight. If not
|
2819
|
+
``None``, ``by_weight`` is automatically set to ``True``. If ``None``
|
2820
|
+
and ``by_weight`` is ``True``, we use the edge label ``l`` as a
|
2821
|
+
weight.
|
2822
|
+
|
2823
|
+
- ``by_weight`` -- boolean (default: ``False``); if ``True``, the edges
|
2824
|
+
in the graph are weighted, otherwise all edges have weight 1
|
2825
|
+
|
2826
|
+
- ``check_weight`` -- boolean (default: ``True``); whether to check that
|
2827
|
+
the ``weight_function`` outputs a number for each edge
|
2828
|
+
|
2829
|
+
- ``report_weight`` -- boolean (default: ``False``); if ``False``, just
|
2830
|
+
a cycle is returned. Otherwise a tuple of cycle length and cycle is
|
2831
|
+
returned.
|
2832
|
+
|
2826
2833
|
OUTPUT: iterator
|
2827
2834
|
|
2828
2835
|
EXAMPLES::
|
@@ -2870,12 +2877,41 @@ class DiGraph(GenericGraph):
|
|
2870
2877
|
sage: it = g._all_cycles_iterator_vertex('d', simple=True, trivial=True)
|
2871
2878
|
sage: list(it)
|
2872
2879
|
[['d'], ['d', 'c', 'd']]
|
2880
|
+
|
2881
|
+
A cycle is enumerated in increasing length order for a weighted graph::
|
2882
|
+
|
2883
|
+
sage: g = DiGraph()
|
2884
|
+
sage: g.add_edges([('a', 'b', 2), ('a', 'e', 2), ('b', 'a', 1), ('b', 'c', 1),
|
2885
|
+
....: ('c', 'd', 2), ('d', 'b', 1), ('e', 'a', 2)])
|
2886
|
+
sage: it = g._all_cycles_iterator_vertex('a', simple=False, max_length=None,
|
2887
|
+
....: by_weight=True, report_weight=True)
|
2888
|
+
sage: for i in range(7): print(next(it))
|
2889
|
+
(3, ['a', 'b', 'a'])
|
2890
|
+
(4, ['a', 'e', 'a'])
|
2891
|
+
(6, ['a', 'b', 'a', 'b', 'a'])
|
2892
|
+
(7, ['a', 'b', 'a', 'e', 'a'])
|
2893
|
+
(7, ['a', 'b', 'c', 'd', 'b', 'a'])
|
2894
|
+
(7, ['a', 'e', 'a', 'b', 'a'])
|
2895
|
+
(8, ['a', 'e', 'a', 'e', 'a'])
|
2896
|
+
|
2897
|
+
Each edge must have a positive weight::
|
2898
|
+
|
2899
|
+
sage: g = DiGraph()
|
2900
|
+
sage: g.add_edges([('a', 'b', -2), ('b', 'a', 1)])
|
2901
|
+
sage: next(g._all_cycles_iterator_vertex('a', simple=False, max_length=None,
|
2902
|
+
....: by_weight=True, report_weight=True))
|
2903
|
+
Traceback (most recent call last):
|
2904
|
+
...
|
2905
|
+
ValueError: negative weight is not allowed
|
2873
2906
|
"""
|
2874
2907
|
if starting_vertices is None:
|
2875
2908
|
starting_vertices = [vertex]
|
2876
2909
|
# First enumerate the empty cycle
|
2877
2910
|
if trivial:
|
2878
|
-
|
2911
|
+
if report_weight:
|
2912
|
+
yield (0, [vertex])
|
2913
|
+
else:
|
2914
|
+
yield [vertex]
|
2879
2915
|
# First we remove vertices and edges that are not part of any cycle
|
2880
2916
|
if remove_acyclic_edges:
|
2881
2917
|
sccs = self.strongly_connected_components()
|
@@ -2887,30 +2923,175 @@ class DiGraph(GenericGraph):
|
|
2887
2923
|
h.delete_edges((u, v) for u, v in h.edge_iterator(labels=False) if d[u] != d[v])
|
2888
2924
|
else:
|
2889
2925
|
h = self
|
2890
|
-
|
2926
|
+
|
2927
|
+
by_weight, weight_function = self._get_weight_function(by_weight=by_weight,
|
2928
|
+
weight_function=weight_function,
|
2929
|
+
check_weight=check_weight)
|
2930
|
+
if by_weight:
|
2931
|
+
for e in h.edge_iterator():
|
2932
|
+
if weight_function(e) < 0:
|
2933
|
+
raise ValueError("negative weight is not allowed")
|
2934
|
+
|
2935
|
+
from heapq import heappop, heappush
|
2936
|
+
heap_queue = [(0, [vertex])]
|
2891
2937
|
if max_length is None:
|
2892
2938
|
from sage.rings.infinity import Infinity
|
2893
2939
|
max_length = Infinity
|
2894
|
-
while
|
2895
|
-
path =
|
2940
|
+
while heap_queue:
|
2941
|
+
length, path = heappop(heap_queue)
|
2896
2942
|
# Checks if a cycle has been found
|
2897
2943
|
if len(path) > 1 and path[0] == path[-1]:
|
2898
|
-
|
2899
|
-
|
2900
|
-
|
2944
|
+
if report_weight:
|
2945
|
+
yield (length, path)
|
2946
|
+
else:
|
2947
|
+
yield path
|
2948
|
+
# If simple is set to True, only simple cycles are
|
2901
2949
|
# allowed, Then it discards the current path
|
2902
|
-
if
|
2903
|
-
for
|
2950
|
+
if (not simple or path.count(path[-1]) == 1):
|
2951
|
+
for e in h.outgoing_edge_iterator(path[-1]):
|
2952
|
+
neighbor = e[1]
|
2953
|
+
# Makes sure that the current cycle is not too long.
|
2904
2954
|
# If cycles are not rooted, makes sure to keep only the
|
2905
2955
|
# minimum cycle according to the lexicographic order
|
2906
|
-
if
|
2907
|
-
|
2956
|
+
if length + weight_function(e) <= max_length and \
|
2957
|
+
(rooted or neighbor not in starting_vertices or path[0] <= neighbor):
|
2958
|
+
heappush(heap_queue, (length + weight_function(e), path + [neighbor]))
|
2959
|
+
|
2960
|
+
def _all_simple_cycles_iterator_edge(self, edge, max_length=None,
|
2961
|
+
remove_acyclic_edges=True,
|
2962
|
+
weight_function=None, by_weight=False,
|
2963
|
+
check_weight=True, report_weight=False):
|
2964
|
+
r"""
|
2965
|
+
Return an iterator over the **simple** cycles of ``self`` starting with the
|
2966
|
+
given edge in increasing length order. Each edge must have a positive weight.
|
2967
|
+
|
2968
|
+
INPUT:
|
2969
|
+
|
2970
|
+
- ``edge`` -- the starting edge of the cycle.
|
2971
|
+
|
2972
|
+
- ``max_length`` -- nonnegative integer (default: ``None``); the
|
2973
|
+
maximum length of the enumerated paths. If set to ``None``, then all
|
2974
|
+
lengths are allowed.
|
2975
|
+
|
2976
|
+
- ``remove_acyclic_edges`` -- boolean (default: ``True``); whether
|
2977
|
+
acyclic edges must be removed from the graph. Used to avoid
|
2978
|
+
recomputing it for each edge
|
2979
|
+
|
2980
|
+
- ``weight_function`` -- function (default: ``None``); a function that
|
2981
|
+
takes as input an edge ``(u, v, l)`` and outputs its weight. If not
|
2982
|
+
``None``, ``by_weight`` is automatically set to ``True``. If ``None``
|
2983
|
+
and ``by_weight`` is ``True``, we use the edge label ``l`` as a
|
2984
|
+
weight.
|
2985
|
+
|
2986
|
+
- ``by_weight`` -- boolean (default: ``False``); if ``True``, the edges
|
2987
|
+
in the graph are weighted, otherwise all edges have weight 1
|
2988
|
+
|
2989
|
+
- ``check_weight`` -- boolean (default: ``True``); whether to check that
|
2990
|
+
the ``weight_function`` outputs a number for each edge
|
2991
|
+
|
2992
|
+
- ``report_weight`` -- boolean (default: ``False``); if ``False``, just
|
2993
|
+
a cycle is returned. Otherwise a tuple of cycle length and cycle is
|
2994
|
+
returned.
|
2995
|
+
|
2996
|
+
OUTPUT: iterator
|
2997
|
+
|
2998
|
+
ALGORITHM:
|
2999
|
+
|
3000
|
+
Given an edge `uv`, this algorithm extracts k-shortest `vu`-path in `G-uv`
|
3001
|
+
in increasing length order by using k-shortest path algorithm. Thus, it
|
3002
|
+
extracts only simple cycles. See
|
3003
|
+
:math:`~sage.graphs.path_enumeration.shortest_simple_paths` for more
|
3004
|
+
information.
|
3005
|
+
|
3006
|
+
EXAMPLES:
|
3007
|
+
|
3008
|
+
sage: g = graphs.Grid2dGraph(2, 5).to_directed()
|
3009
|
+
sage: it = g._all_simple_cycles_iterator_edge(((0, 0), (0, 1), None), report_weight=True)
|
3010
|
+
sage: for i in range(5): print(next(it))
|
3011
|
+
(2, [(0, 0), (0, 1), (0, 0)])
|
3012
|
+
(4, [(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
|
3013
|
+
(6, [(0, 0), (0, 1), (0, 2), (1, 2), (1, 1), (1, 0), (0, 0)])
|
3014
|
+
(8, [(0, 0), (0, 1), (0, 2), (0, 3), (1, 3), (1, 2), (1, 1), (1, 0), (0, 0)])
|
3015
|
+
(10, [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 4), (1, 3), (1, 2), (1, 1), (1, 0), (0, 0)])
|
3016
|
+
|
3017
|
+
Each edge must have a positive weight::
|
3018
|
+
|
3019
|
+
sage: g = DiGraph()
|
3020
|
+
sage: g.add_edges([('a', 'b', -2), ('b', 'a', 1)])
|
3021
|
+
sage: next(g._all_simple_cycles_iterator_edge(('a', 'b', -2), max_length=None, by_weight=True))
|
3022
|
+
Traceback (most recent call last):
|
3023
|
+
...
|
3024
|
+
ValueError: negative weight is not allowed
|
3025
|
+
|
3026
|
+
TESTS:
|
3027
|
+
|
3028
|
+
A graph with a loop::
|
3029
|
+
|
3030
|
+
sage: g = DiGraph(loops=True)
|
3031
|
+
sage: g.add_edges([('a', 'b'), ('b', 'c'), ('c', 'a'), ('c', 'c')])
|
3032
|
+
sage: it = g._all_simple_cycles_iterator_edge(('a', 'b'), remove_acyclic_edges=True)
|
3033
|
+
sage: next(it)
|
3034
|
+
['a', 'b', 'c', 'a']
|
3035
|
+
sage: g = DiGraph(loops=True)
|
3036
|
+
sage: g.add_edges([('a', 'b'), ('b', 'c'), ('c', 'c')])
|
3037
|
+
sage: it = g._all_simple_cycles_iterator_edge(('c', 'c'), remove_acyclic_edges=True)
|
3038
|
+
sage: next(it)
|
3039
|
+
['c', 'c']
|
3040
|
+
"""
|
3041
|
+
# First we remove vertices and edges that are not part of any cycle
|
3042
|
+
if remove_acyclic_edges:
|
3043
|
+
h = None
|
3044
|
+
for component in self.strongly_connected_components_subgraphs():
|
3045
|
+
if component.has_edge(edge):
|
3046
|
+
h = component
|
3047
|
+
if h is None:
|
3048
|
+
# edge connects two strongly connected components, so
|
3049
|
+
# no simple cycle starting with edge exists.
|
3050
|
+
return
|
3051
|
+
else:
|
3052
|
+
h = copy(self)
|
3053
|
+
# delete edge
|
3054
|
+
h.delete_edge(edge)
|
3055
|
+
|
3056
|
+
by_weight, weight_function = self._get_weight_function(by_weight=by_weight,
|
3057
|
+
weight_function=weight_function,
|
3058
|
+
check_weight=check_weight)
|
3059
|
+
|
3060
|
+
if by_weight:
|
3061
|
+
for e in self.edge_iterator():
|
3062
|
+
if weight_function(e) < 0:
|
3063
|
+
raise ValueError("negative weight is not allowed")
|
3064
|
+
|
3065
|
+
it = h.shortest_simple_paths(source=edge[1], target=edge[0],
|
3066
|
+
weight_function=weight_function,
|
3067
|
+
by_weight=by_weight,
|
3068
|
+
check_weight=check_weight,
|
3069
|
+
algorithm='Feng',
|
3070
|
+
report_edges=False,
|
3071
|
+
report_weight=True)
|
3072
|
+
|
3073
|
+
edge_weight = weight_function(edge)
|
3074
|
+
|
3075
|
+
if max_length is None:
|
3076
|
+
from sage.rings.infinity import Infinity
|
3077
|
+
max_length = Infinity
|
3078
|
+
for length, path in it:
|
3079
|
+
if length + edge_weight > max_length:
|
3080
|
+
break
|
3081
|
+
|
3082
|
+
if report_weight:
|
3083
|
+
yield length + edge_weight, [edge[0]] + path
|
3084
|
+
else:
|
3085
|
+
yield [edge[0]] + path
|
2908
3086
|
|
2909
3087
|
def all_cycles_iterator(self, starting_vertices=None, simple=False,
|
2910
|
-
rooted=False, max_length=None, trivial=False
|
3088
|
+
rooted=False, max_length=None, trivial=False,
|
3089
|
+
weight_function=None, by_weight=False,
|
3090
|
+
check_weight=True, report_weight=False,
|
3091
|
+
algorithm='A'):
|
2911
3092
|
r"""
|
2912
3093
|
Return an iterator over all the cycles of ``self`` starting with one of
|
2913
|
-
the given vertices.
|
3094
|
+
the given vertices. Each edge must have a positive weight.
|
2914
3095
|
|
2915
3096
|
The cycles are enumerated in increasing length order.
|
2916
3097
|
|
@@ -2937,11 +3118,38 @@ class DiGraph(GenericGraph):
|
|
2937
3118
|
- ``trivial`` -- boolean (default: ``False``); if set to ``True``, then
|
2938
3119
|
the empty paths are also enumerated
|
2939
3120
|
|
3121
|
+
- ``weight_function`` -- function (default: ``None``); a function that
|
3122
|
+
takes as input an edge ``(u, v, l)`` and outputs its weight. If not
|
3123
|
+
``None``, ``by_weight`` is automatically set to ``True``. If ``None``
|
3124
|
+
and ``by_weight`` is ``True``, we use the edge label ``l`` as a
|
3125
|
+
weight.
|
3126
|
+
|
3127
|
+
- ``by_weight`` -- boolean (default: ``False``); if ``True``, the edges
|
3128
|
+
in the graph are weighted, otherwise all edges have weight 1
|
3129
|
+
|
3130
|
+
- ``check_weight`` -- boolean (default: ``True``); whether to check that
|
3131
|
+
the ``weight_function`` outputs a number for each edge
|
3132
|
+
|
3133
|
+
- ``report_weight`` -- boolean (default: ``False``); if ``False``, just
|
3134
|
+
a cycle is returned. Otherwise a tuple of cycle length and cycle is
|
3135
|
+
returned.
|
3136
|
+
|
3137
|
+
- ``algorithm`` -- string (default: ``'A'``); the algorithm used to
|
3138
|
+
enumerate the cycles.
|
3139
|
+
|
3140
|
+
- The algorithm ``'A'`` holds cycle iterators starting with each vertex,
|
3141
|
+
and output them in increasing length order.
|
3142
|
+
|
3143
|
+
- The algorithm ``'B'`` holds cycle iterators starting with each edge,
|
3144
|
+
and output them in increasing length order. It depends on the k-shortest
|
3145
|
+
simple paths algorithm. Thus, it is not available if ``simple=False``.
|
3146
|
+
|
2940
3147
|
OUTPUT: iterator
|
2941
3148
|
|
2942
3149
|
.. SEEALSO::
|
2943
3150
|
|
2944
3151
|
- :meth:`all_simple_cycles`
|
3152
|
+
- :meth:`~sage.graphs.path_enumeration.shortest_simple_paths`
|
2945
3153
|
|
2946
3154
|
AUTHOR:
|
2947
3155
|
|
@@ -3009,6 +3217,44 @@ class DiGraph(GenericGraph):
|
|
3009
3217
|
sage: g = digraphs.Circuit(4)
|
3010
3218
|
sage: list(g.all_cycles_iterator(simple=True))
|
3011
3219
|
[[0, 1, 2, 3, 0]]
|
3220
|
+
|
3221
|
+
A cycle is enumerated in increasing length order for a weighted graph::
|
3222
|
+
|
3223
|
+
sage: g = DiGraph()
|
3224
|
+
sage: g.add_edges([('a', 'b', 2), ('a', 'e', 2), ('b', 'a', 1), ('b', 'c', 1),
|
3225
|
+
....: ('c', 'd', 2), ('d', 'b', 1), ('e', 'a', 2)])
|
3226
|
+
sage: it = g.all_cycles_iterator(simple=False, max_length=None,
|
3227
|
+
....: by_weight=True, report_weight=True)
|
3228
|
+
sage: for i in range(9): print(next(it))
|
3229
|
+
(3, ['a', 'b', 'a'])
|
3230
|
+
(4, ['a', 'e', 'a'])
|
3231
|
+
(4, ['b', 'c', 'd', 'b'])
|
3232
|
+
(6, ['a', 'b', 'a', 'b', 'a'])
|
3233
|
+
(7, ['a', 'b', 'a', 'e', 'a'])
|
3234
|
+
(7, ['a', 'b', 'c', 'd', 'b', 'a'])
|
3235
|
+
(7, ['a', 'e', 'a', 'b', 'a'])
|
3236
|
+
(8, ['a', 'e', 'a', 'e', 'a'])
|
3237
|
+
(8, ['b', 'c', 'd', 'b', 'c', 'd', 'b'])
|
3238
|
+
|
3239
|
+
Each edge must have a positive weight::
|
3240
|
+
|
3241
|
+
sage: g = DiGraph()
|
3242
|
+
sage: g.add_edges([('a', 'b', -2), ('b', 'a', 1)])
|
3243
|
+
sage: next(g.all_cycles_iterator(simple=False, max_length=None,
|
3244
|
+
....: by_weight=True, report_weight=True))
|
3245
|
+
Traceback (most recent call last):
|
3246
|
+
...
|
3247
|
+
ValueError: negative weight is not allowed
|
3248
|
+
|
3249
|
+
The algorithm ``'B'`` is available only when `simple=True`::
|
3250
|
+
|
3251
|
+
sage: g = DiGraph()
|
3252
|
+
sage: g.add_edges([('a', 'b', 1), ('b', 'a', 1)])
|
3253
|
+
sage: next(g.all_cycles_iterator(algorithm='B', simple=False))
|
3254
|
+
....:
|
3255
|
+
Traceback (most recent call last):
|
3256
|
+
...
|
3257
|
+
ValueError: The algorithm 'B' is available only when simple=True.
|
3012
3258
|
"""
|
3013
3259
|
if starting_vertices is None:
|
3014
3260
|
starting_vertices = self
|
@@ -3022,24 +3268,64 @@ class DiGraph(GenericGraph):
|
|
3022
3268
|
h = copy(self)
|
3023
3269
|
h.delete_edges((u, v) for u, v in h.edge_iterator(labels=False) if d[u] != d[v])
|
3024
3270
|
|
3025
|
-
|
3026
|
-
|
3027
|
-
|
3028
|
-
return h._all_cycles_iterator_vertex(v,
|
3029
|
-
starting_vertices=starting_vertices,
|
3030
|
-
simple=simple,
|
3031
|
-
rooted=rooted,
|
3032
|
-
max_length=max_length,
|
3033
|
-
trivial=trivial,
|
3034
|
-
remove_acyclic_edges=False)
|
3271
|
+
by_weight, weight_function = self._get_weight_function(by_weight=by_weight,
|
3272
|
+
weight_function=weight_function,
|
3273
|
+
check_weight=check_weight)
|
3035
3274
|
|
3036
|
-
|
3275
|
+
if by_weight:
|
3276
|
+
for e in h.edge_iterator():
|
3277
|
+
if weight_function(e) < 0:
|
3278
|
+
raise ValueError("negative weight is not allowed")
|
3279
|
+
|
3280
|
+
if algorithm == 'A':
|
3281
|
+
# We create one cycles iterator per vertex. This is necessary if we
|
3282
|
+
# want to iterate over cycles with increasing length.
|
3283
|
+
def cycle_iter(v):
|
3284
|
+
return h._all_cycles_iterator_vertex(v,
|
3285
|
+
starting_vertices=starting_vertices,
|
3286
|
+
simple=simple,
|
3287
|
+
rooted=rooted,
|
3288
|
+
max_length=max_length,
|
3289
|
+
trivial=trivial,
|
3290
|
+
remove_acyclic_edges=False,
|
3291
|
+
weight_function=weight_function,
|
3292
|
+
by_weight=by_weight,
|
3293
|
+
check_weight=check_weight,
|
3294
|
+
report_weight=True)
|
3295
|
+
|
3296
|
+
iterators = {v: cycle_iter(v) for v in starting_vertices}
|
3297
|
+
elif algorithm == 'B':
|
3298
|
+
if not simple:
|
3299
|
+
raise ValueError("The algorithm 'B' is available only when simple=True.")
|
3300
|
+
|
3301
|
+
def simple_cycle_iter(hh, e):
|
3302
|
+
return hh._all_simple_cycles_iterator_edge(e,
|
3303
|
+
max_length=max_length,
|
3304
|
+
remove_acyclic_edges=False,
|
3305
|
+
weight_function=weight_function,
|
3306
|
+
by_weight=by_weight,
|
3307
|
+
check_weight=check_weight,
|
3308
|
+
report_weight=True)
|
3309
|
+
|
3310
|
+
SCCS = h.strongly_connected_components_subgraphs()
|
3311
|
+
iterators = dict()
|
3312
|
+
while SCCS:
|
3313
|
+
hh = SCCS.pop()
|
3314
|
+
if not hh.size():
|
3315
|
+
continue
|
3316
|
+
e = next(hh.edge_iterator())
|
3317
|
+
iterators[e] = simple_cycle_iter(hh, e)
|
3318
|
+
hh.delete_edge(e)
|
3319
|
+
SCCS.extend(hh.strongly_connected_components_subgraphs())
|
3320
|
+
else:
|
3321
|
+
raise ValueError(f"The algorithm {algorithm} is not valid. \
|
3322
|
+
Use the algorithm 'A' or 'B'.")
|
3037
3323
|
|
3038
3324
|
cycles = []
|
3039
|
-
for
|
3325
|
+
for key, it in iterators.items():
|
3040
3326
|
try:
|
3041
|
-
cycle = next(
|
3042
|
-
cycles.append((
|
3327
|
+
length, cycle = next(it)
|
3328
|
+
cycles.append((length, cycle, key))
|
3043
3329
|
except StopIteration:
|
3044
3330
|
pass
|
3045
3331
|
# Since we always extract a shortest path, using a heap
|
@@ -3048,20 +3334,28 @@ class DiGraph(GenericGraph):
|
|
3048
3334
|
heapify(cycles)
|
3049
3335
|
while cycles:
|
3050
3336
|
# We choose the shortest available cycle
|
3051
|
-
|
3052
|
-
|
3337
|
+
length, shortest_cycle, key = heappop(cycles)
|
3338
|
+
if report_weight:
|
3339
|
+
yield (length, shortest_cycle)
|
3340
|
+
else:
|
3341
|
+
yield shortest_cycle
|
3053
3342
|
# We update the cycle iterator to its next available cycle if it
|
3054
3343
|
# exists
|
3055
3344
|
try:
|
3056
|
-
cycle = next(
|
3057
|
-
heappush(cycles, (
|
3345
|
+
length, cycle = next(iterators[key])
|
3346
|
+
heappush(cycles, (length, cycle, key))
|
3058
3347
|
except StopIteration:
|
3059
3348
|
pass
|
3060
3349
|
|
3061
3350
|
def all_simple_cycles(self, starting_vertices=None, rooted=False,
|
3062
|
-
max_length=None, trivial=False
|
3351
|
+
max_length=None, trivial=False,
|
3352
|
+
weight_function=None, by_weight=False,
|
3353
|
+
check_weight=True, report_weight=False,
|
3354
|
+
algorithm='A'):
|
3063
3355
|
r"""
|
3064
|
-
Return a list of all simple cycles of ``self``.
|
3356
|
+
Return a list of all simple cycles of ``self``. The cycles are
|
3357
|
+
enumerated in increasing length order. Each edge must have a
|
3358
|
+
positive weight.
|
3065
3359
|
|
3066
3360
|
INPUT:
|
3067
3361
|
|
@@ -3082,6 +3376,31 @@ class DiGraph(GenericGraph):
|
|
3082
3376
|
- ``trivial`` -- boolean (default: ``False``); if set to ``True``, then
|
3083
3377
|
the empty paths are also enumerated
|
3084
3378
|
|
3379
|
+
- ``weight_function`` -- function (default: ``None``); a function that
|
3380
|
+
takes as input an edge ``(u, v, l)`` and outputs its weight. If not
|
3381
|
+
``None``, ``by_weight`` is automatically set to ``True``. If ``None``
|
3382
|
+
and ``by_weight`` is ``True``, we use the edge label ``l`` as a
|
3383
|
+
weight.
|
3384
|
+
|
3385
|
+
- ``by_weight`` -- boolean (default: ``False``); if ``True``, the edges
|
3386
|
+
in the graph are weighted, otherwise all edges have weight 1
|
3387
|
+
|
3388
|
+
- ``check_weight`` -- boolean (default: ``True``); whether to check that
|
3389
|
+
the ``weight_function`` outputs a number for each edge
|
3390
|
+
|
3391
|
+
- ``report_weight`` -- boolean (default: ``False``); if ``False``, just
|
3392
|
+
a cycle is returned. Otherwise a tuple of cycle length and cycle is
|
3393
|
+
returned.
|
3394
|
+
|
3395
|
+
- ``algorithm`` -- string (default: ``'A'``); the algorithm used to
|
3396
|
+
enumerate the cycles.
|
3397
|
+
|
3398
|
+
- The algorithm ``'A'`` holds cycle iterators starting with each vertex,
|
3399
|
+
and output them in increasing length order.
|
3400
|
+
|
3401
|
+
- The algorithm ``'B'`` holds cycle iterators starting with each edge,
|
3402
|
+
and output them in increasing length order.
|
3403
|
+
|
3085
3404
|
OUTPUT: list
|
3086
3405
|
|
3087
3406
|
.. NOTE::
|
@@ -3141,52 +3460,46 @@ class DiGraph(GenericGraph):
|
|
3141
3460
|
|
3142
3461
|
sage: g = graphs.CompleteGraph(20).to_directed()
|
3143
3462
|
sage: g.all_simple_cycles(max_length=2)
|
3144
|
-
[[0,
|
3145
|
-
[0,
|
3146
|
-
[0,
|
3147
|
-
[
|
3148
|
-
[1,
|
3149
|
-
[1,
|
3150
|
-
[
|
3151
|
-
[2,
|
3152
|
-
[2,
|
3153
|
-
[
|
3154
|
-
[3,
|
3155
|
-
[3,
|
3156
|
-
[
|
3157
|
-
[4,
|
3158
|
-
[
|
3159
|
-
[
|
3160
|
-
[
|
3161
|
-
[
|
3162
|
-
[
|
3163
|
-
[
|
3164
|
-
[
|
3165
|
-
[
|
3166
|
-
[
|
3167
|
-
[
|
3168
|
-
[
|
3169
|
-
[
|
3170
|
-
[
|
3171
|
-
[
|
3172
|
-
[
|
3173
|
-
[
|
3174
|
-
[
|
3175
|
-
[
|
3176
|
-
[
|
3177
|
-
[12, 13, 12], [12, 14, 12], [12, 15, 12], [13, 16, 13],
|
3178
|
-
[13, 17, 13], [13, 18, 13], [13, 19, 13], [13, 14, 13],
|
3179
|
-
[13, 15, 13], [14, 16, 14], [14, 17, 14], [14, 18, 14],
|
3180
|
-
[14, 19, 14], [14, 15, 14], [15, 16, 15], [15, 17, 15],
|
3181
|
-
[15, 18, 15], [15, 19, 15], [16, 17, 16], [16, 18, 16],
|
3182
|
-
[16, 19, 16], [17, 18, 17], [17, 19, 17], [18, 19, 18]]
|
3463
|
+
[[0, 1, 0], [0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], [0, 7, 0],
|
3464
|
+
[0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 0], [0, 12, 0], [0, 13, 0],
|
3465
|
+
[0, 14, 0], [0, 15, 0], [0, 16, 0], [0, 17, 0], [0, 18, 0], [0, 19, 0],
|
3466
|
+
[1, 2, 1], [1, 3, 1], [1, 4, 1], [1, 5, 1], [1, 6, 1], [1, 7, 1], [1, 8, 1],
|
3467
|
+
[1, 9, 1], [1, 10, 1], [1, 11, 1], [1, 12, 1], [1, 13, 1], [1, 14, 1],
|
3468
|
+
[1, 15, 1], [1, 16, 1], [1, 17, 1], [1, 18, 1], [1, 19, 1], [2, 3, 2],
|
3469
|
+
[2, 4, 2], [2, 5, 2], [2, 6, 2], [2, 7, 2], [2, 8, 2], [2, 9, 2], [2, 10, 2],
|
3470
|
+
[2, 11, 2], [2, 12, 2], [2, 13, 2], [2, 14, 2], [2, 15, 2], [2, 16, 2],
|
3471
|
+
[2, 17, 2], [2, 18, 2], [2, 19, 2], [3, 4, 3], [3, 5, 3], [3, 6, 3],
|
3472
|
+
[3, 7, 3], [3, 8, 3], [3, 9, 3], [3, 10, 3], [3, 11, 3], [3, 12, 3],
|
3473
|
+
[3, 13, 3], [3, 14, 3], [3, 15, 3], [3, 16, 3], [3, 17, 3], [3, 18, 3],
|
3474
|
+
[3, 19, 3], [4, 5, 4], [4, 6, 4], [4, 7, 4], [4, 8, 4], [4, 9, 4], [4, 10, 4],
|
3475
|
+
[4, 11, 4], [4, 12, 4], [4, 13, 4], [4, 14, 4], [4, 15, 4], [4, 16, 4],
|
3476
|
+
[4, 17, 4], [4, 18, 4], [4, 19, 4], [5, 6, 5], [5, 7, 5], [5, 8, 5],
|
3477
|
+
[5, 9, 5], [5, 10, 5], [5, 11, 5], [5, 12, 5], [5, 13, 5], [5, 14, 5],
|
3478
|
+
[5, 15, 5], [5, 16, 5], [5, 17, 5], [5, 18, 5], [5, 19, 5], [6, 7, 6],
|
3479
|
+
[6, 8, 6], [6, 9, 6], [6, 10, 6], [6, 11, 6], [6, 12, 6], [6, 13, 6],
|
3480
|
+
[6, 14, 6], [6, 15, 6], [6, 16, 6], [6, 17, 6], [6, 18, 6], [6, 19, 6],
|
3481
|
+
[7, 8, 7], [7, 9, 7], [7, 10, 7], [7, 11, 7], [7, 12, 7], [7, 13, 7],
|
3482
|
+
[7, 14, 7], [7, 15, 7], [7, 16, 7], [7, 17, 7], [7, 18, 7], [7, 19, 7],
|
3483
|
+
[8, 9, 8], [8, 10, 8], [8, 11, 8], [8, 12, 8], [8, 13, 8], [8, 14, 8],
|
3484
|
+
[8, 15, 8], [8, 16, 8], [8, 17, 8], [8, 18, 8], [8, 19, 8], [9, 10, 9],
|
3485
|
+
[9, 11, 9], [9, 12, 9], [9, 13, 9], [9, 14, 9], [9, 15, 9], [9, 16, 9],
|
3486
|
+
[9, 17, 9], [9, 18, 9], [9, 19, 9], [10, 11, 10], [10, 12, 10], [10, 13, 10],
|
3487
|
+
[10, 14, 10], [10, 15, 10], [10, 16, 10], [10, 17, 10], [10, 18, 10],
|
3488
|
+
[10, 19, 10], [11, 12, 11], [11, 13, 11], [11, 14, 11], [11, 15, 11],
|
3489
|
+
[11, 16, 11], [11, 17, 11], [11, 18, 11], [11, 19, 11], [12, 13, 12],
|
3490
|
+
[12, 14, 12], [12, 15, 12], [12, 16, 12], [12, 17, 12], [12, 18, 12],
|
3491
|
+
[12, 19, 12], [13, 14, 13], [13, 15, 13], [13, 16, 13], [13, 17, 13],
|
3492
|
+
[13, 18, 13], [13, 19, 13], [14, 15, 14], [14, 16, 14], [14, 17, 14],
|
3493
|
+
[14, 18, 14], [14, 19, 14], [15, 16, 15], [15, 17, 15], [15, 18, 15],
|
3494
|
+
[15, 19, 15], [16, 17, 16], [16, 18, 16], [16, 19, 16], [17, 18, 17],
|
3495
|
+
[17, 19, 17], [18, 19, 18]]
|
3183
3496
|
|
3184
3497
|
sage: g = graphs.CompleteGraph(20).to_directed()
|
3185
3498
|
sage: g.all_simple_cycles(max_length=2, starting_vertices=[0])
|
3186
|
-
[[0,
|
3187
|
-
[0,
|
3188
|
-
[0,
|
3189
|
-
[0,
|
3499
|
+
[[0, 1, 0], [0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0],
|
3500
|
+
[0, 6, 0], [0, 7, 0], [0, 8, 0], [0, 9, 0], [0, 10, 0],
|
3501
|
+
[0, 11, 0], [0, 12, 0], [0, 13, 0], [0, 14, 0], [0, 15, 0],
|
3502
|
+
[0, 16, 0], [0, 17, 0], [0, 18, 0], [0, 19, 0]]
|
3190
3503
|
|
3191
3504
|
One may prefer to distinguish equivalent cycles having distinct starting
|
3192
3505
|
vertices (compare the following examples)::
|
@@ -3197,10 +3510,41 @@ class DiGraph(GenericGraph):
|
|
3197
3510
|
sage: g.all_simple_cycles(max_length=2, rooted=True)
|
3198
3511
|
[[0, 1, 0], [0, 2, 0], [0, 3, 0], [1, 0, 1], [1, 2, 1], [1, 3, 1],
|
3199
3512
|
[2, 0, 2], [2, 1, 2], [2, 3, 2], [3, 0, 3], [3, 1, 3], [3, 2, 3]]
|
3513
|
+
|
3514
|
+
A cycle is enumerated in increasing length order for a weighted graph::
|
3515
|
+
|
3516
|
+
sage: cycles = g.all_simple_cycles(weight_function=lambda e:e[0]+e[1],
|
3517
|
+
....: by_weight=True, report_weight=True)
|
3518
|
+
sage: cycles
|
3519
|
+
[(2, [0, 1, 0]), (4, [0, 2, 0]), (6, [0, 1, 2, 0]), (6, [0, 2, 1, 0]),
|
3520
|
+
(6, [0, 3, 0]), (6, [1, 2, 1]), (8, [0, 1, 3, 0]), (8, [0, 3, 1, 0]),
|
3521
|
+
(8, [1, 3, 1]), (10, [0, 2, 3, 0]), (10, [0, 3, 2, 0]), (10, [2, 3, 2]),
|
3522
|
+
(12, [0, 1, 2, 3, 0]), (12, [0, 1, 3, 2, 0]), (12, [0, 2, 1, 3, 0]),
|
3523
|
+
(12, [0, 2, 3, 1, 0]), (12, [0, 3, 1, 2, 0]), (12, [0, 3, 2, 1, 0]),
|
3524
|
+
(12, [1, 2, 3, 1]), (12, [1, 3, 2, 1])]
|
3525
|
+
|
3526
|
+
The algorithm ``'B'`` can be used::
|
3527
|
+
|
3528
|
+
sage: cycles_B = g.all_simple_cycles(weight_function=lambda e:e[0]+e[1], by_weight=True,
|
3529
|
+
....: report_weight=True, algorithm='B')
|
3530
|
+
sage: cycles_B
|
3531
|
+
[(2, [0, 1, 0]), (4, [0, 2, 0]), (6, [0, 1, 2, 0]), (6, [0, 2, 1, 0]),
|
3532
|
+
(6, [0, 3, 0]), (6, [1, 2, 1]), (8, [0, 1, 3, 0]), (8, [0, 3, 1, 0]),
|
3533
|
+
(8, [1, 3, 1]), (10, [0, 2, 3, 0]), (10, [0, 3, 2, 0]), (10, [2, 3, 2]),
|
3534
|
+
(12, [0, 1, 3, 2, 0]), (12, [0, 1, 2, 3, 0]), (12, [0, 2, 3, 1, 0]),
|
3535
|
+
(12, [0, 2, 1, 3, 0]), (12, [0, 3, 2, 1, 0]), (12, [0, 3, 1, 2, 0]),
|
3536
|
+
(12, [1, 2, 3, 1]), (12, [1, 3, 2, 1])]
|
3537
|
+
sage: cycles.sort() == cycles_B.sort()
|
3538
|
+
True
|
3200
3539
|
"""
|
3201
3540
|
return list(self.all_cycles_iterator(starting_vertices=starting_vertices,
|
3202
3541
|
simple=True, rooted=rooted,
|
3203
|
-
max_length=max_length, trivial=trivial
|
3542
|
+
max_length=max_length, trivial=trivial,
|
3543
|
+
weight_function=weight_function,
|
3544
|
+
by_weight=by_weight,
|
3545
|
+
check_weight=check_weight,
|
3546
|
+
report_weight=report_weight,
|
3547
|
+
algorithm=algorithm))
|
3204
3548
|
|
3205
3549
|
def path_semigroup(self):
|
3206
3550
|
"""
|