source: git/Singular/LIB/arnoldclassify.lib @ 078a4a

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