source: git/Singular/LIB/rinvar.lib @ 35f23d

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