source: git/Singular/LIB/qhmoduli.lib @ 6d37e8

spielwiese
Last change on this file since 6d37e8 was 1f92589, checked in by Anne Frühbis-Krüger <anne@…>, 23 years ago
*anne: corrected some typing mistakes and line breqks git-svn-id: file:///usr/local/Singular/svn/trunk@5191 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 44.8 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2version="Id: qhmoduli.lib,v 1.0 2000/12/12 12:32:15 Singular Exp $";
3category="Singularities";
4info="
5LIBRARY:  qhmoduli.lib    Moduli Spaces of Semi-Quasihomogeneous Singularities
6AUTHOR:   Thomas Bayer, email: bayert@in.tum.de
7
8PROCEDURES:
9 ArnoldAction(f, [G, w])  Induced action of G_f on T_.
10 ModEqn(f)                Equations of the moduli space for principal part f
11 QuotientEquations(G,A,I) Equations of Variety(I)/G w.r.t. action 'A'
12 StabEqn(f)               Equations of the stabilizer of f.
13 StabEqnId(I, w)          Equations of the stabilizer of the qhom. ideal I.
14 StabOrder(f)             Order of the stabilizer of f.
15 UpperMonomials(f, [w])   Upper basis of the Milnor algebra of f.
16
17 Max(data)                maximal integer contained in 'data'
18 Min(data)                minimal integer contained in  'data'
19 Table(cmd, i, lb, ub)    list, i-th entry is cmd(i), lb <= i <= ub
20";
21
22// NOTE: This library has been written in the frame of the diploma thesis
23// 'Computing moduli spaces of semiquasihomogeneous singularities and an
24//  implementation in Singular', Arbeitsgruppe Algebraische Geometrie,
25// Fachbereich Mathematik, University Kaiserslautern,
26// Advisor: Prof. Gert-Martin Greuel
27
28LIB "rinvar.lib";
29
30///////////////////////////////////////////////////////////////////////////////
31
32proc ModEqn(poly f, list #)
33"USAGE:   ModEqn(f [, opt]); poly f; int opt;
34PURPOSE: compute equations of the moduli space of semiquasihomogenos hypersurface         singularity with principal part f w.r.t. right equivalence
35ASSUME:  f quasihomogeneous polynomial with an isolated singularity at 0
36RETURN:  polynomial ring, possibly a simple extension of the groundfield of
37         the basering, containing the ideal 'modid'
38         - 'modid' is the ideal of the moduli space  if opt is even (> 0).
39           otherwise it contains generators of the coordinate ring R of the
40           moduli space (note : Spec(R) is the moduli space)
41OPTIONS: 1 compute equations of the mod. space,
42         2 use a primary decomposition
43         4 compute E_f0, i.e., the image of G_f0
44         To combine options, add their value, default: opt =7
45EXAMPLE: example ModEqn; shows an example
46"
47{
48  int sizeOfAction, i, dimT, nonLinearQ, milnorNr, dbPrt;
49  int imageQ, opt;
50  intvec wt;
51  ideal B;
52  list Gf, tIndex, sList;
53  string ringSTR;
54
55  dbPrt = printlevel-voice+2;
56  if(size(#) > 0) { opt = #[1]; }
57  else { opt = 7; }
58  if(opt / 4 > 0) { imageQ = 1; opt = opt - 4;}
59  else { imageQ = 0; }
60
61  wt = weight(f);
62  milnorNr = vdim(std(jacob(f)));
63  if(milnorNr == -1) {
64                ERROR("the polynomial " + string(f) + " has a nonisolated singularity at 0");
65        }       // singularity not isolated
66
67  // 1st step : compute a basis of T_
68
69  B = UpperMonomials(f, wt);
70  dimT = size(B);
71  dbprint(dbPrt, "moduli equations of f = " + string(f) + ", f has Milnor number = " + string(milnorNr));
72  dbprint(dbPrt, " upper basis = " + string(B));
73  if(size(B) > 1) {
74
75    // 2nd step : compute the stabilizer G_f of f
76
77    dbprint(dbPrt, " compute equations of the stabilizer of f, called G_f");
78    Gf = StabEqn(f);
79    dbprint(dbPrt, " order of the stabilizer = " + string(StabOrder(Gf)));
80
81    // 3rd step : compute the induced action of G_f on T_ by means of a theorem of Arnold
82
83    dbprint(dbPrt, " compute the induced action");
84    def RME1 = ArnoldAction(f, Gf, B);
85    setring(RME1);
86    export(RME1);
87    dbprint(dbPrt, " G_f = " + string(stabid));
88    dbprint(dbPrt, " action of G_f : " + string(actionid));
89
90    // 4th step : linearize the action of G_f
91
92    sizeOfAction = size(actionid);
93    def RME2 = LinearizeAction(stabid, actionid, nvars(Gf[1]));
94    setring RME2;
95    export(RME2);
96    kill(RME1);
97
98    if(size(actionid) == sizeOfAction) { nonLinearQ = 0;}
99    else  {
100      nonLinearQ = 1;
101      dbprint(dbPrt, " linearized action = " + string(actionid));
102      dbprint(dbPrt, " embedding of T_ = " + string(embedid));
103    }
104
105
106
107    if(!imageQ) {        // do not compute the image of Gf
108      // 5th step : set E_f = G_f,
109      dbprint(dbPrt, " compute equations of the quotient T_/G_f");
110      def RME3 = basering;
111    }
112    else {
113
114      // 5th step : compute the ideal and the action of E_f
115
116      dbprint(dbPrt, " compute E_f");
117      def RME3 = ImageGroup(groupid, actionid);
118      setring(RME3);
119      ideal embedid = imap(RME2, embedid);
120      dbprint(dbPrt, " E_f  = (" + string(groupid) + ")");
121      dbprint(dbPrt, " action of E'f = " + string(actionid));
122      dbprint(dbPrt, " compute equations of the quotient T_/E_f");
123    }
124    export(RME3);
125    kill(RME2);
126
127    // 6th step : compute the equations of the quotient T_/E_f
128
129                ideal G = groupid; ideal variety = embedid;
130                kill(groupid); kill(embedid);
131    def RME4 = QuotientEquations(G, actionid, variety, opt);
132    setring RME4;
133    poly mPoly = minpoly;
134    kill(RME3);
135    export(RME4);
136
137    // simplify the ideal and create a new ring with propably less variables
138
139    if(opt == 1 || opt == 3) {      // equations computed ?
140      sList = SimplifyIdeal(id, 0, "Y");
141      ideal newid = sList[1];
142      dbprint(dbPrt, " number of equations = " + string(size(sList[1])));
143      dbprint(dbPrt, " number of variables = " + string(size(sList[3])));
144      ringSTR = "ring RME5 = (" + charstr(basering) + "), (Y(1.." + string(size(sList[3])) + ")),dp;";
145      execute(ringSTR);
146      minpoly = number(imap(RME4, mPoly));
147      ideal modid = imap(RME4, newid);
148    }
149    else {
150      def RME5 = RME4;
151      setring(RME5);
152      ideal modid = imap(RME4, id);
153    }
154    export(modid);
155    kill(RME4);
156  }
157  else {
158                def RME5 = basering;
159                ideal modid = maxideal(1);
160                if(size(B) == 1) {                      // 1-dimensional
161                        modid[size(modid)] = 0;
162                        modid = simplify(modid,2);
163                }
164                export(modid);
165        }
166dbprint(dbPrt, "
167// 'ModEqn' created a new ring.
168// To see the ring, type (if the name of the ring is R):
169     show(R);
170// To access the ideal of the moduli space of semiquasihomogeneous singularities
171// with principal part f, type
172     def R = ModEqn(f); setring R;  modid;
173// 'modid' is the ideal of the moduli space.
174// if 'opt' = 0 or even, then 'modid' contains algebra generators of S s.t.
175// spec(S) = moduli space of f.
176");
177  return(RME5);
178}
179example
180{"EXAMPLE:";  echo = 2;
181  ring B   = 0,(x,y), ls;
182  poly f = -x4 + xy5;
183  def R = ModEqn(f);
184  setring R;
185  modid;
186}
187
188
189///////////////////////////////////////////////////////////////////////////////
190
191proc QuotientEquations(ideal G, ideal Gaction, ideal embedding, list#)
192"USAGE:   QuotientEquations(G,action,emb [, opt]); ideal G,action,emb;int opt
193PURPOSE: compute the quotient of the variety given by the parameterization
194         'emb'  by the linear action 'action' of the algebraic group G.
195ASSUME:  'action' is linear, G must be finite if the Reynolds operator is
196         needed (i.e., NullCone(G,action) returns some non-invariant polys)
197RETURN:   polynomial ring over a simple extension of the groundfield of the
198          basering, containing the ideals 'id' and 'embedid'.
199          - 'id' contains the equations of the quotient, if opt = 1;
200            if opt = 0, 2, 'id' contains generators of the coordinate ring R
201            of the quotient (Spec(R) is the quotient)
202          - 'embedid' = 0, if opt = 1;
203            if opt = 0, 2, it is the ideal defining the equivariant embedding
204OPTIONS: 1 compute equations of the quotient,
205         2 use a primary decomposition when computing the Reynolds operator @*
206         To combine options, add their value, default: opt =3.
207EXAMPLE: example QuotientEquations; shows an example
208"
209{
210  int i, opt, primaryDec, relationsQ, dbPrt;
211  ideal Gf, variety;
212  intvec wt;
213
214  dbPrt = printlevel-voice+3;
215  if(size(#) > 0) { opt = #[1]; }
216  else { opt = 3; }
217
218  if(opt / 2 > 0) { primaryDec = 1; opt = opt - 2; }
219  else { primaryDec = 0; }
220  if(opt > 0) { relationsQ = 1;}
221  else { relationsQ = 0; }
222
223  Gf = std(G);
224  variety = EquationsOfEmbedding(embedding, nvars(basering) - size(Gaction));
225
226  if(size(variety) == 0) {    // use Hilbert function !
227    for(i = 1; i <= ncols(Gaction); i ++) { wt[i] = 1;};
228  }
229  def RQER = InvariantRing(Gf, Gaction, primaryDec);    // compute the nullcone of the linear action
230
231  def RQEB = basering;
232  setring(RQER);
233  export(RQER);
234
235  if(relationsQ > 0) {
236    dbprint(dbPrt, " compute equations of the variety (" + string(size(imap(RQER, invars))) + " invariants) ");
237    if(!defined(variety)) { ideal variety = imap(RQEB, variety); }
238    if(wt[1] > 0) {
239      def RQES = ImageVariety(variety, imap(RQER, invars), wt);
240    }
241    else {
242      def RQES = ImageVariety(variety, imap(RQER, invars));  // forget imap
243    }
244    setring(RQES);
245    ideal id = imageid;
246    ideal embedid = 0;
247  }
248  else {
249    def RQES = basering;
250    ideal id =  imap(RQER, invars);
251    ideal embedid = imap(RQEB, variety);
252  }
253  kill(RQER);
254  export(id);
255  export(embedid);
256  return(RQES);
257}
258
259///////////////////////////////////////////////////////////////////////////////
260
261proc UpperMonomials(poly f, list #)
262"USAGE:   UpperMonomials(poly f, [intvec w])
263PURPOSE: compute the upper monomials of the milnor algebra of f.
264ASSUME:  f is quasihomogeneous (w.r.t. w)
265RETURN:  ideal
266EXAMPLE: example UpperMonomials; shows an example
267"
268{
269  int i,d;
270  intvec wt;
271  ideal I, J;
272
273  if(size(#) == 0) { wt = weight(f);}
274  else { wt = #[1];}
275   J = kbase(std(jacob(f)));
276  d = deg(f, wt);
277  for(i = 1; i <= size(J); i++) { if(deg(J[i], wt) > d) {I = I, J[i];} }
278  return(simplify(I, 2));
279}
280example
281{"EXAMPLE:";  echo = 2;
282  ring B   = 0,(x,y,z), ls;
283  poly f = -z5+y5+x2z+x2y;
284  UpperMonomials(f);
285}
286
287///////////////////////////////////////////////////////////////////////////////
288
289proc ArnoldAction(poly f, list #)
290"USAGE:   ArnoldAction(f, [Gf, B]); poly f; list Gf, B;
291         'Gf' is a list of two rings (coming from 'StabEqn')
292PURPOSE: compute the induced action of the stabilizer G of f on T_, where
293         T_ is given by the upper monomials B of the Milnor algebra of f.
294ASSUME:  f is quasihomogeneous
295RETURN:  polynomial ring over the same groundfield, containing the ideals
296         'actionid' and 'stabid'.
297         - 'actionid' is the ideal defining the induced action of Gf on T_ @*
298         - 'stabid' is the ideal of the stabilizer Gf in the new ring
299EXAMPLE: example ArnoldAction; shows an example
300"
301{
302  int i, offset, ub, pos, nrStabVars, dbPrt;
303  intvec wt = weight(f);
304  ideal B;
305  list Gf, parts, baseDeg;
306  string ringSTR1, ringSTR2, parName, namesSTR, varSTR;
307
308  dbPrt = printlevel-voice+2;
309  if(size(#) == 0) {
310    Gf = StabEqn(f);
311    B = UpperMonomials(f, wt);
312  }
313  else {
314    Gf = #[1];
315    if(size(#) > 1) { B = #[2];}
316    else {B = UpperMonomials(f, wt);}
317  }
318  if(size(B) == 0) { ERROR("the principal part " + string(f) + " has no upper monomials");}
319  for(i = 1; i <= size(B); i = i + 1) {
320    baseDeg[i] = deg(B[i], wt);
321  }
322  ub = Max(baseDeg) + 1;          // max degree of an upper mono.
323  def RAAB = basering;
324  def STR1 = Gf[1];
325  def STR2 = Gf[2];
326  nrStabVars = nvars(STR1);
327
328  dbprint(dbPrt, "ArnoldAction of f = ", f, ", upper base = " + string(B));
329
330  setring STR1;
331  poly mPoly = minpoly;
332  setring RAAB;
333
334  // setup new ring with s(..) and t(..) as parameters
335
336  varSTR = string(maxideal(1));
337  ringSTR2 = "ring RAAS = ";
338  if(npars(basering) == 1) {
339    parName = parstr(basering);
340    ringSTR2 = ringSTR2 + "(0, " + parstr(1) + "), ";
341  }
342  else {
343    parName = "a";
344    ringSTR2 = ringSTR2 + "0, ";
345  }
346  offset = 1 + nrStabVars;
347  namesSTR = "s(1.." + string(nrStabVars) + "), t(1.." + string(size(B)) + ")";
348  ringSTR2 = ringSTR2 + "(" + namesSTR + "), lp;";
349  ringSTR1 = "ring RAAR = (0, " + parName + "," + namesSTR + "), (" + varSTR + "), ls;";  // lp ?
350
351  execute(ringSTR1);
352  export(RAAR);
353  ideal upperBasis, stabaction, action, mPoly, reduceIdeal;
354  poly f, F, monos, h;
355
356  reduceIdeal = imap(STR1, mPoly), imap(STR1, stabid);
357  f = imap(RAAB, f);
358  F = f;
359  upperBasis = imap(RAAB, B);
360  for(i = 1; i <= size(upperBasis); i = i + 1) {
361    F = F + par(i + offset)*upperBasis[i];
362  }
363  monos = F - f;
364  stabaction = imap(STR2, actionid);
365
366  // action of the stabilizer on the semiuniversal unfolding of f
367
368  F = f + APSubstitution(monos, stabaction, reduceIdeal, wt, ub, nrStabVars, size(upperBasis));
369
370  // apply the theorem of Arnold
371
372  h = ArnoldFormMain(f, upperBasis, F, reduceIdeal, nrStabVars, size(upperBasis)) - f;
373
374  // extract the polynomials of the action of the stabilizer on T_
375
376  parts = MonosAndTerms(h, wt, ub);
377  for(i = 1; i <= size(parts[1]); i = i + 1) {
378    pos = FirstEntryQHM(upperBasis, parts[1][i]);
379    action[pos] = parts[2][i]/parts[1][i];
380  }
381  execute(ringSTR2);
382  minpoly = number(imap(STR1, mPoly));
383  ideal actionid = imap(RAAR, action);
384  ideal stabid = imap(STR1, stabid);
385  export(actionid);
386  export(stabid);
387  kill(RAAR);
388dbprint(dbPrt, "
389// 'ArnoldAction' created a new ring.
390// To see the ring, type (if the name of the ring is R):
391     show(R);
392// To access the ideal of the stabilizer G of f and its group action,
393// where f is the quasihomogeneous principal part, type
394     def R = ArnoldAction(f); setring R;  stabid; actionid;
395// 'stabid' is the ideal of the group G and 'actionid' is the ideal defining
396// the group action of the group G on T_. Note: this action might be nonlinear
397");
398  return(RAAS);
399}
400example
401{"EXAMPLE:";  echo = 2;
402  ring B   = 0,(x,y,z), ls;
403  poly f = -z5+y5+x2z+x2y;
404  def R = ArnoldAction(f);
405  setring R;
406  actionid;
407  stabid;
408}
409
410///////////////////////////////////////////////////////////////////////////////
411
412proc StabOrder(list #)
413"USAGE:   StabOrder(f); poly f;
414PURPOSE: compute the order of the stabilizer group of f.
415ASSUME:  f quasihomogeneous polynomial with an isolated singularity at 0
416RETURN:  int
417GLOBAL: varSubsList
418"
419{
420  list stab;
421
422  if(size(#) == 1) { stab = StabEqn(#[1]); }
423  else {  stab = #;}
424
425  def RSTO = stab[1];
426  setring(RSTO);
427  return(vdim(std(stabid)));
428}
429
430///////////////////////////////////////////////////////////////////////////////
431
432proc StabEqn(poly f)
433"USAGE:   StabEqn(f); f polynomial
434PURPOSE: compute the equations of the isometry group of f.
435ASSUME:  f semiquasihomogeneous polynomial with an isolated singularity at 0
436RETURN:  list of two ring 'S1', 'S2'
437         - 'S1' contians the equations of the stabilizer (ideal 'stabid') @*
438         - 'S2' contains the action of the stabilizer (ideal 'actionid')
439EXAMPLE: example StabEqn; shows an example
440GLOBAL: varSubsList, contains the index j s.t. x(i) -> x(i)t(j) ...
441"
442{
443dbprint(dbPrt, "
444// 'StabEqn' created a list of 2 rings.
445// To see the rings, type (if the name of your list is stab):
446     show(stab);
447// To access the 1-st ring and map (and similair for the others), type:
448     def S1 = stab[1]; setring S1;  stabid;
449// S1/stabid is the coordinate ring of the variety of the
450// stabilizer, say G. If G x K^n --> K^n is the action of G on
451// K^n, then the ideal 'actionid' in the second ring describes
452// the dual map on the ring level.
453// To access the 2-nd ring and map (and similair for the others), type:
454     def S2 = stab[2]; setring S2;  actionid;
455");
456
457        return(StabEqnId(ideal(f), qhweight(f)));
458}
459example
460{"EXAMPLE:";  echo = 2;
461  ring B = 0,(x,y,z), ls;
462  poly f = -z5+y5+x2z+x2y;
463  list stab = StabEqn(f);
464  def S1 = stab[1]; setring S1;  stabid;
465  def S2 = stab[2]; setring S2;  actionid;
466}
467
468///////////////////////////////////////////////////////////////////////////////
469
470proc StabEqnId(ideal data, intvec wt)
471"USAGE:   StabEqn(I, w); I ideal, w intvec
472PURPOSE: compute the equations of the isometry group of the ideal I
473         each generator of I is fixed by the stabilizer.
474ASSUME:  I semiquasihomogeneous ideal wrt 'w' with an isolated singularity at 0
475RETURN:  list of two ring 'S1', 'S2'
476         - 'S1' contians the equations of the stabilizer (ideal 'stabid') @*
477         - 'S2' contains the action of the stabilizer (ideal 'actionid')
478EXAMPLE: example StabEqnId; shows an example
479GLOBAL: varSubsList, contains the index j s.t. t(i) -> t(i)t(j) ...
480"
481{
482  int i, j, c, k, r, nrVars, offset, n, sln, dbPrt;
483  list variables, rd, temp, sList, varSubsList;
484  poly mPoly;
485  string ringSTR, ringSTR1, varString, parString;
486
487  dbPrt = printlevel-voice+2;
488  dbprint(dbPrt, "StabilizerEquations of " + string(data));
489
490  export(varSubsList);
491  n = nvars(basering);
492  variables = StabVar(wt);    // possible quasihomogeneous substitutions
493  nrVars = 0;
494  for(i = 1; i <= size(wt); i = i + 1) {
495    nrVars = nrVars + size(variables[i]);
496  }
497
498  // set the new basering needed for the substitutions
499
500  varString = "s(1.." + string(nrVars) + ")";
501  if(npars(basering) == 1) {
502    parString = "(0, " + parstr(basering) + ")";
503  }
504  else { parString = "0"; }
505
506  def RSTB = basering;
507  mPoly = minpoly;
508  ringSTR = "ring RSTR = " + parString + ", (" + varstr(basering) + ", " + varString + "), dp;";  // dp
509        ringSTR1 = "ring RSTT = " + parString + ", (" + varString + ", " + varstr(basering) + "), dp;";
510
511  if(defined(RSTR)) { kill(RSTR);}
512        if(defined(RSTT)) { kill(RSTT);}
513        execute(ringSTR1);      // this ring is only used for the result, where the variables
514  export(RSTT);           // are s(1..m),t(1..n), as needed for Derksens algorithm (NullCone)
515  minpoly = number(imap(RSTB, mPoly));
516
517  execute(ringSTR);
518  export(RSTR);
519  minpoly = number(imap(RSTB, mPoly));
520  poly f, f1, g, h, vars, pp;      // f1 is the polynomial after subs,
521  ideal allEqns, qhsubs, actionid, stabid, J;
522  list ringList;          // all t(i)`s which do not appear in f1
523  ideal data = simplify(imap(RSTB, data), 2);
524
525  // generate the quasihomogeneous substitution map F
526
527  nrVars = 0;
528  offset = 0;
529  for(i = 1; i <= size(wt); i = i + 1) {    // build the substitution t(i) -> ...
530    if(i > 1) { offset = offset + size(variables[i - 1]); }
531    g = 0;
532    for(j = 1; j <= size(variables[i]); j = j + 1) {
533      pp = 1;
534      for(k = 2; k <= size(variables[i][j]); k = k + 1) {
535        pp = pp * var(variables[i][j][k]);
536        if(variables[i][j][k] == i) { varSubsList[i] = offset + j;}
537      }
538      g = g + s(offset + j) * pp;
539    }
540    qhsubs[i] = g;
541  }
542  dbprint(dbPrt, "  qhasihomogenous substituion =" + string(qhsubs));
543  map F = RSTR, qhsubs;
544  kill(varSubsList);
545
546  // get the equations of the stabilizer by comparing coefficients
547  // in the equation f = F(f).
548
549  vars = RingVarProduct(Table("i", "i", 1, size(wt)));
550
551  allEqns = 0;
552
553  for(r = 1; r <= ncols(data); r++) {
554
555  f = data[r];
556  f1 = F(f);
557  int d = deg(f);
558  matrix newcoMx = coef(f1, vars);        // coefficients of F(f)
559  matrix coMx = coef(f, vars);          // coefficients of f
560
561  for(i = 1; i <= ncols(newcoMx); i = i + 1) {      // build the system of eqns via coeff. comp.
562    j = 1;
563    h = 0;
564    while(j <= ncols(coMx)) {        // all monomials in f
565      if(coMx[j][1] == newcoMx[i][1]) { h = coMx[j][2]; j = ncols(coMx) + 1;}
566      else {j = j + 1;}
567    }
568    J = J, newcoMx[i][2] - h;        // add equation
569  }
570  allEqns =  allEqns, J;
571
572  }
573  allEqns = std(allEqns);
574
575  // simplify the equations, i.e., if s(i) in J then remove s(i) from J
576  // and from the basering
577
578  sList = SimplifyIdeal(allEqns, n, "s");
579  stabid = sList[1];
580  map phi = basering, sList[2];
581        sln = size(sList[3]) - n;
582
583  // change the substitution
584
585  actionid = phi(qhsubs);
586
587        // change to new ring, auxillary construction
588
589        setring(RSTT);
590        ideal actionid, stabid;
591
592        actionid = imap(RSTR, actionid);
593        stabid = imap(RSTR, stabid);
594        export(stabid);
595  export(actionid);
596  ringList[2] = RSTT;
597
598  dbprint(dbPrt, "  substitution = " + string(actionid));
599  dbprint(dbPrt, "  equations of stabilizer = " + string(stabid));
600
601  varString = "s(1.." + string(sln) + ")";
602  ringSTR = "ring RSTS = " + parString + ", (" + varString + "), dp;";
603  execute(ringSTR);
604  minpoly = number(imap(RSTB, mPoly));
605  ideal stabid = std(imap(RSTR, stabid));
606  export(stabid);
607  ringList[1] = RSTS;
608dbprint(dbPrt, "
609// 'StabEqnId' created a list of 2 rings.
610// To see the rings, type (if the name of your list is stab):
611     show(stab);
612// To access the 1-st ring and map (and similair for the others), type:
613     def S1 = stab[1]; setring S1;  stabid;
614// S1/stabid is the coordinate ring of the variety of the
615// stabilizer, say G. If G x K^n --> K^n is the action of G on
616// K^n, then the ideal 'actionid' in the second ring describes
617// the dual map on the ring level.
618// To access the 2-nd ring and map (and similair for the others), type:
619     def S2 = stab[2]; setring S2;  actionid;
620");
621  return(ringList);
622}
623example
624{"EXAMPLE:";  echo = 2;
625  ring B   = 0,(x,y,z), ls;
626  ideal I = x2,y3,z6;
627  intvec w = 3,2,1;
628  list stab = StabEqnId(I, w);
629  def S1 = stab[1]; setring S1;  stabid;
630  def S2 = stab[2]; setring S2;  actionid;
631}
632
633///////////////////////////////////////////////////////////////////////////////
634static
635proc ArnoldFormMain(poly f, B, poly Fs, ideal reduceIdeal, int nrs, int nrt)
636"USAGE:   ArnoldFormMain(f, B, Fs, rI, nrs, nrt);
637   poly f,Fs; ideal B, rI; int nrs, nrt
638PURPOSE: compute the induced action of 'G_f' on T_, where f is the principal
639         part and 'Fs' is the semiuniversal unfolding of 'f' with x_i
640         substituted by actionid[i], 'B' is a list of upper basis monomials
641         for the milnor algebra of 'f', 'nrs' = number of variables for 'G_f'
642         and 'nrt' = dimension of T_
643ASSUME:  f is quasihomogeneous with an isolated singularity at 0,
644         s(1..r), t(1..m) are parameters of the basering
645RETURN:  poly
646EXAMPLE: example ArnoldAction; shows an example
647"
648{
649  int i, j, d, ub, dbPrt;
650  list upperBasis, basisDegList, gmonos, common, parts;
651  ideal jacobianId, jacobIdstd, mapId;    // needed for phi
652  intvec wt = weight(f);
653  matrix gCoeffMx;        // for lift command
654  poly newFs, g, gred, tt;        // g = sum of all monomials of degree d, gred is needed for lift
655  map phi;          // the map from Arnold's Theorem
656
657  dbPrt = printlevel-voice+2;
658  jacobianId = jacob(f);
659  jacobIdstd = std(jacobianId);
660  newFs = Fs;
661  for(i = 1; i <= size(B); i = i + 1) {
662    basisDegList[i] = deg(B[i], wt);
663  }
664  ub = Max(basisDegList) + 1;          // max degree of an upper monomial
665
666  parts = MonosAndTerms(newFs - f, wt, ub);
667  gmonos = parts[1];
668  d = deg(f, wt);
669
670  for(i = d + 1; i < ub; i = i + 1) {    // base[1] = monomials of degree i
671    upperBasis[i] = SelectMonos(list(B, B), wt, i);    // B must not contain 0's
672  }
673
674  // test if each monomial of Fs is contained in B, if not,
675  // compute a substitution via Arnold's theorem and substitutite
676  // it into newFs
677
678  for(i = d + 1; i < ub; i = i + 1) {  // ub instead of @UB
679    dbprint(dbPrt, "-- degree = " + string(i) + " of " + string(ub - 1) + " ---------------------------");
680    if(size(newFs) < 80) { dbprint(dbPrt, "  polynomial = " + string(newFs - f));}
681    else {  dbprint(dbPrt, "  poly has deg (not weighted) " + string(deg(newFs)) + " and contains " + string(size(newFs)) + " monos");}
682
683    // select monomials of degree i and intersect them with upperBasis[i]
684
685    gmonos = SelectMonos(parts, wt, i);
686    common = IntersectionQHM(upperBasis[i][1], gmonos[1]);
687    if(size(common) == size(gmonos[1])) {
688      dbprint(dbPrt, " no additional monomials ");
689    }
690
691    // other monomials than those in upperBasis occur, compute
692    // the map constructed in the proof of Arnold's theorem
693    // write g = c[i] * jacobianId[i]
694
695    else {
696      dbprint(dbPrt, "  additional Monomials found, compute the map ");
697      g = PSum(gmonos[2]);      // sum of all monomials in g of degree i
698      dbprint(dbPrt, "  sum of degree " + string(i) + " is " + string(g));
699
700      gred = reduce(g, jacobIdstd);
701      gCoeffMx = lift(jacobianId, g - gred);    // compute c[i]
702      mapId = var(1) - gCoeffMx[1][1];    // generate the map
703      for(j = 2; j <= size(gCoeffMx); j = j + 1) {
704        mapId[j] = var(j) - gCoeffMx[1][j];
705      }
706      dbprint(dbPrt, "  map = " + string(mapId));
707      // apply the map to newFs
708      newFs = APSubstitution(newFs, mapId, reduceIdeal, wt, ub, nrs, nrt);
709      parts = MonosAndTerms(newFs - f, wt, ub);  // monos and terms of deg < ub
710      newFs = PSum(parts[2]) + f;      // result of APS... is already reduced
711      dbprint(dbPrt, "  monomials of degree " + string(i));
712    }
713  }
714  return(newFs);
715}
716
717///////////////////////////////////////////////////////////////////////////////
718
719proc MonosAndTerms(poly f, wt, int ub)
720"USAGE:   MonosAndTerms(f, w, ub); poly f, intvec w, int ub
721PURPOSE: returns a list of all monomials and terms occuring in f of
722         weighted degree < ub
723RETURN:  list
724         _[1]  list of monomials
725         _[2]  list of terms
726EXAMPLE: example MonosAndTerms shows an example
727"
728{
729  int i, k;
730  list monomials, terms;
731  poly mono, lcInv, data;
732
733  data = jet(f, ub - 1, wt);
734  k = 0;
735  for(i = 1; i <= size(data); i = i + 1) {
736    mono = lead(data[i]);
737    if(deg(mono, wt) < ub) {
738      k = k + 1;
739      lcInv = 1/leadcoef(mono);
740      monomials[k] = mono * lcInv;
741      terms[k] = mono;
742    }
743  }
744  return(list(monomials, terms));
745}
746example
747{"EXAMPLE:";  echo = 2;
748  ring B = 0,(x,y,z), lp;
749  poly f = 6*x2 + 2*x3 + 9*x*y2 + z*y + x*z6;
750  MonosAndTerms(f, intvec(2,1,1), 5);
751}
752
753///////////////////////////////////////////////////////////////////////////////
754
755proc SelectMonos(parts, intvec wt, int d)
756"USAGE:   SelectMonos(parts, w, d); list/ideal parts, intvec w, int d
757PURPOSE: returns a list of all monomials and terms occuring in f of
758         weighted degree = d
759RETURN:  list
760         _[1]  list of monomials
761         _[2]  list of terms
762EXAMPLE: example SelectMonos; shows an example
763"
764{
765  int i, k;
766  list monomials, terms;
767  poly mono;
768
769  k = 0;
770  for(i = 1; i <= size(parts[1]); i = i + 1) {
771    mono = parts[1][i];
772    if(deg(mono, wt) == d) {
773      k = k + 1;
774      monomials[k] = mono;
775      terms[k] = parts[2][i];
776    }
777  }
778  return(list(monomials, terms));
779}
780example
781{"EXAMPLE:";  echo = 2;
782  ring B = 0,(x,y,z), lp;
783  poly f = 6*x2 + 2*x3 + 9*x*y2 + z*y + x*z6;
784  list mt =  MonosAndTerms(f, intvec(2,1,1), 5);
785  SelectMonos(mt, intvec(2,1,1), 4);
786}
787
788///////////////////////////////////////////////////////////////////////////////
789
790proc Expand(substitution, degVec, ideal reduceI, intvec w1, int ub, list truncated)
791"USAGE:   Expand(substitution, degVec, reduceI, w, ub, truncated);
792         ideal/list substitution, list/intvec degVec, ideal reduceI, intvec w,
793         int ub, list truncated
794PURPOSE: substitute 'substitution' in the monomial given by the list of
795         exponents 'degVec', omit all terms of weighted degree > ub and reduce
796         the result w.r.t. 'reduceI'. If truncated[i] = 0 then the result is
797         stored for later use.
798RETURN:  poly
799NOTE:    used by APSubstitution
800GLOBAL:  computedPowers
801"
802{
803  int i, minDeg;
804  list powerList;
805  poly g, h;
806
807  // compute substitution[1]^degVec[1],...,subs[n]^degVec[n]
808
809  for(i = 1; i <= ncols(substitution); i = i + 1) {
810    if(size(substitution[i]) < 3 || degVec[i] < 4) {
811      powerList[i] = reduce(substitution[i]^degVec[i], reduceI); // new
812    }  // directly for small exponents
813    else {
814      powerList[i] = PolyPower1(i, substitution[i], degVec[i], reduceI, w1, truncated[i], ub);
815    }
816  }
817  // multiply the terms obtained by using PolyProduct();
818  g = powerList[1];
819  minDeg = w1[1] * degVec[1];
820  for(i = 2; i <= ncols(substitution); i = i + 1) {
821    g = jet(g, ub - w1[i] * degVec[i] - 1, w1);
822    h = jet(powerList[i], ub - minDeg - 1, w1);
823    g = PolyProduct(g, h, reduceI, w1, ub);
824    if(g == 0) { Print(" g = 0 "); break;}
825    minDeg = minDeg + w1[i] * degVec[i];
826  }
827  return(g);
828}
829
830///////////////////////////////////////////////////////////////////////////////
831
832proc PolyProduct(poly g1, poly h1, ideal reduceI, intvec wt, int ub)
833"USAGE:   PolyProduct(g, h, reduceI, wt, ub); poly g, h; ideal reduceI,
834          intvec wt, int ub.
835PURPOSE: compute g*h and reduce it w.r.t 'reduceI' and omit terms of weighted
836         degree > ub.
837RETURN:  poly
838NOTE:    used by 'Expand'
839"
840{
841  int SUBSMAXSIZE = 3000;    //
842  int i, nrParts, sizeOfPart, currentPos, partSize, maxSIZE;
843  poly g, h, gxh, prodComp, @g2;    // replace @g2 by subst.
844
845  g = g1;
846  h = h1;
847
848  if(size(g)*size(h) > SUBSMAXSIZE) {
849
850    // divide the polynomials with more terms in parts s.t.
851    // the product of each part with the other polynomial
852    // has at most SUBMAXSIZE terms
853
854    if(size(g) < size(h)) { poly @h = h; h = g; g = @h;@h = 0; }
855    maxSIZE = SUBSMAXSIZE / size(h);
856    //print(" SUBSMAXSIZE = "+string(SUBSMAXSIZE)+" exceeded by "+string(size(g)*size(h)) + ", maxSIZE = ", string(maxSIZE));
857    nrParts = size(g) / maxSIZE + 1;
858    partSize = size(g) / nrParts;
859    gxh = 0;  // 'g times h'
860    for(i = 1; i <= nrParts; i = i + 1){
861      //print(" loop #" + string(i) + " of " + string(nrParts));
862      currentPos = (i - 1) * partSize;
863      if(i < nrParts) {sizeOfPart = partSize;}
864      else { sizeOfPart = size(g) - (nrParts - 1) * partSize; print(" last #" + string(sizeOfPart) + " terms ");}
865      prodComp = g[currentPos + 1..sizeOfPart + currentPos] * h;  // multiply a part
866      @g2 = jet(prodComp, ub - 1, wt);  // eventual reduce ...
867      if(size(@g2) < size(prodComp)) { print(" killed " + string(size(prodComp) - size(@g2)) + " terms ");}
868      gxh =  reduce(gxh + @g2, reduceI);
869
870    }
871  }
872  else {
873    gxh = reduce(jet(g * h,ub - 1, wt), reduceI);
874  }  // compute directly
875  return(gxh);
876}
877
878///////////////////////////////////////////////////////////////////////////////
879
880proc PolyPower1(int varIndex, poly f, int e, ideal reduceI, intvec wt, int truncated, int ub)
881"USAGE:   PolyPower1(i, f, e, reduceI, wt, truncated, ub);int i, e, ub;poly f;
882         ideal reduceI; intvec wt; list truncated;
883PURPOSE: compute f^e, use previous computations if possible, and reduce it
884         w.r.t reudecI and omit terms of weighted degree > ub.
885RETURN:  poly
886NOTE:    used by 'Expand'
887GLOBAL:  'computedPowers'
888"
889{
890  int i, ordOfg, lb, maxPrecomputedPower;
891  poly g, fn;
892
893  if(e == 0) { return(1);}
894  if(e == 1) { return(f);}
895  if(f == 0) { return(1); }
896  else {
897
898    // test if f has been computed to some power
899
900    if(computedPowers[varIndex][1] > 0) {
901      maxPrecomputedPower = computedPowers[varIndex][1];
902      if(maxPrecomputedPower >= e) {
903        // no computation necessary, f^e has already benn computed
904        g = computedPowers[varIndex][2][e - 1];
905        //Print("No computation, from list : g = elem [", varIndex, ", 2, ", e - 1, "]");
906        lb = e + 1;
907      }
908      else {  // f^d computed, where d < e
909        g = computedPowers[varIndex][2][maxPrecomputedPower - 1];
910        ordOfg = maxPrecomputedPower * wt[varIndex];
911        lb = maxPrecomputedPower + 1;
912      }
913    }
914    else {    // no precomputed data
915      lb = 2;
916      ordOfg = wt[varIndex];
917      g = f;
918    }
919    for(i = lb; i <= e; i = i + 1) {
920      fn = jet(f, ub - ordOfg - 1, wt); // reduce w.r.t. reduceI
921      g = PolyProduct(g, fn, reduceI, wt, ub);
922      ordOfg = ordOfg + wt[varIndex];
923      if(g == 0) { break; }
924      if((i > maxPrecomputedPower) && !truncated) {
925        if(maxPrecomputedPower == 0) {  // init computedPowers
926          computedPowers[varIndex] = list(i, list(g));
927        }
928        computedPowers[varIndex][1] = i;  // new degree
929        computedPowers[varIndex][2][i - 1] = g;
930        maxPrecomputedPower = i;
931      }
932    }
933  }
934  return(g);
935}
936
937///////////////////////////////////////////////////////////////////////////////
938
939proc Num(int i)
940// Type : void
941// Purpose : set basering R, poly f and weight w to ...
942{
943  string p = "poly f = " + example_poly[i];
944  //string str = "wt = " + example_weight[ex_nr5 + i - 1] + ";";
945  string r = "ring R = 0, (" + example_vars[i] + "), ls;";
946  //execute(str);
947  execute(r);
948  execute(p);
949  wt = weight(f);
950  keepring R;
951}
952
953///////////////////////////////////////////////////////////////////////////////
954
955proc RingVarsToList(list @index)
956{
957  int i;
958  list temp;
959
960  for(i = 1; i <= size(@index); i = i + 1) { temp[i] = string(var(@index[i])); }
961  return(temp);
962}
963
964///////////////////////////////////////////////////////////////////////////////
965
966proc APSubstitution(poly f, ideal substitution, ideal reduceIdeal, intvec wt, int ub, int nrs, int nrt)
967"USAGE:   APSubstitution(f, subs, reduceI, w, ub, int nrs, int nrt); poly f
968         ideal subs, reduceI, intvec w, int ub, nrs, nrt;
969         nrs = number of parameters s(1..nrs),
970         nrt = number of parameters t(1..nrt)
971PURPOSE: substitute 'subs' in f, omit all terms with weighted degree > ub and
972         reduce the result w.r.t. 'reduceI'.
973RETURN:  poly
974GLOBAL:  'computedPowers'
975"
976{
977  int i, j, k, d, offset;
978  int n = nvars(basering);
979  list  coeffList, parts, degVecList, degOfMonos;
980  list computedPowers, truncatedQ, degOfSubs, @temp;
981  string ringSTR, @ringVars;
982
983  export(computedPowers);
984
985  // store arguments in strings
986
987  def RASB = basering;
988
989  parts = MonosAndTerms(f, wt, ub);
990  for(i = 1; i <= size(parts[1]); i = i + 1) {
991    coeffList[i] = parts[2][i]/parts[1][i];
992    degVecList[i] = leadexp(parts[1][i]);
993    degOfMonos[i] = deg(parts[1][i], wt);
994  }
995
996  // built new basering with no parameters and order dp !
997  // the parameters of the basering are appended to
998  // the variables of the basering !
999  // set ideal mpoly = minpoly for reduction !
1000
1001  @ringVars = "(" + varstr(basering) + ", " + parstr(1) + ",";  // precondition
1002  if(nrs > 0) {
1003    @ringVars = @ringVars + "s(1.." + string(nrs) + "), ";
1004  }
1005  @ringVars = @ringVars + "t(1.." + string(nrt) + "))";
1006  ringSTR = "ring RASR = 0, " + @ringVars + ", dp;";    // new basering
1007
1008  // built the "reduction" ring with the reduction ideal
1009
1010  execute(ringSTR);
1011  export(RASR);
1012  ideal reduceIdeal, substitution, newSubs;
1013  intvec w1, degVec;
1014  list minDeg, coeffList, degList;
1015  poly f, g, h, subsPoly;
1016
1017  w1 = wt;            // new weights
1018  offset = nrs + nrt + 1;
1019  for(i = n + 1; i <= offset + n; i = i + 1) { w1[i] = 0; }
1020
1021  reduceIdeal = std(imap(RASB, reduceIdeal)); // omit later !
1022  coeffList = imap(RASB, coeffList);
1023  substitution = imap(RASB, substitution);
1024
1025  f = imap(RASB, f);
1026
1027  for(i = 1; i <= n; i = i + 1) {      // all "base" variables
1028    computedPowers[i] = list(0);
1029    for(j = 1; j <= size(substitution[i]); j = j + 1) { degList[j] = deg(substitution[i][j], w1);}
1030    degOfSubs[i] = degList;
1031  }
1032
1033  // substitute in each monomial seperately
1034
1035  g = 0;
1036  for(i = 1; i <= size(degVecList); i = i + 1) {
1037    truncatedQ = Table("0", "i", 1, n);
1038    newSubs = 0;
1039    degVec = degVecList[i];
1040    d = degOfMonos[i];
1041
1042    // check if some terms in the substitution can be omitted
1043    // degVec = list of exponents of the monomial m
1044    // minDeg[j] denotes the weighted degree of the monomial m'
1045    // where m' is the monomial m without the j-th variable
1046
1047    for(j = 1; j <= size(degVec); j = j + 1) { minDeg[j] = d - degVec[j] * wt[j]; }
1048
1049    for(j = 1; j <= size(degVec); j = j + 1) {
1050      subsPoly = 0;      // set substitution to 0
1051      if(degVec[j] > 0) {
1052
1053        // if variable occurs then check if
1054        // substitution[j][k] * (linear part)^(degVec[j]-1) + minDeg[j] < ub
1055        // i.e. look for the smallest possible combination in subs[j]^degVec[j]
1056        // which comes from the term substitution[j][k]. This term is multiplied
1057        // with the rest of the monomial, which has at least degree minDeg[j].
1058        // If the degree of this product is < ub then substitution[j][k] contributes
1059        // to the result and cannot be omitted
1060
1061        for(k = 1; k <= size(substitution[j]); k = k + 1) {
1062          if(degOfSubs[j][k] + (degVec[j] - 1) * wt[j] + minDeg[j]  < ub) {
1063            subsPoly = subsPoly + substitution[j][k];
1064          }
1065        }
1066      }
1067      newSubs[j] = subsPoly;        // set substitution
1068      if(substitution[j] - subsPoly != 0) { truncatedQ[j] = 1;}  // mark that substitution[j] is truncated
1069    }
1070    h = Expand(newSubs, degVec, reduceIdeal, w1, ub, truncatedQ) * coeffList[i];  // already reduced
1071    g = reduce(g + h, reduceIdeal);
1072  }
1073   kill(computedPowers);
1074  setring RASB;
1075  poly fnew = imap(RASR, g);
1076  kill(RASR);
1077  return(fnew);
1078}
1079
1080///////////////////////////////////////////////////////////////////////////////
1081
1082static proc StabVar(intvec wt)
1083"USAGE:   StabVar(w); intvec w
1084PURPOSE: compute the indicies for quasihomogeneous substitutions of each
1085         variable.
1086ASSUME:  f semiquasihomogeneous polynomial with an isolated singularity at 0
1087RETURN:  list
1088         _[i]  list of combinations for var(i) (i must be appended
1089         to each comb)
1090GLOBAL:  'varSubsList', contains the index j s.t. x(i) -> x(i)t(j) ...
1091"
1092{
1093  int i, j, k, uw, ic;
1094  list varList, variables, subs;
1095  string str, varString;
1096
1097  varList = StabVarComb(wt);
1098  for(i = 1; i <= size(wt); i = i + 1) {
1099    subs = 0;
1100
1101    // built linear substituitons
1102    for(j = 1; j <= size(varList[1][i]); j = j + 1) {
1103      subs[j] = list(i) + list(varList[1][i][j]);
1104    }
1105    variables[i] = subs;
1106    if(size(varList[2][i]) > 0) {
1107
1108      // built nonlinear substituitons
1109      subs = 0;
1110      for(j = 1; j <= size(varList[2][i]); j = j + 1) {
1111        subs[j] = list(i) + varList[2][i][j];
1112      }
1113      variables[i] = variables[i] + subs;
1114    }
1115  }
1116  return(variables);
1117}
1118
1119///////////////////////////////////////////////////////////////////////////////
1120
1121static proc StabVarComb(intvec wt)
1122"USAGE:   StabVarComb(w); intvec w
1123PURPOSE: list all possible indices of indeterminates for a quasihom. subs.
1124RETURN:  list
1125         _[1] linear substitutions
1126         _[2] nonlinear substiutions
1127GLOBAL: 'varSubsList', contains the index j s.t. x(i) -> x(i)t(j) ...
1128"
1129{
1130  int mi, ma, i, j, k, uw, ic;
1131  list index, indices, usedWeights, combList, combinations;
1132  list linearSubs, nonlinearSubs;
1133  list partitions, subs, temp;        // subs[i] = substitution for var(i)
1134
1135  linearSubs = Table("0", "i", 1, size(wt));
1136  nonlinearSubs = Table("0", "i", 1, size(wt));
1137
1138  uw = 0;
1139  ic = 0;
1140  mi = Min(wt);
1141  ma = Max(wt);
1142
1143  for(i = mi; i <= ma; i = i + 1) {
1144    if(ContainedQ(wt, i)) {    // find variables of weight i
1145      k = 0;
1146      index = 0;
1147      // collect the indices of all variables of weight i
1148      for(j = 1; j <= size(wt); j = j + 1) {
1149        if(wt[j] == i) {
1150          k = k + 1;
1151          index[k] = j;
1152        }
1153      }
1154      uw = uw + 1;
1155      usedWeights[uw] = i;
1156      ic = ic + 1;
1157      indices[i] = index;
1158
1159      // linear part of the substitution
1160
1161      for(j = 1; j <= size(index); j = j + 1) {
1162        linearSubs[index[j]] = index;
1163      }
1164
1165      // nonlinear part of the substitution
1166
1167      if(uw > 1) {    // variables of least weight do not allow nonlinear subs.
1168
1169      partitions = Partitions(i, delete(usedWeights, uw));
1170      for(j = 1; j <= size(partitions); j = j + 1) {
1171        combinations[j] = AllCombinations(partitions[j], indices);
1172      }
1173      for(j = 1; j <= size(index); j = j + 1) {
1174        nonlinearSubs[index[j]] = FlattenQHM(combinations);   // flatten one level !
1175      }
1176
1177      } // end if
1178
1179    }
1180  }
1181  combList[1] = linearSubs;
1182  combList[2] = nonlinearSubs;
1183  return(combList);
1184}
1185
1186///////////////////////////////////////////////////////////////////////////////
1187
1188proc AllCombinations(list partition, list indices)
1189"USAGE:   AllCombinations(partition,indices); list partition, indices)
1190PURPOSE: all combinations for a given partititon
1191RETURN:  list
1192GLOBAL: varSubsList, contains the index j s.t. x(i) -> x(i)t(j) ...
1193"
1194{
1195  int i, k, m, ok, p, offset;
1196  list nrList, indexList;
1197
1198  k = 0;
1199  offset = 0;
1200  i = 1;
1201  ok = 1;
1202  m = partition[1];
1203  while(ok) {
1204    if(i > size(partition)) {
1205      ok = 0;
1206      p = 0;
1207    }
1208    else { p = partition[i];}
1209    if(p == m) { i = i + 1;}
1210    else {
1211      k = k + 1;
1212      nrList[k] = i - 1 - offset;
1213      offset = offset + i - 1;
1214      indexList[k] = indices[m];
1215      if(ok) { m = partition[i];}
1216    }
1217  }
1218  return(AllCombinationsAux(nrList, indexList));
1219}
1220
1221///////////////////////////////////////////////////////////////////////////////
1222
1223proc AllSingleCombinations(int n, list index)
1224"USAGE:   AllSingleCombinations(n index); int n, list index
1225PURPOSE: all combinations for var(n)
1226RETURN:  list
1227"
1228{
1229  int i, j, k;
1230  list comb, newC, temp, newIndex;
1231
1232  if(n == 1) {
1233    for(i = 1; i <= size(index); i = i + 1) {
1234      temp = index[i];
1235      comb[i] = temp;
1236    }
1237    return(comb);
1238  }
1239  if(size(index) == 1) {
1240    temp = Table(string(index[1]), "i", 1, n);
1241    comb[1] = temp;
1242    return(comb);
1243  }
1244  newIndex = index;
1245  for(i = 1; i <= size(index); i = i + 1) {
1246    if(i > 1) { newIndex = delete(newIndex, 1); }
1247    newC = AllSingleCombinations(n - 1, newIndex);
1248    k = size(comb);
1249    temp = 0;
1250    for(j = 1; j <= size(newC); j = j + 1) {
1251      temp[1] = index[i];
1252      temp = temp + newC[j];
1253      comb[k + j] = temp;
1254      temp = 0;
1255    }
1256  }
1257  return(comb);
1258}
1259
1260///////////////////////////////////////////////////////////////////////////////
1261
1262proc AllCombinationsAux(list parts, list index)
1263"USAGE:  AllCombinationsAux(parts ,index); list parts, index
1264PURPOSE: all compbinations for nonlinear substituiton
1265RETURN:  list
1266"
1267{
1268  int i, j, k;
1269  list comb, firstC, restC;
1270
1271  if(size(parts) == 0 || size(index) == 0) { return(comb);}
1272
1273  firstC = AllSingleCombinations(parts[1], index[1]);
1274  restC = AllCombinationsAux(delete(parts, 1), delete(index, 1));
1275
1276  if(size(restC) == 0) { comb = firstC;}
1277  else {
1278    for(i = 1; i <= size(firstC); i = i + 1) {
1279      k = size(comb);
1280      for(j = 1; j <= size(restC); j = j + 1) {
1281        //elem = firstC[i] + restC[j];
1282        // comb[k + j] = elem;
1283        comb[k + j] = firstC[i] + restC[j];
1284      }
1285    }
1286  }
1287  return(comb);
1288}
1289
1290///////////////////////////////////////////////////////////////////////////////
1291
1292proc Partitions(int n, list nr)
1293"USAGE:   Partitions(n, nr); int n, list nr
1294PURPOSE: partitions of n consisting of elements from nr
1295RETURN:  list
1296"
1297{
1298  int i, j, k;
1299  list parts, temp, restP, newP, decP;
1300
1301  if(size(nr) == 0) { return(list());}
1302  if(size(nr) == 1) {
1303    if(NumFactor(nr[1], n) > 0) {
1304      parts[1] = Table(string(nr[1]), "i", 1, NumFactor(nr[1], n));
1305    }
1306    return(parts);
1307  }
1308  else {
1309    parts =  Partitions(n, nr[1]);
1310    restP = Partitions(n, delete(nr, 1));
1311
1312    parts = parts + restP;
1313    for(i = 1; i <= n / nr[1]; i = i + 1) {
1314      temp = Table(string(nr[1]), "i", 1, i);
1315      decP = Partitions(n - i*nr[1], delete(nr, 1));
1316      k = size(parts);
1317      for(j = 1; j <= size(decP); j = j + 1) {
1318        newP = temp + decP[j];        // new partition
1319        if(!ContainedQ(parts, newP, 1)) {
1320          k = k + 1;
1321          parts[k] = newP;
1322        }
1323      }
1324    }
1325  }
1326  return(parts);
1327}
1328
1329///////////////////////////////////////////////////////////////////////////////
1330
1331proc NumFactor(int a, int b)
1332" USAGE: NumFactor(a, b); int a, b
1333PURPOSE: if b divides a then return b/a, else return 0
1334RETURN:  int
1335"
1336{
1337  int c = int(b/a);
1338  if(c*a == b) { return(c); }
1339  else {return(0)}
1340}
1341
1342///////////////////////////////////////////////////////////////////////////////
1343
1344proc Table(string cmd, string iterator, int lb, int ub)
1345" USAGE: Table(cmd,i, lb, ub); string cmd, i; int lb, ub
1346PURPOSE: generate a list of size ub - lb + 1 s.t. _[i] = cmd(i)
1347RETURN:  list
1348"
1349{
1350  list data;
1351  execute("int " + iterator + ";");
1352
1353  for(int @i = lb; @i <= ub; @i++) {
1354    execute(iterator + " = " + string(@i));
1355    execute("data[" + string(@i) + "] = " + cmd + ";");
1356  }
1357  return(data);
1358}
1359
1360///////////////////////////////////////////////////////////////////////////////
1361
1362static proc FlattenQHM(list data)
1363" USAGE: FlattenQHM(n, nr); list data
1364PURPOSE: flatten the list (one level) 'data', which is a list of lists
1365RETURN:  list
1366"
1367{
1368  int i, j, c;
1369  list fList, temp;
1370
1371  c = 1;
1372
1373  for(i = 1; i <= size(data); i = i + 1) {
1374    for(j = 1; j <= size(data[i]); j = j + 1) {
1375      fList[c] = data[i][j];
1376      c = c + 1;
1377    }
1378  }
1379  return(fList);
1380}
1381
1382///////////////////////////////////////////////////////////////////////////////
1383
1384static proc IntersectionQHM(list l1, list l2)
1385// Type : list
1386// Purpose : Intersection of l1 and l2
1387{
1388  list l;
1389  int b, c;
1390
1391  c = 1;
1392
1393  for(int i = 1; i <= size(l1); i = i + 1) {
1394    b = ContainedQ(l2, l1[i]);
1395    if(b == 1) {
1396      l[c] = l1[i];
1397      c = c + 1;
1398    }
1399  }
1400  return(l);
1401}
1402
1403///////////////////////////////////////////////////////////////////////////////
1404
1405static proc FirstEntryQHM(data, elem)
1406// Type : int
1407// Purpose : position of first entry equal to elem in data (from left to right)
1408{
1409  int i, pos;
1410
1411  i = 0;
1412  pos = 0;
1413  while(!pos && i < size(data)) {
1414    i = i + 1;
1415    if(data[i] == elem) { pos = i;}
1416  }
1417  return(pos);
1418}
1419
1420///////////////////////////////////////////////////////////////////////////////
1421
1422static proc PSum(e)
1423{
1424  poly f;
1425  for(int i = 1; i <= size(e); i = i + 1) {
1426    f = f + e[i];
1427  }
1428  return(f);
1429
1430}
1431
1432///////////////////////////////////////////////////////////////////////////////
1433
1434proc Max(data)
1435"USAGE:   Max(data); intvec/list of integers data
1436PURPOSE: find the maximal integer contained in 'data'
1437RETURN:  list
1438ASSUME:  'data' contians only integers and is not empty
1439"
1440{
1441  int i;
1442  int max = data[1];
1443
1444  for(i = 1; i <= size(data); i = i + 1) {
1445    if(data[i] > max) { max = data[i]; }
1446  }
1447  return(max);
1448}
1449
1450///////////////////////////////////////////////////////////////////////////////
1451
1452proc Min(data)
1453"USAGE:   Min(data); intvec/list of integers data
1454PURPOSE: find the minimal integer contained in 'data'
1455RETURN:  list
1456ASSUME:  'data' contians only integers and is not empty
1457"
1458{
1459  int i;
1460  int min = data[1];
1461
1462  for(i = 1; i <= size(data); i = i + 1) {
1463    if(data[i] < min) { min = data[i]; }
1464  }
1465  return(min);
1466}
1467
1468///////////////////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.