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.
- passagemath_graphs-10.6.1rc1.dist-info/METADATA +292 -0
- passagemath_graphs-10.6.1rc1.dist-info/RECORD +260 -0
- passagemath_graphs-10.6.1rc1.dist-info/WHEEL +5 -0
- passagemath_graphs-10.6.1rc1.dist-info/top_level.txt +2 -0
- passagemath_graphs.libs/libgcc_s-69c45f16.so.1 +0 -0
- passagemath_graphs.libs/libgmp-8e78bd9b.so.10.5.0 +0 -0
- passagemath_graphs.libs/libstdc++-1f1a71be.so.6.0.33 +0 -0
- sage/all__sagemath_graphs.py +39 -0
- sage/combinat/abstract_tree.py +2723 -0
- sage/combinat/all__sagemath_graphs.py +34 -0
- sage/combinat/binary_tree.py +5306 -0
- sage/combinat/cluster_algebra_quiver/all.py +22 -0
- sage/combinat/cluster_algebra_quiver/cluster_seed.py +5208 -0
- sage/combinat/cluster_algebra_quiver/interact.py +124 -0
- sage/combinat/cluster_algebra_quiver/mutation_class.py +625 -0
- sage/combinat/cluster_algebra_quiver/mutation_type.py +1555 -0
- sage/combinat/cluster_algebra_quiver/quiver.py +2290 -0
- sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py +2468 -0
- sage/combinat/designs/MOLS_handbook_data.py +570 -0
- sage/combinat/designs/all.py +58 -0
- sage/combinat/designs/bibd.py +1655 -0
- sage/combinat/designs/block_design.py +1071 -0
- sage/combinat/designs/covering_array.py +269 -0
- sage/combinat/designs/covering_design.py +530 -0
- sage/combinat/designs/database.py +5615 -0
- sage/combinat/designs/design_catalog.py +122 -0
- sage/combinat/designs/designs_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/designs_pyx.pxd +21 -0
- sage/combinat/designs/designs_pyx.pyx +993 -0
- sage/combinat/designs/difference_family.py +3951 -0
- sage/combinat/designs/difference_matrices.py +279 -0
- sage/combinat/designs/evenly_distributed_sets.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/evenly_distributed_sets.pyx +661 -0
- sage/combinat/designs/ext_rep.py +1064 -0
- sage/combinat/designs/gen_quadrangles_with_spread.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/gen_quadrangles_with_spread.pyx +339 -0
- sage/combinat/designs/group_divisible_designs.py +361 -0
- sage/combinat/designs/incidence_structures.py +2357 -0
- sage/combinat/designs/latin_squares.py +581 -0
- sage/combinat/designs/orthogonal_arrays.py +2244 -0
- sage/combinat/designs/orthogonal_arrays_build_recursive.py +1780 -0
- sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +967 -0
- sage/combinat/designs/resolvable_bibd.py +815 -0
- sage/combinat/designs/steiner_quadruple_systems.py +1306 -0
- sage/combinat/designs/subhypergraph_search.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/subhypergraph_search.pyx +530 -0
- sage/combinat/designs/twographs.py +306 -0
- sage/combinat/finite_state_machine.py +14874 -0
- sage/combinat/finite_state_machine_generators.py +2006 -0
- sage/combinat/graph_path.py +448 -0
- sage/combinat/interval_posets.py +3908 -0
- sage/combinat/nu_tamari_lattice.py +269 -0
- sage/combinat/ordered_tree.py +1446 -0
- sage/combinat/posets/all.py +46 -0
- sage/combinat/posets/bubble_shuffle.py +247 -0
- sage/combinat/posets/cartesian_product.py +493 -0
- sage/combinat/posets/d_complete.py +182 -0
- sage/combinat/posets/elements.py +273 -0
- sage/combinat/posets/forest.py +30 -0
- sage/combinat/posets/hasse_cython.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/posets/hasse_cython.pyx +174 -0
- sage/combinat/posets/hasse_diagram.py +3672 -0
- sage/combinat/posets/hochschild_lattice.py +158 -0
- sage/combinat/posets/incidence_algebras.py +794 -0
- sage/combinat/posets/lattices.py +5117 -0
- sage/combinat/posets/linear_extension_iterator.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/posets/linear_extension_iterator.pyx +292 -0
- sage/combinat/posets/linear_extensions.py +1037 -0
- sage/combinat/posets/mobile.py +275 -0
- sage/combinat/posets/moebius_algebra.py +776 -0
- sage/combinat/posets/poset_examples.py +2178 -0
- sage/combinat/posets/posets.py +9360 -0
- sage/combinat/rooted_tree.py +1070 -0
- sage/combinat/shard_order.py +239 -0
- sage/combinat/tamari_lattices.py +384 -0
- sage/combinat/yang_baxter_graph.py +923 -0
- sage/databases/all__sagemath_graphs.py +1 -0
- sage/databases/knotinfo_db.py +1231 -0
- sage/ext_data/all__sagemath_graphs.py +1 -0
- sage/ext_data/graphs/graph_plot_js.html +330 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/graphs/all.py +42 -0
- sage/graphs/asteroidal_triples.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/asteroidal_triples.pyx +320 -0
- sage/graphs/base/all.py +1 -0
- sage/graphs/base/boost_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/boost_graph.pxd +106 -0
- sage/graphs/base/boost_graph.pyx +3045 -0
- sage/graphs/base/c_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/c_graph.pxd +106 -0
- sage/graphs/base/c_graph.pyx +5096 -0
- sage/graphs/base/dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/dense_graph.pxd +28 -0
- sage/graphs/base/dense_graph.pyx +801 -0
- sage/graphs/base/graph_backends.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/graph_backends.pxd +5 -0
- sage/graphs/base/graph_backends.pyx +797 -0
- sage/graphs/base/overview.py +85 -0
- sage/graphs/base/sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/sparse_graph.pxd +90 -0
- sage/graphs/base/sparse_graph.pyx +1653 -0
- sage/graphs/base/static_dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/static_dense_graph.pxd +5 -0
- sage/graphs/base/static_dense_graph.pyx +1032 -0
- sage/graphs/base/static_sparse_backend.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/static_sparse_backend.pxd +27 -0
- sage/graphs/base/static_sparse_backend.pyx +1583 -0
- sage/graphs/base/static_sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/static_sparse_graph.pxd +37 -0
- sage/graphs/base/static_sparse_graph.pyx +1375 -0
- sage/graphs/bipartite_graph.py +2732 -0
- sage/graphs/centrality.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/centrality.pyx +1038 -0
- sage/graphs/cographs.py +519 -0
- sage/graphs/comparability.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/comparability.pyx +851 -0
- sage/graphs/connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/connectivity.pxd +157 -0
- sage/graphs/connectivity.pyx +4813 -0
- sage/graphs/convexity_properties.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/convexity_properties.pxd +16 -0
- sage/graphs/convexity_properties.pyx +870 -0
- sage/graphs/digraph.py +4754 -0
- sage/graphs/digraph_generators.py +1993 -0
- sage/graphs/distances_all_pairs.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/distances_all_pairs.pxd +12 -0
- sage/graphs/distances_all_pairs.pyx +2938 -0
- sage/graphs/domination.py +1363 -0
- sage/graphs/dot2tex_utils.py +100 -0
- sage/graphs/edge_connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/edge_connectivity.pyx +1215 -0
- sage/graphs/generators/all.py +1 -0
- sage/graphs/generators/basic.py +1769 -0
- sage/graphs/generators/chessboard.py +538 -0
- sage/graphs/generators/classical_geometries.py +1611 -0
- sage/graphs/generators/degree_sequence.py +235 -0
- sage/graphs/generators/distance_regular.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/generators/distance_regular.pyx +2846 -0
- sage/graphs/generators/families.py +4759 -0
- sage/graphs/generators/intersection.py +565 -0
- sage/graphs/generators/platonic_solids.py +262 -0
- sage/graphs/generators/random.py +2623 -0
- sage/graphs/generators/smallgraphs.py +5741 -0
- sage/graphs/generators/world_map.py +724 -0
- sage/graphs/generic_graph.py +26867 -0
- sage/graphs/generic_graph_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/generic_graph_pyx.pxd +34 -0
- sage/graphs/generic_graph_pyx.pyx +1673 -0
- sage/graphs/genus.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/genus.pyx +622 -0
- sage/graphs/graph.py +9645 -0
- sage/graphs/graph_coloring.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_coloring.pyx +2284 -0
- sage/graphs/graph_database.py +1177 -0
- sage/graphs/graph_decompositions/all.py +1 -0
- sage/graphs/graph_decompositions/bandwidth.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/bandwidth.pyx +428 -0
- sage/graphs/graph_decompositions/clique_separators.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.pyx +616 -0
- sage/graphs/graph_decompositions/cutwidth.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/cutwidth.pyx +753 -0
- sage/graphs/graph_decompositions/fast_digraph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.pxd +13 -0
- sage/graphs/graph_decompositions/fast_digraph.pyx +212 -0
- sage/graphs/graph_decompositions/graph_products.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/graph_products.pyx +508 -0
- sage/graphs/graph_decompositions/modular_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/modular_decomposition.pxd +27 -0
- sage/graphs/graph_decompositions/modular_decomposition.pyx +1536 -0
- sage/graphs/graph_decompositions/slice_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.pxd +18 -0
- sage/graphs/graph_decompositions/slice_decomposition.pyx +1106 -0
- sage/graphs/graph_decompositions/tree_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/tree_decomposition.pxd +17 -0
- sage/graphs/graph_decompositions/tree_decomposition.pyx +1996 -0
- sage/graphs/graph_decompositions/vertex_separation.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/vertex_separation.pxd +5 -0
- sage/graphs/graph_decompositions/vertex_separation.pyx +1963 -0
- sage/graphs/graph_editor.py +82 -0
- sage/graphs/graph_generators.py +3314 -0
- sage/graphs/graph_generators_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_generators_pyx.pyx +95 -0
- sage/graphs/graph_input.py +812 -0
- sage/graphs/graph_latex.py +2064 -0
- sage/graphs/graph_list.py +410 -0
- sage/graphs/graph_plot.py +1756 -0
- sage/graphs/graph_plot_js.py +338 -0
- sage/graphs/hyperbolicity.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/hyperbolicity.pyx +1704 -0
- sage/graphs/hypergraph_generators.py +364 -0
- sage/graphs/independent_sets.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/independent_sets.pxd +13 -0
- sage/graphs/independent_sets.pyx +402 -0
- sage/graphs/isgci.py +1033 -0
- sage/graphs/isoperimetric_inequalities.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/isoperimetric_inequalities.pyx +489 -0
- sage/graphs/line_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/line_graph.pyx +743 -0
- sage/graphs/lovasz_theta.py +77 -0
- sage/graphs/matching.py +1633 -0
- sage/graphs/matching_covered_graph.py +3590 -0
- sage/graphs/orientations.py +1489 -0
- sage/graphs/partial_cube.py +459 -0
- sage/graphs/path_enumeration.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/path_enumeration.pyx +2040 -0
- sage/graphs/pq_trees.py +1129 -0
- sage/graphs/print_graphs.py +201 -0
- sage/graphs/schnyder.py +865 -0
- sage/graphs/spanning_tree.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/spanning_tree.pyx +1457 -0
- sage/graphs/strongly_regular_db.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/strongly_regular_db.pyx +3340 -0
- sage/graphs/traversals.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/traversals.pxd +9 -0
- sage/graphs/traversals.pyx +1872 -0
- sage/graphs/trees.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/trees.pxd +15 -0
- sage/graphs/trees.pyx +310 -0
- sage/graphs/tutte_polynomial.py +713 -0
- sage/graphs/views.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/views.pyx +794 -0
- sage/graphs/weakly_chordal.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/weakly_chordal.pyx +604 -0
- sage/groups/all__sagemath_graphs.py +1 -0
- sage/groups/perm_gps/all__sagemath_graphs.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_graphs.py +1 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.pxd +38 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +1666 -0
- sage/knots/all.py +6 -0
- sage/knots/free_knotinfo_monoid.py +507 -0
- sage/knots/gauss_code.py +291 -0
- sage/knots/knot.py +682 -0
- sage/knots/knot_table.py +284 -0
- sage/knots/knotinfo.py +2900 -0
- sage/knots/link.py +4715 -0
- sage/sandpiles/all.py +13 -0
- sage/sandpiles/examples.py +225 -0
- sage/sandpiles/sandpile.py +6365 -0
- sage/topology/all.py +22 -0
- sage/topology/cell_complex.py +1214 -0
- sage/topology/cubical_complex.py +1976 -0
- sage/topology/delta_complex.py +1806 -0
- sage/topology/filtered_simplicial_complex.py +744 -0
- sage/topology/moment_angle_complex.py +823 -0
- sage/topology/simplicial_complex.py +5160 -0
- sage/topology/simplicial_complex_catalog.py +92 -0
- sage/topology/simplicial_complex_examples.py +1680 -0
- sage/topology/simplicial_complex_homset.py +205 -0
- sage/topology/simplicial_complex_morphism.py +836 -0
- sage/topology/simplicial_set.py +4102 -0
- sage/topology/simplicial_set_catalog.py +55 -0
- sage/topology/simplicial_set_constructions.py +2954 -0
- sage/topology/simplicial_set_examples.py +865 -0
- sage/topology/simplicial_set_morphism.py +1464 -0
@@ -0,0 +1,2468 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-graphs
|
2
|
+
# sage.doctest: needs sage.graphs
|
3
|
+
r"""
|
4
|
+
Quiver mutation types
|
5
|
+
|
6
|
+
AUTHORS:
|
7
|
+
|
8
|
+
- Gregg Musiker (2012, initial version)
|
9
|
+
- Christian Stump (2012, initial version)
|
10
|
+
- Hugh Thomas (2012, initial version)
|
11
|
+
"""
|
12
|
+
# ****************************************************************************
|
13
|
+
# Copyright (C) 2011 Gregg Musiker <gmusiker@gmail.com>
|
14
|
+
# Christian Stump <christian.stump@gmail.com>
|
15
|
+
# Hugh Thomas <hugh@math.unb.ca>
|
16
|
+
#
|
17
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
18
|
+
# https://www.gnu.org/licenses/
|
19
|
+
# ***************************************************************************
|
20
|
+
from __future__ import annotations
|
21
|
+
from pathlib import Path
|
22
|
+
import pickle
|
23
|
+
|
24
|
+
from sage.structure.sage_object import SageObject
|
25
|
+
from copy import copy
|
26
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
27
|
+
from sage.misc.cachefunc import cached_method
|
28
|
+
from sage.misc.lazy_import import lazy_import
|
29
|
+
from sage.rings.integer_ring import ZZ
|
30
|
+
from sage.rings.infinity import infinity
|
31
|
+
from sage.graphs.digraph import DiGraph
|
32
|
+
from sage.graphs.graph import Graph
|
33
|
+
from sage.arith.misc import binomial, euler_phi
|
34
|
+
from sage.misc.misc_c import prod
|
35
|
+
|
36
|
+
lazy_import('sage.matrix.constructor', 'matrix')
|
37
|
+
|
38
|
+
|
39
|
+
class QuiverMutationTypeFactory(SageObject):
|
40
|
+
def __call__(self, *args):
|
41
|
+
"""
|
42
|
+
For a detailed description, see :meth:`QuiverMutationType`.
|
43
|
+
|
44
|
+
EXAMPLES::
|
45
|
+
|
46
|
+
sage: from sage.combinat.cluster_algebra_quiver.quiver_mutation_type import QuiverMutationTypeFactory
|
47
|
+
sage: QuiverMutationTypeFactory()
|
48
|
+
QuiverMutationType
|
49
|
+
"""
|
50
|
+
# get data as arguments or as list/tuple
|
51
|
+
if len(args) == 1:
|
52
|
+
data = args[0]
|
53
|
+
else:
|
54
|
+
data = args
|
55
|
+
|
56
|
+
# data is a QuiverMutationType
|
57
|
+
if isinstance(data, QuiverMutationType_Irreducible):
|
58
|
+
return data
|
59
|
+
elif isinstance(data, QuiverMutationType_Reducible):
|
60
|
+
return data
|
61
|
+
|
62
|
+
# check that data is a tuple or list
|
63
|
+
if isinstance(data, tuple) and data:
|
64
|
+
pass
|
65
|
+
elif isinstance(data, list) and data:
|
66
|
+
data = tuple(data)
|
67
|
+
else:
|
68
|
+
_mutation_type_error(data)
|
69
|
+
|
70
|
+
# check for reducible types
|
71
|
+
if all(isinstance(data_component, (list, tuple,
|
72
|
+
QuiverMutationType_Irreducible))
|
73
|
+
for data_component in data):
|
74
|
+
if len(data) == 1:
|
75
|
+
return QuiverMutationType(data[0])
|
76
|
+
else:
|
77
|
+
data = tuple(QuiverMutationType(comp) for comp in data)
|
78
|
+
return QuiverMutationType_Reducible(*data)
|
79
|
+
|
80
|
+
# check for irreducible types
|
81
|
+
if len(data) == 2:
|
82
|
+
data = (data[0], data[1], None)
|
83
|
+
elif len(data) == 3:
|
84
|
+
pass
|
85
|
+
else:
|
86
|
+
_mutation_type_error(data)
|
87
|
+
|
88
|
+
if isinstance(data[2], list):
|
89
|
+
data = (data[0], data[1], tuple(data[2]))
|
90
|
+
if isinstance(data[1], list):
|
91
|
+
data = (data[0], tuple(data[1]), data[2])
|
92
|
+
|
93
|
+
# mutation type casting
|
94
|
+
if data == ('D', 2, None):
|
95
|
+
return QuiverMutationType(('A', 1, None), ('A', 1, None))
|
96
|
+
elif data == ('D', 3, None):
|
97
|
+
data = ('A', 3, None)
|
98
|
+
elif data == ('C', 2, None):
|
99
|
+
data = ('B', 2, None)
|
100
|
+
elif data == ('E', 9, None):
|
101
|
+
data = ('E', 8, 1)
|
102
|
+
elif data[0] == 'A' and data[2] == 1 and isinstance(data[1], tuple) and len(data[1]) == 2 and min(data[1]) == 0:
|
103
|
+
if max(data[1]) == 0:
|
104
|
+
pass
|
105
|
+
elif max(data[1]) == 1:
|
106
|
+
data = ('A', 1, None)
|
107
|
+
elif max(data[1]) == 2:
|
108
|
+
return QuiverMutationType(('A', 1, None), ('A', 1, None))
|
109
|
+
elif max(data[1]) == 3:
|
110
|
+
data = ('A', 3, None)
|
111
|
+
else:
|
112
|
+
data = ('D', max(data[1]), None)
|
113
|
+
elif data[0] == 'GR' and data[2] is None and isinstance(data[1], tuple) and len(data[1]) == 2 and data[1][1] > data[1][0]:
|
114
|
+
if min(data[1]) > max(data[1]) / 2 and max(data[1]) != min(data[1]) + 1:
|
115
|
+
data = (data[0], (max(data[1]) - min(data[1]), max(data[1])), data[2])
|
116
|
+
if min(data[1]) == 2 and max(data[1]) > 3:
|
117
|
+
data = ('A', max(data[1]) - 3, None)
|
118
|
+
elif data[1] == (3, 6):
|
119
|
+
data = ('D', 4, None)
|
120
|
+
elif data[1] == (3, 7):
|
121
|
+
data = ('E', 6, None)
|
122
|
+
elif data[1] == (3, 8):
|
123
|
+
data = ('E', 8, None)
|
124
|
+
elif data[1] == (3, 9):
|
125
|
+
data = ('E', 8, [1, 1])
|
126
|
+
elif data[1] == (4, 8):
|
127
|
+
data = ('E', 7, [1, 1])
|
128
|
+
elif data == ('TR', 1, None):
|
129
|
+
data = ('A', 1, None)
|
130
|
+
elif data == ('TR', 2, None):
|
131
|
+
data = ('A', 3, None)
|
132
|
+
elif data == ('TR', 3, None):
|
133
|
+
data = ('D', 6, None)
|
134
|
+
elif data == ('TR', 4, None):
|
135
|
+
data = ('E', 8, (1, 1))
|
136
|
+
# mutation type casting from Kac conventions
|
137
|
+
elif data == ('A', 1, 1):
|
138
|
+
data = ('A', (1, 1), 1)
|
139
|
+
elif data[0] == 'B' and data[2] == 1:
|
140
|
+
if data[1] == 2:
|
141
|
+
data = ('CC', 2, 1)
|
142
|
+
elif data[1] > 2:
|
143
|
+
data = ('BD', data[1], 1)
|
144
|
+
elif data[0] == 'B' and data[2] == -1:
|
145
|
+
if data[1] == 2:
|
146
|
+
data = ('BB', 2, 1)
|
147
|
+
elif data[1] > 2:
|
148
|
+
data = ('CD', data[1], 1)
|
149
|
+
elif data[0] == 'C' and data[1] > 1 and data[2] == 1:
|
150
|
+
data = ('CC', data[1], 1)
|
151
|
+
elif data[0] == 'C' and data[1] > 1 and data[2] == -1:
|
152
|
+
data = ('BB', data[1], 1)
|
153
|
+
elif data == ('A', 2, 2):
|
154
|
+
data = ('BC', 1, 1)
|
155
|
+
elif data[0] == 'A' and data[1] in ZZ and data[1] > 1 and data[1] % 2 == 0 and data[2] == 2:
|
156
|
+
data = ('BC', data[1] // 2, 1)
|
157
|
+
elif data[0] == 'A' and data[1] in ZZ and data[1] > 3 and data[1] % 2 and data[2] == 2:
|
158
|
+
data = ('CD', (data[1] + 1) // 2, 1)
|
159
|
+
# We think of ('A',3, 2) as ('D',3, 2)
|
160
|
+
elif data == ('A', 3, 2):
|
161
|
+
data = ('BB', 2, 1)
|
162
|
+
elif data[0] == 'D' and data[1] in ZZ and data[1] > 2 and data[2] == 2:
|
163
|
+
data = ('BB', data[1] - 1, 1)
|
164
|
+
elif data == ('E', 6, 2):
|
165
|
+
data = ('F', 4, -1)
|
166
|
+
elif data == ('D', 4, 3):
|
167
|
+
data = ('G', 2, -1)
|
168
|
+
elif data == ('F', 4, (2, 1)):
|
169
|
+
data = ('F', 4, (1, 2))
|
170
|
+
elif data == ('G', 2, (3, 1)):
|
171
|
+
data = ('G', 2, (1, 3))
|
172
|
+
elif data[0] == 'T' and data[2] is None:
|
173
|
+
data = (data[0], tuple(sorted(data[1])), data[2])
|
174
|
+
r, p, q = data[1]
|
175
|
+
if r == 1:
|
176
|
+
data = ('A', p + q - 1, None)
|
177
|
+
elif r == p == 2:
|
178
|
+
data = ('D', q + 2, None)
|
179
|
+
elif r == 2 and p == 3:
|
180
|
+
if q in (3, 4, 5):
|
181
|
+
data = ('E', q + 3, None)
|
182
|
+
elif q == 6:
|
183
|
+
data = ('E', 8, 1)
|
184
|
+
else:
|
185
|
+
data = ('E', q + 3, None)
|
186
|
+
elif r == 2 and p == q == 4:
|
187
|
+
data = ('E', 7, 1)
|
188
|
+
elif r == p == q == 3:
|
189
|
+
data = ('E', 6, 1)
|
190
|
+
elif data[0] == 'R2' and data[2] is None and all(data[1][i] in ZZ and data[1][i] > 0 for i in [0, 1]):
|
191
|
+
data = (data[0], tuple(sorted(data[1])), data[2])
|
192
|
+
if data[1] == (1, 1):
|
193
|
+
data = ('A', 2, None)
|
194
|
+
elif data[1] == (1, 2):
|
195
|
+
data = ('B', 2, None)
|
196
|
+
elif data[1] == (1, 3):
|
197
|
+
data = ('G', 2, None)
|
198
|
+
elif data[1] == (1, 4):
|
199
|
+
data = ('BC', 1, 1)
|
200
|
+
elif data[1] == (2, 2):
|
201
|
+
data = ('A', (1, 1), 1)
|
202
|
+
|
203
|
+
# setting the parameters and returning the mutation type
|
204
|
+
letter, rank, twist = data
|
205
|
+
if not isinstance(letter, str):
|
206
|
+
_mutation_type_error(data)
|
207
|
+
if isinstance(rank, list):
|
208
|
+
rank = tuple(rank)
|
209
|
+
if isinstance(twist, list):
|
210
|
+
twist = tuple(twist)
|
211
|
+
return QuiverMutationType_Irreducible(letter, rank, twist)
|
212
|
+
|
213
|
+
def _repr_(self) -> str:
|
214
|
+
"""
|
215
|
+
Return the string representation of ``self``.
|
216
|
+
|
217
|
+
EXAMPLES::
|
218
|
+
|
219
|
+
sage: QuiverMutationType # indirect doctest
|
220
|
+
QuiverMutationType
|
221
|
+
"""
|
222
|
+
return "QuiverMutationType"
|
223
|
+
|
224
|
+
def samples(self, finite=None, affine=None, elliptic=None,
|
225
|
+
mutation_finite=None):
|
226
|
+
"""
|
227
|
+
Return a sample of the available quiver mutations types.
|
228
|
+
|
229
|
+
INPUT:
|
230
|
+
|
231
|
+
- ``finite``
|
232
|
+
|
233
|
+
- ``affine``
|
234
|
+
|
235
|
+
- ``elliptic``
|
236
|
+
|
237
|
+
- ``mutation_finite``
|
238
|
+
|
239
|
+
All four input keywords default values are ``None``. If
|
240
|
+
set to ``True`` or ``False``, only these samples are returned.
|
241
|
+
|
242
|
+
EXAMPLES::
|
243
|
+
|
244
|
+
sage: QuiverMutationType.samples()
|
245
|
+
[['A', 1], ['A', 5], ['B', 2], ['B', 5], ['C', 3],
|
246
|
+
['C', 5], [ ['A', 1], ['A', 1] ], ['D', 5], ['E', 6],
|
247
|
+
['E', 7], ['E', 8], ['F', 4], ['G', 2],
|
248
|
+
['A', [1, 1], 1], ['A', [4, 5], 1], ['D', 4, 1],
|
249
|
+
['BB', 5, 1], ['E', 6, [1, 1]], ['E', 7, [1, 1]],
|
250
|
+
['R2', [1, 5]], ['R2', [3, 5]], ['E', 10], ['BE', 5],
|
251
|
+
['GR', [3, 10]], ['T', [3, 3, 4]]]
|
252
|
+
|
253
|
+
sage: QuiverMutationType.samples(finite=True)
|
254
|
+
[['A', 1], ['A', 5], ['B', 2], ['B', 5], ['C', 3],
|
255
|
+
['C', 5], [ ['A', 1], ['A', 1] ], ['D', 5], ['E', 6],
|
256
|
+
['E', 7], ['E', 8], ['F', 4], ['G', 2]]
|
257
|
+
|
258
|
+
sage: QuiverMutationType.samples(affine=True)
|
259
|
+
[['A', [1, 1], 1], ['A', [4, 5], 1], ['D', 4, 1], ['BB', 5, 1]]
|
260
|
+
|
261
|
+
sage: QuiverMutationType.samples(elliptic=True)
|
262
|
+
[['E', 6, [1, 1]], ['E', 7, [1, 1]]]
|
263
|
+
|
264
|
+
sage: QuiverMutationType.samples(mutation_finite=False)
|
265
|
+
[['R2', [1, 5]], ['R2', [3, 5]], ['E', 10], ['BE', 5],
|
266
|
+
['GR', [3, 10]], ['T', [3, 3, 4]]]
|
267
|
+
"""
|
268
|
+
result = self._samples()
|
269
|
+
if finite is not None:
|
270
|
+
result = [t for t in result if t.is_finite() == finite]
|
271
|
+
if affine is not None:
|
272
|
+
result = [t for t in result if t.is_affine() == affine]
|
273
|
+
if elliptic is not None:
|
274
|
+
result = [t for t in result if t.is_elliptic() == elliptic]
|
275
|
+
if mutation_finite is not None:
|
276
|
+
result = [t for t in result
|
277
|
+
if t.is_mutation_finite() == mutation_finite]
|
278
|
+
return result
|
279
|
+
|
280
|
+
@cached_method
|
281
|
+
def _samples(self):
|
282
|
+
"""
|
283
|
+
Return a list of sample of available Cartan types.
|
284
|
+
|
285
|
+
EXAMPLES::
|
286
|
+
|
287
|
+
sage: X = QuiverMutationType._samples()
|
288
|
+
"""
|
289
|
+
finite_types = \
|
290
|
+
[QuiverMutationType(t) for t in [['A', 1], ['A', 5], ['B', 2], ['B', 5],
|
291
|
+
['C', 3], ['C', 5], ['D', 2], ['D', 5],
|
292
|
+
["E", 6], ["E", 7], ["E", 8], ["F", 4],
|
293
|
+
["G", 2]]]
|
294
|
+
affine_types = \
|
295
|
+
[QuiverMutationType(t) for t in [['A', [1, 1], 1], ['A', [4, 5], 1], ['D', 4, 1], ['BB', 5, 1]]]
|
296
|
+
elliptic_types = \
|
297
|
+
[QuiverMutationType(t) for t in [['E', 6, [1, 1]], ['E', 7, [1, 1]]]]
|
298
|
+
mutation_finite_types = \
|
299
|
+
[QuiverMutationType(t) for t in [['R2', (1, 5)], ['R2', (3, 5)]]]
|
300
|
+
mutation_infinite_types = \
|
301
|
+
[QuiverMutationType(t) for t in [['E', 10], ['BE', 5], ['GR', (3, 10)], ['T', (3, 3, 4)]]]
|
302
|
+
|
303
|
+
return finite_types + affine_types + elliptic_types + mutation_finite_types + mutation_infinite_types
|
304
|
+
|
305
|
+
|
306
|
+
QuiverMutationType = QuiverMutationTypeFactory()
|
307
|
+
|
308
|
+
|
309
|
+
QuiverMutationType.__doc__ = \
|
310
|
+
r"""
|
311
|
+
|
312
|
+
*Quiver mutation types* can be seen as a slight generalization of
|
313
|
+
*generalized Cartan types*.
|
314
|
+
|
315
|
+
Background on generalized Cartan types can be found at
|
316
|
+
|
317
|
+
:wikipedia:`Generalized_Cartan_matrix`
|
318
|
+
|
319
|
+
For the compendium on the cluster algebra and quiver package in Sage see [MS2011]_
|
320
|
+
|
321
|
+
A `B`-matrix is a skew-symmetrizable `( n \times n )`-matrix `M`.
|
322
|
+
I.e., there exists an invertible diagonal matrix `D` such that `DM` is
|
323
|
+
skew-symmetric. `M` can be encoded as a *quiver* by having a directed
|
324
|
+
edge from vertex `i` to vertex `j` with label `(a,b)` if `a = M_{i,j}
|
325
|
+
> 0` and `b = M_{j,i} < 0`. We consider quivers up to *mutation
|
326
|
+
equivalence*.
|
327
|
+
|
328
|
+
To a quiver mutation type we can associate a *generalized Cartan type*
|
329
|
+
by sending `M` to the generalized Cartan matrix `C(M)` obtained by
|
330
|
+
replacing all positive entries by their negatives and adding `2`'s on
|
331
|
+
the main diagonal.
|
332
|
+
|
333
|
+
:class:`QuiverMutationType` constructs a quiver mutation type object. For
|
334
|
+
more detail on the possible different types, please see the
|
335
|
+
compendium.
|
336
|
+
|
337
|
+
INPUT:
|
338
|
+
|
339
|
+
The input consists either of a quiver mutation type, or of a
|
340
|
+
``letter`` (a string), a ``rank`` (one integer or a list/tuple of
|
341
|
+
integers), and an optional ``twist`` (an integer or a list of
|
342
|
+
integers). There are several different naming conventions for quiver
|
343
|
+
mutation types.
|
344
|
+
|
345
|
+
- Finite type -- ``letter`` is a Dynkin type (A-G), and ``rank`` is
|
346
|
+
the rank.
|
347
|
+
|
348
|
+
- Affine type -- there is more than one convention for naming affine
|
349
|
+
types.
|
350
|
+
|
351
|
+
* Kac's notation: ``letter`` is a Dynkin type, ``rank`` is the
|
352
|
+
rank of the associated finite Dynkin diagram, and ``twist`` is the
|
353
|
+
twist, which could be 1, 2, or 3. In the special case of affine
|
354
|
+
type A, there is more than one quiver mutation type associated to
|
355
|
+
the Cartan type. In this case only, ``rank`` is a pair of integers
|
356
|
+
(i,j), giving the number of edges pointing clockwise and the number
|
357
|
+
of edges pointing counter-clockwise. The total number of vertices
|
358
|
+
is given by i+j in this case.
|
359
|
+
|
360
|
+
* Naive notation: ``letter`` is one of 'BB', 'BC', 'BD', 'CC',
|
361
|
+
'CD'. The name specifies the two ends of the diagram, which are
|
362
|
+
joined by a path. The total number of vertices is given by
|
363
|
+
``rank +1`` (to match the indexing people expect because these
|
364
|
+
are affine types). In general, ``rank`` must be large enough
|
365
|
+
for the picture to make sense, but we accept ``letter`` is
|
366
|
+
``BC`` and ``rank=1``.
|
367
|
+
|
368
|
+
* Macdonald notation: for the dual of an untwisted affine type
|
369
|
+
(such as ['C', 6, 1]), we accept a twist of -1 (i.e.,
|
370
|
+
['C',6,-1]).
|
371
|
+
|
372
|
+
- Elliptic type -- ``letter`` is a Dynkin type, ``rank`` is the rank
|
373
|
+
of the finite Dynkin diagram, and ``twist`` is a tuple of two
|
374
|
+
integers. We follow Saito's notation.
|
375
|
+
|
376
|
+
- Other shapes:
|
377
|
+
|
378
|
+
* Rank 2: ``letter`` is 'R2', and ``rank`` is a pair of integers
|
379
|
+
specifying the label on the unique edge.
|
380
|
+
|
381
|
+
* Triangle: ``letter`` is ``TR``, and ``rank`` is the number of
|
382
|
+
vertices along a side.
|
383
|
+
|
384
|
+
* T: This defines a quiver shaped like a T. ``letter`` is 'T',
|
385
|
+
and the ``rank`` is a triple, whose entries specify the number
|
386
|
+
of vertices along each path from the branch point (counting the
|
387
|
+
branch point).
|
388
|
+
|
389
|
+
* Grassmannian: This defines the cluster algebra (without
|
390
|
+
coefficients) corresponding to the cluster algebra with
|
391
|
+
coefficients which is the coordinate ring of a Grassmannian.
|
392
|
+
``letter`` is 'GR'. ``rank`` is a pair of integers (`k`, `n`)
|
393
|
+
with 'k' < 'n' specifying the Grassmannian of `k`-planes in
|
394
|
+
`n`-space. This defines a quiver given by a (k-1) x (n-k-1)
|
395
|
+
grid where each square is cyclically oriented.
|
396
|
+
|
397
|
+
* Exceptional mutation finite quivers: The two exceptional
|
398
|
+
mutation finite quivers, found by Derksen-Owen, have ``letter``
|
399
|
+
as 'X' and ``rank`` 6 or 7, equal to the number of vertices.
|
400
|
+
|
401
|
+
* AE, BE, CE, DE: Quivers are built of one end which looks like
|
402
|
+
type (affine A), B, C, or D, and the other end which looks like
|
403
|
+
type E (i.e., it consists of two antennae, one of length one,
|
404
|
+
and one of length two). ``letter`` is 'AE', 'BE', 'CE', or
|
405
|
+
'DE', and ``rank`` is the total number of vertices. Note that
|
406
|
+
'AE' is of a slightly different form and requires ``rank`` to be
|
407
|
+
a pair of integers (i,j) just as in the case of affine type A.
|
408
|
+
See Exercise 4.3 in Kac's book Infinite Dimensional Lie Algebras
|
409
|
+
for more details.
|
410
|
+
|
411
|
+
* Infinite type E: It is also possible to obtain infinite-type E
|
412
|
+
quivers by specifying ``letter`` as 'E' and ``rank`` as the
|
413
|
+
number of vertices.
|
414
|
+
|
415
|
+
REFERENCES:
|
416
|
+
|
417
|
+
- A good reference for finite and affine Dynkin diagrams, including
|
418
|
+
Kac's notation, is the :wikipedia:`Dynkin_diagram`.
|
419
|
+
|
420
|
+
- A good reference for the skew-symmetrizable elliptic diagrams is
|
421
|
+
"Cluster algebras of finite mutation type via unfolding" by
|
422
|
+
A. Felikson, M. Shapiro, and P. Tumarkin, [FST2012]_.
|
423
|
+
|
424
|
+
EXAMPLES:
|
425
|
+
|
426
|
+
Finite types::
|
427
|
+
|
428
|
+
sage: QuiverMutationType('A', 1)
|
429
|
+
['A', 1]
|
430
|
+
sage: QuiverMutationType('A',5)
|
431
|
+
['A', 5]
|
432
|
+
|
433
|
+
sage: QuiverMutationType('B', 2)
|
434
|
+
['B', 2]
|
435
|
+
sage: QuiverMutationType('B',5)
|
436
|
+
['B', 5]
|
437
|
+
|
438
|
+
sage: QuiverMutationType('C', 2)
|
439
|
+
['B', 2]
|
440
|
+
sage: QuiverMutationType('C',5)
|
441
|
+
['C', 5]
|
442
|
+
|
443
|
+
sage: QuiverMutationType('D', 2)
|
444
|
+
[ ['A', 1], ['A', 1] ]
|
445
|
+
sage: QuiverMutationType('D',3)
|
446
|
+
['A', 3]
|
447
|
+
sage: QuiverMutationType('D',4)
|
448
|
+
['D', 4]
|
449
|
+
|
450
|
+
sage: QuiverMutationType('E',6)
|
451
|
+
['E', 6]
|
452
|
+
|
453
|
+
sage: QuiverMutationType('G', 2)
|
454
|
+
['G', 2]
|
455
|
+
|
456
|
+
sage: QuiverMutationType('A',(1,0), 1)
|
457
|
+
['A', 1]
|
458
|
+
|
459
|
+
sage: QuiverMutationType('A',(2,0), 1)
|
460
|
+
[ ['A', 1], ['A', 1] ]
|
461
|
+
|
462
|
+
sage: QuiverMutationType('A',(7,0), 1)
|
463
|
+
['D', 7]
|
464
|
+
|
465
|
+
Affine types::
|
466
|
+
|
467
|
+
sage: QuiverMutationType('A',(1, 1), 1)
|
468
|
+
['A', [1, 1], 1]
|
469
|
+
sage: QuiverMutationType('A',(2,4), 1)
|
470
|
+
['A', [2, 4], 1]
|
471
|
+
|
472
|
+
sage: QuiverMutationType('BB', 2, 1)
|
473
|
+
['BB', 2, 1]
|
474
|
+
sage: QuiverMutationType('BB',4, 1)
|
475
|
+
['BB', 4, 1]
|
476
|
+
|
477
|
+
sage: QuiverMutationType('CC', 2, 1)
|
478
|
+
['CC', 2, 1]
|
479
|
+
sage: QuiverMutationType('CC',4, 1)
|
480
|
+
['CC', 4, 1]
|
481
|
+
|
482
|
+
sage: QuiverMutationType('BC', 1, 1)
|
483
|
+
['BC', 1, 1]
|
484
|
+
sage: QuiverMutationType('BC',5, 1)
|
485
|
+
['BC', 5, 1]
|
486
|
+
|
487
|
+
sage: QuiverMutationType('BD',3, 1)
|
488
|
+
['BD', 3, 1]
|
489
|
+
sage: QuiverMutationType('BD',5, 1)
|
490
|
+
['BD', 5, 1]
|
491
|
+
|
492
|
+
sage: QuiverMutationType('CD',3, 1)
|
493
|
+
['CD', 3, 1]
|
494
|
+
sage: QuiverMutationType('CD',5, 1)
|
495
|
+
['CD', 5, 1]
|
496
|
+
|
497
|
+
sage: QuiverMutationType('D',4, 1)
|
498
|
+
['D', 4, 1]
|
499
|
+
sage: QuiverMutationType('D',6, 1)
|
500
|
+
['D', 6, 1]
|
501
|
+
|
502
|
+
sage: QuiverMutationType('E',6, 1)
|
503
|
+
['E', 6, 1]
|
504
|
+
sage: QuiverMutationType('E',7, 1)
|
505
|
+
['E', 7, 1]
|
506
|
+
sage: QuiverMutationType('E',8, 1)
|
507
|
+
['E', 8, 1]
|
508
|
+
|
509
|
+
sage: QuiverMutationType('F',4, 1)
|
510
|
+
['F', 4, 1]
|
511
|
+
sage: QuiverMutationType('F',4,-1)
|
512
|
+
['F', 4, -1]
|
513
|
+
|
514
|
+
sage: QuiverMutationType('G', 2, 1)
|
515
|
+
['G', 2, 1]
|
516
|
+
sage: QuiverMutationType('G', 2,-1)
|
517
|
+
['G', 2, -1]
|
518
|
+
sage: QuiverMutationType('A',3, 2) == QuiverMutationType('D',3, 2)
|
519
|
+
True
|
520
|
+
|
521
|
+
Affine types using Kac's Notation::
|
522
|
+
|
523
|
+
sage: QuiverMutationType('A', 1, 1)
|
524
|
+
['A', [1, 1], 1]
|
525
|
+
sage: QuiverMutationType('B',5, 1)
|
526
|
+
['BD', 5, 1]
|
527
|
+
sage: QuiverMutationType('C',5, 1)
|
528
|
+
['CC', 5, 1]
|
529
|
+
sage: QuiverMutationType('A', 2, 2)
|
530
|
+
['BC', 1, 1]
|
531
|
+
sage: QuiverMutationType('A',7, 2)
|
532
|
+
['CD', 4, 1]
|
533
|
+
sage: QuiverMutationType('A',8, 2)
|
534
|
+
['BC', 4, 1]
|
535
|
+
sage: QuiverMutationType('D',6, 2)
|
536
|
+
['BB', 5, 1]
|
537
|
+
sage: QuiverMutationType('E',6, 2)
|
538
|
+
['F', 4, -1]
|
539
|
+
sage: QuiverMutationType('D',4,3)
|
540
|
+
['G', 2, -1]
|
541
|
+
|
542
|
+
Elliptic types::
|
543
|
+
|
544
|
+
sage: QuiverMutationType('E',6,[1, 1])
|
545
|
+
['E', 6, [1, 1]]
|
546
|
+
sage: QuiverMutationType('F',4,[2, 1])
|
547
|
+
['F', 4, [1, 2]]
|
548
|
+
sage: QuiverMutationType('G', 2,[3,3])
|
549
|
+
['G', 2, [3, 3]]
|
550
|
+
|
551
|
+
Mutation finite types:
|
552
|
+
|
553
|
+
Rank 2 cases::
|
554
|
+
|
555
|
+
sage: QuiverMutationType('R2',(1, 1))
|
556
|
+
['A', 2]
|
557
|
+
sage: QuiverMutationType('R2',(1, 2))
|
558
|
+
['B', 2]
|
559
|
+
sage: QuiverMutationType('R2',(1,3))
|
560
|
+
['G', 2]
|
561
|
+
sage: QuiverMutationType('R2',(1,4))
|
562
|
+
['BC', 1, 1]
|
563
|
+
sage: QuiverMutationType('R2',(1,5))
|
564
|
+
['R2', [1, 5]]
|
565
|
+
sage: QuiverMutationType('R2',(2, 2))
|
566
|
+
['A', [1, 1], 1]
|
567
|
+
sage: QuiverMutationType('R2',(3,5))
|
568
|
+
['R2', [3, 5]]
|
569
|
+
|
570
|
+
Exceptional Derksen-Owen quivers::
|
571
|
+
|
572
|
+
sage: QuiverMutationType('X',6)
|
573
|
+
['X', 6]
|
574
|
+
|
575
|
+
|
576
|
+
(Mainly) mutation infinite types:
|
577
|
+
|
578
|
+
Infinite type E::
|
579
|
+
|
580
|
+
sage: QuiverMutationType('E',9)
|
581
|
+
['E', 8, 1]
|
582
|
+
sage: QuiverMutationType('E', 10)
|
583
|
+
['E', 10]
|
584
|
+
sage: QuiverMutationType('E', 12)
|
585
|
+
['E', 12]
|
586
|
+
|
587
|
+
sage: QuiverMutationType('AE',(2,3))
|
588
|
+
['AE', [2, 3]]
|
589
|
+
sage: QuiverMutationType('BE',5)
|
590
|
+
['BE', 5]
|
591
|
+
sage: QuiverMutationType('CE',5)
|
592
|
+
['CE', 5]
|
593
|
+
sage: QuiverMutationType('DE',6)
|
594
|
+
['DE', 6]
|
595
|
+
|
596
|
+
Grassmannian types::
|
597
|
+
|
598
|
+
sage: QuiverMutationType('GR',(2,4))
|
599
|
+
['A', 1]
|
600
|
+
sage: QuiverMutationType('GR',(2,6))
|
601
|
+
['A', 3]
|
602
|
+
sage: QuiverMutationType('GR',(3,6))
|
603
|
+
['D', 4]
|
604
|
+
sage: QuiverMutationType('GR',(3,7))
|
605
|
+
['E', 6]
|
606
|
+
sage: QuiverMutationType('GR',(3,8))
|
607
|
+
['E', 8]
|
608
|
+
sage: QuiverMutationType('GR',(3, 10))
|
609
|
+
['GR', [3, 10]]
|
610
|
+
|
611
|
+
Triangular types::
|
612
|
+
|
613
|
+
sage: QuiverMutationType('TR', 2)
|
614
|
+
['A', 3]
|
615
|
+
sage: QuiverMutationType('TR',3)
|
616
|
+
['D', 6]
|
617
|
+
sage: QuiverMutationType('TR',4)
|
618
|
+
['E', 8, [1, 1]]
|
619
|
+
sage: QuiverMutationType('TR',5)
|
620
|
+
['TR', 5]
|
621
|
+
|
622
|
+
T types::
|
623
|
+
|
624
|
+
sage: QuiverMutationType('T',(1, 1, 1))
|
625
|
+
['A', 1]
|
626
|
+
sage: QuiverMutationType('T',(1, 1,4))
|
627
|
+
['A', 4]
|
628
|
+
sage: QuiverMutationType('T',(1,4,4))
|
629
|
+
['A', 7]
|
630
|
+
sage: QuiverMutationType('T',(2, 2, 2))
|
631
|
+
['D', 4]
|
632
|
+
sage: QuiverMutationType('T',(2, 2,4))
|
633
|
+
['D', 6]
|
634
|
+
sage: QuiverMutationType('T',(2,3,3))
|
635
|
+
['E', 6]
|
636
|
+
sage: QuiverMutationType('T',(2,3,4))
|
637
|
+
['E', 7]
|
638
|
+
sage: QuiverMutationType('T',(2,3,5))
|
639
|
+
['E', 8]
|
640
|
+
sage: QuiverMutationType('T',(2,3,6))
|
641
|
+
['E', 8, 1]
|
642
|
+
sage: QuiverMutationType('T',(2,3,7))
|
643
|
+
['E', 10]
|
644
|
+
sage: QuiverMutationType('T',(3,3,3))
|
645
|
+
['E', 6, 1]
|
646
|
+
sage: QuiverMutationType('T',(3,3,4))
|
647
|
+
['T', [3, 3, 4]]
|
648
|
+
|
649
|
+
Reducible types::
|
650
|
+
|
651
|
+
sage: QuiverMutationType(['A',3],['B',4])
|
652
|
+
[ ['A', 3], ['B', 4] ]
|
653
|
+
"""
|
654
|
+
|
655
|
+
|
656
|
+
class QuiverMutationType_abstract(UniqueRepresentation, SageObject):
|
657
|
+
"""
|
658
|
+
EXAMPLES::
|
659
|
+
|
660
|
+
sage: mut_type1 = QuiverMutationType('A',5)
|
661
|
+
sage: mut_type2 = QuiverMutationType('A',5)
|
662
|
+
sage: mut_type3 = QuiverMutationType('A',6)
|
663
|
+
sage: mut_type1 == mut_type2
|
664
|
+
True
|
665
|
+
sage: mut_type1 == mut_type3
|
666
|
+
False
|
667
|
+
"""
|
668
|
+
|
669
|
+
def _repr_(self):
|
670
|
+
"""
|
671
|
+
Return the string representation of ``self``.
|
672
|
+
|
673
|
+
EXAMPLES::
|
674
|
+
|
675
|
+
sage: QuiverMutationType(['A', 2]) # indirect doctest
|
676
|
+
['A', 2]
|
677
|
+
"""
|
678
|
+
return self._description
|
679
|
+
|
680
|
+
def plot(self, circular=False, directed=True):
|
681
|
+
"""
|
682
|
+
Return the plot of the underlying graph or digraph of ``self``.
|
683
|
+
|
684
|
+
INPUT:
|
685
|
+
|
686
|
+
- ``circular`` -- boolean (default: ``False``); if ``True``, the
|
687
|
+
circular plot is chosen, otherwise >>spring<< is used
|
688
|
+
|
689
|
+
- ``directed`` -- boolean (default: ``True``); if ``True``, the
|
690
|
+
directed version is shown, otherwise the undirected
|
691
|
+
|
692
|
+
EXAMPLES::
|
693
|
+
|
694
|
+
sage: QMT = QuiverMutationType(['A',5])
|
695
|
+
sage: pl = QMT.plot() # needs sage.plot sage.symbolic
|
696
|
+
sage: pl = QMT.plot(circular=True) # needs sage.plot sage.symbolic
|
697
|
+
"""
|
698
|
+
return self.standard_quiver().plot(circular=circular, directed=directed)
|
699
|
+
|
700
|
+
def show(self, circular=False, directed=True):
|
701
|
+
"""
|
702
|
+
Show the plot of the underlying digraph of ``self``.
|
703
|
+
|
704
|
+
INPUT:
|
705
|
+
|
706
|
+
- ``circular`` -- boolean (default: ``False``); if ``True``, the
|
707
|
+
circular plot is chosen, otherwise >>spring<< is used
|
708
|
+
|
709
|
+
- ``directed`` -- boolean (default: ``True``); if ``True``, the
|
710
|
+
directed version is shown, otherwise the undirected
|
711
|
+
|
712
|
+
TESTS::
|
713
|
+
|
714
|
+
sage: QMT = QuiverMutationType(['A', 5])
|
715
|
+
sage: QMT.show() # long time # needs sage.plot sage.symbolic
|
716
|
+
"""
|
717
|
+
self.plot(circular=circular, directed=directed).show()
|
718
|
+
|
719
|
+
def letter(self):
|
720
|
+
"""
|
721
|
+
Return the classification letter of ``self``.
|
722
|
+
|
723
|
+
EXAMPLES::
|
724
|
+
|
725
|
+
sage: mut_type = QuiverMutationType( ['A',5] ); mut_type
|
726
|
+
['A', 5]
|
727
|
+
sage: mut_type.letter()
|
728
|
+
'A'
|
729
|
+
|
730
|
+
sage: mut_type = QuiverMutationType( ['BC',5, 1] ); mut_type
|
731
|
+
['BC', 5, 1]
|
732
|
+
sage: mut_type.letter()
|
733
|
+
'BC'
|
734
|
+
|
735
|
+
sage: mut_type = QuiverMutationType(['A',3],['B',3]); mut_type
|
736
|
+
[ ['A', 3], ['B', 3] ]
|
737
|
+
sage: mut_type.letter()
|
738
|
+
'A x B'
|
739
|
+
|
740
|
+
sage: mut_type = QuiverMutationType(['A',3],['B',3],['X',6]); mut_type
|
741
|
+
[ ['A', 3], ['B', 3], ['X', 6] ]
|
742
|
+
sage: mut_type.letter()
|
743
|
+
'A x B x X'
|
744
|
+
"""
|
745
|
+
return self._letter
|
746
|
+
|
747
|
+
def rank(self):
|
748
|
+
"""
|
749
|
+
Return the rank in the standard quiver of ``self``.
|
750
|
+
|
751
|
+
The rank is the number of vertices.
|
752
|
+
|
753
|
+
EXAMPLES::
|
754
|
+
|
755
|
+
sage: mut_type = QuiverMutationType( ['A',5] ); mut_type
|
756
|
+
['A', 5]
|
757
|
+
sage: mut_type.rank()
|
758
|
+
5
|
759
|
+
|
760
|
+
sage: mut_type = QuiverMutationType( ['A',[4,5], 1] ); mut_type
|
761
|
+
['A', [4, 5], 1]
|
762
|
+
sage: mut_type.rank()
|
763
|
+
9
|
764
|
+
|
765
|
+
sage: mut_type = QuiverMutationType( ['BC',5, 1] ); mut_type
|
766
|
+
['BC', 5, 1]
|
767
|
+
sage: mut_type.rank()
|
768
|
+
6
|
769
|
+
|
770
|
+
sage: mut_type = QuiverMutationType(['A',3],['B',3]); mut_type
|
771
|
+
[ ['A', 3], ['B', 3] ]
|
772
|
+
sage: mut_type.rank()
|
773
|
+
6
|
774
|
+
|
775
|
+
sage: mut_type = QuiverMutationType(['A',3],['B',3],['X',6]); mut_type
|
776
|
+
[ ['A', 3], ['B', 3], ['X', 6] ]
|
777
|
+
sage: mut_type.rank()
|
778
|
+
12
|
779
|
+
"""
|
780
|
+
return self._rank
|
781
|
+
|
782
|
+
@cached_method
|
783
|
+
def b_matrix(self):
|
784
|
+
"""
|
785
|
+
Return the B-matrix of the standard quiver of ``self``.
|
786
|
+
|
787
|
+
The conventions for B-matrices agree with Fomin-Zelevinsky (up
|
788
|
+
to a reordering of the simple roots).
|
789
|
+
|
790
|
+
EXAMPLES::
|
791
|
+
|
792
|
+
sage: mut_type = QuiverMutationType(['A',5]); mut_type
|
793
|
+
['A', 5]
|
794
|
+
sage: mut_type.b_matrix() # needs sage.modules
|
795
|
+
[ 0 1 0 0 0]
|
796
|
+
[-1 0 -1 0 0]
|
797
|
+
[ 0 1 0 1 0]
|
798
|
+
[ 0 0 -1 0 -1]
|
799
|
+
[ 0 0 0 1 0]
|
800
|
+
|
801
|
+
sage: mut_type = QuiverMutationType(['A',3],['B',3]); mut_type
|
802
|
+
[ ['A', 3], ['B', 3] ]
|
803
|
+
sage: mut_type.b_matrix() # needs sage.modules
|
804
|
+
[ 0 1 0 0 0 0]
|
805
|
+
[-1 0 -1 0 0 0]
|
806
|
+
[ 0 1 0 0 0 0]
|
807
|
+
[ 0 0 0 0 1 0]
|
808
|
+
[ 0 0 0 -1 0 -1]
|
809
|
+
[ 0 0 0 0 2 0]
|
810
|
+
"""
|
811
|
+
return _edge_list_to_matrix(self._digraph.edges(sort=True), list(range(self._rank)), [])
|
812
|
+
|
813
|
+
@cached_method
|
814
|
+
def standard_quiver(self):
|
815
|
+
"""
|
816
|
+
Return the standard quiver of ``self``.
|
817
|
+
|
818
|
+
EXAMPLES::
|
819
|
+
|
820
|
+
sage: mut_type = QuiverMutationType( ['A',5] ); mut_type
|
821
|
+
['A', 5]
|
822
|
+
sage: mut_type.standard_quiver() # needs sage.modules
|
823
|
+
Quiver on 5 vertices of type ['A', 5]
|
824
|
+
|
825
|
+
sage: mut_type = QuiverMutationType( ['A',[5,3], 1] ); mut_type
|
826
|
+
['A', [3, 5], 1]
|
827
|
+
sage: mut_type.standard_quiver() # needs sage.modules
|
828
|
+
Quiver on 8 vertices of type ['A', [3, 5], 1]
|
829
|
+
|
830
|
+
sage: mut_type = QuiverMutationType(['A',3],['B',3]); mut_type
|
831
|
+
[ ['A', 3], ['B', 3] ]
|
832
|
+
sage: mut_type.standard_quiver() # needs sage.modules
|
833
|
+
Quiver on 6 vertices of type [ ['A', 3], ['B', 3] ]
|
834
|
+
|
835
|
+
sage: mut_type = QuiverMutationType(['A',3],['B',3],['X',6]); mut_type
|
836
|
+
[ ['A', 3], ['B', 3], ['X', 6] ]
|
837
|
+
sage: mut_type.standard_quiver() # needs sage.modules
|
838
|
+
Quiver on 12 vertices of type [ ['A', 3], ['B', 3], ['X', 6] ]
|
839
|
+
"""
|
840
|
+
from .quiver import ClusterQuiver
|
841
|
+
Q = ClusterQuiver(self._digraph)
|
842
|
+
Q._mutation_type = self
|
843
|
+
return Q
|
844
|
+
|
845
|
+
@cached_method
|
846
|
+
def cartan_matrix(self):
|
847
|
+
"""
|
848
|
+
Return the Cartan matrix of ``self``.
|
849
|
+
|
850
|
+
Note that (up to a reordering of the simple roots) the convention for
|
851
|
+
the definition of Cartan matrix, used here and elsewhere in Sage,
|
852
|
+
agrees with the conventions of Kac, Fulton-Harris, and
|
853
|
+
Fomin-Zelevinsky, but disagrees with the convention of Bourbaki.
|
854
|
+
The `(i,j)` entry is `2(\\alpha_i,\\alpha_j)/(\\alpha_i,\\alpha_i)`.
|
855
|
+
|
856
|
+
EXAMPLES::
|
857
|
+
|
858
|
+
sage: mut_type = QuiverMutationType(['A',5]); mut_type
|
859
|
+
['A', 5]
|
860
|
+
sage: mut_type.cartan_matrix() # needs sage.modules
|
861
|
+
[ 2 -1 0 0 0]
|
862
|
+
[-1 2 -1 0 0]
|
863
|
+
[ 0 -1 2 -1 0]
|
864
|
+
[ 0 0 -1 2 -1]
|
865
|
+
[ 0 0 0 -1 2]
|
866
|
+
|
867
|
+
sage: mut_type = QuiverMutationType(['A',3],['B',3]); mut_type
|
868
|
+
[ ['A', 3], ['B', 3] ]
|
869
|
+
sage: mut_type.cartan_matrix() # needs sage.modules
|
870
|
+
[ 2 -1 0 0 0 0]
|
871
|
+
[-1 2 -1 0 0 0]
|
872
|
+
[ 0 -1 2 0 0 0]
|
873
|
+
[ 0 0 0 2 -1 0]
|
874
|
+
[ 0 0 0 -1 2 -1]
|
875
|
+
[ 0 0 0 0 -2 2]
|
876
|
+
"""
|
877
|
+
# as soon as CartanMatrix is implemented we should use it here:
|
878
|
+
# from sage.combinat.root_system.cartan_matrix import CartanMatrix
|
879
|
+
cmat = copy(self.b_matrix())
|
880
|
+
for i, j in cmat.nonzero_positions():
|
881
|
+
a = cmat[i, j]
|
882
|
+
if a > 0:
|
883
|
+
cmat[i, j] = -a
|
884
|
+
for i in range(self._rank):
|
885
|
+
cmat[i, i] = 2
|
886
|
+
# return CartanMatrix(cmat)
|
887
|
+
return cmat
|
888
|
+
|
889
|
+
def is_irreducible(self):
|
890
|
+
"""
|
891
|
+
Return ``True`` if ``self`` is irreducible.
|
892
|
+
|
893
|
+
EXAMPLES::
|
894
|
+
|
895
|
+
sage: mt = QuiverMutationType(['A', 2])
|
896
|
+
sage: mt.is_irreducible()
|
897
|
+
True
|
898
|
+
"""
|
899
|
+
return self._info['irreducible']
|
900
|
+
|
901
|
+
def is_mutation_finite(self):
|
902
|
+
"""
|
903
|
+
Return ``True`` if ``self`` is of finite mutation type.
|
904
|
+
|
905
|
+
This means that its mutation class has only finitely many
|
906
|
+
different B-matrices.
|
907
|
+
|
908
|
+
EXAMPLES::
|
909
|
+
|
910
|
+
sage: mt = QuiverMutationType(['D',5, 1])
|
911
|
+
sage: mt.is_mutation_finite()
|
912
|
+
True
|
913
|
+
"""
|
914
|
+
return self._info['mutation_finite']
|
915
|
+
|
916
|
+
def is_simply_laced(self):
|
917
|
+
"""
|
918
|
+
Return ``True`` if ``self`` is simply laced.
|
919
|
+
|
920
|
+
This means that the only arrows that appear in the quiver of
|
921
|
+
``self`` are single unlabelled arrows.
|
922
|
+
|
923
|
+
EXAMPLES::
|
924
|
+
|
925
|
+
sage: mt = QuiverMutationType(['A', 2])
|
926
|
+
sage: mt.is_simply_laced()
|
927
|
+
True
|
928
|
+
|
929
|
+
sage: mt = QuiverMutationType(['B', 2])
|
930
|
+
sage: mt.is_simply_laced()
|
931
|
+
False
|
932
|
+
|
933
|
+
sage: mt = QuiverMutationType(['A',(1, 1), 1])
|
934
|
+
sage: mt.is_simply_laced()
|
935
|
+
False
|
936
|
+
"""
|
937
|
+
return self._info['simply_laced']
|
938
|
+
|
939
|
+
def is_skew_symmetric(self):
|
940
|
+
"""
|
941
|
+
Return ``True`` if the B-matrix of ``self`` is skew-symmetric.
|
942
|
+
|
943
|
+
EXAMPLES::
|
944
|
+
|
945
|
+
sage: mt = QuiverMutationType(['A', 2])
|
946
|
+
sage: mt.is_skew_symmetric()
|
947
|
+
True
|
948
|
+
|
949
|
+
sage: mt = QuiverMutationType(['B', 2])
|
950
|
+
sage: mt.is_skew_symmetric()
|
951
|
+
False
|
952
|
+
|
953
|
+
sage: mt = QuiverMutationType(['A',(1, 1), 1])
|
954
|
+
sage: mt.is_skew_symmetric()
|
955
|
+
True
|
956
|
+
"""
|
957
|
+
return self._info['skew_symmetric']
|
958
|
+
|
959
|
+
def is_finite(self):
|
960
|
+
"""
|
961
|
+
Return ``True`` if ``self`` is of finite type.
|
962
|
+
|
963
|
+
This means that the cluster algebra associated to ``self`` has
|
964
|
+
only a finite number of cluster variables.
|
965
|
+
|
966
|
+
EXAMPLES::
|
967
|
+
|
968
|
+
sage: mt = QuiverMutationType(['A', 2])
|
969
|
+
sage: mt.is_finite()
|
970
|
+
True
|
971
|
+
|
972
|
+
sage: mt = QuiverMutationType(['A',[4, 2], 1])
|
973
|
+
sage: mt.is_finite()
|
974
|
+
False
|
975
|
+
"""
|
976
|
+
return self._info['finite']
|
977
|
+
|
978
|
+
def is_affine(self):
|
979
|
+
"""
|
980
|
+
Return ``True`` if ``self`` is of affine type.
|
981
|
+
|
982
|
+
EXAMPLES::
|
983
|
+
|
984
|
+
sage: mt = QuiverMutationType(['A', 2])
|
985
|
+
sage: mt.is_affine()
|
986
|
+
False
|
987
|
+
|
988
|
+
sage: mt = QuiverMutationType(['A',[4, 2], 1])
|
989
|
+
sage: mt.is_affine()
|
990
|
+
True
|
991
|
+
"""
|
992
|
+
if self.is_irreducible():
|
993
|
+
return self._info['affine']
|
994
|
+
else:
|
995
|
+
return False
|
996
|
+
|
997
|
+
def is_elliptic(self):
|
998
|
+
"""
|
999
|
+
Return ``True`` if ``self`` is of elliptic type.
|
1000
|
+
|
1001
|
+
EXAMPLES::
|
1002
|
+
|
1003
|
+
sage: mt = QuiverMutationType(['A', 2])
|
1004
|
+
sage: mt.is_elliptic()
|
1005
|
+
False
|
1006
|
+
|
1007
|
+
sage: mt = QuiverMutationType(['E',6,[1, 1]])
|
1008
|
+
sage: mt.is_elliptic()
|
1009
|
+
True
|
1010
|
+
"""
|
1011
|
+
if self.is_irreducible():
|
1012
|
+
return self._info['elliptic']
|
1013
|
+
else:
|
1014
|
+
return False
|
1015
|
+
|
1016
|
+
def properties(self):
|
1017
|
+
"""
|
1018
|
+
Print a scheme of all properties of ``self``.
|
1019
|
+
|
1020
|
+
Most properties have natural definitions for either irreducible or
|
1021
|
+
reducible types. ``affine`` and ``elliptic`` are only defined for
|
1022
|
+
irreducible types.
|
1023
|
+
|
1024
|
+
EXAMPLES::
|
1025
|
+
|
1026
|
+
sage: mut_type = QuiverMutationType(['A',3]); mut_type
|
1027
|
+
['A', 3]
|
1028
|
+
sage: mut_type.properties()
|
1029
|
+
['A', 3] has rank 3 and the following properties:
|
1030
|
+
- irreducible: True
|
1031
|
+
- mutation finite: True
|
1032
|
+
- simply-laced: True
|
1033
|
+
- skew-symmetric: True
|
1034
|
+
- finite: True
|
1035
|
+
- affine: False
|
1036
|
+
- elliptic: False
|
1037
|
+
|
1038
|
+
sage: mut_type = QuiverMutationType(['B',3]); mut_type
|
1039
|
+
['B', 3]
|
1040
|
+
sage: mut_type.properties()
|
1041
|
+
['B', 3] has rank 3 and the following properties:
|
1042
|
+
- irreducible: True
|
1043
|
+
- mutation finite: True
|
1044
|
+
- simply-laced: False
|
1045
|
+
- skew-symmetric: False
|
1046
|
+
- finite: True
|
1047
|
+
- affine: False
|
1048
|
+
- elliptic: False
|
1049
|
+
|
1050
|
+
sage: mut_type = QuiverMutationType(['B',3, 1]); mut_type
|
1051
|
+
['BD', 3, 1]
|
1052
|
+
sage: mut_type.properties()
|
1053
|
+
['BD', 3, 1] has rank 4 and the following properties:
|
1054
|
+
- irreducible: True
|
1055
|
+
- mutation finite: True
|
1056
|
+
- simply-laced: False
|
1057
|
+
- skew-symmetric: False
|
1058
|
+
- finite: False
|
1059
|
+
- affine: True
|
1060
|
+
- elliptic: False
|
1061
|
+
|
1062
|
+
sage: mut_type = QuiverMutationType(['E',6,[1, 1]]); mut_type
|
1063
|
+
['E', 6, [1, 1]]
|
1064
|
+
sage: mut_type.properties()
|
1065
|
+
['E', 6, [1, 1]] has rank 8 and the following properties:
|
1066
|
+
- irreducible: True
|
1067
|
+
- mutation finite: True
|
1068
|
+
- simply-laced: False
|
1069
|
+
- skew-symmetric: True
|
1070
|
+
- finite: False
|
1071
|
+
- affine: False
|
1072
|
+
- elliptic: True
|
1073
|
+
|
1074
|
+
sage: mut_type = QuiverMutationType(['A',3],['B',3]); mut_type
|
1075
|
+
[ ['A', 3], ['B', 3] ]
|
1076
|
+
sage: mut_type.properties()
|
1077
|
+
[ ['A', 3], ['B', 3] ] has rank 6 and the following properties:
|
1078
|
+
- irreducible: False
|
1079
|
+
- mutation finite: True
|
1080
|
+
- simply-laced: False
|
1081
|
+
- skew-symmetric: False
|
1082
|
+
- finite: True
|
1083
|
+
|
1084
|
+
sage: mut_type = QuiverMutationType('GR',[4,9]); mut_type
|
1085
|
+
['GR', [4, 9]]
|
1086
|
+
sage: mut_type.properties()
|
1087
|
+
['GR', [4, 9]] has rank 12 and the following properties:
|
1088
|
+
- irreducible: True
|
1089
|
+
- mutation finite: False
|
1090
|
+
- simply-laced: True
|
1091
|
+
- skew-symmetric: True
|
1092
|
+
- finite: False
|
1093
|
+
- affine: False
|
1094
|
+
- elliptic: False
|
1095
|
+
"""
|
1096
|
+
txt = '{} has rank {} and the following properties:'
|
1097
|
+
print(txt.format(self, self.rank()))
|
1098
|
+
s = "\t- {} {}"
|
1099
|
+
print(s.format('irreducible: ', self.is_irreducible()))
|
1100
|
+
print(s.format('mutation finite: ', self.is_mutation_finite()))
|
1101
|
+
print(s.format('simply-laced: ', self.is_simply_laced()))
|
1102
|
+
print(s.format('skew-symmetric: ', self.is_skew_symmetric()))
|
1103
|
+
print(s.format('finite: ', self.is_finite()))
|
1104
|
+
if self.is_irreducible():
|
1105
|
+
print(s.format('affine: ', self.is_affine()))
|
1106
|
+
print(s.format('elliptic: ', self.is_elliptic()))
|
1107
|
+
|
1108
|
+
|
1109
|
+
class QuiverMutationType_Irreducible(QuiverMutationType_abstract):
|
1110
|
+
"""
|
1111
|
+
The mutation type for a cluster algebra or a quiver. Should not be
|
1112
|
+
called directly, but through :class:`QuiverMutationType`.
|
1113
|
+
"""
|
1114
|
+
|
1115
|
+
def __init__(self, letter, rank, twist=None):
|
1116
|
+
"""
|
1117
|
+
Should not be called directly but through QuiverMutationType.
|
1118
|
+
|
1119
|
+
INPUT:
|
1120
|
+
|
1121
|
+
- ``letter`` -- the letter of the mutation type
|
1122
|
+
- ``rank`` -- the rank of the mutation type
|
1123
|
+
- ``twist`` -- the twist of the mutation type
|
1124
|
+
|
1125
|
+
EXAMPLES::
|
1126
|
+
|
1127
|
+
sage: QuiverMutationType('A',5)
|
1128
|
+
['A', 5]
|
1129
|
+
|
1130
|
+
sage: QuiverMutationType('A',[4,5], 1)
|
1131
|
+
['A', [4, 5], 1]
|
1132
|
+
|
1133
|
+
sage: QuiverMutationType('BB',5, 1)
|
1134
|
+
['BB', 5, 1]
|
1135
|
+
|
1136
|
+
sage: QuiverMutationType('X',6)
|
1137
|
+
['X', 6]
|
1138
|
+
"""
|
1139
|
+
# _rank and _bi_rank are initialized
|
1140
|
+
self._rank = None
|
1141
|
+
self._bi_rank = None
|
1142
|
+
|
1143
|
+
# _graph and _digraph are initialized
|
1144
|
+
self._graph = Graph()
|
1145
|
+
self._digraph = DiGraph()
|
1146
|
+
|
1147
|
+
# _info is initialized
|
1148
|
+
self._info = {}
|
1149
|
+
self._info['irreducible'] = True
|
1150
|
+
self._info['mutation_finite'] = False
|
1151
|
+
self._info['simply_laced'] = False
|
1152
|
+
self._info['skew_symmetric'] = False
|
1153
|
+
self._info['finite'] = False
|
1154
|
+
self._info['affine'] = False
|
1155
|
+
self._info['elliptic'] = False
|
1156
|
+
self._info['irreducible_components'] = False
|
1157
|
+
|
1158
|
+
if isinstance(rank, tuple):
|
1159
|
+
rank = list(rank)
|
1160
|
+
if isinstance(twist, tuple):
|
1161
|
+
twist = list(twist)
|
1162
|
+
|
1163
|
+
# _letter/twist is the input letter/twist
|
1164
|
+
self._letter = letter
|
1165
|
+
self._twist = twist
|
1166
|
+
|
1167
|
+
data = [letter, rank, twist]
|
1168
|
+
|
1169
|
+
# type A (finite and affine)
|
1170
|
+
if letter == 'A':
|
1171
|
+
if twist is None and rank in ZZ and rank > 0:
|
1172
|
+
self._rank = rank
|
1173
|
+
self._info['mutation_finite'] = True
|
1174
|
+
self._info['simply_laced'] = True
|
1175
|
+
self._info['skew_symmetric'] = True
|
1176
|
+
self._info['finite'] = True
|
1177
|
+
elif twist == 1 and isinstance(rank, list) and len(rank) == 2 and all(ri in ZZ and ri >= 0 for ri in rank) and rank != [0, 0]:
|
1178
|
+
if isinstance(rank, tuple):
|
1179
|
+
rank = list(rank)
|
1180
|
+
data[1] = rank
|
1181
|
+
rank = sorted(rank)
|
1182
|
+
self._bi_rank = rank
|
1183
|
+
self._rank = sum(self._bi_rank)
|
1184
|
+
self._info['mutation_finite'] = True
|
1185
|
+
if self._rank > 2:
|
1186
|
+
self._info['simply_laced'] = True
|
1187
|
+
self._info['skew_symmetric'] = True
|
1188
|
+
if rank[0] > 0:
|
1189
|
+
self._info['affine'] = True
|
1190
|
+
elif rank[0] == 0:
|
1191
|
+
self._info['finite'] = True
|
1192
|
+
else:
|
1193
|
+
_mutation_type_error(data)
|
1194
|
+
# types ['A', 1] and ['A',[0, 1], 1] need to be treated on
|
1195
|
+
# itself (as there is no edge)
|
1196
|
+
if twist is None and self._rank == 1 or twist == 1 and self._rank == 1:
|
1197
|
+
self._graph.add_vertex(0)
|
1198
|
+
# type ['A',[1, 1], 1] needs to be treated on itself as well
|
1199
|
+
# (as there is a double edge)
|
1200
|
+
elif twist == 1 and self._bi_rank[0] == 1 and self._bi_rank[1] == 1:
|
1201
|
+
self._graph.add_edge(0, 1, 2)
|
1202
|
+
else:
|
1203
|
+
for i in range(self._rank - 1):
|
1204
|
+
self._graph.add_edge(i, i + 1, 1)
|
1205
|
+
if twist == 1:
|
1206
|
+
self._digraph.add_edge(self._rank - 1, 0, 1)
|
1207
|
+
for i in range(self._rank - 1):
|
1208
|
+
if i < (2 * self._bi_rank[0]) and i % 2 == 0:
|
1209
|
+
self._digraph.add_edge(i + 1, i, 1)
|
1210
|
+
else:
|
1211
|
+
self._digraph.add_edge(i, i + 1, 1)
|
1212
|
+
|
1213
|
+
# type B (finite)
|
1214
|
+
elif letter == 'B':
|
1215
|
+
if twist is None and rank in ZZ and rank > 1:
|
1216
|
+
self._rank = rank
|
1217
|
+
self._info['mutation_finite'] = True
|
1218
|
+
self._info['finite'] = True
|
1219
|
+
else:
|
1220
|
+
_mutation_type_error(data)
|
1221
|
+
for i in range(rank - 2):
|
1222
|
+
self._graph.add_edge(i, i+1, 1)
|
1223
|
+
if (rank % 2 == 0):
|
1224
|
+
self._graph.add_edge(rank-2, rank-1, (1, -2))
|
1225
|
+
else:
|
1226
|
+
self._graph.add_edge(rank-2, rank-1, (2, -1))
|
1227
|
+
|
1228
|
+
# type C (finite)
|
1229
|
+
elif letter == 'C':
|
1230
|
+
if twist is None and rank in ZZ and rank > 1:
|
1231
|
+
self._rank = rank
|
1232
|
+
self._info['mutation_finite'] = True
|
1233
|
+
self._info['finite'] = True
|
1234
|
+
else:
|
1235
|
+
_mutation_type_error(data)
|
1236
|
+
for i in range(rank - 2):
|
1237
|
+
self._graph.add_edge(i, i+1, 1)
|
1238
|
+
if (rank % 2 == 0):
|
1239
|
+
self._graph.add_edge(rank-2, rank-1, (2, -1))
|
1240
|
+
else:
|
1241
|
+
self._graph.add_edge(rank-2, rank-1, (1, -2))
|
1242
|
+
|
1243
|
+
# type BB (affine)
|
1244
|
+
elif letter == 'BB':
|
1245
|
+
if twist == 1 and rank in ZZ and rank > 1:
|
1246
|
+
self._rank = rank + 1
|
1247
|
+
self._info['mutation_finite'] = True
|
1248
|
+
self._info['affine'] = True
|
1249
|
+
else:
|
1250
|
+
_mutation_type_error(data)
|
1251
|
+
for i in range(rank - 2):
|
1252
|
+
self._graph.add_edge(i, i+1, 1)
|
1253
|
+
if rank % 2 == 0:
|
1254
|
+
self._graph.add_edge(rank-2, rank-1, (1, -2))
|
1255
|
+
else:
|
1256
|
+
self._graph.add_edge(rank-2, rank-1, (2, -1))
|
1257
|
+
self._graph.add_edge(rank, 0, (1, -2))
|
1258
|
+
|
1259
|
+
# type CC (affine)
|
1260
|
+
elif letter == 'CC':
|
1261
|
+
if twist == 1 and rank in ZZ and rank > 1:
|
1262
|
+
self._rank = rank + 1
|
1263
|
+
self._info['mutation_finite'] = True
|
1264
|
+
self._info['affine'] = True
|
1265
|
+
else:
|
1266
|
+
_mutation_type_error(data)
|
1267
|
+
for i in range(rank - 2):
|
1268
|
+
self._graph.add_edge(i, i+1, 1)
|
1269
|
+
if rank % 2 == 0:
|
1270
|
+
self._graph.add_edge(rank-2, rank-1, (2, -1))
|
1271
|
+
else:
|
1272
|
+
self._graph.add_edge(rank-2, rank-1, (1, -2))
|
1273
|
+
self._graph.add_edge(rank, 0, (2, -1))
|
1274
|
+
|
1275
|
+
# type BC (affine)
|
1276
|
+
elif letter == 'BC':
|
1277
|
+
if twist == 1 and rank in ZZ and rank >= 1:
|
1278
|
+
self._rank = rank + 1
|
1279
|
+
self._info['mutation_finite'] = True
|
1280
|
+
self._info['affine'] = True
|
1281
|
+
else:
|
1282
|
+
_mutation_type_error(data)
|
1283
|
+
if rank == 1:
|
1284
|
+
self._graph.add_edge(0, 1, (1, -4))
|
1285
|
+
else:
|
1286
|
+
for i in range(rank - 2):
|
1287
|
+
self._graph.add_edge(i, i+1, 1)
|
1288
|
+
if (rank % 2 == 0):
|
1289
|
+
self._graph.add_edge(rank-2, rank-1, (2, -1))
|
1290
|
+
else:
|
1291
|
+
self._graph.add_edge(rank-2, rank-1, (1, -2))
|
1292
|
+
if twist == 1:
|
1293
|
+
self._graph.add_edge(rank, 0, (1, -2))
|
1294
|
+
|
1295
|
+
# type BD (affine)
|
1296
|
+
elif letter == 'BD':
|
1297
|
+
if twist == 1 and rank in ZZ and rank > 2:
|
1298
|
+
self._rank = rank + 1
|
1299
|
+
self._info['mutation_finite'] = True
|
1300
|
+
self._info['affine'] = True
|
1301
|
+
else:
|
1302
|
+
_mutation_type_error(data)
|
1303
|
+
for i in range(rank - 2):
|
1304
|
+
self._graph.add_edge(i, i+1, 1)
|
1305
|
+
if (rank % 2 == 0):
|
1306
|
+
self._graph.add_edge(rank-2, rank-1, (1, -2))
|
1307
|
+
else:
|
1308
|
+
self._graph.add_edge(rank-2, rank-1, (2, -1))
|
1309
|
+
if twist == 1:
|
1310
|
+
self._graph.add_edge(rank, 1, 1)
|
1311
|
+
|
1312
|
+
# type CD (affine)
|
1313
|
+
elif letter == 'CD':
|
1314
|
+
if twist == 1 and rank in ZZ and rank > 2:
|
1315
|
+
self._rank = rank + 1
|
1316
|
+
self._info['mutation_finite'] = True
|
1317
|
+
self._info['affine'] = True
|
1318
|
+
else:
|
1319
|
+
_mutation_type_error(data)
|
1320
|
+
for i in range(rank - 2):
|
1321
|
+
self._graph.add_edge(i, i+1, 1)
|
1322
|
+
if (rank % 2 == 0):
|
1323
|
+
self._graph.add_edge(rank-2, rank-1, (2, -1))
|
1324
|
+
else:
|
1325
|
+
self._graph.add_edge(rank-2, rank-1, (1, -2))
|
1326
|
+
if twist == 1:
|
1327
|
+
self._graph.add_edge(rank, 1, 1)
|
1328
|
+
|
1329
|
+
# type D (finite and affine)
|
1330
|
+
elif letter == 'D':
|
1331
|
+
if rank in ZZ and rank > 3 and twist is None:
|
1332
|
+
self._rank = rank
|
1333
|
+
self._info['mutation_finite'] = True
|
1334
|
+
self._info['simply_laced'] = True
|
1335
|
+
self._info['skew_symmetric'] = True
|
1336
|
+
self._info['finite'] = True
|
1337
|
+
elif twist == 1 and rank in ZZ and rank > 3:
|
1338
|
+
self._rank = rank + 1
|
1339
|
+
self._info['mutation_finite'] = True
|
1340
|
+
self._info['simply_laced'] = True
|
1341
|
+
self._info['skew_symmetric'] = True
|
1342
|
+
self._info['affine'] = True
|
1343
|
+
else:
|
1344
|
+
_mutation_type_error(data)
|
1345
|
+
for i in range(rank - 2):
|
1346
|
+
self._graph.add_edge(i, i+1, 1)
|
1347
|
+
|
1348
|
+
self._graph.add_edge(rank-3, rank-1, 1)
|
1349
|
+
if twist is not None:
|
1350
|
+
self._graph.add_edge(rank, 1, 1)
|
1351
|
+
|
1352
|
+
# type E (finite, affine and elliptic)
|
1353
|
+
elif letter == 'E':
|
1354
|
+
if rank in [6, 7, 8] and twist is None:
|
1355
|
+
self._rank = rank
|
1356
|
+
self._info['mutation_finite'] = True
|
1357
|
+
self._info['simply_laced'] = True
|
1358
|
+
self._info['skew_symmetric'] = True
|
1359
|
+
self._info['finite'] = True
|
1360
|
+
if rank == 6:
|
1361
|
+
self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (2, 5)])
|
1362
|
+
elif rank == 7:
|
1363
|
+
self._graph.add_edges([(0, 1), (1, 2), (2, 3),
|
1364
|
+
(3, 4), (4, 5), (2, 6)])
|
1365
|
+
elif rank == 8:
|
1366
|
+
self._graph.add_edges([(0, 1), (1, 2), (2, 3),
|
1367
|
+
(3, 4), (4, 5), (5, 6), (2, 7)])
|
1368
|
+
elif rank in [6, 7, 8] and twist == 1:
|
1369
|
+
self._rank = rank + 1
|
1370
|
+
self._info['mutation_finite'] = True
|
1371
|
+
self._info['simply_laced'] = True
|
1372
|
+
self._info['skew_symmetric'] = True
|
1373
|
+
self._info['affine'] = True
|
1374
|
+
if rank == 6:
|
1375
|
+
self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (2, 5), (5, 6)])
|
1376
|
+
elif rank == 7:
|
1377
|
+
self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (3, 7)])
|
1378
|
+
elif rank == 8:
|
1379
|
+
self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (2, 8)])
|
1380
|
+
elif rank in [6, 7, 8] and twist == [1, 1]:
|
1381
|
+
self._rank = rank + 2
|
1382
|
+
self._info['mutation_finite'] = True
|
1383
|
+
self._info['skew_symmetric'] = True
|
1384
|
+
self._info['elliptic'] = True
|
1385
|
+
if rank == 6:
|
1386
|
+
self._digraph.add_edges([(0, 1, 1), (1, 2, 1), (3, 2, 1), (3, 4, 1), (5, 6, 1), (6, 7, 1), (5, 1, 1), (2, 5, 2), (5, 3, 1), (6, 2, 1)])
|
1387
|
+
elif rank == 7:
|
1388
|
+
self._digraph.add_edges([(1, 0, 1), (1, 2, 1), (2, 3, 1), (4, 3, 1), (4, 5, 1),
|
1389
|
+
(6, 5, 1), (7, 8, 1), (3, 7, 2), (7, 2, 1), (7, 4, 1), (8, 3, 1)])
|
1390
|
+
elif rank == 8:
|
1391
|
+
self._digraph.add_edges([(0, 1, 1), (1, 9, 1), (3, 9, 1), (3, 4, 1), (2, 8, 1), (2, 1, 1),
|
1392
|
+
(9, 2, 2), (2, 3, 1), (8, 9, 1), (5, 4, 1), (5, 6, 1), (7, 6, 1)])
|
1393
|
+
# type E (mutation infinite)
|
1394
|
+
elif rank > 9 and twist is None:
|
1395
|
+
self._info['simply_laced'] = True
|
1396
|
+
self._info['skew_symmetric'] = True
|
1397
|
+
self._rank = rank
|
1398
|
+
for i in range(rank-2):
|
1399
|
+
self._graph.add_edge(i, i+1, 1)
|
1400
|
+
self._graph.add_edge(2, rank-1)
|
1401
|
+
else:
|
1402
|
+
_mutation_type_error(data)
|
1403
|
+
|
1404
|
+
# type AE (mutation infinite)
|
1405
|
+
elif letter == 'AE':
|
1406
|
+
if isinstance(rank, list) and len(rank) == 2 and all(rank[i] in ZZ and rank[i] > 0 for i in [0, 1]) and twist is None:
|
1407
|
+
if isinstance(rank, tuple):
|
1408
|
+
rank = list(rank)
|
1409
|
+
data[1] = rank
|
1410
|
+
rank = sorted(rank)
|
1411
|
+
self._bi_rank = rank
|
1412
|
+
self._rank = sum(self._bi_rank) + 1
|
1413
|
+
if self._rank > 3:
|
1414
|
+
self._info['simply_laced'] = True
|
1415
|
+
self._info['skew_symmetric'] = True
|
1416
|
+
if self._bi_rank == [1, 1]:
|
1417
|
+
self._graph.add_edges([(0, 1, 2), (1, 2, None)])
|
1418
|
+
else:
|
1419
|
+
self._digraph.add_edge(self._rank - 2, 0)
|
1420
|
+
for i in range(self._rank-2):
|
1421
|
+
if i < (2 * self._bi_rank[0]) and i % 2 == 0:
|
1422
|
+
self._digraph.add_edge(i + 1, i)
|
1423
|
+
else:
|
1424
|
+
self._digraph.add_edge(i, i + 1)
|
1425
|
+
self._digraph.add_edge(self._rank-2, self._rank-1)
|
1426
|
+
else:
|
1427
|
+
_mutation_type_error(data)
|
1428
|
+
|
1429
|
+
# type BE (mutation infinite)
|
1430
|
+
elif letter == 'BE':
|
1431
|
+
if rank > 4 and twist is None:
|
1432
|
+
self._rank = rank
|
1433
|
+
for i in range(rank-3):
|
1434
|
+
self._graph.add_edge(i, i+1)
|
1435
|
+
self._graph.add_edge(2, rank-1)
|
1436
|
+
if rank % 2 == 0:
|
1437
|
+
self._graph.add_edge(rank-3, rank-2, (2, -1))
|
1438
|
+
else:
|
1439
|
+
self._graph.add_edge(rank-3, rank-2, (1, -2))
|
1440
|
+
else:
|
1441
|
+
_mutation_type_error(data)
|
1442
|
+
|
1443
|
+
# type CE (mutation infinite)
|
1444
|
+
elif letter == 'CE':
|
1445
|
+
if rank > 4 and twist is None:
|
1446
|
+
self._rank = rank
|
1447
|
+
for i in range(rank-3):
|
1448
|
+
self._graph.add_edge(i, i+1)
|
1449
|
+
self._graph.add_edge(2, rank-1)
|
1450
|
+
if rank % 2 == 0:
|
1451
|
+
self._graph.add_edge(rank-3, rank-2, (1, -2))
|
1452
|
+
else:
|
1453
|
+
self._graph.add_edge(rank-3, rank-2, (2, -1))
|
1454
|
+
else:
|
1455
|
+
_mutation_type_error(data)
|
1456
|
+
|
1457
|
+
# type DE (mutation infinite)
|
1458
|
+
elif letter == 'DE':
|
1459
|
+
if rank > 5 and twist is None:
|
1460
|
+
self._rank = rank
|
1461
|
+
self._info['simply_laced'] = True
|
1462
|
+
self._info['skew_symmetric'] = True
|
1463
|
+
for i in range(rank-3):
|
1464
|
+
self._graph.add_edge(i, i+1)
|
1465
|
+
self._graph.add_edge(2, rank-2)
|
1466
|
+
self._graph.add_edge(rank-4, rank-1)
|
1467
|
+
else:
|
1468
|
+
_mutation_type_error(data)
|
1469
|
+
|
1470
|
+
# type F (finite, affine, and elliptic)
|
1471
|
+
elif letter == 'F':
|
1472
|
+
if rank == 4 and twist is None:
|
1473
|
+
self._rank = rank
|
1474
|
+
self._info['mutation_finite'] = True
|
1475
|
+
self._info['finite'] = True
|
1476
|
+
self._graph.add_edges([(0, 1, None), (1, 2, (2, -1)), (2, 3, None)])
|
1477
|
+
elif rank == 4 and twist == 1:
|
1478
|
+
self._rank = rank + 1
|
1479
|
+
self._info['mutation_finite'] = True
|
1480
|
+
self._info['affine'] = True
|
1481
|
+
self._graph.add_edges([(0, 1, None), (1, 2, None),
|
1482
|
+
(2, 3, (1, -2)), (3, 4, None)])
|
1483
|
+
elif rank == 4 and twist == -1:
|
1484
|
+
self._rank = rank + 1
|
1485
|
+
self._info['mutation_finite'] = True
|
1486
|
+
self._info['affine'] = True
|
1487
|
+
self._graph.add_edges([(0, 1, None), (1, 2, None),
|
1488
|
+
(2, 3, (2, -1)), (3, 4, None)])
|
1489
|
+
elif rank == 4 and (twist == [1, 2]):
|
1490
|
+
self._rank = rank + 2
|
1491
|
+
self._info['mutation_finite'] = True
|
1492
|
+
self._info['elliptic'] = True
|
1493
|
+
self._digraph.add_edges([(0, 1, None), (1, 2, None),
|
1494
|
+
(2, 3, (2, -1)), (4, 2, (1, -2)),
|
1495
|
+
(3, 4, 2), (4, 5, None), (5, 3, None)])
|
1496
|
+
elif rank == 4 and (twist == [2, 1]):
|
1497
|
+
self._rank = rank + 2
|
1498
|
+
self._info['mutation_finite'] = True
|
1499
|
+
self._info['elliptic'] = True
|
1500
|
+
self._digraph.add_edges([(0, 1, None), (1, 2, None),
|
1501
|
+
(2, 3, (1, -2)), (4, 2, (2, -1)),
|
1502
|
+
(3, 4, 2), (4, 5, None), (5, 3, None)])
|
1503
|
+
elif rank == 4 and twist == [2, 2]:
|
1504
|
+
self._rank = rank + 2
|
1505
|
+
self._info['mutation_finite'] = True
|
1506
|
+
self._info['elliptic'] = True
|
1507
|
+
self._digraph.add_edges([(0, 1, None), (1, 2, None),
|
1508
|
+
(3, 1, None), (2, 3, 2),
|
1509
|
+
(4, 2, (2, -1)), (3, 4, (1, -2)),
|
1510
|
+
(5, 4, None)])
|
1511
|
+
elif rank == 4 and twist == [1, 1]:
|
1512
|
+
self._rank = rank + 2
|
1513
|
+
self._info['mutation_finite'] = True
|
1514
|
+
self._info['elliptic'] = True
|
1515
|
+
self._digraph.add_edges([(0, 1, None), (1, 2, None),
|
1516
|
+
(3, 1, None), (2, 3, 2), (4, 2, (1, -2)),
|
1517
|
+
(3, 4, (2, -1)), (5, 4, None)])
|
1518
|
+
else:
|
1519
|
+
_mutation_type_error(data)
|
1520
|
+
|
1521
|
+
# type G (finite, affine, and elliptic)
|
1522
|
+
elif letter == 'G':
|
1523
|
+
if rank == 2 and twist is None:
|
1524
|
+
self._rank = rank
|
1525
|
+
self._info['mutation_finite'] = True
|
1526
|
+
self._info['finite'] = True
|
1527
|
+
self._graph.add_edges([(0, 1, (1, -3))])
|
1528
|
+
elif rank == 2 and twist == -1:
|
1529
|
+
self._rank = rank + 1
|
1530
|
+
self._info['mutation_finite'] = True
|
1531
|
+
self._info['affine'] = True
|
1532
|
+
self._graph.add_edges([(0, 1, None), (1, 2, (1, -3))])
|
1533
|
+
elif rank == 2 and twist == 1:
|
1534
|
+
self._rank = rank + 1
|
1535
|
+
self._info['mutation_finite'] = True
|
1536
|
+
self._info['affine'] = True
|
1537
|
+
self._graph.add_edges([(0, 1, None), (1, 2, (3, -1))])
|
1538
|
+
elif rank == 2 and (twist == [1, 3]):
|
1539
|
+
self._rank = rank + 2
|
1540
|
+
self._info['mutation_finite'] = True
|
1541
|
+
self._info['elliptic'] = True
|
1542
|
+
self._digraph.add_edges([(0, 1, None), (1, 2, (3, -1)),
|
1543
|
+
(3, 1, (1, -3)), (2, 3, 2)])
|
1544
|
+
elif rank == 2 and (twist == [3, 1]):
|
1545
|
+
self._rank = rank + 2
|
1546
|
+
self._info['mutation_finite'] = True
|
1547
|
+
self._info['elliptic'] = True
|
1548
|
+
self._digraph.add_edges([(0, 1, None), (1, 2, (1, -3)),
|
1549
|
+
(3, 1, (3, -1)), (2, 3, 2)])
|
1550
|
+
elif rank == 2 and twist == [3, 3]:
|
1551
|
+
self._rank = rank + 2
|
1552
|
+
self._info['mutation_finite'] = True
|
1553
|
+
self._info['elliptic'] = True
|
1554
|
+
self._digraph.add_edges([(1, 0, None), (0, 2, 2), (3, 0, (3, -1)),
|
1555
|
+
(2, 1, None), (2, 3, (1, -3))])
|
1556
|
+
elif rank == 2 and twist == [1, 1]:
|
1557
|
+
self._rank = rank + 2
|
1558
|
+
self._info['mutation_finite'] = True
|
1559
|
+
self._info['elliptic'] = True
|
1560
|
+
self._digraph.add_edges([(1, 0, None), (0, 2, 2), (3, 0, (1, -3)),
|
1561
|
+
(2, 1, None), (2, 3, (3, -1))])
|
1562
|
+
else:
|
1563
|
+
_mutation_type_error(data)
|
1564
|
+
|
1565
|
+
# type GR (mutation infinite)
|
1566
|
+
elif letter == 'GR':
|
1567
|
+
if twist is None and isinstance(rank, list) and len(rank) == 2 and all(rank[i] in ZZ and rank[i] > 0 for i in [0, 1]) and rank[1] - 1 > rank[0] > 1:
|
1568
|
+
gr_rank = (rank[0]-1, rank[1]-rank[0]-1)
|
1569
|
+
self._rank = prod(gr_rank)
|
1570
|
+
self._info['simply_laced'] = True
|
1571
|
+
self._info['skew_symmetric'] = True
|
1572
|
+
a, b = gr_rank
|
1573
|
+
for i in range(a):
|
1574
|
+
for j in range(b):
|
1575
|
+
if i < a-1:
|
1576
|
+
if (i+j) % 2 == 0:
|
1577
|
+
self._digraph.add_edge(i*b+j, (i+1)*b+j)
|
1578
|
+
else:
|
1579
|
+
self._digraph.add_edge((i+1)*b+j, i*b+j)
|
1580
|
+
if j < b-1:
|
1581
|
+
if (i+j) % 2 == 0:
|
1582
|
+
self._digraph.add_edge(i*b+j+1, i*b+j)
|
1583
|
+
else:
|
1584
|
+
self._digraph.add_edge(i*b+j, i*b+j+1)
|
1585
|
+
else:
|
1586
|
+
_mutation_type_error(data)
|
1587
|
+
|
1588
|
+
# type R2 (rank 2 finite mutation types)
|
1589
|
+
elif letter == 'R2':
|
1590
|
+
if twist is None and isinstance(rank, list) and len(rank) == 2 and all(rank[i] in ZZ and rank[i] > 0 for i in [0, 1]):
|
1591
|
+
rank = sorted(rank)
|
1592
|
+
b, c = rank
|
1593
|
+
self._rank = 2
|
1594
|
+
if b == c:
|
1595
|
+
self._info['skew_symmetric'] = True
|
1596
|
+
self._graph.add_edge(0, 1, (b, -c))
|
1597
|
+
else:
|
1598
|
+
_mutation_type_error(data)
|
1599
|
+
|
1600
|
+
# type T
|
1601
|
+
elif letter == 'T':
|
1602
|
+
if twist is None and isinstance(rank, list) and len(rank) == 3 and all(rank[i] in ZZ and rank[i] > 0 for i in [0, 1, 2]):
|
1603
|
+
if isinstance(rank, tuple):
|
1604
|
+
rank = list(rank)
|
1605
|
+
data[1] = rank
|
1606
|
+
rank = sorted(rank)
|
1607
|
+
self._rank = sum(rank) - 2
|
1608
|
+
self._info['simply_laced'] = True
|
1609
|
+
self._info['skew_symmetric'] = True
|
1610
|
+
r, p, q = rank
|
1611
|
+
for i in range(q-1):
|
1612
|
+
if i == 0:
|
1613
|
+
self._graph.add_edge(0, 1)
|
1614
|
+
self._graph.add_edge(0, r)
|
1615
|
+
self._graph.add_edge(0, r+p-1)
|
1616
|
+
else:
|
1617
|
+
if i < r-1:
|
1618
|
+
self._graph.add_edge(i, i+1)
|
1619
|
+
if i < p-1:
|
1620
|
+
self._graph.add_edge(i+r-1, i+r)
|
1621
|
+
self._graph.add_edge(i+r+p-2, i+r+p-1)
|
1622
|
+
else:
|
1623
|
+
_mutation_type_error(data)
|
1624
|
+
|
1625
|
+
# type TR (mutation infinite if rank > 2)
|
1626
|
+
elif letter == 'TR':
|
1627
|
+
# type ['TR', 1] needs to be treated on itself (as there is no edge)
|
1628
|
+
if twist is None and rank == 1:
|
1629
|
+
self._graph.add_vertex(0)
|
1630
|
+
elif twist is None and rank > 1:
|
1631
|
+
self._rank = rank*(rank+1)//2
|
1632
|
+
self._info['simply_laced'] = True
|
1633
|
+
self._info['skew_symmetric'] = True
|
1634
|
+
level = 0
|
1635
|
+
while level < rank:
|
1636
|
+
nr = rank*level-sum(range(level))
|
1637
|
+
for i in range(nr, nr+rank-level-1):
|
1638
|
+
self._digraph.add_edge(i, i+1)
|
1639
|
+
self._digraph.add_edge(i+rank-level, i)
|
1640
|
+
self._digraph.add_edge(i+1, i+rank-level)
|
1641
|
+
level += 1
|
1642
|
+
else:
|
1643
|
+
_mutation_type_error(data)
|
1644
|
+
|
1645
|
+
# type X
|
1646
|
+
elif letter == 'X':
|
1647
|
+
if rank in [6, 7] and twist is None:
|
1648
|
+
self._rank = rank
|
1649
|
+
self._info['mutation_finite'] = True
|
1650
|
+
self._info['skew_symmetric'] = True
|
1651
|
+
self._digraph.add_edges([(0, 1, 2), (1, 2, None), (2, 0, None),
|
1652
|
+
(2, 3, None), (3, 4, 2), (4, 2, None),
|
1653
|
+
(2, 5, None)])
|
1654
|
+
if rank == 7:
|
1655
|
+
self._digraph.add_edges([(5, 6, 2), (6, 2, None)])
|
1656
|
+
else:
|
1657
|
+
_mutation_type_error(data)
|
1658
|
+
|
1659
|
+
# otherwise, an error is raised
|
1660
|
+
else:
|
1661
|
+
_mutation_type_error(data)
|
1662
|
+
|
1663
|
+
# in the bipartite case, the digraph is constructed from the graph
|
1664
|
+
if not self._digraph:
|
1665
|
+
if self._graph.is_bipartite():
|
1666
|
+
self._digraph = _bipartite_graph_to_digraph(self._graph)
|
1667
|
+
else:
|
1668
|
+
raise ValueError('The QuiverMutationType does not have '
|
1669
|
+
'a Coxeter diagram.')
|
1670
|
+
|
1671
|
+
# in the other cases, the graph is constructed from the digraph
|
1672
|
+
if not self._graph:
|
1673
|
+
self._graph = self._digraph.to_undirected()
|
1674
|
+
|
1675
|
+
# _description is as for CartanType
|
1676
|
+
if twist:
|
1677
|
+
self._description = str([letter, rank, twist])
|
1678
|
+
else:
|
1679
|
+
self._description = str([letter, rank])
|
1680
|
+
|
1681
|
+
def irreducible_components(self):
|
1682
|
+
"""
|
1683
|
+
Return a list of all irreducible components of ``self``.
|
1684
|
+
|
1685
|
+
EXAMPLES::
|
1686
|
+
|
1687
|
+
sage: mut_type = QuiverMutationType('A',3); mut_type
|
1688
|
+
['A', 3]
|
1689
|
+
sage: mut_type.irreducible_components()
|
1690
|
+
(['A', 3],)
|
1691
|
+
"""
|
1692
|
+
return (self,)
|
1693
|
+
|
1694
|
+
@cached_method
|
1695
|
+
def class_size(self):
|
1696
|
+
r"""
|
1697
|
+
If it is known, the size of the mutation class of all quivers
|
1698
|
+
which are mutation equivalent to the standard quiver of
|
1699
|
+
``self`` (up to isomorphism) is returned.
|
1700
|
+
|
1701
|
+
Otherwise, :obj:`NotImplemented` is returned.
|
1702
|
+
|
1703
|
+
Formula for finite type A is taken from Torkildsen - Counting
|
1704
|
+
cluster-tilted algebras of type `A_n`.
|
1705
|
+
Formulas for affine type A and finite type D are taken from Bastian,
|
1706
|
+
Prellberg, Rubey, Stump - Counting the number of elements in the
|
1707
|
+
mutation classes of `\widetilde A_n` quivers.
|
1708
|
+
Formulas for finite and affine types B and C are
|
1709
|
+
proven but not yet published.
|
1710
|
+
Conjectural formulas for several other non-simply-laced affine types
|
1711
|
+
are implemented.
|
1712
|
+
Exceptional Types (finite, affine, and elliptic) E, F, G, and X are
|
1713
|
+
hardcoded.
|
1714
|
+
|
1715
|
+
EXAMPLES::
|
1716
|
+
|
1717
|
+
sage: mut_type = QuiverMutationType( ['A',5] ); mut_type
|
1718
|
+
['A', 5]
|
1719
|
+
sage: mut_type.class_size()
|
1720
|
+
19
|
1721
|
+
|
1722
|
+
sage: mut_type = QuiverMutationType( ['A',[10,3], 1] ); mut_type
|
1723
|
+
['A', [3, 10], 1]
|
1724
|
+
sage: mut_type.class_size()
|
1725
|
+
142120
|
1726
|
+
|
1727
|
+
sage: mut_type = QuiverMutationType( ['B',6] ); mut_type
|
1728
|
+
['B', 6]
|
1729
|
+
sage: mut_type.class_size()
|
1730
|
+
132
|
1731
|
+
|
1732
|
+
sage: mut_type = QuiverMutationType( ['BD',6, 1] ); mut_type
|
1733
|
+
['BD', 6, 1]
|
1734
|
+
sage: mut_type.class_size()
|
1735
|
+
Warning: This method uses a formula which has not been proved correct.
|
1736
|
+
504
|
1737
|
+
|
1738
|
+
Check that :issue:`14048` is fixed::
|
1739
|
+
|
1740
|
+
sage: mut_type = QuiverMutationType( ['F',4,(2, 1)] )
|
1741
|
+
sage: mut_type.class_size()
|
1742
|
+
90
|
1743
|
+
"""
|
1744
|
+
if not self.is_mutation_finite():
|
1745
|
+
return infinity
|
1746
|
+
|
1747
|
+
# type A (finite and affine)
|
1748
|
+
if self._letter == 'A':
|
1749
|
+
# the formula is taken from Torkildsen - Counting
|
1750
|
+
# cluster-tilted algebras of type A
|
1751
|
+
if self.is_finite():
|
1752
|
+
n = self._rank
|
1753
|
+
a = binomial(2*(n+1), n+1) // (n+2)
|
1754
|
+
if n % 2 == 1:
|
1755
|
+
a += binomial(n+1, (n+1)//2)
|
1756
|
+
if n % 3 == 0:
|
1757
|
+
a += 2 * binomial(2*n//3, n//3)
|
1758
|
+
return a // (n+3)
|
1759
|
+
# the formula is taken from Bastian, Prellberg, Rubey, Stump
|
1760
|
+
elif self.is_affine():
|
1761
|
+
i, j = self._bi_rank
|
1762
|
+
i = ZZ(i)
|
1763
|
+
j = ZZ(j)
|
1764
|
+
n = i+j
|
1765
|
+
f = euler_phi
|
1766
|
+
if i == j:
|
1767
|
+
return (binomial(2 * i, i) +
|
1768
|
+
sum(f(k) * binomial(2 * i // k, i // k)**2
|
1769
|
+
for k in i.divisors()
|
1770
|
+
if k in j.divisors()) // n) // 4
|
1771
|
+
else:
|
1772
|
+
return sum(f(k) * binomial(2 * i // k, i // k) *
|
1773
|
+
binomial(2 * j // k, j // k)
|
1774
|
+
for k in i.divisors()
|
1775
|
+
if k in j.divisors()) // (2 * n)
|
1776
|
+
|
1777
|
+
# types B and C (finite and affine)
|
1778
|
+
elif self._letter in ['B', 'C']:
|
1779
|
+
# this formula is proven but nowhere published correctness
|
1780
|
+
# is clear enough that I don't think a warning is needed
|
1781
|
+
if self.is_finite():
|
1782
|
+
n = self._rank
|
1783
|
+
return binomial(2 * n, n) // (n + 1)
|
1784
|
+
|
1785
|
+
elif self._letter in ['BB', 'CC']:
|
1786
|
+
# these two formulas are not yet proven
|
1787
|
+
print("Warning: This method uses a formula "
|
1788
|
+
"which has not been proved correct.")
|
1789
|
+
if self.is_affine():
|
1790
|
+
if self._twist == 1:
|
1791
|
+
n = self._rank - 1
|
1792
|
+
N = binomial(2 * n - 1, n - 1)
|
1793
|
+
if n % 2:
|
1794
|
+
return N
|
1795
|
+
else:
|
1796
|
+
return N + binomial(n - 1, n // 2 - 1)
|
1797
|
+
|
1798
|
+
# type BC (affine)
|
1799
|
+
elif self._letter == 'BC':
|
1800
|
+
# this formula is not yet proven
|
1801
|
+
print("Warning: This method uses a formula "
|
1802
|
+
"which has not been proved correct.")
|
1803
|
+
if self.is_affine():
|
1804
|
+
if self._twist == 1:
|
1805
|
+
n = self._rank - 1
|
1806
|
+
return binomial(2 * n, n)
|
1807
|
+
|
1808
|
+
# types BD and CD (affine)
|
1809
|
+
elif self._letter in ['BD', 'CD']:
|
1810
|
+
# this formula is not yet proven
|
1811
|
+
print("Warning: This method uses a formula "
|
1812
|
+
"which has not been proved correct.")
|
1813
|
+
if self.is_affine():
|
1814
|
+
if self._twist == 1:
|
1815
|
+
n = self._rank - 2
|
1816
|
+
return 2 * binomial(2 * n, n)
|
1817
|
+
|
1818
|
+
# type D (finite and affine)
|
1819
|
+
elif self._letter == 'D':
|
1820
|
+
# the formula is taken from Bastian, Prellberg, Rubey, Stump
|
1821
|
+
if self.is_finite():
|
1822
|
+
if self._rank == 4:
|
1823
|
+
return 6
|
1824
|
+
else:
|
1825
|
+
f = euler_phi
|
1826
|
+
n = ZZ(self._rank)
|
1827
|
+
return sum(f(n // k) * binomial(2 * k, k)
|
1828
|
+
for k in n.divisors()) // (2 * n)
|
1829
|
+
# this formula is not yet proven
|
1830
|
+
elif self.is_affine():
|
1831
|
+
n = self._rank - 3
|
1832
|
+
if n == 2:
|
1833
|
+
return 9
|
1834
|
+
else:
|
1835
|
+
print("Warning: This method uses a formula "
|
1836
|
+
"which has not been proved correct.")
|
1837
|
+
if n % 2:
|
1838
|
+
return 2 * binomial(2 * n, n)
|
1839
|
+
else:
|
1840
|
+
return 2 * binomial(2 * n, n) + binomial(n, n // 2)
|
1841
|
+
|
1842
|
+
# the exceptional types are hard-coded
|
1843
|
+
# type E (finite, affine and elliptic)
|
1844
|
+
elif self._letter == 'E':
|
1845
|
+
if self.is_finite():
|
1846
|
+
if self._rank == 6:
|
1847
|
+
return 67
|
1848
|
+
elif self._rank == 7:
|
1849
|
+
return 416
|
1850
|
+
elif self._rank == 8:
|
1851
|
+
return 1574
|
1852
|
+
elif self.is_affine():
|
1853
|
+
if self._rank == 7:
|
1854
|
+
return 132
|
1855
|
+
elif self._rank == 8:
|
1856
|
+
return 1080
|
1857
|
+
elif self._rank == 9:
|
1858
|
+
return 7560
|
1859
|
+
elif self.is_elliptic():
|
1860
|
+
if self._rank == 8:
|
1861
|
+
return 49
|
1862
|
+
elif self._rank == 9:
|
1863
|
+
return 506
|
1864
|
+
elif self._rank == 10:
|
1865
|
+
return 5739
|
1866
|
+
|
1867
|
+
# type F
|
1868
|
+
elif self._letter == 'F':
|
1869
|
+
if self.is_finite():
|
1870
|
+
return 15
|
1871
|
+
elif self.is_affine():
|
1872
|
+
return 60
|
1873
|
+
elif self.is_elliptic():
|
1874
|
+
if self._twist == [1, 2]:
|
1875
|
+
return 90
|
1876
|
+
if self._twist == [1, 1] or self._twist == [2, 2]:
|
1877
|
+
return 35
|
1878
|
+
|
1879
|
+
# type G
|
1880
|
+
elif self._letter == 'G':
|
1881
|
+
if self.is_finite():
|
1882
|
+
return 2
|
1883
|
+
elif self.is_affine():
|
1884
|
+
return 6
|
1885
|
+
elif self.is_elliptic():
|
1886
|
+
if self._twist == [1, 3]:
|
1887
|
+
return 7
|
1888
|
+
if self._twist == [1, 1] or self._twist == [3, 3]:
|
1889
|
+
return 2
|
1890
|
+
|
1891
|
+
# type X
|
1892
|
+
elif self._letter == 'X':
|
1893
|
+
if self._rank == 6:
|
1894
|
+
return 5
|
1895
|
+
elif self._rank == 7:
|
1896
|
+
return 2
|
1897
|
+
|
1898
|
+
# otherwise the size is returned to be unknown
|
1899
|
+
else:
|
1900
|
+
print("Size unknown")
|
1901
|
+
return NotImplemented
|
1902
|
+
|
1903
|
+
def dual(self):
|
1904
|
+
"""
|
1905
|
+
Return the :class:`QuiverMutationType` which is dual to ``self``.
|
1906
|
+
|
1907
|
+
EXAMPLES::
|
1908
|
+
|
1909
|
+
sage: mut_type = QuiverMutationType('A',5); mut_type
|
1910
|
+
['A', 5]
|
1911
|
+
sage: mut_type.dual()
|
1912
|
+
['A', 5]
|
1913
|
+
|
1914
|
+
sage: mut_type = QuiverMutationType('B',5); mut_type
|
1915
|
+
['B', 5]
|
1916
|
+
sage: mut_type.dual()
|
1917
|
+
['C', 5]
|
1918
|
+
sage: mut_type.dual().dual()
|
1919
|
+
['B', 5]
|
1920
|
+
sage: mut_type.dual().dual() == mut_type
|
1921
|
+
True
|
1922
|
+
"""
|
1923
|
+
letter = self.letter()
|
1924
|
+
# the self-dual cases
|
1925
|
+
if letter != 'BC' and letter[0] in ['B', 'C']:
|
1926
|
+
if letter == 'BB':
|
1927
|
+
letter = 'CC'
|
1928
|
+
elif letter == 'CC':
|
1929
|
+
letter = 'BB'
|
1930
|
+
elif letter[0] == 'B':
|
1931
|
+
letter = 'C' + letter[1:]
|
1932
|
+
elif letter[0] == 'C':
|
1933
|
+
letter = 'B' + letter[1:]
|
1934
|
+
rank = self._rank
|
1935
|
+
if self.is_affine():
|
1936
|
+
rank -= 1
|
1937
|
+
twist = self._twist
|
1938
|
+
return QuiverMutationType(letter, rank, twist)
|
1939
|
+
# the cases F and G have non-trivial duality in some cases
|
1940
|
+
elif letter in ['F', 'G']:
|
1941
|
+
if self.is_finite():
|
1942
|
+
return self
|
1943
|
+
elif self.is_affine():
|
1944
|
+
rank = self._rank - 1
|
1945
|
+
twist = - self._twist
|
1946
|
+
elif self.is_elliptic():
|
1947
|
+
twist = self._twist
|
1948
|
+
rank = self._rank - 2
|
1949
|
+
if letter == 'F':
|
1950
|
+
if self._twist == [2, 2]:
|
1951
|
+
twist == [1, 1]
|
1952
|
+
if self._twist == [1, 1]:
|
1953
|
+
twist == [2, 2]
|
1954
|
+
if letter == 'G':
|
1955
|
+
if self._twist == [3, 3]:
|
1956
|
+
twist = [1, 1]
|
1957
|
+
elif self._twist == [1, 1]:
|
1958
|
+
twist = [3, 3]
|
1959
|
+
else:
|
1960
|
+
rank = self._rank
|
1961
|
+
return QuiverMutationType(letter, rank, twist)
|
1962
|
+
else:
|
1963
|
+
return self
|
1964
|
+
|
1965
|
+
|
1966
|
+
class QuiverMutationType_Reducible(QuiverMutationType_abstract):
|
1967
|
+
"""
|
1968
|
+
The mutation type for a cluster algebra or a quiver. Should not be
|
1969
|
+
called directly, but through :class:`QuiverMutationType`. Inherits from
|
1970
|
+
:class:`QuiverMutationType_abstract`.
|
1971
|
+
"""
|
1972
|
+
|
1973
|
+
def __init__(self, *args):
|
1974
|
+
"""
|
1975
|
+
Should not be called directly, but through QuiverMutationType.
|
1976
|
+
|
1977
|
+
INPUT:
|
1978
|
+
|
1979
|
+
- ``data`` -- list; each of whose entries is a
|
1980
|
+
:class:`QuiverMutationType_Irreducible`
|
1981
|
+
|
1982
|
+
EXAMPLES::
|
1983
|
+
|
1984
|
+
sage: QuiverMutationType(['A',4],['B',6])
|
1985
|
+
[ ['A', 4], ['B', 6] ]
|
1986
|
+
"""
|
1987
|
+
data = args
|
1988
|
+
if len(data) < 2 or not all(isinstance(comp, QuiverMutationType_Irreducible) for comp in data):
|
1989
|
+
_mutation_type_error(data)
|
1990
|
+
|
1991
|
+
# _info is initialized
|
1992
|
+
self._info = {}
|
1993
|
+
self._info['irreducible'] = False
|
1994
|
+
self._info['mutation_finite'] = all(comp.is_mutation_finite()
|
1995
|
+
for comp in data)
|
1996
|
+
self._info['simply_laced'] = all(comp.is_simply_laced()
|
1997
|
+
for comp in data)
|
1998
|
+
self._info['skew_symmetric'] = all(comp.is_skew_symmetric()
|
1999
|
+
for comp in data)
|
2000
|
+
self._info['finite'] = all(comp.is_finite() for comp in data)
|
2001
|
+
self._info['irreducible_components'] = copy(data)
|
2002
|
+
|
2003
|
+
# letter and rank are initialized
|
2004
|
+
self._letter = ''
|
2005
|
+
self._rank = 0
|
2006
|
+
|
2007
|
+
# graph and digraph are initialized
|
2008
|
+
self._graph = Graph()
|
2009
|
+
self._digraph = DiGraph()
|
2010
|
+
|
2011
|
+
for comp in data:
|
2012
|
+
if self._letter:
|
2013
|
+
self._letter += ' x '
|
2014
|
+
self._letter += comp._letter
|
2015
|
+
self._rank += comp._rank
|
2016
|
+
self._graph = self._graph.disjoint_union(comp._graph,
|
2017
|
+
labels='integers')
|
2018
|
+
self._digraph = self._digraph.disjoint_union(comp._digraph,
|
2019
|
+
labels='integers')
|
2020
|
+
self._graph.name('')
|
2021
|
+
self._digraph.name('')
|
2022
|
+
|
2023
|
+
# _description is as for CartanType
|
2024
|
+
self._description = "[ "
|
2025
|
+
comps = self.irreducible_components()
|
2026
|
+
for i in range(len(comps)):
|
2027
|
+
if i > 0:
|
2028
|
+
self._description += ", "
|
2029
|
+
self._description += comps[i]._description
|
2030
|
+
self._description += " ]"
|
2031
|
+
|
2032
|
+
def irreducible_components(self):
|
2033
|
+
"""
|
2034
|
+
Return a list of all irreducible components of ``self``.
|
2035
|
+
|
2036
|
+
EXAMPLES::
|
2037
|
+
|
2038
|
+
sage: mut_type = QuiverMutationType('A',3); mut_type
|
2039
|
+
['A', 3]
|
2040
|
+
sage: mut_type.irreducible_components()
|
2041
|
+
(['A', 3],)
|
2042
|
+
|
2043
|
+
sage: mut_type = QuiverMutationType(['A',3],['B',3]); mut_type
|
2044
|
+
[ ['A', 3], ['B', 3] ]
|
2045
|
+
sage: mut_type.irreducible_components()
|
2046
|
+
(['A', 3], ['B', 3])
|
2047
|
+
|
2048
|
+
sage: mut_type = QuiverMutationType(['A',3],['B',3],['X',6])
|
2049
|
+
sage: mut_type
|
2050
|
+
[ ['A', 3], ['B', 3], ['X', 6] ]
|
2051
|
+
sage: mut_type.irreducible_components()
|
2052
|
+
(['A', 3], ['B', 3], ['X', 6])
|
2053
|
+
"""
|
2054
|
+
return self._info['irreducible_components']
|
2055
|
+
|
2056
|
+
@cached_method
|
2057
|
+
def class_size(self):
|
2058
|
+
"""
|
2059
|
+
If it is known, the size of the mutation class of all quivers
|
2060
|
+
which are mutation equivalent to the standard quiver of
|
2061
|
+
``self`` (up to isomorphism) is returned.
|
2062
|
+
|
2063
|
+
Otherwise, :obj:`NotImplemented` is returned.
|
2064
|
+
|
2065
|
+
EXAMPLES::
|
2066
|
+
|
2067
|
+
sage: mut_type = QuiverMutationType(['A',3],['B',3]); mut_type
|
2068
|
+
[ ['A', 3], ['B', 3] ]
|
2069
|
+
sage: mut_type.class_size()
|
2070
|
+
20
|
2071
|
+
|
2072
|
+
sage: mut_type = QuiverMutationType(['A',3],['B',3],['X',6])
|
2073
|
+
sage: mut_type
|
2074
|
+
[ ['A', 3], ['B', 3], ['X', 6] ]
|
2075
|
+
sage: mut_type.class_size()
|
2076
|
+
100
|
2077
|
+
"""
|
2078
|
+
if not self.is_mutation_finite():
|
2079
|
+
return infinity
|
2080
|
+
|
2081
|
+
components = []
|
2082
|
+
multiplicities = []
|
2083
|
+
for x in self.irreducible_components():
|
2084
|
+
if not components.count(x):
|
2085
|
+
components.append(x)
|
2086
|
+
multiplicities.append(1)
|
2087
|
+
else:
|
2088
|
+
y = components.index(x)
|
2089
|
+
multiplicities[y] += 1
|
2090
|
+
|
2091
|
+
sizes = [x.class_size() for x in components]
|
2092
|
+
if NotImplemented in sizes:
|
2093
|
+
print("Size unknown")
|
2094
|
+
return NotImplemented
|
2095
|
+
else:
|
2096
|
+
return prod(binomial(sizes[i] + multiplicities[i] - 1,
|
2097
|
+
multiplicities[i])
|
2098
|
+
for i in range(len(sizes)))
|
2099
|
+
|
2100
|
+
def dual(self):
|
2101
|
+
"""
|
2102
|
+
Return the :class:`QuiverMutationType` which is dual to ``self``.
|
2103
|
+
|
2104
|
+
EXAMPLES::
|
2105
|
+
|
2106
|
+
sage: mut_type = QuiverMutationType(['A',5],['B',6],['C',5],['D',4]); mut_type
|
2107
|
+
[ ['A', 5], ['B', 6], ['C', 5], ['D', 4] ]
|
2108
|
+
sage: mut_type.dual()
|
2109
|
+
[ ['A', 5], ['C', 6], ['B', 5], ['D', 4] ]
|
2110
|
+
"""
|
2111
|
+
comps = self.irreducible_components()
|
2112
|
+
return QuiverMutationType([comp.dual() for comp in comps])
|
2113
|
+
|
2114
|
+
|
2115
|
+
def _construct_classical_mutation_classes(n) -> dict[tuple, list | set]:
|
2116
|
+
r"""
|
2117
|
+
Return a dict with keys being tuples representing regular
|
2118
|
+
QuiverMutationTypes of the given rank, and with values being lists
|
2119
|
+
or sets containing all mutation equivalent quivers as dig6 data.
|
2120
|
+
|
2121
|
+
EXAMPLES::
|
2122
|
+
|
2123
|
+
sage: from sage.combinat.cluster_algebra_quiver.quiver_mutation_type import _construct_classical_mutation_classes
|
2124
|
+
sage: rank_2_classes = _construct_classical_mutation_classes(2) # long time
|
2125
|
+
sage: for mut_class in sorted(rank_2_classes.keys(),key=str): # long time
|
2126
|
+
....: print("{} {}".format(mut_class, rank_2_classes[mut_class]))
|
2127
|
+
('A', (1, 1), 1) [('AO', (((0, 1), (2, -2)),))]
|
2128
|
+
('A', 2) [('AO', ())]
|
2129
|
+
('B', 2) [('AO', (((0, 1), (1, -2)),)), ('AO', (((0, 1), (2, -1)),))]
|
2130
|
+
('BC', 1, 1) [('AO', (((0, 1), (1, -4)),)),
|
2131
|
+
('AO', (((0, 1), (4, -1)),))]
|
2132
|
+
"""
|
2133
|
+
from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver
|
2134
|
+
data: dict[tuple, set | list] = {}
|
2135
|
+
|
2136
|
+
# finite A
|
2137
|
+
data[('A', n)] = ClusterQuiver(['A', n]).mutation_class(data_type='dig6')
|
2138
|
+
# affine A
|
2139
|
+
for j in range(1, n//2+1):
|
2140
|
+
data[('A', (n-j, j), 1)] = ClusterQuiver(['A', [n-j, j], 1]).mutation_class(data_type='dig6')
|
2141
|
+
# finite B
|
2142
|
+
if n > 1:
|
2143
|
+
data[('B', n)] = ClusterQuiver(['B', n]).mutation_class(data_type='dig6')
|
2144
|
+
# affine B
|
2145
|
+
if n > 2:
|
2146
|
+
data[('BB', n-1, 1)] = ClusterQuiver(['BB', n-1, 1]).mutation_class(data_type='dig6')
|
2147
|
+
# finite C
|
2148
|
+
if n > 2:
|
2149
|
+
data[('C', n)] = ClusterQuiver(['C', n]).mutation_class(data_type='dig6')
|
2150
|
+
# affine C
|
2151
|
+
if n > 1:
|
2152
|
+
data[('BC', n-1, 1)] = ClusterQuiver(['BC', n-1, 1]).mutation_class(data_type='dig6')
|
2153
|
+
# affine CC
|
2154
|
+
if n > 2:
|
2155
|
+
data[('CC', n-1, 1)] = ClusterQuiver(['CC', n-1, 1]).mutation_class(data_type='dig6')
|
2156
|
+
# affine BD
|
2157
|
+
if n > 3:
|
2158
|
+
data[('BD', n-1, 1)] = ClusterQuiver(['BD', n-1, 1]).mutation_class(data_type='dig6')
|
2159
|
+
# affine CD
|
2160
|
+
if n > 3:
|
2161
|
+
data[('CD', n-1, 1)] = ClusterQuiver(['CD', n-1, 1]).mutation_class(data_type='dig6')
|
2162
|
+
# finite D
|
2163
|
+
if n > 3:
|
2164
|
+
data[('D', n)] = ClusterQuiver(['D', n]).mutation_class(data_type='dig6')
|
2165
|
+
# affine D
|
2166
|
+
if n > 4:
|
2167
|
+
data[('D', n-1, 1)] = ClusterQuiver(['D', n-1, 1]).mutation_class(data_type='dig6')
|
2168
|
+
|
2169
|
+
return data
|
2170
|
+
|
2171
|
+
|
2172
|
+
def _construct_exceptional_mutation_classes(n) -> dict[tuple, list | set]:
|
2173
|
+
r"""
|
2174
|
+
Return a dict with keys being tuples representing exceptional
|
2175
|
+
QuiverMutationTypes of the given rank, and with values being lists
|
2176
|
+
or sets containing all mutation equivalent quivers as dig6 data.
|
2177
|
+
|
2178
|
+
EXAMPLES::
|
2179
|
+
|
2180
|
+
sage: from sage.combinat.cluster_algebra_quiver.quiver_mutation_type import _construct_exceptional_mutation_classes
|
2181
|
+
sage: rank_3_exceptional = _construct_exceptional_mutation_classes(3) # long time
|
2182
|
+
sage: for mut_class in sorted(rank_3_exceptional.keys(), key=str): # long time
|
2183
|
+
....: print("{} {}".format(mut_class, rank_3_exceptional[mut_class]))
|
2184
|
+
('G', 2, -1) [('BH?', (((1, 2), (1, -3)),)),
|
2185
|
+
('BGO', (((2, 1), (3, -1)),)), ('BW?', (((0, 1), (3, -1)),)),
|
2186
|
+
('BP?', (((0, 1), (1, -3)),)),
|
2187
|
+
('BP_', (((0, 1), (1, -3)), ((2, 0), (3, -1)))),
|
2188
|
+
('BP_', (((0, 1), (3, -1)), ((1, 2), (1, -3)), ((2, 0), (2, -2))))]
|
2189
|
+
('G', 2, 1) [('BH?', (((1, 2), (3, -1)),)),
|
2190
|
+
('BGO', (((2, 1), (1, -3)),)), ('BW?', (((0, 1), (1, -3)),)),
|
2191
|
+
('BP?', (((0, 1), (3, -1)),)),
|
2192
|
+
('BKO', (((1, 0), (3, -1)), ((2, 1), (1, -3)))),
|
2193
|
+
('BP_', (((0, 1), (2, -2)), ((1, 2), (1, -3)), ((2, 0), (3, -1))))]
|
2194
|
+
"""
|
2195
|
+
from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver
|
2196
|
+
data: dict[tuple, list | set] = {}
|
2197
|
+
# finite E
|
2198
|
+
if n in [6, 7, 8]:
|
2199
|
+
data[('E', n)] = ClusterQuiver(['E', n]).mutation_class(data_type='dig6')
|
2200
|
+
# affine E
|
2201
|
+
if n in [7, 8, 9]:
|
2202
|
+
data[('E', n - 1, 1)] = ClusterQuiver(['E', n - 1, 1]).mutation_class(data_type='dig6')
|
2203
|
+
# elliptic E
|
2204
|
+
if n in [8, 9, 10]:
|
2205
|
+
data[('E', n - 2, (1, 1))] = ClusterQuiver(['E', n - 2, [1, 1]]).mutation_class(data_type='dig6')
|
2206
|
+
# finite F
|
2207
|
+
if n == 4:
|
2208
|
+
data[('F', 4)] = ClusterQuiver(['F', 4]).mutation_class(data_type='dig6')
|
2209
|
+
# affine F
|
2210
|
+
if n == 5:
|
2211
|
+
data[('F', 4, 1)] = ClusterQuiver(['F', 4, 1]).mutation_class(data_type='dig6')
|
2212
|
+
data[('F', 4, -1)] = ClusterQuiver(['F', 4, -1]).mutation_class(data_type='dig6')
|
2213
|
+
# finite G
|
2214
|
+
if n == 2:
|
2215
|
+
data[('G', 2)] = ClusterQuiver(['G', 2]).mutation_class(data_type='dig6')
|
2216
|
+
# affine G
|
2217
|
+
if n == 3:
|
2218
|
+
data[('G', 2, 1)] = ClusterQuiver(['G', 2, 1]).mutation_class(data_type='dig6')
|
2219
|
+
data[('G', 2, -1)] = ClusterQuiver(['G', 2, -1]).mutation_class(data_type='dig6')
|
2220
|
+
# elliptic G
|
2221
|
+
if n == 4:
|
2222
|
+
data[('G', 2, (1, 3))] = ClusterQuiver(['G', 2, (1, 3)]).mutation_class(data_type='dig6')
|
2223
|
+
data[('G', 2, (1, 1))] = ClusterQuiver(['G', 2, (1, 1)]).mutation_class(data_type='dig6')
|
2224
|
+
data[('G', 2, (3, 3))] = ClusterQuiver(['G', 2, (3, 3)]).mutation_class(data_type='dig6')
|
2225
|
+
# X
|
2226
|
+
if n in [6, 7]:
|
2227
|
+
data[('X', n)] = ClusterQuiver(['X', n]).mutation_class(data_type='dig6')
|
2228
|
+
# elliptic F
|
2229
|
+
if n == 6:
|
2230
|
+
data[('F', 4, (1, 2))] = ClusterQuiver(['F', 4, (1, 2)]).mutation_class(data_type='dig6')
|
2231
|
+
data[('F', 4, (1, 1))] = ClusterQuiver(['F', 4, (1, 1)]).mutation_class(data_type='dig6')
|
2232
|
+
data[('F', 4, (2, 2))] = ClusterQuiver(['F', 4, (2, 2)]).mutation_class(data_type='dig6')
|
2233
|
+
|
2234
|
+
return data
|
2235
|
+
|
2236
|
+
|
2237
|
+
def _save_data_dig6(n, types='ClassicalExceptional', verbose=False):
|
2238
|
+
"""
|
2239
|
+
Save all exceptional mutation classes as dig6 data into the file ``exc_classes_n.dig6`` in the folder ``DOT_SAGE``.
|
2240
|
+
|
2241
|
+
TESTS::
|
2242
|
+
|
2243
|
+
sage: # needs sage.modules
|
2244
|
+
sage: from sage.combinat.cluster_algebra_quiver.quiver_mutation_type import save_quiver_data
|
2245
|
+
sage: save_quiver_data(2) # indirect doctest
|
2246
|
+
<BLANKLINE>
|
2247
|
+
The following types are saved to file ... and will now be used to determine quiver mutation types:
|
2248
|
+
[('A', 1)]
|
2249
|
+
<BLANKLINE>
|
2250
|
+
The following types are saved to file ... and will now be used to determine quiver mutation types:
|
2251
|
+
[('A', (1, 1), 1), ('A', 2), ('B', 2), ('BC', 1, 1), ('G', 2)]
|
2252
|
+
sage: save_quiver_data(2, up_to=False) # indirect doctest
|
2253
|
+
<BLANKLINE>
|
2254
|
+
The following types are saved to file ... and will now be used to determine quiver mutation types:
|
2255
|
+
[('A', (1, 1), 1), ('A', 2), ('B', 2), ('BC', 1, 1), ('G', 2)]
|
2256
|
+
sage: save_quiver_data(2, up_to=False, types='Classical') # indirect doctest
|
2257
|
+
<BLANKLINE>
|
2258
|
+
The following types are saved to file ... and will now be used to determine quiver mutation types:
|
2259
|
+
[('A', (1, 1), 1), ('A', 2), ('B', 2), ('BC', 1, 1)]
|
2260
|
+
sage: save_quiver_data(2, up_to=False, types='Exceptional') # indirect doctest
|
2261
|
+
<BLANKLINE>
|
2262
|
+
The following types are saved to file ... and will now be used to determine quiver mutation types:
|
2263
|
+
[('G', 2)]
|
2264
|
+
sage: save_quiver_data(2, up_to=False, verbose=False) # indirect doctest
|
2265
|
+
"""
|
2266
|
+
data = {}
|
2267
|
+
possible_types = ['Classical', 'ClassicalExceptional', 'Exceptional']
|
2268
|
+
if types not in possible_types:
|
2269
|
+
raise ValueError('The third input must be either ClassicalExceptional'
|
2270
|
+
' (default), Classical, or Exceptional.')
|
2271
|
+
|
2272
|
+
if types in possible_types[:2]:
|
2273
|
+
data.update(_construct_classical_mutation_classes(n))
|
2274
|
+
if types in possible_types[1:]:
|
2275
|
+
data.update(_construct_exceptional_mutation_classes(n))
|
2276
|
+
|
2277
|
+
from sage.env import DOT_SAGE
|
2278
|
+
types_path = Path(DOT_SAGE) / 'cluster_algebra_quiver'
|
2279
|
+
types_path.mkdir(exist_ok=True)
|
2280
|
+
types_file = types_path / f'mutation_classes_{n}.dig6'
|
2281
|
+
from sage.misc.temporary_file import atomic_write
|
2282
|
+
with atomic_write(types_file, binary=True) as f:
|
2283
|
+
pickle.dump(data, f)
|
2284
|
+
if verbose:
|
2285
|
+
keys = sorted(data, key=str)
|
2286
|
+
print("\nThe following types are saved to file", types_file, "and will now be used to determine quiver mutation types:")
|
2287
|
+
print(keys)
|
2288
|
+
|
2289
|
+
|
2290
|
+
def save_quiver_data(n, up_to=True, types='ClassicalExceptional', verbose=True):
|
2291
|
+
r"""
|
2292
|
+
Save mutation classes of certain quivers of ranks up to and equal
|
2293
|
+
to `n` or equal to `n` to
|
2294
|
+
``DOT_SAGE/cluster_algebra_quiver/mutation_classes_n.dig6``.
|
2295
|
+
|
2296
|
+
This data will then be used to determine quiver mutation types.
|
2297
|
+
|
2298
|
+
INPUT:
|
2299
|
+
|
2300
|
+
- ``n`` -- the rank (or the upper limit on the rank) of the mutation
|
2301
|
+
classes that are being saved
|
2302
|
+
|
2303
|
+
- ``up_to`` -- (default: ``True``) if ``True``, saves data for
|
2304
|
+
ranks smaller than or equal to `n`; if ``False``, saves data
|
2305
|
+
for rank exactly `n`
|
2306
|
+
|
2307
|
+
- ``types`` -- (default: ``'ClassicalExceptional'``) if all, saves data
|
2308
|
+
for both exceptional mutation-finite quivers and for classical
|
2309
|
+
quiver; the input 'Exceptional' or 'Classical' is also allowed
|
2310
|
+
to save only part of this data
|
2311
|
+
|
2312
|
+
TESTS::
|
2313
|
+
|
2314
|
+
sage: # needs sage.modules
|
2315
|
+
sage: from sage.combinat.cluster_algebra_quiver.quiver_mutation_type import save_quiver_data
|
2316
|
+
sage: save_quiver_data(2)
|
2317
|
+
<BLANKLINE>
|
2318
|
+
The following types are saved to file ... and will now be used to determine quiver mutation types:
|
2319
|
+
[('A', 1)]
|
2320
|
+
<BLANKLINE>
|
2321
|
+
The following types are saved to file ... and will now be used to determine quiver mutation types:
|
2322
|
+
[('A', (1, 1), 1), ('A', 2), ('B', 2), ('BC', 1, 1), ('G', 2)]
|
2323
|
+
sage: save_quiver_data(2,up_to=False)
|
2324
|
+
<BLANKLINE>
|
2325
|
+
The following types are saved to file ... and will now be used to determine quiver mutation types:
|
2326
|
+
[('A', (1, 1), 1), ('A', 2), ('B', 2), ('BC', 1, 1), ('G', 2)]
|
2327
|
+
sage: save_quiver_data(2,up_to=False, types='Classical')
|
2328
|
+
<BLANKLINE>
|
2329
|
+
The following types are saved to file ... and will now be used to determine quiver mutation types:
|
2330
|
+
[('A', (1, 1), 1), ('A', 2), ('B', 2), ('BC', 1, 1)]
|
2331
|
+
sage: save_quiver_data(2,up_to=False, types='Exceptional')
|
2332
|
+
<BLANKLINE>
|
2333
|
+
The following types are saved to file ... and will now be used to determine quiver mutation types:
|
2334
|
+
[('G', 2)]
|
2335
|
+
sage: save_quiver_data(2,up_to=False, verbose=False)
|
2336
|
+
"""
|
2337
|
+
from sage.combinat.cluster_algebra_quiver.mutation_type import load_data
|
2338
|
+
if up_to is True:
|
2339
|
+
ranks = range(1, n + 1)
|
2340
|
+
elif up_to is False:
|
2341
|
+
ranks = [n]
|
2342
|
+
for i in ranks:
|
2343
|
+
_save_data_dig6(i, types=types, verbose=verbose)
|
2344
|
+
# we finally clear the load_data
|
2345
|
+
load_data.clear_cache()
|
2346
|
+
|
2347
|
+
|
2348
|
+
def _bipartite_graph_to_digraph(g) -> DiGraph:
|
2349
|
+
"""
|
2350
|
+
Return a digraph obtained from a bipartite graph ``g`` by choosing one
|
2351
|
+
set of the bipartition to be the set of sinks and the other to be the
|
2352
|
+
set of sources.
|
2353
|
+
|
2354
|
+
EXAMPLES::
|
2355
|
+
|
2356
|
+
sage: from sage.combinat.cluster_algebra_quiver.quiver_mutation_type import _bipartite_graph_to_digraph
|
2357
|
+
sage: G = Graph([(1, 2)])
|
2358
|
+
sage: _bipartite_graph_to_digraph(G)
|
2359
|
+
Digraph on 2 vertices
|
2360
|
+
"""
|
2361
|
+
sources = g.bipartite_sets()[0]
|
2362
|
+
dg = DiGraph()
|
2363
|
+
dg.add_vertices(g)
|
2364
|
+
for a, b, c in g.edge_iterator():
|
2365
|
+
if a in sources:
|
2366
|
+
dg.add_edge(a, b, c)
|
2367
|
+
else:
|
2368
|
+
dg.add_edge(b, a, c)
|
2369
|
+
return dg
|
2370
|
+
|
2371
|
+
|
2372
|
+
def _is_mutation_type(data) -> bool:
|
2373
|
+
"""
|
2374
|
+
Return ``True`` if ``data`` is a QuiverMutationType.
|
2375
|
+
|
2376
|
+
EXAMPLES::
|
2377
|
+
|
2378
|
+
sage: from sage.combinat.cluster_algebra_quiver.quiver_mutation_type import _is_mutation_type
|
2379
|
+
sage: _is_mutation_type ( [ 'A', 2 ] )
|
2380
|
+
True
|
2381
|
+
sage: _is_mutation_type ( [ 'P', 1 ] )
|
2382
|
+
False
|
2383
|
+
"""
|
2384
|
+
try:
|
2385
|
+
QuiverMutationType(data)
|
2386
|
+
return True
|
2387
|
+
except Exception:
|
2388
|
+
return False
|
2389
|
+
|
2390
|
+
|
2391
|
+
def _mutation_type_error(data):
|
2392
|
+
r"""
|
2393
|
+
Output an error message because data which is not a valid quiver mutation
|
2394
|
+
type has been passed to QuiverMutationType.
|
2395
|
+
|
2396
|
+
EXAMPLES::
|
2397
|
+
|
2398
|
+
sage: QuiverMutationType( 'Christian', 'Stump' ) # indirect doctest
|
2399
|
+
Traceback (most recent call last):
|
2400
|
+
...
|
2401
|
+
ValueError: ['Christian', 'Stump'] is not a valid quiver mutation type
|
2402
|
+
Finite types have the form [ '?', n ] for type ? and rank n
|
2403
|
+
Affine type A has the form [ 'A', [ i, j ], 1 ] for rank i+j
|
2404
|
+
Affine type ? has the form [ '?', k, \pm 1 ] for rank k+1
|
2405
|
+
Elliptic type ? has the form [ '?', k, [i, j] ] (1 <= i,j <= 3) for rank k+2
|
2406
|
+
For correct syntax in other types, please consult the documentation.
|
2407
|
+
"""
|
2408
|
+
if data[2] is None:
|
2409
|
+
del data[2]
|
2410
|
+
return_str = str(data) + ' is not a valid quiver mutation type'
|
2411
|
+
return_str += '\n Finite types have the form [ \'?\', n ] for type ? and rank n'
|
2412
|
+
return_str += '\n Affine type A has the form [ \'A\', [ i, j ], 1 ] for rank i+j'
|
2413
|
+
return_str += '\n Affine type ? has the form [ \'?\', k, \\pm 1 ] for rank k+1'
|
2414
|
+
return_str += '\n Elliptic type ? has the form [ \'?\', k, [i, j] ] (1 <= i,j <= 3) for rank k+2'
|
2415
|
+
return_str += '\n For correct syntax in other types, please consult the documentation.'
|
2416
|
+
|
2417
|
+
raise ValueError(return_str)
|
2418
|
+
|
2419
|
+
|
2420
|
+
def _edge_list_to_matrix(edges, nlist, mlist) -> matrix:
|
2421
|
+
r"""
|
2422
|
+
Return the matrix obtained from the edge list of a quiver.
|
2423
|
+
|
2424
|
+
INPUT:
|
2425
|
+
|
2426
|
+
- ``edges`` -- the list of edges
|
2427
|
+
- ``nlist`` -- the list of mutable vertices of the quiver
|
2428
|
+
- ``mlist`` -- the list of frozen vertices of the quiver
|
2429
|
+
|
2430
|
+
OUTPUT:
|
2431
|
+
|
2432
|
+
An `(n+m) \times n` matrix corresponding to the edge-list.
|
2433
|
+
|
2434
|
+
EXAMPLES::
|
2435
|
+
|
2436
|
+
sage: from sage.combinat.cluster_algebra_quiver.quiver_mutation_type import _edge_list_to_matrix
|
2437
|
+
sage: G = QuiverMutationType(['A', 2])._digraph
|
2438
|
+
sage: _edge_list_to_matrix(G.edges(sort=True), [0, 1], []) # needs sage.modules
|
2439
|
+
[ 0 1]
|
2440
|
+
[-1 0]
|
2441
|
+
|
2442
|
+
sage: G2 = DiGraph([('a', 'b', 1)])
|
2443
|
+
sage: _edge_list_to_matrix(G2.edges(sort=True), ['a', 'b'], []) # needs sage.modules
|
2444
|
+
[ 0 1]
|
2445
|
+
[-1 0]
|
2446
|
+
|
2447
|
+
sage: G3 = DiGraph([('a', 'b', 1), ('b', 'c', 1)])
|
2448
|
+
sage: _edge_list_to_matrix(G3.edges(sort=True), ['a', 'b'], ['c']) # needs sage.modules
|
2449
|
+
[ 0 1]
|
2450
|
+
[-1 0]
|
2451
|
+
[ 0 -1]
|
2452
|
+
"""
|
2453
|
+
n = len(nlist)
|
2454
|
+
nmlist = nlist + mlist
|
2455
|
+
nm = len(nmlist)
|
2456
|
+
M = matrix(ZZ, nm, n, sparse=True)
|
2457
|
+
for v1, v2, label in edges:
|
2458
|
+
if label is None:
|
2459
|
+
a, b = 1, -1
|
2460
|
+
elif label in ZZ:
|
2461
|
+
a, b = label, -label
|
2462
|
+
else:
|
2463
|
+
a, b = label
|
2464
|
+
if v1 in nlist:
|
2465
|
+
M[nmlist.index(v2), nmlist.index(v1)] = b
|
2466
|
+
if v2 in nlist:
|
2467
|
+
M[nmlist.index(v1), nmlist.index(v2)] = a
|
2468
|
+
return M
|