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

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