Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/combinat/cyclic_sieving_phenomenon.py
8817 views
1
r"""
2
Cyclic sieving phenomenon
3
4
Implementation of the Cyclic Sieving Phenomenon as described in
5
Reiner, Stanton, White - The cyclic sieving phenomenon, Journal of Combinatorial Theory A 108 (2004)
6
7
We define the CyclicSievingPolynomial of a finite set S together with cyclic action cyc_act (of order n) to be the unique
8
polynomial P(q) of order < n such that the triple ( S, cyc_act, P(q) ) exhibits the cyclic sieving phenomenon.
9
10
AUTHORS:
11
12
- Christian Stump
13
"""
14
#*****************************************************************************
15
# Copyright (C) 2010 Christian Stump [email protected]
16
#
17
# Distributed under the terms of the GNU General Public License (GPL)
18
# http://www.gnu.org/licenses/
19
#*****************************************************************************
20
21
from copy import copy
22
from sage.rings.all import ZZ, QQ
23
from sage.rings.arith import lcm
24
25
def CyclicSievingPolynomial( L, cyc_act=None, order=None, get_order=False):
26
"""
27
Returns the unique polynomial p of degree smaller than order such that the triple
28
( L, cyc_act, p ) exhibits the CSP. If ``cyc_act`` is None, ``L`` is expected to contain the orbit lengths.
29
30
INPUT:
31
32
- L -- if cyc_act is None: list of orbit sizes, otherwise list of objects
33
34
- cyc_act -- (default:None) function taking an element of L and returning an element of L (must define a bijection on L)
35
36
- order -- (default:None) if set to an integer, this cyclic order of cyc_act is used (must be an integer multiple of the order of cyc_act)
37
otherwise, the order of cyc_action is used
38
39
- get_order -- (default:False) if True, a tuple [p,n] is returned where p as above, and n is the order
40
41
EXAMPLES::
42
43
sage: from sage.combinat.cyclic_sieving_phenomenon import CyclicSievingPolynomial
44
sage: S42 = [ Set(S) for S in subsets([1,2,3,4]) if len(S) == 2 ]; S42
45
[{1, 2}, {1, 3}, {2, 3}, {1, 4}, {2, 4}, {3, 4}]
46
sage: cyc_act = lambda S: Set( i.mod(4)+1 for i in S)
47
sage: cyc_act([1,3])
48
{2, 4}
49
sage: cyc_act([1,4])
50
{1, 2}
51
sage: CyclicSievingPolynomial( S42, cyc_act )
52
q^3 + 2*q^2 + q + 2
53
sage: CyclicSievingPolynomial( S42, cyc_act, get_order=True )
54
[q^3 + 2*q^2 + q + 2, 4]
55
sage: CyclicSievingPolynomial( S42, cyc_act, order=8 )
56
q^6 + 2*q^4 + q^2 + 2
57
sage: CyclicSievingPolynomial([4,2])
58
q^3 + 2*q^2 + q + 2
59
60
TESTS:
61
62
We check that :trac:`13997` is handled::
63
64
sage: CyclicSievingPolynomial( S42, cyc_act, order=8, get_order=True )
65
[q^6 + 2*q^4 + q^2 + 2, 8]
66
"""
67
68
if cyc_act:
69
orbits = orbit_decomposition( L, cyc_act )
70
else:
71
orbits = [ range(k) for k in L ]
72
73
R = QQ['q']
74
q = R.gen()
75
p = R(0)
76
77
orbit_sizes = {}
78
for orbit in orbits:
79
l = len( orbit )
80
if l in orbit_sizes:
81
orbit_sizes[ l ] += 1
82
else:
83
orbit_sizes[ l ] = 1
84
85
keys = orbit_sizes.keys()
86
87
n = lcm( keys )
88
89
if order:
90
if order.mod(n) != 0:
91
raise ValueError("The given order is not valid as it is not a multiple of the order of the given cyclic action")
92
else:
93
order = n
94
95
for i in range(n):
96
if i == 0:
97
j = sum( orbit_sizes[ l ] for l in keys )
98
else:
99
j = sum( orbit_sizes[ l ] for l in keys if ZZ(i).mod(n/l) == 0 )
100
p += j*q**i
101
102
p = p(q**ZZ(order/n))
103
104
if get_order:
105
return [p,order]
106
else:
107
return p
108
109
def CyclicSievingCheck( L, cyc_act, f, order=None ):
110
"""
111
Returns True if the triple ( L, cyc_act, f ) exhibits the cyclic sieving phenomenon. If cyc_act is None, L is expected to obtain the orbit lengths.
112
113
INPUT:
114
115
- L -- if cyc_act is None: list of orbit sizes, otherwise list of objects
116
117
- cyc_act -- (default:None) function taking an element of L and returning an element of L (must define a bijection on L)
118
119
- order -- (default:None) if set to an integer, this cyclic order of cyc_act is used (must be an integer multiple of the order of cyc_act)
120
otherwise, the order of cyc_action is used
121
122
EXAMPLES::
123
124
sage: from sage.combinat.cyclic_sieving_phenomenon import *
125
sage: from sage.combinat.q_analogues import q_binomial
126
sage: S42 = [ Set(S) for S in subsets([1,2,3,4]) if len(S) == 2 ]; S42
127
[{1, 2}, {1, 3}, {2, 3}, {1, 4}, {2, 4}, {3, 4}]
128
sage: cyc_act = lambda S: Set( i.mod(4)+1 for i in S)
129
sage: cyc_act([1,3])
130
{2, 4}
131
sage: cyc_act([1,4])
132
{1, 2}
133
sage: p = q_binomial(4,2); p
134
q^4 + q^3 + 2*q^2 + q + 1
135
sage: CyclicSievingPolynomial( S42, cyc_act )
136
q^3 + 2*q^2 + q + 2
137
sage: CyclicSievingCheck( S42, cyc_act, p )
138
True
139
"""
140
p1,n = CyclicSievingPolynomial( L, cyc_act=cyc_act, order=order, get_order=True )
141
R = p1.parent()
142
q = R.gen()
143
p2 = R(f).mod(q**n-1)
144
return p1 == p2
145
146
def orbit_decomposition( L, cyc_act ):
147
"""
148
Returns the orbit decomposition of L by the action of cyc_act
149
150
INPUT:
151
152
- L -- list
153
154
- cyc_act -- function taking an element of L and returning an element of L (must define a bijection on L)
155
156
OUTPUT:
157
158
- a list of lists, the orbits under the cyc_act acting on L
159
160
EXAMPLES::
161
162
sage: from sage.combinat.cyclic_sieving_phenomenon import *
163
sage: S42 = [ Set(S) for S in subsets([1,2,3,4]) if len(S) == 2 ]; S42
164
[{1, 2}, {1, 3}, {2, 3}, {1, 4}, {2, 4}, {3, 4}]
165
sage: cyc_act = lambda S: Set( i.mod(4)+1 for i in S)
166
sage: cyc_act([1,3])
167
{2, 4}
168
sage: cyc_act([1,4])
169
{1, 2}
170
sage: orbit_decomposition( S42, cyc_act )
171
[[{2, 4}, {1, 3}], [{1, 2}, {2, 3}, {3, 4}, {1, 4}]]
172
"""
173
orbits = []
174
L_prime = set(L)
175
while L_prime != set():
176
obj = L_prime.pop()
177
orbit = [obj]
178
obj = cyc_act( obj )
179
while obj in L_prime:
180
orbit.append( obj )
181
L_prime.remove( obj )
182
obj = cyc_act( obj )
183
orbits.append( orbit )
184
return orbits
185
186