source: git/Singular/LIB/rinvar.lib @ 4bde6b

spielwiese
Last change on this file since 4bde6b was 4bde6b, checked in by Hans Schoenemann <hannes@…>, 4 years ago
spelling p1
  • Property mode set to 100644
File size: 35.7 KB
Line 
1/////////////////////////////////////////////////////////////////////////////
2version="version rinvar.lib 4.1.2.0 Feb_2019 "; // $Id$
3category="Invariant theory";
4info="
5LIBRARY:  rinvar.lib      Invariant Rings of Reductive Groups
6AUTHOR:   Thomas Bayer,   tbayer@in.tum.de
7          http://wwwmayr.informatik.tu-muenchen.de/personen/bayert/
8          Current Address: Institut fuer Informatik, TU Muenchen
9OVERVIEW:
10 Implementation based on Derksen's algorithm. Written in the scope of the
11 diploma thesis (advisor: Prof. Gert-Martin Greuel) 'Computations of moduli
12 spaces of semiquasihomogenous singularities and an implementation in Singular'
13
14PROCEDURES:
15 HilbertSeries(I, w);           Hilbert series of the ideal I w.r.t. weight w
16 HilbertWeights(I, w);          weighted degrees of the generators of I
17 ImageVariety(I, F);            ideal of the image variety F(variety(I))
18 ImageGroup(G, F);              ideal of G w.r.t. the induced representation
19 InvariantRing(G, Gaction);     generators of the invariant ring of G
20 InvariantQ(f, G, Gaction);     decide if f is invariant w.r.t. G
21 LinearizeAction(G, Gaction);   linearization of the action 'Gaction' of G
22 LinearActionQ(action,s,t);     decide if action is linear in var(s..nvars)
23 LinearCombinationQ(base, f);   decide if f is in the linear hull of 'base'
24 MinimalDecomposition(f,s,t);   minimal decomposition of f (like coef)
25 NullCone(G, act);              ideal of the nullcone of the action 'act' of G
26 ReynoldsImage(RO,f);           image of f under the Reynolds operator 'RO'
27 ReynoldsOperator(G, Gaction);  Reynolds operator of the group G
28 SimplifyIdeal(I[,m,s]);        simplify the ideal I (try to reduce variables)
29
30SEE ALSO: qhmoduli_lib, zeroset_lib
31";
32
33LIB "presolve.lib";
34LIB "elim.lib";
35LIB "zeroset.lib";
36LIB "ring.lib";
37
38///////////////////////////////////////////////////////////////////////////////
39
40proc EquationsOfEmbedding(ideal embedding, int nrs)
41"USAGE:   EquationsOfEmbedding(embedding, s); ideal embedding; int s;
42PURPOSE: compute the ideal of the variety parameterized by 'embedding' by
43         implicitation and change the variables to the old ones.
44RETURN:  ideal
45ASSUME:  nvars(basering) = n, size(embedding) = r and s = n - r.
46         The polynomials of embedding contain only var(s + 1 .. n).
47NOTE:    the result is the Zariski closure of the parameterized variety
48EXAMPLE: example  EquationsOfEmbedding; shows an example
49"
50{
51  ideal tvars;
52
53  for(int i = nrs + 1; i <= nvars(basering); i++) { tvars[i - nrs] = var(i); }
54
55  def RE1 = ImageVariety(ideal(0), embedding);  // implicitation of the parameterization
56  // map F = RE1, tvars;
57        map F = RE1, maxideal(1);
58  return(F(imageid));
59}
60example
61{"EXAMPLE:";  echo = 2;
62  ring R   = 0,(s(1..5), t(1..4)),dp;
63  ideal emb = t(1), t(2), t(3), t(3)^2;
64  ideal I = EquationsOfEmbedding(emb, 5);
65  I;
66}
67
68///////////////////////////////////////////////////////////////////////////////
69
70proc ImageGroup(ideal Grp, ideal Gaction)
71"USAGE:   ImageGroup(G, action); ideal G, action;
72PURPOSE: compute the ideal of the image of G in GL(m,K) induced by the linear
73         action 'action', where G is an algebraic group and 'action' defines
74         an action of G on K^m (size(action) = m).
75RETURN:  ring, a polynomial ring over the same ground field as the basering,
76         containing the ideals 'groupid' and 'actionid'.
77         - 'groupid' is the ideal of the image of G (order <= order of G)
78         - 'actionid' defines the linear action of 'groupid' on K^m.
79NOTE:    'action' and 'actionid' have the same orbits
80         all variables which give only rise to 0's in the m x m matrices of G
81         have been omitted.
82ASSUME:  basering K[s(1..r),t(1..m)] has r + m variables, G is the ideal of an
83         algebraic group and F is an action of G on K^m. G contains only the
84         variables s(1)...s(r). The action 'action' is given by polynomials
85         f_1,...,f_m in basering, s.t. on the ring level we have
86         K[t_1,...,t_m] --> K[s_1,...,s_r,t_1,...,t_m]/G
87         t_i   -->  f_i(s_1,...,s_r,t_1,...,t_m)
88EXAMPLE: example ImageGroup; shows an example
89"
90{
91  int i, j, k, newVars, nrt, imageSize, dbPrt;
92  ideal matrixEntries;
93  matrix coMx;
94  poly tVars;
95  string ringSTR1, ringSTR2, order;
96
97  dbPrt = printlevel-voice+2;
98  dbprint(dbPrt, "Image Group of " + string(Grp) + ", action =  "
99                                   + string(Gaction));
100  def RIGB = basering;
101  string @mPoly = string(minpoly);
102  tVars = 1;
103  k = 0;
104
105  // compute the representation of G induced by Gaction, i.e., a matrix
106  // of size(Gaction) x size(Gaction) and polynomials in s(1),...,s(r) as
107  // entries
108  // the matrix is represented as the list 'matrixEntries' where
109  // the entries which are always 0 are omittet.
110
111  for(i = 1; i <= ncols(Gaction); i++) {
112    tVars = tVars * var(i + nvars(basering) - ncols(Gaction));
113  }
114  for(i = 1; i <= ncols(Gaction); i++){
115    coMx = coef(Gaction[i], tVars);
116    for(j = 1; j <= ncols(coMx); j++){
117      k++;
118      matrixEntries[k] = coMx[2, j];
119    }
120  }
121  newVars = size(matrixEntries);
122  nrt = ncols(Gaction);
123
124  // this matrix defines an embedding of G into GL(m, K).
125  // in the next step the ideal of this image is computed
126  // note that we have omitted all variables which give give rise
127  // only to 0's. Note that z(1..newVars) are slack variables
128
129  def RIGR=addNvarsTo(basering,newVars,"z",1); setring RIGR;
130  ideal I1, I2, Gn, G, F, mEntries, newGaction;
131  G = imap(RIGB, Grp);
132  F = imap(RIGB, Gaction);
133  mEntries = imap(RIGB, matrixEntries);
134
135  // prepare the ideals needed to compute the image
136  // and compute the new action of the image on K^m
137
138  for(i=1;i<=size(mEntries);i++){ I1[i] = var(i + nvars(RIGB))-mEntries[i]; }
139  I1 = std(I1);
140
141  for(i = 1; i <= ncols(F); i++) { newGaction[i] = reduce(F[i], I1); }
142  I2 = G, I1;
143  I2 = std(I2);
144  Gn = nselect(I2, 1.. nvars(RIGB));
145  imageSize = ncols(Gn);
146
147  // create a new basering which might contain more variables
148  // s(1..newVars) as the original basering and map the ideal
149  // Gn (contains only z(1..newVars)) to this ring
150
151  list l1; 
152  for (int zz = 1; zz <= newVars; zz++)
153  {
154   l1[size(l1)+1] = "s("+string(zz)+")";
155  }
156  for (int yy = 1; yy <= nrt; yy++)
157  {
158   l1[size(l1)+1] = "t("+string(yy)+")";
159  }
160  ring RIGS = create_ring(ringlist(basering)[1], l1, "lp", "no_minpoly");
161  execute("minpoly = number(" + @mPoly + ");");
162  ideal mapIdeal, groupid, actionid;
163  int offset;
164
165  // construct the map F : RIGB -> RIGS
166
167  for(i=1;i<=nvars(RIGB)-nrt;i++) { mapIdeal[i] = 0;}            // s(i)-> 0
168  offset = nvars(RIGB) - nrt;
169  for(i=1;i<=nrt;i++) { mapIdeal[i+offset] = var(newVars + i);}  // t(i)->t(i)
170  offset = offset + nrt;
171  for(i=1;i<=newVars;i++) { mapIdeal[i + offset] = var(i);}      // z(i)->s(i)
172
173  // map Gn and newGaction to RIGS
174
175  map F = RIGR, mapIdeal;
176  groupid = F(Gn);
177  actionid = F(newGaction);
178  export groupid, actionid;
179  dbprint(dbPrt+1, "
180// 'ImageGroup' created a new ring.
181// To see the ring, type (if the name 'R' was assigned to the return value):
182     show(R);
183// To access the ideal of the image of the input group and to access the new
184// action of the group, type
185     setring R;  groupid; actionid;
186");
187  setring RIGB;
188  return(RIGS);
189}
190example
191{"EXAMPLE:";  echo = 2;
192  ring B   = 0,(s(1..2), t(1..2)),dp;
193  ideal G = s(1)^3-1, s(2)^10-1;
194  ideal action = s(1)*s(2)^8*t(1), s(1)*s(2)^7*t(2);
195  def R = ImageGroup(G, action);
196  setring R;
197  groupid;
198  actionid;
199}
200
201///////////////////////////////////////////////////////////////////////////////
202
203proc HilbertWeights(ideal I,intvec wt)
204"USAGE:   HilbertWeights(I, w); ideal I, intvec wt
205PURPOSE: compute the weights of the "slack" variables needed for the
206         computation of the algebraic relations of the generators of 'I' s.t.
207         the Hilbert driven 'std' can be used.
208RETURN: intvec
209ASSUME: basering = K[t_1,...,t_m,...], 'I' is quasihomogenous w.r.t. 'w' and
210        contains only polynomials in t_1,...,t_m
211"
212{
213  int offset = size(wt);
214  intvec wtn = wt;
215
216  for(int i = 1; i <= size(I); i++) { wtn[offset + i] = deg(I[i], wt); }
217  return(wtn);
218}
219
220///////////////////////////////////////////////////////////////////////////////
221
222proc HilbertSeries(ideal I,intvec wt)
223"USAGE:   HilbertSeries(I, w); ideal I, intvec wt
224PURPOSE: compute the polynomial p of the Hilbert Series, represented by p/q, of
225         the ring K[t_1,...,t_m,y_1,...,y_r]/I1 where 'w' are the weights of
226         the variables, computed, e.g., by 'HilbertWeights', 'I1' is of the
227         form I[1] - y_1,...,I[r] - y_r and is quasihomogenous w.r.t. 'w'
228RETURN:  intvec
229NOTE:    the leading 0 of the result does not belong to p, but is needed in
230         the Hilbert driven 'std'.
231"
232{
233  int i;
234  intvec hs1;
235  matrix coMx;
236  poly f = 1;
237
238  for(i = 1; i <= ncols(I); i++) { f = f * (1 - var(1)^deg(I[i], wt));}
239  coMx = coeffs(f, var(1));
240  for(i = 1; i <= deg(f) + 1; i++) {
241    hs1[i] = int(coMx[i, 1]);
242  }
243  hs1[size(hs1) + 1] = 0;
244  return(hs1);
245}
246///////////////////////////////////////////////////////////////////////////////
247
248proc HilbertSeries1(wt)
249"USAGE:   HilbertSeries1(wt); ideal I, intvec wt
250PURPOSE: compute the polynomial p of the Hilbert Series represented by p/q of
251         the ring K[t_1,...,t_m,y_1,...,y_r]/I where I is a complete inter-
252         section and the generator I[i] has degree wt[i]
253RETURN:  poly
254"
255{
256  int i, j;
257  intvec hs1;
258  matrix ma;
259  poly f = 1;
260
261  for(i = 1; i <= size(wt); i++) { f = f * (1 - var(1)^wt[i]);}
262  ma = coef(f, var(1));
263  j = ncols(ma);
264  for(i = 0; i <= deg(f); i++) {
265    if(var(1)^i == ma[1, j]) {
266      hs1[i + 1] = int(ma[2, j]);
267      j--;
268    }
269    else { hs1[i + 1] = 0; }
270  }
271  hs1[size(hs1) + 1] = 0;
272  return(hs1);
273}
274
275///////////////////////////////////////////////////////////////////////////////
276
277proc ImageVariety(ideal I,ideal F, list #)
278"USAGE:   ImageVariety(ideal I, F [, w]);ideal I; F is a list/ideal, intvec w.
279PURPOSE: compute the Zariski closure of the image of the variety of I under
280         the morphism F.
281NOTE:    if 'I' and 'F' are quasihomogenous w.r.t. 'w' then the Hilbert-driven
282         'std' is used.
283RETURN:  polynomial ring over the same ground field, containing the ideal
284         'imageid'. The variables are Y(1),...,Y(k) where k = size(F)
285         - 'imageid' is the ideal of the Zariski closure of F(X) where
286           X is the variety of I.
287EXAMPLE: example ImageVariety; shows an example
288"
289{
290  int i, dbPrt, nrNewVars;
291  intvec wt, wth, hs1;
292  def RARB = basering;
293  nrNewVars = ncols(F);
294
295  dbPrt = printlevel-voice+2;
296  dbprint(dbPrt, "ImageVariety of " + string(I) + " under the map " + string(F));
297
298  if(size(#) > 0) { wt = #[1]; }
299
300  // create new ring for elimination, Y(1),...,Y(m) are slack variables.
301
302  //string @mPoly = string(minpoly);
303  def RAR1=addNvarsTo(basering,nrNewVars,"Y",1); setring RAR1;
304  list RAR2l=ringlist(RAR1);
305  list RAR2ll=RAR2l[2];
306  RAR2ll=RAR2ll[size(RAR2ll)-nrNewVars+1..size(RAR2ll)];
307  RAR2l[2]=RAR2ll;
308  RAR2l[3]=list(list("dp",1:nrNewVars),list("C",0));
309  def RAR2=ring(RAR2l);
310
311  ideal I, J1, J2, Fm;
312
313  I = imap(RARB, I);
314  Fm = imap(RARB, F);
315
316  if(size(wt) > 1) {
317    wth = HilbertWeights(Fm, wt);
318    hs1 = HilbertSeries(Fm, wt);
319  }
320
321  // get the ideal of the graph of F : X -> Y and compute a standard basis
322
323  for(i = 1; i <= nrNewVars; i++) { J1[i] = var(i + nvars(RARB)) - Fm[i];}
324  J1 = J1, I;
325  if(size(wt) > 1) {
326    J1 = std(J1, hs1, wth);  // Hilbert-driven algorithm
327  }
328  else {
329    J1 = std(J1);
330  }
331
332  // forget all elements which contain other than the slack variables
333
334  J2 = nselect(J1, 1.. nvars(RARB));
335
336  setring RAR2;
337  ideal imageid = imap(RAR1, J2);
338  export(imageid);
339     dbprint(dbPrt+1, "
340// 'ImageVariety' created a new ring.
341// To see the ring, type (if the name 'R' was assigned to the return value):
342     show(R);
343// To access the ideal of the image variety, type
344     setring R;  imageid;
345");
346  setring RARB;
347  return(RAR2);
348}
349example
350{"EXAMPLE:";  echo = 2;
351  ring B   = 0,(x,y),dp;
352  ideal I  = x4 - y4;
353  ideal F  = x2, y2, x*y;
354  def R = ImageVariety(I, F);
355  setring R;
356  imageid;
357}
358
359///////////////////////////////////////////////////////////////////////////////
360
361proc LinearizeAction(ideal Grp,def Gaction, int nrs)
362"USAGE:   LinearizeAction(G,action,r); ideal G, action; int r
363PURPOSE: linearize the group action 'action' and find an equivariant embedding
364         of K^m where m = size(action).
365ASSUME:  G contains only variables var(1..r) (r = nrs)
366basering = K[s(1..r),t(1..m)], K = Q or K = Q(a) and minpoly != 0.
367RETURN:  polynomial ring containing the ideals 'actionid', 'embedid', 'groupid'
368         - 'actionid' is the ideal defining the linearized action of G
369         - 'embedid' is a parameterization of an equivariant embedding (closed)
370         - 'groupid' is the ideal of G in the new ring
371NOTE:    set printlevel > 0 to see a trace
372EXAMPLE: example LinearizeAction; shows an example
373"
374{
375  def altring = basering;
376  int i, j, k, ok, loop, nrt, sizeOfDecomp, dbPrt;
377  intvec wt;
378  ideal action, basis, G, reduceIdeal;
379  matrix decompMx;
380  poly actCoeff;
381  string str, order;
382
383  dbPrt = printlevel-voice+2;
384  dbprint(dbPrt, "LinearizeAction " + string(Gaction));
385  def RLAR = basering;
386  string @mPoly = string(minpoly);
387  order = ordstr(basering);
388  nrt = ncols(Gaction);
389  for(i = 1; i <= nrs; i++) { wt[i] = 0;}
390  for(i = nrs + 1; i <= nrs + nrt; i++) { basis[i - nrs] = var(i); wt[i] = 1;}
391  dbprint(dbPrt, "  basis = " + string(basis));
392  if(attrib(Grp, "isSB")) { G = Grp; }
393  else { G = std(Grp); }
394  reduceIdeal = G;
395  action = Gaction;
396  loop = 1;
397  i = 1;
398
399  // check if each component of 'action' is linear in t(1),...,t(nrt).
400
401  while(loop){
402    if(deg(action[i], wt) <= 1) {
403      sizeOfDecomp = 0;
404      dbprint(dbPrt, "  " + string(action[i]) + " is linear");
405    }
406    else {   // action[i] is not linear
407
408    // compute the minimal decomposition of action[i]
409    // action[i]=decompMx[1,1]*decompMx[2,1]+ ... +decompMx[1,k]*decompMx[2,k]
410    // decompMx[1,j] contains variables var(1)...var(nrs)
411    // decompMx[2,j] contains variables var(nrs + 1)...var(nvars(basering))
412
413    dbprint(dbPrt, "  " + string(action[i])
414                   + " is not linear, a minimal decomposition is :");
415    decompMx = MinimalDecomposition(action[i], nrs, nrt);
416    sizeOfDecomp = ncols(decompMx);
417    dbprint(dbPrt, decompMx);
418
419    for(j = 1; j <= sizeOfDecomp; j++) {
420      // check if decompMx[2,j] is a linear combination of basis elements
421      actCoeff = decompMx[2, j];
422      ok = LinearCombinationQ(basis, actCoeff, nrt + nrs);
423      if(ok == 0) {
424
425        // nonlinear element, compute new component of the action
426
427        dbprint(dbPrt, "  the polynomial " + string(actCoeff)
428                   + " is not a linear combination of the elements of basis");
429        nrt++;
430        if(defined(RLAB)) { kill RLAB;}
431        def RLAB = basering;
432        if(defined(RLAR)) { kill RLAR;}
433        ring RLAR = create_ring(ringlist(basering)[1], "(" + varstr(basering)+ ",t(" + string(nrt) + "))", "(" + order + ")", "no_minpoly");
434        execute("minpoly = number(" + @mPoly + ");");
435
436        ideal basis, action, G, reduceIdeal;
437        matrix decompMx;
438        map F;
439        poly actCoeff;
440
441        wt[nrs + nrt] = 1;
442        basis = imap(RLAB, basis), imap(RLAB, actCoeff);
443        action = imap(RLAB, action);
444        decompMx = imap(RLAB, decompMx);
445        actCoeff = imap(RLAB, actCoeff);
446        G = imap(RLAB, G);
447        attrib(G, "isSB", 1);
448        reduceIdeal = imap(RLAB, reduceIdeal), actCoeff - var(nrs + nrt);
449
450        // compute action on the new basis element
451
452        for(k = 1; k <= nrs; k++) { F[k] = 0;}
453        for(k = nrs + 1; k < nrs + nrt; k++) { F[k] = action[k - nrs];}
454        actCoeff = reduce(F(actCoeff), G);
455        action[ncols(action) + 1] = actCoeff;
456        dbprint(dbPrt, "  extend basering by " + string(var(nrs + nrt)));
457        dbprint(dbPrt, "  new basis = " + string(basis));
458        dbprint(dbPrt, "  action of G on new basis element = "
459                    + string(actCoeff));
460        dbprint(dbPrt, "  decomp : " + string(decompMx[2, j]) + " -> "
461                    + string(var(nrs + nrt)));
462      } // end if
463      else {
464        dbprint(dbPrt, "  the polynomial " + string(actCoeff)
465                    + " is a linear combination of the elements of basis");
466      }
467    } // end for
468    reduceIdeal = std(reduceIdeal);
469    action[i] = reduce(action[i], reduceIdeal);
470    } // end else
471    if(i < ncols(action)) { i++;}
472    else {loop = 0;}
473  } // end while
474  if(defined(actionid)) { kill actionid; }
475  ideal actionid, embedid, groupid;
476  actionid = action;
477  embedid = basis;
478  groupid = G;
479  export actionid, embedid, groupid;
480dbprint(dbPrt+1, "
481// 'LinearizeAction' created a new ring.
482// To see the ring, type (if the name 'R' was assigned to the return value):
483     show(R);
484// To access the new action and the equivariant embedding, type
485     setring R; actionid; embedid; groupid
486");
487  setring altring;
488  return(RLAR);
489}
490example
491{"EXAMPLE:";  echo = 2;
492  ring B   = 0,(s(1..5), t(1..3)),dp;
493  ideal G =  s(3)-s(4), s(2)-s(5), s(4)*s(5), s(1)^2*s(4)+s(1)^2*s(5)-1, s(1)^2*s(5)^2-s(5), s(4)^4-s(5)^4+s(1)^2, s(1)^4+s(4)^3-s(5)^3, s(5)^5-s(1)^2*s(5);
494  ideal action = -s(4)*t(1)+s(5)*t(1), -s(4)^2*t(2)+2*s(4)^2*t(3)^2+s(5)^2*t(2), s(4)*t(3)+s(5)*t(3);
495  LinearActionQ(action, 5);
496  def R = LinearizeAction(G, action, 5);
497  setring R;
498  R;
499  actionid;
500  embedid;
501  groupid;
502  LinearActionQ(actionid, 5);
503}
504
505///////////////////////////////////////////////////////////////////////////////
506
507proc LinearActionQ(def Gaction, int nrs)
508"USAGE:   LinearActionQ(action,nrs); ideal action, int nrs
509PURPOSE: check whether the action defined by 'action' is linear w.r.t. the
510         variables var(nrs + 1...nvars(basering)).
511RETURN:  0 action not linear
512         1 action is linear
513EXAMPLE: example LinearActionQ; shows an example
514"
515{
516  int i, nrt, loop;
517  intvec wt;
518
519  nrt = ncols(Gaction);
520  for(i = 1; i <= nrs; i++) { wt[i] = 0;}
521  for(i = nrs + 1; i <= nrs + nrt; i++) { wt[i] = 1;}
522  loop = 1;
523  i = 1;
524  while(loop)
525  {
526    if(deg(Gaction[i], wt) > 1) { loop = 0; }
527    else
528    {
529      i++;
530      if(i > ncols(Gaction)) { loop = 0;}
531    }
532  }
533  return(i > ncols(Gaction));
534}
535example
536{"EXAMPLE:";  echo = 2;
537  ring R   = 0,(s(1..5), t(1..3)),dp;
538  ideal G =  s(3)-s(4), s(2)-s(5), s(4)*s(5), s(1)^2*s(4)+s(1)^2*s(5)-1,
539             s(1)^2*s(5)^2-s(5), s(4)^4-s(5)^4+s(1)^2, s(1)^4+s(4)^3-s(5)^3,
540             s(5)^5-s(1)^2*s(5);
541  ideal Gaction = -s(4)*t(1)+s(5)*t(1),
542                  -s(4)^2*t(2)+2*s(4)^2*t(3)^2+s(5)^2*t(2),
543                   s(4)*t(3)+s(5)*t(3);
544  LinearActionQ(Gaction, 5);
545  LinearActionQ(Gaction, 8);
546}
547
548///////////////////////////////////////////////////////////////////////////////
549
550proc LinearCombinationQ(ideal I, poly f)
551"USAGE:   LinearCombination(I, f); ideal I, poly f
552PURPOSE: test whether f can be written as a linear combination of the generators of I.
553RETURN:  0 f is not a linear combination
554         1 f is a linear combination
555"
556{
557  int i, loop, sizeJ;
558  ideal J;
559
560  J = I, f;
561  sizeJ = size(J);
562
563  def RLC = ImageVariety(ideal(0), J);   // compute algebraic relations
564  setring RLC;
565  matrix coMx;
566  poly relation = 0;
567
568  loop = 1;
569  i = 1;
570  while(loop)
571  { // look for a linear relation containing Y(nr)
572    if(deg(imageid[i]) == 1)
573    {
574      coMx = coef(imageid[i], var(sizeJ));
575      if(coMx[1,1] == var(sizeJ))
576      {
577        relation = imageid[i];
578        loop = 0;
579      }
580    }
581    else
582    {
583      i++;
584      if(i > ncols(imageid)) { loop = 0;}
585    }
586  }
587  return(i <= ncols(imageid));
588}
589
590///////////////////////////////////////////////////////////////////////////////
591
592proc InvariantRing(ideal G, ideal action, list #)
593"USAGE:   InvariantRing(G, Gact [, opt]); ideal G, Gact; int opt
594PURPOSE: compute generators of the invariant ring of G w.r.t. the action 'Gact'
595ASSUME:  G is a finite group and 'Gact' is a linear action.
596RETURN:  ring R; this ring comes with the ideals 'invars' and 'groupid' and
597         with the poly 'newA':
598         - 'invars' contains the algebra generators of the invariant ring
599         - 'groupid' is the ideal of G in the new ring
600         - 'newA' is the new representation of the primitive root of the
601           minimal polynomial of the ring which was active when calling the
602           procedure (if the minpoly did not change, 'newA' is set to 'a').
603NOTE:    the minimal polynomial of the output ring depends on some random
604         choices
605EXAMPLE: example InvariantRing; shows an example
606"
607{
608  int i, ok, dbPrt, noReynolds, primaryDec;
609  ideal invarsGens, groupid;
610
611  dbPrt = printlevel-voice+2;
612
613  if(size(#) > 0) { primaryDec = #[1]; }
614  else { primaryDec = 0; }
615
616  dbprint(dbPrt, "InvariantRing of " + string(G));
617  dbprint(dbPrt, " action  = " + string(action));
618
619  if(!attrib(G, "isSB")) { groupid = std(G);}
620  else { groupid = G; }
621
622  // compute the nullcone of G by means of Derksen's algorithm
623
624  invarsGens = NullCone(groupid, action);  // compute nullcone of linear action
625  dbprint(dbPrt, " generators of zero-fibre ideal are " + string(invarsGens));
626
627  // make all generators of the nullcone invariant
628  // if necessary, compute the Reynolds Operator, i.e., find all elements
629  // of the variety defined by G. It might be necessary to extend the
630  // ground field.
631
632  def IRB = basering;
633  if(defined(RIRR)) { kill RIRR;}
634  def RIRR = basering;
635  setring RIRR;
636//  export(RIRR);
637//  export(invarsGens);
638  noReynolds = 1;
639  dbprint(dbPrt, " nullcone is generated by " + string(size(invarsGens)));
640   dbprint(dbPrt, " degrees = " + string(maxdeg(invarsGens)));
641  for(i = 1; i <= ncols(invarsGens); i++){
642    ok = InvariantQ(invarsGens[i], groupid, action);
643    if(ok) { dbprint(dbPrt, string(i) + ": poly " + string(invarsGens[i])
644                                      + " is invariant");}
645    else {
646      if(noReynolds) {
647
648        // compute the Reynolds operator and change the ring !
649        noReynolds = 0;
650        def RORN = ReynoldsOperator(groupid, action, primaryDec);
651        setring RORN;
652        ideal groupid = std(id);
653        attrib(groupid, "isSB", 1);
654        ideal action = actionid;
655        setring RIRR;
656        string parName, minPoly;
657        if(npars(basering) == 0) {
658          parName = "a";
659          minPoly = "0";
660        }
661        else {
662          parName = parstr(basering);
663          minPoly = string(minpoly);
664        }
665        ring RA1 = create_ring(0, "(" + varstr(basering) + "," + parName + ")", "lp");
666        if (minPoly!="0") { execute("ideal mpoly = std(" + minPoly + ");"); }
667        ideal I = imap(RIRR,invarsGens);
668        setring RORN;
669        map Phi = RA1, maxideal(1);
670        Phi[nvars(RORN) + 1] = newA;
671        ideal invarsGens = Phi(I);
672        kill Phi,RA1,RIRR;
673// end of ersetzt durch
674
675      }
676      dbprint(dbPrt, string(i) + ": poly " + string(invarsGens[i])
677                               + " is NOT invariant");
678      invarsGens[i] = ReynoldsImage(ROelements, invarsGens[i]);
679      dbprint(dbPrt, " --> " + string(invarsGens[i]));
680    }
681  }
682  for(i = 1; i <= ncols(invarsGens); i++){
683    ok =  InvariantQ(invarsGens[i], groupid, action);
684    if(ok) { dbprint(dbPrt, string(i) + ": poly " + string(invarsGens[i])
685                                      + " is invariant"); }
686    else { print(string(i) + ": Fatal Error with Reynolds ");}
687  }
688  if(noReynolds == 0) {
689    def RIRS = RORN;
690    setring RIRS;
691    kill RORN;
692    export groupid;
693  }
694  else {
695    def RIRS = RIRR;
696    kill RIRR;
697    setring RIRS;
698    export groupid;
699  }
700  ideal invars = invarsGens;
701  kill invarsGens;
702  if (defined(ROelements)) { kill ROelements,actionid,theZeroset,id; }
703  export invars;
704  dbprint(dbPrt+1, "
705// 'InvariantRing' created a new ring.
706// To see the ring, type (if the name 'R' was assigned to the return value):
707     show(R);
708// To access the generators of the invariant ring type
709     setring R; invars;
710// Note that the input group G is stored in R as the ideal 'groupid'; to
711// see it, type
712    groupid;
713// Note that 'InvariantRing' might change the minimal polynomial
714// The representation of the algebraic number is given by 'newA'
715");
716  setring IRB;
717  return(RIRS);
718}
719example
720{"EXAMPLE:";  echo = 2;
721  ring B = 0, (s(1..2), t(1..2)), dp;
722  ideal G = -s(1)+s(2)^3, s(1)^4-1;
723  ideal action = s(1)*t(1), s(2)*t(2);
724
725  def R = InvariantRing(std(G), action);
726  setring R;
727  invars;
728}
729
730///////////////////////////////////////////////////////////////////////////////
731
732proc InvariantQ(poly f, ideal G,def action)
733"USAGE:   InvariantQ(f, G, action); poly f; ideal G, action
734PURPOSE: check whether the polynomial f is invariant w.r.t. G, where G acts via
735         'action' on K^m.
736ASSUME:  basering = K[s_1,...,s_m,t_1,...,t_m] where K = Q of K = Q(a) and
737         minpoly != 0, f contains only t_1,...,t_m, G is the ideal of an
738         algebraic group and a standardbasis.
739RETURN:  int;
740         0 if f is not invariant,
741         1 if f is invariant
742NOTE:    G need not be finite
743"
744{
745  def altring=basering;
746  map F;
747  if(deg(f) == 0) { return(1); }
748  for(int i = 1; i <= size(action); i++) {
749    F[nvars(basering) - size(action) + i] = action[i];
750  }
751  return(reduce(f - F(f), G) == 0);
752}
753
754///////////////////////////////////////////////////////////////////////////////
755
756proc MinimalDecomposition(poly f, int nrs, int nrt)
757"USAGE:   MinimalDecomposition(f,a,b); poly f; int a, b.
758PURPOSE: decompose f as a sum M[1,1]*M[2,1] + ... + M[1,r]*M[2,r] where M[1,i]
759         contains only s(1..a), M[2,i] contains only t(1...b) s.t. r is minimal
760ASSUME:  f polynomial in K[s(1..a),t(1..b)], K = Q or K = Q(a) and minpoly != 0
761RETURN:  2 x r matrix M s.t.  f = M[1,1]*M[2,1] + ... + M[1,r]*M[2,r]
762EXAMPLE: example MinimalDecomposition;
763"
764{
765  int i, sizeOfMx, changed, loop;
766  list initialTerms;
767  matrix coM1, coM2, coM, decompMx, auxM;
768  matrix m[2][2] = 0,1,1,0;
769  poly vars1, vars2;
770
771  if(f == 0) { return(decompMx); }
772
773  // first decompose f w.r.t. t(1..nrt)
774  // then  decompose f w.r.t. s(1..nrs)
775
776  vars1 = RingVarProduct(nrs+1..nrt+nrs);
777  vars2 = RingVarProduct(1..nrs);
778  coM1 = SimplifyCoefficientMatrix(m*coef(f, vars1));    // exchange rows of decomposition
779  coM2 = SimplifyCoefficientMatrix(coef(f, vars2));
780  if(ncols(coM2) < ncols(coM1)) {
781    auxM = coM1;
782    coM1 = coM2;
783    coM2 = auxM;
784  }
785  decompMx = coM1;        // decompMx is the smaller decomposition
786  if(ncols(decompMx) == 1) { return(decompMx);}      // n = 1 is minimal
787  changed = 0;
788  loop = 1;
789  i = 1;
790
791  // first loop, try coM1
792
793  while(loop) {
794    coM = MinimalDecomposition(f - coM1[1, i]*coM1[2, i], nrs, nrt);
795    if(size(coM) == 1) { sizeOfMx = 0; }    // coM = 0
796    else {sizeOfMx = ncols(coM); }      // number of columns
797    if(sizeOfMx + 1 < ncols(decompMx)) {    // shorter decomposition
798      changed = 1;
799      decompMx = coM;
800      initialTerms[1] =  coM1[1, i];
801      initialTerms[2] =  coM1[2, i];
802    }
803    if(sizeOfMx == 1) { loop = 0;}      // n = 2 is minimal
804    if(i < ncols(coM1)) {i++;}
805    else {loop = 0;}
806  }
807  if(sizeOfMx > 1) {            // n > 2
808    loop = 1;          // coM2 might yield
809    i = 1;            // a smaller decomposition
810  }
811
812  // first loop, try coM2
813
814  while(loop) {
815    coM = MinimalDecomposition(f - coM2[1, i]*coM2[2, i], nrs, nrt);
816    if(size(coM) == 1) { sizeOfMx = 0; }
817    else {sizeOfMx = ncols(coM); }
818    if(sizeOfMx + 1 < ncols(decompMx)) {
819      changed = 1;
820      decompMx = coM;
821      initialTerms[1] =  coM2[1, i];
822      initialTerms[2] =  coM2[2, i];
823    }
824    if(sizeOfMx == 1) { loop = 0;}
825    if(i < ncols(coM2)) {i++;}
826    else {loop = 0;}
827  }
828  if(!changed) { return(decompMx); }
829  if(size(decompMx) == 1) { matrix decompositionM[2][1];}
830  else  { matrix decompositionM[2][ncols(decompMx) + 1];}
831  decompositionM[1, 1] = initialTerms[1];
832  decompositionM[2, 1] = initialTerms[2];
833  if(size(decompMx) > 1) {
834    for(i = 1; i <= ncols(decompMx); i++) {
835      decompositionM[1, i + 1] = decompMx[1, i];
836      decompositionM[2, i + 1] = decompMx[2, i];
837    }
838  }
839  return(decompositionM);
840}
841example
842{"EXAMPLE:"; echo = 2;
843  ring R = 0, (s(1..2), t(1..2)), dp;
844  poly h = s(1)*(t(1) + t(1)^2) +  (t(2) + t(2)^2)*(s(1)^2 + s(2));
845  matrix M = MinimalDecomposition(h, 2, 2);
846  M;
847  M[1,1]*M[2,1] + M[1,2]*M[2,2] - h;
848}
849
850///////////////////////////////////////////////////////////////////////////////
851
852proc NullCone(ideal G,def action)
853"USAGE:   NullCone(G, action); ideal G, action
854PURPOSE: compute the ideal of the nullcone of the linear action of G on K^n,
855         given by 'action', by means of Deksen's algorithm
856ASSUME:  basering = K[s(1..r),t(1..n)], K = Q or K = Q(a) and minpoly != 0,
857         G is an ideal of a reductive algebraic group in K[s(1..r)],
858         'action' is a linear group action of G on K^n (n = ncols(action))
859RETURN:  ideal of the nullcone of G.
860NOTE:    the generators of the nullcone are homogeneous, but in general not invariant
861EXAMPLE: example NullCone; shows an example
862"
863{
864  int i, nt, dbPrt, offset, groupVars;
865  string ringSTR, vars, order;
866  def RNCB = basering;
867
868  // prepare the ring needed for the computation
869  // s(1...) variables of the group
870  // t(1...) variables of the affine space
871  // y(1...) additional 'slack' variables
872
873  nt = size(action);
874  order = "(dp(" + string(nvars(basering) - nt) + "), dp)";
875  // ring for the computation
876
877  string @minPoly = string(minpoly);
878  offset =  size(G) + nt;
879  list l2;
880  for (int xx = 1; xx <= (nvars(basering) - nt); xx++)
881  {
882   l2[size(l2)+1] = "s("+string(xx)+")";
883  }
884  for (int yy = 1; yy <= nt; yy++)
885  {
886   l2[size(l2)+1] = "t("+string(yy)+")";
887  }
888  for (int zz = 1; zz <= nt; zz++)
889  {
890   l2[size(l2)+1] = "Y("+string(zz)+")";
891  }
892  ring RNCR = create_ring(ringlist(basering)[1], l2, order, "no_minpoly");
893  execute("poly aaa = number(" + @minPoly + ");");
894  if (aaa!=0) { minpoly = number(aaa); }
895  ideal action, G, I, J, N, generators;
896  map F;
897  poly f;
898
899  // built the ideal of the graph of GxV -> V, (s,v) -> s(v), i.e.
900  // of the image of the map GxV -> GxVxV, (s,v) -> (s,v,s(v))
901
902  G = fetch(RNCB, G);
903  action = fetch(RNCB, action);
904  groupVars = nvars(basering) - 2*nt;
905  offset =  groupVars + nt;
906  I = G;
907  for(i = 1; i <= nt; i = i + 1) {
908    I = I, var(offset + i) - action[i];
909  }
910
911  J = std(I);  // takes long, try to improve
912
913  // eliminate
914
915  N = nselect(J, 1.. groupVars);
916
917  // substitute
918  for(i = 1; i <= nvars(basering); i = i + 1) { F[i] = 0; }
919  for(i = groupVars + 1; i <= offset; i = i + 1) { F[i] = var(i); }
920
921  generators = mstd(F(N))[2];
922  setring RNCB;
923  return(fetch(RNCR, generators));
924}
925example
926{"EXAMPLE:";  echo = 2;
927  ring R = 0, (s(1..2), x, y), dp;
928  ideal G = -s(1)+s(2)^3, s(1)^4-1;
929  ideal action = s(1)*x, s(2)*y;
930
931  ideal inv = NullCone(G, action);
932  inv;
933}
934
935///////////////////////////////////////////////////////////////////////////////
936
937proc ReynoldsOperator(ideal Grp, ideal Gaction, list #)
938"USAGE:   ReynoldsOperator(G, action [, opt]); ideal G, action; int opt
939PURPOSE: compute the Reynolds operator of the group G which acts via 'action'
940RETURN:  polynomial ring R over a simple extension of the ground field of the
941         basering (the extension might be trivial), containing a list
942         'ROelements', the ideals 'id', 'actionid' and the polynomial 'newA'.
943         R = K(a)[s(1..r),t(1..n)].
944         - 'ROelements'  is a list of ideals, each ideal represents a
945           substitution map F : R -> R according to the zero-set of G
946         - 'id' is the ideal of G in the new ring
947         - 'newA' is the new representation of a' in terms of a. If the
948           basering does not contain a parameter then 'newA' = 'a'.
949ASSUME:  basering = K[s(1..r),t(1..n)], K = Q or K = Q(a') and minpoly != 0,
950         G is the ideal of a finite group in K[s(1..r)], 'action' is a linear
951         group action of G
952"
953{
954  def ROBR = basering;
955  int i, j, n, ns, primaryDec;
956  ideal G1 = Grp;
957  list solution, saction;
958  string str;
959
960  if(size(#) > 0) { primaryDec = #[1]; }
961  else { primaryDec = 0; }
962  kill #;
963
964  n = nvars(basering);
965  ns = n - size(Gaction);
966  for(i = ns + 1; i <= n; i++) { G1 = G1, var(i);}
967
968  def RORR = zeroSet(G1, primaryDec);
969  setring ROBR;
970  string parName, minPoly;
971  if(npars(basering) == 0) {
972    parName = "a";
973    minPoly = "0";
974  }
975  else {
976    parName = parstr(basering);
977    minPoly = string(minpoly);
978  }
979  ring RA1 = create_ring(0, "(" + varstr(basering) + "," + parName + ")", "lp");
980  if (minPoly!="0") { execute("ideal mpoly = std(" + minPoly + ");"); }
981  ideal Grp = imap(ROBR,Grp);
982  ideal Gaction = imap(ROBR,Gaction);
983  setring RORR;
984  map Phi = RA1, maxideal(1);
985  Phi[nvars(RORR) + 1] = newA;
986  id = Phi(Grp); // id already defined by zeroSet of level 0
987  ideal actionid = Phi(Gaction);
988  kill parName,minPoly,Phi,RA1;
989// end of ersetzt durch
990  list ROelements;
991  ideal Rf;
992  map groupElem;
993  poly h1, h2;
994
995  for(i = 1; i <= size(theZeroset); i++) {
996    groupElem = theZeroset[i];    // element of G
997    for(j = ns + 1; j<=n; j++) { groupElem[j] = var(j); } //do not change t's
998    for(j = 1; j <= n - ns; j++) {
999      h1 = actionid[j];
1000      h2 = groupElem(h1);
1001      Rf[ns + j] = h2;
1002    }
1003    ROelements[i] = Rf;
1004  }
1005  export actionid, ROelements;
1006  setring ROBR;
1007  return(RORR);
1008}
1009
1010///////////////////////////////////////////////////////////////////////////////
1011
1012proc ReynoldsImage(list reynoldsOp, poly f)
1013"USAGE:   ReynoldsImage(RO, f); list RO, poly f
1014PURPOSE: compute the Reynolds image of the polynomial f, where RO represents
1015         the Reynolds operator
1016RETURN:  poly
1017"
1018{
1019  def RIBR=basering;
1020  map F;
1021  poly h = 0;
1022
1023  for(int i = 1; i <= size(reynoldsOp); i++) {
1024    F = RIBR, reynoldsOp[i];
1025    h = h + F(f);
1026  }
1027  return(h/size(reynoldsOp));
1028}
1029
1030///////////////////////////////////////////////////////////////////////////////
1031
1032static proc SimplifyCoefficientMatrix(matrix coefMatrix)
1033"USAGE:   SimplifyCoefficientMatrix(M); M matrix coming from coef(...)
1034PURPOSE: simplify the matrix, i.e. find linear dependencies among the columns
1035RETURN:  matrix M, f = M[1,1]*M[2,1] + ... + M[1,n]*M[2,n]
1036"
1037{
1038  int i, j , loop;
1039  intvec columnList;
1040  matrix decompMx = coefMatrix;
1041
1042  loop = 1;
1043  i = 1;
1044  while(loop) {
1045    columnList = 1..i;            // current column
1046    for(j = i + 1; j <= ncols(decompMx); j++) {
1047      // test if decompMx[2, j] equals const * decompMx[2, i]
1048      if(LinearCombinationQ(ideal(decompMx[2, i]), decompMx[2, j])) {    // column not needed
1049        decompMx[1, i] = decompMx[1, i] +  decompMx[2, j] / decompMx[2, i] * decompMx[1, j];
1050      }
1051      else { columnList[size(columnList) + 1] = j; }
1052    }
1053    if(defined(auxM)) { kill auxM;}
1054    matrix auxM[2][size(columnList)];      // built new matrix and omit
1055    for(j = 1; j <= size(columnList); j++)    // the linear dependent columns
1056    {
1057      auxM[1, j] = decompMx[1, columnList[j]];    // found above
1058      auxM[2, j] = decompMx[2, columnList[j]];
1059    }
1060    decompMx = auxM;
1061    if(i < ncols(decompMx) - 1) { i++;}
1062    else { loop = 0;}
1063  }
1064  return(decompMx);
1065}
1066
1067///////////////////////////////////////////////////////////////////////////////
1068
1069proc SimplifyIdeal(ideal I, list #)
1070"USAGE:   SimplifyIdeal(I [,m, name]); ideal I; int m, string name"
1071PURPOSE: simplify ideal I to the ideal I', do not change the names of the
1072         first m variables, new ideal I' might contain less variables.
1073         I' contains variables var(1..m)
1074RETURN: list
1075  _[1] ideal I'
1076  _[2] ideal representing a map phi to a ring with probably less vars. s.th.
1077       phi(I) = I'
1078  _[3] list of variables
1079  _[4] list from 'elimpart'
1080"
1081{
1082  int i, k, m;
1083  string nameCMD;
1084  ideal mId, In, mapId;  // ideal for the map
1085  list sList, result;
1086
1087  sList = elimpart(I);
1088  In = sList[1];
1089  mapId = sList[5];
1090
1091  if(size(#) > 0)
1092  {
1093    m = #[1];
1094    nameCMD = #[2];
1095  }
1096  else { m = 0;} // nvars(basering);
1097  k = 0;
1098  for(i = 1; i <= nvars(basering); i++)
1099  {
1100    if(sList[4][i] != 0)
1101    {
1102      k++;
1103      if(k <= m) { mId[i] = sList[4][i]; }
1104      else { execute("mId["+string(i) +"] = "+nameCMD+"("+string(k-m)+");");}
1105    }
1106    else { mId[i] = 0;}
1107  }
1108  map phi = basering, mId;
1109  result[1] = phi(In);
1110  result[2] = phi(mapId);
1111  result[3] = simplify(sList[4], 2);
1112  result[4] = sList;
1113  return(result);
1114}
1115
1116///////////////////////////////////////////////////////////////////////////////
1117
1118proc RingVarProduct(def index)
1119// list of indices
1120{
1121  poly f = 1;
1122  for(int i = 1; i <= size(index); i++)
1123  {
1124    f = f * var(index[i]);
1125  }
1126  return(f);
1127}
1128///////////////////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.