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

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