source: git/Singular/LIB/qhmoduli.lib @ 70597c

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