source: git/Singular/LIB/qhmoduli.lib @ 7de8e4

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