-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.magma
347 lines (277 loc) · 9.6 KB
/
main.magma
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
///////////////////////////////////////////////////////////////
//
// Magma code for computing the algebra A(g) for g a simple Lie algebra
//
// in support of a paper by Maurice Chayet & Skip Garibaldi
// https://arxiv.org/abs/2005.07618
//
//
// Expect to have defined:
// KC = string, the Killing-Cartan type of the Lie algebra g, e.g., "G2" or "D4"
// F = field of definition of Lie algebra g
// construction = 1 to do the general construction from section 4, 2 to do construction #2 from section 9
//
// After this, construct the algebra A(g)
//
//
// For an example use, see "example.magma";
//
/////////////////////////////////////////////////////////////////
//
// Most of this code was written in November 2017 and July 2019
//
/////////////////////////////////////////////////////////////////
load "generic-routines.magma"; // generic functions for any Magma program
load "randelt.magma"; // can make random elements of an algebra over Q, e.g.
load "dual-coxeter.magma"; // dual Coxeter number and other data
// check that KC, etc., meet some basic criteria
key := KC; // a common typo
if construction eq 2 then
assert KC in ["A2", "G2", "F4", "E6", "E7"]; // See Proposition 9.4
end if;
printf "g is a simple Lie algebra of type %o over the %o\n", key, F;
g := LieAlgebra(key, F : Isogeny := "SC");
R := RootDatum(g);
key_family := KC[1];
key_rank := Rank(R);
hv := hvee_function(key_family, key_rank);
hvee := hv; // common typo
// check the characteristic hypothesis from the paper
assert (Characteristic(F) eq 0) or (Characteristic(F) gt h_function(key_family, key_rank)+ 1);
function calc_exp_dim(R);
a := AdjointRepresentationDecomposition(R);
wt := Weights(a)[1];
two_hst := LieRepresentationDecomposition(R, 2*wt);
sp := SymmetricPower(a, 2);
return Integers()!(RepresentationDimension(sp) - RepresentationDimension(two_hst));
end function;
exp_dim := calc_exp_dim(R); // expected dimension of the constructed algebra A(g)
basis := Basis(g);
d := #basis;
// the basis for the adjoint representation, according ot Magma, is different from the basis for g
// so here we give the matrix according to g
function ad(X);
return Matrix([b*X : b in basis]);
end function;
stock_ad := AdjointRepresentation(g);
gram_matrix := Matrix(F, KillingMatrix(g));
gram_comatrix := gram_matrix^(-1);
cobasis := [gram_comatrix[i] : i in [1..d]];
// it takes two elements of g and gives a scalar
function K(x, y);
return (Matrix(F, x)*gram_matrix*Transpose(Matrix(y)))[1,1];
end function;
// --------- some asserts
X := randelt(g);
assert ad(X) eq Matrix(stock_ad(X));
for i in [1..#basis] do
assert basis[i]*X eq ad(X)[i];
end for;
Y := randelt(g);
assert Y eq &+[Y[i]*basis[i] : i in [1..#basis]];
if key in ["A1", "A2", "G2", "D4", "F4", "E6", "E7", "E8"] then
okubo_alpha := 5/(2*(d+2));
assert Trace(ad(X)^4) eq okubo_alpha * K(X,X)^2;
end if;
// ---------
// the Jordan product
function jordan(T1, T2);
return (1/2)*(Matrix(T1)*Matrix(T2) + Matrix(T2)*Matrix(T1));
end function;
assert 2*jordan(ad(X), ad(Y)) eq ad(X)*ad(Y) + ad(Y)*ad(X);
if construction eq 1 then
pi := ad;
d_pi := d;
mu_pi := 1;
// takes X, Y in g and returns P(X,Y) in End(g); note we act on the right
function oldP(X, Y);
return (1/2)*(gram_matrix*Transpose(Matrix(Y))*Matrix(X) + gram_matrix*Transpose(Matrix(X))*Matrix(Y));
end function;
function P(X,Y);
return (1/2)*Matrix([K(b,X)*Y + K(b,Y)*X : b in basis]);
end function;
assert oldP(X,Y) eq P(X,Y);
// take X, Y in g and returns S(X,Y) in End(g); note we act on the right
function S(X,Y);
return hvee*jordan(ad(X), ad(Y)) + P(X,Y);
end function;
elif construction eq 2 then
La := pi_array[key];
pi := HighestWeightRepresentation(g, La);
d_pi := IntegerRing()!Sqrt(Dimension(Codomain(pi)));
mu_pi := (hvee + 1)/(hvee+6);
// takes a weight as a vector/SeqEnum and returns a weight
// as a sum of roots in the root datum R
function vecToRoot(v);
return BasisChange(R, v : InBasis := "Weight", OutBasis := "Root");
end function;
La_as_root := vecToRoot(La);
// verify Okubo's lemma
nu := mu_pi * d_pi * (6 * mu_pi - 1) / (2 * d * (d+2));
assert Trace(Matrix(pi(X))^4) eq nu * K(X,X)^2;
// take X, Y in g and returns S(X,Y) in End(g); note we act on the right
function S(X,Y);
return 6*hvee*jordan(pi(X), pi(Y)) - K(X,Y)/2;
end function;
end if;
assert d * Trace(Matrix(pi(X))^2) eq mu_pi * d_pi * K(X, X);
assert &+[S(basis[i], g!cobasis[i]) : i in [1..#basis]] eq (hvee+1)*IdentityMatrix(F, d_pi);
function S2prod0(U, V, A, B); // U, V, A, B belong to g, return an element of End(g)
adAB := jordan(ad(A), ad(B));
adUV := jordan(ad(U), ad(V));
prod0 := S(U, V*adAB) + S(U*adAB, V)
+ S(A, B*adUV) + S(A*adUV, B);
prod1 := S(U*A, V*B) + S(U*B, V*A);
prod3 := S(K(U,A)*V,B) + S(K(U,B)*V,A)
+ S(K(V,A)*U,B) + S(K(V,B)*U,A);
return (hvee/2)*(prod0 + prod1) + (1/4)*prod3;
end function;
function S2prod(u, v, a, b); // u, v, a, b are indexes in to the basis of g, wrapper for S2prod0
return S2prod0(basis[u], basis[v], basis[a], basis[b]);
end function;
function gOnVpi(x, elt); // x in g, elt in End(V_pi)
act := Matrix(pi(x));
return elt*act - act*elt;
end function;
// check that S2prod0 is g-invariant
for i in [1..25] do
X := randelt(g);
Y := randelt(g);
U := randelt(g);
V := randelt(g);
x := randelt(g);
act := ad(x);
M := S2prod0(U*act, V, X, Y) + S2prod0(U, V*act, X, Y) + S2prod0(U, V, X*act, Y) + S2prod0(U, V, X, Y*act);
alt := S2prod0(U, V, X, Y);
assert M eq gOnVpi(x, alt);
end for;
if construction eq 1 then
str := "End(g)";
elif construction eq 2 then
str := "End(V_pi)";
end if;
section("Finding a basis for the image of S in " cat str);
// now we calculate the images
print "Calculating the images of basis elements under S";
elts := [ ];
checkpoint := Realtime();
for i in [1..d] do
for j in [i..d] do
new_elt := [* i, j, S(basis[i], basis[j]) *];
if not(IsZero(new_elt[3])) then // if you get the zero matrix, ignore it
Append(~elts, new_elt);
end if;
end for;
if i mod 10 eq 0 then
printf info_str cat "Did %o (%o%%) in %o\n", i, Round(i*100.0/d), print_time(Realtime()-checkpoint);
end if;
end for;
printf info_str cat "Done after %o\n", print_time(Realtime()-checkpoint);
print "\nSubselecting a basis for the image from this list";
indices := []; // pointers into elts
baselts := []; // actual basis vectors in End(g)
checkpoint := Realtime();
for i in [1..#elts] do
x := elts[i][3];
if IsIndependent(baselts cat [x]) then
Append(~baselts, x);
Append(~indices, i);
if (exp_dim le 25) or (i mod 5 eq 0) then
printf info_str cat "Basis has %o elts of %o, after %o\n", #indices, exp_dim, print_time(Realtime()-checkpoint);
end if;
end if;
end for;
assert #indices eq exp_dim;
printf info_str cat "Done after %o\n", print_time(Realtime()-checkpoint);
basmat := VerticalJoin([Vector(elt) : elt in baselts]);
assert Rank(basmat) eq Nrows(basmat);
function EndVpiToCoords(v);
return Solution(basmat, Vector(v));
end function;
// now we calculate the products
section("Calculating the products of elements of the basis");
// now we calculate the products
checkpoint := Realtime();
prods := [];
for i in [1..exp_dim] do
if (exp_dim le 25) or (i mod 5 eq 0) then
printf info_str cat "Calculating products for row %o of %o, after %o\n", i, exp_dim, print_time(Realtime()-checkpoint);
est := (Realtime()-checkpoint)/i*(exp_dim-i);
if (i mod 25 eq 0) then
printf info_str cat info_str cat "estimated %o remaining\n", print_time(est);
end if;
end if;
prod := []; // this is a row
ind_i := elts[indices[i]];
for j in [1..(i-1)] do
Append(~prod, prods[j][i]);
end for;
for j in [i..exp_dim] do
ind_j := elts[indices[j]];
Append(~prod, EndVpiToCoords(S2prod(ind_i[1], ind_i[2], ind_j[1], ind_j[2])));
end for;
Append(~prods, prod);
end for;
printf info_str cat "Done after %o\n", print_time(Realtime()-checkpoint);
// construct the "structure constant algebra"
section("Constructing the algebra A as a structure constant algebra");
A := Algebra<F, exp_dim | prods>;
assert IsCommutative(A);
// move elements from End(V_pi) into A
function EndVpiToA(x);
return A!Eltseq(EndVpiToCoords(x));
end function;
// move elements from A to End(V_pi)
function AToEndVpi(a);
return &+[a[i]*baselts[i] : i in [1..exp_dim]];
end function;
function gOnA(x, a);
return EndVpiToA(gOnVpi(x, AToEndVpi(a)));
end function;
// construct the identity element
print "Identifying identity element e";
e := EndVpiToA(IdentityMatrix(F, d_pi));
a := randelt(A);
assert e*a eq a;
assert IsOne(e);
emat := AToEndVpi(e);
assert emat eq IdentityMatrix(F,d_pi);
print "Checking that the product on A is g-invariant";
for i in [1..25] do
a := randelt(A);
b := randelt(A);
x := randelt(g);
assert gOnA(x, a*b) eq gOnA(x, a)*b + a*gOnA(x, b);
end for;
if construction eq 2 then
print "Checking that a certain quartic does the right thing";
X := randelt(g);
a := EndVpiToA(6*hvee*Matrix(pi(X))^2 - K(X,X)*IdentityMatrix(F, d_pi)/2);
assert a^2 eq K(X,X) * a;
end if;
// what is the matrix for left multiplication by a ?
function Lmatrix(a);
P := Parent(a);
rows := [Eltseq(a*b) : b in Basis(P)];
return Matrix(F, rows);
end function;
// the reduced trace, meaning trace divided by the dimension
function Trd(a);
return Trace(Lmatrix(a))/exp_dim;
end function;
// we can furthermore verify Example 4.9, that squares of elements are idempotents
H := randelt(g);
KH := K(H,H);
if KH ne 0 then
u := EndVpiToA(S(H,H))/KH;
assert u * u eq u;
end if;
// project onto the kernel of the counit
// A = algebra
// counit = counit for the algebra
// x = element to project
function pr_counit(A, counit, x);
rval := x - counit(x)*One(A);
assert IsZero(counit(rval));
return rval;
end function;