source: git/Singular/LIB/rinvar.lib @ cbe2b8a

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