source: git/Singular/LIB/arnoldclassify.lib @ 8fd403

spielwiese
Last change on this file since 8fd403 was 61fbaf, checked in by Hans Schoenemann <hannes@…>, 18 months ago
doc: arnoldClassify_to_string
  • Property mode set to 100644
File size: 59.8 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2version="version arnoldclassify.lib 4.3.1.2 Nov_2022 "; // $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
37arnoldClassify_to_string(f); singularity class of a power series f
38arnoldCorank(f);         corank of singularity defined by f
39arnoldDeterminacy(f,#);  upper bound for the determinacy of f
40arnoldMilnorCode(f,#);   Milnor Code of a singularity f
41arnoldMorseSplit(f,#);   result of Splitting Lemma applied to f
42";
43
44LIB "inout.lib";
45LIB "elim.lib";
46LIB "sing.lib";
47LIB "findifs.lib";
48
49///////////////////////////////////////////////////////////////////////////////
50static proc mod_init()
51{
52//* define new datastruct singclass
53newstruct("singclass", "string Restrictions, string NormalForm,
54intvec MilnorCode, int Tjurina, int Determinacy, int Milnor, int Corank,
55int Modality, int s, int r, int k, string Class, string Series ");
56
57//* define new datastruct singclass
58newstruct("singseries", " string Restrictions, string MilnorCode,
59 string MilnorNumber, string Corank, string Modality, string SpecialForm,
60 string NormalForm, string Series ");
61
62LIB "SingularityDBM.lib";
63arnold_classify_init();
64}
65
66///////////////////////////////////////////////////////////////////////////////
67proc arnoldClassify( poly fPoly )
68"USAGE:   arnoldClassify (f); f poly
69ASSUME:  The basering is local of characteristic 0 and f defines an
70         isolated singularity from Arnol'd's list of corank at most 2.
71COMPUTE: singularity class with respect to right equivalence and
72         invariants used in the process of classification
73RETURN:  Singularity class of f of type singclass containing
74         @* - name of singularity series as listed by arnoldListAllSeries(),
75         @* - name of singularity class,
76         @* - parameters k,r,s defining the singularity class, -1 if not used,
77         @* - modality, corank, Milnor number, determinacy,
78         @* - Tjurina number, -2 if not computed, -1 if infinite,
79         @* - Milnor code, -1 if not computed,
80         @* - normal form of the singularity series from Arnol'd's list,
81         @* - restrictions on parameters as string in SINGULAR syntax.
82EXAMPLE: example arnoldClassify; shows an example
83"
84{
85
86//* initialisation
87//* new datastructure singclass to save intrinsic information
88 singclass f;
89 f = init_newsingclass( f );
90
91//* Check the basering
92 if( check_basering() )
93 {
94  f.Class = "NoClass";
95 }
96
97//* Detect units
98 if(jet(fPoly,0) != 0 )
99   {
100   return( ERROR("The polynomial is a unit." ));
101 }
102
103//* Compute Basic Invariants: Corank, Determinacy and Milnornumber
104 ideal Jf = std(jacob( fPoly ));
105 f.Milnor = vdim( Jf );
106 if( f.Milnor < 0 )
107 { ERROR("Milnornumber of the singularity must be finite.")}
108 f.Determinacy = arnoldDeterminacy( Jf , f.Milnor);
109 f.Corank = arnoldCorank( fPoly );
110
111//* Check if Milnornumber is finite
112 if( f.Milnor < 0 ){
113  f.Class = "NoClass";
114  ERROR("Milnornumber of the singularity must be finite.")
115  return( f );
116 }
117
118//* Singularities with Milnornumber = 0 belong to A[0];
119 if( f.Milnor == 0 ){
120  f.Class = "A[0]";
121  f.Series = "A[k]";
122  f.k = 0;
123  f.r = -1;
124  f.s = -1;
125  f.Modality = 0;
126  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
127  return( f );
128 }
129
130//* Singularities with Corank <=1 belong to A[k];
131 if( f.Corank <= 1){
132  f.Class = "A["+string(f.Milnor)+"]";
133  f.Series = "A[k]";
134  f.k = f.Milnor;
135  f.r = -1;
136  f.s = -1;
137  f.Modality = 0;
138  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
139  return( f );
140 }
141
142//* Reduce f to f.Determinacy-jet
143  if(f.Determinacy >0 ){
144   fPoly = jet(fPoly, f.Determinacy);
145  }
146
147//* Classification of singularities of Corank 2
148 if( f.Corank == 2 ){
149   return( Classify_Corank2(f, fPoly));
150 }
151
152//* Classification of singularities of Corank 3
153 if( f.Corank == 3 ){
154  return( Classify_Corank3(f, fPoly));
155 }
156
157//* No classification for singularities of corank > 3
158 f.Class = "NoClass";
159 return( f );
160
161}
162example
163{ "EXAMPLE:"; echo=2;
164  ring r = 0,(x,y),ds;
165  int k = random(3,10);
166  poly g = x4 + x2*y^(2*k+1)+x*y^(3*k+1)+ y^(4*k +1);
167  arnoldClassify(g);
168  map phi=r,y-x^2,x+y;
169  phi(g);
170  arnoldClassify(phi(g));
171  ring C = (0,i), (x,y), ds;
172  minpoly = i2 + 1;
173  poly f =(x2+y2)^2+x5;
174  arnoldClassify(f);
175}
176
177///////////////////////////////////////////////////////////////////////////////
178static proc Classify_Corank2( singclass f, poly fPoly)
179{
180//* Classifies Singularities of Corank 2; Series D,J,E,W,X,Y,Z
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//* whether 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 red@br = char(basering), (x(1..f.Corank)), (c,ds); }
233  else{
234    number m = leadcoef(L[1][4][1]);
235    ring red@br = (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//* Diagram 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   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
414   return( f );
415  }
416  else{
417  //* Set an upper bound = r+s;
418   int bound = 4*f.k + (f.Milnor - 12*f.k +3);
419   weights, fPoly = Transform_Newton_Polygon_Y( f, fPoly, bound);
420   int b1 =
421   int((2*weights[1] + 2* f.k*weights[2]) div weights[2]  - 4*f.k);
422   int b2 = f.Milnor - 12*f.k +3 - b1;
423
424   //* Y-class
425   f.Series = "Y[k,r,s]";
426   f.r = max(b1,b2);
427   f.s =  min(b1,b2);
428   f.Class = "Y["+string(f.k)+","+string(f.r)+","+string(f.s)+"]";
429   f.Modality = 3*f.k - 2;
430   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
431   return( f );
432  }
433}
434
435///////////////////////////////////////////////////////////////////////////////
436static proc Transform_Newton_Polygon_Y( singclass f, poly fPoly, int bound )
437{
438//* Eliminates Monomials until the Newton Polygon of fPoly coincides
439//* with the Newton Polygon of the normalform
440
441//* Reduce fPoly to monomials which might get eliminated
442  def weights1 = qhweight(var(1)^2*var(2)^(2*f.k) + var(2)^bound);
443  intvec weights2 = 1,0;
444  poly fquasi = jet( jet(fPoly, 2*weights1[1]+2*f.k*weights1[2], weights1),2, weights2) ;
445
446//* Find minimal ("steepest") weights
447  def weights3 = Classify_Y_FindWeights( fquasi, f.k, weights1);
448
449//* if the weights are (k,1), no monomials to eliminate, return fPoly
450  if (weights3 == weights1 )
451  { return (ERROR("Parameters r and s must be greater 0."));}
452
453//* Compute quasihomogeneous jet w.r.t to weight
454  def d =  2*weights3[1]+2*f.k*weights3[2];
455  fquasi = jet(fPoly, d, weights3);
456
457//* Check if monomial of the form y^l is contained in fquasi
458  if ( Coeff (fquasi, var(2), var(2)^(d div weights3[2])) == 0 )
459  {
460   int counter = 1;
461
462   while ( counter < 10){
463    //* Find genereous transformation
464    int ran = random(-50,50);
465    map Phi = basering,x+ran*t*var(2)^((d div weights3[2] - 2)div 2 ),y;
466    if (Coeff (Phi(fquasi), var(2), var(2)^(d div weights3[2])) != 0 )
467    { counter = 11;}
468    counter = counter+1;
469   }
470  fPoly = Phi(fPoly);
471  }
472
473//* Compute the zero of multiplicity 2 if fquasi has one
474
475 poly factor = jet(fPoly,2*weights3[1]+2*f.k*weights3[2],weights3);
476 factor =
477 Classify_Y_TwoZero(factor);
478
479//* If fquasi has a zero with mult 2
480 if( factor == 0 ){ return( weights3, fPoly );}
481
482 poly inversefactor =number(1/leadcoef(factor))*(2*lead(factor)-factor);
483 map CoordChange = basering, inversefactor, var(2);
484 fPoly = CoordChange( fPoly );
485 fPoly = jet( fPoly, f.Determinacy);
486
487 fquasi =
488 jet( jet(fPoly, 2*weights3[1]+2*f.k*weights3[2], weights3), 2, weights2);
489 if( leadmonom(fquasi) != var(1)^2*var(2)^(2*f.k))
490 { return( weights3, fPoly ); }
491
492return (Transform_Newton_Polygon_Y( f, fPoly, bound ) );
493}
494
495/////////////////////////////////////////////////////////////////////////////
496static proc Classify_Y_FindWeights( poly f, int k, intvec weights1 )
497{
498//* Assume f is a polynomial with no polynomials lying in the Newton
499//* Diagram above the line defined by x^2y^2 and x^2y^(bound)
500//* Computes the weight of all monomials lying under the line and
501//* returns the smallest one
502
503//* Check if leading term of f is x^2y^2k;
504 poly firstlead = lead(f);
505
506 if( leadmonom(firstlead) != var(1)^2*var(2)^(2*k) )
507 { ERROR("Something went wrong");}
508
509//* Compute the the minimal weights
510 f = f - firstlead;
511 intvec weights2;
512 while( f != 0 ){
513  weights2 = qhweight( firstlead + lead( f ));
514  if (weights2[1] * weights1[2] < weights2[2] * weights1[1])
515  { weights1 = weights2;}
516  f = f - lead(f);
517 }
518 return( weights1 );
519}
520
521///////////////////////////////////////////////////////////////////////////////
522static proc Classify_Y_TwoZero( poly f )
523{
524//* Assume f = (ax + by^l)^2* x^2
525
526def factors = factorize ( f );
527
528for( int i = 1; i<= size(factors[2]); i++)
529{
530 if( factors[2][i] == 2 )
531 {
532   if ( factors[1][i] != 1 && factors[1][i] - lead(factors[1][i]) != 0)
533  { return( factors[1][i]);}
534 }
535}
536return( 0 );
537}
538
539///////////////////////////////////////////////////////////////////////////////
540static proc Classify_Corank3( singclass f, poly fPoly)
541{
542return( "Not implemented yet.")
543//* todo
544
545}
546
547
548
549///////////////////////////////////////////////////////////////////////////////
550static proc Classify_Corank2_MC_3 ( singclass f )
551{
552//* Classifies the singularities of corank 2 with non-zero 3-jet using
553//* the Milnor code.
554
555 intvec mc = f.MilnorCode;
556
557 if( mc[1] != 1 ){
558  f.Class = "NoClass";
559   return( f ); }
560
561//* Check type "D[k]"
562 if( mc[2] == 1 ){
563    f.Class = "D["+string(mc[3]+3)+"]";
564  f.Series = "D[k]";
565  f.k = mc[3]+3;
566  f.r = -1;
567  f.s = -1;
568  f.Modality = 0;
569  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
570  return( f );
571 }
572
573//* Check type "J[k,r]"
574 if(mc[3] > mc[2]&& mc[2]>1){
575  f.k = (mc[2]+1) div 2;
576  f.r = f.Milnor - 3*mc[2]-1;
577  f.s = -1;
578  f.Class = "J["+string(f.k)+","+string(f.r)+"]";
579  f.Series = "J[k,r]";
580  f.Modality = f.k-1;
581  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
582  return( f );
583 }
584
585 else{
586
587//* Check type "J[k,0]"
588  if( f.Milnor mod 6 == 4 ){
589           f.k = (f.Milnor + 2 ) div 6;
590   f.Class ="J[" + string(f.k) + "," + string(0) +"]";
591   f.Series = "J[k,0]";
592   f.r = -1;
593   f.s = -1;
594   f.Modality = f.k-1;
595   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
596   return( f );
597        }
598
599//* Check type "E[6k]"
600  if(f.Milnor mod 6 == 0 ){
601   f.k = f.Milnor div 6;
602   f.r = -1;
603   f.s = -1;
604   f.Class = "E[" + string(6*f.k)+ "]";
605   f.Series = "E[6k]";
606   f.Modality = f.k - 1;
607   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
608   return( f );
609  }
610
611//* Check type "E[6k+1]"
612  if( f.Milnor mod 6 == 1 ){
613   f.k = (f.Milnor - 1) div 6;
614   f.r = -1;
615   f.s = -1;
616   f.Class = "E[" + string(6*f.k+1) + "]";
617   f.Series = "E[6k+1]";
618   f.Modality = f.k -1;
619   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
620   return( f );
621  }
622
623//* Check type "E[6k+2]"
624  if( f.Milnor mod 6 == 2 ){
625   f.k = (f.Milnor - 2) div 6;
626   f.r = -1;
627   f.s = -1;
628   f.Class = "E[" + string(6*f.k+2) + "]";
629   f.Series = "E[6k+2]";
630   f.Modality = f.k - 1;
631   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
632   return( f );
633  }
634
635 }
636 f.Class = "NoClass";
637 return( f );
638}
639
640///////////////////////////////////////////////////////////////////////////////
641static proc Classify_Corank2_MC_5 ( singclass f , poly fPoly)
642{
643
644//* Classifies the singularity classes of the series W, Z and the singularity
645//* class Z[k,r,s] using the Milnor code. They are of corank 2, have
646//* zero 3-jet, non-zero 4-jet and the Milnor code is of length 5.
647
648 intvec mc = f.MilnorCode;
649 if( mc[1] != 1 || mc[2]!= 1){  f.Class = "NoClass"; return(f);}
650 if( mc[3] mod 2 == 0 )
651 {
652
653//* Check type "W#[k,2r]"
654  if( mc[3] == mc[5] && mc[3] < mc[4] ){
655   f.k = mc[3] div 2;
656   f.r = mc[4]-mc[3];
657   f.s = -1;
658   f.Class = "W#[" + string(f.k) + "," + string (2*f.r) +"]";
659   f.Series = "W#[k,2r]";
660   f.Modality = 3*f.k -1;
661   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
662   return(f);
663  }
664
665//* Check type "W[k,r]"
666  if( mc[3]==mc[4] && mc[3]<mc[5] ){
667   f.k = mc[3] div 2;
668   f.r = mc[5] - mc[3];
669   f.s = -1;
670   f.Class = "W[" +string(f.k) +"," + string(f.r) + "]";
671   f.Series = "W[k,r]";
672   f.Modality = 3*f.k - 1;
673   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
674   return(f);
675  }
676
677//* Check type "W#[k,2r-1]"
678  if(mc[5] < mc[3] && mc[3] < mc[4]
679  && f.Milnor mod 2 == 0
680  && 2*mc[4]+mc[5]+2> f.Milnor div 2){
681   f.k = mc[3] div 2;
682   f.r = (f.Milnor - 12*f.k-2) div 2;
683   f.s = -1;
684   f.Class = "W#[" +string(f.k) +"," +string(2*f.r-1) +"]";
685   f.Series = "W#[k,2r-1]";
686   f.Modality = 3*f.k -1;
687   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
688   return(f);
689  }
690 }
691
692//* Check type "X[k,0]"
693 if( f.Milnor mod 12 == 9 && mc[3]>=mc[5] && mc[5]<=3*mc[3]-2*mc[4] ){
694  f.k = (f.Milnor + 3) div 12;
695  f.r = 0;
696  f.s = -1;
697  f.Class = "X[" + string(f.k) +",0]";
698  if(f.k == 1){f.Series = "X[1,0]";}
699  else{f.Series = "X[k,0]";}
700  f.Modality = 3*f.k -2;
701  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
702  return(f);
703 }
704
705//* Check type "W[12k+1]"
706 if( f.Milnor mod 12 == 1 && mc[3]==mc[5] && mc[4]<mc[3] ){
707   f.k = (f.Milnor - 1) div 12;
708  f.r = -1;
709  f.s = -1;
710   f.Class = "W[" + string(12*f.k+1) +"]";
711  f.Series = "W[12k+1]";
712  f.Modality = 3*f.k -2;
713  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
714   return(f);
715 }
716
717//* Check type "W[12k+5]"
718 if( f.Milnor mod 12 == 5 && mc[3]==mc[5] && mc[4]<mc[3]){
719   f.k = (f.Milnor - 5) div 12;
720  f.r = -1;
721  f.s = -1;
722   f.Class = "W[" + string(12*f.k+5) +"]";
723  f.Series = "W[12k+5]";
724  f.Modality = 3*f.k -1;
725  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
726   return(f);
727 }
728
729//* Check type "W[12k+6]"
730 if( mc[3] >= mc[5] && f.Milnor mod 12 == 6  &&
731  (2*mc[4]+mc[5]+2) < (f.Milnor div 2) && mc[3]> mc[5]){
732   f.k = (f.Milnor-6) div 12;
733   f.r = -1;
734   f.s = -1;
735   f.Class = "W[" +string(12*f.k+6) +"]";
736   f.Series = "W[12k+6]";
737   f.Modality = 3*f.k -1;
738   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
739   return(f);
740 }
741
742//* Check type "W[k,0]"
743 if( f.Milnor mod 12 == 3  && mc[5]<= (3*mc[3] -2*mc[4])){
744  f.k = (f.Milnor - 3) div 12;
745  f.r = -1;
746  f.s = -1;
747  f.Class = "W["+ string(f.k) +",0]";
748  f.Series = "W[k,0]";
749  f.Modality = 3*f.k -1;
750  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
751  return(f);
752 }
753
754//* Check type "W[12k]"
755 if(f.Milnor mod 12 == 0  && mc[3]> mc[5] &&
756  2*mc[4]+ mc[5]+ 2 < (f.Milnor div 2)){
757  f.k = f.Milnor div 12;
758  f.r = -1;
759  f.s = -1;
760  f.Class = "W[" + string(12*f.k) +"]";
761  f.Series = "W[12k]";
762  f.Modality = 3*f.k -2;
763  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
764  return(f);
765 }
766
767//* Check type "X[k,r]"
768 if( (mc[4] < mc[3] && mc[3] < mc[5] ) ||
769 (mc[3]==mc[4] && mc[3] < mc[5] ) ){
770  f.k = (2*mc[3] + mc[4] + 3) div 6;
771  f.r = mc[5] - mc[3];
772  f.s = -1;
773  f.Class = "X[" + string(f.k) +"," + string(f.r)+ "]";
774  if(f.k == 1){f.Series = "X[1,r]";}
775  else{f.Series = "X[k,r]";}
776  f.Modality = 3*f.k -2;
777  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
778  return(f);
779 }
780
781 //* Need Tjurina number to classify Z[k,r,s]
782 //* Check type "Z[k,r,s]"
783 f.Tjurina = tjurina(fPoly);
784 if( mc[3]<mc[4] && mc[4] < mc[5] &&
785   f.Milnor > ( 3* (mc[3] + mc[4] +1)) &&
786   mc[4] mod 2 == 1 &&
787   f.Tjurina == f.Milnor - (mc[4] + mc[3]) div 2 ){
788
789   f.k = (mc[3]+1) div 2;
790   f.r = (mc[4] - mc[3]) div 2;
791   f.s = mc[5] - mc[4];
792   f.Class = "Z[" + string(f.k) +"," + string(f.r)+ ","+string(f.s)+"]";
793   if(f.k == 1){f.Series = "Z[1,r,s]";}
794   else{f.Series = "Z[k,r,s]";}
795   f.Modality = 3*f.k +f.r -2;
796   f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
797   return(f);
798 }
799
800 if( mc[3] mod 2 == 1){
801  return(f);
802 }
803 f.Class = "NoClass";
804 return(f);
805}
806
807///////////////////////////////////////////////////////////////////////////////
808static proc Classify_Z( singclass f)
809{
810//* If the input is a singularity of the series Z, this procedure determines
811//* the class and the parameters.
812
813 intvec mc = f.MilnorCode;
814 f.k = (mc[3]+1) div 2;
815
816//* Check type "Z[k,r]"
817 if (f.Milnor mod 6 == 3 && mc[5]<=mc[4]){
818  f.r = (mc[4] - mc[3]) div 2;
819  f.s = -1;
820  f.Class = "Z["+string(f.k)+","+string(f.r)+"]";
821  if(f.k == 1){ f.Series = "Z[1,r]";}
822  else {f.Series = "Z[k,r]";}
823  f.Modality = 3*f.k + f.r-2;
824  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
825  return(f);
826 }
827
828//* Check type "Z[k,12k+6r]"
829 if (f.Milnor mod 6 ==0 && mc[4]==mc[5] && mc[3]<mc[5]){
830  f.r = (f.Milnor - 12*f.k) div 6;
831  f.s = -1;
832     f.Class = "Z["+string(f.k)+","+string(12*f.k+6*f.r)+"]";
833  if(f.k == 1){ f.Series = "Z[1,6r+12]";}
834  else {f.Series = "Z[k,12k+6r]";}
835  f.Modality = 3*f.k + f.r - 2;
836  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
837  return(f);
838 }
839
840//* Check type "Z[k,12k+6r+1]"
841 if (f.Milnor mod 6 == 1 && mc[5] mod 2 ==1 ){
842  f.r = (f.Milnor - 12*f.k -1) div 6;
843  f.s = -1;
844     f.Class = "Z["+string(f.k)+","+string(12*f.k+6*f.r+1)+"]";
845  if(f.k == 1){ f.Series = "Z[1,6r+13]";}
846  else {f.Series = "Z[k,12k+6r+1]";}
847  f.Modality = 3*f.k +f.r - 2;
848  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
849  return(f);
850 }
851
852//* Check type "Z[k,12k+6r-1]"
853 if (f.Milnor mod 6 ==5 && mc[4] > mc[5]  ){
854  f.r = (f.Milnor - 12*f.k +1) div 6 ;
855  f.s = -1;
856     f.Class = "Z["+string(f.k)+","+string(12*f.k+6*f.r-1)+"]";
857  if(f.k == 1){ f.Series = "Z[1,6r+11]";}
858  else {f.Series = "Z[k,12k+6r-1]";}
859  f.Modality = 3*f.k + f.r -2;
860  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
861  return(f);
862 }
863
864 //* Check type "Z[k,r,s]"
865 if( mc[3]<mc[4] && mc[4]<mc[5] &&
866  f.Milnor>3*(mc[4]+mc[3]+1) && mc[4] mod 2 ==1){
867        f.r = (mc[4] - mc[3]) div 2;
868        f.s = mc[5] - mc[4];
869  f.Class = "Z["+string(f.k)+","+string(f.r)+","+string(f.s)+"]";
870  if(f.k == 1){ f.Series = "Z[1,r,s]";}
871  else {f.Series = "Z[k,r,s]";}
872  f.Modality = 3*f.k +f.r -2;
873  f.NormalForm, f.Restrictions = NormalFormAndRestrictionsDB(f.Series);
874  return(f);
875 }
876}
877
878///////////////////////////////////////////////////////////////////////////////
879static proc arnold_classify_init()
880{
881 // Check or create Singularity Database
882   string s;
883   link l="DBM:r Singularitylist";
884   s = read(l,"VERSION");
885   if (s == "" ) {
886     create_singularity_dbm();
887   }
888   close(l);
889   l="DBM:r Singularitylist";
890   s = read(l,"VERSION");
891}
892
893
894///////////////////////////////////////////////////////////////////////////////
895proc arnoldMorseSplit ( poly f, list # )
896"USAGE:   arnoldMorseSplit(f); f poly
897ASSUME:  base ring is local, f in maxideal(2) has isolated critical point at 0
898COMPUTE: result of Splitting Lemma applied to f
899RETURN:  polynomial g in maxideal(3) right equivalent to f
900EXAMPLE: example arnoldMorseSplit; shows an example
901"
902{
903//* save basering
904 def @br = basering;
905 int n = nvars(basering);
906
907//* Set Determinacy (Needed for Splitting Lemma) whether given in # or compute
908 int Determinacy;
909 if (size(#) == 0 ){
910  Determinacy = arnoldDeterminacy(std(jacob(f)));
911 }
912 else{
913  Determinacy = #[1];
914 }
915//* define ring_ext to change variable names in x(1), ..., x(n)
916//* requirement for procedure morse_arnold
917 ring ring_ext = char(basering), (x(1..n)), (c, ds);
918 map Phi = @br, maxideal(1);
919
920
921//* Apply Splitting Lemma
922 poly f = Morse_arnold( Phi( f ), Determinacy );
923
924//* Define inverse map to map f back into original ring
925 setring @br;
926 map Phi_inverse = ring_ext, maxideal(1);
927
928 return( Phi_inverse(f) );
929
930}
931example
932{ "EXAMPLE"; echo=2;
933   ring r=0,(x,y,z),ds;
934   export r;
935   poly f=(x2+3y-2z)^2+xyz-(x-y3+x2*z3)^3;
936   poly g=arnoldMorseSplit(f);
937   g;
938}
939
940
941///////////////////////////////////////////////////////////////////////////////
942static proc Morse_arnold( poly f , int Determinacy)
943{
944//* find g(x_1, ..., x_s) such that f ~ g + x_s+1^2 + ... + x_n^2
945//* s = Corank(f);
946
947//* initialisation
948 int n, i, j, k;
949 poly f2, imagef, Q, P;
950 ideal B1, B2;
951 map Phi, Phi2;
952
953//* save basering;
954 def @br = basering;
955 n = nvars(basering);
956
957//* Check if Determinacy is finite
958 if (Determinacy < 0 ){
959  ERROR("Determinacy must be finite.");
960 }
961 f = jet(f, Determinacy);
962
963//* Change order of variables sorted by frequency of appearance ->
964//* improves running time
965 f = ReorderVar(f);
966
967//* B1 defines the map which renumerates the variables such that
968//* g depends on the first s variables
969 B1 = maxideal(1);
970 i = 1;  //Variable x_i
971 j = 1;  //running index for B1, coordinate transformation x_i -> x_j
972
973//* While-loop over the variables,
974//* Write f = Q x_i^2 + P x_i + R,
975//* Either Q=P=0 and g depends on x_i or g is independent from x_i
976//*  and eliminate P
977 while( i <= n )
978 {
979  f2 = jet(f,2);
980  k = i+1; //* Variable for coordinate transformation
981
982  if((f2 - subst( f2, var(i), 0 )) == 0 ){
983   //* g depends on x_i -> send x_i via B1 to x_j
984   B1[i] = var(j);
985   j = j+1;
986  }
987  else{
988   //* Write f = Q x_i^2 + P x_i + R;
989      Q = Coeff( f2, var(i), var(i)^2);
990
991   //* Check if
992   if( Q == 0 && i == n ){ ERROR("Something went wrong"); }
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 polynomial 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:  integer 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 parameters 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<=r)\";";
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<=r)\";";
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
2018proc arnoldClassify_to_string(poly  fPoly)
2019"USAGE:   arnoldClassify_to_string (f); f poly
2020ASSUME:  The basering is local of characteristic 0 and f defines an
2021         isolated singularity from Arnol'd's list of corank at most 2.
2022COMPUTE: singularity class with respect to right equivalence and
2023         invariants used in the process of classification
2024RETURN:  string: separated by |:
2025         @* - name of singularity series as listed by arnoldListAllSeries(),
2026         @* - name of singularity class,
2027         @* - parameters k,r,s defining the singularity class, -1 if not used,
2028         @* - modality, corank, Milnor number, determinacy,
2029         @* - Tjurina number, -2 if not computed, -1 if infinite,
2030         @* - Milnor code, -1 if not computed,
2031         @* - normal form of the singularity series from Arnol'd's list,
2032         @* - restrictions on parameters as string in SINGULAR syntax.
2033EXAMPLE: example arnoldClassify_to_string; shows an example
2034"
2035{
2036  singclass f=arnoldClassify(fPoly);
2037  string s=f.Restrictions+"|"+
2038    f.NormalForm+"|"+
2039    string(f.MilnorCode)+"|"+
2040    string(f.Tjurina)+"|"+
2041    string(f.Determinacy)+"|"+
2042    string(f.Milnor)+"|"+
2043    string(f.Corank)+"|"+
2044    string(f.Modality)+"|"+
2045    string(f.r)+"|"+
2046    string(f.s)+"|"+
2047    f.Class+"|"+
2048    f.Series;
2049  return(s);
2050}
2051example
2052{ "EXAMPLE:"; echo=2;
2053  ring r = 0,(x,y),ds;
2054  int k = random(3,10);
2055  poly g = x4 + x2*y^(2*k+1)+x*y^(3*k+1)+ y^(4*k +1);
2056  arnoldClassify_to_string(g);
2057}
2058
Note: See TracBrowser for help on using the repository browser.