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