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.
Files changed (132) hide show
  1. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc1.dist-info}/METADATA +5 -6
  2. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc1.dist-info}/RECORD +132 -130
  3. sage/combinat/abstract_tree.py +188 -17
  4. sage/combinat/cluster_algebra_quiver/interact.py +1 -2
  5. sage/combinat/cluster_algebra_quiver/mutation_type.py +518 -519
  6. sage/combinat/cluster_algebra_quiver/quiver.py +233 -205
  7. sage/combinat/designs/covering_design.py +2 -6
  8. sage/combinat/designs/database.py +11 -10
  9. sage/combinat/designs/designs_pyx.cpython-312-darwin.so +0 -0
  10. sage/combinat/designs/designs_pyx.pyx +2 -2
  11. sage/combinat/designs/evenly_distributed_sets.cpython-312-darwin.so +0 -0
  12. sage/combinat/designs/evenly_distributed_sets.pyx +4 -4
  13. sage/combinat/designs/gen_quadrangles_with_spread.cpython-312-darwin.so +0 -0
  14. sage/combinat/designs/latin_squares.py +53 -20
  15. sage/combinat/designs/orthogonal_arrays.py +2 -1
  16. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-312-darwin.so +0 -0
  17. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +22 -21
  18. sage/combinat/designs/resolvable_bibd.py +191 -157
  19. sage/combinat/designs/subhypergraph_search.cpython-312-darwin.so +0 -0
  20. sage/combinat/designs/subhypergraph_search.pyx +4 -4
  21. sage/combinat/designs/twographs.py +2 -2
  22. sage/combinat/finite_state_machine.py +6 -6
  23. sage/combinat/posets/bubble_shuffle.py +247 -0
  24. sage/combinat/posets/d_complete.py +3 -3
  25. sage/combinat/posets/elements.py +3 -3
  26. sage/combinat/posets/hasse_cython.cpython-312-darwin.so +0 -0
  27. sage/combinat/posets/hasse_cython.pyx +1 -1
  28. sage/combinat/posets/hasse_diagram.py +16 -22
  29. sage/combinat/posets/hochschild_lattice.py +158 -0
  30. sage/combinat/posets/incidence_algebras.py +14 -16
  31. sage/combinat/posets/lattices.py +51 -53
  32. sage/combinat/posets/linear_extension_iterator.cpython-312-darwin.so +0 -0
  33. sage/combinat/posets/linear_extensions.py +10 -12
  34. sage/combinat/posets/moebius_algebra.py +4 -4
  35. sage/combinat/posets/poset_examples.py +70 -23
  36. sage/combinat/posets/posets.py +294 -103
  37. sage/databases/knotinfo_db.py +2 -1
  38. sage/graphs/asteroidal_triples.cpython-312-darwin.so +0 -0
  39. sage/graphs/asteroidal_triples.pyx +24 -3
  40. sage/graphs/base/boost_graph.cpython-312-darwin.so +0 -0
  41. sage/graphs/base/boost_graph.pxd +3 -3
  42. sage/graphs/base/c_graph.cpython-312-darwin.so +0 -0
  43. sage/graphs/base/c_graph.pyx +1 -1
  44. sage/graphs/base/dense_graph.cpython-312-darwin.so +0 -0
  45. sage/graphs/base/dense_graph.pxd +5 -3
  46. sage/graphs/base/dense_graph.pyx +44 -0
  47. sage/graphs/base/graph_backends.cpython-312-darwin.so +0 -0
  48. sage/graphs/base/sparse_graph.cpython-312-darwin.so +0 -0
  49. sage/graphs/base/static_dense_graph.cpython-312-darwin.so +0 -0
  50. sage/graphs/base/static_sparse_backend.cpython-312-darwin.so +0 -0
  51. sage/graphs/base/static_sparse_backend.pyx +8 -5
  52. sage/graphs/base/static_sparse_graph.cpython-312-darwin.so +0 -0
  53. sage/graphs/base/static_sparse_graph.pyx +86 -15
  54. sage/graphs/bipartite_graph.py +59 -36
  55. sage/graphs/centrality.cpython-312-darwin.so +0 -0
  56. sage/graphs/centrality.pyx +82 -9
  57. sage/graphs/cographs.py +1 -1
  58. sage/graphs/comparability.cpython-312-darwin.so +0 -0
  59. sage/graphs/comparability.pyx +64 -26
  60. sage/graphs/connectivity.cpython-312-darwin.so +0 -0
  61. sage/graphs/convexity_properties.cpython-312-darwin.so +0 -0
  62. sage/graphs/convexity_properties.pyx +52 -9
  63. sage/graphs/digraph.py +439 -95
  64. sage/graphs/digraph_generators.py +174 -102
  65. sage/graphs/distances_all_pairs.cpython-312-darwin.so +0 -0
  66. sage/graphs/dot2tex_utils.py +1 -1
  67. sage/graphs/edge_connectivity.cpython-312-darwin.so +0 -0
  68. sage/graphs/generators/basic.py +1 -1
  69. sage/graphs/generators/distance_regular.cpython-312-darwin.so +0 -0
  70. sage/graphs/generators/distance_regular.pyx +1 -1
  71. sage/graphs/generators/families.py +37 -27
  72. sage/graphs/generators/random.py +2 -2
  73. sage/graphs/generators/smallgraphs.py +3 -3
  74. sage/graphs/generic_graph.py +558 -86
  75. sage/graphs/generic_graph_pyx.cpython-312-darwin.so +0 -0
  76. sage/graphs/generic_graph_pyx.pyx +58 -11
  77. sage/graphs/genus.cpython-312-darwin.so +0 -0
  78. sage/graphs/genus.pyx +3 -4
  79. sage/graphs/graph.py +291 -8
  80. sage/graphs/graph_coloring.cpython-312-darwin.so +0 -0
  81. sage/graphs/graph_database.py +67 -12
  82. sage/graphs/graph_decompositions/bandwidth.cpython-312-darwin.so +0 -0
  83. sage/graphs/graph_decompositions/clique_separators.cpython-312-darwin.so +0 -0
  84. sage/graphs/graph_decompositions/clique_separators.pyx +24 -3
  85. sage/graphs/graph_decompositions/cutwidth.cpython-312-darwin.so +0 -0
  86. sage/graphs/graph_decompositions/fast_digraph.cpython-312-darwin.so +0 -0
  87. sage/graphs/graph_decompositions/fast_digraph.pyx +1 -1
  88. sage/graphs/graph_decompositions/graph_products.cpython-312-darwin.so +0 -0
  89. sage/graphs/graph_decompositions/graph_products.pyx +67 -21
  90. sage/graphs/graph_decompositions/modular_decomposition.cpython-312-darwin.so +0 -0
  91. sage/graphs/graph_decompositions/slice_decomposition.cpython-312-darwin.so +0 -0
  92. sage/graphs/graph_decompositions/slice_decomposition.pyx +34 -8
  93. sage/graphs/graph_decompositions/tree_decomposition.cpython-312-darwin.so +0 -0
  94. sage/graphs/graph_decompositions/vertex_separation.cpython-312-darwin.so +0 -0
  95. sage/graphs/graph_generators.py +45 -32
  96. sage/graphs/graph_generators_pyx.cpython-312-darwin.so +0 -0
  97. sage/graphs/graph_generators_pyx.pyx +15 -15
  98. sage/graphs/graph_latex.py +1 -1
  99. sage/graphs/graph_list.py +52 -9
  100. sage/graphs/graph_plot.py +7 -0
  101. sage/graphs/hyperbolicity.cpython-312-darwin.so +0 -0
  102. sage/graphs/hyperbolicity.pyx +2 -0
  103. sage/graphs/independent_sets.cpython-312-darwin.so +0 -0
  104. sage/graphs/isoperimetric_inequalities.cpython-312-darwin.so +0 -0
  105. sage/graphs/isoperimetric_inequalities.pyx +42 -6
  106. sage/graphs/line_graph.cpython-312-darwin.so +0 -0
  107. sage/graphs/line_graph.pyx +153 -37
  108. sage/graphs/matching_covered_graph.py +84 -60
  109. sage/graphs/orientations.py +3 -18
  110. sage/graphs/path_enumeration.cpython-312-darwin.so +0 -0
  111. sage/graphs/path_enumeration.pyx +2 -2
  112. sage/graphs/spanning_tree.cpython-312-darwin.so +0 -0
  113. sage/graphs/strongly_regular_db.cpython-312-darwin.so +0 -0
  114. sage/graphs/strongly_regular_db.pyx +15 -15
  115. sage/graphs/traversals.cpython-312-darwin.so +0 -0
  116. sage/graphs/traversals.pyx +13 -12
  117. sage/graphs/trees.cpython-312-darwin.so +0 -0
  118. sage/graphs/tutte_polynomial.py +1 -1
  119. sage/graphs/views.cpython-312-darwin.so +0 -0
  120. sage/graphs/weakly_chordal.cpython-312-darwin.so +0 -0
  121. sage/graphs/weakly_chordal.pyx +50 -8
  122. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-312-darwin.so +0 -0
  123. sage/knots/free_knotinfo_monoid.py +3 -3
  124. sage/knots/knotinfo.py +102 -82
  125. sage/knots/link.py +72 -39
  126. sage/topology/cubical_complex.py +4 -5
  127. sage/topology/delta_complex.py +4 -4
  128. sage/topology/simplicial_complex.py +0 -1
  129. sage/topology/simplicial_complex_catalog.py +6 -0
  130. sage/topology/simplicial_complex_examples.py +4 -16
  131. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc1.dist-info}/WHEEL +0 -0
  132. {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
- if hasattr(self, '_embedding'):
1092
- G._embedding = copy(self._embedding)
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
- attributes_to_copy = ('_assoc', '_embedding')
1855
- for attr in attributes_to_copy:
1856
- if hasattr(self, attr):
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
- yield [vertex]
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
- queue = [[vertex]]
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 queue:
2895
- path = queue.pop(0)
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
- yield path
2899
- # Makes sure that the current cycle is not too long
2900
- # Also if a cycle has been encountered and only simple cycles are
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 len(path) <= max_length and (not simple or path.count(path[-1]) == 1):
2903
- for neighbor in h.neighbor_out_iterator(path[-1]):
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 rooted or neighbor not in starting_vertices or path[0] <= neighbor:
2907
- queue.append(path + [neighbor])
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
- # We create one cycles iterator per vertex. This is necessary if we
3026
- # want to iterate over cycles with increasing length.
3027
- def cycle_iter(v):
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
- vertex_iterators = {v: cycle_iter(v) for v in starting_vertices}
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 vi in vertex_iterators.values():
3325
+ for key, it in iterators.items():
3040
3326
  try:
3041
- cycle = next(vi)
3042
- cycles.append((len(cycle), cycle))
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
- _, shortest_cycle = heappop(cycles)
3052
- yield shortest_cycle
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(vertex_iterators[shortest_cycle[0]])
3057
- heappush(cycles, (len(cycle), cycle))
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, 16, 0], [0, 1, 0], [0, 17, 0], [0, 2, 0], [0, 18, 0],
3145
- [0, 3, 0], [0, 19, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], [0, 7, 0],
3146
- [0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 0], [0, 12, 0],
3147
- [0, 13, 0], [0, 14, 0], [0, 15, 0], [1, 16, 1], [1, 17, 1],
3148
- [1, 2, 1], [1, 18, 1], [1, 3, 1], [1, 19, 1], [1, 4, 1], [1, 5, 1],
3149
- [1, 6, 1], [1, 7, 1], [1, 8, 1], [1, 9, 1], [1, 10, 1], [1, 11, 1],
3150
- [1, 12, 1], [1, 13, 1], [1, 14, 1], [1, 15, 1], [2, 16, 2],
3151
- [2, 17, 2], [2, 18, 2], [2, 3, 2], [2, 19, 2], [2, 4, 2],
3152
- [2, 5, 2], [2, 6, 2], [2, 7, 2], [2, 8, 2], [2, 9, 2], [2, 10, 2],
3153
- [2, 11, 2], [2, 12, 2], [2, 13, 2], [2, 14, 2], [2, 15, 2],
3154
- [3, 16, 3], [3, 17, 3], [3, 18, 3], [3, 19, 3], [3, 4, 3],
3155
- [3, 5, 3], [3, 6, 3], [3, 7, 3], [3, 8, 3], [3, 9, 3], [3, 10, 3],
3156
- [3, 11, 3], [3, 12, 3], [3, 13, 3], [3, 14, 3], [3, 15, 3],
3157
- [4, 16, 4], [4, 17, 4], [4, 18, 4], [4, 19, 4], [4, 5, 4],
3158
- [4, 6, 4], [4, 7, 4], [4, 8, 4], [4, 9, 4], [4, 10, 4], [4, 11, 4],
3159
- [4, 12, 4], [4, 13, 4], [4, 14, 4], [4, 15, 4], [5, 16, 5],
3160
- [5, 17, 5], [5, 18, 5], [5, 19, 5], [5, 6, 5], [5, 7, 5],
3161
- [5, 8, 5], [5, 9, 5], [5, 10, 5], [5, 11, 5], [5, 12, 5],
3162
- [5, 13, 5], [5, 14, 5], [5, 15, 5], [6, 16, 6], [6, 17, 6],
3163
- [6, 18, 6], [6, 19, 6], [6, 7, 6], [6, 8, 6], [6, 9, 6],
3164
- [6, 10, 6], [6, 11, 6], [6, 12, 6], [6, 13, 6], [6, 14, 6],
3165
- [6, 15, 6], [7, 16, 7], [7, 17, 7], [7, 18, 7], [7, 19, 7],
3166
- [7, 8, 7], [7, 9, 7], [7, 10, 7], [7, 11, 7], [7, 12, 7],
3167
- [7, 13, 7], [7, 14, 7], [7, 15, 7], [8, 16, 8], [8, 17, 8],
3168
- [8, 18, 8], [8, 19, 8], [8, 9, 8], [8, 10, 8], [8, 11, 8],
3169
- [8, 12, 8], [8, 13, 8], [8, 14, 8], [8, 15, 8], [9, 16, 9],
3170
- [9, 17, 9], [9, 18, 9], [9, 19, 9], [9, 10, 9], [9, 11, 9],
3171
- [9, 12, 9], [9, 13, 9], [9, 14, 9], [9, 15, 9], [10, 16, 10],
3172
- [10, 17, 10], [10, 18, 10], [10, 19, 10], [10, 11, 10],
3173
- [10, 12, 10], [10, 13, 10], [10, 14, 10], [10, 15, 10],
3174
- [11, 16, 11], [11, 17, 11], [11, 18, 11], [11, 19, 11],
3175
- [11, 12, 11], [11, 13, 11], [11, 14, 11], [11, 15, 11],
3176
- [12, 16, 12], [12, 17, 12], [12, 18, 12], [12, 19, 12],
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, 16, 0], [0, 1, 0], [0, 17, 0], [0, 2, 0], [0, 18, 0],
3187
- [0, 3, 0], [0, 19, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0],
3188
- [0, 7, 0], [0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 0],
3189
- [0, 12, 0], [0, 13, 0], [0, 14, 0], [0, 15, 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
  """