source: git/Singular/LIB/qhmoduli.lib @ 238c959

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