source: git/Singular/LIB/qhmoduli.lib @ 797d4f

spielwiese
Last change on this file since 797d4f was 334c21f, checked in by Hans Schönemann <hannes@…>, 15 years ago
*hannes: syntax fix git-svn-id: file:///usr/local/Singular/svn/trunk@11696 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 44.6 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2version="$Id: qhmoduli.lib,v 1.17 2009-04-14 12:08:36 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++)
495  {
496    nrVars = nrVars + size(Variables[i]);
497  }
498
499  // set the new basering needed for the substitutions
500
501  varString = "s(1.." + string(nrVars) + ")";
502  if(npars(basering) == 1)
503  {
504    parString = "(0, " + parstr(basering) + ")";
505  }
506  else { parString = "0"; }
507
508  def RSTB = basering;
509  mPoly = minpoly;
510  ringSTR = "ring RSTR = " + parString + ", (" + varstr(basering) + ", " + varString + "), dp;";  // dp
511        ringSTR1 = "ring RSTT = " + parString + ", (" + varString + ", " + varstr(basering) + "), dp;";
512
513  if(defined(RSTR)) { kill RSTR;}
514        if(defined(RSTT)) { kill RSTT;}
515        execute(ringSTR1);      // this ring is only used for the result, where the variables
516  export(RSTT);           // are s(1..m),t(1..n), as needed for Derksens algorithm (NullCone)
517  minpoly = number(imap(RSTB, mPoly));
518
519  execute(ringSTR);
520  export(RSTR);
521  minpoly = number(imap(RSTB, mPoly));
522  poly f, f1, g, h, vars, pp;      // f1 is the polynomial after subs,
523  ideal allEqns, qhsubs, actionid, stabid, J;
524  list ringList;          // all t(i)`s which do not appear in f1
525  ideal data = simplify(imap(RSTB, data), 2);
526
527  // generate the quasihomogeneous substitution map F
528
529  nrVars = 0;
530  offset = 0;
531  for(i = 1; i <= size(wt); i++)
532  {    // build the substitution t(i) -> ...
533    if(i > 1) { offset = offset + size(Variables[i - 1]); }
534    g = 0;
535    for(j = 1; j <= size(Variables[i]); j++)
536    {
537      pp = 1;
538      for(k = 2; k <= size(Variables[i][j]); k++)
539      {
540        pp = pp * var(Variables[i][j][k]);
541        if(Variables[i][j][k] == i) { varSubsList[i] = offset + j;}
542      }
543      g = g + s(offset + j) * pp;
544    }
545    qhsubs[i] = g;
546  }
547  dbprint(dbPrt, "  qhasihomogenous substituion =" + string(qhsubs));
548  map F = RSTR, qhsubs;
549  kill varSubsList;
550
551  // get the equations of the stabilizer by comparing coefficients
552  // in the equation f = F(f).
553
554  vars = RingVarProduct(Table("i", "i", 1, size(wt)));
555
556  allEqns = 0;
557
558  matrix newcoMx, coMx;
559  int d;
560  for(r = 1; r <= ncols(data); r++)
561  {
562
563  f = data[r];
564  f1 = F(f);
565  d = deg(f);
566  newcoMx = coef(f1, vars);        // coefficients of F(f)
567  coMx = coef(f, vars);          // coefficients of f
568
569  for(i = 1; i <= ncols(newcoMx); i++)
570  {      // build the system of eqns via coeff. comp.
571    j = 1;
572    h = 0;
573    while(j <= ncols(coMx))
574    {        // all monomials in f
575      if(coMx[j][1] == newcoMx[i][1]) { h = coMx[j][2]; j = ncols(coMx) + 1;}
576      else {j = j + 1;}
577    }
578    J = J, newcoMx[i][2] - h;        // add equation
579  }
580  allEqns =  allEqns, J;
581
582  }
583  allEqns = std(allEqns);
584
585  // simplify the equations, i.e., if s(i) in J then remove s(i) from J
586  // and from the basering
587
588  sList = SimplifyIdeal(allEqns, n, "s");
589  stabid = sList[1];
590  map phi = basering, sList[2];
591        sln = size(sList[3]) - n;
592
593  // change the substitution
594
595  actionid = phi(qhsubs);
596
597        // change to new ring, auxillary construction
598
599        setring(RSTT);
600        ideal actionid, stabid;
601
602        actionid = imap(RSTR, actionid);
603        stabid = imap(RSTR, stabid);
604        export(stabid);
605  export(actionid);
606  ringList[2] = RSTT;
607
608  dbprint(dbPrt, "  substitution = " + string(actionid));
609  dbprint(dbPrt, "  equations of stabilizer = " + string(stabid));
610
611  varString = "s(1.." + string(sln) + ")";
612  ringSTR = "ring RSTS = " + parString + ", (" + varString + "), dp;";
613  execute(ringSTR);
614  minpoly = number(imap(RSTB, mPoly));
615  ideal stabid = std(imap(RSTR, stabid));
616  export(stabid);
617  ringList[1] = RSTS;
618dbprint(dbPrt, "
619// 'StabEqnId' created a list of 2 rings.
620// To see the rings, type (if the name of your list is stab):
621     show(stab);
622// To access the 1-st ring and map (and similair for the others), type:
623     def S1 = stab[1]; setring S1;  stabid;
624// S1/stabid is the coordinate ring of the variety of the
625// stabilizer, say G. If G x K^n --> K^n is the action of G on
626// K^n, then the ideal 'actionid' in the second ring describes
627// the dual map on the ring level.
628// To access the 2-nd ring and map (and similair for the others), type:
629     def S2 = stab[2]; setring S2;  actionid;
630");
631  return(ringList);
632}
633example
634{"EXAMPLE:";  echo = 2;
635  ring B   = 0,(x,y,z), ls;
636  ideal I = x2,y3,z6;
637  intvec w = 3,2,1;
638  list stab = StabEqnId(I, w);
639  def S1 = stab[1]; setring S1;  stabid;
640  def S2 = stab[2]; setring S2;  actionid;
641}
642
643///////////////////////////////////////////////////////////////////////////////
644static
645proc ArnoldFormMain(poly f, B, poly Fs, ideal reduceIdeal, int nrs, int nrt)
646"USAGE:   ArnoldFormMain(f, B, Fs, rI, nrs, nrt);
647   poly f,Fs; ideal B, rI; int nrs, nrt
648PURPOSE: compute the induced action of 'G_f' on T_, where f is the principal
649         part and 'Fs' is the semiuniversal unfolding of 'f' with x_i
650         substituted by actionid[i], 'B' is a list of upper basis monomials
651         for the milnor algebra of 'f', 'nrs' = number of variables for 'G_f'
652         and 'nrt' = dimension of T_
653ASSUME:  f is quasihomogeneous with an isolated singularity at 0,
654         s(1..r), t(1..m) are parameters of the basering
655RETURN:  poly
656EXAMPLE: example ArnoldAction; shows an example
657"
658{
659  int i, j, d, ub, dbPrt;
660  list upperBasis, basisDegList, gmonos, common, parts;
661  ideal jacobianId, jacobIdstd, mapId;    // needed for phi
662  intvec wt = weight(f);
663  matrix gCoeffMx;        // for lift command
664  poly newFs, g, gred, tt;        // g = sum of all monomials of degree d, gred is needed for lift
665  map phi;          // the map from Arnold's Theorem
666
667  dbPrt = printlevel-voice+2;
668  jacobianId = jacob(f);
669  jacobIdstd = std(jacobianId);
670  newFs = Fs;
671  for(i = 1; i <= size(B); i++)
672  {
673    basisDegList[i] = deg(B[i], wt);
674  }
675  ub = Max(basisDegList) + 1;          // max degree of an upper monomial
676
677  parts = MonosAndTerms(newFs - f, wt, ub);
678  gmonos = parts[1];
679  d = deg(f, wt);
680
681  for(i = d + 1; i < ub; i++)
682  {    // base[1] = monomials of degree i
683    upperBasis[i] = SelectMonos(list(B, B), wt, i);    // B must not contain 0's
684  }
685
686  // test if each monomial of Fs is contained in B, if not,
687  // compute a substitution via Arnold's theorem and substitutite
688  // it into newFs
689
690  for(i = d + 1; i < ub; i = i + 1)
691  {  // ub instead of @UB
692    dbprint(dbPrt, "-- degree = " + string(i) + " of " + string(ub - 1) + " ---------------------------");
693    if(size(newFs) < 80) { dbprint(dbPrt, "  polynomial = " + string(newFs - f));}
694    else {  dbprint(dbPrt, "  poly has deg (not weighted) " + string(deg(newFs)) + " and contains " + string(size(newFs)) + " monos");}
695
696    // select monomials of degree i and intersect them with upperBasis[i]
697
698    gmonos = SelectMonos(parts, wt, i);
699    common = IntersectionQHM(upperBasis[i][1], gmonos[1]);
700    if(size(common) == size(gmonos[1]))
701    {
702      dbprint(dbPrt, " no additional monomials ");
703    }
704
705    // other monomials than those in upperBasis occur, compute
706    // the map constructed in the proof of Arnold's theorem
707    // write g = c[i] * jacobianId[i]
708
709    else
710    {
711      dbprint(dbPrt, "  additional Monomials found, compute the map ");
712      g = PSum(gmonos[2]);      // sum of all monomials in g of degree i
713      dbprint(dbPrt, "  sum of degree " + string(i) + " is " + string(g));
714
715      gred = reduce(g, jacobIdstd);
716      gCoeffMx = lift(jacobianId, g - gred);    // compute c[i]
717      mapId = var(1) - gCoeffMx[1][1];    // generate the map
718      for(j = 2; j <= size(gCoeffMx); j++)
719      {
720        mapId[j] = var(j) - gCoeffMx[1][j];
721      }
722      dbprint(dbPrt, "  map = " + string(mapId));
723      // apply the map to newFs
724      newFs = APSubstitution(newFs, mapId, reduceIdeal, wt, ub, nrs, nrt);
725      parts = MonosAndTerms(newFs - f, wt, ub);  // monos and terms of deg < ub
726      newFs = PSum(parts[2]) + f;      // result of APS... is already reduced
727      dbprint(dbPrt, "  monomials of degree " + string(i));
728    }
729  }
730  return(newFs);
731}
732
733///////////////////////////////////////////////////////////////////////////////
734
735static proc MonosAndTerms(poly f, wt, int ub)
736"USAGE:   MonosAndTerms(f, w, ub); poly f, intvec w, int ub
737PURPOSE: returns a list of all monomials and terms occuring in f of
738         weighted degree < ub
739RETURN:  list
740         _[1]  list of monomials
741         _[2]  list of terms
742EXAMPLE: example MonosAndTerms shows an example
743"
744{
745  int i, k;
746  list monomials, terms;
747  poly mono, lcInv, data;
748
749  data = jet(f, ub - 1, wt);
750  k = 0;
751  for(i = 1; i <= size(data); i++)
752  {
753    mono = lead(data[i]);
754    if(deg(mono, wt) < ub)
755    {
756      k = k + 1;
757      lcInv = 1/leadcoef(mono);
758      monomials[k] = mono * lcInv;
759      terms[k] = mono;
760    }
761  }
762  return(list(monomials, terms));
763}
764example
765{"EXAMPLE:";  echo = 2;
766  ring B = 0,(x,y,z), lp;
767  poly f = 6*x2 + 2*x3 + 9*x*y2 + z*y + x*z6;
768  MonosAndTerms(f, intvec(2,1,1), 5);
769}
770
771///////////////////////////////////////////////////////////////////////////////
772
773static proc SelectMonos(parts, intvec wt, int d)
774"USAGE:   SelectMonos(parts, w, d); list/ideal parts, intvec w, int d
775PURPOSE: returns a list of all monomials and terms occuring in f of
776         weighted degree = d
777RETURN:  list
778         _[1]  list of monomials
779         _[2]  list of terms
780EXAMPLE: example SelectMonos; shows an example
781"
782{
783  int i, k;
784  list monomials, terms;
785  poly mono;
786
787  k = 0;
788  for(i = 1; i <= size(parts[1]); i++)
789  {
790    mono = parts[1][i];
791    if(deg(mono, wt) == d)
792    {
793      k++;
794      monomials[k] = mono;
795      terms[k] = parts[2][i];
796    }
797  }
798  return(list(monomials, terms));
799}
800example
801{"EXAMPLE:";  echo = 2;
802  ring B = 0,(x,y,z), lp;
803  poly f = 6*x2 + 2*x3 + 9*x*y2 + z*y + x*z6;
804  list mt =  MonosAndTerms(f, intvec(2,1,1), 5);
805  SelectMonos(mt, intvec(2,1,1), 4);
806}
807
808///////////////////////////////////////////////////////////////////////////////
809
810static proc Expand(substitution, degVec, ideal reduceI, intvec w1, int ub, list truncated)
811"USAGE:   Expand(substitution, degVec, reduceI, w, ub, truncated);
812         ideal/list substitution, list/intvec degVec, ideal reduceI, intvec w,
813         int ub, list truncated
814PURPOSE: substitute 'substitution' in the monomial given by the list of
815         exponents 'degVec', omit all terms of weighted degree > ub and reduce
816         the result w.r.t. 'reduceI'. If truncated[i] = 0 then the result is
817         stored for later use.
818RETURN:  poly
819NOTE:    used by APSubstitution
820GLOBAL:  computedPowers
821"
822{
823  int i, minDeg;
824  list powerList;
825  poly g, h;
826
827  // compute substitution[1]^degVec[1],...,subs[n]^degVec[n]
828
829  for(i = 1; i <= ncols(substitution); i++)
830  {
831    if(size(substitution[i]) < 3 || degVec[i] < 4)
832    {
833      powerList[i] = reduce(substitution[i]^degVec[i], reduceI); // new
834    }  // directly for small exponents
835    else
836    {
837      powerList[i] = PolyPower1(i, substitution[i], degVec[i], reduceI, w1, truncated[i], ub);
838    }
839  }
840  // multiply the terms obtained by using PolyProduct();
841  g = powerList[1];
842  minDeg = w1[1] * degVec[1];
843  for(i = 2; i <= ncols(substitution); i++)
844  {
845    g = jet(g, ub - w1[i] * degVec[i] - 1, w1);
846    h = jet(powerList[i], ub - minDeg - 1, w1);
847    g = PolyProduct(g, h, reduceI, w1, ub);
848    if(g == 0) { Print(" g = 0 "); break;}
849    minDeg = minDeg + w1[i] * degVec[i];
850  }
851  return(g);
852}
853
854///////////////////////////////////////////////////////////////////////////////
855
856static proc PolyProduct(poly g1, poly h1, ideal reduceI, intvec wt, int ub)
857"USAGE:   PolyProduct(g, h, reduceI, wt, ub); poly g, h; ideal reduceI,
858          intvec wt, int ub.
859PURPOSE: compute g*h and reduce it w.r.t 'reduceI' and omit terms of weighted
860         degree > ub.
861RETURN:  poly
862NOTE:    used by 'Expand'
863"
864{
865  int SUBSMAXSIZE = 3000;
866  int i, nrParts, sizeOfPart, currentPos, partSize, maxSIZE;
867  poly g, h, gxh, prodComp, @g2;    // replace @g2 by subst.
868
869  g = g1;
870  h = h1;
871
872  if(size(g)*size(h) > SUBSMAXSIZE)
873  {
874    // divide the polynomials with more terms in parts s.t.
875    // the product of each part with the other polynomial
876    // has at most SUBMAXSIZE terms
877
878    if(size(g) < size(h)) { poly @h = h; h = g; g = @h;@h = 0; }
879    maxSIZE = SUBSMAXSIZE / size(h);
880    //print(" SUBSMAXSIZE = "+string(SUBSMAXSIZE)+" exceeded by "+string(size(g)*size(h)) + ", maxSIZE = ", string(maxSIZE));
881    nrParts = size(g) / maxSIZE + 1;
882    partSize = size(g) / nrParts;
883    gxh = 0;  // 'g times h'
884    for(i = 1; i <= nrParts; i++)
885    {
886      //print(" loop #" + string(i) + " of " + string(nrParts));
887      currentPos = (i - 1) * partSize;
888      if(i < nrParts) {sizeOfPart = partSize;}
889      else { sizeOfPart = size(g) - (nrParts - 1) * partSize; print(" last #" + string(sizeOfPart) + " terms ");}
890      prodComp = g[currentPos + 1..sizeOfPart + currentPos] * h;  // multiply a part
891      @g2 = jet(prodComp, ub - 1, wt);  // eventual reduce ...
892      if(size(@g2) < size(prodComp)) { print(" killed " + string(size(prodComp) - size(@g2)) + " terms ");}
893      gxh =  reduce(gxh + @g2, reduceI);
894    }
895  }
896  else
897  {
898    gxh = reduce(jet(g * h,ub - 1, wt), reduceI);
899  }  // compute directly
900  return(gxh);
901}
902
903///////////////////////////////////////////////////////////////////////////////
904
905static proc PolyPower1(int varIndex, poly f, int e, ideal reduceI, intvec wt,
906                       int truncated, int ub)
907"USAGE:   PolyPower1(i, f, e, reduceI, wt, truncated, ub);int i, e, ub;poly f;
908         ideal reduceI; intvec wt; list truncated;
909PURPOSE: compute f^e, use previous computations if possible, and reduce it
910         w.r.t reudecI and omit terms of weighted degree > ub.
911RETURN:  poly
912NOTE:    used by 'Expand'
913GLOBAL:  'computedPowers'
914"
915{
916  int i, ordOfg, lb, maxPrecomputedPower;
917  poly g, fn;
918
919  if(e == 0) { return(1);}
920  if(e == 1) { return(f);}
921  if(f == 0) { return(1); }
922  else
923  {
924    // test if f has been computed to some power
925    if(computedPowers[varIndex][1] > 0)
926    {
927      maxPrecomputedPower = computedPowers[varIndex][1];
928      if(maxPrecomputedPower >= e)
929      {
930        // no computation necessary, f^e has already benn computed
931        g = computedPowers[varIndex][2][e - 1];
932        //Print("No computation, from list : g = elem [", varIndex, ", 2, ", e - 1, "]");
933        lb = e + 1;
934      }
935      else {  // f^d computed, where d < e
936        g = computedPowers[varIndex][2][maxPrecomputedPower - 1];
937        ordOfg = maxPrecomputedPower * wt[varIndex];
938        lb = maxPrecomputedPower + 1;
939      }
940    }
941    else
942    {    // no precomputed data
943      lb = 2;
944      ordOfg = wt[varIndex];
945      g = f;
946    }
947    for(i = lb; i <= e; i++)
948    {
949      fn = jet(f, ub - ordOfg - 1, wt); // reduce w.r.t. reduceI
950      g = PolyProduct(g, fn, reduceI, wt, ub);
951      ordOfg = ordOfg + wt[varIndex];
952      if(g == 0) { break; }
953      if((i > maxPrecomputedPower) && !truncated)
954      {
955        if(maxPrecomputedPower == 0)
956        {  // init computedPowers
957          computedPowers[varIndex] = list(i, list(g));
958        }
959        computedPowers[varIndex][1] = i;  // new degree
960        computedPowers[varIndex][2][i - 1] = g;
961        maxPrecomputedPower = i;
962      }
963    }
964  }
965  return(g);
966}
967
968///////////////////////////////////////////////////////////////////////////////
969
970static proc RingVarsToList(list @index)
971{
972  int i;
973  list temp;
974
975  for(i = 1; i <= size(@index); i++) { temp[i] = string(var(@index[i])); }
976  return(temp);
977}
978
979///////////////////////////////////////////////////////////////////////////////
980static
981proc APSubstitution(poly f, ideal substitution, ideal reduceIdeal, intvec wt, int ub, int nrs, int nrt)
982"USAGE:   APSubstitution(f, subs, reduceI, w, ub, int nrs, int nrt); poly f
983         ideal subs, reduceI, intvec w, int ub, nrs, nrt;
984         nrs = number of parameters s(1..nrs),
985         nrt = number of parameters t(1..nrt)
986PURPOSE: substitute 'subs' in f, omit all terms with weighted degree > ub and
987         reduce the result w.r.t. 'reduceI'.
988RETURN:  poly
989GLOBAL:  'computedPowers'
990"
991{
992  int i, j, k, d, offset;
993  int n = nvars(basering);
994  list  coeffList, parts, degVecList, degOfMonos;
995  list computedPowers, truncatedQ, degOfSubs, @temp;
996  string ringSTR, @ringVars;
997
998  export(computedPowers);
999
1000  // store arguments in strings
1001
1002  def RASB = basering;
1003
1004  parts = MonosAndTerms(f, wt, ub);
1005  for(i = 1; i <= size(parts[1]); i = i + 1)
1006  {
1007    coeffList[i] = parts[2][i]/parts[1][i];
1008    degVecList[i] = leadexp(parts[1][i]);
1009    degOfMonos[i] = deg(parts[1][i], wt);
1010  }
1011
1012  // built new basering with no parameters and order dp !
1013  // the parameters of the basering are appended to
1014  // the variables of the basering !
1015  // set ideal mpoly = minpoly for reduction !
1016
1017  @ringVars = "(" + varstr(basering) + ", " + parstr(1) + ",";  // precondition
1018  if(nrs > 0)
1019  {
1020    @ringVars = @ringVars + "s(1.." + string(nrs) + "), ";
1021  }
1022  @ringVars = @ringVars + "t(1.." + string(nrt) + "))";
1023  ringSTR = "ring RASR = 0, " + @ringVars + ", dp;";    // new basering
1024
1025  // built the "reduction" ring with the reduction ideal
1026
1027  execute(ringSTR);
1028  export(RASR);
1029  ideal reduceIdeal, substitution, newSubs;
1030  intvec w1, degVec;
1031  list minDeg, coeffList, degList;
1032  poly f, g, h, subsPoly;
1033
1034  w1 = wt;            // new weights
1035  offset = nrs + nrt + 1;
1036  for(i = n + 1; i <= offset + n; i = i + 1) { w1[i] = 0; }
1037
1038  reduceIdeal = std(imap(RASB, reduceIdeal)); // omit later !
1039  coeffList = imap(RASB, coeffList);
1040  substitution = imap(RASB, substitution);
1041
1042  f = imap(RASB, f);
1043
1044  for(i = 1; i <= n; i++)
1045  {      // all "base" variables
1046    computedPowers[i] = list(0);
1047    for(j = 1; j <= size(substitution[i]); j++) { degList[j] = deg(substitution[i][j], w1);}
1048    degOfSubs[i] = degList;
1049  }
1050
1051  // substitute in each monomial seperately
1052
1053  g = 0;
1054  for(i = 1; i <= size(degVecList); i++)
1055  {
1056    truncatedQ = Table("0", "i", 1, n);
1057    newSubs = 0;
1058    degVec = degVecList[i];
1059    d = degOfMonos[i];
1060
1061    // check if some terms in the substitution can be omitted
1062    // degVec = list of exponents of the monomial m
1063    // minDeg[j] denotes the weighted degree of the monomial m'
1064    // where m' is the monomial m without the j-th variable
1065
1066    for(j = 1; j <= size(degVec); j++) { minDeg[j] = d - degVec[j] * wt[j]; }
1067
1068    for(j = 1; j <= size(degVec); j++)
1069    {
1070      subsPoly = 0;      // set substitution to 0
1071      if(degVec[j] > 0)
1072      {
1073        // if variable occurs then check if
1074        // substitution[j][k] * (linear part)^(degVec[j]-1) + minDeg[j] < ub
1075        // i.e. look for the smallest possible combination in subs[j]^degVec[j]
1076        // which comes from the term substitution[j][k]. This term is multiplied
1077        // with the rest of the monomial, which has at least degree minDeg[j].
1078        // If the degree of this product is < ub then substitution[j][k] contributes
1079        // to the result and cannot be omitted
1080
1081        for(k = 1; k <= size(substitution[j]); k++)
1082        {
1083          if(degOfSubs[j][k] + (degVec[j] - 1) * wt[j] + minDeg[j]  < ub)
1084          {
1085            subsPoly = subsPoly + substitution[j][k];
1086          }
1087        }
1088      }
1089      newSubs[j] = subsPoly;        // set substitution
1090      if(substitution[j] - subsPoly != 0) { truncatedQ[j] = 1;}  // mark that substitution[j] is truncated
1091    }
1092    h = Expand(newSubs, degVec, reduceIdeal, w1, ub, truncatedQ) * coeffList[i];  // already reduced
1093    g = reduce(g + h, reduceIdeal);
1094  }
1095  kill computedPowers;
1096  setring RASB;
1097  poly fnew = imap(RASR, g);
1098  kill RASR;
1099  return(fnew);
1100}
1101
1102///////////////////////////////////////////////////////////////////////////////
1103
1104static proc StabVar(intvec wt)
1105"USAGE:   StabVar(w); intvec w
1106PURPOSE: compute the indicies for quasihomogeneous substitutions of each
1107         variable.
1108ASSUME:  f semiquasihomogeneous polynomial with an isolated singularity at 0
1109RETURN:  list
1110         _[i]  list of combinations for var(i) (i must be appended
1111         to each comb)
1112GLOBAL:  'varSubsList', contains the index j s.t. x(i) -> x(i)t(j) ...
1113"
1114{
1115  int i, j, k, uw, ic;
1116  list varList, Variables, subs;
1117  string str, varString;
1118
1119  varList = StabVarComb(wt);
1120  for(i = 1; i <= size(wt); i = i + 1)
1121  {
1122    subs = 0;
1123    // built linear substituitons
1124    for(j = 1; j <= size(varList[1][i]); j++)
1125    {
1126      subs[j] = list(i) + list(varList[1][i][j]);
1127    }
1128    Variables[i] = subs;
1129    if(size(varList[2][i]) > 0)
1130    {
1131      // built nonlinear substituitons
1132      subs = 0;
1133      for(j = 1; j <= size(varList[2][i]); j++)
1134      {
1135        subs[j] = list(i) + varList[2][i][j];
1136      }
1137      Variables[i] = Variables[i] + subs;
1138    }
1139  }
1140  return(Variables);
1141}
1142
1143///////////////////////////////////////////////////////////////////////////////
1144
1145static proc StabVarComb(intvec wt)
1146"USAGE:   StabVarComb(w); intvec w
1147PURPOSE: list all possible indices of indeterminates for a quasihom. subs.
1148RETURN:  list
1149         _[1] linear substitutions
1150         _[2] nonlinear substiutions
1151GLOBAL: 'varSubsList', contains the index j s.t. x(i) -> x(i)t(j) ...
1152"
1153{
1154  int mmi, mma, ii, j, k, uw, ic;
1155  list index, indices, usedWeights, combList, combinations;
1156  list linearSubs, nonlinearSubs;
1157  list partitions, subs, temp;        // subs[i] = substitution for var(i)
1158
1159  linearSubs = Table("0", "i", 1, size(wt));
1160  nonlinearSubs = Table("0", "i", 1, size(wt));
1161
1162  uw = 0;
1163  ic = 0;
1164  mmi = Min(wt);
1165  mma = Max(wt);
1166
1167  for(ii = mmi; ii <= mma; ii++)
1168  {
1169    if(containedQ(wt, ii))
1170    {    // find variables of weight ii
1171      k = 0;
1172      index = 0;
1173      // collect the indices of all variables of weight i
1174      for(j = 1; j <= size(wt); j++)
1175      {
1176        if(wt[j] == ii)
1177        {
1178          k++;
1179          index[k] = j;
1180        }
1181      }
1182      uw++;
1183      usedWeights[uw] = ii;
1184      ic++;
1185      indices[ii] = index;
1186
1187      // linear part of the substitution
1188
1189      for(j = 1; j <= size(index); j++)
1190      {
1191        linearSubs[index[j]] = index;
1192      }
1193
1194      // nonlinear part of the substitution
1195
1196      if(uw > 1)
1197      {    // variables of least weight do not allow nonlinear subs.
1198
1199        partitions = Partitions(ii, delete(usedWeights, uw));
1200        for(j = 1; j <= size(partitions); j++)
1201        {
1202          combinations[j] = AllCombinations(partitions[j], indices);
1203        }
1204        for(j = 1; j <= size(index); j++)
1205        {
1206          nonlinearSubs[index[j]] = FlattenQHM(combinations);   // flatten one level !
1207        }
1208      }
1209    }
1210  }
1211  "type of i:", typeof(i);
1212  combList[1] = linearSubs;
1213  combList[2] = nonlinearSubs;
1214  return(combList);
1215}
1216
1217///////////////////////////////////////////////////////////////////////////////
1218
1219static proc AllCombinations(list partition, list indices)
1220"USAGE:   AllCombinations(partition,indices); list partition, indices)
1221PURPOSE: all combinations for a given partititon
1222RETURN:  list
1223GLOBAL: varSubsList, contains the index j s.t. x(i) -> x(i)t(j) ...
1224"
1225{
1226  int i, k, m, ok, p, offset;
1227  list nrList, indexList;
1228
1229  k = 0;
1230  offset = 0;
1231  i = 1;
1232  ok = 1;
1233  m = partition[1];
1234  while(ok)
1235  {
1236    if(i > size(partition))
1237    {
1238      ok = 0;
1239      p = 0;
1240    }
1241    else { p = partition[i];}
1242    if(p == m) { i = i + 1;}
1243    else
1244    {
1245      k = k + 1;
1246      nrList[k] = i - 1 - offset;
1247      offset = offset + i - 1;
1248      indexList[k] = indices[m];
1249      if(ok) { m = partition[i];}
1250    }
1251  }
1252  return(AllCombinationsAux(nrList, indexList));
1253}
1254
1255///////////////////////////////////////////////////////////////////////////////
1256
1257static proc AllSingleCombinations(int n, list index)
1258"USAGE:   AllSingleCombinations(n index); int n, list index
1259PURPOSE: all combinations for var(n)
1260RETURN:  list
1261"
1262{
1263  int i, j, k;
1264  list comb, newC, temp, newIndex;
1265
1266  if(n == 1)
1267  {
1268    for(i = 1; i <= size(index); i++)
1269    {
1270      temp = index[i];
1271      comb[i] = temp;
1272    }
1273    return(comb);
1274  }
1275  if(size(index) == 1)
1276  {
1277    temp = Table(string(index[1]), "i", 1, n);
1278    comb[1] = temp;
1279    return(comb);
1280  }
1281  newIndex = index;
1282  for(i = 1; i <= size(index); i = i + 1)
1283  {
1284    if(i > 1) { newIndex = delete(newIndex, 1); }
1285    newC = AllSingleCombinations(n - 1, newIndex);
1286    k = size(comb);
1287    temp = 0;
1288    for(j = 1; j <= size(newC); j++)
1289    {
1290      temp[1] = index[i];
1291      temp = temp + newC[j];
1292      comb[k + j] = temp;
1293      temp = 0;
1294    }
1295  }
1296  return(comb);
1297}
1298
1299///////////////////////////////////////////////////////////////////////////////
1300
1301static proc AllCombinationsAux(list parts, list index)
1302"USAGE:  AllCombinationsAux(parts ,index); list parts, index
1303PURPOSE: all compbinations for nonlinear substituiton
1304RETURN:  list
1305"
1306{
1307  int i, j, k;
1308  list comb, firstC, restC;
1309
1310  if(size(parts) == 0 || size(index) == 0) { return(comb);}
1311
1312  firstC = AllSingleCombinations(parts[1], index[1]);
1313  restC = AllCombinationsAux(delete(parts, 1), delete(index, 1));
1314
1315  if(size(restC) == 0) { comb = firstC;}
1316  else
1317  {
1318    for(i = 1; i <= size(firstC); i++)
1319    {
1320      k = size(comb);
1321      for(j = 1; j <= size(restC); j++)
1322      {
1323        //elem = firstC[i] + restC[j];
1324        // comb[k + j] = elem;
1325        comb[k + j] = firstC[i] + restC[j];
1326      }
1327    }
1328  }
1329  return(comb);
1330}
1331
1332///////////////////////////////////////////////////////////////////////////////
1333
1334static proc Partitions(int n, list nr)
1335"USAGE:   Partitions(n, nr); int n, list nr
1336PURPOSE: partitions of n consisting of elements from nr
1337RETURN:  list
1338"
1339{
1340  int i, j, k;
1341  list parts, temp, restP, newP, decP;
1342
1343  if(size(nr) == 0) { return(list());}
1344  if(size(nr) == 1)
1345  {
1346    if(NumFactor(nr[1], n) > 0)
1347    {
1348      parts[1] = Table(string(nr[1]), "i", 1, NumFactor(nr[1], n));
1349    }
1350    return(parts);
1351  }
1352  else
1353  {
1354    parts =  Partitions(n, nr[1]);
1355    restP = Partitions(n, delete(nr, 1));
1356
1357    parts = parts + restP;
1358    for(i = 1; i <= n / nr[1]; i = i + 1)
1359    {
1360      temp = Table(string(nr[1]), "i", 1, i);
1361      decP = Partitions(n - i*nr[1], delete(nr, 1));
1362      k = size(parts);
1363      for(j = 1; j <= size(decP); j++)
1364      {
1365        newP = temp + decP[j];        // new partition
1366        if(!containedQ(parts, newP, 1))
1367        {
1368          k = k + 1;
1369          parts[k] = newP;
1370        }
1371      }
1372    }
1373  }
1374  return(parts);
1375}
1376
1377///////////////////////////////////////////////////////////////////////////////
1378
1379static proc NumFactor(int a, int b)
1380" USAGE: NumFactor(a, b); int a, b
1381PURPOSE: if b divides a then return b/a, else return 0
1382RETURN:  int
1383"
1384{
1385  int c = int(b/a);
1386  if(c*a == b) { return(c); }
1387  else {return(0)}
1388}
1389
1390///////////////////////////////////////////////////////////////////////////////
1391
1392static proc Table(string cmd, string iterator, int lb, int ub)
1393" USAGE: Table(cmd,i, lb, ub); string cmd, i; int lb, ub
1394PURPOSE: generate a list of size ub - lb + 1 s.t. _[i] = cmd(i)
1395RETURN:  list
1396"
1397{
1398  list data;
1399  execute("int " + iterator + ";");
1400
1401  for(int @i = lb; @i <= ub; @i++)
1402  {
1403    execute(iterator + " = " + string(@i));
1404    execute("data[" + string(@i) + "] = " + cmd + ";");
1405  }
1406  return(data);
1407}
1408
1409///////////////////////////////////////////////////////////////////////////////
1410
1411static proc FlattenQHM(list data)
1412" USAGE: FlattenQHM(n, nr); list data
1413PURPOSE: flatten the list (one level) 'data', which is a list of lists
1414RETURN:  list
1415"
1416{
1417  int i, j, c;
1418  list fList, temp;
1419
1420  c = 1;
1421
1422  for(i = 1; i <= size(data); i++)
1423  {
1424    for(j = 1; j <= size(data[i]); j++)
1425    {
1426      fList[c] = data[i][j];
1427      c = c + 1;
1428    }
1429  }
1430  return(fList);
1431}
1432
1433///////////////////////////////////////////////////////////////////////////////
1434
1435static proc IntersectionQHM(list l1, list l2)
1436// Type : list
1437// Purpose : Intersection of l1 and l2
1438{
1439  list l;
1440  int b, c;
1441
1442  c = 1;
1443
1444  for(int i = 1; i <= size(l1); i++)
1445  {
1446    b = containedQ(l2, l1[i]);
1447    if(b == 1)
1448    {
1449      l[c] = l1[i];
1450      c++;
1451    }
1452  }
1453  return(l);
1454}
1455
1456///////////////////////////////////////////////////////////////////////////////
1457
1458static proc FirstEntryQHM(data, elem)
1459// Type : int
1460// Purpose : position of first entry equal to elem in data (from left to right)
1461{
1462  int i, pos;
1463
1464  i = 0;
1465  pos = 0;
1466  while(i < size(data))
1467  {
1468    i++;
1469    if(data[i] == elem) { pos = i; break;}
1470  }
1471  return(pos);
1472}
1473
1474///////////////////////////////////////////////////////////////////////////////
1475
1476static proc PSum(e)
1477{
1478  poly f;
1479  for(int i = size(e);i>=1;i--)
1480  {
1481    f = f + e[i];
1482  }
1483  return(f);
1484}
1485
1486///////////////////////////////////////////////////////////////////////////////
1487
1488proc Max(data)
1489"USAGE:   Max(data); intvec/list of integers
1490PURPOSE: find the maximal integer contained in 'data'
1491RETURN:  list
1492ASSUME:  'data' contians only integers and is not empty
1493"
1494{
1495  int i;
1496  int max = data[1];
1497
1498  for(i = size(data); i>1;i--)
1499  {
1500    if(data[i] > max) { max = data[i]; }
1501  }
1502  return(max);
1503}
1504example
1505{"EXAMPLE:";  echo = 2;
1506  Max(list(1,2,3));
1507}
1508
1509///////////////////////////////////////////////////////////////////////////////
1510
1511proc Min(data)
1512"USAGE:   Min(data); intvec/list of integers
1513PURPOSE: find the minimal integer contained in 'data'
1514RETURN:  list
1515ASSUME:  'data' contians only integers and is not empty
1516"
1517{
1518  int i;
1519  int min = data[1];
1520
1521  for(i = size(data);i>1; i--)
1522  {
1523    if(data[i] < min) { min = data[i]; }
1524  }
1525  return(min);
1526}
1527example
1528{"EXAMPLE:";  echo = 2;
1529  Min(intvec(1,2,3));
1530}
1531
1532///////////////////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.