source: git/Singular/LIB/arnoldclassify.lib @ ab758e

spielwiese
Last change on this file since ab758e was ab758e, checked in by Hans Schoenemann <hannes@…>, 5 years ago
format (arnoldclassify.lib,SingularityDBM.lib)
  • Property mode set to 100644
File size: 58.1 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2version="version arnoldclassify.lib 4.1.1.4 Sep_2017 "; // $Id$
3category="Singularities";
4info="
5LIBRARY:  arnoldClassify.lib     Arnol'd Classifier of Singularities
6AUTHOR:   Eva Maria Hemmerling,  ehemmerl@rhrk.uni-kl.de
7
8OVERVIEW:
9   A library for classifying isolated hypersurface singularities
10   from the list of V.I. Arnol'd w.r.t. right equivalence up to corank 2.
11   The method relies on Baciu's list of Milnor codes and Newton's rotating
12   ruler method to distinguish the Y- and Z- singularities.
13
14REFERENCES:
15[AVG85] Arnold, Varchenko, Gusein-Zade: Singularities of Differentiable Maps.
16Vol. 1: The classification of critical points caustics and wave fronts.
17Birkh\"auser, Boston 1985
18
19[Bac01] Corina Baciu: The classification of Hypersurface Singularities
20using the Milnor Code, Diplomarbeit, Universit\"at Kaiserslautern, 2001.
21
22[GP12] Greuel, Pfister: A SINGULAR Introduction to Commutative Algebra,
23Springer Science and Business Media, 2012
24
25[Hem17] Eva Maria Hemmerling: Algorithmic Arnol'd Classification in SINGULAR,
26Master Thesis, TU Kaiserslautern, 2017.
27
28SEE ALSO:  classify_lib, realclassify_lib
29
30KEYWORDS: singularities; Arnol'd; classification; Milnor code
31
32PROCEDURES:
33arnoldListAllSeries();   list of all singularity series up to corank 2
34arnoldShowSeries(S);     data defining a singularity series S
35arnoldNormalForm(S,#);   normalform for a singularity series S
36arnoldClassify(f);       singularity class of a power series f
37arnoldCorank(f);         corank of singularity defined by f
38arnoldDeterminacy(f,#);  upper bound for the determinacy of f
39arnoldMilnorCode(f,#);   Milnor Code of a singularity f
40arnoldMorseSplit(f,#);   result of Splitting Lemma applied to f
41";
42
43LIB "inout.lib";
44LIB "elim.lib";
45LIB "sing.lib";
46LIB "findifs.lib";
47
48///////////////////////////////////////////////////////////////////////////////
49static proc mod_init()
50{
51//* define new datastruct singclass
52newstruct("singclass", "string Restrictions, string NormalForm,
53intvec MilnorCode, int Tjurina, int Determinacy, int Milnor, int Corank,
54int Modality, int s, int r, int k, string Class, string Series ");
55
56//* define new datastruct singclass
57newstruct("singseries", " string Restrictions, string MilnorCode,
58 string MilnorNumber, string Corank, string Modality, string SpecialForm,
59 string NormalForm, string Series ");
60
61LIB "SingularityDBM.lib";
62arnold_classify_init();
63}
64
65///////////////////////////////////////////////////////////////////////////////
66proc arnoldClassify( poly fPoly )
67"USAGE:   arnoldClassify (f); f poly
68ASSUME:  The basering is local of characteristic at most 13 and f defines an
69         isolated singularity from Arnol'd's list of corank at most 2.
70COMPUTE: singularity class respect to right equivalence and
71         invariants used in the process of classification
72RETURN:  Singularity class of f of type singclass containing
73         @* - name of singularity series as listed by arnoldListAllSeries(),
74         @* - name of singularity class,
75         @* - parameters k,r,s defining the singularity class, -1 if not used,
76         @* - modality, corank, Milnor number, determinacy,
77         @* - Tjurina number, -2 if not computed, -1 if infinite,
78         @* - Milnor code, -1 if not computed,
79         @* - normal form of the singularity series from Arnol'd's list,
80         @* - restrictions on parameters as string in SINGULAR syntax.
81EXAMPLE: example arnoldClassify; shows an example
82"
83{
84
85//* initialisation
86//* new datastructure singclass to save intrinsic information
87 singclass f;
88 f = init_newsingclass( f );
89
90//* Check the basering
91 if( check_basering() )
92 {
93  f.Class = "NoClass";
94 }
95
96//* Detect units
97 if(jet(fPoly,0) != 0 )
98   {
99   return( ERROR("The polynomial is a unit." ));
100 }
101
102//* Compute Basic Invariants: Corank, Determinacy and Milnornumber
103 ideal Jf = std(jacob( fPoly ));
104 f.Milnor = vdim( Jf );
105 if( f.Milnor < 0 )
106 { ERROR("Milnornumber of the singularity must be finite.")}
107 f.Determinacy = arnoldDeterminacy( Jf , f.Milnor);
108 f.Corank = arnoldCorank( fPoly );
109
110//* Check if Milnornumber is finite
111 if( f.Milnor < 0 ){
112  f.Class = "NoClass";
113  ERROR("Milnornumber of the singularity must be finite.")
114  return( f );
115 }
116
117//* Singularities with Milnornumber = 0 belong to A[0];
118 if( f.Milnor == 0 ){
119  f.Class = "A[0]";
120  f.Series = "A[k]";
121  f.k = 0;
122  f.r = -1;
123  f.s = -1;
124  f.Modality = 0;
125  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
126  return( f );
127 }
128
129//* Singularities with Corank <=1 belong to A[k];
130 if( f.Corank <= 1){
131  f.Class = "A["+string(f.Milnor)+"]";
132  f.Series = "A[k]";
133  f.k = f.Milnor;
134  f.r = -1;
135  f.s = -1;
136  f.Modality = 0;
137  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
138  return( f );
139 }
140
141//* Reduce f to f.Determinacy-jet
142  if(f.Determinacy >0 ){
143   fPoly = jet(fPoly, f.Determinacy);
144  }
145
146//* Classification of singularities of Corank 2
147 if( f.Corank == 2 ){
148   return( Classify_Corank2(f, fPoly));
149 }
150
151//* Classification of singularities of Corank 3
152 if( f.Corank == 3 ){
153  return( Classify_Corank3(f, fPoly));
154 }
155
156//* No classification for singularities of corank > 3
157 f.Class = "NoClass";
158 return( f );
159
160}
161example
162{ "EXAMPLE:"; echo=2;
163  ring r = 0,(x,y),ds;
164  int k = random(3,10);
165  poly g = x4 + x2*y^(2*k+1)+x*y^(3*k+1)+ y^(4*k +1);
166  arnoldClassify(g);
167  map phi=r,y-x^2,x+y;
168  phi(g);
169  arnoldClassify(phi(g));
170  ring C = (0,i), (x,y), ds;
171  minpoly = i2 + 1;
172  poly f =(x2+y2)^2+x5;
173  arnoldClassify(f);
174}
175
176///////////////////////////////////////////////////////////////////////////////
177static proc Classify_Corank2( singclass f, poly fPoly)
178{
179//* Classifies Singularities of Corank 2; Series D,J,E,W,X,Y,Z
180 def br = basering;
181
182//* Zero 4-jet is no listed singularity
183 if( jet( fPoly, 4) == 0 ){
184  f.Class = "NoClass";
185  return(f);
186 }
187
188//* Compute MilnorCode
189 f.MilnorCode = arnoldMilnorCode( fPoly );
190
191//* Classification of the series D,J and E using MilnorCode
192//* (have Nonzero 3-jet and milnorcode of length 3)
193 if (size( f.MilnorCode ) == 3 ){
194  def g = Classify_Corank2_MC_3( f );
195  return( g );
196 }
197
198//* Classification of series W, X and class Z[k,r,s] using MilnorCode
199//* (have zero 3-jet and milnorcode of length 5)
200 if ( size( f.MilnorCode ) == 5 ){
201  def g = Classify_Corank2_MC_5( f, fPoly );
202  if( g.Class != ""){
203   return( g );
204  }
205
206//* Classification of series Y and Z except Z[k,r,s]
207//* Splitting Lemma needed
208  f.k = (f.MilnorCode[3]+1) div 2;
209   return( Classify_Z_Y( f, fPoly ));
210 }
211 ERROR("MilnorCode must have length 3 or 5.");
212}
213
214///////////////////////////////////////////////////////////////////////////////
215static proc Classify_Z_Y( singclass f, poly fPoly )
216{
217
218//* classifies singularity f defined by polynomial fPoly which is of type
219//* Z or Y with zero 3-jet and non-zero 4-jet.
220//* The idea is to transform the Newton Polygon of fPoly until we can decide
221//* wether f is of type Z or Y. For further information abouth the algorithm
222//* refer to [Hem17]
223
224//* Apply Splitting lemma if needed such that fPoly is given in two variables
225 if( nvars(basering) > f.Corank ){
226  fPoly = Morse_arnold( fPoly, f.Determinacy );
227
228  //* Reduce number of variables
229  def br = basering;
230  list L = ringlist(br);
231  if( size(L[1]) == 0 )
232  { ring redbr = char(basering), (x(1..f.Corank)), (c,ds); }
233  else{
234    number m = leadcoef(L[1][4][1]);
235    ring redbr = (char(basering),t), (x(1..f.Corank)), (c,ds);
236    number m = imap(br, m);
237    minpoly = m;
238  }
239   map MapReduce = br, maxideal(1);
240  poly fPoly = MapReduce( fPoly );
241 }
242
243//* Newton Polygon transformation, not needed if f.k = 1
244if( f.k > 1 ){
245 fPoly = Transform_Newton_Polygon( f, fPoly );
246}
247
248//* Check if quasihomogeneous part of fPoly ( w.r.t. to (k,1)) has
249//* linear factor of multiplicity 3
250 def b = Check_linear_factor_mult_3( f, fPoly );
251
252if( b==1){return ( Classify_Y( f, fPoly ));}
253else{ return ( Classify_Z( f ) );}
254}
255
256///////////////////////////////////////////////////////////////////////////////
257static proc Check_linear_factor_mult_3( singclass f, poly fPoly)
258{
259 //* set weights;
260 intvec weights = f.k,1;
261
262 //* Compute quasihomogeneous part of fPoly and set y=1
263 poly h1 = jet( fPoly, 4*weights[1], weights);
264 poly h2 = subst(h1, var(2), 1);
265 //* Compute gcd of h and derivative twice
266 h2 = gcd( h2, diff(h2,var(1)));
267 h2 = gcd( h2, diff(h2, var(1)));
268
269 //* Switch coordinates and repeat the last step
270 if( deg(h2) == 0 ){
271  h2 = subst(h1, var(1), 1);
272  //* Compute gcd of h and derivative
273  h2 = gcd( h2, diff(h2,var(2)));
274  h2 = gcd( h2, diff(h2, var(2)));
275 }
276
277 if (deg(h2) > 0){ return( 0 );}
278 else{ return( 1 ); }
279}
280
281///////////////////////////////////////////////////////////////////////////////
282static proc Transform_Newton_Polygon( singclass f, poly fPoly)
283{
284//* Check that 3-jet is zero and 4-jet is not zero
285 if( jet( fPoly, 3 ) != 0 ){ERROR( "Three-jet must be zero.");}
286 if( jet( fPoly, 4 ) == 0 ){ERROR("Four-jet must not be zero.");}
287
288 //* Make sure var(1) is contained in the 4-jet
289 if( diff( jet(fPoly,4) , var(1)) == 0 ){
290  map CoordSwitch = basering, var(2), var(1);
291  fPoly = CoordSwitch(fPoly);
292 }
293
294 //* Eliminate all monomials with weighted degree smaller than 4k (= 4*f.k)
295 return( Classify_Z_Y_EliminateMonomials( f, fPoly ));
296}
297
298///////////////////////////////////////////////////////////////////////////////
299static proc Classify_Z_Y_EliminateMonomials( singclass f, poly fPoly)
300{
301//* Eliminates all monomials with weighted degree smaller than 4k (= 4*f.k)
302
303//* Computes the weights for the first monomial to eliminate
304//* Use Newtons Rulers Method
305intvec weights = Classify_Z_Y_FindWeights( fPoly, f.k);
306
307//* if the weights are (k,1), no monomials to eliminate, return fPoly
308if (weights[1] == f.k && weights[2] ==1 ){ return (fPoly);}
309
310//* Compute quasihomogeneous part w.r.t to weights
311poly fquasi = jet( fPoly, 4*weights[1], weights);
312
313//* Check if fquasi contains monomial of the form y^l
314if ( Coeff (fquasi, var(2), var(2)^(4*weights[1] div weights[2])) == 0 )
315{
316 int counter = 1;
317
318 while ( counter < 10){
319  //* Find genereous transformation
320  int ran = random(-50,50);
321  map Phi = basering, x + ran*t*var(2)^( (d div weights[2] - 2) div 2 ),y;
322  if (Coeff (Phi(fquasi), var(2), var(2)^(d div weights[2])) != 0 )
323  { counter = 11;}
324  counter = counter+1;
325 }
326 fPoly = Phi(fPoly);
327}
328
329//* Compute the fourthzero if fquasi has one
330poly factor = Classify_Z_Y_FourthZero( fquasi );
331
332//* If fquasi has a fourth zero
333if( factor == 0 ){ ERROR("Field extension needed.")}
334
335poly inversefactor =
336number ( 1 /leadcoef(factor)) * (2*lead(factor) - factor);
337map CoordChange = basering, inversefactor, var(2);
338fPoly = CoordChange( fPoly );
339fPoly = jet( fPoly, f.Determinacy);
340
341return (Classify_Z_Y_EliminateMonomials( f, fPoly ) );
342}
343
344/////////////////////////////////////////////////////////////////////////////
345static proc Classify_Z_Y_FindWeights( poly fPoly, int k )
346{
347//* Input poly f with zero 3-jet and non-zero 4-jet with var(1) contained
348//* in 4-jet. Computes the weights for all monomials lying in the Newton
349//* Diagramm under the line defined by x^4 and x^3y^k and returns the
350//* smallest one. In case there is no other monomial than x^4, return
351//* weights (k,1)
352
353//* Cut off monomials above the line x^4 and x^3y^k
354 intvec weights = k, 1;
355 fPoly = jet( fPoly, 4*k, weights );
356
357//* Check if leading term of f is x^4;
358 poly firstlead = lead(fPoly);
359 if( leadmonom(firstlead) != var(1)^4 ){ ERROR("Something went wrong");}
360
361//* Compute the the minimal weights
362 fPoly = fPoly - firstlead;
363 intvec weights2;
364 while( fPoly != 0 ){
365  weights2 = qhweight( firstlead + lead( fPoly ));
366  if (weights2[1] * weights[2] < weights2[2] * weights[1]){ weights = weights2;}
367  fPoly = fPoly - lead(fPoly);
368 }
369 return(weights);
370}
371
372///////////////////////////////////////////////////////////////////////////////
373static proc Classify_Z_Y_FourthZero( poly fPoly )
374{
375//* Assume f = (ax + by^l)^4
376//* Differentiate three times w.r.t x ( f''' = 24a^3(ax +by^l) )
377//* and take gcd of f and f'''
378
379poly f3 = diff(diff(diff( fPoly, var(1)), var(1)), var(1));
380poly factor = gcd( f3, fPoly);
381
382//* Check if the factor^4 is equal input f
383if( factor^4 == fPoly){ return(factor); }
384else{ return(0);}
385}
386
387///////////////////////////////////////////////////////////////////////////////
388static proc Classify_Y( singclass f, poly fPoly)
389{
390//* Determines the parameters r and s of the singularity f of type Y[k,r,s]
391//* Case k = 1
392intvec weights;
393  if ( f.k ==1 ){
394   //* Set an upper bound
395   int bound = f.Milnor + 1;
396
397   //* Transform Newton Polygon and compute intersection point of y axis
398   weights, fPoly = Transform_Newton_Polygon_Y( f, fPoly, bound );
399    int b1 = int(( 2*weights[1]+ 2*f.k*weights[2] )div weights[2] - 4) ;
400
401   //* Switch variables and repeat the last step
402   map CoordChange = basering, var(2), var(1);
403   weights, fPoly =
404   Transform_Newton_Polygon_Y( f, CoordChange(fPoly), bound );
405   int b2 = int(( 2*weights[1]+ 2*f.k*weights[2] )div weights[2] - 4) ;
406
407   //* Y-class
408   f.Series = "Y[1,r,s]";
409   f.s = min(b1,b2);
410   f.r =  int(f.Milnor - 9 - f.s);
411   f.Class = "Y["+string(f.k)+","+string(f.r)+","+string(f.s)+"]";
412   f.Modality = 3*f.k - 2;
413   return( f );
414  }
415  else{
416  //* Set an upper bound = r+s;
417   int bound = 4*f.k + (f.Milnor - 12*f.k +3);
418   weights, fPoly = Transform_Newton_Polygon_Y( f, fPoly, bound);
419   int b1 =
420   int((2*weights[1] + 2* f.k*weights[2]) div weights[2]  - 4*f.k);
421   int b2 = f.Milnor - 12*f.k +3 - b1;
422
423   //* Y-class
424   f.Series = "Y[k,r,s]";
425   f.r = max(b1,b2);
426   f.s =  min(b1,b2);
427   f.Class = "Y["+string(f.k)+","+string(f.r)+","+string(f.s)+"]";
428   f.Modality = 3*f.k - 2;
429   return( f );
430  }
431}
432
433///////////////////////////////////////////////////////////////////////////////
434static proc Transform_Newton_Polygon_Y( singclass f, poly fPoly, int bound )
435{
436//* Eliminates Monomials until the Newton Polygon of fPoly coincides
437//* with the Newton Polygon of the normalform
438
439//* Reduce fPoly to monomials which might get eliminated
440  def weights1 = qhweight(var(1)^2*var(2)^(2*f.k) + var(2)^bound);
441  intvec weights2 = 1,0;
442  poly fquasi = jet( jet(fPoly, 2*weights1[1]+2*f.k*weights1[2], weights1),2, weights2) ;
443
444//* Find minimal ("steepest") weights
445  def weights3 = Classify_Y_FindWeights( fquasi, f.k, weights1);
446
447//* if the weights are (k,1), no monomials to eliminate, return fPoly
448  if (weights3 == weights1 )
449  { return (ERROR("Parameters r and s must be greater 0."));}
450
451//* Compute quasihomogeneous jet w.r.t to weight
452  def d =  2*weights3[1]+2*f.k*weights3[2];
453  fquasi = jet(fPoly, d, weights3);
454
455//* Check if monomial of the form y^l is contained in fquasi
456  if ( Coeff (fquasi, var(2), var(2)^(d div weights3[2])) == 0 )
457  {
458   int counter = 1;
459
460   while ( counter < 10){
461    //* Find genereous transformation
462    int ran = random(-50,50);
463    map Phi = basering,x+ran*t*var(2)^((d div weights3[2] - 2)div 2 ),y;
464    if (Coeff (Phi(fquasi), var(2), var(2)^(d div weights3[2])) != 0 )
465    { counter = 11;}
466    counter = counter+1;
467   }
468  fPoly = Phi(fPoly);
469  }
470
471//* Compute the zero of multiplicity 2 if fquasi has one
472
473 poly factor = jet(fPoly,2*weights3[1]+2*f.k*weights3[2],weights3);
474 factor =
475 Classify_Y_TwoZero(factor);
476
477//* If fquasi has a zero with mult 2
478 if( factor == 0 ){ return( weights3, fPoly );}
479
480 poly inversefactor =number(1/leadcoef(factor))*(2*lead(factor)-factor);
481 map CoordChange = basering, inversefactor, var(2);
482 fPoly = CoordChange( fPoly );
483 fPoly = jet( fPoly, f.Determinacy);
484
485 fquasi =
486 jet( jet(fPoly, 2*weights3[1]+2*f.k*weights3[2], weights3), 2, weights2);
487 if( leadmonom(fquasi) != var(1)^2*var(2)^(2*f.k))
488 { return( weights3, fPoly ); }
489
490return (Transform_Newton_Polygon_Y( f, fPoly, bound ) );
491}
492
493/////////////////////////////////////////////////////////////////////////////
494static proc Classify_Y_FindWeights( poly f, int k, intvec weights1 )
495{
496//* Assume f is a polynomial with no polynomials lying in the Newton
497//* Diagramm above the line defined by x^2y^2 and x^2y^(bound)
498//* Computes the weight of all monomials lying under the line and
499//* returns the smallest one
500
501//* Check if leading term of f is x^2y^2k;
502 poly firstlead = lead(f);
503
504 if( leadmonom(firstlead) != var(1)^2*var(2)^(2*k) )
505 { ERROR("Something went wrong");}
506
507//* Compute the the minimal weights
508 f = f - firstlead;
509 intvec weights2;
510 while( f != 0 ){
511  weights2 = qhweight( firstlead + lead( f ));
512  if (weights2[1] * weights1[2] < weights2[2] * weights1[1])
513  { weights1 = weights2;}
514  f = f - lead(f);
515 }
516 return( weights1 );
517}
518
519///////////////////////////////////////////////////////////////////////////////
520static proc Classify_Y_TwoZero( poly f )
521{
522//* Assume f = (ax + by^l)^2* x^2
523
524def factors = factorize ( f );
525
526for( int i = 1; i<= size(factors[2]); i++)
527{
528 if( factors[2][i] == 2 )
529 {
530   if ( factors[1][i] != 1 && factors[1][i] - lead(factors[1][i]) != 0)
531  { return( factors[1][i]);}
532 }
533}
534return( 0 );
535}
536
537///////////////////////////////////////////////////////////////////////////////
538static proc Classify_Corank3( singclass f, poly fPoly)
539{
540return( "Not implemented yet.")
541//* todo
542
543}
544
545
546
547///////////////////////////////////////////////////////////////////////////////
548static proc Classify_Corank2_MC_3 ( singclass f )
549{
550//* Classifies the singularities of corank 2 with non-zero 3-jet using
551//* the Milnor code.
552
553 intvec mc = f.MilnorCode;
554
555 if( mc[1] != 1 ){
556  f.Class = "NoClass";
557   return( f ); }
558
559//* Check type "D[k]"
560 if( mc[2] == 1 ){
561    f.Class = "D["+string(mc[3]+3)+"]";
562  f.Series = "D[k]";
563  f.k = mc[3]+3;
564  f.r = -1;
565  f.s = -1;
566  f.Modality = 0;
567  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
568  return( f );
569 }
570
571//* Check type "J[k,r]"
572 if(mc[3] > mc[2]&& mc[2]>1){
573  f.k = (mc[2]+1) div 2;
574  f.r = f.Milnor - 3*mc[2]-1;
575  f.s = -1;
576  f.Class = "J["+string(f.k)+","+string(f.r)+"]";
577  f.Series = "J[k,r]";
578  f.Modality = f.k-1;
579  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
580  return( f );
581 }
582
583 else{
584
585//* Check type "J[k,0]"
586  if( f.Milnor mod 6 == 4 ){
587           f.k = (f.Milnor + 2 ) div 6;
588   f.Class ="J[" + string(f.k) + "," + string(0) +"]";
589   f.Series = "J[k,0]";
590   f.r = -1;
591   f.s = -1;
592   f.Modality = f.k-1;
593   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
594   return( f );
595        }
596
597//* Check type "E[6k]"
598  if(f.Milnor mod 6 == 0 ){
599   f.k = f.Milnor div 6;
600   f.r = -1;
601   f.s = -1;
602   f.Class = "E[" + string(6*f.k)+ "]";
603   f.Series = "E[6k]";
604   f.Modality = f.k - 1;
605   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
606   return( f );
607  }
608
609//* Check type "E[6k+1]"
610  if( f.Milnor mod 6 == 1 ){
611   f.k = (f.Milnor - 1) div 6;
612   f.r = -1;
613   f.s = -1;
614   f.Class = "E[" + string(6*f.k+1) + "]";
615   f.Series = "E[6k+1]";
616   f.Modality = f.k -1;
617   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
618   return( f );
619  }
620
621//* Check type "E[6k+2]"
622  if( f.Milnor mod 6 == 2 ){
623   f.k = (f.Milnor - 2) div 6;
624   f.r = -1;
625   f.s = -1;
626   f.Class = "E[" + string(6*f.k+2) + "]";
627   f.Series = "E[6k+2]";
628   f.Modality = f.k - 1;
629   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
630   return( f );
631  }
632
633 }
634 f.Class = "NoClass";
635 return( f );
636}
637
638///////////////////////////////////////////////////////////////////////////////
639static proc Classify_Corank2_MC_5 ( singclass f , poly fPoly)
640{
641
642//* Classifies the singularity classes of the series W, Z and the singularity
643//* class Z[k,r,s] using the Milnor code. They are of corank 2, have
644//* zero 3-jet, non-zero 4-jet and the Milnor code is of length 5.
645
646 intvec mc = f.MilnorCode;
647 if( mc[1] != 1 || mc[2]!= 1){  f.Class = "NoClass"; return(f);}
648 if( mc[3] mod 2 == 0 )
649 {
650
651//* Check type "W#[k,2r]"
652  if( mc[3] == mc[5] && mc[3] < mc[4] ){
653   f.k = mc[3] div 2;
654   f.r = mc[4]-mc[3];
655   f.s = -1;
656   f.Class = "W#[" + string(f.k) + "," + string (2*f.r) +"]";
657   f.Series = "W#[k,2r]";
658   f.Modality = 3*f.k -1;
659   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
660   return(f);
661  }
662
663//* Check type "W[k,r]"
664  if( mc[3]==mc[4] && mc[3]<mc[5] ){
665   f.k = mc[3] div 2;
666   f.r = mc[5] - mc[3];
667   f.s = -1;
668   f.Class = "W[" +string(f.k) +"," + string(f.r) + "]";
669   f.Series = "W[k,r]";
670   f.Modality = 3*f.k - 1;
671   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
672   return(f);
673  }
674
675//* Check type "W#[k,2r-1]"
676  if(mc[5] < mc[3] && mc[3] < mc[4]
677  && f.Milnor mod 2 == 0
678  && 2*mc[4]+mc[5]+2> f.Milnor div 2){
679   f.k = mc[3] div 2;
680   f.r = (f.Milnor - 12*f.k-2) div 2;
681   f.s = -1;
682   f.Class = "W#[" +string(f.k) +"," +string(2*f.r-1) +"]";
683   f.Series = "W#[k,2r-1]";
684   f.Modality = 3*f.k -1;
685   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
686   return(f);
687  }
688 }
689
690//* Check type "X[k,0]"
691 if( f.Milnor mod 12 == 9 && mc[3]>=mc[5] && mc[5]<=3*mc[3]-2*mc[4] ){
692  f.k = (f.Milnor + 3) div 12;
693  f.r = 0;
694  f.s = -1;
695  f.Class = "X[" + string(f.k) +",0]";
696  if(f.k == 1){f.Series = "X[1,0]";}
697  else{f.Series = "X[k,0]";}
698  f.Modality = 3*f.k -2;
699  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
700  return(f);
701 }
702
703//* Check type "W[12k+1]"
704 if( f.Milnor mod 12 == 1 && mc[3]==mc[5] && mc[4]<mc[3] ){
705   f.k = (f.Milnor - 1) div 12;
706  f.r = -1;
707  f.s = -1;
708   f.Class = "W[" + string(12*f.k+1) +"]";
709  f.Series = "W[12k+1]";
710  f.Modality = 3*f.k -2;
711  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
712   return(f);
713 }
714
715//* Check type "W[12k+5]"
716 if( f.Milnor mod 12 == 5 && mc[3]==mc[5] && mc[4]<mc[3]){
717   f.k = (f.Milnor - 5) div 12;
718  f.r = -1;
719  f.s = -1;
720   f.Class = "W[" + string(12*f.k+5) +"]";
721  f.Series = "W[12k+5]";
722  f.Modality = 3*f.k -1;
723  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
724   return(f);
725 }
726
727//* Check type "W[12k+6]"
728 if( mc[3] >= mc[5] && f.Milnor mod 12 == 6  &&
729  (2*mc[4]+mc[5]+2) < (f.Milnor div 2) && mc[3]> mc[5]){
730   f.k = (f.Milnor-6) div 12;
731   f.r = -1;
732   f.s = -1;
733   f.Class = "W[" +string(12*f.k+6) +"]";
734   f.Series = "W[12k+6]";
735   f.Modality = 3*f.k -1;
736   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
737   return(f);
738 }
739
740//* Check type "W[k,0]"
741 if( f.Milnor mod 12 == 3  && mc[5]<= (3*mc[3] -2*mc[4])){
742  f.k = (f.Milnor - 3) div 12;
743  f.r = -1;
744  f.s = -1;
745  f.Class = "W["+ string(f.k) +",0]";
746  f.Series = "W[k,0]";
747  f.Modality = 3*f.k -1;
748  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
749  return(f);
750 }
751
752//* Check type "W[12k]"
753 if(f.Milnor mod 12 == 0  && mc[3]> mc[5] &&
754  2*mc[4]+ mc[5]+ 2 < (f.Milnor div 2)){
755  f.k = f.Milnor div 12;
756  f.r = -1;
757  f.s = -1;
758  f.Class = "W[" + string(12*f.k) +"]";
759  f.Series = "W[12k]";
760  f.Modality = 3*f.k -2;
761  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
762  return(f);
763 }
764
765//* Check type "X[k,r]"
766 if( (mc[4] < mc[3] && mc[3] < mc[5] ) ||
767 (mc[3]==mc[4] && mc[3] < mc[5] ) ){
768  f.k = (2*mc[3] + mc[4] + 3) div 6;
769  f.r = mc[5] - mc[3];
770  f.s = -1;
771  f.Class = "X[" + string(f.k) +"," + string(f.r)+ "]";
772  if(f.k == 1){f.Series = "X[1,r]";}
773  else{f.Series = "X[k,r]";}
774  f.Modality = 3*f.k -2;
775  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
776  return(f);
777 }
778
779 //* Need Tjurina number to classify Z[k,r,s]
780 //* Check type "Z[k,r,s]"
781 f.Tjurina = tjurina(fPoly);
782 if( mc[3]<mc[4] && mc[4] < mc[5] &&
783   f.Milnor > ( 3* (mc[3] + mc[4] +1)) &&
784   mc[4] mod 2 == 1 &&
785   f.Tjurina == f.Milnor - (mc[4] + mc[3]) div 2 ){
786
787   f.k = (mc[3]+1) div 2;
788   f.r = (mc[4] - mc[3]) div 2;
789   f.s = mc[5] - mc[4];
790   f.Class = "Z[" + string(f.k) +"," + string(f.r)+ ","+string(f.s)+"]";
791   if(f.k == 1){f.Series = "Z[1,r,s]";}
792   else{f.Series = "Z[k,r,s]";}
793   f.Modality = 3*f.k +f.r -2;
794   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
795   return(f);
796 }
797
798 if( mc[3] mod 2 == 1){
799  return(f);
800 }
801 f.Class = "NoClass";
802 return(f);
803}
804
805///////////////////////////////////////////////////////////////////////////////
806static proc Classify_Z( singclass f)
807{
808//* If the input is a singularity of the series Z, this procedure determines
809//* the class and the parameters.
810
811 intvec mc = f.MilnorCode;
812 f.k = (mc[3]+1) div 2;
813
814//* Check type "Z[k,r]"
815 if (f.Milnor mod 6 == 3 && mc[5]<=mc[4]){
816  f.r = (mc[4] - mc[3]) div 2;
817  f.s = -1;
818  f.Class = "Z["+string(f.k)+","+string(f.r)+"]";
819  if(f.k == 1){ f.Series = "Z[1,r]";}
820  else {f.Series = "Z[k,r]";}
821  f.Modality = 3*f.k + f.r-2;
822  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
823  return(f);
824 }
825
826//* Check type "Z[k,12k+6r]"
827 if (f.Milnor mod 6 ==0 && mc[4]==mc[5] && mc[3]<mc[5]){
828  f.r = (f.Milnor - 12*f.k) div 6;
829  f.s = -1;
830     f.Class = "Z["+string(f.k)+","+string(12*f.k+6*f.r)+"]";
831  if(f.k == 1){ f.Series = "Z[1,6r+12]";}
832  else {f.Series = "Z[k,12k+6r]";}
833  f.Modality = 3*f.k + f.r - 2;
834  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
835  return(f);
836 }
837
838//* Check type "Z[k,12k+6r+1]"
839 if (f.Milnor mod 6 == 1 && mc[5] mod 2 ==1 ){
840  f.r = (f.Milnor - 12*f.k -1) div 6;
841  f.s = -1;
842     f.Class = "Z["+string(f.k)+","+string(12*f.k+6*f.r+1)+"]";
843  if(f.k == 1){ f.Series = "Z[1,6r+13]";}
844  else {f.Series = "Z[k,12k+6r+1]";}
845  f.Modality = 3*f.k +f.r - 2;
846  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
847  return(f);
848 }
849
850//* Check type "Z[k,12k+6r-1]"
851 if (f.Milnor mod 6 ==5 && mc[4] > mc[5]  ){
852  f.r = (f.Milnor - 12*f.k +1) div 6 ;
853  f.s = -1;
854     f.Class = "Z["+string(f.k)+","+string(12*f.k+6*f.r-1)+"]";
855  if(f.k == 1){ f.Series = "Z[1,6r+11]";}
856  else {f.Series = "Z[k,12k+6r-1]";}
857  f.Modality = 3*f.k + f.r -2;
858  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
859  return(f);
860 }
861
862 //* Check type "Z[k,r,s]"
863 if( mc[3]<mc[4] && mc[4]<mc[5] &&
864  f.Milnor>3*(mc[4]+mc[3]+1) && mc[4] mod 2 ==1){
865        f.r = (mc[4] - mc[3]) div 2;
866        f.s = mc[5] - mc[4];
867  f.Class = "Z["+string(f.k)+","+string(f.r)+","+string(f.s)+"]";
868  if(f.k == 1){ f.Series = "Z[1,r,s]";}
869  else {f.Series = "Z[k,r,s]";}
870  f.Modality = 3*f.k +f.r -2;
871  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
872  return(f);
873 }
874}
875
876///////////////////////////////////////////////////////////////////////////////
877static proc arnold_classify_init()
878{
879 // Check or create Singularity Database
880   string s;
881   link l="DBM:r Singularitylist";
882   s = read(l,"VERSION");
883   if (s == "" ) {
884     create_singularity_dbm();
885   }
886   close(l);
887   l="DBM:r Singularitylist";
888   s = read(l,"VERSION");
889}
890
891
892///////////////////////////////////////////////////////////////////////////////
893proc arnoldMorseSplit ( poly f, list # )
894"USAGE:   arnoldMorseSplit(f); f poly
895ASSUME:  base ring is local, f in maxideal(2) has isolated critical point at 0
896COMPUTE: result of Splitting Lemma applied to f
897RETURN:  poly g in maxideal(3) right equivalent to f
898EXAMPLE: example arnoldMorseSplit; shows an example
899"
900{
901//* save basering
902 def br = basering;
903 int n = nvars(basering);
904
905//* Set Determinacy (Needed for Splitting Lemma) wether given in # or compute
906 int Determinacy;
907 if (size(#) == 0 ){
908  Determinacy = arnoldDeterminacy(std(jacob(f)));
909 }
910 else{
911  Determinacy = #[1];
912 }
913//* define ring_ext to change variable names in x(1), ..., x(n)
914//* requirement for procedure morse_arnold
915 ring ring_ext = char(basering), (x(1..n)), (c, ds);
916 map Phi = br, maxideal(1);
917
918
919//* Apply Splitting Lemma
920 poly f = Morse_arnold( Phi( f ), Determinacy );
921
922//* Define inverse map to map f back into original ring
923 setring br;
924 map Phi_inverse = ring_ext, maxideal(1);
925
926 return( Phi_inverse(f) );
927
928}
929example
930{ "EXAMPLE"; echo=2;
931   ring r=0,(x,y,z),ds;
932   export r;
933   poly f=(x2+3y-2z)^2+xyz-(x-y3+x2*z3)^3;
934   poly g=arnoldMorseSplit(f);
935   g;
936}
937
938
939///////////////////////////////////////////////////////////////////////////////
940static proc Morse_arnold( poly f , int Determinacy)
941{
942//* find g(x_1, ..., x_s) such that f ~ g + x_s+1^2 + ... + x_n^2
943//* s = Corank(f);
944
945//* initialisation
946 int n, i, j, k;
947 poly f2, imagef, Q, P;
948 ideal B1, B2;
949 map Phi, Phi2;
950
951//* save basering;
952 def br = basering;
953 n = nvars(basering);
954
955//* Check if Determinacy is finite
956 if (Determinacy < 0 ){
957  ERROR("Determinacy must be finite.");
958 }
959 f = jet(f, Determinacy);
960
961//* Change order of variables sorted by frequency of appearance ->
962//* improves running time
963 f = ReorderVar(f);
964
965//* B1 defines the map which renumerates the variables such that
966//* g depends on the first s variables
967 B1 = maxideal(1);
968 i = 1;  //Variable x_i
969 j = 1;  //running index for B1, coordinate transformation x_i -> x_j
970
971//* While-loop over the variables,
972//* Write f = Q x_i^2 + P x_i + R,
973//* Either Q=P=0 and g depends on x_i or g is independent from x_i
974//*  and eliminate P
975 while( i <= n )
976 {
977  f2 = jet(f,2);
978  k = i+1; //* Variable for coordinate transformation
979
980  if((f2 - subst( f2, var(i), 0 )) == 0 ){
981   //* g depends on x_i -> send x_i via B1 to x_j
982   B1[i] = var(j);
983   j = j+1;
984  }
985  else{
986   //* Write f = Q x_i^2 + P x_i + R;
987      Q = Coeff( f2, var(i), var(i)^2);
988
989   //* Check if
990   if( Q == 0 && i == n ){
991    ERROR("Someting went wrong");
992   }
993
994   //* Find coordinate change Phi2 such that Q(0) != 0
995   Phi2 = br, maxideal(1);  //* Identity
996   while( Q == 0 && i<n && k <= n ){
997    B2 = maxideal(1);
998    B2[k]= var(k)+ var(i);
999    Phi2 = br, B2;
1000    imagef = Phi2( f );
1001    Q = Coeff( jet(imagef,2), var(i), var(i)^2);
1002    k = k+1;
1003   }
1004   f = Phi2(f);
1005   f = jet(f, Determinacy);
1006
1007   P = Coeff( f , var(i), var(i) );
1008   //* Apply coordinate changes until P = 0
1009   while( P != 0 ){
1010    //* Raise ord(P) by completing the square until > determinacy
1011     P = P / number(2*Q);
1012     B2 = maxideal(1);
1013     B2[i] = var(i) - P;
1014     Phi2 = br, B2;
1015     f = Phi2(f);
1016     f = jet(f, Determinacy);
1017     P = Coeff( f, var(i), var(i));
1018   }
1019  B1[i] = 0;
1020  f = subst(f, var(i), 0);
1021  }
1022 i = i+1;
1023 }
1024 Phi = br, B1;
1025 f = Phi(f);
1026 return( f );
1027}
1028
1029///////////////////////////////////////////////////////////////////////////////
1030static proc Coeff(poly f, list #)
1031{
1032//* initialisation
1033  poly   a, term;
1034  int    n, i;
1035  matrix K;
1036
1037  n     = nvars(basering);
1038  i     = 1;
1039  term  = #[2];
1040  K     = coef(f, #[1]);
1041
1042  while( (i<=ncols(K)) && (K[1,i] != term) )
1043  { i++;
1044    if(i>ncols(K)) { break; }
1045  }
1046  if(i<=ncols(K)) { a = K[2,i]; }
1047  if(i>ncols(K)) { a = 0; }
1048
1049  return(a);
1050}
1051
1052///////////////////////////////////////////////////////////////////////////////
1053static proc ReorderVar( poly f )
1054"USAGE:    GetRf();"
1055{
1056//* Initialisation
1057 intvec frequ;
1058 int maxim, maxim_var, i, j, n;
1059 ideal B = maxideal(1);
1060
1061//* save basering;
1062 def br = basering;
1063 n = nvars(basering);
1064
1065//* frequ[i] determines the frequency of appearance of x_i in f
1066 for ( i=1; i <= n; i=i+1 ){
1067  frequ[i] = ncols( coef( f, var(i) ));
1068  if( Coeff(f, var(i), 0) == 0 ) { frequ[i] = frequ[i]+1; }
1069 }
1070
1071//* Determines the order of the variables, lowest frequency first
1072 for( i=n; i>0; i=i-1 ){
1073  maxim = 0;
1074  maxim_var = 0;
1075  for (j = 1; j<= n; j=j+1 ){
1076   if(frequ[j] > maxim ){ maxim = frequ[j]; maxim_var = j;}
1077  }
1078  B[maxim_var]= var(i);
1079  frequ[maxim_var]=-1;
1080 }
1081
1082//* Reorder variables
1083 map Phi = br, B;
1084 return (Phi(f));
1085}
1086
1087///////////////////////////////////////////////////////////////////////////////
1088static proc Hcode (intvec a)
1089"USAGE:   Hcode(a); a intvec
1090RETURN:  intvec consisting of the numbers of successive repetitions of
1091         entries in a
1092EXAMPLE: example Hcode; shows an example."
1093{
1094  int n=size(a)-1;
1095  a[n+1]=0;
1096  int i,j,k=1,0,k;
1097  int a0=a[i];
1098  intvec c;
1099
1100  while( i <= n )
1101  {
1102    j++;
1103    k=0;
1104    while( i <= n && a0 == a[i] )
1105    {
1106      i++;
1107      k++;
1108    }
1109    c[j]=k;
1110    a0=a[i];
1111  }
1112
1113  return(c);
1114}
1115example
1116{ "EXAMPLE:"; echo=2;
1117  intvec v = 1,3,4,4,4,4,4,4,4,3,9,9,9,9,1;
1118  Hcode(v);
1119}
1120
1121///////////////////////////////////////////////////////////////////////////////
1122proc arnoldMilnorCode (poly f, list #)
1123"USAGE:   arnoldMilnorCode(f[,e]); f poly, e int
1124ASSUME:  basering is local, f has isolated critical point at 0
1125COMPUTE: Milnor code of f consisting of the numbers of successive repetitions
1126         of coefficients of the 2nd Hilbert series of basering/(jacob(f)^e),
1127         see [Bac01].
1128RETURN:  Milnor code of f as intvec where e=1 by default
1129EXAMPLE: example arnoldMilnorCode; shows an example"
1130{
1131  int  e=1;
1132  if(size(#)==1) { e=#[1]; }
1133  ideal jf=std(jacob(f)^e);
1134  intvec v=hilb(jf,2);
1135
1136  return(Hcode(v));
1137}
1138example
1139{ "EXAMPLE:"; echo=2;
1140  ring r=0,(x,y,z),ds;
1141  poly f=x2y+y3+z2;
1142  arnoldMilnorCode(f);
1143  arnoldMilnorCode(f,2);
1144  // a big second argument may result in memory overflow
1145}
1146
1147///////////////////////////////////////////////////////////////////////////////
1148proc arnoldDeterminacy( I, list # )
1149"USAGE:   arnoldDeterminacy( I[, m]); I poly or ideal, m int.
1150ASSUME:  the basering is local, I is (the Jacobian ideal of) a poly f
1151         with isolated critical point at 0, m is the Milnor number of f
1152COMPUTE: determinacy bound k for f w.r.t. right equivalence
1153RETURN:  int k s.th. f is right-k-determined, -1 for infinity
1154NOTE:    uses [Cor. A.9.7,GP12]
1155EXAMPLE: example arnoldDeterminacy; shows an example"
1156{
1157 //* Case: input = poly *//
1158 if(typeof(I)=="poly")
1159 {
1160  ideal J=std(jacob(I));
1161  return(arnoldDeterminacy(J, #));
1162  }
1163 //* Case Input = Ideal *//
1164  if (typeof(I)=="ideal")
1165  {
1166  int k;   //* upper bound of determinacy
1167  int time;
1168
1169  //* Computation of Milnor number *//
1170  if( size(#) > 0){  k = #[1] + 1; }
1171  else { k = vdim(std(I)) + 1;}
1172
1173  //* If milnor number infinite > return -1 otherwise apply A.9.7.
1174  if( k == -1 ){ return (-1); }
1175
1176   int m;
1177   I=std(I);
1178  for(int i=0;i<=2;i++)
1179  {
1180   m = deg(highcorner(I))+2-i;
1181   if(m<k){ k = m;}
1182
1183   //* if the computation of the standard bases for takes > 10 sek
1184   //* algo breaks and returns upper bound found so far
1185   time = timer;
1186   if(i<2){ I = std(maxideal(1)* I); }
1187   if( timer - time > 12 ){ break; }
1188  }
1189    return( k );
1190  }
1191 ERROR("The input has to be a Jacobian ideal or a polynomial");
1192}
1193examples
1194{
1195  ring r=0,(x,y),ds;
1196  poly f=x3+xy3;
1197  ideal I=std(jacob(f));
1198  int k=arnoldDeterminacy(I);
1199  print(k);
1200}
1201
1202
1203///////////////////////////////////////////////////////////////////////////////
1204proc arnoldCorank(poly f)
1205"USAGE:   arnoldCorank(f);  f poly
1206ASSUME:  basering is local, f in maxideal(2) has isolated critical point at 0
1207RETURN:  corank of the Hessian matrix of f
1208EXAMPLE: example arnoldCorank; shows an example"
1209{
1210  matrix M = jacob(jacob(jet(f,2)));
1211  list lba = bareiss(M);
1212  int cr = nvars(basering) - size(module(lba[1]));
1213  return(cr);
1214}
1215example
1216{ "EXAMPLE:"; echo=2;
1217  ring r=0,(x,y,z),ds;
1218  poly f=(x2+3y-2z)^2+xyz-(x-y3+x2*z3)^3;
1219  arnoldCorank(f);
1220}
1221
1222///////////////////////////////////////////////////////////////////////////////
1223static proc check_basering()
1224{
1225  if( char(basering) >= 13 )
1226  {
1227    ERROR("The characteristic of the basering must be at most 13.");
1228    return(1);
1229  }
1230  int n=nvars(basering);
1231  int i=1;
1232  while( i<n && 1>var(i) ) { i++; }
1233  if( 1<var(i) )
1234  {
1235    ERROR("The basering must be local.");
1236    return(1);
1237  }
1238  return(0);  // basering is OK, return (0)
1239}
1240
1241///////////////////////////////////////////////////////////////////////////////
1242static proc init_newsingclass( singclass f )
1243"USAGE:  creates a new singclass, sets the iPoly to the f_input and
1244        the integer values to -1 resp. -2 to indicate that these values
1245        have not been computed yet
1246RETURN: singclass f"
1247{
1248 f.Corank = -1;
1249 f.Milnor = -2;
1250 f.Determinacy = -2;
1251 f.Tjurina = -2;
1252 f.Modality = -1;
1253 intvec mc = -1;
1254 f.MilnorCode = mc;
1255 f.k=-1;
1256 f.r=-1;
1257 f.s=-1;
1258
1259 return(f);
1260}
1261
1262///////////////////////////////////////////////////////////////////////////////
1263proc arnoldShowSeries( string typ )
1264"USAGE:   arnoldShowSeries( S );  S string
1265ASSUME:  S is the name of a singularity series listed by arnoldListAllSeries().
1266RETURN:  data of the singularity series S of type singseries including
1267         @* - Milnor number of S,
1268         @* - Corank of S,
1269         @* - Milnor code of S (see [Bac01]),
1270         @* - normal form of S as string with parameters k,r,s and a,b,c,d,
1271         @* - restrictions on parameters in the normal form in SINGULAR syntax,
1272         @* - normal form with special (valid) parameters.
1273EXAMPLE: example arnoldShowSeries; shows an example
1274"
1275{
1276 string DatabasePath, Database, value;
1277
1278//* Defining the link to the database Singularitylist which stores
1279//* the singularities
1280 string DBMPATH=system("getenv","DBMPATH");
1281 if( DBMPATH != "" ) { DatabasePath = DBMPATH+"/Singularitylist"; }
1282 else { DatabasePath = "Singularitylist"; }
1283 Database="DBM: ",DatabasePath;
1284
1285//* link to the database
1286 link dbmLink=Database;
1287//* database Singularitylist entry for key
1288 value = read(dbmLink, typ);
1289if(value =="")
1290   {ERROR("SingularitySeries not known. Call arnoldListAllSeries() to get
1291    a list of all valid Singularity types.");}
1292 close(dbmLink);
1293 execute(value);
1294 return( f );
1295}
1296example
1297{ "EXAMPLE:"; echo=2;
1298  arnoldShowSeries("Z[k,12k+6r]");
1299}
1300
1301
1302///////////////////////////////////////////////////////////////////////////////
1303static proc normalformDB( typ )
1304{
1305 if( typeof(typ) == "string" )
1306  {
1307  def f = arnoldShowSeries(typ);
1308  return( f.NormalForm );
1309  }
1310
1311 if( typeof(typ) =="singclass")
1312  {
1313  def f = arnoldShowSeries( typ.Series );
1314  return( f.NormalForm );
1315  }
1316}
1317
1318///////////////////////////////////////////////////////////////////////////////
1319static proc NormalFormAndRestrictionsDB( typ )
1320{
1321 if( typeof(typ) == "string" )
1322  {
1323  def f = arnoldShowSeries(typ);
1324  return( f.NormalForm, f.Restrictions);
1325  }
1326
1327 if( typeof(typ) =="singclass")
1328  {
1329  def f = arnoldShowSeries( typ.Series );
1330  return( f.NormalForm, f.Restrictions );
1331  }
1332}
1333
1334///////////////////////////////////////////////////////////////////////////////
1335static proc specialformDB( typ )
1336{
1337 if( typeof(typ) == "string" )
1338  {
1339  def f = arnoldShowSeries(typ);
1340  return( f.SpecialForm );
1341  }
1342
1343 if( typeof(typ) =="singclass")
1344  {
1345  def f = arnoldShowSeries( typ.Series );
1346  return( f.SpecialForm );
1347  }
1348}
1349
1350///////////////////////////////////////////////////////////////////////////////
1351static proc restrictionsDB( typ )
1352{
1353 if( typeof(typ) == "string" )
1354  {
1355  def f = arnoldShowSeries(typ);
1356  return( f.Restrictions );
1357  }
1358
1359 if( typeof(typ) =="singclass")
1360  {
1361  def f = arnoldShowSeries( typ.Series );
1362  return( f.Restrictions );
1363  }
1364}
1365
1366///////////////////////////////////////////////////////////////////////////////
1367proc arnoldNormalForm( typ, list #)
1368"USAGE:   arnoldNormalForm( S [, l]), S string or singclass, l list
1369ASSUME:  If S is of type string, then S is the name of a singularity series
1370         as listed by arnoldListAllSeries() and l may contain suitable
1371         integer parameters k,r,s. Otherwise S of type singclass is a
1372         singularity class from Arnol'd's list.
1373         Optional suitable polynomial parameters a,b,c,d can be appended to l.
1374         If a,b,c,d are not given, valid values are chosen automatically.
1375RETURN:  string NF is the normal form of the series S if no parameters given,
1376         or poly NF is the normal form of the class S with paramaters k,r,s.
1377EXAMPLE: example arnoldNormalForm; shows an example"
1378{
1379
1380//* Sort list entries by type
1381 int noparas = 1;
1382 list polys;
1383 for( int i = 1; i<=size(#); i++)
1384 {
1385  if(typeof( #[i] ) == "int" )
1386  {
1387   if( noparas == 1 ){ intvec paras = #[1]; noparas =0; }
1388   else{ paras[size(paras)+1] = #[i];}
1389  }
1390  if( typeof(#[i]) == "poly")
1391  {
1392   polys[size(polys)+1] = #[i];
1393  }
1394  if( typeof(#[i]) != "int" && typeof(#[i]) != "poly")
1395  {ERROR("Entries of list # must be of type poly or int.");}
1396 }
1397
1398//* If no paras and typ = "string" -> string
1399  if( (typeof (typ) == "string") && (noparas == 1) )
1400  { return( specialformDB(typ) ); }
1401
1402//* Set parameter k,r,s
1403 if( typeof( typ ) == "singclass" )
1404 { int k = typ.k; int r = typ.r; int s = typ.s; string Series = typ.Series; }
1405 if( typeof( typ ) == "string" )
1406 { int k,r,s = paras; string Series = typ; }
1407
1408//* Check if basering is defined
1409 if(!defined(basering)){
1410  ERROR("No basering defined!")}
1411
1412//* Check case k=1
1413 if( k == 1 ){
1414  if( Series[1] == "Y"){ Series = replace( Series, "k", string(k)); }
1415  if( Series[1] == "X"){ Series = replace( Series, "k", string(k)); }
1416  if( Series[1] == "Z"){ Series = replace( Series, "k", string(k)); }
1417 }
1418
1419//* If no polynomial parameter Specialform
1420  if(size(polys) != 0 && size(polys) <4 )
1421  {ERROR("Not enough polynomial parameter as input.")}
1422  if(size(polys) == 0 ){
1423    //* Define ring for the NF; NF given in C(x,y)
1424    def br = basering;
1425      if(defined(RingNF) != 0 ) { kill RingNF; }
1426    ring RingNF=char(basering),(x,y),(c, ds);
1427    map Conv = br,maxideal(1);
1428
1429    string nf_str = specialformDB(Series);
1430    }
1431  else{
1432
1433   //* Set polynomial parameter
1434   poly a,b,c,d;
1435   a = polys[1];
1436   b = polys[2];
1437   c = polys[3];
1438   d = polys[4];
1439
1440   //* Define ring for the NF; NF given in C(x,y)
1441    def br = basering;
1442     if(defined(RingNF) != 0 ) { kill RingNF; }
1443     ring RingNF=char(basering),(x,y),(c, ds);
1444     map Conv = br,maxideal(1);
1445
1446   //* Map Polynomial parameter
1447   poly a = Conv(a);
1448   poly b = Conv(b);
1449   poly c = Conv(c);
1450   poly d = Conv(d);
1451
1452   //* Get NormalForm from Databank
1453   string nf_str = normalformDB(Series);
1454
1455   //* Replace polynomial parameter
1456   nf_str = replace( nf_str, "a(y)", "("+string(a)+")");
1457   nf_str = replace( nf_str, "b(y)", "("+string(b)+")");
1458   nf_str = replace( nf_str, "c(y)", "("+string(c)+")");
1459   nf_str = replace( nf_str, "d(y)", "("+string(d)+")");
1460
1461   //* Check parameter
1462   int okay = 0;
1463   string res = restrictionsDB(Series);
1464   string str = "if(" + res + "){okay = 1;};";
1465   execute(str);
1466   if(okay!=1)
1467   {ERROR("Parameter do not satisfy restrictions of
1468   the singularity series.")}
1469 }
1470
1471 //* Replace integer parameter
1472 nf_str = replace( nf_str, "k", string(k));
1473 nf_str = replace( nf_str, "r", string(r));
1474 nf_str = replace( nf_str, "s", string(s));
1475
1476 //* Generate polynomial nf
1477 nf_str = "poly nf  = " + nf_str;
1478 execute( nf_str );
1479
1480 //* Map poly nf back to basering;
1481 setring br;
1482 map ConvBack = RingNF, maxideal(1);
1483  return( ConvBack(nf) );
1484}
1485example
1486{ "EXAMPLE:"; echo=2;
1487  ring R = 0, (x,y), ds;
1488 poly a,b,c,d;
1489 a= 1+y2;
1490 c= 3+y;
1491 int k = 5;
1492 int r = 4;
1493 int s = 3;
1494 arnoldNormalForm ("W[12k+1]", k,r,s,a,b,c,d);
1495 def f = _;
1496 def sf = arnoldClassify( f );
1497 arnoldNormalForm(sf, a,b,c,d);
1498 arnoldNormalForm("W[12k+1]");
1499 arnoldNormalForm(sf);
1500}
1501
1502///////////////////////////////////////////////////////////////////////////////
1503proc arnoldListAllSeries()
1504"USAGE:    arnoldListAllSeries();
1505RETRURN:  list of names of singularity series listed by Arnol'd up to corank 2
1506EXAMPLE:  example arnoldListAllSeries; shows an example"
1507{
1508list l=
1509"A[k]",
1510"D[k]",
1511"E[6k]",
1512"E[6k+1]",
1513"E[6k+2]",
1514"J[k,0]",
1515"J[k,r]",
1516"W[12k]",
1517"W[12k+1]",
1518"W[12k+5]",
1519"W[12k+6]",
1520"W[k,0]",
1521"W[k,r]",
1522"W#[k,2r]",
1523"W#[k,2r-1]",
1524"X[k,0]",
1525"X[k,r]",
1526"Y[k,r,s]",
1527"Z[k,r]",
1528"Z[k,r,s]",
1529"Z[1,6r+11]",
1530"Z[1,6r+12]",
1531"Z[1,6r+13]",
1532"Z[k,12k+6r]",
1533"Z[k,12k+6r+1]",
1534"Z[k,12k+6r-1]";
1535
1536return(l);
1537}
1538example
1539{ arnoldListAllSeries();
1540}
1541
1542///////////////////////////////////////////////////////////////////////////////
1543///////////////////////////////////////////////////////////////////////////////
1544//* The following part of the library generates two files, Singularitylist.dir
1545//* and Singularitylist.pag containing a data base for singularities up to
1546//* corank 2 listed by Arnol'd.
1547
1548///////////////////////////////////////////////////////////////////////////////
1549static proc makedbm_init()
1550{
1551//* Generates file containing a data base for singularities up to corank 2
1552//* listed by Arnol'd. This file is needed for arnoldclassify.lib.
1553
1554  string s;
1555  link l="DBM:r Singularitylist";
1556  s = read(l,"VERSION");
1557  if (s == "" ) {
1558    "Need to create database...";
1559    create_singularity_dbm();
1560  }
1561  close(l);
1562  l="DBM:r Singularitylist";
1563  s = read(l,"VERSION");
1564  "Creation done. Current version:", s;
1565}
1566///////////////////////////////////////////////////////////////////////////////
1567
1568static proc dbm_read (link l)
1569{
1570  string s="";
1571  s=read(l);
1572  while( s != "" )
1573  {
1574    s,"=",read(l,s);
1575    s=read(l);
1576  }
1577}
1578
1579///////////////////////////////////////////////////////////////////////////////
1580static proc dbm_getnext (link l)
1581{
1582  string s="";
1583  s=read(l);
1584  if( s != "" ) { s,"=",read(l,s); }
1585}
1586
1587///////////////////////////////////////////////////////////////////////////////
1588static proc create_singularity_dbm
1589{
1590  link l="DBM:rw Singularitylist";
1591
1592//*Data typ singseries;
1593  string s;
1594
1595//* A[k]
1596    s = "singseries f;
1597    f.Series = \"A[k]\";
1598    f.Modality = \"0\";
1599    f.Corank = \"1\";
1600    f.MilnorNumber = \"k\";
1601    f.MilnorCode = \"k\";
1602    f.NormalForm = \"x^(k+1)\";
1603    f.SpecialForm = \"x^(k+1)\";
1604    f.Restrictions = \"(k>1)\";";
1605  write(l, "A[k]", s);
1606
1607//* D[k]
1608    s = "singseries f;
1609    f.Series = \"D[k]\";
1610    f.Modality = \"0\";
1611    f.Corank = \"2\";
1612    f.MilnorNumber = \"k\";
1613    f.MilnorCode = \"1,1,k-3\";
1614    f.NormalForm = \"x^2*y+y^(k-1)\";
1615    f.SpecialForm = \"x^2*y+y^(k-1)\";
1616    f.Restrictions = \"(k>=4)\";";
1617  write(l, "D[k]", s);
1618
1619//* J[k,0]
1620    s = "singseries f;
1621    f.Series = \"J[k,0]\";
1622    f.Modality = \"0\";
1623    f.Corank = \"2\";
1624    f.MilnorNumber = \"6*k-2\";
1625    f.MilnorCode = \"1,2*k+j,2*k-2*j-3\";
1626    f.NormalForm = \"x^3 + b(y)*x^2*y^k+c(y)*x*y^(2*k+1)+y^(3*k)\";
1627    f.SpecialForm = \"x^3 + x^2*y^k+y^(3*k)\";
1628    f.Restrictions = \"(k>1)&& (4*b^3 + 27 != 0)&&
1629     (deg(b)==0)&&(deg(c)<=(k-3))&&(k>2||c==0)\";";
1630  write(l, "J[k,0]", s);
1631
1632//* J[k,r]
1633    s = "singseries f;
1634    f.Series = \"J[k,r]\";
1635    f.Modality = \"0\";
1636    f.Corank = \"2\";
1637    f.MilnorNumber = \"6*k-2+r\";
1638    f.MilnorCode = \"1,2*k-1,2*k+r-1\";
1639    f.NormalForm = \"x^3 + x^2*y^k+a(y)*y^(3*k+r)\";
1640    f.SpecialForm = \"x^3 + x^2*y^k+y^(3*k+r)\";
1641    f.Restrictions = \"(k>1)&&(r>0)&&(jet(a,0)!= 0)&&(deg(a)<=(k-2)) \";";
1642  write(l, "J[k,r]", s);
1643
1644//* E[6k]
1645    s = "singseries f;
1646    f.Series = \"E[6k]\";
1647    f.Modality = \"0\";
1648    f.Corank = \"2\";
1649    f.MilnorNumber = \"6*k\";
1650    f.MilnorCode = \"1,2*k+j,2*k-2j-1\";
1651    f.NormalForm = \"x^3 + a(y)*x*y^(2*k+1)+y^(3*k+1)\";
1652    f.SpecialForm = \"x^3+y^(3*k+1)\";
1653    f.Restrictions = \"(k>=1)&&(k>1||a==0)&&(deg(a)<=(k-2))\";";
1654  write(l, "E[6k]", s);
1655
1656//* E[6k+1]
1657    s = "singseries f;
1658    f.Series = \"E[6k+1]\";
1659    f.Modality = \"0\";
1660    f.Corank = \"2\";
1661    f.MilnorNumber = \"6*k+1\";
1662    f.MilnorCode = \"1,2*k,2*k\";
1663    f.NormalForm = \"x^3 + x*y^(2*k+1)+a(y)*y^(3*k+2)\";
1664    f.SpecialForm = \"x^3 + x*y^(2*k+1)\";
1665    f.Restrictions = \"(k>=1)&&(k>1||a==0)&&(deg(a)<=(k-2))\";";
1666  write(l, "E[6k+1]", s);
1667
1668//* E[6k+2]
1669    s = "singseries f;
1670    f.Series = \"E[6k+2]\";
1671    f.Modality = \"0\";
1672    f.Corank = \"2\";
1673    f.MilnorNumber = \"6*k+2\";
1674    f.MilnorCode = \"1,2*k+j+1,2*k-2j-1\";
1675    f.NormalForm = \"x^3 + a(y)*x*y^(2*k+2)+y^(3*k+2)\";
1676    f.SpecialForm = \"x^3 +y^(3*k+2)\";
1677    f.Restrictions = \"(k>=1)&&(k>1||a==0)&&(deg(a)<=(k-2))\";";
1678  write(l, "E[6k+2]", s);
1679
1680//* X[k,0]
1681    s = "singseries f;
1682    f.Series = \"X[k,0]\";
1683    f.Modality = \"3*k-2\";
1684    f.Corank = \"2\";
1685    f.MilnorNumber = \"12*k-3\";
1686    f.MilnorCode = \"1,1,2*k-1+j,2k-1-2*j+t,2*k-1+j-2t\";
1687    f.NormalForm = \"x^4 + b(y)*x^3*y^k + a(y)*x^2*y^(2*k) + x*y^(3*k)\";
1688    f.SpecialForm = \"x^4 + x^3*y^k + x*y^(3*k)\";
1689    f.Restrictions = \"(jet(a,0)*jet(b,0)!=9)&&(k>1)&&(4*(jet(a,0)^3+jet(b,0)^3)
1690     - jet(a,0)^2*jet(b,0)^2-18* jet(a,0)*jet(b,0) + 27 !=0)&&(deg(a)<=(k-2))
1691     &&(deg(b)<=(2*k-2))\";";
1692  write(l, "X[k,0]", s);
1693
1694    //* X[1,0]
1695        s = "singseries f;
1696        f.Series = \"X[1,0]\";
1697        f.Modality = \"1\";
1698        f.Corank = \"2\";
1699        f.MilnorNumber = \"9\";
1700        f.MilnorCode = \"1,1,1+j,1-2*j+t,1+j-2t\";
1701        f.NormalForm = \"x^4 + a(y)*x^2*y^2 + y^4\";
1702        f.SpecialForm = \"x^4 + x^2*y^2 + y^4\";
1703        f.Restrictions = \"(deg(a)==0)&&(jet(a,0)^2!=4)\";";
1704      write(l, "X[1,0]", s);
1705
1706    //* X[k,r]
1707        s = "singseries f;
1708        f.Series = \"X[k,r]\";
1709        f.Modality = \"3*k-2\";
1710        f.Corank = \"2\";
1711        f.MilnorNumber = \"12*k-3+r\";
1712        f.MilnorCode = \"1,1,2*k-1+j,2k-1-2*j,2*k-1+j+r\";
1713        f.NormalForm = \"x4+a(y)*x3*y^(k)+x^2*y^(2*k)+b(y)*y^(4*k+r)\";
1714        f.SpecialForm = \"x4+x3*y^(k)+x^2*y^(2*k)+y^(4*k+r)\";
1715        f.Restrictions = \"(k>1)&&(r>0)&&(deg(a)<=(k-2))&&(jet(a,0)^2!=4)&&
1716        (jet(b,0)!=0)&&(deg(b)<=(2*k-2))\";";
1717      write(l, "X[k,r]", s);
1718
1719    //* X[1,r]
1720        s = "singseries f;
1721        f.Series = \"X[1,r]\";
1722        f.Modality = \"1\";
1723        f.Corank = \"2\";
1724        f.MilnorNumber = \"9+r\";
1725        f.MilnorCode = \"1,1,1+j,1-2*j,1+j+r\";
1726        f.NormalForm = \"x4+x^2*y^2+a(y)*y^(4+r)\";
1727        f.SpecialForm = \"x4+x^2*y^2+y^(4+r)\";
1728        f.Restrictions = \"(deg(a)==0)&&(jet(a,0)!=0)\";";
1729        write(l, "X[1,r]", s);
1730
1731    //* Y[k,r,s]
1732        s = "singseries f;
1733        f.Series = \"Y[k,r,s]\";
1734        f.Modality = \"3*k-2\";
1735        f.Corank = \"2\";
1736        f.MilnorNumber = \"12*k-3+r+s\";
1737        f.MilnorCode = \"1,1,2*k-1,2*k-1+j,2*k-1-2*j+r+s\";
1738        f.NormalForm = \"((x + a(y)*y^k)^2 + b(y)*y^(2*k+s))*(x2 + y^(2*k+r))\";
1739        f.SpecialForm = \"((x + y^k)^2 + y^(2*k+s))*(x2 + y^(2*k+r))\";
1740        f.Restrictions = \"(jet(a,0)!=0)&&(deg(a)<=(k-2))&&(k>1)&&(jet(b,0)!=0)
1741        &&(1<=s)&&(s<=7)\";";
1742        write(l, "Y[k,r,s]", s);
1743
1744    //* Y[1,r,s]
1745        s = "singseries f;
1746        f.Series = \"Y[1,r,s]\";
1747        f.Modality = \"1\";
1748        f.Corank = \"2\";
1749        f.MilnorNumber = \"9+r+s\";
1750        f.MilnorCode = \"1,1,1,1+j,1-2*j+r+s\";
1751        f.NormalForm = \" x^(4+r)+ a(y)*x2*y2 + y^(4+s)\";
1752        f.SpecialForm = \" x^(4+r)+ x2*y2 + y^(4+s)\";
1753        f.Restrictions = \"(deg(a)==0)&&(jet(a,0)!=0)&&(1<=s)&&(s<=7)\";";
1754        write(l, "Y[1,r,s]", s);
1755
1756    //* Z[k,r]
1757        s = "singseries f;
1758        f.Series = \"Z[k,r]\";
1759        f.Modality = \"3*k+r-2\";
1760        f.Corank = \"2\";
1761        f.MilnorNumber = \"12*k-3+6*r\";
1762        f.MilnorCode = \"1,1,2*k-1,2*k-1+j,2*k-1+6*r-2*j\";
1763        f.NormalForm = \"(x + a(y)*y^k)*(x^3 + d(y)*x2*y^(k+1) +
1764        c(y)*x*y^(2*k+2*r+1) + y^(3*k+3*r))\";
1765        f.SpecialForm = \"(x + y^k)*(x^3 + 2*y^(k+1) + x*y^(2*k+2*r+1) +
1766        y^(3*k+3*r))\";
1767        f.Restrictions = \"(k>1)&&(r>=0)&&(4*d^3+27!=0)&&(deg(d)==0)&&
1768        (deg(c)<=(2*k+r-3))&&(deg(a)<=(k-2))\";";
1769        write(l, "Z[k,r]", s);
1770
1771    //* Z[1,r]
1772        s = "singseries f;
1773        f.Series = \"Z[1,r]\";
1774        f.Modality = \"1+r\";
1775        f.Corank = \"2\";
1776        f.MilnorNumber = \"9+6*r\";
1777        f.MilnorCode = \"1,1,1,1+j,1+6*r-2*j\";
1778        f.NormalForm = \"y*(x^3 + d(y)*x^2*y^(2) + c(y)*x*y^(2+2*r+1) +
1779        y^(3+3*r))\";
1780        f.SpecialForm = \"y*(x^3 + x^2*y^(2) + x*y^(2+2*r+1) +
1781        y^(3+3*r))\";
1782        f.Restrictions = \"(r>=0)&&(4*d^3+27!=0)&&(deg(d)==0)
1783        &&(deg(c)<=(r-1))\";";
1784        write(l, "Z[1,r]", s);
1785
1786    //* Z[k,r,s]
1787        s = "singseries f;
1788        f.Series = \"Z[k,r,s]\";
1789        f.Modality = \"3*k+r-2\";
1790        f.Corank = \"2\";
1791        f.MilnorNumber = \"12*k+6*r+s-3\";
1792        f.MilnorCode = \"1,1,2*k-1,2*k-1+2*r,2*k-1+2*r-s\";
1793        f.NormalForm = \"(x^2 + a(y)*x*y^k + b(y)*y^(2*k+r))*
1794        (x^2 + y^(2*k+2*r+s))\";
1795        f.SpecialForm = \"(x^2 + x*y^k + y^(2*k+r))*(x^2 + y^(2*k+2*r+s))\";
1796        f.Restrictions = \"(k>1)&&(r>=0)&&(deg(a)<=(k-2))&&(jet(a,0)!=0)&&
1797        (jet(b,0)!=0)&&(deg(b)<=(2*k+r-2))\";";
1798        write(l, "Z[k,r,s]", s);
1799
1800    //* Z[1,r,s]
1801        s = "singseries f;
1802        f.Series = \"Z[1,r,s]\";
1803        f.Modality = \"1+r\";
1804        f.Corank = \"2\";
1805        f.MilnorNumber = \"9+6*r+s\";
1806        f.MilnorCode = \"1,1,1,1+2*r,1+2*r-s\";
1807        f.NormalForm = \"y*(x^3 + x^2*y^(r+1) + b(y)*y^(3*r+s+3))\";
1808        f.SpecialForm = \"y*(x^3 + x^2*y^(r+1) + y^(3*r+s+3))\";
1809        f.Restrictions = \"(r>=0)&&(jet(b,0)!=0)&&(deg(b)<=(2*k+r-2))\";";
1810        write(l, "Z[1,r,s]", s);
1811
1812    //* Z[k,12k+6r-1]
1813        s = "singseries f;
1814        f.Series = \"Z[k,12k+6r-1]\";
1815        f.Modality = \"3*k+r-2\";
1816        f.Corank = \"2\";
1817        f.MilnorNumber = \"12*k+6r-1\";
1818        f.MilnorCode = \"1,1,2k-1,2k-1+j,2k+1+6*r-2*j\";
1819        f.NormalForm = \"(x + a(y)*y^k)*(x^3 + b(y)*x*y^(2*k+2*r+1) +
1820         y^(3*k+3*r+1))\";
1821        f.SpecialForm = \"(x + y^k)*(x^3 + x*y^(2*k+2*r+1) + y^(3*k+3*r+1))\";
1822        f.Restrictions = \" (k>1)&&(r>=0)&&(deg(a)<=(k-2))&&(jet(a,0)!=0)&&
1823        (jet(b,0)!=0)&&(deg(b)<=(2*k+r-2))\";";
1824        write(l, "Z[k,12k+6r-1]", s);
1825
1826        //* Z[1,6r+11]
1827            s = "singseries f;
1828            f.Series = \"Z[1,6r+11]\";
1829            f.Modality = \"1+r\";
1830            f.Corank = \"2\";
1831            f.MilnorNumber = \"6r+11\";
1832            f.MilnorCode = \"1,1,1,1+j,3+6*r-2*j\";
1833            f.NormalForm = \"y*(x^3 + b(y)*x*y^(2+2*r+1) + y^(3+3*r+1))\";
1834            f.SpecialForm = \"y*(x^3 + x*y^(2+2*r+1) + y^(3+3*r+1))\";
1835            f.Restrictions = \"(r>=0)&&(deg(b)<=(r))\";";
1836            write(l, "Z[1,6r+11]", s);
1837
1838    //* Z[k,12k+6r+1]
1839        s = "singseries f;
1840        f.Series = \"Z[k,12k+6r+1]\";
1841        f.Modality = \"3*k+r-2\";
1842        f.Corank = \"2\";
1843        f.MilnorNumber = \"12*k+6r+1\";
1844        f.MilnorCode = \"1,1,2k-1,2k-1+j,2k+3+6*r-2*j\";
1845        f.NormalForm = \"(x + a(y)*y^k)*(x^3 + b(y)*x*y^(2*k+2*r+2) +
1846         y^(3*k+3*r+2))\";
1847        f.SpecialForm = \"(x + y^k)*(x^3 + x*y^(2*k+2*r+2) + y^(3*k+3*r+2))\";
1848        f.Restrictions = \" (k>1)&&(r>=0)&&(deg(a)<=(k-2))&&(jet(a,0)!=0)&&
1849        (jet(b,0)!=0)&&(deg(b)<=(2*k+r-2))\";";
1850        write(l, "Z[k,12k+6r+1]", s);
1851
1852    //* Z[1,6r+13]
1853        s = "singseries f;
1854        f.Series = \"Z[1,6r+13]\";
1855        f.Modality = \"1+r\";
1856        f.Corank = \"2\";
1857        f.MilnorNumber = \"6r+13\";
1858        f.MilnorCode = \"1,1,1,1+j,5+6*r-2*j\";
1859        f.NormalForm = \"y*(x^3 + b(y)*x*y^(2*r+4) + y^(3*r+5))\";
1860        f.SpecialForm = \"y*(x^3 + x*y^(2*r+4) + y^(3*r+5))\";
1861        f.Restrictions = \" (r>=0)&&(deg(b)<=(r))\";";
1862        write(l, "Z[1,6r+13]", s);
1863
1864    //* Z[k,12k+6r]
1865        s = "singseries f;
1866        f.Series = \"Z[k,12k+6r]\";
1867        f.Modality = \"3*k+r-2\";
1868        f.Corank = \"2\";
1869        f.MilnorNumber = \"12*k+6r\";
1870        f.MilnorCode = \"1,1,2k-1,2k-1+2*r,2k+2*r\";
1871        f.NormalForm = \"(x + a(y)*y^k)*(x^3 + x*y^(2*k+2*r+1) +
1872        b(y)* y^(3*k+3*r+2))\";
1873        f.SpecialForm = \"(x + y^k)*(x^3 + x*y^(2*k+2*r+1) +y^(3*k+3*r+2))\";
1874        f.Restrictions = \" (k>1)&&(r>=0)&&(deg(a)<=(k-2))&&(jet(a,0)!=0)&&
1875        (jet(b,0)!=0)&&(deg(b)<=(2*k+r-2))\";";
1876        write(l, "Z[k,12k+6r]", s);
1877
1878
1879    //* Z[1,6r+12]
1880        s = "singseries f;
1881        f.Series = \"Z[1,6r+12]\";
1882        f.Modality = \"1+r\";
1883        f.Corank = \"2\";
1884        f.MilnorNumber = \"6*r+12\";
1885        f.MilnorCode = \"1,1,1,1+2*r,2+2*r\";
1886        f.NormalForm = \"y*(x^3 + x*y^(2*r+3) +b(y)* y^(3*r+5))\";
1887        f.SpecialForm = \"y*(x^3 + x*y^(2*r+3) +y^(3*r+5))\";
1888        f.Restrictions = \"(r>=0)&&(deg(b)<=(r))\";";
1889        write(l, "Z[1,6r+12]", s);
1890
1891
1892    //* W[k,r]
1893        s = "singseries f;
1894        f.Series = \"W[k,r]\";
1895        f.Modality = \"3*k-1\";
1896        f.Corank = \"2\";
1897        f.MilnorNumber = \"12*k+3+r\";
1898        f.MilnorCode = \"1,1,2k,2k,2k+r\";
1899        f.NormalForm = \"x4+a(y)*x^3*y^(k+1)+x^2*y^(2*k+1)+b(y)*y^(4*k+2+r) \";
1900        f.SpecialForm = \"x4+x^2*y^(2*k+1)+y^(4*k+2+r) \";
1901        f.Restrictions = \"(k>=1)&&(r>0)&&(k>1||a==0)&&(deg(a)<=(k-2))&&
1902        (jet(b,0)!=0)&&(deg(b)<=(2*k-1))\";";
1903        write(l, "W[k,r]", s);
1904
1905    //* W[k,0]
1906        s = "singseries f;
1907        f.Series = \"W[k,0]\";
1908        f.Modality = \"3*k-1\";
1909        f.Corank = \"2\";
1910        f.MilnorNumber = \"12*k+3\";
1911        f.MilnorCode = \"1,1,2k+j,2k-2-2*j+t,2k+6+j+2*t\";
1912        f.NormalForm = \"x4+b(y)*x2*y^(2*k+1)+a(y)*x*y^(3*k+2)+y^(4*k+2) \";
1913        f.SpecialForm = \"x4+x2*y^(2*k+1)+y^(4*k+2) \";
1914        f.Restrictions = \" (k>=1)&&(k>1||a==0)&&(deg(a)<=(k-2))&&
1915        (jet(b,0)^2!=4)&&(deg(b)<=(2*k-1))\";";
1916        write(l, "W[k,0]", s);
1917
1918    //* W[12k]
1919        s = "singseries f;
1920        f.Series = \"W[12k]\";
1921        f.Modality = \"3*k-2\";
1922        f.Corank = \"2\";
1923        f.MilnorNumber = \"12*k\";
1924        f.MilnorCode = \"1,1,2k+j,2k-3-2*j+t,2k+3+j-2*t\";
1925        f.NormalForm = \"x4+a(y)*x*y^(3*k+1)+c(y)*x^2*y^(2*k+1)+y^(4*k+1)\";
1926        f.SpecialForm = \"x4+x^2*y^(2*k+1)+y^(4*k+1)\";
1927        f.Restrictions = \"(k>=1)&&(k>1||a==0)&&(deg(a)<=(k-2))&&
1928        (deg(c)<=(2*k-2))\";";
1929        write(l, "W[12k]", s);
1930
1931    //* W[12k+1]
1932        s = "singseries f;
1933        f.Series = \"W[12k+1]\";
1934        f.Modality = \"3*k-2\";
1935        f.Corank = \"2\";
1936        f.MilnorNumber = \"12*k+1\";
1937        f.MilnorCode = \"1,1,2k+j,2k-1-2*j,2k+j\";
1938        f.NormalForm = \"x4+x*y^(3*k+1)+a(y)*x^2*y^(2*k+1)+c(y)*y^(4*k+2) \";
1939        f.SpecialForm = \"x4+x*y^(3*k+1)+y^(4*k+2) \";
1940        f.Restrictions = \"(k>=1)&&(k>1||a==0)&&(deg(a)<=(k-2))&&
1941        (deg(c)<=(2*k-2))\";";
1942        write(l, "W[12k+1]", s);
1943
1944    //* W[12k+5]
1945        s = "singseries f;
1946        f.Series = \"W[12k+5]\";
1947        f.Modality = \"3*k-1\";
1948        f.Corank = \"2\";
1949        f.MilnorNumber = \"12*k+5\";
1950        f.MilnorCode = \"1,1,2k+j,2k+1-2*j,2k+j\";
1951        f.NormalForm = \"x4+x*y^(3*k+2)+a(y)*x^2*y^(2*k+2)+b(y)*y^(4*k+3) \";
1952        f.SpecialForm = \"x4+x*y^(3*k+2)+y^(4*k+3) \";
1953        f.Restrictions = \"(k>=1)&&(k>1||a==0)&&(deg(a)<=(k-2))&&
1954        (deg(b)<=(2*k-1))\";";
1955        write(l, "W[12k+5]", s);
1956
1957    //* W[12k+6]
1958        s = "singseries f;
1959        f.Series = \"W[12k+6]\";
1960        f.Modality = \"3*k-1\";
1961        f.Corank = \"2\";
1962        f.MilnorNumber = \"12*k+6\";
1963        f.MilnorCode = \"1,1,2k+j,2k-3-2*j+t,2k+9+j-2*t\";
1964        f.NormalForm = \"x4+a(y)*x*y^(3*k+3)+b(y)*x^2*y^(2*k+2)+y^(4*k+3) \";
1965        f.SpecialForm = \"x4+x^2*y^(2*k+2)+y^(4*k+3) \";
1966        f.Restrictions = \"(k>=1)&&(k>1||a==0)&&(deg(a)<=(k-2))&&
1967        (deg(b)<=(2*k-1))\";";
1968        write(l, "W[12k+6]", s);
1969
1970    //* W#[k,2r]
1971        s = "singseries f;
1972        f.Series = \"W#[k,2r]\";
1973        f.Modality = \"3*k-1\";
1974        f.Corank = \"2\";
1975        f.MilnorNumber = \"12*k+3+2*r\";
1976        f.MilnorCode = \"1,1,2k,2k+r,2k\";
1977        f.NormalForm = \"(x2+y^(2*k+1))^2+b(y)*x^2*y^(2*k+1+r)+
1978        a(y)*x*y^(3*k+2+r) \";
1979        f.SpecialForm = \"(x2+y^(2*k+1))^2+x^2*y^(2*k+1+r) \";
1980        f.Restrictions = \"(k>=1)&&(r>0)&&(k>1||a==0)&&(deg(a)<=(k-2))&&
1981        (jet(b,0)!=0)&&(deg(b)<=(2*k-1))\";";
1982        write(l, "W#[k,2r]", s);
1983
1984    //* W#[k,2r-1]
1985        s = "singseries f;
1986        f.Series = \"W#[k,2r-1]\";
1987        f.Modality = \"3*k-1\";
1988        f.Corank = \"2\";
1989        f.MilnorNumber = \"12*k+2+2*r\";
1990        f.MilnorCode = \"1,1,2k,2k-3+j,2*k+5+2*r-2*j\";
1991        f.NormalForm = \"(x2+y^(2*k+1))^2+b(y)*x*y^(3*k+1+r)+
1992        a(y)*y^(4*k+2+r)\";
1993        f.SpecialForm = \"(x2+y^(2*k+1))^2+x*y^(3*k+1+r)\";
1994        f.Restrictions = \"(k>=1)&&(r>0)&&(k>1||a==0)&&(deg(a)<=(k-2))
1995        &&(jet(b,0)!=0)&&(deg(b)<=(2*k-1))\";";
1996        write(l, "W#[k,2r-1]", s);
1997
1998 write(l,"VERSION", "1.0");
1999  close(l);
2000}
2001
2002///////////////////////////////////////////////////////////////////////////////
2003static proc read_singularity_db( string typ )
2004{
2005  string DBMPATH=system("getenv","DBMPATH");
2006  string DatabasePath, Database, S, Text, Tp;
2007
2008  if( DBMPATH != "" ) { DatabasePath = DBMPATH+"/Singularitylist"; }
2009  else { DatabasePath = "Singularitylist"; }
2010  Database="DBM: ",DatabasePath;
2011
2012  link dbmLink=Database;
2013  Tp = read(dbmLink, typ);
2014    return(Tp);
2015
2016}
2017
Note: See TracBrowser for help on using the repository browser.