source: git/Singular/LIB/rinvar.lib @ 1b2216

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