1 | /////////////////////////////////////////////////////////////////////////////// |
---|
2 | version="version arnoldclassify.lib 4.3.1.2 Nov_2022 "; // $Id$ |
---|
3 | category="Singularities"; |
---|
4 | info=" |
---|
5 | LIBRARY: arnoldClassify.lib Arnol'd Classifier of Singularities |
---|
6 | AUTHOR: Eva Maria Hemmerling, ehemmerl@rhrk.uni-kl.de |
---|
7 | |
---|
8 | OVERVIEW: |
---|
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 | |
---|
14 | REFERENCES: |
---|
15 | [AVG85] Arnold, Varchenko, Gusein-Zade: Singularities of Differentiable Maps. |
---|
16 | Vol. 1: The classification of critical points caustics and wave fronts. |
---|
17 | Birkh\"auser, Boston 1985 |
---|
18 | |
---|
19 | [Bac01] Corina Baciu: The classification of Hypersurface Singularities |
---|
20 | using the Milnor Code, Diplomarbeit, Universit\"at Kaiserslautern, 2001. |
---|
21 | |
---|
22 | [GP12] Greuel, Pfister: A SINGULAR Introduction to Commutative Algebra, |
---|
23 | Springer Science and Business Media, 2012 |
---|
24 | |
---|
25 | [Hem17] Eva Maria Hemmerling: Algorithmic Arnol'd Classification in SINGULAR, |
---|
26 | Master Thesis, TU Kaiserslautern, 2017. |
---|
27 | |
---|
28 | SEE ALSO: classify_lib, realclassify_lib |
---|
29 | |
---|
30 | KEYWORDS: singularities; Arnol'd; classification; Milnor code |
---|
31 | |
---|
32 | PROCEDURES: |
---|
33 | arnoldListAllSeries(); list of all singularity series up to corank 2 |
---|
34 | arnoldShowSeries(S); data defining a singularity series S |
---|
35 | arnoldNormalForm(S,#); normalform for a singularity series S |
---|
36 | arnoldClassify(f); singularity class of a power series f |
---|
37 | arnoldClassify_to_string(f); singularity class of a power series f |
---|
38 | arnoldCorank(f); corank of singularity defined by f |
---|
39 | arnoldDeterminacy(f,#); upper bound for the determinacy of f |
---|
40 | arnoldMilnorCode(f,#); Milnor Code of a singularity f |
---|
41 | arnoldMorseSplit(f,#); result of Splitting Lemma applied to f |
---|
42 | "; |
---|
43 | |
---|
44 | LIB "inout.lib"; |
---|
45 | LIB "elim.lib"; |
---|
46 | LIB "sing.lib"; |
---|
47 | LIB "findifs.lib"; |
---|
48 | |
---|
49 | /////////////////////////////////////////////////////////////////////////////// |
---|
50 | static proc mod_init() |
---|
51 | { |
---|
52 | //* define new datastruct singclass |
---|
53 | newstruct("singclass", "string Restrictions, string NormalForm, |
---|
54 | intvec MilnorCode, int Tjurina, int Determinacy, int Milnor, int Corank, |
---|
55 | int Modality, int s, int r, int k, string Class, string Series "); |
---|
56 | |
---|
57 | //* define new datastruct singclass |
---|
58 | newstruct("singseries", " string Restrictions, string MilnorCode, |
---|
59 | string MilnorNumber, string Corank, string Modality, string SpecialForm, |
---|
60 | string NormalForm, string Series "); |
---|
61 | |
---|
62 | LIB "SingularityDBM.lib"; |
---|
63 | arnold_classify_init(); |
---|
64 | } |
---|
65 | |
---|
66 | /////////////////////////////////////////////////////////////////////////////// |
---|
67 | proc arnoldClassify( poly fPoly ) |
---|
68 | "USAGE: arnoldClassify (f); f poly |
---|
69 | ASSUME: The basering is local of characteristic 0 and f defines an |
---|
70 | isolated singularity from Arnol'd's list of corank at most 2. |
---|
71 | COMPUTE: singularity class with respect to right equivalence and |
---|
72 | invariants used in the process of classification |
---|
73 | RETURN: 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. |
---|
82 | EXAMPLE: 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 | } |
---|
162 | example |
---|
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 | /////////////////////////////////////////////////////////////////////////////// |
---|
178 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
215 | static 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 |
---|
244 | if( 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 | |
---|
252 | if( b==1){return ( Classify_Y( f, fPoly ));} |
---|
253 | else{ return ( Classify_Z( f ) );} |
---|
254 | } |
---|
255 | |
---|
256 | /////////////////////////////////////////////////////////////////////////////// |
---|
257 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
282 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
299 | static 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 |
---|
305 | intvec weights = Classify_Z_Y_FindWeights( fPoly, f.k); |
---|
306 | |
---|
307 | //* if the weights are (k,1), no monomials to eliminate, return fPoly |
---|
308 | if (weights[1] == f.k && weights[2] ==1 ){ return (fPoly);} |
---|
309 | |
---|
310 | //* Compute quasihomogeneous part w.r.t to weights |
---|
311 | poly fquasi = jet( fPoly, 4*weights[1], weights); |
---|
312 | |
---|
313 | //* Check if fquasi contains monomial of the form y^l |
---|
314 | if ( 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 |
---|
330 | poly factor = Classify_Z_Y_FourthZero( fquasi ); |
---|
331 | |
---|
332 | //* If fquasi has a fourth zero |
---|
333 | if( factor == 0 ){ ERROR("Field extension needed.")} |
---|
334 | |
---|
335 | poly inversefactor = |
---|
336 | number ( 1 /leadcoef(factor)) * (2*lead(factor) - factor); |
---|
337 | map CoordChange = basering, inversefactor, var(2); |
---|
338 | fPoly = CoordChange( fPoly ); |
---|
339 | fPoly = jet( fPoly, f.Determinacy); |
---|
340 | |
---|
341 | return (Classify_Z_Y_EliminateMonomials( f, fPoly ) ); |
---|
342 | } |
---|
343 | |
---|
344 | ///////////////////////////////////////////////////////////////////////////// |
---|
345 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
373 | static 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 | |
---|
379 | poly f3 = diff(diff(diff( fPoly, var(1)), var(1)), var(1)); |
---|
380 | poly factor = gcd( f3, fPoly); |
---|
381 | |
---|
382 | //* Check if the factor^4 is equal input f |
---|
383 | if( factor^4 == fPoly){ return(factor); } |
---|
384 | else{ return(0);} |
---|
385 | } |
---|
386 | |
---|
387 | /////////////////////////////////////////////////////////////////////////////// |
---|
388 | static 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 |
---|
392 | intvec 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
436 | static 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 | |
---|
492 | return (Transform_Newton_Polygon_Y( f, fPoly, bound ) ); |
---|
493 | } |
---|
494 | |
---|
495 | ///////////////////////////////////////////////////////////////////////////// |
---|
496 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
522 | static proc Classify_Y_TwoZero( poly f ) |
---|
523 | { |
---|
524 | //* Assume f = (ax + by^l)^2* x^2 |
---|
525 | |
---|
526 | def factors = factorize ( f ); |
---|
527 | |
---|
528 | for( 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 | } |
---|
536 | return( 0 ); |
---|
537 | } |
---|
538 | |
---|
539 | /////////////////////////////////////////////////////////////////////////////// |
---|
540 | static proc Classify_Corank3( singclass f, poly fPoly) |
---|
541 | { |
---|
542 | return( "Not implemented yet.") |
---|
543 | //* todo |
---|
544 | |
---|
545 | } |
---|
546 | |
---|
547 | |
---|
548 | |
---|
549 | /////////////////////////////////////////////////////////////////////////////// |
---|
550 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
641 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
808 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
879 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
895 | proc arnoldMorseSplit ( poly f, list # ) |
---|
896 | "USAGE: arnoldMorseSplit(f); f poly |
---|
897 | ASSUME: base ring is local, f in maxideal(2) has isolated critical point at 0 |
---|
898 | COMPUTE: result of Splitting Lemma applied to f |
---|
899 | RETURN: polynomial g in maxideal(3) right equivalent to f |
---|
900 | EXAMPLE: 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 | } |
---|
931 | example |
---|
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 | /////////////////////////////////////////////////////////////////////////////// |
---|
942 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1030 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1053 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1088 | static proc Hcode (intvec a) |
---|
1089 | "USAGE: Hcode(a); a intvec |
---|
1090 | RETURN: intvec consisting of the numbers of successive repetitions of |
---|
1091 | entries in a |
---|
1092 | EXAMPLE: 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 | } |
---|
1115 | example |
---|
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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1122 | proc arnoldMilnorCode (poly f, list #) |
---|
1123 | "USAGE: arnoldMilnorCode(f[,e]); f poly, e int |
---|
1124 | ASSUME: basering is local, f has isolated critical point at 0 |
---|
1125 | COMPUTE: 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]. |
---|
1128 | RETURN: Milnor code of f as intvec where e=1 by default |
---|
1129 | EXAMPLE: 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 | } |
---|
1138 | example |
---|
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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1148 | proc arnoldDeterminacy( I, list # ) |
---|
1149 | "USAGE: arnoldDeterminacy( I[, m]); I poly or ideal, m int. |
---|
1150 | ASSUME: 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 |
---|
1152 | COMPUTE: determinacy bound k for f w.r.t. right equivalence |
---|
1153 | RETURN: integer k s.th. f is right-k-determined, -1 for infinity |
---|
1154 | NOTE: uses [Cor. A.9.7,GP12] |
---|
1155 | EXAMPLE: 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 | } |
---|
1193 | examples |
---|
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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1204 | proc arnoldCorank(poly f) |
---|
1205 | "USAGE: arnoldCorank(f); f poly |
---|
1206 | ASSUME: basering is local, f in maxideal(2) has isolated critical point at 0 |
---|
1207 | RETURN: corank of the Hessian matrix of f |
---|
1208 | EXAMPLE: 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 | } |
---|
1215 | example |
---|
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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1223 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1242 | static 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 |
---|
1246 | RETURN: 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1263 | proc arnoldShowSeries( string typ ) |
---|
1264 | "USAGE: arnoldShowSeries( S ); S string |
---|
1265 | ASSUME: S is the name of a singularity series listed by arnoldListAllSeries(). |
---|
1266 | RETURN: 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. |
---|
1273 | EXAMPLE: 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); |
---|
1289 | if(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 | } |
---|
1296 | example |
---|
1297 | { "EXAMPLE:"; echo=2; |
---|
1298 | arnoldShowSeries("Z[k,12k+6r]"); |
---|
1299 | } |
---|
1300 | |
---|
1301 | |
---|
1302 | /////////////////////////////////////////////////////////////////////////////// |
---|
1303 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1319 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1335 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1351 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1367 | proc arnoldNormalForm( typ, list #) |
---|
1368 | "USAGE: arnoldNormalForm( S [, l]), S string or singclass, l list |
---|
1369 | ASSUME: 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. |
---|
1375 | RETURN: 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. |
---|
1377 | EXAMPLE: 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 | } |
---|
1485 | example |
---|
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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1503 | proc arnoldListAllSeries() |
---|
1504 | "USAGE: arnoldListAllSeries(); |
---|
1505 | RETRURN: list of names of singularity series listed by Arnol'd up to corank 2 |
---|
1506 | EXAMPLE: example arnoldListAllSeries; shows an example" |
---|
1507 | { |
---|
1508 | list 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 | |
---|
1536 | return(l); |
---|
1537 | } |
---|
1538 | example |
---|
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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1549 | static 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 | |
---|
1568 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
1580 | static proc dbm_getnext (link l) |
---|
1581 | { |
---|
1582 | string s=""; |
---|
1583 | s=read(l); |
---|
1584 | if( s != "" ) { s,"=",read(l,s); } |
---|
1585 | } |
---|
1586 | |
---|
1587 | /////////////////////////////////////////////////////////////////////////////// |
---|
1588 | static 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 | /////////////////////////////////////////////////////////////////////////////// |
---|
2003 | static 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 | |
---|
2018 | proc arnoldClassify_to_string(poly fPoly) |
---|
2019 | "USAGE: arnoldClassify_to_string (f); f poly |
---|
2020 | ASSUME: The basering is local of characteristic 0 and f defines an |
---|
2021 | isolated singularity from Arnol'd's list of corank at most 2. |
---|
2022 | COMPUTE: singularity class with respect to right equivalence and |
---|
2023 | invariants used in the process of classification |
---|
2024 | RETURN: 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. |
---|
2033 | EXAMPLE: 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 | } |
---|
2051 | example |
---|
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 | |
---|