source: git/Singular/LIB/equising.lib @ 3753f2

fieker-DuValspielwiese
Last change on this file since 3753f2 was 3753f2, checked in by Hans Schoenemann <hannes@…>, 4 years ago
fix: reset equising::createMyRing_new
  • Property mode set to 100644
File size: 53.0 KB
Line 
1///////////////////////////////////////////////////////////////////////
2version="version equising.lib 4.1.2.0 Feb_2019 "; // $Id$
3category="Singularities";
4info="
5LIBRARY:  equising.lib  Equisingularity Stratum of a Family of Plane Curves
6AUTHOR:   Christoph Lossen, lossen@mathematik.uni-kl.de
7          Andrea Mindnich, mindnich@mathematik.uni-kl.de
8
9PROCEDURES:
10 tau_es(f);             codim of mu-const stratum in semi-universal def. base
11 esIdeal(f);            (Wahl's) equisingularity ideal of f
12 esStratum(F[,m,L]);    equisingularity stratum of a family F
13 isEquising(F[,m,L]);   tests if a given deformation is equisingular
14
15 control_Matrix(M);     computes list of blowing-up data
16";
17
18LIB "hnoether.lib";
19LIB "poly.lib";
20LIB "elim.lib";
21LIB "deform.lib";
22LIB "sing.lib";
23
24////////////////////////////////////////////////////////////////////////////////
25//
26//  The following (static) procedures are used by esComputation
27//
28////////////////////////////////////////////////////////////////////////////////
29// COMPUTES  a weight vector. x and y get weight 1 and all other
30//           variables get weight 0.
31static proc xyVector()
32{
33  intvec iv ;
34  iv[nvars(basering)]=0 ;
35  iv[rvar(x)] =1;
36  iv[rvar(y)] =1;
37  return (iv);
38}
39
40////////////////////////////////////////////////////////////////////////////////
41// exchanges the variables x and y in the polynomial f
42static proc swapXY(poly f)
43{
44  def r_base = basering;
45  ideal MI = maxideal(1);
46  MI[rvar(x)]=y;
47  MI[rvar(y)]=x;
48  map phi = r_base, MI;
49  f=phi(f);
50  return (f);
51}
52
53////////////////////////////////////////////////////////////////////////////////
54// computes m-jet w.r.t. the variables x,y (other variables weighted 0
55static proc m_Jet(poly F,int m);
56{
57  intvec w=xyVector();
58  poly Fd=jet(F,m,w);
59  return(Fd);
60}
61
62
63////////////////////////////////////////////////////////////////////////////////
64// computes the 4 control matrices (input is multsequence(L))
65proc control_Matrix(list M);
66"USAGE:   control_Matrix(L); L list
67ASSUME:  L is the output of multsequence(hnexpansion(f)).
68RETURN:  list M of 4 intmat's:
69@format
70  M[1] contains the multiplicities at the respective infinitely near points
71       p[i,j] (i=step of blowup+1, j=branch) -- if branches j=k,...,k+m pass
72       through the same p[i,j] then the multiplicity is stored in M[1][k,j],
73       while M[1][k+1]=...=M[1][k+m]=0.
74  M[2] contains the number of branches meeting at p[i,j] (again, the information
75       is stored according to the above rule)
76  M[3] contains the information about the splitting of M[1][i,j] with respect to
77       different tangents of branches at p[i,j] (information is stored only for
78       minimal j>=k corresponding to a new tangent direction).
79       The entries are the sum of multiplicities of all branches with the
80       respective tangent.
81  M[4] contains the maximal sum of higher multiplicities for a branch passing
82       through p[i,j] ( = degree Bound for blowing up)
83@end format
84NOTE:    the branches are ordered in such a way that only consecutive branches
85         can meet at an infinitely near point. @*
86         the final rows of the matrices M[1],...,M[3] is (1,1,1,...,1), and
87         correspond to infinitely near points such that the strict transforms
88         of the branches are smooth and intersect the exceptional divisor
89         transversally.
90SEE ALSO: multsequence
91EXAMPLE: example control_Matrix; shows an example
92"
93{
94  int i,j,k,dummy;
95
96  dummy=0;
97  for (j=1;j<=ncols(M[2]);j++)
98  {
99    dummy=dummy+M[1][nrows(M[1])-1,j]-M[1][nrows(M[1]),j];
100  }
101  intmat S[nrows(M[1])+dummy][ncols(M[1])];
102  intmat T[nrows(M[1])+dummy][ncols(M[1])];
103  intmat U[nrows(M[1])+dummy][ncols(M[1])];
104  intmat maxDeg[nrows(M[1])+dummy][ncols(M[1])];
105
106  for (i=1;i<=nrows(M[2]);i++)
107  {
108    dummy=1;
109    for (j=1;j<=ncols(M[2]);j++)
110    {
111      for (k=dummy;k<dummy+M[2][i,j];k++)
112      {
113        T[i,dummy]=T[i,dummy]+1;
114        S[i,dummy]=S[i,dummy]+M[1][i,k];
115        if (i>1)
116        {
117          U[i-1,dummy]=U[i-1,dummy]+M[1][i-1,k];
118        }
119      }
120      dummy=k;
121    }
122  }
123
124  // adding an extra row (in some cases needed to control ES-Stratum
125  // computation)
126  for (i=nrows(M[1]);i<=nrows(S);i++)
127  {
128    for (j=1;j<=ncols(M[2]);j++)
129    {
130      S[i,j]=1;
131      T[i,j]=1;
132      U[i,j]=1;
133    }
134  }
135
136  // Computing the degree Bounds to be stored in M[4]:
137  for (i=1;i<=nrows(S);i++)
138  {
139    dummy=1;
140    for (j=1;j<=ncols(S);j++)
141    {
142      for (k=dummy;k<dummy+T[i,j];k++)
143      {
144        maxDeg[i,k]=S[i,dummy];  // multiplicity at i-th blowup
145      }
146      dummy=k;
147    }
148  }
149  // adding up multiplicities
150  for (i=nrows(S);i>=2;i--)
151  {
152    for (j=1;j<=ncols(S);j++)
153    {
154      maxDeg[i-1,j]=maxDeg[i-1,j]+maxDeg[i,j];
155    }
156  }
157
158  list L=S,T,U,maxDeg;
159  return(L);
160}
161
162
163////////////////////////////////////////////////////////////////////////////////
164//  matrix of higher tangent directions:
165//  returns list: 1) tangent directions
166//                2) swapping information (x <--> y)
167static proc inf_Tangents(list L,int s); // L aus hnexpansion,
168{
169  int nv=nvars(basering);
170  matrix M;
171  matrix B[s][size(L)];
172  intvec V;
173  intmat Mult=multsequence(L)[1];
174
175  int i,j,k,counter,e;
176  for (k=1;k<=size(L);k++)
177  {
178    V[k]=L[k][3];  // switch: 0 --> tangent 2nd parameter
179                   //         1 --> tangent 1st parameter
180    e=0;
181    M=L[k][1];
182    counter=1;
183    B[counter,k]=M[1,1];
184
185    for (i=1;i<=nrows(M);i++)
186    {
187      for (j=2;j<=ncols(M);j++)
188      {
189        counter=counter+1;
190        if (M[i,j]==var(nv-1))
191        {
192          if (i<>nrows(M))
193          {
194            B[counter,k]=M[i,j];
195            j=ncols(M)+1; // goto new row of HNmatrix...
196            if (counter<>s)
197            {
198              if (counter+1<=nrows(Mult))
199              {
200                e=Mult[counter-1,k]-Mult[counter,k]-Mult[counter+1,k];
201              }
202              else
203              {
204                e=Mult[counter-1,k]-Mult[counter,k]-1;
205              }
206            }
207          }
208          else
209          {
210            B[counter,k]=0;
211            j=ncols(M)+1; // goto new row of HNmatrix...
212          }
213        }
214        else
215        {
216          if (e<=0)
217          {
218            B[counter,k]=M[i,j];
219          }
220          else  // point is still proximate to an earlier point
221          {
222            B[counter,k]=y; // marking proximity (without swap....)
223            if (counter+1<=nrows(Mult))
224            {
225              e=e-Mult[counter+1,k];
226            }
227            else
228            {
229              e=e-1;
230            }
231          }
232        }
233
234        if (counter==s) // given number of points determined
235        {
236            j=ncols(M)+1;
237            i=nrows(M)+1;
238            // leave procedure
239        }
240      }
241    }
242  }
243  L=B,V;
244  return(L);
245}
246
247////////////////////////////////////////////////////////////////////////////////
248// compute "good" upper bound for needed number of help variables
249//
250static proc Determine_no_b(intmat U,matrix B)
251// U is assumed to be 3rd output of control_Matrix
252// B is assumed to be 1st output of inf_Tangents
253{
254  int nv=nvars(basering);
255  int i,j,counter;
256  for (j=1;j<=ncols(U);j++)
257  {
258    for (i=1;i<=nrows(U);i++)
259    {
260      if (U[i,j]>1)
261      {
262        if (B[i,j]<>var(nv-1) and B[i,j]<>var(nv))
263        {
264          counter=counter+1;
265        }
266      }
267
268    }
269  }
270  counter=counter+ncols(U);
271  return(counter);
272}
273
274////////////////////////////////////////////////////////////////////////////////
275// compute number of infinitely near free points corresponding to non-zero
276// entries in control_Matrix[1] (except first row)
277//
278static proc no_freePoints(intmat Mult,matrix B)
279// Mult is assumed to be 1st output of control_Matrix
280// U is assumed to be 3rd output of control_Matrix
281// B is assumed to be 1st output of inf_Tangents
282{
283  int i,j,k,counter;
284  for (j=1;j<=ncols(Mult);j++)
285  {
286    for (i=2;i<=nrows(Mult);i++)
287    {
288      if (Mult[i,j]>=1)
289      {
290        if (B[i-1,j]<>x and B[i-1,j]<>y)
291        {
292          counter=counter+1;
293        }
294      }
295    }
296  }
297  return(counter);
298}
299
300
301///////////////////////////////////////////////////////////////////////////////
302// COMPUTES string(minpoly) and substitutes the parameter by newParName
303static proc makeMinPolyString (string newParName)
304{
305  int i;
306  string parName = parstr(basering);
307  int parNameSize = size(parName);
308
309  string oldMinPolyStr = string (minpoly);
310  int minPolySize = size(oldMinPolyStr);
311
312  string newMinPolyStr = "";
313
314  for (i=1;i <= minPolySize; i++)
315  {
316    if (oldMinPolyStr[i,parNameSize] == parName)
317    {
318      newMinPolyStr = newMinPolyStr + newParName;
319      i = i + parNameSize-1;
320    }
321    else
322    {
323      newMinPolyStr = newMinPolyStr + oldMinPolyStr[i];
324    }
325  }
326
327  return(newMinPolyStr);
328}
329
330///////////////////////////////////////////////////////////////////////////////
331//
332// DEFINES: A new basering, "myRing",
333//          with new names for the parameters and variables.
334//          The new names for the parameters are a(1..k),
335//          and t(1..s),x,y for the variables
336//          The ring ordering is ordStr.
337// NOTE:    This proc uses 'execute'.
338static proc createMyRing_new(poly p_F, string ordStr,
339                                string minPolyStr, int no_b)
340{
341  def r_old = basering;
342
343  int chara = char(basering);
344  string charaStr;
345  int i;
346  string helpStr;
347  int nDefParams = nvars(r_old)-2;
348
349  ideal qIdeal = ideal(basering);
350
351  if ((npars(basering)==0) and (minPolyStr==""))
352  {
353    helpStr = "ring myRing1 ="
354              + string(chara)+ ", (t(1..nDefParams), x, y),("+ ordStr +");";
355    execute(helpStr);
356  }
357  else
358  {
359    charaStr = charstr(basering);
360    if ((charaStr == string(chara) + "," + parstr(basering)) or (minPolyStr<>""))
361    {
362      if (minPolyStr<>"")
363      {
364        helpStr = "ring myRing1 =
365                 (" + string(chara) + ",a),
366                 (t(1..nDefParams), x, y),(" + ordStr + ");";
367        execute(helpStr);
368
369        execute (minPolyStr);
370      }
371      else // no minpoly given
372      {
373        helpStr = "ring myRing1 =
374                  (" + string(chara) + ",a(1..npars(basering)) ),
375                  (t(1..nDefParams), x, y),(" + ordStr + ");";
376        execute(helpStr);
377      }
378    }
379    else
380    {
381      // ground field is of type (p^k,a)....
382      i = find (charaStr,",");
383      helpStr = "ring myRing1 = (" + charaStr[1,i] + "a),
384              (t(1..nDefParams), x, y),(" + ordStr + ");";
385      execute (helpStr);
386    }
387  }
388
389  ideal mIdeal = maxideal(1);
390  ideal qIdeal = fetch(r_old, qIdeal);
391  poly p_F = fetch(r_old, p_F);
392  export p_F,mIdeal;
393
394  // Extension by no_b auxiliary variables
395  if (no_b>0)
396  {
397    if (npars(basering) == 0)
398    {
399      ordStr = "(dp("+string(no_b)+"),"+ordStr+")";
400      helpStr = "ring myRing ="
401                + string(chara)+ ", (b(1..no_b), t(1..nDefParams), x, y),"
402                + ordStr +";";
403      execute(helpStr);
404    }
405    else
406    {
407      charaStr = charstr(basering);
408      if (charaStr == string(chara) + "," + parstr(basering))
409      {
410        if (minpoly !=0)
411        {
412          ordStr = "(dp(" + string(no_b) + ")," + ordStr + ")";
413          minPolyStr = makeMinPolyString("a");
414          helpStr = "ring myRing =
415                   (" + string(chara) + ",a),
416                   (b(1..no_b), t(1..nDefParams), x, y)," + ordStr + ";";
417          execute(helpStr);
418
419          helpStr = "minpoly =" + minPolyStr + ";";
420          execute (helpStr);
421        }
422        else // no minpoly given
423        {
424          ordStr = "(dp(" + string(no_b) + ")," + ordStr + ")";
425          helpStr = "ring myRing =
426                    (" + string(chara) + ",a(1..npars(basering)) ),
427                    (b(1..no_b), t(1..nDefParams), x, y)," + ordStr + ";";
428          execute(helpStr);
429        }
430      }
431      else
432      {
433        i = find (charaStr,",");
434        ordStr = "(dp(" + string(no_b) + ")," + ordStr + ")";
435        helpStr = "ring myRing =
436                (" + charaStr[1,i] + "a),
437                (b(1..no_b), t(1..nDefParams), x, y)," + ordStr + ";";
438        execute (helpStr);
439      }
440    }
441    ideal qIdeal = imap(myRing1, qIdeal);
442
443    if(size(qIdeal) != 0)
444    {
445      def r_base = basering;
446      setring r_base;
447      kill myRing;
448      qring myRing = std(qIdeal);
449    }
450
451    poly p_F = imap(myRing1, p_F);
452    ideal mIdeal = imap(myRing1, mIdeal);
453    export p_F,mIdeal;
454    kill myRing1;
455  }
456  else
457  {
458    if(size(qIdeal) != 0)
459    {
460      def r_base = basering;
461      setring r_base;
462      kill myRing1;
463      qring myRing = std(qIdeal);
464      poly p_F = imap(myRing1, p_F);
465      ideal mIdeal = imap(myRing1, mIdeal);
466      export p_F,mIdeal;
467    }
468    else
469    {
470      def myRing=myRing1;
471    }
472    kill myRing1;
473  }
474
475  setring r_old;
476  return(myRing);
477}
478
479////////////////////////////////////////////////////////////////////////////////
480// returns list of coef, leadmonomial
481//
482static proc determine_coef (poly Fm)
483{
484  def r_base = basering; // is assumed to be the result of createMyRing
485
486  int chara = char(basering);
487  string charaStr;
488  int i;
489  string minPolyStr = "";
490  string helpStr = "";
491
492  if (npars(basering) == 0)
493  {
494    ring myRing1 = create_ring("("+string(chara)+")", "(y,x)", "ds");
495  }
496  else
497  {
498    charaStr = charstr(basering);
499    if (charaStr == string(chara) + "," + parstr(basering))
500    {
501      if (minpoly !=0)
502      {
503        minPolyStr = makeMinPolyString("a");
504        ring myRing1 = create_ring("(" + string(chara) + ",a)", "(y,x)", "ds");
505
506        helpStr = "minpoly =" + minPolyStr + ";";
507        execute (helpStr);
508      }
509      else // no minpoly given
510      {
511        list l5; 
512        for (int zz = 1; zz <= npars(basering); zz++)
513        {
514         l5[size(l5)+1] = "a("+string(zz)+")";
515        }
516        ring myRing1 = create_ring("("+string(chara)+","+string(l5)+")", "(y,x)", "ds");
517      }
518    }
519    else
520    {
521      i = find (charaStr,",");
522
523      ring myRing1 = create_ring("(" + charaStr[1,i] + ",a)", "(y,x)", "ds");
524    }
525  }
526  poly f=imap(r_base,Fm);
527  poly g=leadmonom(f);
528  setring r_base;
529  poly g=imap(myRing1,g);
530  kill myRing1;
531  def M=coef(Fm,xy);
532
533  for (i=1; i<=ncols(M); i++)
534  {
535    if (M[1,i]==g)
536    {
537      poly h=M[2,i];  // determine coefficient of leading monomial (in K[t])
538      i=ncols(M)+1;
539    }
540  }
541  return(list(h,g));
542}
543
544///////////////////////////////////////////////////////////////////////////////
545// RETURNS: 1, if p_f = 0 or char(basering) divides the order of p_f
546//             or p_f is not squarefree.
547//          0, otherwise
548static proc checkPoly (poly p_f)
549{
550  int i_print = printlevel - voice + 3;
551  int i_ord;
552
553  if (p_f == 0)
554  {
555    print("Input is a 'deformation'  of the zero polynomial!");
556    return(1);
557  }
558
559  i_ord = mindeg1(p_f);
560
561  if (number(i_ord) == 0)
562  {
563    print("Characteristic of coefficient field "
564            +"divides order of zero-fiber !");
565    return(1);
566  }
567
568  if (squarefree(p_f) != p_f)
569  {
570    print("Original polynomial (= zero-fiber) is not reduced!");
571    return(1);
572  }
573
574  return(0);
575}
576
577////////////////////////////////////////////////////////////////////////////////
578static proc make_ring_small(ideal J)
579// returns varstr for new ring, the map and the number of vars
580{
581  attrib(J,"isSB",1);
582  int counter=0;
583  ideal newmap;
584  string newvar="";
585  for (int i=1; i<=nvars(basering); i++)
586  {
587    if (reduce(var(i),J)<>0)
588    {
589      newmap[i]=var(i);
590
591      if (newvar=="")
592      {
593        newvar=newvar+string(var(i));
594        counter=counter+1;
595      }
596      else
597      {
598        newvar=newvar+","+string(var(i));
599        counter=counter+1;
600      }
601    }
602    else
603    {
604      newmap[i]=0;
605    }
606  }
607  list L=newvar,newmap,counter;
608  attrib(J,"isSB",0);
609  return(L);
610}
611
612///////////////////////////////////////////////////////////////////////////////
613//  The following procedure is called by esStratum (typ=0), resp. by
614//  isEquising (typ=1)
615///////////////////////////////////////////////////////////////////////////////
616
617static proc esComputation (int typ, poly p_F, list #)
618{
619  intvec ov=option(get);  // store options set at beginning
620  option(redSB);
621  // Initialize variables
622  int branch=1;
623  int blowup=1;
624  int auxVar=1;
625  int nVars;
626
627  intvec upper_bound, upper_bound_old, fertig, soll;
628  list blowup_string;
629  int i_print= printlevel-voice+2;
630
631  int no_b, number_of_branches, swapped;
632  int i,j,k,m, counter, dummy;
633  string helpStr = "";
634  string ordStr = "";
635  string MinPolyStr = "";
636
637  if (nvars(basering)<=2)
638  {
639    print("family is trivial (no deformation parameters)!");
640    if (typ==1) //isEquising
641    {
642      option(set,ov);
643      return(1);
644    }
645    else
646    {
647      option(set,ov);
648      return(list(ideal(0),0));
649    }
650  }
651
652  if (size(#)>0)
653  {
654    if (typeof(#[1])=="int")
655    {
656      def artin_bd=#[1];  // compute modulo maxideal(artin_bd)
657      if (artin_bd <= 1)
658      {
659        print("Do you really want to compute over Basering/maxideal("
660              +string(artin_bd)+") ?");
661        print("No computation performed !");
662        if (typ==1) //isEquising
663        {
664          option(set,ov);
665          return(1);
666        }
667        else
668        {
669          option(set,ov);
670          return(list(ideal(0),int(1)));
671        }
672      }
673      if (size(#)>1)
674      {
675        if (typeof(#[2])=="list")
676        {
677          def @L=#[2];  // is assumed to be the Hamburger-Noether matrix
678        }
679      }
680    }
681    else
682    {
683      if (typeof(#)=="list")
684      {
685        def @L=#;  // is assumed to be the Hamburger-Noether matrix
686      }
687    }
688  }
689  int ring_is_changed;
690  def old_ring=basering;
691  if(defined(@L)<=0)
692  {
693    // define a new ring without deformation-parameters and change to it:
694    string str;
695    string minpolyStr = string(minpoly);
696    ring HNERing = create_ring(ringlist(basering)[1], "(x,y)", "ls", "no_minpoly");
697    if (minpolyStr!="0")
698    {str = "minpoly ="+ minpolyStr+";";execute(str);}
699    ring_is_changed=1;
700    // Basering changed to HNERing (variables x,y, with ls ordering)
701
702    k=nvars(old_ring);
703    matrix Map_Phi[1][k];
704    Map_Phi[1,k-1]=x;
705    Map_Phi[1,k]=y;
706    map phi=old_ring,Map_Phi;
707    poly f=phi(p_F);
708
709    // Heuristics: if x,y are transversal parameters then computation of HNE
710    // can be much faster when exchanging variables...!
711    if (2*size(coeffs(f,x))<size(coeffs(f,y)))
712    {
713      swapped=1;
714      f=swapXY(f);
715    }
716
717    int error=checkPoly(f);
718    if (error)
719    {
720      setring old_ring;
721      if (typ==1) //isEquising
722      {
723        print("Return value (=0) has no meaning!");
724        option(set,ov);
725        return(0);
726      }
727      else
728      {
729        option(set,ov);
730        return(list( ideal(0),error));
731      }
732    }
733
734    dbprint(i_print,"// ");
735    dbprint(i_print,"// Compute HN expansion");
736    dbprint(i_print,"// ---------------------");
737    i=printlevel;
738    printlevel=printlevel-5;
739    list LLL=hnexpansion(f);
740
741    if (size(LLL)==0) { // empty list returned by hnexpansion
742      setring old_ring;
743      print(i_print,"Unable to compute HN expansion !");
744      if (typ==1) //isEquising
745      {
746        print("Return value (=0) has no meaning!");
747        option(set,ov);
748        return(0);
749      }
750      else
751      {
752        option(set,ov);
753        return(list(ideal(0),int(1)));
754      }
755      option(set,ov);
756      return(0);
757    }
758    else
759    {
760      if (typeof(LLL[1])=="ring") {
761        def HNering = LLL[1];
762        setring HNering;
763        def @L=stripHNE(hne);
764      }
765      else {
766        def @L=stripHNE(LLL);
767      }
768    }
769    printlevel=i;
770    dbprint(i_print,"// finished");
771    dbprint(i_print,"// ");
772  }
773  def HNEring=basering;
774  list M=multsequence(@L);
775  M=control_Matrix(M);     // this returns the 4 control matrices
776  def maxDeg=M[4];
777
778  list L1=inf_Tangents(@L,nrows(M[1]));
779  matrix B=L1[1];
780  intvec V=L1[2];
781  kill L1;
782
783  // if we have computed the HNE for f after swapping x and y, we have
784  // to reinterprete the (swap) matrix V:
785  if (swapped==1)
786  {
787    for (i=1;i<=size(V);i++) { V[i]=V[i]-1; } // turns 0 into -1, 1 into 0
788  }
789
790  // Determine maximal number of needed auxiliary parameters (free tangents):
791  no_b=Determine_no_b(M[3],B);
792
793  // test whether HNexpansion needed field extension....
794  string minPolyStr = "";
795  if (minpoly !=0)
796  {
797    minPolyStr = makeMinPolyString("a");
798    minPolyStr = "minpoly =" + minPolyStr + ";";
799  }
800
801  setring old_ring;
802
803  def myRing=createMyRing_new(p_F,"dp",minPolyStr,no_b);
804  setring myRing;  // comes with mIdeal
805  map hole=HNEring,mIdeal;
806  // basering has changed to myRing, in particular, the "old"
807  // variable names, e.g., A,B,C,z,y are replaced by t(1),t(2),t(3),x,y
808
809  ideal bNodes;
810
811  // Initialize some variables:
812  map phi;
813  poly G, F_save;
814  poly b_dummy;
815  ideal J,Jnew,final_Map;
816  number_of_branches=ncols(M[1]);
817  for (i=1;i<=number_of_branches;i++)
818  {
819    poly F(i);
820    ideal bl_Map(i);
821  }
822  upper_bound[number_of_branches]=0;
823  upper_bound[1]=number_of_branches;
824  upper_bound_old=upper_bound;
825  fertig[number_of_branches]=0;
826  for (i=1;i<=number_of_branches;i++){ soll[i]=1; }
827
828  // Hole:  B = matrix of blowup points
829  if (ring_is_changed==0) { matrix B=hole(B); }
830  else                    { matrix B=imap(HNEring,B); }
831  m=M[1][blowup,branch];    // multiplicity at 0
832
833  // now, we start by checking equimultiplicity along trivial section
834  poly Fm=m_Jet(p_F,m-1);
835
836  matrix coef_Mat = coef(Fm,xy);
837  Jnew=coef_Mat[2,1..ncols(coef_Mat)];
838  J=J,Jnew;
839
840  if (defined(artin_bd)) // the artin_bd-th power of the maxideal of
841                         // deformation parameters can be cutted off
842  {
843    J=jet(J,artin_bd-1);
844  }
845
846  J=interred(J);
847  if (defined(artin_bd)) { J=jet(J,artin_bd-1); }
848
849// J=std(J);
850
851  if (typ==1) // isEquising
852  {
853    if(ideal(nselect(J,1..no_b))<>0)
854    {
855      setring old_ring;
856      option(set,ov);
857      return(0);
858    }
859  }
860
861  F(1)=p_F;
862
863  // and reduce the remaining terms in F(1):
864  bl_Map(1)=maxideal(1);
865
866  attrib(J,"isSB",1);
867  bl_Map(1)=reduce(bl_Map(1),J);
868  attrib(J,"isSB",0);
869
870  phi=myRing,bl_Map(1);
871  F(1)=phi(F(1));
872
873  // simplify F(1)
874  attrib(J,"isSB",1);
875  F(1)=reduce(F(1),J);
876  attrib(J,"isSB",0);
877
878  // now we compute the m-jet:
879  Fm=m_Jet(F(1),m);
880
881  G=1;
882  counter=branch;
883  k=upper_bound[branch];
884
885  F_save=F(1);  // is truncated differently in the following loop
886
887  while(counter<=k)
888  {
889    F(counter)=m_Jet(F_save,maxDeg[blowup,counter]);
890    if (V[counter]==0) // 2nd ring variable is tangent to this branch
891    {
892      G=G*(y-(b(auxVar)+B[blowup,counter])*x)^(M[3][blowup,counter]);
893    }
894    else // 1st ring variable is tangent to this branch
895    {
896      G=G*(x-(b(auxVar)+B[blowup,counter])*y)^(M[3][blowup,counter]);
897      F(counter)=swapXY(F(counter));
898    }
899    bl_Map(counter)=maxideal(1);
900    bl_Map(counter)[nvars(basering)]=xy+(b(auxVar)+B[blowup,counter])*x;
901
902    bNodes[counter]=b(auxVar);
903
904    auxVar=auxVar+1;
905    upper_bound[counter]=counter+M[2][blowup+1,counter]-1;
906    counter=counter+M[2][blowup+1,counter];
907
908  }
909
910  list LeadDataFm=determine_coef(Fm);
911  def LeadDataG=coef(G,xy);
912
913  for (i=1; i<=ncols(LeadDataG); i++)
914  {
915    if (LeadDataG[1,i]==LeadDataFm[2])
916    {
917      poly LeadG = LeadDataG[2,i];  // determine the coefficient of G
918      i=ncols(LeadDataG)+1;
919    }
920  }
921
922  G=LeadDataFm[1]*G-LeadG*Fm;  // leading terms in y should cancel...
923
924  coef_Mat = coef(G,xy);
925  Jnew=coef_Mat[2,1..ncols(coef_Mat)];
926
927  // simplification of Jnew
928
929  if (defined(artin_bd)) // the artin_bd-th power of the maxideal of
930                         // deformation parameters can be cutted off
931  {
932    Jnew=jet(Jnew,artin_bd-1);
933  }
934  Jnew=interred(Jnew);
935  if (defined(artin_bd)) { Jnew=jet(Jnew,artin_bd-1); }
936  J=J,Jnew;
937
938  if (typ==1) // isEquising
939  {
940    if(ideal(nselect(J,1..no_b))<>0)
941    {
942      setring old_ring;
943      option(set,ov);
944      return(0);
945    }
946  }
947
948  while (fertig<>soll and blowup<nrows(M[3]))
949  {
950    upper_bound_old=upper_bound;
951    dbprint(i_print,"// Blowup Step "+string(blowup)+" completed");
952    blowup=blowup+1;
953
954    for (branch=1;branch<=number_of_branches;branch=branch+1)
955    {
956      Jnew=0;
957
958      // First we check if the branch still has to be considered:
959      if (branch==upper_bound_old[branch] and fertig[branch]<>1)
960      {
961        if (M[3][blowup-1,branch]==1 and
962               ((B[blowup,branch]<>x and B[blowup,branch]<>y)
963            or (blowup==nrows(M[3])) ))
964        {
965          fertig[branch]=1;
966          dbprint(i_print,"// 1 branch finished");
967        }
968      }
969
970      if (branch<=upper_bound_old[branch] and fertig[branch]<>1)
971      {
972        for (i=branch;i>=1;i--)
973        {
974          if (M[1][blowup-1,i]<>0)
975          {
976            m=M[1][blowup-1,i]; // multiplicity before blowup
977            i=0;
978          }
979        }
980
981        // we blow up the branch and take the strict transform:
982        attrib(J,"isSB",1);
983        bl_Map(branch)=reduce(bl_Map(branch),J);
984        attrib(J,"isSB",0);
985
986        phi=myRing,bl_Map(branch);
987        F(branch)=phi(F(branch))/x^m;
988
989        // simplify F
990        attrib(Jnew,"isSB",1);
991
992        F(branch)=reduce(F(branch),Jnew);
993        attrib(Jnew,"isSB",0);
994
995        m=M[1][blowup,branch]; // multiplicity after blowup
996        Fm=m_Jet(F(branch),m); // homogeneous part of lowest degree
997
998
999        // we check for Fm=F[k]*...*F[k+s] where
1000        //
1001        //    F[j]=(y-b'(j)*x)^m(j), respectively F[j]=(-b'(j)*y+x)^m(j)
1002        //
1003        // according to the entries m(j)= M[3][blowup,j] and
1004        //                          b'(j) mod m_A = B[blowup,j]
1005        // computed from the HNE of the special fibre of the family:
1006        G=1;
1007        counter=branch;
1008        k=upper_bound[branch];
1009
1010        F_save=F(branch);
1011
1012        while(counter<=k)
1013        {
1014          F(counter)=m_Jet(F_save,maxDeg[blowup,counter]);
1015
1016          if (B[blowup,counter]<>x and B[blowup,counter]<>y)
1017          {
1018            G=G*(y-(b(auxVar)+B[blowup,counter])*x)^(M[3][blowup,counter]);
1019            bl_Map(counter)=maxideal(1);
1020            bl_Map(counter)[nvars(basering)]=
1021                                        xy+(b(auxVar)+B[blowup,counter])*x;
1022            bNodes[counter]=b(auxVar);
1023            auxVar=auxVar+1;
1024          }
1025          else
1026          {
1027            if (B[blowup,counter]==x)
1028            {
1029              G=G*x^(M[3][blowup,counter]);  // branch has tangent x !!
1030              F(counter)=swapXY(F(counter)); // will turn x to y for blow up
1031              bl_Map(counter)=maxideal(1);
1032              bl_Map(counter)[nvars(basering)]=xy;
1033            }
1034            else
1035            {
1036              G=G*y^(M[3][blowup,counter]); // tangent has to be y
1037              bl_Map(counter)=maxideal(1);
1038              bl_Map(counter)[nvars(basering)]=xy;
1039            }
1040            bNodes[counter]=0;
1041          }
1042          upper_bound[counter]=counter+M[2][blowup+1,counter]-1;
1043          counter=counter+M[2][blowup+1,counter];
1044        }
1045        G=determine_coef(Fm)[1]*G-Fm;  // leading terms in y should cancel
1046        coef_Mat = coef(G,xy);
1047        Jnew=coef_Mat[2,1..ncols(coef_Mat)];
1048        if (defined(artin_bd)) // the artin_bd-th power of the maxideal of
1049                              // deformation parameters can be cutted off
1050        {
1051          Jnew=jet(Jnew,artin_bd-1);
1052        }
1053
1054        // simplification of J
1055        Jnew=interred(Jnew);
1056
1057        J=J,Jnew;
1058        if (typ==1) // isEquising
1059        {
1060          if (defined(artin_bd)) { J=jet(Jnew,artin_bd-1); }
1061          if(ideal(nselect(J,1..no_b))<>0)
1062          {
1063            setring old_ring;
1064            option(set,ov);
1065            return(0);
1066          }
1067        }
1068      }
1069    }
1070    if (number_of_branches>=2)
1071    {
1072      J=interred(J);
1073      if (typ==1) // isEquising
1074      {
1075        if (defined(artin_bd)) { J=jet(Jnew,artin_bd-1); }
1076        if(ideal(nselect(J,1..no_b))<>0)
1077        {
1078          setring old_ring;
1079          option(set,ov);
1080          return(0);
1081        }
1082      }
1083    }
1084  }
1085
1086  // Computation for all equimultiple sections being trivial (I^s(f))
1087  ideal Jtriv=J;
1088  for (i=1;i<=no_b; i++)
1089  {
1090    if (reduce(b(i),std(bNodes))!=0){
1091      Jtriv=subst(Jtriv,b(i),0);
1092    }
1093  }
1094  Jtriv=std(Jtriv);
1095
1096
1097
1098  dbprint(i_print,"// ");
1099  dbprint(i_print,"// Elimination starts:");
1100  dbprint(i_print,"// -------------------");
1101
1102  poly gg;
1103  int b_left=no_b;
1104
1105  for (i=1;i<=no_b; i++)
1106  {
1107    attrib(J,"isSB",1);
1108    gg=reduce(b(i),J);
1109    if (gg==0)
1110    {
1111      b_left = b_left-1;  // another b(i) has to be 0
1112    }
1113    J = subst(J, b(i), gg);
1114    attrib(J,"isSB",0);
1115  }
1116  J=simplify(J,10);
1117  if (typ==1) // isEquising
1118  {
1119    if (defined(artin_bd)) { J=jet(Jnew,artin_bd-1); }
1120    if(ideal(nselect(J,1..no_b))<>0)
1121    {
1122      setring old_ring;
1123      option(set,ov);
1124      return(0);
1125    }
1126  }
1127
1128  //new CL 11/06:  check in which equations b(k) appears and remove those b(k)
1129  //               which appear in exactly one of the equations (by removing this
1130  //               equation)
1131  dbprint(i_print,"// ");
1132  dbprint(i_print,"// Remove superfluous equations:");
1133  dbprint(i_print,"// -----------------------------");
1134  int Z,App_in;
1135  ideal J_Tmp;
1136  int ncJ=ncols(J);
1137
1138  intmat Mdet[ncJ][1];
1139  for (Z=1;Z<=ncJ;Z++){ Mdet[Z,1]=Z; }
1140
1141  for (i=1;i<=no_b; i++)
1142  {
1143    ideal b_appears_in(i);            // Eintraege sind spaeter 1 oder 0
1144    intmat b_app_in(i)[1][ncJ];       // Eintraege sind spaeter 1 oder 0
1145    b_appears_in(i)[ncJ]=0;
1146    J_Tmp = matrix(J)-subst(J,b(i),0);
1147    for (Z=1; Z<=ncJ; Z++) {
1148      if (J_Tmp[Z]<>0) {      // b(i) appear in J_Tmp[Z]
1149        b_appears_in(i)[Z]=1;
1150        b_app_in(i)[1,Z]=1;
1151      }
1152    }
1153    if (size(b_appears_in(i))==1) { //b(i) appears only in one J_Tmp[Z]
1154      App_in = (b_app_in(i)*Mdet)[1,1];  // determines Z
1155      J[App_in]=0;
1156      b_appears_in(i)[App_in]=0;
1157      b_app_in(i)[1,App_in]=0;
1158    }
1159  }
1160
1161  for (i=1;i<=no_b; i++)
1162  {
1163    if (size(b_appears_in(i))==1) { //b(i) appears only in one J_Tmp[Z]
1164      App_in = (b_app_in(i)*Mdet)[1,1];  // determines Z
1165      J[App_in]=0;
1166      b_appears_in(i)[App_in]=0;
1167      b_app_in(i)[1,Z]=1;
1168      i=0;
1169    }
1170  }
1171
1172  Jtriv = nselect(Jtriv,1..no_b);
1173  ideal J_no_b = nselect(J,1..no_b);
1174  if (size(J) > size(J_no_b))
1175  {
1176    dbprint(i_print,"// std computation started");
1177    // some b(i) didn't appear in linear conditions and have to be eliminated
1178    if (defined(artin_bd))
1179    {
1180      // first we make the ring smaller (removing variables, which are
1181      // forced to 0 by J
1182      list LL=make_ring_small(J);
1183      ideal Shortmap=LL[2];
1184      minPolyStr = "";
1185      if (minpoly !=0)
1186      {
1187        minPolyStr = "minpoly = "+string(minpoly);
1188      }
1189      ordStr = "dp(" + string(b_left) + "),dp";
1190      ideal qId = ideal(basering);
1191
1192      ring Shortring = create_ring(ringlist(basering)[1], "("+ LL[1] +")", "("+ ordStr  +")", "no_minpoly");
1193      execute(minPolyStr);
1194      // ring has changed to "Shortring"
1195
1196      ideal MM=maxideal(artin_bd);
1197      MM=subst(MM,x,0);
1198      MM=subst(MM,y,0);
1199      MM=simplify(MM,2);
1200      dbprint(i_print-1,"// maxideal("+string(artin_bd)+") has "
1201                         +string(size(MM))+" elements");
1202      dbprint(i_print-1,"//");
1203
1204      // we change to the qring mod m^artin_bd
1205      // first, we have to check if we were in a qring when starting
1206      ideal qId = imap(myRing, qId);
1207      if (size(qId) == 0)
1208      {
1209         attrib(MM,"isSB",1);
1210         qring QQ=MM;
1211      }
1212      else
1213      {
1214         qId=qId,MM;
1215         qring QQ = std(qId);
1216      }
1217
1218      ideal Shortmap=imap(myRing,Shortmap);
1219      map phiphi=myRing,Shortmap;
1220
1221      ideal J=phiphi(J);
1222      option(redSB);
1223      J=std(J);
1224      J=nselect(J,1..no_b);
1225
1226      setring myRing;
1227      // back to "myRing"
1228
1229      J=nselect(J,1..no_b);
1230      Jnew=imap(QQ,J);
1231
1232      J=J,Jnew;
1233      J=interred(J);
1234      if (defined(artin_bd)){ J=jet(J,artin_bd-1); }
1235    }
1236    else
1237    {
1238      J=std(J);
1239      J=nselect(J,1..no_b);
1240      if (defined(artin_bd)){ J=jet(J,artin_bd-1); }
1241    }
1242  }
1243
1244  dbprint(i_print,"// finished");
1245  dbprint(i_print,"// ");
1246
1247  minPolyStr = "";option(set,ov);
1248  if (minpoly !=0)
1249  {
1250   minPolyStr = "minpoly = "+string(minpoly);
1251  }
1252
1253  kill HNEring;
1254
1255  if (typ==1) // isEquising
1256  {
1257    if (defined(artin_bd)) { J=jet(Jnew,artin_bd-1); }
1258    if(J<>0)
1259    {
1260      setring old_ring;
1261      option(set,ov);
1262      return(0);
1263    }
1264    else
1265    {
1266      setring old_ring;
1267      option(set,ov);
1268      return(1);
1269    }
1270  }
1271
1272  setring old_ring;
1273  // we are back in the original ring
1274
1275  if (npars(myRing)<>0)
1276  {
1277    ideal qIdeal = ideal(basering);
1278    ring ESSring = create_ring("("+ string(char(basering))+ "," + parstr(myRing) +")", "("+ varstr(basering)+")", "("+ ordstr(basering) +")");
1279    execute(minPolyStr);
1280    // basering has changed to ESSring
1281
1282    ideal qIdeal = fetch(old_ring, qIdeal);
1283    if(qIdeal != 0)
1284    {
1285      def r_base = basering;
1286      kill ESSring;
1287      qring ESSring = std(qIdeal);
1288    }
1289    kill qIdeal;
1290
1291    ideal SSS;
1292    for (int ii=1;ii<=nvars(basering);ii++)
1293    {
1294      SSS[ii+no_b]=var(ii);
1295    }
1296    map phi=myRing,SSS;   // b(i) variables are mapped to zero
1297
1298    ideal ES=phi(J);
1299    ideal ES_all_triv=phi(Jtriv);
1300    kill phi;
1301
1302    if (defined(p_F)<=0)
1303    {
1304      poly p_F=fetch(old_ring,p_F);
1305      export(p_F);
1306    }
1307    export(ES);
1308    export(ES_all_triv);
1309    setring old_ring;
1310    dbprint(i_print+2,"
1311// 'esStratum' created a list M of a ring and an integer.
1312// To access the ideal defining the equisingularity stratum, type:
1313        def ESSring = M[1]; setring ESSring;  ES; ");
1314
1315    option(set,ov);
1316    return(list(ESSring,0));
1317  }
1318  else
1319  {
1320    // no new ring definition necessary
1321    ideal SSS;
1322    for (int ii=1;ii<=nvars(basering);ii++)
1323    {
1324      SSS[ii+no_b]=var(ii);
1325    }
1326    map phi=myRing,SSS;  // b(i) variables are mapped to zero
1327
1328    ideal ES=phi(J);
1329    ideal ES_all_triv=phi(Jtriv);
1330    kill phi;
1331
1332    setring old_ring;
1333    dbprint(i_print,"// output of 'esStratum' is a list consisting of:
1334//    _[1][1] = ideal defining the equisingularity stratum
1335//    _[1][2] = ideal defining the part of the equisingularity stratum
1336//              where all equimultiple sections are trivial
1337//    _[2] = 0");
1338
1339    option(set,ov);
1340    return(list(list(ES,ES_all_triv),0));
1341  }
1342
1343}
1344
1345////////////////////////////////////////////////////////////////////////////////
1346
1347proc tau_es (poly f,list #)
1348"USAGE:   tau_es(f); f poly
1349ASSUME:  f is a reduced bivariate polynomial, the basering has precisely
1350         two variables, is local and no qring.
1351RETURN:  int, the codimension of the mu-const stratum in the semi-universal
1352         deformation base.
1353NOTE:    printlevel>=1 displays additional information.
1354         When called with any additional parameter, the computation of the
1355         Milnor number is avoided (no check for NND).
1356SEE ALSO: esIdeal, tjurina, invariants
1357EXAMPLE: example tau_es; shows an example.
1358"
1359{
1360  int i,j,k,s;
1361  int slope_x, slope_y, upper;
1362  int i_print = printlevel - voice + 3;
1363  string MinPolyStr;
1364
1365  // some checks first
1366  if ( nvars(basering)<>2 )
1367  {
1368    print("// basering has not the correct number (two) of variables !");
1369    print("// computation stopped");
1370    return(0);
1371  }
1372  if ( mult(std(1+var(1)+var(2))) <> 0)
1373  {
1374    print("// basering is not local !");
1375    print("// computation stopped");
1376    return(0);
1377  }
1378
1379  if (mult(std(f))<=1)
1380  {
1381    // f is rigid
1382    return(0);
1383  }
1384
1385  if ( deg(squarefree(f))!=deg(f) )
1386  {
1387    print("// input polynomial was not reduced");
1388    print("// try    squarefree(f);   first");
1389    return(0);
1390  }
1391
1392  def old_ring=basering;
1393  ring @myRing = create_ring(ringlist(basering)[1], "("+varstr(basering)+")", "ds", "no_minpoly");
1394  poly f=imap(old_ring,f);
1395
1396  ideal Jacobi_Id = jacob(f);
1397
1398  // check for A_k singularity
1399  // ----------------------------------------
1400  if (mult(std(f))==2)
1401  {
1402    dbprint(i_print-1,"// ");
1403    dbprint(i_print-1,"// polynomial defined A_k singularity");
1404    dbprint(i_print-1,"// ");
1405    return( vdim(std(Jacobi_Id)) );
1406  }
1407
1408  // check for D_k singularity
1409  // ----------------------------------------
1410  if (mult(std(f))==3 and size(factorize(jet(f,3))[1])>=3)
1411  {
1412    dbprint(i_print,"// ");
1413    dbprint(i_print,"// polynomial defined D_k singularity");
1414    dbprint(i_print,"// ");
1415    ideal ES_Id = f, jacob(f);
1416    return( vdim(std(Jacobi_Id)));
1417  }
1418
1419
1420  if (size(#)==0)
1421  {
1422    // check if Newton polygon non-degenerate
1423    // ----------------------------------------
1424    Jacobi_Id=std(Jacobi_Id);
1425    int mu = vdim(Jacobi_Id);
1426    poly f_tilde=f+var(1)^mu+var(2)^mu;  //to obtain convenient Newton-polygon
1427
1428    list NP=newtonpoly(f_tilde);
1429    dbprint(i_print-1,"// Newton polygon:");
1430    dbprint(i_print-1,NP);
1431    dbprint(i_print-1,"");
1432
1433    if(is_NND(f,mu,NP))          // f is Newton non-degenerate
1434    {
1435      upper=NP[1][2];
1436      ideal ES_Id= x^k*y^upper;
1437      dbprint(i_print-1,"polynomial is Newton non-degenerate");
1438      dbprint(i_print-1,"");
1439      k=0;
1440      for (i=1;i<=size(NP)-1;i++)
1441      {
1442        slope_x=NP[i+1][1]-NP[i][1];
1443        slope_y=NP[i][2]-NP[i+1][2];
1444        for (k=NP[i][1]+1; k<=NP[i+1][1]; k++)
1445        {
1446          while ( slope_x*upper + slope_y*k >=
1447                  slope_x*NP[i][2] + slope_y*NP[i][1])
1448          {
1449            upper=upper-1;
1450          }
1451          upper=upper+1;
1452          ES_Id=ES_Id, x^k*y^upper;
1453        }
1454      }
1455      ES_Id=std(ES_Id);
1456      dbprint(i_print-2,"ideal of monomials above Newton bd. is generated by:");
1457      dbprint(i_print-2,ES_Id);
1458      ideal ESfix_Id = ES_Id, f, maxideal(1)*jacob(f);
1459      ES_Id = ES_Id, Jacobi_Id;
1460      ES_Id = std(ES_Id);
1461      dbprint(i_print-1,"// ");
1462      dbprint(i_print-1,"// Equisingularity ideal is computed!");
1463      dbprint(i_print-1,"");
1464      return(vdim(ES_Id));
1465    }
1466    else
1467    {
1468      dbprint(i_print-1,"polynomial is Newton degenerate !");
1469      dbprint(i_print-1,"");
1470    }
1471  }
1472
1473  // for Newton degenerate polynomials, we compute the HN expansion, and
1474  // count the number of free points .....
1475
1476  dbprint(i_print-1,"// ");
1477  dbprint(i_print-1,"// Compute HN expansion");
1478  dbprint(i_print-1,"// ---------------------");
1479  i=printlevel;
1480  printlevel=printlevel-5;
1481  if (2*size(coeffs(f,x))<size(coeffs(f,y)))
1482  {
1483    f=swapXY(f);
1484  }
1485  list LLL=hnexpansion(f);
1486  if (size(LLL)==0) { // empty list returned by hnexpansion
1487    setring old_ring;
1488    ERROR("Unable to compute HN expansion !");
1489  }
1490  else
1491  {
1492    if (typeof(LLL[1])=="ring") {
1493      def HNering = LLL[1];
1494      setring HNering;
1495      def @L=hne;
1496    }
1497    else {
1498      def @L=LLL;
1499    }
1500  }
1501  def HNEring=basering;
1502
1503  printlevel=i;
1504  dbprint(i_print-1,"// finished");
1505  dbprint(i_print-1,"// ");
1506
1507  list M=multsequence(@L);
1508  M=control_Matrix(M);     // this returns the 4 control matrices
1509  intmat Mult=M[1];
1510
1511  list L1=inf_Tangents(@L,nrows(M[1]));
1512  matrix B=L1[1];
1513
1514  // determine sum_i m_i(m_i+1)/2 (over inf. near points)
1515  int conditions=0;
1516  for (i=1;i<=nrows(Mult);i++)
1517  {
1518    for (j=1;j<=ncols(Mult);j++)
1519    {
1520      conditions=conditions+(Mult[i,j]*(Mult[i,j]+1) div 2);
1521    }
1522  }
1523  int freePts=no_freePoints(M[1],B);
1524  int taues=conditions-freePts-2;
1525
1526  setring old_ring;
1527  return(taues);
1528}
1529example
1530{
1531   "EXAMPLE:"; echo=2;
1532   ring r=32003,(x,y),ds;
1533   poly f=(x4-y4)^2-x10;
1534   tau_es(f);
1535}
1536
1537
1538////////////////////////////////////////////////////////////////////////////////
1539
1540proc esIdeal (poly f,list #)
1541"USAGE:   esIdeal(f[,any]]); f poly
1542ASSUME:  f is a reduced bivariate polynomial, the basering has precisely
1543         two variables, is local and no qring, and the characteristic of
1544         the ground field does not divide mult(f).
1545RETURN:  if called with only one parameter: list of two ideals,
1546@format
1547          _[1]:  equisingularity ideal of f (in sense of Wahl),
1548          _[2]:  ideal of equisingularity with fixed position of the
1549                 singularity;
1550@end format
1551         if called with more than one parameter: list of three ideals,
1552@format
1553          _[1]:  equisingularity ideal of f (in sense of Wahl)
1554          _[2]:  ideal of equisingularity with fixed position of the
1555                 singularity;
1556          _[3]:  ideal of all g such that the deformation defined by f+eg
1557                 (e^2=0) is isomorphic to an equisingular deformation
1558                 of V(f) with all equimultiple sections being trivial.
1559@end format
1560NOTE:    if some of the above condition is not satisfied then return
1561         value is list(0,0).
1562SEE ALSO: tau_es, esStratum
1563KEYWORDS: equisingularity ideal
1564EXAMPLE: example esIdeal; shows examples.
1565"
1566{
1567
1568  int typ;
1569  if (size(#)>0) { typ=1; }   // I^s is also computed
1570  int i,k,s;
1571  int slope_x, slope_y, upper;
1572  int i_print = printlevel - voice + 3;
1573  string MinPolyStr;
1574
1575  // some checks first
1576  if ( nvars(basering)<>2 )
1577  {
1578    print("// basering has not the correct number (two) of variables !");
1579    print("// computation stopped");
1580    return(list(0,0));
1581  }
1582  if ( mult(std(1+var(1)+var(2))) <> 0)
1583  {
1584    print("// basering is not local !");
1585    print("// computation stopped");
1586    return(list(0,0));
1587  }
1588
1589  if (mult(std(f))<=1)
1590  {
1591    // f is rigid
1592    if (typ==0)
1593    {
1594      return(list(ideal(1),ideal(1)));
1595    }
1596    else
1597    {
1598      return(list(ideal(1),ideal(1),ideal(1)));
1599    }
1600  }
1601
1602  if ( deg(squarefree(f))!=deg(f) )
1603  {
1604    print("// input polynomial was not squarefree");
1605    print("// try    squarefree(f);   first");
1606    return(list(0,0));
1607  }
1608
1609  if (char(basering)<>0)
1610  {
1611    if (mult(std(f)) mod char(basering)==0)
1612    {
1613      print("// characteristic of ground field divides "
1614            + "multiplicity of polynomial !");
1615      print("// computation stopped");
1616      return(list(0,0));
1617    }
1618  }
1619
1620  // check for A_k singularity
1621  // ----------------------------------------
1622  if (mult(std(f))==2)
1623  {
1624    dbprint(i_print,"// ");
1625    dbprint(i_print,"// polynomial defined A_k singularity");
1626    dbprint(i_print,"// ");
1627    ideal ES_Id = f, jacob(f);
1628    ES_Id = interred(ES_Id);
1629    ideal ESfix_Id = f, maxideal(1)*jacob(f);
1630    ESfix_Id= interred(ESfix_Id);
1631    if (typ==0) // only for computation of I^es and I^es_fix
1632    {
1633      return( list(ES_Id,ESfix_Id) );
1634    }
1635    else
1636    {
1637      return( list(ES_Id,ESfix_Id,ES_Id) );
1638    }
1639  }
1640
1641  // check for D_k singularity
1642  // ----------------------------------------
1643  if (mult(std(f))==3 and size(factorize(jet(f,3))[1])>=3)
1644  {
1645    dbprint(i_print,"// ");
1646    dbprint(i_print,"// polynomial defined D_k singularity");
1647    dbprint(i_print,"// ");
1648    ideal ES_Id = f, jacob(f);
1649    ES_Id = interred(ES_Id);
1650    ideal ESfix_Id = f, maxideal(1)*jacob(f);
1651    ESfix_Id= interred(ESfix_Id);
1652    if (typ==0) // only for computation of I^es and I^es_fix
1653    {
1654      return( list(ES_Id,ESfix_Id) );
1655    }
1656    else
1657    {
1658      return( list(ES_Id,ESfix_Id,ES_Id) );
1659    }
1660  }
1661
1662  // check if Newton polygon non-degenerate
1663  // ----------------------------------------
1664  int mu = milnor(f);
1665  poly f_tilde=f+var(1)^mu+var(2)^mu;  //to obtain a convenient Newton-polygon
1666
1667  list NP=newtonpoly(f_tilde);
1668  dbprint(i_print-1,"// Newton polygon:");
1669  dbprint(i_print-1,NP);
1670  dbprint(i_print-1,"");
1671
1672  if(is_NND(f,mu,NP))          // f is Newton non-degenerate
1673  {
1674    upper=NP[1][2];
1675    ideal ES_Id= x^k*y^upper;
1676    dbprint(i_print,"polynomial is Newton non-degenerate");
1677    dbprint(i_print,"");
1678    k=0;
1679    for (i=1;i<=size(NP)-1;i++)
1680    {
1681      slope_x=NP[i+1][1]-NP[i][1];
1682      slope_y=NP[i][2]-NP[i+1][2];
1683      for (k=NP[i][1]+1; k<=NP[i+1][1]; k++)
1684      {
1685        while ( slope_x*upper + slope_y*k >=
1686                slope_x*NP[i][2] + slope_y*NP[i][1])
1687        {
1688          upper=upper-1;
1689        }
1690        upper=upper+1;
1691        ES_Id=ES_Id, x^k*y^upper;
1692      }
1693    }
1694    ES_Id=std(ES_Id);
1695    dbprint(i_print-1,"ideal of monomials above Newton bd. is generated by:");
1696    dbprint(i_print-1,ES_Id);
1697    ideal ESfix_Id = ES_Id, f, maxideal(1)*jacob(f);
1698    ES_Id = ES_Id, f, jacob(f);
1699    dbprint(i_print,"// ");
1700    dbprint(i_print,"// equisingularity ideal is computed!");
1701    if (typ==0)
1702    {
1703      return(list(ES_Id,ESfix_Id));
1704    }
1705    else
1706    {
1707      return(list(ES_Id,ESfix_Id,ES_Id));
1708    }
1709  }
1710  else
1711  {
1712    dbprint(i_print,"polynomial is Newton degenerate !");
1713    dbprint(i_print,"");
1714  }
1715
1716  def old_ring=basering;
1717
1718  dbprint(i_print,"// ");
1719  dbprint(i_print,"// versal deformation with triv. section");
1720  dbprint(i_print,"// =====================================");
1721  dbprint(i_print,"// ");
1722
1723  ideal JJ=maxideal(1)*jacob(f);
1724  ideal kbase_versal=kbase(std(JJ));
1725  s=size(kbase_versal);
1726  ring @Pt=QQ,(t(1..s)),ds;
1727  def @Px=@Pt+old_ring;
1728  setring @Px;
1729  // basering has changed to @Px
1730
1731  poly F=imap(old_ring,f);
1732  ideal kbase_versal=imap(old_ring,kbase_versal);
1733  for (i=1; i<=s; i++)
1734  {
1735    F=F+var(i)*kbase_versal[i];
1736  }
1737  dbprint(i_print-1,F);
1738  dbprint(i_print-1,"");
1739
1740
1741  ideal ES_Id,ES_Id_all_triv;
1742  poly Ftriv=F;
1743
1744  dbprint(i_print,"// ");
1745  dbprint(i_print,"// Compute equisingularity Stratum over Spec(C[t]/t^2)");
1746  dbprint(i_print,"// ===================================================");
1747  dbprint(i_print,"// ");
1748  list M=esStratum(F,2);
1749  dbprint(i_print,"// finished");
1750  dbprint(i_print,"// ");
1751
1752  if (M[2]==1) // error occurred during esStratum computation
1753  {
1754    print("Some error has occurred during the computation");
1755    return(list(0,0));
1756  }
1757
1758  if ( typeof(M[1])=="list" )
1759  {
1760    int defpars = nvars(basering)-2;
1761    poly Fred,Ftrivred;
1762    poly g;
1763    F=reduce(F,std(M[1][1]));
1764    Ftriv=reduce(Ftriv,std(M[1][2]));
1765
1766    for (i=1; i<=defpars; i++)
1767    {
1768      Fred=reduce(F,std(var(i)));
1769      Ftrivred=reduce(Ftriv,std(var(i)));
1770
1771      g=subst(F-Fred,var(i),1);
1772      ES_Id=ES_Id, g;
1773      F=Fred;
1774
1775      g=subst(Ftriv-Ftrivred,var(i),1);
1776      ES_Id_all_triv=ES_Id_all_triv, g;
1777      Ftriv=Ftrivred;
1778    }
1779
1780    setring old_ring;
1781    // back to original ring
1782
1783    ideal ES_Id = imap(@Px,ES_Id);
1784    ES_Id = interred(ES_Id);
1785
1786    ideal ES_Id_all_triv = imap(@Px,ES_Id_all_triv);
1787    ES_Id_all_triv = interred(ES_Id_all_triv);
1788
1789    ideal ESfix_Id = ES_Id, f, maxideal(1)*jacob(f);
1790    ES_Id = ES_Id, f, jacob(f);
1791    ES_Id_all_triv = ES_Id_all_triv, f, jacob(f);
1792
1793    if (typ==0)
1794    {
1795      return(list(ES_Id,ESfix_Id));
1796    }
1797    else
1798    {
1799      return(list(ES_Id,ESfix_Id,ES_Id_all_triv));
1800    }
1801  }
1802  else
1803  {
1804    def AuxRing=M[1];
1805
1806    dbprint(i_print,"// ");
1807    dbprint(i_print,"// change ring to ESSring");
1808
1809    setring AuxRing;  // contains p_F, ES
1810
1811    int defpars = nvars(basering)-2;
1812    poly Fred,Fredtriv;
1813    poly g;
1814    ideal ES_Id,ES_Id_all_triv;
1815
1816    poly p_Ftriv=p_F;
1817
1818    p_F=reduce(p_F,std(ES));
1819    p_Ftriv=reduce(p_Ftriv,std(ES_all_triv));
1820    for (i=1; i<=defpars; i++)
1821    {
1822      Fred=reduce(p_F,std(var(i)));
1823      Fredtriv=reduce(p_Ftriv,std(var(i)));
1824
1825      g=subst(p_F-Fred,var(i),1);
1826      ES_Id=ES_Id, g;
1827      p_F=Fred;
1828
1829      g=subst(p_Ftriv-Fredtriv,var(i),1);
1830      ES_Id_all_triv=ES_Id_all_triv, g;
1831      p_Ftriv=Fredtriv;
1832
1833    }
1834
1835    dbprint(i_print,"// ");
1836    dbprint(i_print,"// back to the original ring");
1837
1838    setring old_ring;
1839    // back to original ring
1840
1841    ideal ES_Id = imap(AuxRing,ES_Id);
1842    ES_Id = interred(ES_Id);
1843
1844    ideal ES_Id_all_triv = imap(AuxRing,ES_Id_all_triv);
1845    ES_Id_all_triv = interred(ES_Id_all_triv);
1846
1847    kill @Px;
1848    kill AuxRing;
1849
1850    ideal ESfix_Id = ES_Id, f, maxideal(1)*jacob(f);
1851    ES_Id = ES_Id, f, jacob(f);
1852    ES_Id_all_triv = ES_Id_all_triv, f, jacob(f);
1853    dbprint(i_print,"// ");
1854    dbprint(i_print,"// equisingularity ideal is computed!");
1855    if (typ==0)
1856    {
1857      return(list(ES_Id,ESfix_Id));
1858    }
1859    else
1860    {
1861      return(list(ES_Id,ESfix_Id,ES_Id_all_triv));
1862    }
1863  }
1864}
1865example
1866{
1867  "EXAMPLE:"; echo=2;
1868  ring r=0,(x,y),ds;
1869  poly f=x7+y7+(x-y)^2*x2y2;
1870  list K=esIdeal(f);
1871  option(redSB);
1872  // Wahl's equisingularity ideal:
1873  std(K[1]);
1874
1875  ring rr=0,(x,y),ds;
1876  poly f=x4+4x3y+6x2y2+4xy3+y4+2x2y15+4xy16+2y17+xy23+y24+y30+y31;
1877  list K=esIdeal(f);
1878  vdim(std(K[1]));
1879  // the latter should be equal to:
1880  tau_es(f);
1881}
1882
1883///////////////////////////////////////////////////////////////////////////////
1884
1885proc esStratum (poly p_F, list #)
1886"USAGE:   esStratum(F[,m,L]); F poly, m int, L list
1887ASSUME:  F defines a deformation of a reduced bivariate polynomial f
1888         and the characteristic of the basering does not divide mult(f). @*
1889         If nv is the number of variables of the basering, then the first
1890         nv-2 variables are the deformation parameters. @*
1891         If the basering is a qring, ideal(basering) must only depend
1892         on the deformation parameters.
1893COMPUTE: equations for the stratum of equisingular deformations with
1894         fixed (trivial) section.
1895RETURN:  list l: either consisting of a list and an integer, where
1896@format
1897  l[1][1]=ideal defining the equisingularity stratum
1898  l[1][2]=ideal defining the part of the equisingularity stratum where all
1899          equimultiple sections through the non-nodes of the reduced total
1900          transform are trivial sections
1901  l[2]=1 if some error has occurred,  l[2]=0 otherwise;
1902@end format
1903or consisting of a ring and an integer, where
1904@format
1905  l[1]=ESSring is a ring extension of basering containing the ideal ES
1906        (describing the ES-stratum), the ideal ES_all_triv (describing the
1907        part with trival equimultiple sections) and the polynomial p_F=F,
1908  l[2]=1 if some error has occurred,  l[2]=0 otherwise.
1909@end format
1910NOTE:    L is supposed to be the output of hnexpansion (with the given ordering
1911         of the variables appearing in f). @*
1912         If m is given, the ES Stratum over A/maxideal(m) is computed. @*
1913         This procedure uses @code{execute} or calls a procedure using
1914         @code{execute}.
1915         printlevel>=2 displays additional information.
1916SEE ALSO: esIdeal, isEquising
1917KEYWORDS: equisingularity stratum
1918EXAMPLE: example esStratum; shows examples.
1919"
1920{
1921  list l=esComputation (0,p_F,#);
1922  return(l);
1923}
1924example
1925{
1926   "EXAMPLE:"; echo=2;
1927   int p=printlevel;
1928   printlevel=1;
1929   ring r = 0,(a,b,c,d,e,f,g,x,y),ds;
1930   poly F = (x2+2xy+y2+x5)+ax+by+cx2+dxy+ey2+fx3+gx4;
1931   list M = esStratum(F);
1932   M[1][1];
1933
1934   printlevel=3;     // displays additional information
1935   esStratum(F,2)  ; // ES-stratum over Q[a,b,c,d,e,f,g] / <a,b,c,d,e,f,g>^2
1936
1937   ideal I = f-fa,e+b;
1938   qring q = std(I);
1939   poly F = imap(r,F);
1940   esStratum(F);
1941   printlevel=p;
1942}
1943
1944///////////////////////////////////////////////////////////////////////////////
1945
1946proc isEquising (poly p_F, list #)
1947"USAGE:   isEquising(F[,m,L]); F poly, m int, L list
1948ASSUME:  F defines a deformation of a reduced bivariate polynomial f
1949         and the characteristic of the basering does not divide mult(f). @*
1950         If nv is the number of variables of the basering, then the first
1951         nv-2 variables are the deformation parameters. @*
1952         If the basering is a qring, ideal(basering) must only depend
1953         on the deformation parameters.
1954COMPUTE: tests if the given family is equisingular along the trivial
1955         section.
1956RETURN:  int: 1 if the family is equisingular, 0 otherwise.
1957NOTE:    L is supposed to be the output of hnexpansion (with the given ordering
1958         of the variables appearing in f). @*
1959         If m is given, the family is considered over A/maxideal(m). @*
1960         This procedure uses @code{execute} or calls a procedure using
1961         @code{execute}.
1962         printlevel>=2 displays additional information.
1963EXAMPLE: example isEquising; shows examples.
1964"
1965{
1966  int check=esComputation (1,p_F,#);
1967  return(check);
1968}
1969example
1970{
1971   "EXAMPLE:"; echo=2;
1972   ring r = 0,(a,b,x,y),ds;
1973   poly F = (x2+2xy+y2+x5)+ay3+bx5;
1974   isEquising(F);
1975   ideal I = ideal(a);
1976   qring q = std(I);
1977   poly F = imap(r,F);
1978   isEquising(F);
1979
1980   ring rr=0,(A,B,C,x,y),ls;
1981   poly f=x7+y7+(x-y)^2*x2y2;
1982   poly F=f+A*y*diff(f,x)+B*x*diff(f,x);
1983   isEquising(F);
1984   isEquising(F,2);    // computation over  Q[a,b] / <a,b>^2
1985}
1986
1987
1988
1989/*  Examples:
1990
1991LIB "equising.lib";
1992ring r = 0,(x,y),ds;
1993poly p1 = y^2+x^3;
1994poly p2 = p1^2+x5y;
1995poly p3 = p2^2+x^10*p1;
1996poly p=p3^2+x^20*p2;
1997p;
1998list L=versal(p);
1999def Px=L[1];
2000setring Px;
2001poly F=Fs[1,1];
2002int t=timer;
2003list M=esStratum(F);
2004timer-t;  //-> 3
2005
2006LIB "equising.lib";
2007option(prot);
2008printlevel=2;
2009ring r=0,(x,y),ds;
2010poly f=(x-yx+y2)^2-(y+x)^31;
2011list L=versal(f);
2012def Px=L[1];
2013setring Px;
2014poly F=Fs[1,1];
2015int t=timer;
2016list M=esStratum(F);
2017timer-t;  //-> 233
2018
2019LIB "equising.lib";
2020printlevel=2;
2021option(prot);
2022timer=1;
2023ring r=0,(x,y),ls;
2024poly f=(x4-y4)^2-x10;
2025list L=versal(f);
2026def Px=L[1];
2027setring Px;
2028poly F=Fs[1,1];
2029int t=timer;
2030list M=esStratum(F,3);
2031timer-t;  //-> 8
2032
2033LIB "equising.lib";
2034printlevel=2;
2035timer=1;
2036ring rr=0,(x,y),ls;
2037poly f=x7+y7+(x-y)^2*x2y2;
2038list K=esIdeal(f);
2039// tau_es
2040vdim(std(K[1])); //-> 22
2041// tau_es_fix
2042vdim(std(K[2])); //-> 24
2043
2044LIB "equising.lib";
2045printlevel=2;
2046timer=1;
2047ring rr=0,(x,y),ls;
2048poly f=x7+y7+(x-y)^2*x2y2+x2y4; // Newton non-deg.
2049list K=esIdeal(f);
2050// tau_es
2051vdim(std(K[1])); //-> 21
2052// tau_es_fix
2053vdim(std(K[2])); //-> 23
2054
2055LIB "equising.lib";
2056ring r=0,(w,v),ds;
2057poly f=w2-v199;
2058list L=hnexpansion(f);
2059list LL=versal(f);
2060def Px=LL[1];
2061setring Px;
2062list L=imap(r,L);
2063poly F=Fs[1,1];
2064list M=esStratum(F,2,L);
2065
2066LIB "equising.lib";
2067printlevel=2;
2068timer=1;
2069ring rr=0,(A,B,C,x,y),ls;
2070poly f=x7+y7+(x-y)^2*x2y2;
2071poly F=f+A*y*diff(f,x)+B*x*diff(f,x)+C*diff(f,y);
2072list M=esStratum(F,6);
2073std(M[1][1]);  // standard basis of equisingularity ideal
2074
2075LIB "equising.lib";
2076printlevel=2;
2077timer=1;
2078ring rr=0,(x,y),ls;
2079poly f=x20+y7+(x-y)^2*x2y2+x2y4; // Newton non-degenerate
2080list K=esIdeal(f);
2081K;
2082
2083ring rr=0,(x,y),ls;
2084poly f=x6y-3x4y4-x4y5+3x2y7-x4y6+2x2y8-y10+2x2y9-y11+x2y10-y12-y13;
2085list K=esIdeal(f);
2086list L=versal(f);
2087def Px=L[1];
2088setring Px;
2089poly F=Fs[1,1];
2090list M=esStratum(F,2);
2091
2092LIB "equising.lib";
2093ring R=0,(A,B,C,D,x,y),ds;
2094poly f=x6y-3x4y4-x4y5+3x2y7-x4y6+2x2y8-y10+2x2y9-y11+x2y10-y12-y13;
2095poly F=f+Ax9+Bx7y2+Cx9y+Dx8y2;
2096list M=esStratum(F,2);
2097
2098LIB "equising.lib";
2099printlevel=2;
2100ring rr=0,(x,y),ls;
2101poly f=x6y-3x4y4-x4y5+3x2y7-x4y6+2x2y8-y10+2x2y9-y11+x2y10-y12-y13;
2102list K=esIdeal(f);
2103vdim(std(K[1]));  //-> 51
2104tau_es(f);        //-> 51
2105
2106printlevel=3;
2107f=f*(y-x2)*(y2-x3)*(x-y5);
2108int t=timer;
2109list L=esIdeal(f);
2110vdim(std(L[1]));  //-> 99
2111timer-t;   //-> 42
2112t=timer;
2113tau_es(f);        //-> 99
2114timer-t;   //-> 23
2115
2116LIB "equising.lib";
2117printlevel=3;
2118ring rr=0,(x,y),ds;
2119poly f=x4+4x3y+6x2y2+4xy3+y4+2x2y15+4xy16+2y17+xy23+y24+y30+y31;
2120list K=esIdeal(f);
2121vdim(std(K[1]));  //-> 68
2122tau_es(f);        //-> 68
2123
2124list L=versal(f);
2125def Px=L[1];
2126setring Px;
2127poly F=Fs[1,1];
2128list M=esStratum(F);
2129timer-t;          //-> 0
2130
2131*/
Note: See TracBrowser for help on using the repository browser.