I collected a bit of code relevant for the paper On Hecke and asymptotic categories for complex reflection groups https://arxiv.org/abs/2409.01005 on this page.
We have Python code below that can be run online, e.g. in Colab. The code is based on a Mathematica file that can be downloaded on this page. We also have a .sage file or .m file, respectively, that can be downloaded from this site (or copied from below) and you can run it with SageMath or Magma. All files will run in the respective online calculators, see either here SageMath or Magma.
An Erratum for the paper On Hecke and asymptotic categories for complex reflection groups can be found at the bottom of the page.
If you find any errors in the paper On Hecke and asymptotic categories for complex reflection groups please email me:
Same goes for any errors related to this page.
The Chebyshev polynomial of the second kind
Their roots, the numbers
The crucial observation is that this recursion matches the fusion (=tensor product) rule of
The following code computes the higher Chebyshev polynomials for
from functools import lru_cache
from sympy import symbols, expand
X1, X2, X3 = symbols('X1 X2 X3')
# Memoization decorator to cache results
@lru_cache(maxsize=None)
def a(m1, m2, m3):
# Base cases
if (m1, m2, m3) == (0, 0, 0):
return 1
if (m1, m2, m3) == (1, 0, 0):
return X1
if (m1, m2, m3) == (0, 1, 0):
return X2
if (m1, m2, m3) == (0, 0, 1):
return X3
# If any index is negative, return 0
if m1 < 0 or m2 < 0 or m3 < 0:
return 0
# Find maximum of the indices
max_val = max(m1, m2, m3)
# Case 1: m1 is the maximum
if m1 == max_val:
return (X1 * a(m1 - 1, m2, m3)
- a(m1 - 2, m2 + 1, m3)
- a(m1 - 1, m2 - 1, m3 + 1)
- a(m1 - 1, m2, m3 - 1))
# Case 2: m3 is the maximum
elif m3 == max_val:
return (X3 * a(m1, m2, m3 - 1)
- a(m1, m2 + 1, m3 - 2)
- a(m1 + 1, m2 - 1, m3 - 1)
- a(m1 - 1, m2, m3 - 1))
# Case 3: m2 is the maximum
elif m2 == max_val:
return (X2 * a(m1, m2 - 1, m3)
- a(m1 + 1, m2 - 2, m3 + 1)
- a(m1 - 1, m2 - 1, m3 + 1)
- a(m1 + 1, m2 - 1, m3 - 1)
- a(m1 - 1, m2, m3 - 1)
- a(m1, m2 - 2, m3))
a(1, 1, 1)
The result is a polynomial in three variables.
All roots of higher Chebyshev polynomials have their first coordinate in the interior of the N-cusped hypocycloid of parametric equation
Recall that these are plane curves generated by following a point on a circle of radius 1 that rolls within a circle of radius N. Here are the pictures:
To be completely explicit, let
We have the following plot of the first coordinates:
The following SageMath code will create tex code to plot these pictures.
#half sum of positive roots (sage uses the realization of the root system of type A_(N-1) in R^N, and we work in the usual N-1 dimensional subspace with sum of coordinates 0)
def rho(N):
return vector([(N+1-2*i)/2 for i in [1..N]])
#fundamental weights
def fund(N,i):
return vector([1-i/N for j in [1..i]]+[-i/N for j in [i+1..N]])
#computes the set X^+(e)
def param(N,e):
return list(filter(lambda t: sum(t) <=e,tuples([0..e],N-1)))
#computes the set V'_e
def Vpar(N,t):
return [N*fund(N,i)*(sum([t[j-1]*fund(N,j) for j in [1..N-1]])+rho(N)) for i in [1..N-1]]
#computes the j-th Koornwinder Z-function, here q is already the root of unity needed for the Koornwinder variety V_e
def Zfun(N,e,j,gamma):
q=exp(2*I*pi/(N*(e+N)))
gammar=[gamma[0]]+[gamma[i]-gamma[i-1] for i in [1..N-2]] + [-gamma[N-2]]
z=sum([q^(sum([gammar[i] for i in t])) for t in list(Combinations([0..N-1],j))])
return z.real().simplify()+I*z.imag().simplify()
#list all points in the Koornwinder variety V_e
def Koornwinder(N,e):
return [[Zfun(N,e,j,gamma) for j in [1..N-1]] for gamma in [Vpar(N,t) for t in param(N,e)]]
#draw the nice pictures (there is a truncation up to 3 decimal places for the points)
from collections import Counter
def KoornwinderTex(N,e):
precision=3
koorn=Koornwinder(N,e)
tex="\\documentclass[crop,tikz]{standalone}\n\n\\begin{document}\n"
if N%2 == 0:
maxi=N/2
else:
maxi=(N-1)/2
for i in [1..maxi]:
tex+="\\begin{tikzpicture}\n"
tex+="\\def\\a{1} \\def\\b{"+str(N/gcd(N,i))+"} \\def\\scale{"+str(binomial(N,i)/(N/gcd(N,i)))+"}\n"
tex+="\\draw[cyan!30,very thin] ({-\\b*\\scale},{-\\b*\\scale}) grid ({\\b*\\scale},{\\b*\\scale});\n"
tex+="\\draw[->] ({-\\b*\\scale},0) -- ({\\b*\\scale},0);\n"
tex+="\\draw[->] (0,{-\\b*\\scale}) -- (0,{\\b*\\scale});\n"
tex+="\\draw (0,0) circle ({\\b*\\scale});\n"
tex+="\\draw[line width=2pt,red] plot[samples=100,domain=0:\\a*360,smooth,variable=\\t] ({\\scale*((\\b-\\a)*cos(\\t)+\\a*cos((\\b-\\a)*\\t/\\a)},{\\scale*((\\b-\\a)*sin(\\t)-\\a*sin((\\b-\\a)*\\t/\\a)});\n\n"
k=Counter([round(float(t[i-1].real()),precision)+I*round(float(t[i-1].imag()),precision) for t in koorn]) #counts the multiplicity of the points, precision of 3 decimal places
for x in k:
tex+="\\draw[blue,fill=blue] ("+str(x.real())+","+str(x.imag())+") circle (4*"+str(round(0.2*k[x],1))+"pt);\n"
tex+="\\end{tikzpicture}\n\n"
tex+="\\end{document}"
return tex
#Example: print LaTeX code for N=4 and e=6
print(KoornwinderTex(4,6))
The notation is as in the paper On Hecke and asymptotic categories for complex reflection groups.
We additionally need to check that certain graphs have eigenvalues being (multi)subsets of the roots of the Chebyshev polynomials (so they are in the Koornwinder variety). The corresponding calculations can be found in the folders on this side, ordered by the graph names.
The following MAGMA code check whether the joint spectrum of three commuting matrices is in the Koornwinder variety.
k<X1,X2,X3>:=PolynomialRing(Rationals(),3);
//This function computes the Chebyshev polynomial for N=4
function cheb(m1,m2,m3)
if [m1,m2,m3] eq [0,0,0] then
return 1;
elif [m1,m2,m3] eq [1,0,0] then
return X1;
elif [m1,m2,m3] eq [0,1,0] then
return X2;
elif [m1,m2,m3] eq [0,0,1] then
return X3;
end if;
if m1 lt 0 or m2 lt 0 or m3 lt 0 then
return 0;
end if;
max_val:=Maximum({m1,m2,m3});
if max_val eq m1 then
return X1*cheb(m1-1,m2,m3)-cheb(m1-2,m2+1,m3)-cheb(m1-1,m2-1,m3+1)-cheb(m1-1,m2,m3-1);
elif max_val eq m3 then
return X3*cheb(m1,m2,m3-1)-cheb(m1,m2+1,m3-2)-cheb(m1+1,m2-1,m3-1)-cheb(m1-1,m2,m3-1);
elif max_val eq m2 then
return X2*cheb(m1,m2-1,m3)-cheb(m1+1,m2-2,m3+1)-cheb(m1-1,m2-1,m3+1)-cheb(m1+1,m2-1,m3-1)-cheb(m1-1,m2,m3-1)-cheb(m1,m2-2,m3);
end if;
end function;
//Computes all the triples of positive integers with total sum k
function tuples_level(k)
tuples := [];
for a in [0..k] do
for b in [0..k-a] do
c := k-a-b;
if c ge 0 then
Append(~tuples, [a, b, c]);
end if;
end for;
end for;
return tuples;
end function;
// Check whether a list of points in C^3 is in the Koornwinder variety
function check_Koornwinder(eigenvalues,e)
tup:=tuples_level(e+1);
poly:=[cheb(i[1],i[2],i[3]) : i in tup];
for P in poly do
for eigen in eigenvalues do
if Evaluate(P,eigen) ne 0 then
return false;
end if;
end for;
end for;
return true;
end function;
// Check whether the joint spectrum of the three matrices is in the Koornwinder variety
function check_matrices(M1,M2,M3,e)
D,V:=Diagonalization([M1,M2,M3]);
eigenvalues:=[[D[j][i][i] : j in [1..3]]: i in [1..NumberOfRows(M1)]];
return check_Koornwinder(eigenvalues,e);
end function;
In 2A3-c case, we check that the joint spectrum is in the Koornwinder variety using the code:
M1:=Matrix(CyclotomicField(28),12,12,[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0]);
M2:=Matrix(CyclotomicField(28),12,12,[0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0]);
M3:=Transpose(M1);
check_matrices(M1,M2,M3,3);
One can plot the graphs by copying the adjacency matrices into, for example, GraphOnline.
Empty so far.

