source: git/Singular/LIB/rinvar.lib

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