source: git/Singular/LIB/qhmoduli.lib @ 9ea76a

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