source: git/Singular/LIB/qhmoduli.lib @ 5d21375

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