source: git/Singular/LIB/qhmoduli.lib

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