1########################################################################################
2#
3#  this file contains the functions to read the nilpotent orbits from the database;
4#  also the semi-automated functions for creating the database are listed here (but not
5#  officially documented).
6#
7#  this file contains the following functions
8#     NilpotentOrbitsOfRealForm
9#     CarrierAlgebraOfNilpotentOrbit
10#     corelg.readDBCA
11#     corelg.readDBTriples
12#     corelg.SL2tripleOfNilpotentElement
13#     corelg.SL2tripleOfCharacteristic
14#     corelg.SqrtEltMySign
15#     corelg.CayleyTransform
16#     corelg.CayleyTransformInverse
17#     corelg.ChevalleySystemInnerType
18#     corelg.checkTriples
19#     corelg.mySLAfctCanBas
20#     corelg.principalOrbitsOfRealForm
21#     corelg.lookupRealCayleyTriple
22#     corelg.RealCayleyTriplesOfRealForm
23#     corelg.ConvertRealCayleyTriplesToNilpotentOrbits
24#     corelg.viewReducedEquationsAndAttach
25#     corelg.attachSolution
26#     corelg.TryToFindComplexCayleyTriple
27#     corelg.calgDBentries
28#     corelg.WriteRealNilpotentOrbitsToDB
29#     corelg.RealNilpotentOrbitsInDatabase
30#     corelg.RealNilpotentOrbitsFromDatabase
31
32
33#######################################################################################
34## NOT OFFICIALLY DOCUMENTED:
35##
36## How to construct real nilpotent orbits using only the database of carrier algs:
37##
38## 1) Let form be an entry of corelg.NonCompactRealFormsOfSimpleLieAlgebra
39##
40## 2) res := corelg.RealCayleyTriplesOfRealForm(form)
41##    now res is a record with entries
42##    - form: the input form
43##    - triples: a record with entries
44##          - principal: contains records with entries
45##                 - realsl2: real Cayley triple [f,h,e] with principal carrier alg
46##                 - cdims  : dimensions of gradations of carrier algebra
47##          - nonprincipal: contains records with entries
48##                 - realsl2: real Cayley triple [f,h,e] with non-principal carrier alg
49##                 - cdims  : dimensions of gradations of carrier algebra
50##            OR
51##                 - oldsl2: the original homogeneous real triple [f,h,e]
52##                 - carrier: the corresponding carrier alg with entries g0, gp, gn
53##                 - cdims : dimensions of gradation of carrier algebra
54##    - tobedone: the indices i such that res.triples.nonprincipal[i] does NOT have
55##                a realsl2 attached. These entries have to be solved as below
56##
57## 3) if res.tobedone=[], then all real triples were constructed, go to 5)
58##
59## 4) for an entry i in res.tobedone do
60##      corelg.TryToFindComplexCayleyTriple(res, i, nrvars, nrtries)
61##    here nrvars and nrtries are lists of integers.
62##    IMPORTANT: name of variable 'res' MUST BE "res"
63##               in order to save solution automatically
64##    This function sets up equations to find a complex Cayley triple;
65##    Then all but nrvars[j] variables are set to zero and this is tried nrtries[j]
66##    times until we find a system of equations which has a non-trivial Groebner basis.
67##    If a solution can be generated automatically (which should almost always be the case),
68##    then it is attached. Otherwise, one has to manually follow the instructions; or to do
69##    the same again. Start with nrvars := [6..14] (or so).
70##    nrtries can also be a single integers; then for every entry nrvars[j] the same number
71##    of tries is used.
72##    If a solution has been found, then the other open cases in res.triples.nonprincipal will
73##    be checked and, if possible, solved automatically. Also, the solution will be written
74##    to the database calg_db in the file carrierAlg.db
75##    Afterwards, res.triples.tobedone will be updated.
76##
77## 5) If res.triples.tobedone = [], then do
78##      orbs := corelg.ConvertRealCayleyTriplesToNilpotentOrbits(res)
79##    This function converts the real triples into objects "NilpotentOrbit"
80##    and computes the corresponding WDDs of the characteristics
81##
82##
83## Use "corelg.WriteRealNilpotentOrbitsToDB(type,rank)" for the semi-automated version of this algorithm
84##
85##
86############################################################################################
87
88
89#################################################################################
90#################################################################################
91#
92# READ DATABASES
93#
94#################################################################################
95#################################################################################
96
97## DATABASE OF CARRIER ALGEBRAS
98corelg.readDBCA := function()
99   Print("#I CoReLG: read database of carrier algebras");
100   ReadPackage( "corelg", "gap/carrierAlg.db" );
101   Print(" ... done\n");
102end;
103if not IsBound(corelg.carrierAlgDB) then corelg.carrierAlgDB := []; fi;
104
105
106## DATABASE OF REAL TRIPLES
107corelg.readDBTriples := function()
108   Print("#I CoReLG: read database of real triples");
109   ReadPackage( "corelg", "gap/realTriples.db" );
110   Print(" ... done\n");
111end;
112
113if not IsBound(corelg.realtriplesDB) then corelg.realtriplesDB := []; fi;
114
115## IS SINGULAR LOADED?
116if not IsBound(HasTrivialGroebnerBasis) then HasTrivialGroebnerBasis:=function()end; fi;
117
118
119
120#################################################################################
121#################################################################################
122#
123# SOME PRELIMINARY FUNCTIONS
124#
125#################################################################################
126#################################################################################
127
128
129################################################
130#input:  liealg L and nilpotent element x in L
131#output: an SL2-triple (f,h,x)
132#remark: just a modification of SL2Triple,
133#        avoid nilpotency test
134################################################
135corelg.SL2tripleOfNilpotentElement := function ( L, x )
136local  n, F, B, xc, eqs, T, i, j, k, l, cij, b, v, z, h, R, BR, Rvecs,
137       H, e0, e1, y;
138   n := Dimension( L );
139   F := LeftActingDomain( L );
140   B := Basis( L );
141   T := StructureConstantsTable(B);
142   xc := Coefficients( B, x );
143   eqs := NullMat( 2 * n, 2 * n, F );
144   for i  in [ 1 .. n ]  do
145      for j  in [ 1 .. n ]  do
146         cij := T[i][j];
147         for k  in [ 1 .. Length( cij[1] ) ]  do
148            l := cij[1][k];
149            eqs[i][l] := eqs[i][l] + xc[j] * cij[2][k];
150            eqs[n + i][n + l] := eqs[n + i][n + l] + xc[j] * cij[2][k];
151         od;
152      od;
153      eqs[n + i][i] := One( F );
154   od;
155   b := [  ];
156   for i  in [ 1 .. n ]  do
157      b[i] := Zero( F );
158      b[n + i] := 2 * One( F ) * xc[i];
159   od;
160   v := SolutionMat( eqs, b );
161   if v = fail  then
162      return fail;
163   fi;
164   z := LinearCombination( B, v{[ 1 .. n ]} );
165   h := LinearCombination( B, v{[ n + 1 .. 2 * n ]} );
166   R := LieCentralizer( L, SubalgebraNC( L, [ x ],"basis" ) );
167   BR := Basis( R );
168   Rvecs := BasisVectors( BR );
169   H := List( Rvecs, function ( v )
170           return Coefficients( BR, h * v );
171       end );
172   H := H + 2 * IdentityMat( Dimension( R ), F );
173   e0 := Coefficients( BR, h * z + 2 * z );
174   e1 := SolutionMat( H, e0 );
175   if e1 = fail  then
176      return fail;
177   fi;
178   y := z - LinearCombination( Rvecs, e1 );
179   return [ y, h, x ];
180end;
181
182
183###################################################################
184#input:  liealg, grading record gr with entries g0, gp, gn, and
185#        a characteristic h in span of g0
186#output: an SL2-triple (f,h,x) with x in span of gp[1]
187###################################################################
188corelg.SL2tripleOfCharacteristic := function( L, gr, h )
189local e, f, co, x, sp, mat, sol;
190   e := gr.gp[1];
191   f := gr.gn[1];
192   while true do
193      co := List( e, x -> Random([-2..2]) );
194      x  := co*e;
195      sp := SubspaceNC( L, List( f, y -> x*y) );
196      if Dimension(sp) = Length(e) and h in sp then
197         mat := List( f, u -> Coefficients( Basis(sp), x*u ) );
198         sol := SolutionMat( mat, Coefficients( Basis(sp), h ) );
199         return [sol*f,h,x];
200      fi;
201   od;
202end;
203
204
205################################################
206#input:  rational or real SqrtFieldElt with one monom
207#output: the sign of v
208################################################
209corelg.SqrtEltMySign :=function(v)
210   if v=0*v then return 0; fi;
211   if IsSqrtFieldElement(v) then
212      if IsPosSqrtFieldElt(v) then return 1; else return -1; fi;
213   fi;
214   if v>0 then return 1; else return -1; fi;
215end;
216
217
218################################################
219#Input:  tr: complex Cayley triple [f,h,e]
220#Output: real Cayley triple (cayley transfom)
221################################################
222corelg.CayleyTransform := function(tr,F)
223local e, f, h,i;
224   f := tr[1];
225   h := tr[2];
226   e := tr[3];
227   i := E(4)*One(F);
228   return [(i/2)*(e-f+h),e+f,(i/2)*(e-f-h)];
229end;
230
231################################################
232#Input:  tr: real Cayley triple [f,h,e]
233#Output: complex Cayley triple (cayley transfom)
234################################################
235corelg.CayleyTransformInverse := function(tr,F)
236local e, f, h,i;
237   f := tr[1];
238   h := tr[2];
239   e := tr[3];
240   i := E(4)*One(F);
241   return [(-1/2*One(F))*(-h-i*f-i*e),i*(e-f),(1/2*One(F))*(h-i*f-i*e)];
242end;
243
244
245################################################
246#Input:  calg:  carrier  subalgebra (of L)
247#        tr  :  record with entries g0, gp, gn
248#        sigma: complex conjugation in L
249#Output: Chevalley system in form of list
250#          [ [x_alpha], [x_{-alpha}], [h_\alpha]]
251#Remark: Need that CSA of L lie in K where L=K+P
252################################################
253corelg.ChevalleySystemInnerType := function(calg, tr, sigma)
254local rs, cgen, cf1, cf2, cf, im, pv, nv, hs, i, fstCB, sndCB, cgen2;
255
256  Info(InfoCorelg,5,"    start ChevalleySystemInnerType in dimension ",Dimension(calg));
257  #construct carrier algebra with roots system and
258  #canonical generators
259   rs := RootSystemOfZGradedLieAlgebra(calg,tr);
260   SetRootSystem(calg,rs);
261
262  #get a (non-special) Chevalley system
263   cgen    := List(CanonicalGenerators(rs),x->List(x,y->y));
264   cgen[2] := -cgen[2];
265
266  #find scalars to construct a special system
267   cf1 := List(List(cgen[1],sigma),
268               x->First(Coefficients(Basis(calg),x),y->not y=0*y));
269   cf2 := List(cgen[2],
270               x->First(Coefficients(Basis(calg),x),y->not y=0*y));
271
272   if IsSqrtField(LeftActingDomain(calg)) then
273      cf  := List([1..Length(cf1)],i->Sqroot(AbsoluteValue(cf1[i]^-1*cf2[i])));
274   else
275      cf  := List([1..Length(cf1)],i->Sqrt(AbsoluteValue(cf1[i]^-1*cf2[i])));
276   fi;
277
278  #now set up automorphism and construct special Chevalley system
279   im  := StructuralCopy(cgen);
280   for i in [1..Length(cgen[1])] do
281      im[1][i] := im[1][i]*cf[i];
282      im[2][i] := im[2][i]*cf[i]^-1;
283   od;
284
285  #mapping fstCB to sndCB is an automorphism
286   fstCB := List(Flat(SLAfcts.canbas( calg, [cgen[1],-cgen[2],cgen[3]])),
287                      x-> Coefficients(Basis(calg),x));
288   sndCB := Flat(SLAfcts.canbas( calg, [im[1],-im[2],im[3]]));
289   pv      := List(ChevalleyBasis(calg)[1],x->
290              SolutionMat(fstCB,Coefficients(Basis(calg),x))*sndCB);
291   nv      := List(ChevalleyBasis(calg)[2],x->
292              SolutionMat(fstCB,Coefficients(Basis(calg),-x))*sndCB);
293   hs      := List([1..Length(pv)],x-> -pv[x]*nv[x]);
294   hs      := Concatenation(hs,List([1..Length(nv)],x-> -nv[x]*pv[x]));
295
296   Info(InfoCorelg,5,"    end ChevalleySystemInnerType");
297   return rec(chevSys := [pv,nv,hs],
298              rank    := Length(SimpleSystem(rs)));
299end;
300
301
302
303
304################################################
305#Output: true, if all rsl2 are real Cayley triples
306################################################
307corelg.checkTriples := function(form, triples)
308local L, K, P, theta, sigma, tr, f, e, h;
309   Info(InfoCorelg,5,"    start corelg.checkTriples");
310   L     := form.liealgSF;
311   theta := CartanDecomposition(L).CartanInv;
312   sigma := RealStructure(L);
313   for tr in triples do
314      if IsBound(tr.realsl2) then
315         f := tr.realsl2[1];
316         h := tr.realsl2[2];
317         e := tr.realsl2[3];
318         if not (h*f = -2*f and h*e=2*e and e*f=h) or
319            not theta(e)=-f or not tr.realsl2 = List(tr.realsl2,sigma) then
320               Error("not a real sl2 triple");
321         fi;
322      fi;
323   od;
324   if Length(Filtered(triples,x->not IsBound(x.realsl2)))>0 then
325      Print("corelg.checkTriples: there are entries withouth attached realsl2\n");
326   fi;
327   Info(InfoCorelg,5,"    end corelg.checkTriples");
328   return true;
329end;
330
331
332
333################################################
334#Input:  slightly mod version of SLAfct.canbas
335################################################
336corelg.mySLAfctCanBas := function ( L, c )
337    local  x, y, x1, y1, done, levelx, levely, newlevx, newlevy, sp, i, j, u, tmp;
338    x := c[1];
339    y := c[2];
340    x1 := ShallowCopy( x );
341    y1 := ShallowCopy( y );
342    done := false;
343    levelx := ShallowCopy( x );
344    levely := ShallowCopy( y );
345    while not done  do
346        newlevx := [  ];
347        newlevy := [  ];
348        sp  := MutableBasis( SqrtField, [  ], Zero(SqrtField)*c[1][1]);
349        for i  in [ 1 .. Length( x ) ]  do
350            for j  in [ 1 .. Length( levelx ) ]  do
351                u := x[i] * levelx[j];
352                if not IsZero( u ) and not u in sp then
353                   # corelg.eltInSubspace(L,BasisVectors(sp), u) then
354                    Add( newlevx, u );
355                    CloseMutableBasis( sp, u );
356                    u   := y[i] * levely[j];
357                    Add( newlevy, u );
358                fi;
359            od;
360        od;
361        if newlevx <> [  ]  then
362            Append( x1, newlevx );
363            Append( y1, newlevy );
364            levelx := newlevx;
365            levely := newlevy;
366        else
367            done := true;
368        fi;
369    od;
370    return [ x1, y1, c[3] ];
371end;
372
373
374
375
376#################################################################################
377#################################################################################
378#
379# FUNCTIONS TO CONSTRUCT REAL TRIPLES FROM SCRATCH (ONLY PRINC CAlgs)
380#
381#################################################################################
382#################################################################################
383
384
385################################################
386#Input:  form: a real form of a lie algebra
387#              record containing liealg and grading
388#Output: record with the following entries
389#            - principal: record with
390#                   -oldsl2    (old triple of K in p)
391#                   -cayleysl2 (complex Cayley triple)
392#                   -realsl2   (corresp. real Cayley triple)
393#            - nonprincipal: record with
394#                    -oldsl2    (old triple of K in p)
395#                    -carrier    rec with g0, gp, gn
396################################################
397corelg.principalOrbitsOfRealForm := function(form)
398local res, L, K, P, sl2, sigma, tr, f, h, e, calg, cs, writeToSF,
399      r, mat, ns, cf, x, rsl2, ll, tt1, tt2, F, r2, tmp, t, g,
400      LSF, sigmaSF, csl2, T;
401
402   Info(InfoCorelg,4,"start corelg.principalOrbitsOfRealForm");
403   res := rec(principal :=[], nonprincipal :=[]);
404   L   := form.liealg;
405   F   := LeftActingDomain(L);
406   K   := Basis(CartanDecomposition(L).K);
407   P   := Basis(CartanDecomposition(L).P);
408   g   := [K,P];
409   writeToSF := form.writeToSF;
410   LSF := form.liealgSF;
411
412   if Dimension(CartanSubalgebra(CartanDecomposition(L).K))
413      = Dimension(CartanSubalgebra(L)) then
414      sl2 := SLAfcts.nil_orbs_inner( L, g[1], g[2], g[2] );;
415   else
416
417      sl2 := corelg.nil_orbs_outer(L, g[1], g[2], g[2] );;
418   fi;
419   for t in [1..Length(sl2.sl2)] do
420      tmp        := RegularCarrierAlgebraOfSL2Triple( L, sl2.sl2[t] );
421      sl2.sl2[t] := rec(sl2  := sl2.sl2[t],
422                        g0   := tmp.g0,
423                        gp   := tmp.gp,
424                        gn   := tmp.gn);
425   od;
426
427  #complex conjugation
428   sigma   := RealStructure(L);
429   sigmaSF := RealStructure(LSF);
430
431   for t in [1..Length(sl2.sl2)] do
432      tr := sl2.sl2[t];
433     #tr has the form rec(sl2=rec(f,h,e), g0,gp,gn)
434     #where the g0, gp, gn describe a carrier alg
435      Info(InfoCorelg,4,"   consider triple ",t," of ",Length(sl2.sl2));
436      f    := tr.sl2[1];
437      h    := tr.sl2[2];
438      e    := tr.sl2[3];
439      calg := SubalgebraNC(L,corelg.myflat(Concatenation(tr.g0,tr.gp,tr.gn)),"basis");
440     tr := sl2.sl2[t];
441     #tr has the form rec(sl2=rec(f,h,e), g0,gp,gn)
442     #where the g0, gp, gn describe a carrier alg
443      Info(InfoCorelg,4,"   consider triple ",t," of ",Length(sl2.sl2));
444      f    := tr.sl2[1];
445      h    := tr.sl2[2];
446      e    := tr.sl2[3];
447      calg := SubalgebraNC(L,corelg.myflat(Concatenation(tr.g0,tr.gp,tr.gn)),"basis");
448
449     #do we have principal case?
450      if IsAbelian(SubalgebraNC(L,tr.g0)) then
451        #set CSA
452        #basis of rootsystem lies in tr.gp[1]
453         SetCartanSubalgebra(calg,SubalgebraNC(calg,tr.g0));
454         cs   := corelg.ChevalleySystemInnerType(calg,tr,sigma);
455         r    := [1..Length(SimpleSystem(RootSystem(calg)))];
456
457         mat  := List(Concatenation(cs.chevSys[3]{r},[-h]),
458                      x->Coefficients(Basis(L),x));
459         ns   := NullspaceMat(mat)[1];
460         cf   := List(ns{[1..Length(r)]}, x->Sqroot(x));
461         x    := Sum(List([1..Length(r)], i-> cf[i]*(writeToSF(Flat(cs.chevSys)[r[i]]))));
462         csl2 := [sigmaSF(x),writeToSF(h),x];
463         rsl2 := corelg.CayleyTransform(csl2,SqrtField);
464
465         Add(res.principal, rec(cdims     := [[Length(tr.g0)],List(tr.gp,Length),
466                                                            List(tr.gn,Length)],
467                               #cayleysl2 := csl2,
468                                realsl2   := rsl2));
469      else
470
471         Add(res.nonprincipal, rec(oldsl2  := tr.sl2,
472                               cdims   := [[Length(tr.g0)],List(tr.gp,Length),
473                                                            List(tr.gn,Length)],
474                               carrier := rec(g0  := tr.g0,
475                                              gp  := tr.gp,
476                                              gn  := tr.gn)));
477      fi;
478   od;
479   if not corelg.checkTriples(form,res.principal) then Print("dammit!"); fi;
480   Info(InfoCorelg,4,"end corelg.principalOrbitsOfRealForm");
481   return res;
482end;
483
484
485
486################################################
487#Input:  form and an entry of nonprincipal out
488#        containing entries oldsl2, cdims, carrier
489#Output: try to look-up a real Cayley triple for oldsl2
490#        in the database and stores it if possible;
491#        otherwise returns false
492################################################
493corelg.lookupRealCayleyTriple := function(form, out)
494local L, sigma, ca, grad, rs, cm, pos, ct, cg, salgs, sl2, i, j, t,enum, F,
495      newcg, new, ngrad, ndims, cf, csl2, canbas, my, cb, myenum, dbenum, l1, l2,
496      mycg, mygr, mycf, l, mys1, mys1c, newtr, dbcf, db, cand, tmp, perm, ins1, mycf2,
497      bas, dim, cfh, bas2, dim2,tr,cs,r,mat,ns,x, h, y, xy, K, P,s, my2, mycg2, signs,
498      writeToSF, LSF, sigmaSF, mycgSF, getDBpositions;
499
500   if Length(corelg.carrierAlgDB)=0 then corelg.readDBCA(); fi;
501
502  #find entry in DB corelg.carrierAlgDB
503   getDBpositions := function(type, rank, dims,ins1,signs)
504   return
505       Filtered([1..Length(corelg.carrierAlgDB)],x->
506             corelg.carrierAlgDB[x].type = type and
507             corelg.carrierAlgDB[x].rank = rank and
508             corelg.carrierAlgDB[x].dims = dims and
509             corelg.carrierAlgDB[x].ins1 = ins1 and
510             corelg.carrierAlgDB[x].ordsigns =signs);
511   end;
512
513   L     := form.liealg;
514   LSF   := form.liealgSF;
515   writeToSF := form.writeToSF;
516   sigma   := RealStructure(L);
517   sigmaSF := RealStructure(LSF);
518
519   ca    := SubalgebraNC(L,corelg.myflat(Concatenation(out.carrier.g0,
520                                    out.carrier.gp,out.carrier.gn)),"basis");
521   SetCartanSubalgebra(ca,Intersection(ca,CartanSubalgebra(L)));
522   grad  := List([ [out.carrier.g0], out.carrier.gp, out.carrier.gn],
523                 x-> List(x,y->SubspaceNC(L,y,"basis")));
524
525  #split into simple parts
526   rs    := RootSystemOfZGradedLieAlgebra(ca,out.carrier);
527   SetRootSystem(ca,rs);
528   cm    := CartanMatrix(rs);
529   ct    := CartanType(cm);
530   cg    := CanonicalGenerators(rs);
531   cb    := corelg.myflat(SLAfcts.canbas( ca, cg));
532   salgs := [];
533   sl2   := out.oldsl2;
534   for i in [1..Length(ct.types)] do
535      t     := ct.enumeration[i];
536      newcg := List(cg,x->x{t});
537      enum  := [1..Length(t)];
538      new   := rec(type := ct.types[i],
539                   enum := enum,
540                   alg  := SubalgebraNC(ca,corelg.myflat(newcg),"basis"));
541      ngrad := List(grad, x-> List(x,y->Intersection(y,new.alg)));
542      ngrad := List(ngrad,x-> Filtered(x,y->Dimension(y)>0));
543      ndims := List(ngrad,x-> List(x,Dimension));
544      new.grad := ngrad;
545      new.dims := [ndims[1],ndims[2],ndims[3]];
546      new.cgen := newcg;
547      new.isprincipal := IsAbelian(SubalgebraNC(new.alg,Basis(ngrad[1][1]),"basis"));
548      Add(salgs,new);
549   od;
550
551  #have to split characteristic for principle orbits?
552   if Length(Filtered(salgs,x->x.isprincipal))>0 then
553      bas  := List(salgs,x->BasisVectors(CanonicalBasis(x.alg)));
554      dim  := List(bas,Length);
555      bas2 := Basis(VectorSpace(CF(4),corelg.myflat(bas),"basis"),corelg.myflat(bas));
556      cfh  := Coefficients(bas2,sl2[2]);
557      dim2 := [[1..dim[1]]];
558      for i in [2..Length(dim)] do
559         dim2[i] := dim2[i-1][Length(dim2[i-1])]+[1..dim[i]];
560      od;
561      cfh  := List(dim2,x->cfh{x});
562      for i in [1..Length(salgs)] do salgs[i].h := cfh[i]*bas[i]; od;
563   fi;
564
565   if Length(ct.types) > 1 then
566      Info(InfoCorelg,4,"  Carrier algebra has decomposition",ct.types);
567   fi;
568
569   newtr    := [];
570   for i in [1..Length(salgs)] do
571      my     := salgs[i].alg;
572      mycg   := salgs[i].cgen;
573      mygr   := salgs[i].grad;
574
575      if not salgs[i].isprincipal then
576         myenum := salgs[i].enum;
577        #order gens st first gens lie in s0
578         l      := Length(mycg[1]);
579        #mys1   := Filtered([1..l], x-> corelg.eltInSubspace(L,Basis(mygr[2][1]),mycg[1][x]));
580         mys1   := Filtered([1..l], x-> mycg[1][x] in mygr[2][1] );
581
582         mys1c  := Filtered([1..l], x-> not x in mys1);
583         mycg   := List(mycg, x-> Concatenation(x{mys1},x{mys1c}));
584         perm   := PermList(Concatenation(mys1,mys1c))^-1;
585         myenum := List(myenum, x-> x^perm);
586         ins1   := AsSortedList(List([1..Length(mys1)],x->Position(myenum,x)));
587         mycf   := List([1..l], x->
588                   Coefficients(Basis(VectorSpace(CF(4),[mycg[2][x]],"basis"),
589                               [mycg[2][x]]),sigma(mycg[1][x]))[1]);
590         signs  := List(mycf{myenum},corelg.SqrtEltMySign);
591         pos    := getDBpositions(salgs[i].type[1],salgs[i].type[2],
592                                  salgs[i].dims,ins1,signs);
593
594         if pos = [] then
595            return false;
596         fi;
597        #now find isomorphism from calg in db to my
598         cand   := corelg.carrierAlgDB[pos[1]];
599         dbenum := cand.enum;
600         dbcf   := cand.cfImage;   #coefficient of sigma(xi) wrt yi
601         csl2   := cand.cfCsl2*Sqroot(1);    #cayley sl2 triple
602
603        #adjust ordering wrt enum
604         perm := MappingPermListList(myenum,dbenum);
605         l1   := [1..Length(mys1)];
606         l2   := [Length(mys1)+1..l];
607         if not (ForAll(l1,x->x^perm in l1) and ForAll(l2,x->x^perm in l2)) then
608            Error("cannot use this db entry!");
609         fi;
610         mycg2  := [[],[],[]];
611         mycf2  := ShallowCopy(mycf);
612         for j in [1..l] do
613            mycg2[1][j^perm] := mycg[1][j];
614            mycg2[2][j^perm] := mycg[2][j];
615            mycg2[3][j^perm] := mycg[3][j];
616            mycf2[j^perm]     := mycf[j];
617         od;
618         myenum := List(myenum,x->x^perm);
619         mycg   := mycg2;
620         mycf   := mycf2;
621         cf     := List([1..l],x->Sqroot(dbcf[x]/mycf[x]));
622         mycgSF := [[],[],[]];
623         for j in [1..l] do
624             mycgSF[1][j] := cf[j]*writeToSF(mycg[1][j]);
625             mycgSF[2][j] := cf[j]^-1*writeToSF(mycg[2][j]);
626             mycgSF[3][j] := writeToSF(mycg[3][j]);
627         od;
628         canbas := corelg.myflat(corelg.mySLAfctCanBas(LSF, mycgSF));
629         csl2   := List(csl2,x->x*canbas);
630         if i = 1 then
631            newtr := csl2;
632         else
633            for j in [1..3] do newtr[j] := newtr[j]+csl2[j]; od;
634         fi;
635
636     #else we have a principal carrier algebra
637      else
638
639         if salgs[i].type = ["A",1] then
640            x    := Basis(mygr[2][1])[1];
641            h    := salgs[i].h;
642            cf   := Coefficients(Basis(VectorSpace(CF(4),[h],"basis"),
643                               [h]),x*sigma(x))[1];
644            x    := Sqroot(1/cf)*writeToSF(x);
645            csl2 := [sigmaSF(x),writeToSF(h),x];
646         else
647            tr := rec(g0 := BasisVectors(Basis(mygr[1][1])),
648                      gp := List(mygr[2],x->BasisVectors(Basis(x))),
649                      gn := List(mygr[3],x->BasisVectors(Basis(x))));
650
651            my   := SubalgebraNC(L,corelg.myflat(Concatenation(tr.g0,tr.gp,tr.gn)),"basis");
652            cs   := corelg.ChevalleySystemInnerType(my,tr,sigma).chevSys;
653            r    := Concatenation(cs[1],cs[2]);
654           #r    := Filtered([1..Length(r)], x-> corelg.eltInSubspace(L,tr.gp[1],r[x]));
655            r    := Filtered([1..Length(r)], x-> r[x] in tr.gp[1] );
656            if r = [] then Error("ups.. torus as s0; case A1?"); fi;
657            mat  := List(Concatenation(cs[3]{r},[-salgs[i].h]),
658                     x->Coefficients(Basis(L),x));
659            ns   := NullspaceMat(mat)[1];
660            cf   := List(ns{[1..Length(r)]}, x->Sqroot(x));
661            x    := Sum(List([1..Length(r)], i-> cf[i]*(writeToSF(Flat(cs)[r[i]]))));
662            csl2 :=  [sigmaSF(x),writeToSF(salgs[i].h),x];
663         fi;
664         if i = 1 then
665            newtr := csl2;
666         else
667            for j in [1..3] do newtr[j] := newtr[j]+csl2[j]; od;
668         fi;
669      fi;
670   od;
671   out.realsl2   := corelg.CayleyTransform(newtr,SqrtField);
672   Unbind(out.carrier);
673   Unbind(out.oldsl2);
674   corelg.checkTriples(form,[out]);
675   return true;
676end;
677
678
679################################################
680#Input:  real form
681#Output: record with entries
682#           - form: the input form
683#           - triples: record with entries:
684#               -principal:    cdims, realsl2
685#               -nonprincipal: cdims, realsl2
686#           - tobedone: those indices i where
687#                 nonprincipal[i] has NO realsl2;
688#                 here we need to solve an equation!
689#################################################
690corelg.RealCayleyTriplesOfRealForm := function(form)
691local triples, nonpr, lookup, tr, ctr, wdd;
692   Info(InfoCorelg,4,"start RealSL2Triples");
693   triples   := corelg.principalOrbitsOfRealForm(form);
694   nonpr     := triples.nonprincipal;
695   Info(InfoCorelg,1,"there are ",Length(nonpr)," non-principal triples");
696   lookup := List([1..Length(nonpr)],x->corelg.lookupRealCayleyTriple(form,nonpr[x]));
697   lookup := Filtered([1..Length(nonpr)],x->lookup[x]=false);
698   if Length(lookup)>0 then
699      Print("TO BE SOLVED (getEquationsForX): ",Length(lookup)," carrier algs,\n");
700      Print("their dims are",List(nonpr{lookup},x->Sum(Flat(x.cdims))),"\n");
701   elif Length(nonpr)>0 then
702      Print("could solve all non-principal carrier algebras\n");
703   fi;
704   Info(InfoCorelg,4,"end RealSL2Triples");
705   return rec(form     := form,
706              triples  := triples,
707              tobedone := lookup);
708end;
709
710
711################################################
712#Input:  output of RealCayleyTriplesOfRealForm with tobedone=[]
713#Output: corresponding nilpotent orbits
714################################################
715corelg.ConvertRealCayleyTriplesToNilpotentOrbits := function( res )
716local T, wdd, cb, L, LSF, form, new, i, o;
717
718   form := res.form;
719   if not res.tobedone = [] then
720      Error("tobedone is not emtpy");
721   fi;
722   new := [];
723   L   := form.liealg;
724   LSF := form.liealgSF;
725   T   := SignatureTable(L);
726   cb  := BasisNC(LSF,corelg.myflat(ChevalleyBasis(LSF)));
727   Info(InfoCorelg,4,"compute WDDs and coefficients for constructing orbits");
728   for i in res.triples.principal do
729      wdd := corelg.WDD(L, List(Coefficients(Basis(LSF),i.realsl2[2]),
730                         SqrtFieldEltToCyclotomic)*Basis(L),T);
731      o   := NilpotentOrbit( L, wdd );
732      SetRealCayleyTriple(o, i.realsl2);
733      SetInvariants(o, rec(wdd             := wdd,
734                           carrierAlgebra  := rec(dims   := i.cdims,
735                                                  principal := true)));
736
737     #SetCoefficientsWRTChevBasis( o, List(i.realsl2,x->Coefficients(cb,x)));
738      Add(new,o);
739   od;
740   for i in res.triples.nonprincipal do
741      wdd := corelg.WDD(L, List(Coefficients(Basis(LSF),i.realsl2[2]),
742                         SqrtFieldEltToCyclotomic)*Basis(L),T);
743      o   := NilpotentOrbit( L, wdd );
744      SetRealCayleyTriple(o, i.realsl2);
745      SetInvariants(o, rec(wdd             := wdd,
746                           carrierAlgebra  := rec(dims   := i.cdims,
747                                                  principal := true)));
748     #SetCoefficientsWRTChevBasis( o, List(i.realsl2,x->Coefficients(cb,x)));
749      Add(new,o);
750   od;
751   Info(InfoCorelg,4,"done");
752   return rec(form := form, nilpotentOrbits := new);
753end;
754
755#################################################################################
756#################################################################################
757#
758# FUNCTIONS TO GET, VIEW AND ATTACH SOLUTIONS FOR NON-PRINCIPAL CAlgs
759#
760#################################################################################
761#################################################################################
762
763
764################################################
765#Input:  this is only called from TryToFindComplexCayleyTriple
766#        res is output of RealCayleyTriplesOfRealForm
767#        res.triples.nonprincipal[i] had attached eqs, GR etc
768#Output: tries to attach a solution of the equations GR;
769#        otherwise prints GR so that equations can maybe
770#        solved manually
771################################################
772corelg.viewReducedEquationsAndAttach := function(res,i)
773local out, eqs, ok, notok, isgood,j,jj ,isgood2, ok2, notok2,
774      goodvars, k, var, str;
775  str := "";
776  out := res.triples.nonprincipal[i];
777  if not IsBound(out.eqs) then
778     Error("no eqs attached");
779  fi;
780  isgood2 := function(l)
781     return Length(l)=4 and Length(l[1])=2 and l[1][2] = 1
782            and l[2]=1 and IsGaussRat(l[4]) and
783            ForAll(List([1..Length(l[3])/2],j->l[3][2*j-1]),x-> x in goodvars);
784  end;
785  isgood := function(l)
786     return Length(l)=4 and l[1]=[] and IsGaussRat(l[2])
787            and Length(l[3])=2 and l[3][2]=2 and l[4]=1;
788  end;
789  if not out.GR = fail then
790     Print("these are equations:\n",out.GR,"\n");
791     eqs   := out.GR;
792     ok    := [];
793     notok := [];
794     for j in eqs do
795        if isgood(ExtRepPolynomialRatFun(j)) then
796           Add(ok,ExtRepPolynomialRatFun(j));
797        else
798           Add(notok,j);
799        fi;
800     od;
801     if not ok=[] then
802        goodvars := List(ok,x->x[3][1]);
803        Print("\ncan copy-paste the following part (modify var name 'res'):\n");
804        Append(str,Concatenation( "corelg.attachSolution(res,",String(i),",["));
805        Print("corelg.attachSolution(res,",String(i),",[");
806        for jj in [1..Length(ok)] do
807           j := ok[jj];
808           Append(str,Concatenation("[",String(j[3][1]),",Sqroot(",String(-j[2]),")]"));
809           Print("[",String(j[3][1]),",Sqroot(",String(-j[2]),")]");
810           if not jj = Length(ok) or not notok=[] then Append(str,","); Print(","); fi;
811        od;
812        if notok=[] then
813           Append(str,"]);");
814           Print("]);\n\n");
815           Print("now try to attach this solution:\n");
816           EvalString(str);
817        else
818           ok2    := [];
819           notok2 := [];
820           for j in notok do
821              if isgood2(ExtRepPolynomialRatFun(j)) then
822                 Add(ok2,ExtRepPolynomialRatFun(j));
823              else
824                 Add(notok2,j);
825              fi;
826           od;
827           for jj in [1..Length(ok2)] do
828              j := ok2[jj];
829              Append(str, Concatenation("[",String(j[1][1]),",",String(-j[4]),"*Sqroot(" ));
830              Print("[",j[1][1],",",-j[4],"*Sqroot(");
831              for k in [1..Length(j[3])/2] do
832                 var := j[3][2*k-1];
833                 var := Filtered(ok,x->x[3][1] = var)[1];
834                 Append(str,Concatenation("(",String(-var[2]),")"));
835                 Print("(",-var[2],")");
836                 if not k = Length(j[3])/2 then
837                    Print("*");
838                    Append(str, "*");
839                 fi;
840              od;
841              Append(str,")]");
842              Print(")]");
843              if not jj = Length(ok2) or not notok2 = [] then
844                 Append(str,",");
845                 Print(",");
846              else
847
848              fi;
849           od;
850           if notok2=[] then
851              Append(str,"]);");
852              Print("]);\n\n");
853              Print("now try to attach this solution:\n");
854              EvalString(str);
855           else
856              Print(",\n\n");
857              Print("still to take into account:\n",notok2,"\n\n");
858           fi;
859        fi;
860     fi;
861  else
862     Print("no reduced equations attached\n");
863  fi;
864end;
865
866
867
868
869
870################################################
871#Input:  this is only called from  corelg.viewReducedEquationsAndAttach
872#Output: attach a solution (complex Cayley triple)
873#        to res.triples.nonprincipal[i] and write it to corelg.carrierAlgDB
874################################################
875corelg.attachSolution := function(res,i,v)
876local csl2,j,w,tmp, out, bas, realsl2, L, sigmaSF, calg,  enum, form,
877      rs, cg, gr, l, s1, s1c, cf, CB, cfcsl2, data, pos, perm, F, LSF,
878      cgSF, path;
879
880   if Length(corelg.carrierAlgDB)=0 then corelg.readDBCA(); fi;
881
882   form := res.form;
883   out  := res.triples.nonprincipal[i];
884
885   if not IsBound(out.makeSol) then
886      Error("cannot attach solution, no makeSol entry");
887   fi;
888
889  #make sure everything is over SqrtField
890   for i in [1..Length(v)] do v[i][2] := v[i][2]*Sqroot(1); od;
891
892  #make solution
893   csl2          := out.makeSol(v);
894   realsl2       := corelg.CayleyTransform(csl2,SqrtField);
895   tmp           := rec(realsl2 := realsl2);
896   corelg.checkTriples(res.form,[tmp]);
897   if IsBound(out.realsl2) then
898      Error("Warning: realsl2 was alread bound!");
899   fi;
900   if not Sum(Flat(out.cdims)) = Dimension(res.form.liealg) then
901      Error("dim of calg smaller than dim of alg; no need to store");
902   fi;
903   out.realsl2   := realsl2;
904   out.cayleysl2 := csl2;
905   corelg.checkTriples(res.form,[out]);
906
907  #now rearrange can gens and store everything wrt can bas
908   L       := res.form.liealg;
909   LSF     := res.form.liealgSF;
910   sigmaSF := RealStructure(LSF);
911   calg := SubalgebraNC(L,corelg.myflat(Concatenation(out.carrier.g0,
912                                            out.carrier.gp,out.carrier.gn)),"basis");
913   SetCartanSubalgebra(calg,Intersection(calg,CartanSubalgebra(L)));
914   rs   := RootSystemOfZGradedLieAlgebra(calg,out.carrier);
915   SetRootSystem(calg,rs);
916   cg   := CanonicalGenerators(RootSystem(calg));
917   gr   := List([[out.carrier.g0], out.carrier.gp, out.carrier.gn],
918                 x-> List(x,y->SubspaceNC(L,y,"basis")));
919   l    := Length(cg[1]);
920  #s1   := Filtered([1..l], x -> corelg.eltInSubspace(calg,Basis(gr[2][1]),cg[1][x]));
921   s1   := Filtered([1..l], x -> cg[1][x] in gr[2][1] );
922   s1c  := Filtered([1..l], x -> not x in s1);
923   cg   := List(cg, x-> Concatenation(x{s1},x{s1c}));
924   cgSF := List(cg,x->List(x,res.form.writeToSF));
925   cf   := List([1..l],x->
926                Coefficients(Basis(VectorSpace(SqrtField,[cgSF[2][x]],"basis"),
927                             [cgSF[2][x]]),sigmaSF(cgSF[1][x]))[1]);
928
929   CB     := List(corelg.myflat(SLAfcts.canbas( calg, cg )),res.form.writeToSF);
930   CB     := Basis(VectorSpace(SqrtField,CB,"basis"),CB);
931   cfcsl2 := List(csl2,x->Coefficients(CB,x));
932
933  #adjust enumeration according to rearranged cangens
934   enum   := CartanType(CartanMatrix(rs)).enumeration[1];
935   perm   := PermList(Concatenation(s1,s1c))^-1;
936   enum   := List(enum,x->x^perm);
937   tmp    := rec(type := res.form.type,
938              rank := res.form.rank,
939              enum := enum,
940              dims := List(gr,x->List(x,Dimension)),
941              ins1 := AsSortedList(List([1..Length(s1)],x->Position(enum,x))),
942              cfImage  := cf,          #sigma(cg[1][i]) = cf[i]*cg[2][i]
943              ordsigns := List(cf{enum},corelg.SqrtEltMySign),
944              cfCsl2   := cfcsl2);      #cf of csl2 wrt can bas wrt cg
945  #ins1 are the indicies of std ordered roots which lie in s1
946  #ordsigns are the signs of cf, in order of std ordered roots
947
948   Info(InfoCorelg,4,"   read database before writing");
949   ReadPackage( "corelg", "gap/carrierAlg.db" );
950   pos := Filtered(corelg.carrierAlgDB,x->  x.rank = tmp.rank and
951                                x.type = tmp.type and
952                                x.dims = tmp.dims and
953                                x.ins1 = tmp.ins1);
954
955   if pos=[] then
956      Add(corelg.carrierAlgDB, tmp);
957    ##path := Concatenation(LOADED_PACKAGES.corelg[1],"/gap/carrierAlg.db");
958      path := Filename(DirectoriesPackageLibrary("corelg","gap"),"carrierAlg.db");
959
960      PrintTo(path,"corelg.carrierAlgDB:=");
961      AppendTo(path,corelg.carrierAlgDB);
962      AppendTo(path,";");
963      Info(InfoCorelg,4,"  wrote new entry to database");
964   else
965      Info(InfoCorelg,4,"  entry was already contained in database");
966   fi;
967   Unbind(out.GR);
968   Unbind(out.eqs);
969   Unbind(out.var);
970   Unbind(out.makeSol);
971   Info(InfoCorelg,4,"update to-do list; check other unfinished nonprinciple triples");
972   for i in res.triples.nonprincipal{res.tobedone} do
973      corelg.lookupRealCayleyTriple(form,i);
974   od;
975   res.tobedone := Filtered([1..Length(res.triples.nonprincipal)],
976                   x->not IsBound(res.triples.nonprincipal[x].realsl2));
977   Info(InfoCorelg,4,"this is new to-do list",res.tobedone);
978   return true;
979end;
980
981
982
983################################################
984#Input:  res is output of RealCayleyTriplesOfRealForm
985#        ind should lie in res.tobedone
986#        nrvars list of nr of non-zero variables for
987#               Groebner basis
988#        nrtries list of tries for each number in nrvars
989#                or just one integer (nr of tries)
990#        IMPORTANT: name of variable 'res' MUST BE "res"
991#                   in order to save solution automatically
992#Output: computes equations to construct complex
993#        Cayley triple and (hopefully) attaches it
994#        automatically;
995#################################################
996corelg.TryToFindComplexCayleyTriple := function(res, ind, nrvars,nrtries)
997local L, sigma, ca, s1, sl2, h, bas, s1b, new, n, PR, prb, lhs, rhs,
998      eqs, rateqs, makeSol, complexConjugate, eq, i, I, GR, tmp, j,
999      eqs1, done, ii, k, nzvars, form, out, sigmaSF, LSF, s1bSF, hSF;
1000
1001   if ind>Length(res.triples.nonprincipal) then
1002      Error("there are only ",Length(res.triples.nonprincipal)," nonprincipals\n");
1003   fi;
1004   form := res.form;
1005   out  := res.triples.nonprincipal[ind];
1006   if IsInt(nrtries) then
1007      nrtries := ListWithIdenticalEntries(Length(nrvars),nrtries);
1008   fi;
1009
1010   L   := form.liealg;
1011   LSF := form.liealgSF;
1012   if IsBound(out.realsl2) then
1013      Print("real sl2 triple already attached, don't do anything.\n");
1014      return true;
1015   fi;
1016   if IsBound(out.eqs) then
1017      Print("equations already attached; re-compute them.\n");
1018   fi;
1019
1020   sigma   := RealStructure(L);
1021   sigmaSF := RealStructure(LSF);
1022
1023   ca    := SubalgebraNC(L,corelg.myflat(Concatenation(out.carrier.g0,
1024                                    out.carrier.gp,out.carrier.gn)),"basis");
1025   s1    := SubspaceNC(ca,out.carrier.gp[1],"basis");
1026   sl2   := out.oldsl2;
1027   h     := sl2[2];
1028   bas   := Basis(ca);
1029   s1b   := Basis(s1);
1030   s1bSF := List(s1b,form.writeToSF);
1031   hSF   := form.writeToSF(h);
1032
1033  #set up equations
1034  #new[i][j] = s1b(i) * sigma(s1b(i));
1035   new   := List(s1b, g-> List(s1b,h-> Coefficients(bas,g*sigma(h))));
1036
1037  #if X=sum a_i s1b(i) then the system of equation is
1038  # (a_1,..,a_n) * new * sigma(a_1,..,a_n)^T = h
1039  #write ai = ui + E(4)vi; create indeterminates:
1040   n   := Length(s1b);
1041   PR  := PolynomialRing(CF(4),[1..2*n]);
1042   prb := IndeterminatesOfPolynomialRing(PR);
1043   lhs := List([1..n],i->prb[i]+prb[i+n]*(E(4)));
1044   rhs := List([1..n],i->prb[i]-prb[i+n]*(E(4)));
1045   new := lhs*new;
1046   new := Sum(List([1..n],i-> new[i]*rhs[i]));
1047   new := new - Coefficients(bas,h);
1048   eqs := Filtered(new,x->not x = 0*x);
1049
1050  #write complex equation over rationals
1051   complexConjugate := function(eq)
1052   local tmp, fam, i;
1053      fam := FamilyObj(eq);
1054      tmp := MutableCopyMat(ExtRepPolynomialRatFun(eq));
1055      for i in [1..Length(tmp)] do
1056         tmp[i] := ComplexConjugate(tmp[i]);
1057      od;
1058      return PolynomialByExtRep(fam,tmp);
1059   end;
1060   rateqs := [];
1061   for eq in eqs do
1062       tmp := complexConjugate(eq);
1063       Add(rateqs,(1/2*E(4))*(eq-tmp));
1064       Add(rateqs,(1/2)*(eq+tmp));
1065   od;
1066   eqs := Filtered(rateqs,x-> not x = x*0);
1067
1068   Info(InfoCorelg,4,"there are ",Length(prb)," variables.");
1069   for ii in [1..Length(nrvars)] do
1070      i := nrvars[ii];
1071      j := nrtries[ii];
1072      Info(InfoCorelg,4,"start checking ",i," nonzero variables");
1073      for k in [1..j] do
1074         Print("start try nr ",k,"\n");
1075         nzvars := [];
1076         while Length(nzvars)<i do
1077            tmp := Random(prb);
1078            if not tmp in nzvars then Add(nzvars,tmp); fi;
1079         od;
1080         eqs1 := Concatenation(eqs,Filtered(prb,x-> not x in nzvars));
1081         I    := Ideal(PR,eqs1);
1082         GR   := HasTrivialGroebnerBasis(I);
1083         done := not GR;
1084         if done then break; fi;
1085      od;
1086      if done then break; fi;
1087   od;
1088   if done then
1089      Print("found nontriv GR, now compute it\n");
1090      GR := ReducedGroebnerBasis(I,MonomialLexOrdering());
1091      GR := Filtered(GR,x-> not x in prb);
1092   else
1093      GR := fail;
1094      Print("Error:could not find nice Groebner basis\n");
1095   fi;
1096
1097  #given solution vector l, creates solution triple
1098   makeSol := function(v)
1099   local e,f,j,l;
1100      l := ListWithIdenticalEntries(2*n,0);
1101      for j in v do l[j[1]] := j[2]; od;
1102      e := List([1..n],i-> l[i]+E(4)*l[i+n]);
1103      e := Sum(List([1..n],i->e[i]*s1bSF[i]));
1104      f := sigmaSF(e);
1105      return [f,hSF,e];
1106   end;
1107
1108   out.eqs     := eqs;
1109   out.GR      := GR;
1110   out.var     := prb;
1111   out.makeSol := makeSol;
1112   if not GR = fail then
1113      corelg.viewReducedEquationsAndAttach(res,ind);
1114   fi;
1115   return;
1116end;
1117
1118
1119#################################################
1120#Input:  ()
1121#Output: shows entries in database corelg_carrierAlgDB
1122#################################################
1123corelg.calgDBentries := function()
1124local i, tmp;
1125   if Length(corelg.carrierAlgDB)=0 then corelg.readDBCA(); fi;
1126   for i in ["A","B","C","D","G","E","F"] do
1127      tmp := Collected(List(Filtered(corelg.carrierAlgDB,x->x.type=i),y->y.rank));
1128      Print("for ",i," have ",tmp,"\n");
1129   od;
1130end;
1131
1132
1133
1134#################################################################################
1135#################################################################################
1136#
1137# THE FUNCTIONS FOR WRITING / READING / THE DATABASE realTriples.de
1138# (all real forms of simple complex LAs up to rank 10)
1139#
1140#################################################################################
1141#################################################################################
1142
1143
1144#################################################
1145#Input:  type and rank
1146#Output: adds all nilpotent orbits of given LA to
1147#        database realTriples.db
1148#################################################
1149corelg.WriteRealNilpotentOrbitsToDB := function(type, rank)
1150local form, res, triples, f, new, tr, T, newtr, L, LSF, tmp, cf, i, cnt, cb, path;
1151
1152   if Length(corelg.realtriplesDB)=0 then corelg.readDBTriples(); fi;
1153
1154   form := corelg.NonCompactRealFormsOfSimpleLieAlgebra(type,rank);
1155   for f in form do
1156      if ForAny(corelg.realtriplesDB, x->
1157                x.form = RealFormParameters(f.liealg)) then
1158         Info(InfoCorelg,4,"form ",RealFormParameters(f.liealg)," already in DB");
1159      else
1160         L    := f.liealg;
1161         LSF  := f.liealgSF;
1162         cb   := BasisNC(LSF,corelg.myflat(ChevalleyBasis(LSF)));
1163         new  := rec( form := RealFormParameters(f.liealg), triples :=[]);
1164         tr   := corelg.RealCayleyTriplesOfRealForm(f);
1165         if not tr.tobedone=[] then
1166            Error("sth wrong, there are entries in tobedone!");
1167         fi;
1168         T   := SignatureTable(L);
1169         cnt := 1;
1170         for i in tr.triples.principal do
1171            Info(InfoCorelg,4," principal triple ",cnt," of ",Length(tr.triples.principal));
1172            cnt         := cnt + 1;
1173            newtr       := rec();
1174            cf          := List(i.realsl2,x->Coefficients(Basis(LSF),x));
1175            tmp         := List(cf,x->Filtered([1..Length(x)],j->not x[j]=Zero(SqrtField)));
1176            newtr.rct   := List([1..3],x->Flat(List(tmp[x],y->[y,cf[x][y]])));
1177            cf          := List(i.realsl2,x->Coefficients(cb,x));
1178            tmp         := List(cf,x->Filtered([1..Length(x)],j->not x[j]=Zero(SqrtField)));
1179            newtr.rctcb := List([1..3],x->Flat(List(tmp[x],y->[y,cf[x][y]])));
1180            newtr.cdims := i.cdims;
1181            newtr.princ := true;
1182            newtr.wdd   := corelg.WDD(L,
1183                               List(Coefficients(Basis(LSF),i.realsl2[2]),
1184                                    SqrtFieldEltToCyclotomic)*Basis(L),
1185                               T);
1186            Add(new.triples,newtr);
1187         od;
1188         cnt := 1;
1189         for i in tr.triples.nonprincipal do
1190            Info(InfoCorelg,4," nonprincipal triple ",cnt," of ",Length(tr.triples.nonprincipal));
1191            cnt         := cnt + 1;
1192            newtr       := rec();
1193            cf          := List(i.realsl2,x->Coefficients(Basis(LSF),x));
1194            tmp         := List(cf,x->Filtered([1..Length(x)],j->not x[j]=Zero(SqrtField)));
1195            newtr.rct   := List([1..3],x->Flat(List(tmp[x],y->[y,cf[x][y]])));
1196            cf          := List(i.realsl2,x->Coefficients(cb,x));
1197            tmp         := List(cf,x->Filtered([1..Length(x)],j->not x[j]=Zero(SqrtField)));
1198            newtr.rctcb := List([1..3],x->Flat(List(tmp[x],y->[y,cf[x][y]])));
1199            newtr.cdims := i.cdims;
1200            newtr.princ := false;
1201            newtr.wdd   := corelg.WDD(L,
1202                               List(Coefficients(Basis(LSF),i.realsl2[2]),
1203                                    SqrtFieldEltToCyclotomic)*Basis(L),
1204                               T);
1205            Add(new.triples,newtr);
1206         od;
1207         ReadPackage( "corelg", "gap/realTriples.db" );
1208         Info(InfoCorelg,4,"  re-read corelg.realtriplesDB");
1209         Add(corelg.realtriplesDB,new);
1210       ##path := Concatenation(LOADED_PACKAGES.corelg[1],"/gap/realTriples.db");
1211         path := Filename(DirectoriesPackageLibrary("corelg","gap"),"realTriples.db");
1212         PrintTo(path,"corelg.realtriplesDB:=");
1213         AppendTo(path,corelg.realtriplesDB);
1214         AppendTo(path,";");
1215         Info(InfoCorelg,4,"  wrote new entry to corelg.realtriplesDB");
1216      fi;
1217   od;
1218   return true;
1219end;
1220
1221
1222
1223
1224
1225
1226##############################################################################
1227##
1228##  displays the parameters of the real forms (of type <type>) for which the
1229##  database contains contains its real nilpotent orbits
1230##
1231corelg.RealNilpotentOrbitsInDatabase := function(arg)
1232local i, tmp, t;
1233   if Length(corelg.realtriplesDB)=0 then corelg.readDBTriples(); fi;
1234   if Length(arg) = 1 then
1235      t := [arg[1]];
1236   else
1237      t := ["A","B","C","D","G","E","F"];
1238   fi;
1239   for i in t do
1240      tmp := Filtered(corelg.realtriplesDB,x->x.form[1]=i);
1241      Print("Triples of type ",i,"\n");
1242      for i in List(tmp,x->x.form) do Display(i); od;
1243   od;
1244end;
1245
1246
1247
1248##############################################################################
1249##  returns all real nilpotent orbits in real form L, reads orbits reps from database:
1250##  at the moment, the database contains A2-A8, B2-B10, C2-C10, D4-D8, F4, G2, E6-E8
1251##
1252corelg.RealNilpotentOrbitsFromDatabase := function(LL)
1253local type, rank, pars,param, i,  res, kacs, L, LSF, form, new, dim,orb, neworb,
1254      K, P, ff, ee, hh, tmp, sigma, theta, n, k, makeVec, o, forms, iso, cd,cg, H,
1255      h,e,f,cf, db;
1256
1257   Info(InfoCorelg,1,"start RealNilpotentOrbitsFromDatabase");
1258   if Length(corelg.realtriplesDB)=0 then
1259      corelg.readDBTriples();
1260   fi;
1261
1262   if not LeftActingDomain(LL)=SqrtField then
1263     Error("need LA over SqrtField");
1264   fi;
1265
1266   tmp   := VoganDiagram(LL);
1267   param := tmp!.param;
1268   if Length(param)>1 then
1269      Error("nilpotent orbits only for simple LAs");
1270   fi;
1271   param := [param[1][1],param[1][2]];
1272   Add(param,ShallowCopy(Signs(tmp)));
1273   Add(param,PermInvolution(tmp));
1274
1275  #compact form?
1276   if IdRealForm(LL)[3] = 1 then
1277      return [];
1278   fi;
1279
1280  # deal with case A1?
1281  if param[1]="A" and param[2]=1 then
1282     new :=[];
1283     H   := MaximallyNonCompactCartanSubalgebra(LL);
1284     cd  := CartanDecomposition(LL);
1285     cg  := CanonicalGenerators(RootsystemOfCartanSubalgebra(LL,H));
1286     h   := cg[3][1];
1287     e   := cg[1][1];
1288     f   := cg[2][1];
1289     cf  := Coefficients(Basis(SubspaceNC(LL,[h],"basis"),[h]),-e*cd.CartanInv(e))[1];
1290     e   := (1/Sqrt(cf))*e;
1291     f   := -cd.CartanInv(e);
1292     if not e*f=h or not h*e=2*e or not h*f=-2*f or not cd.CartanInv(e)=-f then
1293        Error("wrong real triple");
1294     fi;
1295     o := NilpotentOrbit( LL, [2] );
1296     SetRealCayleyTriple(o, [e,h,f]);
1297     SetInvariants(o, rec(wdd := [2]));
1298     Add(new,o);
1299     e := -e;
1300     f := -cd.CartanInv(e);
1301     if not e*f=h or not h*e=2*e or not h*f=-2*f or not cd.CartanInv(e)=-f then
1302        Error("wrong real triple");
1303     fi;
1304     o := NilpotentOrbit( LL, [2] );
1305     SetRealCayleyTriple(o, [e,h,f]);
1306     SetInvariants(o, rec(wdd := [2]));
1307     Add(new,o);
1308     return new;
1309  fi;
1310
1311
1312
1313   new := rec();
1314   db  := First(corelg.realtriplesDB,x-> x.form = param);
1315   if db = fail then
1316      Error("cannot find entry with these parameters",param);
1317   fi;
1318
1319   if IsBound(LL!.std) and LL!.std then
1320      Info(InfoCorelg,2,"  don't have to construct isomorphism...");
1321      L := LL;
1322      n := Dimension(L);
1323      iso := IdentityMapping(L);
1324  else
1325      L := RealFormById(param[1],param[2],IdRealForm(LL)[3],SqrtField);
1326      n := Dimension(L);
1327      VoganDiagram(L);
1328      Info(InfoCorelg,2,"  construct isomorphism...");
1329      iso    := IsomorphismOfRealSemisimpleLieAlgebras(L,LL);
1330      Info(InfoCorelg,2,"  ...done");
1331   fi;
1332
1333   new.form   := rec(type:=param[1], rank:=param[2], liealgSF := LL);
1334   Info(InfoCorelg,2,"  read triples...");
1335
1336  #writes compressed coef vector to coef vector
1337   makeVec := function(v)
1338   local vec,i;
1339      vec := ListWithIdenticalEntries(n,Zero(SqrtField));
1340      for i in [1..Length(v)/2] do
1341         vec[v[2*i-1]] := v[2*i]*One(SqrtField);
1342      od;
1343      return vec;
1344   end;
1345
1346   new.nilpotentOrbits := List(db.triples, x->
1347                       rec(rct   := List(x.rct,i->Image(iso,makeVec(i)*Basis(L))),
1348                           rctcb := List(x.rctcb,makeVec),
1349                           cdims := x.cdims,
1350                           princ := x.princ,
1351                           wdd   := x.wdd));
1352
1353   for i in [1..Length(new.nilpotentOrbits)] do
1354      tmp := new.nilpotentOrbits[i];
1355      o   := NilpotentOrbit( LL, tmp.wdd );
1356      SetRealCayleyTriple(o, tmp.rct);
1357      SetInvariants(o, rec(wdd             := tmp.wdd,
1358                           carrierAlgebra  := rec(dims   := tmp.cdims,
1359                                               principal := tmp.princ)));
1360     #SetCoefficientsWRTChevBasis( o, tmp.rctcb);
1361      new.nilpotentOrbits[i] := o;
1362   od;
1363   sigma := RealStructure(LL);
1364   theta := CartanDecomposition(LL).CartanInv;
1365
1366   Info(InfoCorelg,2,"  all triples constructed, now test them");
1367   for tmp in new.nilpotentOrbits do
1368      ff := RealCayleyTriple(tmp)[1];
1369      hh := RealCayleyTriple(tmp)[2];
1370      ee := RealCayleyTriple(tmp)[3];
1371      if not (hh*ff = -2*ff and hh*ee=2*ee and ee*ff=hh) or
1372         not theta(ee)=-ff or
1373         not  RealCayleyTriple(tmp) = List(RealCayleyTriple(tmp),sigma) then
1374            Error("not a real sl2 triple");
1375      fi;
1376   Info(InfoCorelg,2,"  all triples OK");
1377   od;
1378   Info(InfoCorelg,1,"end RealNilpotentOrbitsFromDatabase");
1379
1380   return new.nilpotentOrbits;
1381
1382end;
1383
1384
1385#################################################
1386InstallMethod( NilpotentOrbitsOfRealForm,
1387   "for Lie algebras",
1388   true,
1389   [ IsLieAlgebra ], 0, function(L)
1390
1391   if HasNilpotentOrbitsOfRealForm(L) then
1392      return NilpotentOrbitsOfRealForm(L);
1393   fi;
1394
1395   return corelg.RealNilpotentOrbitsFromDatabase(L);
1396end);
1397
1398
1399
1400
1401##############################################################################
1402InstallGlobalFunction(CarrierAlgebraOfNilpotentOrbit, function(L, orb)
1403local sl2, i, j, g0, h, ca, tmp, esp, hm, K, z, t, grad, gr, tt, zz, old;
1404
1405   sl2 := RealCayleyTriple(orb);
1406   h   := sl2[2];
1407   z   := LieCentraliser(L,SubalgebraNC(L,sl2,"basis"));
1408   zz  := LieDerivedSubalgebra(z);
1409   if Dimension(zz)>0 then
1410      t   := MaximallyNonCompactCartanSubalgebra(zz);
1411   else
1412      t := zz;
1413   fi;
1414
1415   tmp := Concatenation(Basis(t),Basis(LieCentre(z)));
1416   if tmp =[] then t:=SubalgebraNC(L,[],"basis"); else  t   := SubalgebraNC(L,tmp);fi;
1417
1418   z   := LieCentraliser(L,t);
1419   hm  := TransposedMat( AdjointMatrix(Basis(z),h) );
1420   esp := [[], [],[]];
1421   i   := 0;
1422   repeat
1423      old := Length(corelg.myflat(esp));
1424      if i=0 then
1425         esp[1][1] := List(NullspaceMat(hm),x->x*Basis(z));
1426      else
1427         esp[2][i/2] := List(NullspaceMat(hm-i*hm^0),x->x*Basis(z));
1428         esp[3][i/2] := List(NullspaceMat(hm+i*hm^0),x->x*Basis(z));
1429      fi;
1430      i := i+2;
1431   until Length(corelg.myflat(esp))=old;
1432
1433   K          := LieDerivedSubalgebra( SubalgebraNC( L, corelg.myflat(esp),"basis"));
1434   grad       := [[],[],[]];
1435   grad[1][1] := BasisVectors( Basis( Intersection(K,SubspaceNC(L,esp[1][1],"basis")) ) );
1436   for i in [1..Length(esp[2])] do
1437      grad[2][i] := BasisVectors( Basis( Intersection(K,SubspaceNC(L,esp[2][i],"basis")) ) );
1438   od;
1439   for i in [1..Length(esp[3])] do
1440      grad[3][i] := BasisVectors( Basis( Intersection(K,SubspaceNC(L,esp[3][i],"basis")) ) );
1441   od;
1442
1443   return rec(liealg := K, grading := grad, wdd := Invariants(orb).wdd, dims := List(esp,x->List(x,Length)));
1444end);
1445
1446
1447
1448#################################################
1449corelg.sortOrbitsByWDD := function(t,r,nr)
1450local L, orbs, wdds, res, i, j, cdims, tot,ok;
1451
1452   L    := RealFormById(t,r,nr);
1453   orbs := corelg.RealNilpotentOrbitsFromDatabase(L);
1454   orbs := List(orbs,x->CarrierAlgebraOfNilpotentOrbit(L,x));
1455   wdds := List(Collected(List(orbs,x->x.wdd)),x->x[1]);
1456   res  := [];
1457   for i in [1..Length(wdds)] do
1458      res[i] := rec(wdd:=wdds[i],
1459      orbs   := List(Filtered(orbs,x->x.wdd=wdds[i]),
1460                     y->rec(ca:=y.dims, orb :=y)));
1461   od;
1462   Print("display only those wdds which at least two orbs with the same calg\n\n");
1463   ok  := 0;
1464   tot := 0;
1465   for i in res do
1466      if Length(i.orbs)>1 then
1467         tot := tot+1;
1468         cdims := List(i.orbs,x->x.ca);
1469         if not IsDuplicateFreeList(cdims) then
1470            Print("orbits with wdd ",i.wdd,":\n");
1471            for j in i.orbs do
1472               Print("   calg with dim ",j.ca,"\n");
1473            od;
1474            Print("\n");
1475         else
1476            ok := ok+1;
1477         fi;
1478      fi;
1479   od;
1480   Print("there are ",tot, " WDDs which have more than one orbits attached\n");
1481   Print(ok," of these have pairwise distinct carrier alg dims\n");
1482   if tot-ok=0 then
1483      Print("Hence ALL orbits can be distinguished by their wdd and calg dims\n");
1484   else
1485      Print("Hence: ",tot-ok," wdds have orbits which cannot be distinguised by their calg dims\n");
1486   fi;
1487
1488   return rec(alg := L, res:=res, data:=[t,r,nr,tot,tot-ok]);
1489end;
1490
1491
1492#################################################
1493corelg.sortOrbitsByDim := function(t,r,nr)
1494local L, orbs, dims, res, i, ok, tot, wdds,j;
1495
1496   L    := RealFormById(t,r,nr);
1497   orbs := corelg.RealNilpotentOrbitsFromDatabase(L);
1498   orbs := List(orbs,x->CarrierAlgebraOfNilpotentOrbit(L,x));
1499
1500   dims := List(Collected(List(orbs,x->x.dims)),x->x[1]);
1501   res  := [];
1502   for i in [1..Length(dims)] do
1503      res[i] := rec(dim  :=dims[i],
1504                    orbs := List(Filtered(orbs,x->x.dims=dims[i]), y->rec(wdd:=y.wdd, orb :=y)));
1505   od;
1506
1507   ok  := 0;
1508   tot := 0;
1509   for i in res do
1510      wdds := Collected(List(i.orbs,x->x.wdd));
1511      Print("dim ",i.dim, " has the following wdds\n");
1512      for i in wdds do Print("    ",i[1],"\n"); od;
1513   od;
1514
1515end;
1516