passagemath-graphs 10.6.1rc1__cp310-cp310-musllinux_1_2_aarch64.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 (260) hide show
  1. passagemath_graphs-10.6.1rc1.dist-info/METADATA +292 -0
  2. passagemath_graphs-10.6.1rc1.dist-info/RECORD +260 -0
  3. passagemath_graphs-10.6.1rc1.dist-info/WHEEL +5 -0
  4. passagemath_graphs-10.6.1rc1.dist-info/top_level.txt +2 -0
  5. passagemath_graphs.libs/libgcc_s-69c45f16.so.1 +0 -0
  6. passagemath_graphs.libs/libgmp-8e78bd9b.so.10.5.0 +0 -0
  7. passagemath_graphs.libs/libstdc++-1f1a71be.so.6.0.33 +0 -0
  8. sage/all__sagemath_graphs.py +39 -0
  9. sage/combinat/abstract_tree.py +2723 -0
  10. sage/combinat/all__sagemath_graphs.py +34 -0
  11. sage/combinat/binary_tree.py +5306 -0
  12. sage/combinat/cluster_algebra_quiver/all.py +22 -0
  13. sage/combinat/cluster_algebra_quiver/cluster_seed.py +5208 -0
  14. sage/combinat/cluster_algebra_quiver/interact.py +124 -0
  15. sage/combinat/cluster_algebra_quiver/mutation_class.py +625 -0
  16. sage/combinat/cluster_algebra_quiver/mutation_type.py +1555 -0
  17. sage/combinat/cluster_algebra_quiver/quiver.py +2290 -0
  18. sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py +2468 -0
  19. sage/combinat/designs/MOLS_handbook_data.py +570 -0
  20. sage/combinat/designs/all.py +58 -0
  21. sage/combinat/designs/bibd.py +1655 -0
  22. sage/combinat/designs/block_design.py +1071 -0
  23. sage/combinat/designs/covering_array.py +269 -0
  24. sage/combinat/designs/covering_design.py +530 -0
  25. sage/combinat/designs/database.py +5615 -0
  26. sage/combinat/designs/design_catalog.py +122 -0
  27. sage/combinat/designs/designs_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  28. sage/combinat/designs/designs_pyx.pxd +21 -0
  29. sage/combinat/designs/designs_pyx.pyx +993 -0
  30. sage/combinat/designs/difference_family.py +3951 -0
  31. sage/combinat/designs/difference_matrices.py +279 -0
  32. sage/combinat/designs/evenly_distributed_sets.cpython-310-aarch64-linux-gnu.so +0 -0
  33. sage/combinat/designs/evenly_distributed_sets.pyx +661 -0
  34. sage/combinat/designs/ext_rep.py +1064 -0
  35. sage/combinat/designs/gen_quadrangles_with_spread.cpython-310-aarch64-linux-gnu.so +0 -0
  36. sage/combinat/designs/gen_quadrangles_with_spread.pyx +339 -0
  37. sage/combinat/designs/group_divisible_designs.py +361 -0
  38. sage/combinat/designs/incidence_structures.py +2357 -0
  39. sage/combinat/designs/latin_squares.py +581 -0
  40. sage/combinat/designs/orthogonal_arrays.py +2244 -0
  41. sage/combinat/designs/orthogonal_arrays_build_recursive.py +1780 -0
  42. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-310-aarch64-linux-gnu.so +0 -0
  43. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +967 -0
  44. sage/combinat/designs/resolvable_bibd.py +815 -0
  45. sage/combinat/designs/steiner_quadruple_systems.py +1306 -0
  46. sage/combinat/designs/subhypergraph_search.cpython-310-aarch64-linux-gnu.so +0 -0
  47. sage/combinat/designs/subhypergraph_search.pyx +530 -0
  48. sage/combinat/designs/twographs.py +306 -0
  49. sage/combinat/finite_state_machine.py +14874 -0
  50. sage/combinat/finite_state_machine_generators.py +2006 -0
  51. sage/combinat/graph_path.py +448 -0
  52. sage/combinat/interval_posets.py +3908 -0
  53. sage/combinat/nu_tamari_lattice.py +269 -0
  54. sage/combinat/ordered_tree.py +1446 -0
  55. sage/combinat/posets/all.py +46 -0
  56. sage/combinat/posets/bubble_shuffle.py +247 -0
  57. sage/combinat/posets/cartesian_product.py +493 -0
  58. sage/combinat/posets/d_complete.py +182 -0
  59. sage/combinat/posets/elements.py +273 -0
  60. sage/combinat/posets/forest.py +30 -0
  61. sage/combinat/posets/hasse_cython.cpython-310-aarch64-linux-gnu.so +0 -0
  62. sage/combinat/posets/hasse_cython.pyx +174 -0
  63. sage/combinat/posets/hasse_diagram.py +3672 -0
  64. sage/combinat/posets/hochschild_lattice.py +158 -0
  65. sage/combinat/posets/incidence_algebras.py +794 -0
  66. sage/combinat/posets/lattices.py +5117 -0
  67. sage/combinat/posets/linear_extension_iterator.cpython-310-aarch64-linux-gnu.so +0 -0
  68. sage/combinat/posets/linear_extension_iterator.pyx +292 -0
  69. sage/combinat/posets/linear_extensions.py +1037 -0
  70. sage/combinat/posets/mobile.py +275 -0
  71. sage/combinat/posets/moebius_algebra.py +776 -0
  72. sage/combinat/posets/poset_examples.py +2178 -0
  73. sage/combinat/posets/posets.py +9360 -0
  74. sage/combinat/rooted_tree.py +1070 -0
  75. sage/combinat/shard_order.py +239 -0
  76. sage/combinat/tamari_lattices.py +384 -0
  77. sage/combinat/yang_baxter_graph.py +923 -0
  78. sage/databases/all__sagemath_graphs.py +1 -0
  79. sage/databases/knotinfo_db.py +1231 -0
  80. sage/ext_data/all__sagemath_graphs.py +1 -0
  81. sage/ext_data/graphs/graph_plot_js.html +330 -0
  82. sage/ext_data/kenzo/CP2.txt +45 -0
  83. sage/ext_data/kenzo/CP3.txt +349 -0
  84. sage/ext_data/kenzo/CP4.txt +4774 -0
  85. sage/ext_data/kenzo/README.txt +49 -0
  86. sage/ext_data/kenzo/S4.txt +20 -0
  87. sage/graphs/all.py +42 -0
  88. sage/graphs/asteroidal_triples.cpython-310-aarch64-linux-gnu.so +0 -0
  89. sage/graphs/asteroidal_triples.pyx +320 -0
  90. sage/graphs/base/all.py +1 -0
  91. sage/graphs/base/boost_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  92. sage/graphs/base/boost_graph.pxd +106 -0
  93. sage/graphs/base/boost_graph.pyx +3045 -0
  94. sage/graphs/base/c_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  95. sage/graphs/base/c_graph.pxd +106 -0
  96. sage/graphs/base/c_graph.pyx +5096 -0
  97. sage/graphs/base/dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  98. sage/graphs/base/dense_graph.pxd +28 -0
  99. sage/graphs/base/dense_graph.pyx +801 -0
  100. sage/graphs/base/graph_backends.cpython-310-aarch64-linux-gnu.so +0 -0
  101. sage/graphs/base/graph_backends.pxd +5 -0
  102. sage/graphs/base/graph_backends.pyx +797 -0
  103. sage/graphs/base/overview.py +85 -0
  104. sage/graphs/base/sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  105. sage/graphs/base/sparse_graph.pxd +90 -0
  106. sage/graphs/base/sparse_graph.pyx +1653 -0
  107. sage/graphs/base/static_dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  108. sage/graphs/base/static_dense_graph.pxd +5 -0
  109. sage/graphs/base/static_dense_graph.pyx +1032 -0
  110. sage/graphs/base/static_sparse_backend.cpython-310-aarch64-linux-gnu.so +0 -0
  111. sage/graphs/base/static_sparse_backend.pxd +27 -0
  112. sage/graphs/base/static_sparse_backend.pyx +1583 -0
  113. sage/graphs/base/static_sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  114. sage/graphs/base/static_sparse_graph.pxd +37 -0
  115. sage/graphs/base/static_sparse_graph.pyx +1375 -0
  116. sage/graphs/bipartite_graph.py +2732 -0
  117. sage/graphs/centrality.cpython-310-aarch64-linux-gnu.so +0 -0
  118. sage/graphs/centrality.pyx +1038 -0
  119. sage/graphs/cographs.py +519 -0
  120. sage/graphs/comparability.cpython-310-aarch64-linux-gnu.so +0 -0
  121. sage/graphs/comparability.pyx +851 -0
  122. sage/graphs/connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
  123. sage/graphs/connectivity.pxd +157 -0
  124. sage/graphs/connectivity.pyx +4813 -0
  125. sage/graphs/convexity_properties.cpython-310-aarch64-linux-gnu.so +0 -0
  126. sage/graphs/convexity_properties.pxd +16 -0
  127. sage/graphs/convexity_properties.pyx +870 -0
  128. sage/graphs/digraph.py +4754 -0
  129. sage/graphs/digraph_generators.py +1993 -0
  130. sage/graphs/distances_all_pairs.cpython-310-aarch64-linux-gnu.so +0 -0
  131. sage/graphs/distances_all_pairs.pxd +12 -0
  132. sage/graphs/distances_all_pairs.pyx +2938 -0
  133. sage/graphs/domination.py +1363 -0
  134. sage/graphs/dot2tex_utils.py +100 -0
  135. sage/graphs/edge_connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
  136. sage/graphs/edge_connectivity.pyx +1215 -0
  137. sage/graphs/generators/all.py +1 -0
  138. sage/graphs/generators/basic.py +1769 -0
  139. sage/graphs/generators/chessboard.py +538 -0
  140. sage/graphs/generators/classical_geometries.py +1611 -0
  141. sage/graphs/generators/degree_sequence.py +235 -0
  142. sage/graphs/generators/distance_regular.cpython-310-aarch64-linux-gnu.so +0 -0
  143. sage/graphs/generators/distance_regular.pyx +2846 -0
  144. sage/graphs/generators/families.py +4759 -0
  145. sage/graphs/generators/intersection.py +565 -0
  146. sage/graphs/generators/platonic_solids.py +262 -0
  147. sage/graphs/generators/random.py +2623 -0
  148. sage/graphs/generators/smallgraphs.py +5741 -0
  149. sage/graphs/generators/world_map.py +724 -0
  150. sage/graphs/generic_graph.py +26867 -0
  151. sage/graphs/generic_graph_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  152. sage/graphs/generic_graph_pyx.pxd +34 -0
  153. sage/graphs/generic_graph_pyx.pyx +1673 -0
  154. sage/graphs/genus.cpython-310-aarch64-linux-gnu.so +0 -0
  155. sage/graphs/genus.pyx +622 -0
  156. sage/graphs/graph.py +9645 -0
  157. sage/graphs/graph_coloring.cpython-310-aarch64-linux-gnu.so +0 -0
  158. sage/graphs/graph_coloring.pyx +2284 -0
  159. sage/graphs/graph_database.py +1177 -0
  160. sage/graphs/graph_decompositions/all.py +1 -0
  161. sage/graphs/graph_decompositions/bandwidth.cpython-310-aarch64-linux-gnu.so +0 -0
  162. sage/graphs/graph_decompositions/bandwidth.pyx +428 -0
  163. sage/graphs/graph_decompositions/clique_separators.cpython-310-aarch64-linux-gnu.so +0 -0
  164. sage/graphs/graph_decompositions/clique_separators.pyx +616 -0
  165. sage/graphs/graph_decompositions/cutwidth.cpython-310-aarch64-linux-gnu.so +0 -0
  166. sage/graphs/graph_decompositions/cutwidth.pyx +753 -0
  167. sage/graphs/graph_decompositions/fast_digraph.cpython-310-aarch64-linux-gnu.so +0 -0
  168. sage/graphs/graph_decompositions/fast_digraph.pxd +13 -0
  169. sage/graphs/graph_decompositions/fast_digraph.pyx +212 -0
  170. sage/graphs/graph_decompositions/graph_products.cpython-310-aarch64-linux-gnu.so +0 -0
  171. sage/graphs/graph_decompositions/graph_products.pyx +508 -0
  172. sage/graphs/graph_decompositions/modular_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  173. sage/graphs/graph_decompositions/modular_decomposition.pxd +27 -0
  174. sage/graphs/graph_decompositions/modular_decomposition.pyx +1536 -0
  175. sage/graphs/graph_decompositions/slice_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  176. sage/graphs/graph_decompositions/slice_decomposition.pxd +18 -0
  177. sage/graphs/graph_decompositions/slice_decomposition.pyx +1106 -0
  178. sage/graphs/graph_decompositions/tree_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  179. sage/graphs/graph_decompositions/tree_decomposition.pxd +17 -0
  180. sage/graphs/graph_decompositions/tree_decomposition.pyx +1996 -0
  181. sage/graphs/graph_decompositions/vertex_separation.cpython-310-aarch64-linux-gnu.so +0 -0
  182. sage/graphs/graph_decompositions/vertex_separation.pxd +5 -0
  183. sage/graphs/graph_decompositions/vertex_separation.pyx +1963 -0
  184. sage/graphs/graph_editor.py +82 -0
  185. sage/graphs/graph_generators.py +3314 -0
  186. sage/graphs/graph_generators_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  187. sage/graphs/graph_generators_pyx.pyx +95 -0
  188. sage/graphs/graph_input.py +812 -0
  189. sage/graphs/graph_latex.py +2064 -0
  190. sage/graphs/graph_list.py +410 -0
  191. sage/graphs/graph_plot.py +1756 -0
  192. sage/graphs/graph_plot_js.py +338 -0
  193. sage/graphs/hyperbolicity.cpython-310-aarch64-linux-gnu.so +0 -0
  194. sage/graphs/hyperbolicity.pyx +1704 -0
  195. sage/graphs/hypergraph_generators.py +364 -0
  196. sage/graphs/independent_sets.cpython-310-aarch64-linux-gnu.so +0 -0
  197. sage/graphs/independent_sets.pxd +13 -0
  198. sage/graphs/independent_sets.pyx +402 -0
  199. sage/graphs/isgci.py +1033 -0
  200. sage/graphs/isoperimetric_inequalities.cpython-310-aarch64-linux-gnu.so +0 -0
  201. sage/graphs/isoperimetric_inequalities.pyx +489 -0
  202. sage/graphs/line_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  203. sage/graphs/line_graph.pyx +743 -0
  204. sage/graphs/lovasz_theta.py +77 -0
  205. sage/graphs/matching.py +1633 -0
  206. sage/graphs/matching_covered_graph.py +3590 -0
  207. sage/graphs/orientations.py +1489 -0
  208. sage/graphs/partial_cube.py +459 -0
  209. sage/graphs/path_enumeration.cpython-310-aarch64-linux-gnu.so +0 -0
  210. sage/graphs/path_enumeration.pyx +2040 -0
  211. sage/graphs/pq_trees.py +1129 -0
  212. sage/graphs/print_graphs.py +201 -0
  213. sage/graphs/schnyder.py +865 -0
  214. sage/graphs/spanning_tree.cpython-310-aarch64-linux-gnu.so +0 -0
  215. sage/graphs/spanning_tree.pyx +1457 -0
  216. sage/graphs/strongly_regular_db.cpython-310-aarch64-linux-gnu.so +0 -0
  217. sage/graphs/strongly_regular_db.pyx +3340 -0
  218. sage/graphs/traversals.cpython-310-aarch64-linux-gnu.so +0 -0
  219. sage/graphs/traversals.pxd +9 -0
  220. sage/graphs/traversals.pyx +1872 -0
  221. sage/graphs/trees.cpython-310-aarch64-linux-gnu.so +0 -0
  222. sage/graphs/trees.pxd +15 -0
  223. sage/graphs/trees.pyx +310 -0
  224. sage/graphs/tutte_polynomial.py +713 -0
  225. sage/graphs/views.cpython-310-aarch64-linux-gnu.so +0 -0
  226. sage/graphs/views.pyx +794 -0
  227. sage/graphs/weakly_chordal.cpython-310-aarch64-linux-gnu.so +0 -0
  228. sage/graphs/weakly_chordal.pyx +604 -0
  229. sage/groups/all__sagemath_graphs.py +1 -0
  230. sage/groups/perm_gps/all__sagemath_graphs.py +1 -0
  231. sage/groups/perm_gps/partn_ref/all__sagemath_graphs.py +1 -0
  232. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-310-aarch64-linux-gnu.so +0 -0
  233. sage/groups/perm_gps/partn_ref/refinement_graphs.pxd +38 -0
  234. sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +1666 -0
  235. sage/knots/all.py +6 -0
  236. sage/knots/free_knotinfo_monoid.py +507 -0
  237. sage/knots/gauss_code.py +291 -0
  238. sage/knots/knot.py +682 -0
  239. sage/knots/knot_table.py +284 -0
  240. sage/knots/knotinfo.py +2900 -0
  241. sage/knots/link.py +4715 -0
  242. sage/sandpiles/all.py +13 -0
  243. sage/sandpiles/examples.py +225 -0
  244. sage/sandpiles/sandpile.py +6365 -0
  245. sage/topology/all.py +22 -0
  246. sage/topology/cell_complex.py +1214 -0
  247. sage/topology/cubical_complex.py +1976 -0
  248. sage/topology/delta_complex.py +1806 -0
  249. sage/topology/filtered_simplicial_complex.py +744 -0
  250. sage/topology/moment_angle_complex.py +823 -0
  251. sage/topology/simplicial_complex.py +5160 -0
  252. sage/topology/simplicial_complex_catalog.py +92 -0
  253. sage/topology/simplicial_complex_examples.py +1680 -0
  254. sage/topology/simplicial_complex_homset.py +205 -0
  255. sage/topology/simplicial_complex_morphism.py +836 -0
  256. sage/topology/simplicial_set.py +4102 -0
  257. sage/topology/simplicial_set_catalog.py +55 -0
  258. sage/topology/simplicial_set_constructions.py +2954 -0
  259. sage/topology/simplicial_set_examples.py +865 -0
  260. sage/topology/simplicial_set_morphism.py +1464 -0
@@ -0,0 +1,625 @@
1
+ # sage_setup: distribution = sagemath-graphs
2
+ # sage.doctest: needs sage.graphs
3
+ r"""
4
+ mutation_class
5
+
6
+ This file contains helper functions for compute the mutation class of a cluster algebra or quiver.
7
+
8
+ For the compendium on the cluster algebra and quiver package see [MS2011]_
9
+
10
+ AUTHORS:
11
+
12
+ - Gregg Musiker
13
+ - Christian Stump
14
+ """
15
+ # ****************************************************************************
16
+ # Copyright (C) 2011 Gregg Musiker <musiker@math.mit.edu>
17
+ # Christian Stump <christian.stump@univie.ac.at>
18
+ #
19
+ # Distributed under the terms of the GNU General Public License (GPL)
20
+ # https://www.gnu.org/licenses/
21
+ # ****************************************************************************
22
+
23
+ import time
24
+ from sage.groups.perm_gps.partn_ref.refinement_graphs import search_tree, get_orbits
25
+ from sage.rings.integer_ring import ZZ
26
+ from sage.rings.infinity import infinity
27
+ from sage.graphs.digraph import DiGraph
28
+ from sage.combinat.cluster_algebra_quiver.quiver_mutation_type import _edge_list_to_matrix
29
+
30
+
31
+ def _principal_part(mat):
32
+ """
33
+ Return the principal part of a matrix.
34
+
35
+ INPUT:
36
+
37
+ - ``mat`` -- a matrix with at least as many rows as columns
38
+
39
+ OUTPUT: the top square part of the matrix ``mat``
40
+
41
+ EXAMPLES::
42
+
43
+ sage: from sage.combinat.cluster_algebra_quiver.mutation_class import _principal_part
44
+ sage: M = Matrix([[1,2],[3,4],[5,6]]); M # needs sage.modules
45
+ [1 2]
46
+ [3 4]
47
+ [5 6]
48
+ sage: _principal_part(M) # needs sage.modules
49
+ [1 2]
50
+ [3 4]
51
+ """
52
+ n, m = mat.ncols(), mat.nrows() - mat.ncols()
53
+ if m < 0:
54
+ raise ValueError('the input matrix has more columns than rows')
55
+ elif m == 0:
56
+ return mat
57
+ else:
58
+ return mat.submatrix(0, 0, n, n)
59
+
60
+
61
+ def _digraph_mutate(dg, k, frozen=None):
62
+ """
63
+ Return a digraph obtained from ``dg`` by mutating at vertex ``k``.
64
+
65
+ Vertices can be labelled by anything, and frozen vertices must
66
+ be explicitly given.
67
+
68
+ INPUT:
69
+
70
+ - ``dg`` -- a digraph with integral edge labels with ``n+m`` vertices
71
+ - ``k`` -- the vertex at which ``dg`` is mutated
72
+ - ``frozen`` -- the list of frozen vertices (default: empty list)
73
+
74
+ EXAMPLES::
75
+
76
+ sage: from sage.combinat.cluster_algebra_quiver.mutation_class import _digraph_mutate
77
+ sage: from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver
78
+ sage: dg = ClusterQuiver(['A',4]).digraph() # needs sage.modules
79
+ sage: dg.edges(sort=True) # needs sage.modules
80
+ [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -1))]
81
+ sage: _digraph_mutate(dg,2).edges(sort=True) # needs sage.modules
82
+ [(0, 1, (1, -1)), (1, 2, (1, -1)), (3, 2, (1, -1))]
83
+
84
+ TESTS::
85
+
86
+ sage: dg = DiGraph([('a','b',(1,-1)),('c','a',(1,-1))])
87
+ sage: _digraph_mutate(dg,'a').edges(sort=True)
88
+ [('a', 'c', (1, -1)), ('b', 'a', (1, -1)), ('c', 'b', (1, -1))]
89
+ sage: _digraph_mutate(dg,'a',frozen=['b','c']).edges(sort=True)
90
+ [('a', 'c', (1, -1)), ('b', 'a', (1, -1))]
91
+
92
+ sage: dg = DiGraph([('a','b',(2,-2)),('c','a',(2,-2)),('b','c',(2,-2))])
93
+ sage: _digraph_mutate(dg,'a').edges(sort=True)
94
+ [('a', 'c', (2, -2)), ('b', 'a', (2, -2)), ('c', 'b', (2, -2))]
95
+ """
96
+ # assert sorted(list(dg)) == list(range(n + m))
97
+ # this is not assumed anymore
98
+ if frozen is None:
99
+ frozen = []
100
+
101
+ edge_it = dg.incoming_edge_iterator(dg, True)
102
+ edges = {(v1, v2): label for v1, v2, label in edge_it}
103
+ edge_it = dg.incoming_edge_iterator([k], True)
104
+ in_edges = list(edge_it)
105
+ edge_it = dg.outgoing_edge_iterator([k], True)
106
+ out_edges = list(edge_it)
107
+
108
+ in_edges_new = [(v2, v1, (-label[1], -label[0]))
109
+ for (v1, v2, label) in in_edges]
110
+ out_edges_new = [(v2, v1, (-label[1], -label[0]))
111
+ for (v1, v2, label) in out_edges]
112
+ diag_edges_new = []
113
+ diag_edges_del = []
114
+
115
+ for (v1, v2, label1) in in_edges:
116
+ l11, l12 = label1
117
+ for (w1, w2, label2) in out_edges:
118
+ if v1 in frozen and w2 in frozen:
119
+ continue
120
+ l21, l22 = label2
121
+ if (v1, w2) in edges:
122
+ diag_edges_del.append((v1, w2))
123
+ a, b = edges[(v1, w2)]
124
+ a, b = a + l11 * l21, b - l12 * l22
125
+ diag_edges_new.append((v1, w2, (a, b)))
126
+ elif (w2, v1) in edges:
127
+ diag_edges_del.append((w2, v1))
128
+ a, b = edges[(w2, v1)]
129
+ a, b = b + l11 * l21, a - l12 * l22
130
+ if a < 0:
131
+ diag_edges_new.append((w2, v1, (b, a)))
132
+ elif a > 0:
133
+ diag_edges_new.append((v1, w2, (a, b)))
134
+ else:
135
+ a, b = l11 * l21, -l12 * l22
136
+ diag_edges_new.append((v1, w2, (a, b)))
137
+
138
+ del_edges = [tuple(ed[:2]) for ed in in_edges + out_edges]
139
+ del_edges += diag_edges_del
140
+ new_edges = in_edges_new + out_edges_new
141
+ new_edges += diag_edges_new
142
+ new_edges += [(v1, v2, edges[(v1, v2)]) for (v1, v2) in edges
143
+ if (v1, v2) not in del_edges]
144
+
145
+ dg_new = DiGraph()
146
+ dg_new.add_vertices(list(dg))
147
+ for v1, v2, label in new_edges:
148
+ dg_new.add_edge(v1, v2, label)
149
+
150
+ return dg_new
151
+
152
+
153
+ def _matrix_to_digraph(M):
154
+ """
155
+ Return the digraph obtained from the matrix ``M``.
156
+
157
+ In order to generate a quiver, we assume that ``M`` is skew-symmetrizable.
158
+
159
+ EXAMPLES::
160
+
161
+ sage: from sage.combinat.cluster_algebra_quiver.mutation_class import _matrix_to_digraph
162
+ sage: _matrix_to_digraph(matrix(3,[0,1,0,-1,0,-1,0,1,0])) # needs sage.modules
163
+ Digraph on 3 vertices
164
+ """
165
+ n = M.ncols()
166
+
167
+ dg = DiGraph(sparse=True)
168
+ for i, j in M.nonzero_positions():
169
+ if i >= n:
170
+ a, b = M[i, j], -M[i, j]
171
+ else:
172
+ a, b = M[i, j], M[j, i]
173
+ if a > 0:
174
+ dg._backend.add_edge(i, j, (a, b), True)
175
+ elif i >= n:
176
+ dg._backend.add_edge(j, i, (-a, -b), True)
177
+ for i in range(M.nrows()):
178
+ if i not in dg:
179
+ dg.add_vertex(i)
180
+ return dg
181
+
182
+
183
+ def _dg_canonical_form(dg, frozen=None):
184
+ """
185
+ Turn the digraph ``dg`` into its canonical form, and return the
186
+ corresponding isomorphism and the vertex orbits of the automorphism group.
187
+
188
+ The labels of ``dg`` are assumed to be integers between `0` and `n + m - 1`.
189
+
190
+ The canonical form has the following additional property: the frozen
191
+ vertices are the final labels.
192
+
193
+ .. WARNING:: The input ``dg`` is modified.
194
+
195
+ INPUT:
196
+
197
+ - ``dg`` -- a directed graph having edge labels (a, b) with a > 0
198
+
199
+ - ``frozen`` -- list (default: ``[]``) of frozen vertices
200
+
201
+ OUTPUT: dictionary {original label: canonical label}
202
+
203
+ - list of orbits of mutable vertices (using canonical labels)
204
+
205
+ EXAMPLES::
206
+
207
+ sage: from sage.combinat.cluster_algebra_quiver.mutation_class import _dg_canonical_form
208
+ sage: dg = ClusterQuiver(['B',4]).digraph(); dg.edges(sort=True) # needs sage.modules
209
+ [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -2))]
210
+ sage: _dg_canonical_form(dg); dg.edges(sort=True) # needs sage.modules
211
+ ({0: 0, 1: 3, 2: 1, 3: 2}, [[0], [3], [1], [2]])
212
+ [(0, 3, (1, -1)), (1, 2, (1, -2)), (1, 3, (1, -1))]
213
+
214
+ TESTS::
215
+
216
+ sage: dg2 = ClusterQuiver(DiGraph({0:[1,2]})).digraph() # needs sage.modules
217
+ sage: _dg_canonical_form(dg2); dg2.edges(sort=True) # needs sage.modules
218
+ ({0: 0, 1: 1, 2: 2}, [[0], [1, 2]])
219
+ [(0, 1, (1, -1)), (0, 2, (1, -1))]
220
+
221
+ sage: dg2 = ClusterQuiver(DiGraph({0:[1,2]})).digraph() # needs sage.modules
222
+ sage: _dg_canonical_form(dg2, frozen=[0]); dg2.edges(sort=True) # needs sage.modules
223
+ ({0: 2, 1: 0, 2: 1}, [[2], [0, 1]])
224
+ [(2, 0, (1, -1)), (2, 1, (1, -1))]
225
+
226
+ sage: dg3 = ClusterQuiver(DiGraph({0:[1,2],1:[3]})).digraph() # needs sage.modules
227
+ sage: _dg_canonical_form(dg3, frozen=[0,3]); dg3.edges(sort=True) # needs sage.modules
228
+ ({0: 2, 1: 1, 2: 0, 3: 3}, [[2], [1], [0], [3]])
229
+ [(1, 3, (1, -1)), (2, 0, (1, -1)), (2, 1, (1, -1))]
230
+
231
+ sage: dg3 = ClusterQuiver(DiGraph({2:[1,3],1:[0],3:[4]})).digraph() # needs sage.modules
232
+ sage: _dg_canonical_form(dg3, frozen=[4,0]); dg3.edges(sort=True) # needs sage.modules
233
+ ({0: 4, 1: 1, 2: 0, 3: 2, 4: 3}, [[4, 3], [1, 2], [0]])
234
+ [(0, 1, (1, -1)), (0, 2, (1, -1)), (1, 4, (1, -1)), (2, 3, (1, -1))]
235
+ """
236
+ vertices = list(dg)
237
+ n_plus_m = dg.order()
238
+ if frozen is not None:
239
+ partition = [[v for v in vertices if v not in frozen], frozen]
240
+ else:
241
+ frozen = []
242
+ partition = [ vertices ]
243
+
244
+ # here dg is modified by inserting new vertices at middle of edges
245
+ partition_add, edges = _graph_without_edge_labels(dg, vertices)
246
+
247
+ partition += partition_add
248
+ automorphism_group, _, iso = search_tree(dg, partition=partition, lab=True,
249
+ dig=True, certificate=True)
250
+ orbits = get_orbits(automorphism_group, n_plus_m)
251
+ orbits = [[iso[i] for i in orbit] for orbit in orbits]
252
+
253
+ removed = []
254
+ for v in iso:
255
+ if v not in vertices:
256
+ removed.append(v)
257
+ v1, _, _ = next(dg._backend.iterator_in_edges([v], True))
258
+ _, w2, _ = next(dg._backend.iterator_out_edges([v], True))
259
+ dg._backend.del_vertex(v)
260
+ add_index = True
261
+ index = 0
262
+ while add_index:
263
+ l = partition_add[index]
264
+ if v in l:
265
+ dg._backend.add_edge(v1, w2, edges[index], True)
266
+ add_index = False
267
+ index += 1
268
+ for v in removed:
269
+ del iso[v]
270
+
271
+ dg._backend.relabel(iso, True)
272
+ return iso, orbits
273
+
274
+
275
+ def _mutation_class_iter( dg, n, m, depth=infinity, return_dig6=False, show_depth=False, up_to_equivalence=True, sink_source=False ):
276
+ """
277
+ Return an iterator for mutation class of dg with respect to several parameters.
278
+
279
+ .. NOTE:: assuming that the frozen vertices start at vertex n.
280
+
281
+ INPUT:
282
+
283
+ - ``dg`` -- a digraph with `n+m` vertices
284
+ - ``depth`` -- positive integer or infinity specifying (roughly) how many
285
+ steps away from the initial seed to mutate
286
+ - ``return_dig6`` -- indicates whether to convert digraph data to dig6
287
+ string data
288
+ - ``show_depth`` -- if ``True``, indicates that a running count of the
289
+ depth is to be displayed
290
+ - ``up_to_equivalence`` -- if ``True``, only one digraph for each
291
+ graph-isomorphism class is recorded
292
+ - ``sink_source`` -- if ``True``, only mutations at sinks or sources are
293
+ applied
294
+
295
+ EXAMPLES::
296
+
297
+ sage: # needs sage.modules
298
+ sage: from sage.combinat.cluster_algebra_quiver.mutation_class import _mutation_class_iter
299
+ sage: from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver
300
+ sage: dg = ClusterQuiver(['A',[1,2],1]).digraph()
301
+ sage: itt = _mutation_class_iter(dg, 3,0)
302
+ sage: next(itt)[0].edges(sort=True)
303
+ [(0, 1, (1, -1)), (0, 2, (1, -1)), (1, 2, (1, -1))]
304
+ sage: next(itt)[0].edges(sort=True)
305
+ [(0, 2, (1, -1)), (1, 0, (2, -2)), (2, 1, (1, -1))]
306
+ """
307
+ # assuming that the frozen vertices are at the end (from n to n + m - 1)
308
+ # assert sorted(dg) == list(range(n + m)) # commented out for speed
309
+ mlist = list(range(n, n + m))
310
+
311
+ timer = time.time()
312
+ depth_counter = 0
313
+ if up_to_equivalence:
314
+ iso, orbits = _dg_canonical_form( dg, mlist )
315
+ iso_inv = { iso[a]: a for a in iso }
316
+
317
+ dig6 = _digraph_to_dig6( dg, hashable=True )
318
+ dig6s = {}
319
+ if up_to_equivalence:
320
+ orbits = [ orbit[0] for orbit in orbits ]
321
+ dig6s[dig6] = [ orbits, [], iso_inv ]
322
+ else:
323
+ dig6s[dig6] = [list(range(n)), [] ]
324
+ if return_dig6:
325
+ yield (dig6, [])
326
+ else:
327
+ yield (dg, [])
328
+
329
+ gets_bigger = True
330
+ if show_depth:
331
+ timer2 = time.time()
332
+ dc = str(depth_counter)
333
+ dc += ' ' * (5 - len(dc))
334
+ nr = str(len(dig6s))
335
+ nr += ' ' * (10 - len(nr))
336
+ print(f"Depth: {dc} found: {nr} Time: {timer2 - timer:.2f} s")
337
+
338
+ while gets_bigger and depth_counter < depth:
339
+ gets_bigger = False
340
+ for key in list(dig6s):
341
+ mutation_indices = [ i for i in dig6s[key][0] if i < n ]
342
+ if mutation_indices:
343
+ dg = _dig6_to_digraph( key )
344
+ while mutation_indices:
345
+ i = mutation_indices.pop()
346
+ if not sink_source or _dg_is_sink_source( dg, i ):
347
+ dg_new = _digraph_mutate(dg, i, frozen=mlist)
348
+ if up_to_equivalence:
349
+ iso, orbits = _dg_canonical_form( dg_new, mlist )
350
+ i_new = iso[i]
351
+ iso_inv = { iso[a]: a for a in iso }
352
+ else:
353
+ i_new = i
354
+ dig6_new = _digraph_to_dig6( dg_new, hashable=True )
355
+ if dig6_new in dig6s:
356
+ if i_new in dig6s[dig6_new][0]:
357
+ dig6s[dig6_new][0].remove(i_new)
358
+ else:
359
+ gets_bigger = True
360
+ if up_to_equivalence:
361
+ orbits = [ orbit[0] for orbit in orbits if i_new not in orbit ]
362
+ iso_history = { a: dig6s[key][2][iso_inv[a]] for a in iso }
363
+ i_history = iso_history[i_new]
364
+ history = dig6s[key][1] + [i_history]
365
+ dig6s[dig6_new] = [orbits,history,iso_history]
366
+ else:
367
+ orbits = list(range(n))
368
+ del orbits[i_new]
369
+ history = dig6s[key][1] + [i_new]
370
+ dig6s[dig6_new] = [orbits,history]
371
+ if return_dig6:
372
+ yield (dig6_new,history)
373
+ else:
374
+ yield (dg_new,history)
375
+ depth_counter += 1
376
+ if show_depth and gets_bigger:
377
+ timer2 = time.time()
378
+ dc = str(depth_counter)
379
+ dc += ' ' * (5 - len(dc))
380
+ nr = str(len(dig6s))
381
+ nr += ' ' * (10 - len(nr))
382
+ print(f"Depth: {dc} found: {nr} Time: {timer2 - timer:.2f} s")
383
+
384
+
385
+ def _digraph_to_dig6(dg, hashable=False):
386
+ """
387
+ Return the dig6 and edge data of the digraph dg.
388
+
389
+ INPUT:
390
+
391
+ - ``dg`` -- a digraph
392
+ - ``hashable`` -- boolean (default: ``False``); if ``True``, the edge
393
+ labels are turned into a dict
394
+
395
+ EXAMPLES::
396
+
397
+ sage: from sage.combinat.cluster_algebra_quiver.mutation_class import _digraph_to_dig6
398
+ sage: from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver
399
+ sage: dg = ClusterQuiver(['A',4]).digraph() # needs sage.modules
400
+ sage: _digraph_to_dig6(dg) # needs sage.modules
401
+ ('COD?', {})
402
+ """
403
+ dig6 = dg.dig6_string()
404
+ D = {}
405
+ for E in dg._backend.iterator_in_edges(dg,True):
406
+ if E[2] != (1,-1):
407
+ D[ (E[0],E[1]) ] = E[2]
408
+ if hashable:
409
+ D = tuple( sorted( D.items() ) )
410
+ return (dig6,D)
411
+
412
+
413
+ def _dig6_to_digraph( dig6 ):
414
+ """
415
+ Return the digraph obtained from the dig6 and edge data.
416
+
417
+ INPUT:
418
+
419
+ - ``dig6`` -- a pair ``(dig6, edges)`` where ``dig6`` is a string encoding a digraph and ``edges`` is a dict or tuple encoding edges
420
+
421
+ EXAMPLES::
422
+
423
+ sage: # needs sage.modules
424
+ sage: from sage.combinat.cluster_algebra_quiver.mutation_class import _digraph_to_dig6
425
+ sage: from sage.combinat.cluster_algebra_quiver.mutation_class import _dig6_to_digraph
426
+ sage: from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver
427
+ sage: dg = ClusterQuiver(['A',4]).digraph()
428
+ sage: data = _digraph_to_dig6(dg)
429
+ sage: _dig6_to_digraph(data)
430
+ Digraph on 4 vertices
431
+ sage: _dig6_to_digraph(data).edges(sort=True)
432
+ [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -1))]
433
+ """
434
+ dig6, edges = dig6
435
+ dg = DiGraph( dig6 )
436
+ if not isinstance(edges, dict):
437
+ edges = dict( edges )
438
+ for edge in dg._backend.iterator_in_edges(dg,False):
439
+ if edge in edges:
440
+ dg.set_edge_label( edge[0],edge[1],edges[edge] )
441
+ else:
442
+ dg.set_edge_label( edge[0],edge[1], (1,-1) )
443
+ return dg
444
+
445
+
446
+ def _dig6_to_matrix( dig6 ):
447
+ """
448
+ Return the matrix obtained from the dig6 and edge data.
449
+
450
+ INPUT:
451
+
452
+ - ``dig6`` -- a pair ``(dig6, edges)`` where ``dig6`` is a string
453
+ encoding a digraph and ``edges`` is a dict or tuple encoding edges
454
+
455
+ EXAMPLES::
456
+
457
+ sage: from sage.combinat.cluster_algebra_quiver.mutation_class import _digraph_to_dig6, _dig6_to_matrix
458
+ sage: from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver
459
+ sage: dg = ClusterQuiver(['A',4]).digraph() # needs sage.modules
460
+ sage: data = _digraph_to_dig6(dg) # needs sage.modules
461
+ sage: _dig6_to_matrix(data) # needs sage.modules
462
+ [ 0 1 0 0]
463
+ [-1 0 -1 0]
464
+ [ 0 1 0 1]
465
+ [ 0 0 -1 0]
466
+ """
467
+ dg = _dig6_to_digraph(dig6)
468
+ return _edge_list_to_matrix(dg.edges(sort=True), list(range(dg.order())), [])
469
+
470
+
471
+ def _dg_is_sink_source( dg, v ):
472
+ """
473
+ Return ``True`` iff the digraph dg has a sink or a source at vertex `v`.
474
+
475
+ INPUT:
476
+
477
+ - ``dg`` -- a digraph
478
+ - ``v`` -- a vertex of dg
479
+
480
+ EXAMPLES::
481
+
482
+ sage: # needs sage.modules
483
+ sage: from sage.combinat.cluster_algebra_quiver.mutation_class import _dg_is_sink_source
484
+ sage: from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver
485
+ sage: dg = ClusterQuiver(['A',[1,2],1]).digraph()
486
+ sage: _dg_is_sink_source(dg, 0)
487
+ True
488
+ sage: _dg_is_sink_source(dg, 1)
489
+ True
490
+ sage: _dg_is_sink_source(dg, 2)
491
+ False
492
+ """
493
+ in_edges = list(dg._backend.iterator_in_edges([v],True))
494
+ out_edges = list(dg._backend.iterator_out_edges([v],True))
495
+ return not ( in_edges and out_edges )
496
+
497
+
498
+ def _graph_without_edge_labels(dg, vertices):
499
+ """
500
+ Expand the graph, by introducing new vertices in the middle of edges.
501
+ Return the corresponding partition of the new vertices.
502
+
503
+ There is one new vertex for each edge with label not equal to ``(1,-1)``.
504
+ These vertices are numbered starting from the smallest available integer.
505
+
506
+ Each edge having a non-trivial label is replaced by two consecutive edges,
507
+ passing through one new vertex.
508
+
509
+ EXAMPLES::
510
+
511
+ sage: from sage.combinat.cluster_algebra_quiver.mutation_class import _graph_without_edge_labels
512
+ sage: from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver
513
+ sage: dg = ClusterQuiver(['B',4]).digraph(); dg.edges(sort=True) # needs sage.modules
514
+ [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -2))]
515
+ sage: _graph_without_edge_labels(dg, range(4)); dg.edges(sort=True) # needs sage.modules
516
+ ([[4]], ((1, -2),))
517
+ [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 4, (1, -1)), (4, 3, (1, -1))]
518
+ """
519
+ vertices = list(vertices)
520
+ edges = dg.edge_iterator(labels=True)
521
+ edge_labels = tuple(sorted({label for _, _, label in edges
522
+ if label != (1, -1)}))
523
+ edge_partition = [[] for _ in edge_labels]
524
+ i = 0
525
+ while i in vertices:
526
+ i += 1
527
+
528
+ # We have to pass the old vertices to the iterator.
529
+ # Otherwise the ``edge_iterator`` will use the ``vertices``
530
+ # of ``dg``, which are not well-defined, if we add vertices along the way.
531
+ for u, v, label in dg.edge_iterator(vertices=vertices, labels=True):
532
+ if label != (1, -1): # Ignore edges we just added.
533
+ index = edge_labels.index(label)
534
+ edge_partition[index].append(i)
535
+ dg._backend.add_edge(u, i, (1, -1), True)
536
+ dg._backend.add_edge(i, v, (1, -1), True)
537
+ dg._backend.del_edge(u, v, label, True)
538
+ i += 1
539
+ while i in vertices:
540
+ i += 1
541
+ return edge_partition, edge_labels
542
+
543
+
544
+ def _has_two_cycles( dg ):
545
+ """
546
+ Return ``True`` if the input digraph has a 2-cycle and ``False`` otherwise.
547
+
548
+ EXAMPLES::
549
+
550
+ sage: from sage.combinat.cluster_algebra_quiver.mutation_class import _has_two_cycles
551
+ sage: _has_two_cycles(DiGraph([[0,1],[1,0]]))
552
+ True
553
+ sage: from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver
554
+ sage: _has_two_cycles(ClusterQuiver(['A',3]).digraph()) # needs sage.modules
555
+ False
556
+ """
557
+ edge_set = dg.edges(sort=True, labels=False)
558
+ for (v,w) in edge_set:
559
+ if (w,v) in edge_set:
560
+ return True
561
+ return False
562
+
563
+
564
+ def _is_valid_digraph_edge_set( edges, frozen=0 ):
565
+ """
566
+ Return ``True`` if the input data is the edge set of a digraph for a quiver
567
+ (no loops, no 2-cycles, edge-labels of the specified format), and return
568
+ ``False`` otherwise.
569
+
570
+ INPUT:
571
+
572
+ - ``frozen`` -- integer (default: 0); the number of frozen vertices
573
+
574
+ EXAMPLES::
575
+
576
+ sage: from sage.combinat.cluster_algebra_quiver.mutation_class import _is_valid_digraph_edge_set
577
+ sage: _is_valid_digraph_edge_set( [[0,1,'a'],[2,3,(1,-1)]] )
578
+ The given digraph has edge labels which are not integral or integral 2-tuples.
579
+ False
580
+ sage: _is_valid_digraph_edge_set( [[0,1,None],[2,3,(1,-1)]] )
581
+ True
582
+ sage: _is_valid_digraph_edge_set( [[0,1,'a'],[2,3,(1,-1)],[3,2,(1,-1)]] )
583
+ The given digraph or edge list contains oriented 2-cycles.
584
+ False
585
+ """
586
+ try:
587
+ dg = DiGraph()
588
+ dg.allow_multiple_edges(True)
589
+ dg.add_edges( edges )
590
+
591
+ # checks if the digraph contains loops
592
+ if dg.has_loops():
593
+ print("The given digraph or edge list contains loops")
594
+ return False
595
+
596
+ # checks if the digraph contains oriented 2-cycles
597
+ if _has_two_cycles( dg ):
598
+ print("The given digraph or edge list contains oriented 2-cycles.")
599
+ return False
600
+
601
+ # checks if all edge labels are 'None', positive integers or tuples of positive integers
602
+ if not all( i is None or ( i in ZZ and i > 0 ) or ( isinstance(i, tuple) and len(i) == 2 and i[0] in ZZ and i[1] in ZZ ) for i in dg.edge_labels() ):
603
+ print("The given digraph has edge labels which are not integral or integral 2-tuples.")
604
+ return False
605
+
606
+ # checks if all edge labels for multiple edges are 'None' or positive integers
607
+ if dg.has_multiple_edges():
608
+ for e in set( dg.multiple_edges(labels=False) ):
609
+ if not all( i is None or ( i in ZZ and i > 0 ) for i in dg.edge_label( e[0], e[1] ) ):
610
+ print("The given digraph or edge list contains multiple edges with non-integral labels.")
611
+ return False
612
+
613
+ n = dg.order() - frozen
614
+ if n < 0:
615
+ print("The number of frozen variables is larger than the number of vertices.")
616
+ return False
617
+
618
+ if any(e[0] >= n for e in dg.edges(sort=True, labels=False)):
619
+ print("The given digraph or edge list contains edges within the frozen vertices.")
620
+ return False
621
+
622
+ return True
623
+ except Exception:
624
+ print("Could not even build a digraph from the input data.")
625
+ return False