source: git/Singular/LIB/grobcov.lib @ 3686937

spielwiese
Last change on this file since 3686937 was 3686937, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Added '$Id$' as a comment to all libs (LIB/*.lib)
  • Property mode set to 100644
File size: 112.0 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2version="version grobcov.lib 4.0.0.0 Jun_2013 "; // $Id$
3category="General purpose";
4info="
5LIBRARY:  grobcov.lib   Groebner Cover for parametric ideals.
6PURPOSE:  Comprehensive Groebner Systems, Groebner Cover, Canonical Forms,
7          Parametric Polynomial Systems.
8          The library contains Montes-Wibmer's algorithms to compute the
9          canonical Groebner cover of a parametric ideal as described in
10          the paper:
11
12          Montes A., Wibmer M.,
13          \"Groebner Bases for Polynomial Systems with parameters\".
14          Journal of Symbolic Computation 45 (2010) 1391-1425.
15          The locus algorithm and definitions will be
16          published in a forthcoming paper by Abanades, Botana, Montes, Recio:
17          \''Geometrical locus of points using the Groebner cover\''.
18
19
20          The central routine is grobcov. Given a parametric
21          ideal, grobcov outputs its Canonical Groebner Cover, consisting
22          of a set of pairs of (basis, segment). The basis (after
23          normalization) is the reduced Groebner basis for each point
24          of the segment. The segments are disjoint, locally closed
25          and correspond to constant lpp (leading power product)
26          of the basis, and are represented in canonical prime
27          representation. The segments are disjoint and cover the
28          whole parameter space. The output is canonical, it only
29          depends on the given parametric ideal and the monomial order.
30          This is much more than a simple Comprehensive Groebner System.
31          The algorithm grobcov allows options to solve partially the
32          problem when the whole automatic algorithm does not finish
33          in reasonable time.
34
35          grobcov uses a first algorithm cgsdr that outputs a disjoint
36          reduced Comprehensive Groebner System with constant lpp.
37          For this purpose, in this library, the implemented algorithm is
38          Kapur-Sun-Wang algorithm, because it is the most efficient
39          algorithm known for this purpose.
40
41          D. Kapur, Y. Sun, and D.K. Wang.
42          \"A New Algorithm for Computing Comprehensive Groebner Systems\".
43          Proceedings of ISSAC'2010, ACM Press, (2010), 29-36.
44
45          cgsdr can be called directly if only a disjoint reduced
46          Comprehensive Groebner System (CGS) is required.
47
48AUTHORS:  Antonio Montes , Hans Schoenemann.
49OVERVIEW: see \"Groebner Bases for Polynomial Systems with parameters\"
50          Montes A., Wibmer M.,
51          Journal of Symbolic Computation 45 (2010) 1391-1425.
52          (http://www-ma2.upc.edu/~montes/).
53
54NOTATIONS: All given and determined polynomials and ideals are in the
55@*         basering Q[a][x]; (a=parameters, x=variables)
56@*         After defining the ring, the main routines
57@*         grobcov, cgsdr,
58@*         generate the global rings
59@*         @R   (Q[a][x]),
60@*         @P   (Q[a]),
61@*         @RP  (Q[x,a])
62@*         that are used inside and killed before the output.
63@*         If you want to use some internal routine you must
64@*         create before the above rings by calling setglobalrings();
65@*         because most of the internal routines use these rings.
66@*         The call to the basic routines grobcov, cgsdr will
67@*         kill these rings.
68
69PROCEDURES:
70
71grobcov(F);        Is the basic routine giving the canonical
72                   Groebner cover of the parametric ideal F.
73                   This routine accepts many options, that
74                   allow to obtain results even when the canonical
75                   computation does not finish in reasonable time.
76
77cgsdr(F);          Is the procedure for obtaining a first disjoint,
78                   reduced Comprehensive Groebner System that
79                   is used in grobcov, but that can be used
80                   independently if only the CGS is required.
81                   It is a more efficient routine than buildtree
82                   (the own routine that is no more used). It uses
83                   now KSW algorithm.
84
85setglobalrings();  Generates the global rings @R, @P and @PR that are
86                   respectively the rings Q[a][x], Q[a], Q[x,a].
87                   It is called inside each of the fundamental routines
88                   of the library: grobcov, cgsdr and killed before
89                   the output.
90                   If the user want to use some other internal routine,
91                   then setglobalrings() is to be called before, as
92                   the rings @R, @P and @RP are needed in most of them.
93                   globally, and more internal routines can be used, but
94                   these rings are killed by the call to any of the
95                   basic routines.
96
97pdivi(f,F);     Performs a pseudodivision of a parametric polynomial
98                   by a parametric ideal.
99
100pnormalf(f,E,N);   Reduces a parametric polynomial f over V(E) \ V(N)
101                   E is the null ideal and N the non-null ideal
102                   over the parameters.
103
104extend(GC); When the grobcov of an ideal has been computed
105                   with the default option ('ext',0) and the explicit
106                   option ('rep',2) (which is not the default), then
107                   one can call extend (GC) (and options) to obtain the
108                   full representation of the bases. With the default
109                   option ('ext',0) only the generic representation of
110                   the bases are computed, and one can obtain the full
111                   representation using extend.
112
113locus(G):   Special routine for determining the locus of points
114                   of  objects. Given a parametric ideal J with
115                   parameters (a_1,..a_m) and variables (x_1,..,xn),
116                   representing the system determining
117                   the locus of points (a_1,..,a_m)) who verify certain
118                   properties, computing the grobcov G of
119                   J and applying to it locus, determines the different
120                   classes of locus components. They can be
121                   Normal, Special, Accumulation point, Degenerate.
122                   The output are the components given in P-canonical form
123                   of two constructible sets: Normal, and Non-Normal
124                   The Normal Set has Normal and Special components
125                   The Non-Normal set has Accumulation and Degenerate components.
126                   The description of the algorithm and definitions will be
127                   given in a forthcoming paper by Abanades, Botana, Montes, Recio:
128                   ''Geometrical locus of points using the Groebner cover''
129
130locusdg(G):  Is a special routine for computing the locus in dinamical geometry.
131                    It detects automatically a possible point that is to be avoided by the mover,
132                    whose coordinates must be the last two coordinates in the definition of the ring.
133                    If such a point is detected, then it eliminates the segments of the grobcov
134                    depending on the point that is to be avoided.
135                    Then it calls locus.
136
137locusto(L):  Transforms the output of locus to a string that
138                  can be reed from different computational systems.
139
140SEE ALSO: compregb_lib
141";
142
143LIB "primdec.lib";
144LIB "qhmoduli.lib";
145
146// ************ Begin of the grobcov library *********************
147
148// Library grobcov.lib
149// (Groebner cover):
150// Release 1: (public)
151// Initial data: 21-1-2008
152// Final data: 3-7-2008
153// Release 2: (private)
154// Initial data: 6-9-2009
155// Final data: 25-10-2011
156// Release 3: (this release, public)
157// Initial data: 1-7-2012
158// Final data: 4-9-2012
159// basering Q[a][x];
160
161// ************ Begin of buildtree ******************************
162
163proc setglobalrings()
164"USAGE:   setglobalrings();
165          No arguments
166RETURN:   After its call the rings @R=Q[a][x], @P=Q[a], @RP=Q[x,a] are
167          defined as global variables.
168NOTE:     It is called internally by the fundamental routines of the
169          library grobcov, cgsdr, extend, pdivi, pnormalf, locus, locusto,
170          and killed before the output.
171          The user does not need to call it, except when it is interested
172          in using some internal routine of the library that
173          uses these rings.
174          The basering R, must be of the form Q[a][x], a=parameters,
175          x=variables, and should be defined previously.
176KEYWORDS: ring, rings
177EXAMPLE:  setglobalrings; shows an example"
178{
179  if (defined(@P))
180  {
181    kill @P; kill @R; kill @RP;
182  }
183  def RR=basering;
184  def @R=basering;  // must be of the form K[a][x], a=parameters, x=variables
185  def Rx=ringlist(RR);
186  def @P=ring(Rx[1]);
187  list Lx;
188  Lx[1]=0;
189  Lx[2]=Rx[2]+Rx[1][2];
190  Lx[3]=Rx[1][3];
191  Lx[4]=Rx[1][4];
192  Rx[1]=0;
193  def D=ring(Rx);
194  def @RP=D+@P;
195  exportto(Top,@R);      // global ring K[a][x]
196  exportto(Top,@P);      // global ring K[a]
197  exportto(Top,@RP);     // global ring K[x,a] with product order
198  setring(RR);
199};
200example
201{ "EXAMPLE:"; echo = 2;
202  ring R=(0,a,b),(x,y,z),dp;
203  setglobalrings();
204  @R;
205  @P;
206  @RP;
207ringlist(@R);
208ringlist(@P);
209ringlist(@RP);
210}
211
212//*************Auxilliary routines**************
213
214// cld : clears denominators of an ideal and normalizes to content 1
215//       can be used in @R or @P or @RP
216// input:
217//    ideal J (J can be also poly), but the output is an ideal;
218// output:
219//    ideal Jc (the new form of ideal J without denominators and
220//       normalized to content 1)
221proc cld(ideal J)
222{
223  if (size(J)==0){return(ideal(0));}
224  int te=0;
225  def RR=basering;
226  if(not(defined(@RP)))
227  {
228    te=1;
229    setglobalrings();
230  }
231  setring(@RP);
232  def Ja=imap(RR,J);
233  ideal Jb;
234  if (size(Ja)==0){setring(RR); return(ideal(0));}
235  int i;
236  def j=0;
237  for (i=1;i<=ncols(Ja);i++){if (size(Ja[i])!=0){j++; Jb[j]=cleardenom(Ja[i]);}}
238  setring(RR);
239  def Jc=imap(@RP,Jb);
240  if(te){kill @R; kill @RP; kill @P;}
241  return(Jc);
242};
243
244proc memberpos(f,J)
245//"USAGE:  memberpos(f,J);
246//         (f,J) expected (polynomial,ideal)
247//               or       (int,list(int))
248//               or       (int,intvec)
249//               or       (intvec,list(intvec))
250//               or       (list(int),list(list(int)))
251//               or       (ideal,list(ideal))
252//               or       (list(intvec),  list(list(intvec))).
253//         The ring can be @R or @P or @RP or any other.
254//RETURN:  The list (t,pos) t int; pos int;
255//         t is 1 if f belongs to J and 0 if not.
256//         pos gives the position in J (or 0 if f does not belong).
257//EXAMPLE: memberpos; shows an example"
258{
259  int pos=0;
260  int i=1;
261  int j;
262  int t=0;
263  int nt;
264  if (typeof(J)=="ideal"){nt=ncols(J);}
265  else{nt=size(J);}
266  if ((typeof(f)=="poly") or (typeof(f)=="int"))
267  { // (poly,ideal)  or
268    // (poly,list(poly))
269    // (int,list(int)) or
270    // (int,intvec)
271    i=1;
272    while(i<=nt)
273    {
274      if (f==J[i]){return(list(1,i));}
275      i++;
276    }
277    return(list(0,0));
278  }
279  else
280  {
281    if ((typeof(f)=="intvec") or ((typeof(f)=="list") and (typeof(f[1])=="int")))
282    { // (intvec,list(intvec)) or
283      // (list(int),list(list(int)))
284      i=1;
285      t=0;
286      pos=0;
287      while((i<=nt) and (t==0))
288      {
289        t=1;
290        j=1;
291        if (size(f)!=size(J[i])){t=0;}
292        else
293        {
294          while ((j<=size(f)) and t)
295          {
296            if (f[j]!=J[i][j]){t=0;}
297            j++;
298          }
299        }
300        if (t){pos=i;}
301        i++;
302      }
303      if (t){return(list(1,pos));}
304      else{return(list(0,0));}
305    }
306    else
307    {
308      if (typeof(f)=="ideal")
309      { // (ideal,list(ideal))
310        i=1;
311        t=0;
312        pos=0;
313        while((i<=nt) and (t==0))
314        {
315          t=1;
316          j=1;
317          if (ncols(f)!=ncols(J[i])){t=0;}
318          else
319          {
320            while ((j<=ncols(f)) and t)
321            {
322              if (f[j]!=J[i][j]){t=0;}
323              j++;
324            }
325          }
326          if (t){pos=i;}
327          i++;
328        }
329        if (t){return(list(1,pos));}
330        else{return(list(0,0));}
331      }
332      else
333      {
334        if ((typeof(f)=="list") and (typeof(f[1])=="intvec"))
335        { // (list(intvec),list(list(intvec)))
336          i=1;
337          t=0;
338          pos=0;
339          while((i<=nt) and (t==0))
340          {
341            t=1;
342            j=1;
343            if (size(f)!=size(J[i])){t=0;}
344            else
345            {
346              while ((j<=size(f)) and t)
347              {
348                if (f[j]!=J[i][j]){t=0;}
349                j++;
350              }
351            }
352            if (t){pos=i;}
353            i++;
354          }
355          if (t){return(list(1,pos));}
356          else{return(list(0,0));}
357        }
358      }
359    }
360  }
361}
362//example
363//{ "EXAMPLE:"; echo = 2;
364//  list L=(7,4,5,1,1,4,9);
365//  memberpos(1,L);
366//}
367
368proc subset(J,K)
369//"USAGE:   subset(J,K);
370//          (J,K)  expected (ideal,ideal)
371//                   or     (list, list)
372//RETURN:   1 if all the elements of J are in K, 0 if not.
373//EXAMPLE:  subset; shows an example;"
374{
375  int i=1;
376  int nt;
377  if (typeof(J)=="ideal"){nt=ncols(J);}
378  else{nt=size(J);}
379  if (size(J)==0){return(1);}
380  while(i<=nt)
381  {
382    if (memberpos(J[i],K)[1]){i++;}
383    else {return(0);}
384  }
385  return(1);
386}
387//example
388//{ "EXAMPLE:"; echo = 2;
389//  list J=list(7,3,2);
390//  list K=list(1,2,3,5,7,8);
391//  subset(J,K);
392//}
393
394// elimintfromideal: elimine the constant numbers from an ideal
395//        (designed for W, nonnull conditions)
396// input: ideal J
397// output:ideal K with the elements of J that are non constants, in the
398//        ring @P
399proc elimintfromideal(ideal J)
400{
401  int i;
402  int j=0;
403  ideal K;
404  if (size(J)==0){return(ideal(0));}
405  for (i=1;i<=ncols(J);i++){if (size(variables(J[i])) !=0){j++; K[j]=J[i];}}
406  return(K);
407}
408
409// simpqcoeffs : simplifies a quotient of two polynomials
410// input: two coeficients (or terms), that are considered as a quotient
411// output: the two coeficients reduced without common factors
412proc simpqcoeffs(poly n,poly m)
413{
414  def nc=content(n);
415  def mc=content(m);
416  def gc=gcd(nc,mc);
417  ideal s=n/gc,m/gc;
418  return (s);
419}
420
421// pdivi : pseudodivision of a poly f by a parametric ideal F in Q[a][x].
422// input:
423//   poly  f (in the parametric ring @R)
424//   ideal F (in the parametric ring @R)
425// output:
426//   list (poly r, ideal q, poly mu)
427proc pdivi(poly f,ideal F)
428"USAGE:   pdivi(f,F);
429          poly f: the polynomial to be divided
430          ideal F: the divisor ideal
431RETURN:   A list (poly r, ideal q, poly m). r is the remainder of the
432          pseudodivision, q is the set of quotients, and m is the
433          coefficient factor by which f is to be multiplied.
434NOTE:     pseudodivision of a poly f by an ideal F in @R. Returns a
435          list (r,q,m) such that m*f=r+sum(q.G), and no lpp of a divisor
436          divides a pp of r.
437KEYWORDS: division, reduce
438EXAMPLE:  pdivi; shows an example"
439{
440  int te=0;
441  if (defined(@P)==1){te=1;}
442  else{setglobalrings();}
443  def R=basering;
444  int i;
445  int j;
446  poly r=0;
447  poly mu=1;
448  def p=f;
449  ideal q;
450  for (i=1; i<=size(F); i++){q[i]=0;};
451  ideal lpf;
452  ideal lcf;
453  for (i=1;i<=size(F);i++){lpf[i]=leadmonom(F[i]);}
454  for (i=1;i<=size(F);i++){lcf[i]=leadcoef(F[i]);}
455  poly lpp;
456  poly lcp;
457  poly qlm;
458  poly nu;
459  poly rho;
460  int divoc=0;
461  ideal qlc;
462  while (p!=0)
463  {
464    i=1;
465    divoc=0;
466    lpp=leadmonom(p);
467    lcp=leadcoef(p);
468    while (divoc==0 and i<=size(F))
469    {
470      qlm=lpp/lpf[i];
471      if (qlm!=0)
472      {
473        qlc=simpqcoeffs(lcp,lcf[i]);
474        nu=qlc[2];
475        mu=mu*nu;
476        rho=qlc[1]*qlm;
477        p=nu*p-rho*F[i];
478        r=nu*r;
479        for (j=1;j<=size(F);j++){q[j]=nu*q[j];}
480        q[i]=q[i]+rho;
481        divoc=1;
482      }
483      else {i++;}
484    }
485    if (divoc==0)
486    {
487      r=r+lcp*lpp;
488      p=p-lcp*lpp;
489    }
490  }
491  list res=r,q,mu;
492  if(te==0){kill @P; kill @R; kill @RP;}
493  return(res);
494}
495example
496{ "EXAMPLE:"; echo = 2;
497  ring R=(0,a,b,c),(x,y),dp;
498  "Divisor=";
499  poly f=(ab-ac)*xy+(ab)*x+(5c);
500  "Dividends=";
501  ideal F=ax+b,cy+a;
502  "(Remainder, quotients, factor)=";
503  def r=pdivi(f,F);
504  r;
505  "Verifying the division: r[3]*f-(r[2][1]*F[1]+r[2][2]*F[2])-r[1] =";
506  r[3]*f-(r[2][1]*F[1]+r[2][2]*F[2])-r[1];
507}
508
509// pspol : S-poly of two polynomials in @R
510// @R
511// input:
512//   poly f (given in the ring @R)
513//   poly g (given in the ring @R)
514// output:
515//   list (S, red):  S is the S-poly(f,g) and red is a Boolean variable
516//                if red then S reduces by Buchberger 1st criterion
517//                (not used)
518proc pspol(poly f,poly g)
519{
520  def lcf=leadcoef(f);
521  def lcg=leadcoef(g);
522  def lpf=leadmonom(f);
523  def lpg=leadmonom(g);
524  def v=gcd(lpf,lpg);
525  def s=simpqcoeffs(lcf,lcg);
526  def vf=lpf/v;
527  def vg=lpg/v;
528  poly S=s[2]*vg*f-s[1]*vf*g;
529  return(S);
530}
531
532// facvar: Returns all the free-square factors of the elements
533//         of ideal J (non repeated). Integer factors are ignored,
534//         even 0 is ignored. It can be called from ideal @R, but
535//         the given ideal J must only contain poynomials in the
536//         parameters.
537//         Operates in the ring @P, but can be called from ring @R,
538//         and the ideal @P must be defined calling first setglobalrings();
539// input:  ideal J
540// output: ideal Jc: Returns all the free-square factors of the elements
541//         of ideal J (non repeated). Integer factors are ignored,
542//         even 0 is ignored. It can be called from ideal @R.
543proc facvar(ideal J)
544//"USAGE:   facvar(J);
545//          J: an ideal in the parameters
546//RETURN:   all the free-square factors of the elements
547//          of ideal J (non repeated). Integer factors are ignored,
548//          even 0 is ignored. It can be called from ideal @R, but
549//          the given ideal J must only contain poynomials in the
550//          parameters.
551//NOTE:     Operates in the ring @P, and the ideal J must contain only
552//          polynomials in the parameters, but can be called from ring @R.
553//KEYWORDS: factor
554//EXAMPLE:  facvar; shows an example"
555{
556  int i;
557  def RR=basering;
558  setring(@P);
559  def Ja=imap(RR,J);
560  if(size(Ja)==0){setring(RR); return(ideal(0));}
561  Ja=elimintfromideal(Ja); // also in ideal @P
562  ideal Jb;
563  if (size(Ja)==0){Jb=ideal(0);}
564  else
565  {
566    for (i=1;i<=ncols(Ja);i++){if(size(Ja[i])!=0){Jb=Jb,factorize(Ja[i],1);}}
567    Jb=simplify(Jb,2+4+8);
568    Jb=cld(Jb);
569    Jb=elimintfromideal(Jb); // also in ideal @P
570  }
571  setring(RR);
572  def Jc=imap(@P,Jb);
573  return(Jc);
574}
575//example
576//{ "EXAMPLE:"; echo = 2;
577//  ring R=(0,a,b,c),(x,y,z),dp;
578//  setglobalrings();
579//  ideal J=a2-b2,a2-2ab+b2,abc-bc;
580//  facvar(J);
581//}
582
583// Ered: eliminates the factors in the polynom f that are non-null.
584//       In ring @R
585// input:
586//   poly f:
587//   ideal E  of null-conditions
588//   ideal N  of non-null conditions
589//        (E,N) represents V(E)\V(N),
590//        Ered eliminates the non-null factors of f in V(E)\V(N)
591// output:
592//   poly f2  where the non-null conditions have been dropped from f
593proc Ered(poly f,ideal E, ideal N)
594{
595  def RR=basering;
596  setring(@R);
597  poly ff=imap(RR,f);
598  ideal EE=imap(RR,E);
599  ideal NN=imap(RR,N);
600  if((ff==0) or (equalideals(NN,ideal(1)))){setring(RR); return(f);}
601  def v=variables(ff);
602  int i;
603  poly X=1;
604  for(i=1;i<=size(v);i++){X=X*v[i];}
605  matrix M=coef(ff,X);
606  setring(@P);
607  def RPE=imap(@R,EE);
608  def RPN=imap(@R,NN);
609  matrix Mp=imap(@R,M);
610  poly g=Mp[2,1];
611  if (size(Mp)!=2)
612  {
613    for(i=2;i<=size(Mp) div 2;i++)
614    {
615      g=gcd(g,Mp[2,i]);
616    }
617  }
618  if (g==1){setring(RR); return(f);}
619  else
620  {
621    def wg=factorize(g,2);
622    if (wg[1][1]==1){setring(RR); return(f);}
623    else
624    {
625      poly simp=1;
626      int te;
627      for(i=1;i<=size(wg[1]);i++)
628      {
629        te=inconsistent(RPE+wg[1][i],RPN);
630        if(te)
631        {
632          simp=simp*(wg[1][i])^(wg[2][i]);
633        }
634      }
635    }
636    if (simp==1){setring(RR); return(f);}
637    else
638    {
639      setring(RR);
640      def simp0=imap(@P,simp);
641      def f2=f/simp0;
642      return(f2);
643    }
644  }
645}
646
647// pnormalf: reduces a polynomial f wrt a V(E)\V(N)
648//           dividing by E and eliminating factors in N.
649//           called in the ring @R,
650//           operates in the ring @RP.
651// input:
652//         poly  f
653//         ideal E  (depends only on the parameters)
654//         ideal N  (depends only on the parameters)
655//                  (E,N) represents V(E)\V(N)
656//         optional:
657// output: poly f2 reduced wrt to V(E)\V(N)
658proc pnormalf(poly f, ideal E, ideal N)
659"USAGE:   pnormalf(f,E,N);
660          f: the polynomial to be reduced modulo V(E)\V(N)
661          of a segment in the parameters.
662          E: the null conditions ideal
663          N: the non-null conditions
664RETURN:   a reduced polynomial g of f, whose coefficients are reduced
665          modulo E and having no factor in N.
666NOTE: Should be called from ring Q[a][x].
667          Ideals E and N must be given by polynomials
668          in the parameters.
669KEYWORDS: division, pdivi, reduce
670EXAMPLE:  pnormalf; shows an example"
671{
672    def RR=basering;
673    int te=0;
674    if (defined(@P)){te=1;}
675    else{setglobalrings();}
676    setring(@RP);
677    def fa=imap(RR,f);
678    def Ea=imap(RR,E);
679    def Na=imap(RR,N);
680    option(redSB);
681    Ea=std(Ea);
682    def r=cld(reduce(fa,Ea));
683    poly f1=r[1];
684    f1=Ered(r[1],Ea,Na);
685    setring(RR);
686    def f2=imap(@RP,f1);
687    if(te==0){kill @R; kill @RP; kill @P;}
688    return(f2)
689};
690example
691{ "EXAMPLE:"; echo = 2;
692  ring R=(0,a,b,c),(x,y),dp;
693  poly f=(b^2-1)*x^3*y+(c^2-1)*x*y^2+(c^2*b-b)*x+(a-bc)*y;
694  ideal E=(c-1);
695  ideal N=a-b;
696  pnormalf(f,E,N);
697}
698
699// idint: ideal intersection
700//        in the ring @P.
701//        it works in an extended ring
702// input: two ideals in the ring @P
703// output the intersection of both (is not a GB)
704proc idint(ideal I, ideal J)
705{
706  def RR=basering;
707  ring T=0,t,lp;
708  def K=T+RR;
709  setring(K);
710  def Ia=imap(RR,I);
711  def Ja=imap(RR,J);
712  ideal IJ;
713  int i;
714  for(i=1;i<=size(Ia);i++){IJ[i]=t*Ia[i];}
715  for(i=1;i<=size(Ja);i++){IJ[size(Ia)+i]=(1-t)*Ja[i];}
716  ideal eIJ=eliminate(IJ,t);
717  setring(RR);
718  return(imap(K,eIJ));
719}
720
721// lesspol: compare two polynomials by its leading power products
722// input:  two polynomials f,g in the ring @R
723// output: 0 if f<g,  1 if f>=g
724proc lesspol(poly f, poly g)
725{
726  if (leadmonom(f)<leadmonom(g)){return(1);}
727  else
728  {
729    if (leadmonom(g)<leadmonom(f)){return(0);}
730    else
731    {
732      if (leadcoef(f)<leadcoef(g)){return(1);}
733      else {return(0);}
734    }
735  }
736};
737
738// delfromideal: deletes the i-th polynomial from the ideal F
739proc delfromideal(ideal F, int i)
740{
741  int j;
742  ideal G;
743  if (size(F)<i){ERROR("delfromideal was called incorrect arguments");}
744  if (size(F)<=1){return(ideal(0));}
745  if (i==0){return(F)};
746  for (j=1;j<=size(F);j++)
747  {
748    if (j!=i){G[size(G)+1]=F[j];}
749  }
750  return(G);
751}
752
753// delidfromid: deletes the polynomials in J that are in I
754// input: ideals I,J
755// output: the ideal J without the polynomials in I
756proc delidfromid(ideal I, ideal J)
757{
758  int i; list r;
759  ideal JJ=J;
760  for (i=1;i<=size(I);i++)
761  {
762    r=memberpos(I[i],JJ);
763    if (r[1])
764    {
765      JJ=delfromideal(JJ,r[2]);
766    }
767  }
768  return(JJ);
769}
770
771// sortideal: sorts the polynomials in an ideal by lm in ascending order
772proc sortideal(ideal Fi)
773{
774  def RR=basering;
775  setring(@RP);
776  def F=imap(RR,Fi);
777  def H=F;
778  ideal G;
779  int i;
780  int j;
781  poly p;
782  while (size(H)!=0)
783  {
784    j=1;
785    p=H[1];
786    for (i=1;i<=size(H);i++)
787    {
788      if(lesspol(H[i],p)){j=i;p=H[j];}
789    }
790    G[size(G)+1]=p;
791    H=delfromideal(H,j);
792  }
793  setring(RR);
794  def GG=imap(@RP,G);
795  return(GG);
796}
797
798// mingb: given a basis (gb reducing) it
799// order the polynomials is ascending order and
800// eliminates the polynomials whose lpp are divisible by some
801// smaller one
802proc mingb(ideal F)
803{
804  int t; int i; int j;
805  def H=sortideal(F);
806  ideal G;
807  if (ncols(H)<=1){return(H);}
808  G=H[1];
809  for (i=2; i<=ncols(H); i++)
810  {
811    t=1;
812    j=1;
813    while (t and (j<i))
814    {
815      if((leadmonom(H[i])/leadmonom(H[j]))!=0) {t=0;}
816      j++;
817    }
818    if (t) {G[size(G)+1]=H[i];}
819  }
820  return(G);
821}
822
823// redgbn: given a minimal basis (gb reducing) it
824// reduces each polynomial wrt to V(E) \ V(N)
825proc redgbn(ideal F, ideal E, ideal N)
826{
827  int te=0;
828  if (defined(@P)==1){te=1;}
829  ideal G=F;
830  ideal H;
831  int i;
832  if (size(G)==0){return(ideal(0));}
833  for (i=1;i<=size(G);i++)
834  {
835    H=delfromideal(G,i);
836    G[i]=pnormalf(pdivi(G[i],H)[1],E,N);
837    G[i]=primepartZ(G[i]);
838  }
839  if(te==1){setglobalrings();}
840  return(G);
841};
842
843// eliminates repeated elements form an ideal or matrix or module or intmat or bigintmat
844proc elimrepeated(F)
845{
846  int i;
847  def FF=F;
848  FF=F[1];
849  for (i=2;i<=ncols(F);i++)
850  {
851    if (not(memberpos(F[i],FF)[1]))
852    {
853      FF[size(FF)+1]=F[i];
854    }
855  }
856  return(FF);
857}
858
859proc elimrepeatedvl(F)
860{
861  int i;
862  def FF=F;
863  FF=F[1];
864  for (i=2;i<=size(F);i++)
865  {
866    if (not(memberpos(F[i],FF)[1]))
867    {
868      FF[size(FF)+1]=F[i];
869    }
870  }
871  return(FF);
872}
873
874
875// equalideals
876// input: 2 ideals F and G;
877// output: 1 if they are identical (the same polynomials in the same order)
878//         0 else
879proc equalideals(ideal F, ideal G)
880{
881  int i=1; int t=1;
882  if (size(F)!=size(G)){return(0);}
883  while ((i<=size(F)) and (t))
884  {
885    if (F[i]!=G[i]){t=0;}
886    i++;
887  }
888  return(t);
889}
890
891// delintvec
892// input: intvec V
893//        int i
894// output:
895//        intvec W (equal to V but the coordinate i is deleted
896proc delintvec(intvec V, int i)
897{
898  int j;
899  intvec W;
900  for (j=1;j<i;j++){W[j]=V[j];}
901  for (j=i+1;j<=size(V);j++){W[j-1]=V[j];}
902  return(W);
903}
904
905//**************Begin homogenizing************************
906
907// ishomog:
908// Purpose: test if a polynomial is homogeneous in the variables or not
909// input:  poly f
910// output  1 if f is homogeneous, 0 if not
911proc ishomog(f)
912{
913  int i; poly r; int d; int dr;
914  if (f==0){return(1);}
915  d=deg(f); dr=d; r=f;
916  while ((d==dr) and (r!=0))
917  {
918    r=r-lead(r);
919    dr=deg(r);
920  }
921  if (r==0){return(1);}
922  else{return(0);}
923}
924
925// postredgb: given a minimal basis (gb reducing) it
926// reduces each polynomial wrt to the others
927proc postredgb(ideal F)
928{
929  int te=0;
930  if(defined(@P)==1){te=1;}
931  ideal G;
932  ideal H;
933  int i;
934  if (size(F)==0){return(ideal(0));}
935  for (i=1;i<=size(F);i++)
936  {
937    H=delfromideal(F,i);
938    G[i]=pdivi(F[i],H)[1];
939  }
940  if(te==1){setglobalrings();}
941  return(G);
942}
943
944//purpose ideal intersection called in @R and computed in @P
945proc idintR(ideal N, ideal M)
946{
947  def RR=basering;
948  setring(@P);
949  def Np=imap(RR,N);
950  def Mp=imap(RR,M);
951  def Jp=idint(Np,Mp);
952  setring(RR);
953  return(imap(@P,Jp));
954}
955
956//purpose reduced Groebner basis called in @R and computed in @P
957proc gbR(ideal N)
958{
959  def RR=basering;
960  setring(@P);
961  def Np=imap(RR,N);
962  option(redSB);
963  Np=std(Np);
964  setring(RR);
965  return(imap(@P,Np));
966}
967
968//**************End homogenizing************************
969
970//**************Begin of Groebner Cover*****************
971
972// incquotient
973// incremental quotient
974// Input: ideal N: a Groebner basis of an ideal
975//        poly f:
976// Output: Na = N:<f>
977proc incquotient(ideal N, poly f)
978{
979  poly g; int i;
980  ideal Nb; ideal Na=N;
981
982  // begins incquotient
983  if (size(Na)==1)
984  {
985    g=gcd(Na[1],f);
986    if (g!=1)
987    {
988      Na[1]=Na[1]/g;
989    }
990    attrib(Na,"IsSB",1);
991    return(Na);
992  }
993  def P=basering;
994  poly @t;
995  ring H=0,@t,lp;
996  def HP=H+P;
997  setring(HP);
998  def fh=imap(P,f);
999  def Nh=imap(P,N);
1000  ideal Nht;
1001  for (i=1;i<=size(Nh);i++)
1002  {
1003    Nht[i]=Nh[i]*@t;
1004  }
1005  attrib(Nht,"isSB",1);
1006  def fht=(1-@t)*fh;
1007  option(redSB);
1008  Nht=std(Nht,fht);
1009  ideal Nc; ideal v;
1010  for (i=1;i<=size(Nht);i++)
1011  {
1012    v=variables(Nht[i]);
1013    if(memberpos(@t,v)[1]==0)
1014    {
1015      Nc[size(Nc)+1]=Nht[i]/fh;
1016    }
1017  }
1018  setring(P);
1019  ideal HH;
1020  def Nd=imap(HP,Nc); Nb=Nd;
1021  option(redSB);
1022  Nb=std(Nd);
1023  return(Nb);
1024}
1025
1026// eliminates the ith element from a list or an intvec
1027proc elimfromlist(l, int i)
1028{
1029  if(typeof(l)=="list"){list L;}
1030  if (typeof(l)=="intvec"){intvec L;}
1031  if (typeof(l)=="ideal"){ideal L;}
1032  int j;
1033  if((size(l)==0) or (size(l)==1 and i!=1)){return(l);}
1034  if (size(l)==1 and i==1){return(L);}
1035  // L=l[1];
1036  if(i==1)
1037  {
1038    for(j=2;j<=size(l);j++)
1039    {
1040      L[j-1]=l[j];
1041    }
1042  }
1043  else
1044  {
1045    for(j=1;j<=i-1;j++)
1046    {
1047      L[j]=l[j];
1048    }
1049    for(j=i+1;j<=size(l);j++)
1050    {
1051      L[j-1]=l[j];
1052    }
1053  }
1054  return(L);
1055}
1056
1057proc idbefid(ideal a, ideal b)
1058{
1059  poly fa; poly fb; poly la; poly lb;
1060  int te=1; int i; int j;
1061  int na=size(a);
1062  int nb=size(b);
1063  int nm;
1064  if (na<=nb){nm=na;} else{nm=nb;}
1065  for (i=1;i<=nm; i++)
1066  {
1067    fa=a[i]; fb=b[i];
1068    while((fa!=0) or (fb!=0))
1069    {
1070      la=lead(fa);
1071      lb=lead(fb);
1072      fa=fa-la;
1073      fb=fb-lb;
1074      la=leadmonom(la);
1075      lb=leadmonom(lb);
1076      if(leadmonom(la+lb)!=la){return(1);}
1077      else{if(leadmonom(la+lb)!=lb){return(2);}}
1078    }
1079  }
1080  if(na<nb){return(1);}
1081  else
1082  {
1083    if(na>nb){return(2);}
1084    else{return(0);}
1085  }
1086}
1087
1088proc sortlistideals(list L)
1089{
1090  int i; int j; int n;
1091  ideal a; ideal b;
1092  list LL=L;
1093  list NL;
1094  int k; int te;
1095  i=1;
1096  while(size(LL)>0)
1097  {
1098    k=1;
1099    for(j=2;j<=size(LL);j++)
1100    {
1101      te=idbefid(LL[k],LL[j]);
1102      if (te==2){k=j;}
1103    }
1104    NL[size(NL)+1]=LL[k];
1105    n=size(LL);
1106    if (n>1){LL=elimfromlist(LL,k);} else{LL=list();}
1107  }
1108  return(NL);
1109}
1110
1111// returns 1 if the two lists of ideals are equal and 0 if not
1112proc equallistideals(list L, list M)
1113{
1114  int t; int i;
1115  if (size(L)!=size(M)){return(0);}
1116  else
1117  {
1118    t=1;
1119    if (size(L)>0)
1120    {
1121      i=1;
1122      while ((t) and (i<=size(L)))
1123      {
1124        if (equalideals(L[i],M[i])==0){t=0;}
1125        i++;
1126      }
1127    }
1128    return(t);
1129  }
1130}
1131
1132// Prep
1133// Computes the P-representation of V(N) \ V(M).
1134// input:
1135//    ideal N (null ideal) (not necessarily radical nor maximal)
1136//    ideal M (hole ideal) (not necessarily containing N)
1137// output:
1138//    the ((p_1,(p_11,p_1k_1)),..,(p_r,(p_r1,p_rk_r)));
1139//    the Prep of V(N)\V(M)
1140// Assumed to work in the ring @P of the parameters
1141proc Prep(ideal N, ideal M)
1142{
1143  if (N[1]==1)
1144  {
1145    return(list(list(ideal(1),list(ideal(1)))));
1146  }
1147  def RR=basering;
1148  setring(@P);
1149  ideal Np=imap(RR,N);
1150  ideal Mp=imap(RR,M);
1151  int i; int j; list L0;
1152
1153  list Ni=minGTZ(Np);
1154  list prep;
1155  for(j=1;j<=size(Ni);j++)
1156  {
1157    option(redSB);
1158    Ni[j]=std(Ni[j]);
1159  }
1160  list Mij;
1161  for (i=1;i<=size(Ni);i++)
1162  {
1163    Mij=minGTZ(Ni[i]+Mp);
1164    for(j=1;j<=size(Mij);j++)
1165    {
1166      option(redSB);
1167      Mij[j]=std(Mij[j]);
1168    }
1169    if ((size(Mij)==1) and (equalideals(Ni[i],Mij[1])==1)){;}
1170    else
1171    {
1172        prep[size(prep)+1]=list(Ni[i],Mij);
1173    }
1174  }
1175  if (size(prep)==0){prep=list(list(ideal(1),list(ideal(1))));}
1176  setring(RR);
1177  return(imap(@P,prep));
1178}
1179
1180// PtoCrep
1181// Computes the C-representation from the P-representation.
1182// input:
1183//    list ((p_1,(p_11,p_1k_1)),..,(p_r,(p_r1,p_rk_r)));
1184//         the P-representation of V(N)\V(M)
1185// output:
1186//    list (ideal ida, ideal idb)
1187//    the C-representaion of V(N)\V(M) = V(ida)\V(idb)
1188// Assumed to work in the ring @P of the parameters
1189proc PtoCrep(list L)
1190{
1191  def RR=basering;
1192  setring(@P);
1193  def Lp=imap(RR,L);
1194  int i; int j;
1195  ideal ida=ideal(1); ideal idb=ideal(1); list Lb; ideal N;
1196  for (i=1;i<=size(Lp);i++)
1197  {
1198    option(returnSB);
1199    N=Lp[i][1];
1200    ida=intersect(ida,N);
1201    Lb=Lp[i][2];
1202    for(j=1;j<=size(Lb);j++)
1203    {
1204      idb=intersect(idb,Lb[j]);
1205    }
1206  }
1207  def La=list(ida,idb);
1208  setring(RR);
1209  return(imap(@P,La));
1210}
1211
1212// input: F a parametric ideal in Q[a][x]
1213// output: a rComprehensive Groebner System disjoint and reduced.
1214//      It uses Kapur-Sun-Wang algorithm, and with the options
1215//      can compute the homogenization before  (('can',0) or ( 'can',1))
1216//      and dehomogenize the result.
1217proc cgsdr(ideal F, list #)
1218"USAGE: cgsdr(F); To compute a disjoint, reduced CGS.
1219          cgsdr is the starting point of the fundamental routine grobcov.
1220          Inside grobcov it is used only with options 'can' set to 0,1 and
1221          not with options ('can',2).
1222          It is to be used if only a disjoint reduced CGS is required.
1223          F: ideal in Q[a][x] (parameters and variables) to be discussed.
1224
1225          Options: To modify the default options, pairs of arguments
1226          -option name, value- of valid options must be added to the call.
1227
1228          Options:
1229            \"can\",0-1-2: The default value is \"can\",2. In this case no
1230                homogenization is done. With option (\"can\",0) the given
1231                basis is homogenized, and with option (\"can\",1) the
1232                whole given ideal is homogenized before computing the
1233                cgs and dehomogenized after.
1234                with option (\"can\",0) the homogenized basis is used
1235                with option (\"can\",1) the homogenized ideal is used
1236                with option (\"can\",2) the given basis is used
1237            \"null\",ideal E: The default is (\"null\",ideal(0)).
1238            \"nonnull\",ideal N: The default (\"nonnull\",ideal(1)).
1239                When options 'null' and/or 'nonnull' are given, then
1240                the parameter space is restricted to V(E)\V(N).
1241            \"comment\",0-1: The default is (\"comment\",0). Setting (\"comment\",1)
1242                will provide information about the development of the
1243                computation.
1244            \"out\",0-1: 1 (default) the output segments are given as
1245                as difference of varieties.
1246                0: the output segments are given in P-representation
1247                and the segments grouped by lpp
1248                With options (\"can\",0) and (\"can\",1) the option (\"out\",1)
1249                is set to (out,0) because it is not compatible.
1250          One can give none or whatever of these options.
1251          With the default options (\"can\",2,\"out\",1), only the
1252          Kapur-Sun-Wang algorithm is computed. This is very effectif
1253          but is only the starting point for the computation.
1254          When grobcov is computed, the call to cgsdr inside uses
1255          specific options that are more expensive ("can",0-1,"out",0).
1256RETURN:   Returns a list T describing a reduced and disjoint
1257          Comprehensive Groebner System (CGS),
1258          With option (\"out\",0)
1259           the segments are grouped by
1260           leading power products (lpp) of the reduced Groebner
1261           basis and given in P-representation.
1262           The returned list is of the form:
1263           (
1264             (lpp, (num,basis,segment),...,(num,basis,segment),lpp),
1265             ..,,
1266             (lpp, (num,basis,segment),...,(num,basis,segment),lpp)
1267           )
1268           The bases are the reduced Groebner bases (after normalization)
1269           for each point of the corresponding segment.
1270
1271           The third element of each lpp segment is the lpp of the
1272           used ideal in the CGS as a string:
1273            with option (\"can\",0) the homogenized basis is used
1274            with option (\"can\",1) the homogenized ideal is used
1275            with option (\"can\",2) the given basis is used
1276
1277          With option (\"out\",1) (default)
1278           only KSW is applied and segments are given as
1279           difference of varieties and are not grouped
1280           The returned list is of the form:
1281           (
1282             (E,N,B),..(E,N,B)
1283           )
1284           E is the null variety
1285           N is the nonnull variety
1286           segment = V(E)\V(N)
1287           B is the reduced Groebner basis
1288
1289NOTE:     The basering R, must be of the form Q[a][x], a=parameters,
1290          x=variables, and should be defined previously, and the ideal
1291          defined on R.
1292KEYWORDS: CGS, disjoint, reduced, Comprehensive Groebner System
1293EXAMPLE:  cgsdr; shows an example"
1294{
1295  def RR=basering;
1296  setglobalrings();
1297  // INITIALIZING OPTIONS
1298  int i; int j;
1299  int can=2;
1300  int out=1;
1301  poly f;
1302  ideal B;
1303  def E=ideal(0);
1304  def N=ideal(1);
1305  int comment=0;
1306  int start=timer;
1307  list L=#;
1308  for(i=1;i<=size(L) div 2;i++)
1309  {
1310    if(L[2*i-1]=="null"){E=L[2*i];}
1311    else
1312    {
1313      if(L[2*i-1]=="nonnull"){N=L[2*i];}
1314      else
1315      {
1316        if(L[2*i-1]=="comment"){comment=L[2*i];}
1317        else
1318        {
1319          if(L[2*i-1]=="can"){can=L[2*i];}
1320          else
1321          {
1322            if(L[2*i-1]=="out"){out=L[2*i];}
1323          }
1324        }
1325      }
1326    }
1327  }
1328  //if(can==2){out=1;}
1329  B=F;
1330  if ((printlevel) and (comment==0)){comment=printlevel;}
1331  if((can<2) and (out>0)){"Option out,1 is not compatible with can,0,1"; out=0;}
1332  // DEFINING OPTIONS
1333  list LL;
1334  LL[1]="can";     LL[2]=can;
1335  LL[3]="comment"; LL[4]=comment;
1336  LL[5]="out";     LL[6]=out;
1337  LL[7]="null";    LL[8]=E;
1338  LL[9]="nonnull"; LL[10]=N;
1339  if(comment>=1)
1340  {
1341    string("Begin cgsdr with options: ",LL);
1342  }
1343  int ish;
1344  for (i=1;i<=size(B);i++){ish=ishomog(B[i]); if(ish==0){break;};}
1345  if (ish)
1346  {
1347    if(comment>0){string("The given system is homogneous");}
1348    def GS=KSW(B,LL);
1349    //can=0;
1350  }
1351  else
1352  {
1353  // ACTING DEPENDING ON OPTIONS
1354  if(can==2)
1355  {
1356    // WITHOUT HOMOHGENIZING
1357    if(comment>0){string("Option of cgsdr: do not homogenize");}
1358    def GS=KSW(B,LL);
1359    setglobalrings();
1360  }
1361  else
1362  {
1363    if(can==1)
1364    {
1365      // COMPUTING THE HOMOGOENIZED IDEAL
1366      if(comment>0){string("Homogenizing the whole ideal: option can=1");}
1367      list RRL=ringlist(RR);
1368      RRL[3][1][1]="dp";
1369      def Pa=ring(RRL[1]);
1370      list Lx;
1371      Lx[1]=0;
1372      Lx[2]=RRL[2]+RRL[1][2];
1373      Lx[3]=RRL[1][3];
1374      Lx[4]=RRL[1][4];
1375      RRL[1]=0;
1376      def D=ring(RRL);
1377      def RP=D+Pa;
1378      setring(RP);
1379      def B1=imap(RR,B);
1380      option(redSB);
1381      B1=std(B1);
1382      setring(RR);
1383      def B2=imap(RP,B1);
1384    }
1385    else
1386    { // (can=0)
1387       if(comment>0){string("Homogenizing the basis: option can=0");}
1388      def B2=B;
1389    }
1390    // COMPUTING HOMOGENIZED CGS
1391    poly @t;
1392    ring H=0,@t,dp;
1393    def RH=RR+H;
1394    setring(RH);
1395    setglobalrings();
1396    def BH=imap(RR,B2);
1397    def LH=imap(RR,LL);
1398    for (i=1;i<=size(BH);i++)
1399    {
1400      BH[i]=homog(BH[i],@t);
1401    }
1402    if (comment>=1){string("Homogenized system = "); BH;}
1403    def GSH=KSW(BH,LH);
1404    setglobalrings();
1405    // DEHOMOGENIZING THE RESULT
1406    if(out==0)
1407    {
1408      for (i=1;i<=size(GSH);i++)
1409      {
1410        GSH[i][1]=subst(GSH[i][1],@t,1);
1411        for(j=1;j<=size(GSH[i][2]);j++)
1412        {
1413          GSH[i][2][j][2]=subst(GSH[i][2][j][2],@t,1);
1414        }
1415      }
1416    }
1417    else
1418    {
1419      for (i=1;i<=size(GSH);i++)
1420      {
1421        GSH[i][3]=subst(GSH[i][3],@t,1);
1422        GSH[i][7]=subst(GSH[i][7],@t,1);
1423      }
1424    }
1425    setring(RR);
1426    def GS=imap(RH,GSH);
1427    }
1428
1429
1430    setglobalrings();
1431    if(out==0)
1432    {
1433      for (i=1;i<=size(GS);i++)
1434      {
1435        GS[i][1]=postredgb(mingb(GS[i][1]));
1436        for(j=1;j<=size(GS[i][2]);j++)
1437        {
1438          GS[i][2][j][2]=postredgb(mingb(GS[i][2][j][2]));
1439        }
1440      }
1441    }
1442    else
1443    {
1444      for (i=1;i<=size(GS);i++)
1445      {
1446        if(GS[i][2]==1)
1447        {
1448          GS[i][3]=postredgb(mingb(GS[i][3]));
1449          GS[i][7]=postredgb(mingb(GS[i][7]));
1450        }
1451      }
1452    }
1453  }
1454  if(defined(@P)){kill @P; kill @R; kill @RP;}
1455  return(GS);
1456}
1457example
1458{ "EXAMPLE:"; echo = 2;
1459  "Casas conjecture for degree 4";
1460  ring R=(0,a0,a1,a2,a3,a4),(x1,x2,x3),dp;
1461  ideal F=x1^4+(4*a3)*x1^3+(6*a2)*x1^2+(4*a1)*x1+(a0),
1462          x1^3+(3*a3)*x1^2+(3*a2)*x1+(a1),
1463          x2^4+(4*a3)*x2^3+(6*a2)*x2^2+(4*a1)*x2+(a0),
1464          x2^2+(2*a3)*x2+(a2),
1465          x3^4+(4*a3)*x3^3+(6*a2)*x3^2+(4*a1)*x3+(a0),
1466          x3+(a3);
1467  cgsdr(F);
1468}
1469
1470// input:  internal routine called by cgsdr at the end to group the
1471//         lpp segments and improve the output
1472// output: grouped segments by lpp obtained in cgsdr
1473proc grsegments(list T)
1474{
1475  int i;
1476  list L;
1477  list lpp;
1478  list lp;
1479  list ls;
1480  int n=size(T);
1481  lpp[1]=T[n][1];
1482  L[1]=list(lpp[1],list(list(T[n][2],T[n][3],T[n][4])));
1483  if (n>1)
1484  {
1485    for (i=1;i<=size(T)-1;i++)
1486    {
1487      lp=memberpos(T[n-i][1],lpp);
1488      if(lp[1]==1)
1489      {
1490        ls=L[lp[2]][2];
1491        ls[size(ls)+1]=list(T[n-i][2],T[n-i][3],T[n-i][4]);
1492        L[lp[2]][2]=ls;
1493      }
1494      else
1495      {
1496        lpp[size(lpp)+1]=T[n-i][1];
1497        L[size(L)+1]=list(T[n-i][1],list(list(T[n-i][2],T[n-i][3],T[n-i][4])));
1498      }
1499    }
1500  }
1501  return(L);
1502}
1503
1504// idcontains
1505// input: ideal p, ideal q
1506// output: 1 if p contains q,  0 otherwise
1507proc idcontains(ideal p, ideal q)
1508{
1509  int t; int i;
1510  t=1; i=1;
1511  def RR=basering;
1512  setring(@P);
1513  def P=imap(RR,p);
1514  def Q=imap(RR,q);
1515  attrib(P,"isSB",1);
1516  poly r;
1517  while ((t) and (i<=size(Q)))
1518  {
1519    r=reduce(Q[i],P);
1520    if (r!=0){t=0;}
1521    i++;
1522  }
1523  setring(RR);
1524  return(t);
1525}
1526
1527// selectminindeals
1528//   given a list of ideals returns the list of integers corresponding
1529//   to the minimal ideals in the list
1530// input: L (list of ideals)
1531// output: the list of integers corresponding to the minimal ideals in L
1532proc selectminideals(list L)
1533{
1534  if (size(L)==0){return(L)};
1535  def RR=basering;
1536  setring(@P);
1537  def Lp=imap(RR,L);
1538  int i; int j; int t; intvec notsel;
1539  list P;
1540  for (i=1;i<=size(Lp);i++)
1541  {
1542    if(memberpos(i,notsel)[1])
1543    {
1544      i++;
1545      if(i>size(Lp)){break;}
1546    }
1547    t=1;
1548    j=1;
1549    while ((t) and (j<=size(Lp)))
1550    {
1551      if (i==j){j++;}
1552      if ((j<=size(Lp)) and (memberpos(j,notsel)[1]==0))
1553      {
1554
1555        if (idcontains(Lp[i],Lp[j]))
1556        {
1557          notsel[size(notsel)+1]=i;
1558          t=0;
1559        }
1560      }
1561      j++;
1562    }
1563    if (t){P[size(P)+1]=i;}
1564  }
1565  setring(RR);
1566  return(P);
1567}
1568
1569// LCUnion
1570// Given a list of the P-representations of locally closed segments
1571// for which we know that the union is also locally closed
1572// it returns the P-representation of its union
1573// input:  L list of segments in P-representation
1574//      ((p_j^i,(p_j1^i,...,p_jk_j^i | j=1..t_i)) | i=1..s )
1575//      where i represents a segment
1576// output: P-representation of the union
1577//       ((P_j,(P_j1,...,P_jk_j | j=1..t)))
1578proc LCUnion(list LL)
1579{
1580  def RR=basering;
1581  setring(@P);
1582  def L=imap(RR,LL);
1583  int i; int j; int k; list H; list C; list T;
1584  list L0; list P0; list P; list Q0; list Q;
1585  for (i=1;i<=size(L);i++)
1586  {
1587    for (j=1;j<=size(L[i]);j++)
1588    {
1589      P0[size(P0)+1]=L[i][j][1];
1590      L0[size(L0)+1]=intvec(i,j);
1591    }
1592  }
1593  Q0=selectminideals(P0);
1594  for (i=1;i<=size(Q0);i++)
1595  {
1596    Q[i]=L0[Q0[i]];
1597    P[i]=L[Q[i][1]][Q[i][2]];
1598  }
1599  // P is the list of the maximal components of the union
1600  //   with the corresponding initial holes.
1601  // Q is the list of intvec positions in L of the first element of the P's
1602  //   Its elements give (num of segment, num of max component (=min ideal))
1603  for (k=1;k<=size(Q);k++)
1604  {
1605    H=P[k][2]; // holes of P[k][1]
1606    for (i=1;i<=size(L);i++)
1607    {
1608      if (i!=Q[k][1])
1609      {
1610        for (j=1;j<=size(L[i]);j++)
1611        {
1612          C[size(C)+1]=L[i][j];
1613        }
1614      }
1615    }
1616    T[size(T)+1]=list(Q[k],P[k][1],addpart(H,C));
1617  }
1618  setring(RR);
1619  def TT=imap(@P,T);
1620  return(TT);
1621}
1622
1623// Called by LCUnion to modify the holes of a primepart of the union
1624// by the addition of the segments that do not correspond to that part
1625// Works on @P ring.
1626// Input:
1627//   H=(p_i1,..,p_is) the holes of a component to be transformed by the addition of
1628//        the segments C that do not correspond to that component
1629//   C=((q_1,(q_11,..,q_1l_1)),..,(q_k,(q_k1,..,q_kl_k)))
1630//        the list of segments to be added to the holes
1631proc addpart(list H, list C)
1632{
1633  list Q; int i; int j; int k; int l; int t; int t1;
1634  Q=H; intvec notQ; list QQ; list addq;
1635  ideal q;
1636  i=1;
1637  while (i<=size(Q))
1638  {
1639    if (memberpos(i,notQ)[1]==0)
1640    {
1641      q=Q[i];
1642      t=1; j=1;
1643      while ((t) and (j<=size(C)))
1644      {
1645        if (equalideals(q,C[j][1]))
1646        {
1647          t=0;
1648          for (k=1;k<=size(C[j][2]);k++)
1649          {
1650            t1=1;
1651            //kill addq;
1652            //list addq;
1653            l=1;
1654            while((t1) and (l<=size(Q)))
1655            {
1656              if ((l!=i) and (memberpos(l,notQ)[1]==0))
1657              {
1658                if (idcontains(C[j][2][k],Q[l]))
1659                {
1660                  t1=0;
1661                }
1662              }
1663              l++;
1664            }
1665            if (t1)
1666            {
1667              addq[size(addq)+1]=C[j][2][k];
1668            }
1669          }
1670          if((size(notQ)==1) and (notQ[1]==0)){notQ[1]=i;}
1671          else {notQ[size(notQ)+1]=i;}
1672        }
1673        j++;
1674      }
1675      if (size(addq)>0)
1676      {
1677        for (k=1;k<=size(addq);k++)
1678        {
1679          Q[size(Q)+1]=addq[k];
1680        }
1681        kill addq;
1682        list addq;
1683      }
1684      //print("Q="); Q; print("notQ="); notQ;
1685    }
1686    i++;
1687  }
1688  for (i=1;i<=size(Q);i++)
1689  {
1690    if(memberpos(i,notQ)[1]==0)
1691    {
1692      QQ[size(QQ)+1]=Q[i];
1693    }
1694  }
1695  if (size(QQ)==0){QQ[1]=ideal(1);}
1696  return(addpartfine(QQ,C));
1697}
1698
1699// Called by addpart to finish the modification of the holes of a primepart
1700// of the union by the addition of the segments that do not correspond to
1701// that part.
1702// Works on @P ring.
1703proc addpartfine(list H, list C0)
1704{
1705  int i; int j; int k; int te; intvec notQ; int l; list sel; int used;
1706  intvec jtesC;
1707  if ((size(H)==1) and (equalideals(H[1],ideal(1)))){return(H);}
1708  if (size(C0)==0){return(H);}
1709  def RR=basering;
1710  setring(@P);
1711  list newQ; list nQ; list Q; list nQ1; list Q0;
1712  def Q1=imap(RR,H);
1713  //Q1=sortlistideals(Q1);
1714  def C=imap(RR,C0);
1715  while(equallistideals(Q0,Q1)==0)
1716  {
1717    Q0=Q1;
1718    i=0;
1719    Q=Q1;
1720    kill notQ; intvec notQ;
1721    while(i<size(Q))
1722    {
1723      i++;
1724      for(j=1;j<=size(C);j++)
1725      {
1726        te=idcontains(Q[i],C[j][1]);
1727        if(te)
1728        {
1729          for(k=1;k<=size(C[j][2]);k++)
1730          {
1731            if(idcontains(Q[i],C[j][2][k]))
1732            {
1733              te=0; break;
1734            }
1735          }
1736          if (te)
1737          {
1738            used++;
1739            if ((size(notQ)==1) and (notQ[1]==0)){notQ[1]=i;}
1740            else{notQ[size(notQ)+1]=i;}
1741            kill newQ; list newQ;
1742            for(k=1;k<=size(C[j][2]);k++)
1743            {
1744              nQ=minGTZ(Q[i]+C[j][2][k]);
1745              for(l=1;l<=size(nQ);l++)
1746              {
1747                option(redSB);
1748                nQ[l]=std(nQ[l]);
1749                newQ[size(newQ)+1]=nQ[l];
1750              }
1751            }
1752            sel=selectminideals(newQ);
1753            kill nQ1; list nQ1;
1754            for(l=1;l<=size(sel);l++)
1755            {
1756              nQ1[l]=newQ[sel[l]];
1757            }
1758            newQ=nQ1;
1759            for(l=1;l<=size(newQ);l++)
1760            {
1761              Q[size(Q)+1]=newQ[l];
1762            }
1763            break;
1764          }
1765        }
1766      }
1767    }
1768    kill Q1; list Q1;
1769    for(i=1;i<=size(Q);i++)
1770    {
1771      if(memberpos(i,notQ)[1]==0)
1772      {
1773        Q1[size(Q1)+1]=Q[i];
1774      }
1775    }
1776    sel=selectminideals(Q1);
1777    kill nQ1; list nQ1;
1778    for(l=1;l<=size(sel);l++)
1779    {
1780      nQ1[l]=Q1[sel[l]];
1781    }
1782    Q1=nQ1;
1783  }
1784  setring(RR);
1785  //if(used>0){string("addpartfine was ", used, " times used");}
1786  return(imap(@P,Q1));
1787}
1788
1789// specswellCrep
1790// input:
1791//   given two corresponding polynomials g1 and g2 with the same lpp
1792//   g1 belonging to the basis in the segment ida1,idb1
1793//   g2 belonging to the basis in the segment ida2,idb2
1794// output:
1795//   1 if g1 spezializes well to g2 on the whole (ida2,idb2) segment
1796//   0 if not
1797proc specswellCrep(poly g1, poly g2, ideal ida2)
1798{
1799  poly S;
1800  S=leadcoef(g2)*g1-leadcoef(g1)*g2;
1801  def RR=basering;
1802  setring(@RPt);
1803  def SR=imap(RR,S);
1804  def ida2R=imap(RR,ida2);
1805  attrib(ida2R,"isSB",1);
1806  poly S2R=reduce(SR,ida2R);
1807  setring(RR);
1808  def S2=imap(@RPt,S2R);
1809  if (S2==0){return(1);}   // and (nonnullCrep(leadcoef(g1),ida2,idb2))
1810  else {return(0);}
1811}
1812
1813// gcover
1814// input: ideal F: a generating set of a homogeneous ideal in Q[a][x]
1815//    list #: optional
1816// output: the list
1817//   S=((lpp, generic basis, Prep, Crep),..,(lpp, generic basis, Prep, Crep))
1818//      where a Prep is ( (p1,(p11,..,p1k_1)),..,(pj,(pj1,..,p1k_j)) )
1819//            a Crep is ( ida, idb )
1820proc gcover(ideal F,list #)
1821{
1822  int i; int j; int k; ideal lpp; list GPi2; list pairspP; ideal B; int ti;
1823  int i1; int tes; int j1; int selind; int i2; int m;
1824  list prep; list crep; list LCU; poly p; poly lcp; ideal FF;
1825  list lpi;
1826  string lpph;
1827  list L=#;
1828  int canop=1;
1829  int extop=1;
1830  int repop=0;
1831  ideal E=ideal(0);;
1832  ideal N=ideal(1);;
1833  int comment;
1834  for(i=1;i<=size(L) div 2;i++)
1835  {
1836    if(L[2*i-1]=="can"){canop=L[2*i];}
1837    else
1838    {
1839      if(L[2*i-1]=="ext"){extop=L[2*i];}
1840      else
1841      {
1842        if(L[2*i-1]=="rep"){repop=L[2*i];}
1843        else
1844        {
1845          if(L[2*i-1]=="null"){E=L[2*i];}
1846          else
1847          {
1848            if(L[2*i-1]=="nonnull"){N=L[2*i];}
1849            else
1850            {
1851              if (L[2*i-1]=="comment"){comment=L[2*i];}
1852            }
1853          }
1854        }
1855      }
1856    }
1857  }
1858  list GS; list GP;
1859  def RR=basering;
1860  GS=cgsdr(F,L); // "null",NW[1],"nonnull",NW[2],"cgs",CGS,"comment",comment);
1861  setglobalrings();
1862  int start=timer;
1863  GP=GS;
1864  ideal lppr;
1865  list LL;
1866  list S;
1867  poly sp;
1868  ideal BB;
1869  for (i=1;i<=size(GP);i++)
1870  {
1871    kill LL;
1872    list LL;
1873    lpp=GP[i][1];
1874    GPi2=GP[i][2];
1875    lpph=GP[i][3];
1876    kill pairspP; list pairspP;
1877    for(j=1;j<=size(GPi2);j++)
1878    {
1879      pairspP[size(pairspP)+1]=GPi2[j][3];
1880    }
1881    LCU=LCUnion(pairspP);
1882    kill prep; list prep;
1883    for(k=1;k<=size(LCU);k++)
1884    {
1885      prep[k]=list(LCU[k][2],LCU[k][3]);
1886      B=GPi2[LCU[k][1][1]][2]; // ATENTION last 1 has been changed to [2]
1887      LCU[k][1]=B;
1888    }
1889    //"Deciding if combine is needed";
1890    kill BB;
1891    ideal BB;
1892    tes=1; m=1;
1893    while((tes) and (m<=size(LCU[1][1])))
1894    {
1895      j=1;
1896      while((tes) and (j<=size(LCU)))
1897      {
1898        k=1;
1899        while((tes) and (k<=size(LCU)))
1900        {
1901          if(j!=k)
1902          {
1903            sp=pnormalf(pspol(LCU[j][1][m],LCU[k][1][m]),LCU[k][2],N);
1904            if(sp!=0){tes=0;}
1905          }
1906          k++;
1907        }        //setglobalrings();
1908        if(tes)
1909        {
1910          BB[m]=LCU[j][1][m];
1911        }
1912        j++;
1913      }
1914      if(tes==0){break;}
1915      m++;
1916    }
1917    crep=PtoCrep(prep);
1918    if(tes==0)
1919    {
1920      // combine is needed
1921      kill B; ideal B;
1922      for (j=1;j<=size(LCU);j++)
1923      {
1924        LL[j]=LCU[j][2];
1925      }
1926      if (size(LCU)>1)
1927      {
1928        FF=precombint(LL);
1929      }
1930      for (k=1;k<=size(lpp);k++)
1931      {
1932        kill L; list L;
1933        for (j=1;j<=size(LCU);j++)
1934        {
1935          L[j]=list(LCU[j][2],LCU[j][1][k]);
1936        }
1937        if (size(LCU)>1)
1938        {
1939          B[k]=combine(L,FF);
1940        }
1941        else{B[k]=L[1][2];}
1942      }
1943    }
1944    else{B=BB;}
1945    for(j=1;j<=size(B);j++)
1946    {
1947      B[j]=pnormalf(B[j],crep[1],N);
1948    }
1949    S[i]=list(lpp,B,prep,crep,lpph);
1950    if(comment>=1)
1951    {
1952      lpi[size(lpi)+1]=string("[",i,"]");
1953      lpi[size(lpi)+1]=S[i][1];
1954    }
1955  }
1956  if(comment>=1)
1957  {
1958    string("Time in LCUnion + combine = ",timer-start);
1959    if(comment>=2){string("lpp=",lpi)};
1960  }
1961  if(defined(@P)==1){kill @P; kill @RP; kill @R;}
1962  return(S);
1963}
1964
1965// grobcov
1966// input:
1967//    ideal F: a parametric ideal in Q[a][x], where a are the parameters
1968//             and x the variables
1969//    list #: (options) list("null",N,"nonnull",W,"can",0-1,ext",0-1, "rep",0-1-2)
1970//            where
1971//            N is the null conditions ideal (if desired)
1972//            W is the ideal of non-null conditions (if desired)
1973//            The value of \"can\"i s 1 by default and can be set to 0 if we do not
1974//            need to obtain the canonical GC, but only a GC.
1975//            The value of \"ext\" is 0 by default and so the generic representation
1976//             of the bases is given. It can be set to 1, and then the full
1977//             representation of the bases is given.
1978//            The value of \"rep\" is 0 by default, and then the segments
1979//            are given in canonical P-representation. It can be set to 1
1980//            and then they are given in canonical C-representation.
1981//            If it is set to 2, then both representations are given.
1982// output:
1983//    list S: ((lpp,basis,(idp_1,(idp_11,..,idp_1s_1))), ..
1984//             (lpp,basis,(idp_r,(idp_r1,..,idp_rs_r))) ) where
1985//            each element of S corresponds to a lpp-segment
1986//            given by the lpp, the basis, and the P-representation of the segment
1987proc grobcov(ideal F,list #)
1988"USAGE:   grobcov(F); This is the fundamental routine of the
1989          library. It computes the Groebner cover of a parametric ideal
1990          (see (*) Montes A., Wibmer M., Groebner Bases for Polynomial
1991          Systems with parameters. JSC 45 (2010) 1391-1425.)
1992          The Groebner cover of a parametric ideal consist of a set of
1993          pairs(S_i,B_i), where the S_i are disjoint locally closed
1994          segments of the parameter space, and the B_i are the reduced
1995          Groebner bases of the ideal on every point of S_i.
1996
1997          The ideal F must be defined on a parametric ring Q[a][x].
1998          Options: To modify the default options, pair of arguments
1999          -option name, value- of valid options must be added to the call.
2000
2001          Options:
2002            \"null\",ideal E: The default is (\"null\",ideal(0)).
2003            \"nonnull\",ideal N: The default (\"nonnull\",ideal(1)).
2004                When options \"null\" and/or \"nonnull\" are given, then
2005                the parameter space is restricted to V(E)\V(N).
2006            \"can\",0-1: The default is (\"can\",1). With the default option
2007                the homogenized ideal is computed before obtaining the
2008                Groebner cover, so that the result is the canonical
2009                Groebner cover. Setting (\"can\",0) only homogenizes the
2010                basis so the result is not exactly canonical, but the
2011                computation is shorter.
2012            \"ext\",0-1: The default is (\"ext\",0). With the default
2013                (\"ext\",0), only the generic representation is computed
2014                (single polynomials, but not specializing to non-zero at
2015                each point of the segment. With option (\"ext\",1) the
2016                full representation of the bases is computed (possible
2017                shaves) and sometimes a simpler result is obtained.
2018            \"rep\",0-1-2: The default is (\"rep\",0) and then the segments
2019                are given in canonical P-representation. Option (\"rep\",1)
2020                represents the segments in canonical C-representation,
2021                and option (\"rep\",2) gives both representations.
2022            \"comment\",0-3: The default is (\"comment\",0). Setting
2023                \"comment\" higher will provide information about the
2024                development of the computation.
2025          One can give none or whatever of these options.
2026RETURN:   The list
2027          (
2028           (lpp_1,basis_1,segment_1,lpph_1),
2029           ...
2030           (lpp_s,basis_s,segment_s,lpph_s)
2031          )
2032
2033          The lpp are constant over a segment and correspond to the
2034          set of lpp of the reduced Groebner basis for each point
2035          of the segment.
2036          The lpph corresponds to the lpp of the homogenized ideal
2037          and is different for each segment. It is given as a string.
2038
2039          Basis: to each element of lpp corresponds an I-regular function given
2040          in full representation (by option (\"ext\",1)) or in
2041          generic representation (default option (\"ext\",0)). The
2042          I-regular function is the corresponding element of the reduced
2043          Groebner basis for each point of the segment with the given lpp.
2044          For each point in the segment, the polynomial or the set of
2045          polynomials representing it, if they do not specialize to 0,
2046          then after normalization, specializes to the corresponding
2047          element of the reduced Groebner basis. In the full representation
2048          at least one of the polynomials representing the I-regular
2049          function specializes to non-zero.
2050
2051          With the default option (\"rep\",0) the representation of the
2052          segment is the P-representation.
2053          With option (\"rep\",1) the representation of the segment is
2054          the C-representation.
2055          With option (\"rep\",2) both representations of the segment are
2056          given.
2057
2058          The P-representation of a segment is of the form
2059          ((p_1,(p_11,..,p_1k1)),..,(p_r,(p_r1,..,p_rkr))
2060          representing the segment U_i (V(p_i) \ U_j (V(p_ij))),
2061          where the p's are prime ideals.
2062
2063          The C-representation of a segment is of the form
2064          (E,N) representing V(E)\V(N), and the ideals E and N are
2065          radical and N contains E.
2066
2067NOTE: The basering R, must be of the form Q[a][x], a=parameters,
2068          x=variables, and should be defined previously. The ideal must
2069          be defined on R.
2070KEYWORDS: Groebner cover, parametric ideal, canonical, discussion of
2071          parametric ideal.
2072EXAMPLE:  grobcov; shows an example"
2073{
2074  list S; int i; int ish=1; list GBR; list BR; int j; int k;
2075  ideal idp; ideal idq; int s; ideal ext; list SS;
2076  ideal E; ideal N; int canop;  int extop; int repop;
2077  int comment=0; int m;
2078  def RR=basering;
2079  setglobalrings();
2080  list L0=#;
2081  int out=0;
2082  L0[size(L0)+1]="res"; L0[size(L0)+1]=ideal(1);
2083  // default options
2084  int start=timer;
2085  E=ideal(0);
2086  N=ideal(1);
2087  canop=1; // canop=0 for homogenizing the basis but not the ideal (not canonical)
2088           // canop=1 for working with the homogenized ideal
2089  repop=0; // repop=0 for representing the segments in Prep
2090           // repop=1 for representing the segments in Crep
2091           // repop=2 for representing the segments in Prep and Crep
2092  extop=0; // extop=0 if only generic representation of the bases are to be computed
2093           // extop=1 if the full representation of the bases are to be computed
2094  for(i=1;i<=size(L0) div 2;i++)
2095  {
2096    if(L0[2*i-1]=="can"){canop=L0[2*i];}
2097    else
2098    {
2099      if(L0[2*i-1]=="ext"){extop=L0[2*i];}
2100      else
2101      {
2102        if(L0[2*i-1]=="rep"){repop=L0[2*i];}
2103        else
2104        {
2105          if(L0[2*i-1]=="null"){E=L0[2*i];}
2106          else
2107          {
2108            if(L0[2*i-1]=="nonnull"){N=L0[2*i];}
2109            else
2110            {
2111              if (L0[2*i-1]=="comment"){comment=L0[2*i];}
2112            }
2113          }
2114        }
2115      }
2116    }
2117  }
2118  if(not((canop==0) or (canop==1)))
2119  {
2120    string("Option can = ",canop," is not supported. It is changed to can = 1");
2121    canop=1;
2122  }
2123  for(i=1;i<=size(L0) div 2;i++)
2124  {
2125    if(L0[2*i-1]=="can"){L0[2*i]=canop;}
2126  }
2127  if ((printlevel) and (comment==0)){comment=printlevel;}
2128  list LL;
2129  LL[1]="can";     LL[2]=canop;
2130  LL[3]="comment"; LL[4]=comment;
2131  LL[5]="out";     LL[6]=0;
2132  LL[7]="null";    LL[8]=E;
2133  LL[9]="nonnull"; LL[10]=N;
2134  LL[11]="ext";    LL[12]=extop;
2135  LL[13]="rep";    LL[14]=repop;
2136  if (comment>=1)
2137  {
2138    string("Begin grobcov with options: ",LL);
2139  }
2140  kill S;
2141  def S=gcover(F,LL);
2142  // NOW extend
2143  if(extop)
2144  {
2145    S=extend(S,LL);
2146  }
2147  else
2148  {
2149    // NOW representation of the segments by option repop
2150    list Si; list nS;
2151    if(repop==0)
2152    {
2153      for(i=1;i<=size(S);i++)
2154      {
2155        Si=list(S[i][1],S[i][2],S[i][3],S[i][5]);
2156        nS[size(nS)+1]=Si;
2157      }
2158      kill S;
2159      def S=nS;
2160    }
2161    else
2162    {
2163      if(repop==1)
2164      {
2165        for(i=1;i<=size(S);i++)
2166        {
2167          Si=list(S[i][1],S[i][2],S[i][4],S[i][5]);
2168          nS[size(nS)+1]=Si;
2169        }
2170        kill S;
2171        def S=nS;
2172      }
2173      else
2174      {
2175        for(i=1;i<=size(S);i++)
2176        {
2177          Si=list(S[i][1],S[i][2],S[i][3],S[i][4],S[i][5]);
2178          nS[size(nS)+1]=Si;
2179        }
2180        kill S;
2181        def S=nS;
2182      }
2183    }
2184  }
2185  if (comment>=1)
2186  {
2187    string("Time in grobcov = ", timer-start);
2188    string("Number of segments of grobcov = ", size(S));
2189  }
2190  if(defined(@P)==1){kill @R; kill @P; kill @RP;}
2191  return(S);
2192}
2193example
2194{ "EXAMPLE:"; echo = 2;
2195  "Casas conjecture for degree 4";
2196  ring R=(0,a0,a1,a2,a3,a4),(x1,x2,x3),dp;
2197  ideal F=x1^4+(4*a3)*x1^3+(6*a2)*x1^2+(4*a1)*x1+(a0),
2198          x1^3+(3*a3)*x1^2+(3*a2)*x1+(a1),
2199          x2^4+(4*a3)*x2^3+(6*a2)*x2^2+(4*a1)*x2+(a0),
2200          x2^2+(2*a3)*x2+(a2),
2201          x3^4+(4*a3)*x3^3+(6*a2)*x3^2+(4*a1)*x3+(a0),
2202          x3+(a3);
2203  grobcov(F);
2204}
2205
2206// input. GC the grobcov of an ideal in generic representation of the
2207//        bases computed with option option ("rep",2).
2208// output The grobcov in full representation.
2209// option ("comment",1) shows the time.
2210proc extend(list GC, list #);
2211"USAGE:   extend(GC); When the grobcov of an ideal has been computed
2212          with the default option (\"ext\",0) and the explicit option
2213          (\"rep\",2) (which is not the default), then one can call
2214          extend (GC) (and options) to obtain the full representation
2215          of the bases. With the default option (\"ext\",0) only the
2216          generic representation of the bases are computed, and one can
2217          obtain the full representation using extend.
2218            \"rep\",0-1-2: The default is (\"rep\",0) and then the segments
2219                are given in canonical P-representation. Option (\"rep\",1)
2220                represents the segments in canonical C-representation,
2221                and option (\"rep\",2) gives both representations.
2222            \"comment\",0-1: The default is (\"comment\",0). Setting
2223                \"comment\" higher will provide information about the
2224                time used in the computation.
2225          One can give none or whatever of these options.
2226RETURN:   The list
2227          (
2228           (lpp_1,basis_1,segment_1,lpph_1),
2229           ...
2230           (lpp_s,basis_s,segment_s,lpph_s)
2231          )
2232
2233          The lpp are constant over a segment and correspond to the
2234          set of lpp of the reduced Groebner basis for each point
2235          of the segment.
2236          The lpph corresponds to the lpp of the homogenized ideal
2237          and is different for each segment. It is given as a string.
2238
2239          Basis: to each element of lpp corresponds an I-regular function given
2240          in full representation. The
2241          I-regular function is the corresponding element of the reduced
2242          Groebner basis for each point of the segment with the given lpp.
2243          For each point in the segment, the polynomial or the set of
2244          polynomials representing it, if they do not specialize to 0,
2245          then after normalization, specializes to the corresponding
2246          element of the reduced Groebner basis. In the full representation
2247          at least one of the polynomials representing the I-regular
2248          function specializes to non-zero.
2249
2250          With the default option (\"rep\",0) the segments are given
2251          in P-representation.
2252          With option (\"rep\",1) the segments are given
2253          in C-representation.
2254          With option (\"rep\",2) both representations of the segments are
2255          given.
2256
2257          The P-representation of a segment is of the form
2258          ((p_1,(p_11,..,p_1k1)),..,(p_r,(p_r1,..,p_rkr))
2259          representing the segment U_i (V(p_i) \ U_j (V(p_ij))),
2260          where the p's are prime ideals.
2261
2262          The C-representation of a segment is of the form
2263          (E,N) representing V(E)\V(N), and the ideals E and N are
2264          radical and N contains E.
2265
2266NOTE: The basering R, must be of the form Q[a][x], a=parameters,
2267          x=variables, and should be defined previously. The ideal must
2268          be defined on R.
2269KEYWORDS: Groebner cover, parametric ideal, canonical, discussion of
2270          parametric ideal, full representation.
2271EXAMPLE:  extend; shows an example"
2272{
2273  list L=#;
2274  list S=GC;
2275  ideal idp;
2276  ideal idq;
2277  int i; int j; int m; int s;
2278  m=0; i=1;
2279  while((i<=size(S)) and (m==0))
2280  {
2281    if(typeof(S[i][2])=="list"){m=1;}
2282    i++;
2283  }
2284  if(m==1){"Warning! grobcov has already extended bases"; return(S);}
2285  if(size(GC[1])!=5){"Warning! extend make sense only when grobcov has been called with options 'rep',2,'ext',0"; " "; return();}
2286  int repop=0;
2287  int start3=timer;
2288  int comment;
2289  for(i=1;i<=size(L) div 2;i++)
2290  {
2291    if(L[2*i-1]=="comment"){comment=L[2*i];}
2292    else
2293    {
2294      if(L[2*i-1]=="rep"){repop=L[2*i];}
2295    }
2296  }
2297  poly leadc;
2298  poly ext;
2299  int te=0;
2300  list SS;
2301  def R=basering;
2302  if (defined(@R)){te=1;}
2303  else{setglobalrings();}
2304  // Now extend
2305  for (i=1;i<=size(S);i++)
2306  {
2307    m=size(S[i][2]);
2308     for (j=1;j<=m;j++)
2309    {
2310      idp=S[i][4][1];
2311      idq=S[i][4][2];
2312      if (size(idp)>0)
2313      {
2314        leadc=leadcoef(S[i][2][j]);
2315        kill ext;
2316        def ext=extend0(S[i][2][j],idp,idq);
2317        if (typeof(ext)=="poly")
2318        {
2319          S[i][2][j]=pnormalf(ext,idp,idq);
2320        }
2321        else
2322        {
2323          if(size(ext)==1)
2324          {
2325            S[i][2][j]=ext[1];
2326          }
2327          else
2328          {
2329            kill SS; list SS;
2330            for(s=1;s<=size(ext);s++)
2331            {
2332              ext[s]=pnormalf(ext[s],idp,idq);
2333            }
2334            for(s=1;s<=size(S[i][2]);s++)
2335            {
2336              if(s!=j){SS[s]=S[i][2][s];}
2337              else{SS[s]=ext;}
2338            }
2339            S[i][2]=SS;
2340          }
2341        }
2342      }
2343    }
2344  }
2345  // NOW representation of the segments by option repop
2346  list Si; list nS;
2347  if (repop==0)
2348  {
2349    for(i=1;i<=size(S);i++)
2350    {
2351      Si=list(S[i][1],S[i][2],S[i][3],S[i][5]);
2352      nS[size(nS)+1]=Si;
2353    }
2354    S=nS;
2355  }
2356  else
2357  {
2358    if (repop==1)
2359    {
2360      for(i=1;i<=size(S);i++)
2361      {
2362        Si=list(S[i][1],S[i][2],S[i][4],S[i][5]);
2363        nS[size(nS)+1]=Si;
2364      }
2365      S=nS;
2366    }
2367    else
2368    {
2369      for(i=1;i<=size(S);i++)
2370      {
2371        Si=list(S[i][1],S[i][2],S[i][3],S[i][4],S[i][5]);
2372        nS[size(nS)+1]=Si;
2373      }
2374
2375    }
2376  }
2377  if(comment>=1){string("Time in extend = ",timer-start3);}
2378  if(te==0){kill @R; kill @RP; kill @P;}
2379  return(S);
2380}
2381example
2382{
2383  ring R=(0,a0,b0,c0,a1,b1,c1,a2,b2,c2),(x), dp;
2384  short=0;
2385  ideal S=a0*x^2+b0*x+c0,
2386          a1*x^2+b1*x+c1,
2387          a2*x^2+b2*x+c2;
2388  "System S="; S;
2389
2390  def GCS=grobcov(S,"rep",2,"comment",1);
2391  "grobcov(S,'rep',2,'comment',1)="; GCS;
2392  def FGC=extend(GCS,"rep",0,"comment",1);
2393  "Full representation="; FGC;
2394}
2395
2396
2397// nonzerodivisor
2398// input:
2399//    poly g in K[a],
2400//    list P=(p_1,..p_r) representing a minimal prime decomposition
2401// output
2402//    poly f such that f notin p_i for all i and
2403//           g-f in p_i for all i such that g notin p_i
2404proc nonzerodivisor(poly gr, list Pr)
2405{
2406  def RR=basering;
2407  setring(@P);
2408  def g=imap(RR,gr);
2409  def P=imap(RR,Pr);
2410  int i; int k;  list J; ideal F;
2411  def f=g;
2412  ideal Pi;
2413  for (i=1;i<=size(P);i++)
2414  {
2415    option(redSB);
2416    Pi=std(P[i]);
2417    //attrib(Pi,"isSB",1);
2418    if (reduce(g,Pi,1)==0){J[size(J)+1]=i;}
2419  }
2420  for (i=1;i<=size(J);i++)
2421  {
2422    F=ideal(1);
2423    for (k=1;k<=size(P);k++)
2424    {
2425      if (k!=J[i])
2426      {
2427        F=idint(F,P[k]);
2428      }
2429    }
2430    f=f+F[1];
2431  }
2432  setring(RR);
2433  def fr=imap(@P,f);
2434  return(fr);
2435}
2436
2437// deltai
2438// input:
2439//   int i:
2440//   list LPr: (p1,..,pr) of prime components of an ideal in K[a]
2441// output:
2442//   list (fr,fnr) of two polynomials that are equal on V(pi)
2443//       and fr=0 on V(P) \ V(pi), and fnr is nonzero on V(pj) for all j.
2444proc deltai(int i, list LPr)
2445{
2446  def RR=basering;
2447  setring(@P);
2448  def LP=imap(RR,LPr);
2449  int j; poly p;
2450  def F=ideal(1);
2451  poly f;
2452  poly fn;
2453  ideal LPi;
2454  for (j=1;j<=size(LP);j++)
2455  {
2456    if (j!=i)
2457    {
2458      F=idint(F,LP[j]);
2459    }
2460  }
2461  p=0; j=1;
2462  while ((p==0) and (j<=size(F)))
2463  {
2464    LPi=LP[i];
2465    attrib(LPi,"isSB",1);
2466    p=reduce(F[j],LPi);
2467    j++;
2468  }
2469  f=F[j-1];
2470  fn=nonzerodivisor(f,LP);
2471  setring(RR);
2472  def fr=imap(@P,f);
2473  def fnr=imap(@P,fn);
2474  return(list(fr,fnr));
2475}
2476
2477// combine
2478// input: a list of pairs ((p1,P1),..,(pr,Pr)) where
2479//    ideal pi is a prime component
2480//    poly Pi is the polynomial in Q[a][x] on V(pi)\ V(Mi)
2481//    (p1,..,pr) are the prime decomposition of the lpp-segment
2482//    list crep =(ideal ida,ideal idb): the Crep of the segment.
2483//    list Pci of the intersecctions of all pj except the ith one
2484// output:
2485//    poly P on an open and dense set of V(p_1 int ... p_r)
2486proc combine(list L, ideal F)
2487{
2488  // ATTENTION REVISE AND USE Pci and F
2489  int i; poly f;
2490  f=0;
2491  for(i=1;i<=size(L);i++)
2492  {
2493    f=f+F[i]*L[i][2];
2494  }
2495//   f=elimconstfac(f);
2496  f=primepartZ(f);
2497  return(f);
2498}
2499
2500// elimconstfac: eliminate the factors in the polynom f that are in K[a]
2501// input:
2502//   poly f:
2503//   list L: of components of the segment
2504// output:
2505//   poly f2  where the factors of f in K[a] that are non-null on any component
2506//   have been dropped from f
2507proc elimconstfac(poly f)
2508{
2509  int cond; int i; int j; int t;
2510  if (f==0){return(f);}
2511  def RR=basering;
2512  setring(@R);
2513  def ff=imap(RR,f);
2514  def l=factorize(ff,0);
2515  poly f1=1;
2516  for(i=2;i<=size(l[1]);i++)
2517  {
2518      f1=f1*(l[1][i])^(l[2][i]);
2519  }
2520  setring(RR);
2521  def f2=imap(@R,f1);
2522  return(f2);
2523};
2524
2525// nullin
2526// input:
2527//   poly f:  a polynomial in Q[a]
2528//   ideal P: an ideal in Q[a]
2529//   called from ring @R
2530// output:
2531//   t:  with value 1 if f reduces modulo P, 0 if not.
2532proc nullin(poly f,ideal P)
2533{
2534  int t;
2535  def RR=basering;
2536  setring(@P);
2537  def f0=imap(RR,f);
2538  def P0=imap(RR,P);
2539  attrib(P0,"isSB",1);
2540  if (reduce(f0,P0,1)==0){t=1;}
2541  else{t=0;}
2542  setring(RR);
2543  return(t);
2544}
2545
2546// monoms
2547proc monoms(poly f)
2548{
2549  list L;
2550  poly lm; poly lc; poly lp; poly Q; poly mQ;
2551  def p=f;
2552  int i=1;
2553  while (p!=0)
2554  {
2555    lm=lead(p);
2556    p=p-lm;
2557    lc=leadcoef(lm);
2558    lp=leadmonom(lm);
2559    L[size(L)+1]=list(lc,lp);
2560    i++;
2561  }
2562  return(L);
2563}
2564
2565// extend0
2566// input:
2567//   poly f: a generic polynomial in the basis
2568//   ideal idp: such that ideal(S)=idp
2569//   ideal idq: such that S=V(idp)\V(idq)
2570////   NW the list of ((N1,W1),..,(Ns,Ws)) of red-rep of the grouped
2571////      segments in the lpp-segment  NO MORE USED
2572// output:
2573proc extend0(poly f, ideal idp, ideal idq)
2574{
2575  matrix CC; poly Q; list NewMonoms;
2576  int i;  int j;  poly fout; ideal idout;
2577  list L=monoms(f);
2578  int nummonoms=size(L)-1;
2579  Q=L[1][1];
2580  if (nummonoms==0){return(f);}
2581  for (i=2;i<=size(L);i++)
2582  {
2583    CC=matrix(extendcoef(L[i][1],Q,idp,idq));
2584    NewMonoms[i-1]=list(CC,L[i][2]);
2585  }
2586  if (nummonoms==1)
2587  {
2588    for(j=1;j<=ncols(NewMonoms[1][1]);j++)
2589    {
2590      fout=NewMonoms[1][1][2,j]*L[1][2]+NewMonoms[1][1][1,j]*NewMonoms[1][2];
2591      //fout=pnormalf(fout,idp,W);
2592      if(ncols(NewMonoms[1][1])>1){idout[j]=fout;}
2593    }
2594    if(ncols(NewMonoms[1][1])==1){return(fout);} else{return(idout);}
2595  }
2596  else
2597  {
2598    list cfi;
2599    list coefs;
2600    for (i=1;i<=nummonoms;i++)
2601    {
2602      kill cfi; list cfi;
2603      for(j=1;j<=ncols(NewMonoms[i][1]);j++)
2604      {
2605        cfi[size(cfi)+1]=NewMonoms[i][1][2,j];
2606      }
2607      coefs[i]=cfi;
2608    }
2609    def indexpolys=findindexpolys(coefs);
2610    for(i=1;i<=size(indexpolys);i++)
2611    {
2612      fout=L[1][2];
2613      for(j=1;j<=nummonoms;j++)
2614      {
2615        fout=fout+(NewMonoms[j][1][1,indexpolys[i][j]])/(NewMonoms[j][1][2,indexpolys[i][j]])*NewMonoms[j][2];
2616      }
2617      fout=cleardenom(fout);
2618      if(size(indexpolys)>1){idout[i]=fout;}
2619    }
2620    if (size(indexpolys)==1){return(fout);} else{return(idout);}
2621  }
2622}
2623
2624// findindexpolys
2625// input:
2626//   list coefs=( (q11,..,q1r_1),..,(qs1,..,qsr_1) )
2627//               of denominators of the monoms
2628// output:
2629//   list ind=(v_1,..,v_t) of intvec
2630//        each intvec v=(i_1,..,is) corresponds to a polynomial in the sheaf
2631//        that will be built from it in extend procedure.
2632proc findindexpolys(list coefs)
2633{
2634  int i; int j; intvec numdens;
2635  for(i=1;i<=size(coefs);i++)
2636  {
2637    numdens[i]=size(coefs[i]);
2638  }
2639  def RR=basering;
2640  setring(@P);
2641  def coefsp=imap(RR,coefs);
2642  ideal cof; list combpolys; intvec v; int te; list mp;
2643  for(i=1;i<=size(coefsp);i++)
2644  {
2645    cof=ideal(0);
2646    for(j=1;j<=size(coefsp[i]);j++)
2647    {
2648      cof[j]=factorize(coefsp[i][j],3);
2649    }
2650    coefsp[i]=cof;
2651  }
2652  for(j=1;j<=size(coefsp[1]);j++)
2653  {
2654    v[1]=j;
2655    te=1;
2656    for (i=2;i<=size(coefsp);i++)
2657    {
2658      mp=memberpos(coefsp[1][j],coefsp[i]);
2659      if(mp[1])
2660      {
2661        v[i]=mp[2];
2662      }
2663      else{v[i]=0;}
2664    }
2665    combpolys[j]=v;
2666  }
2667  combpolys=reform(combpolys,numdens);
2668  setring(RR);
2669  return(combpolys);
2670}
2671
2672// extendcoef: given Q,P in K[a] where P/Q specializes on an open and dense subset
2673//      of the whole V(p1 int...int pr), it returns a basis of the module
2674//      of all syzygies equivalent to P/Q,
2675proc extendcoef(poly P, poly Q, ideal idp, ideal idq)
2676{
2677  def RR=basering;
2678  setring(@P);
2679  def PL=ringlist(@P);
2680  PL[3][1][1]="dp";
2681  def P1=ring(PL);
2682  setring(P1);
2683  ideal idp0=imap(RR,idp);
2684  option(redSB);
2685  qring q=std(idp0);
2686  poly P0=imap(RR,P);
2687  poly Q0=imap(RR,Q);
2688  ideal PQ=Q0,-P0;
2689  module C=syz(PQ);
2690  setring(@P);
2691  def idp1=imap(RR,idp);
2692  def idq1=imap(RR,idq);
2693  def C1=matrix(imap(q,C));
2694  def redC=selectregularfun(C1,idp1,idq1);
2695  setring(RR);
2696  def CC=imap(@P,redC);
2697  return(CC);
2698}
2699
2700// selectregularfun
2701// input:
2702//   list L of the polynomials matrix CC
2703//      (we assume that one of them is non-null on V(N)\V(M))
2704//   ideal N, ideal M: ideals representing the locally closed set V(N)\V(M)
2705// assume to work in @P
2706proc selectregularfun(matrix CC, ideal NN, ideal MM)
2707{
2708  int numcombused;
2709  def RR=basering;
2710  setring(@P);
2711  def C=imap(RR,CC);
2712  def N=imap(RR,NN);
2713  def M=imap(RR,MM);
2714  if (ncols(C)==1){return(C);}
2715
2716  int i; int j; int k; list c; intvec ci; intvec c0; intvec c1;
2717  list T; list T0; list T1; list LL; ideal N1;ideal M1; int te=0;
2718  for(i=1;i<=ncols(C);i++)
2719  {
2720    if((C[1,i]!=0) and (C[2,i]!=0))
2721    {
2722      if(c0==intvec(0)){c0[1]=i;}
2723      else{c0[size(c0)+1]=i;}
2724    }
2725  }
2726  def C1=submat(C,1..2,c0);
2727  for (i=1;i<=ncols(C1);i++)
2728  {
2729    c=comb(ncols(C1),i);
2730    for(j=1;j<=size(c);j++)
2731    {
2732      ci=c[j];
2733      numcombused++;
2734      if(i==1){N1=N+C1[2,j]; M1=M;}
2735      if(i>1)
2736      {
2737        kill c0; intvec c0 ; kill c1; intvec c1;
2738        c1=ci[size(ci)];
2739        for(k=1;k<size(ci);k++){c0[k]=ci[k];}
2740        T0=searchinlist(c0,LL);
2741        T1=searchinlist(c1,LL);
2742        N1=T0[1]+T1[1];
2743        M1=intersect(T0[2],T1[2]);
2744      }
2745      T=list(ci,PtoCrep(Prep(N1,M1)));
2746      LL[size(LL)+1]=T;
2747      if(equalideals(T[2][1],ideal(1))){te=1; break;}
2748    }
2749    if(te){break;}
2750  }
2751  ci=T[1];
2752  def Cs=submat(C1,1..2,ci);
2753  setring(RR);
2754  return(imap(@P,Cs));
2755}
2756
2757// searchinlist
2758// input:
2759//   intvec c:
2760//   list L=( (c1,T1),..(ck,Tk) )
2761//      where the c's are assumed to be intvects
2762// output:
2763//   object T with index c
2764proc searchinlist(intvec c,list L)
2765{
2766  int i; list T;
2767  for(i=1;i<=size(L);i++)
2768  {
2769    if (L[i][1]==c)
2770    {
2771      T=L[i][2];
2772      break;
2773    }
2774  }
2775  return(T);
2776}
2777
2778// comb: the list of combinations of elements (1,..n) of order p
2779proc comb(int n, int p)
2780{
2781  list L; list L0;
2782  intvec c; intvec d;
2783  int i; int j; int last;
2784  if ((n<0) or (n<p))
2785  {
2786    return(L);
2787  }
2788  if (p==1)
2789  {
2790    for (i=1;i<=n;i++)
2791    {
2792      c=i;
2793      L[size(L)+1]=c;
2794    }
2795    return(L);
2796  }
2797  else
2798  {
2799    L0=comb(n,p-1);
2800    for (i=1;i<=size(L0);i++)
2801    {
2802      c=L0[i]; d=c;
2803      last=c[size(c)];
2804      for (j=last+1;j<=n;j++)
2805      {
2806        d[size(c)+1]=j;
2807        L[size(L)+1]=d;
2808      }
2809    }
2810    return(L);
2811  }
2812}
2813
2814// selectminsheaves
2815// Input: L=((v_11,..,v_1k_1),..,(v_s1,..,v_sk_s))
2816//    where:
2817//    The s lists correspond to the s coefficients of the polynomial f
2818//    (v_i1,..,v_ik_i) correspond to the k_i intvec v_ij of the
2819//    spezializations of the jth rekpresentant (Q,P) of the ith coefficient
2820//    v_ij is an intvec of size equal to the number of little segments
2821//    forming the lpp-segment of 0,1, where 1 represents that it specializes
2822//    to non-zedro an the whole little segment and 0 if not.
2823// Output: S=(w_1,..,w_j)
2824//    where the w_l=(n_l1,..,n_ls) are intvec of length size(L), where
2825//    n_lt fixes which element of (v_t1,..,v_tk_t) is to be
2826//    choosen to form the tth (Q,P) for the lth element of the sheaf
2827//    representing the I-regular function.
2828// The selection is done to obtian the minimal number of elements
2829//    of the sheaf that specializes to non-null everywhere.
2830proc selectminsheaves(list L)
2831{
2832  list C=allsheaves(L);
2833  return(smsheaves(C[1],C[2]));
2834}
2835
2836// smsheaves
2837// Input:
2838//   list C of all the combrep
2839//   list L of the intvec that correesponds to each element of C
2840// Output:
2841//   list LL of the subsets of C that cover all the subsegments
2842//   (the union of the corresponding L(C) has all 1).
2843proc smsheaves(list C, list L)
2844{
2845  int i; int i0; intvec W;
2846  int nor; int norn;
2847  intvec p;
2848  int sp=size(L[1]); int j0=1;
2849  for (i=1;i<=sp;i++){p[i]=1;}
2850  while (p!=0)
2851  {
2852    i0=0; nor=0;
2853    for (i=1; i<=size(L); i++)
2854    {
2855      norn=numones(L[i],pos(p));
2856      if (nor<norn){nor=norn; i0=i;}
2857    }
2858    W[j0]=i0;
2859    j0++;
2860    p=actualize(p,L[i0]);
2861  }
2862  list LL;
2863  for (i=1;i<=size(W);i++)
2864  {
2865    LL[size(LL)+1]=C[W[i]];
2866  }
2867  return(LL);
2868}
2869
2870// allsheaves
2871// Input: L=((v_11,..,v_1k_1),..,(v_s1,..,v_sk_s))
2872//    where:
2873//    The s lists correspond to the s coefficients of the polynomial f
2874//    (v_i1,..,v_ik_i) correspond to the k_i intvec v_ij of the
2875//    spezializations of the jth rekpresentant (Q,P) of the ith coefficient
2876//    v_ij is an intvec of size equal to the number of little segments
2877//    forming the lpp-segment of 0,1, where 1 represents that it specializes
2878//    to non-zero on the whole little segment and 1 if not.
2879// Output:
2880//    (list LL, list LLS)  where
2881//    LL is the list of all combrep
2882//    LLS is the list of intvec of the corresponding elements of LL
2883proc allsheaves(list L)
2884{
2885  intvec V; list LL; intvec W; int r; intvec U;
2886  int i; int j; int k;
2887  int s=size(L[1][1]); // s = number of little segments of the lpp-segment
2888  list LLS;
2889  for (i=1;i<=size(L);i++)
2890  {
2891    V[i]=size(L[i]);
2892  }
2893  LL=combrep(V);
2894  for (i=1;i<=size(LL);i++)
2895  {
2896    W=LL[i];   // size(W)= number of coefficients of the polynomial
2897    kill U; intvec U;
2898    for (j=1;j<=s;j++)
2899    {
2900      k=1; r=1; U[j]=1;
2901      while((r==1) and (k<=size(W)))
2902      {
2903        if(L[k][W[k]][j]==0){r=0; U[j]=0;}
2904        k++;
2905      }
2906    }
2907    LLS[i]=U;
2908  }
2909  return(list(LL,LLS));
2910}
2911
2912// numones
2913// Input:
2914//   intvec v of (0,1) in each position
2915//   intvec pos: the positions to test
2916// Output:
2917//   int nor: the nuber of 1 of v in the positions given by pos.
2918proc numones(intvec v, intvec pos)
2919{
2920  int i; int n;
2921  for (i=1;i<=size(pos);i++)
2922  {
2923    if (v[pos[i]]==1){n++;}
2924  }
2925  return(n);
2926}
2927
2928// pos
2929// Input:  intvec p of zeros and ones
2930// Output: intvec W of the positions where p has ones.
2931proc pos(intvec p)
2932{
2933  int i;
2934  intvec W; int j=1;
2935  for (i=1; i<=size(p); i++)
2936  {
2937    if (p[i]==1){W[j]=i; j++;}
2938  }
2939  return(W);
2940}
2941
2942// actualize: actualizes zeroes of p
2943// Input:
2944//   intvec p: of zeroes and ones
2945//   intvec c: of zeroes and ones (of the same length)
2946// Output;
2947//   intvec pp: of zeroes and ones, where a 0 stays in pp[i] if either
2948//   already p[i]==0 or c[i]==1.
2949proc actualize(intvec p, intvec c)
2950{
2951  int i; intvec pp=p;
2952  for (i=1;i<=size(p);i++)
2953  {
2954    if ((pp[i]==1) and (c[i]==1)){pp[i]=0;}
2955  }
2956  return(pp);
2957}
2958
2959// combrep
2960// Input: V=(n_1,..,n_i)
2961// Output: L=(v_1,..,v_p) where p=prod_j=1^i (n_j)
2962//    is the list of all intvec v_j=(v_j1,..,v_ji) where 1<=v_jk<=n_i
2963proc combrep(intvec V)
2964{
2965  list L; list LL;
2966  int i; int j; int k;  intvec W;
2967  if (size(V)==1)
2968  {
2969    for (i=1;i<=V[1];i++)
2970    {
2971      L[i]=intvec(i);
2972    }
2973    return(L);
2974  }
2975  for (i=1;i<size(V);i++)
2976  {
2977    W[i]=V[i];
2978  }
2979  LL=combrep(W);
2980  for (i=1;i<=size(LL);i++)
2981  {
2982    W=LL[i];
2983    for (j=1;j<=V[size(V)];j++)
2984    {
2985      W[size(V)]=j;
2986      L[size(L)+1]=W;
2987    }
2988  }
2989  return(L);
2990}
2991
2992proc reducemodN(poly f,ideal E)
2993{
2994  def RR=basering;
2995  setring(@RPt);
2996  def fa=imap(RR,f);
2997  def Ea=imap(RR,E);
2998  attrib(Ea,"isSB",1);
2999  // option(redSB);
3000  // Ea=std(Ea);
3001  fa=reduce(fa,Ea);
3002  setring(RR);
3003  def f1=imap(@RPt,fa);
3004  return(f1);
3005}
3006
3007// intersp: computes the intersection of the ideals in S in @P
3008proc intersp(list S)
3009{
3010  def RR=basering;
3011  setring(@P);
3012  def SP=imap(RR,S);
3013  option(returnSB);
3014  def NP=intersect(SP[1..size(SP)]);
3015  setring(RR);
3016  return(imap(@P,NP));
3017}
3018
3019// radicalmember
3020proc radicalmember(poly f,ideal ida)
3021{
3022  int te;
3023  def RR=basering;
3024  setring(@P);
3025  def fp=imap(RR,f);
3026  def idap=imap(RR,ida);
3027  poly @t;
3028  ring H=0,@t,dp;
3029  def PH=@P+H;
3030  setring(PH);
3031  def fH=imap(@P,fp);
3032  def idaH=imap(@P,idap);
3033  idaH[size(idaH)+1]=1-@t*fH;
3034  option(redSB);
3035  def G=std(idaH);
3036  if (G==1){te=1;} else {te=0;}
3037  setring(RR);
3038  return(te);
3039}
3040
3041// NonNull: returns 1 if the poly f is nonnull on V(E)\V(N), 0 otherwise.
3042proc NonNull(poly f, ideal E, ideal N)
3043{
3044  int te=1; int i;
3045  def RR=basering;
3046  setring(@P);
3047  def fp=imap(RR,f);
3048  def Ep=imap(RR,E);
3049  def Np=imap(RR,N);
3050  ideal H;
3051  ideal Ef=Ep+fp;
3052  for (i=1;i<=size(Np);i++)
3053  {
3054    te=radicalmember(Np[i],Ef);
3055    if (te==0){break;}
3056  }
3057  setring(RR);
3058  return(te);
3059}
3060
3061// selectextendcoef
3062// input:
3063//    matrix CC: CC=(p_a1 .. p_ar_a)
3064//                  (q_a1 .. q_ar_a)
3065//            the matrix of elements of a coefficient in oo[a].
3066//    (ideal ida, ideal idb): the canonical representation of the segment S.
3067// output:
3068//    list caout
3069//            the minimum set of elements of CC needed such that at least one
3070//            of the q's is non-null on S, as well as the C-rep of of the
3071//            points where the q's are null on S.
3072//            The elements of caout are of the form (p,q,prep);
3073proc selectextendcoef(matrix CC, ideal ida, ideal idb)
3074{
3075  def RR=basering;
3076  setring(@P);
3077  def ca=imap(RR,CC);
3078  def E0=imap(RR,ida);
3079  ideal E;
3080  def N=imap(RR,idb);
3081  int r=ncols(ca);
3082  int i; int te=1; list com; int j; int k; intvec c; list prep;
3083  list cs; list caout;
3084  i=1;
3085  while ((i<=r) and (te))
3086  {
3087    com=comb(r,i);
3088    j=1;
3089    while((j<=size(com)) and (te))
3090    {
3091      E=E0;
3092      c=com[j];
3093      for (k=1;k<=i;k++)
3094      {
3095        E=E+ca[2,c[k]];
3096      }
3097      prep=Prep(E,N);
3098      if (i==1)
3099      {
3100        cs[j]=list(ca[1,j],ca[2,j],prep);
3101      }
3102      if ((size(prep)==1) and (equalideals(prep[1][1],ideal(1))))
3103      {
3104        te=0;
3105        for(k=1;k<=size(c);k++)
3106        {
3107          caout[k]=cs[c[k]];
3108        }
3109      }
3110      j++;
3111    }
3112    i++;
3113  }
3114  if (te){"error: extendcoef does not extend to the whole S";}
3115  setring(RR);
3116  return(imap(@P,caout));
3117}
3118
3119// input:
3120//   ideal E1: in some basering (depends only on the parameters)
3121//   ideal E2: in some basering (depends only on the parameters)
3122// output:
3123//   ideal Ep=E1+E2; computed in P
3124proc plusP(ideal E1,ideal E2)
3125{
3126  def RR=basering;
3127  setring(@P);
3128  def E1p=imap(RR,E1);
3129  def E2p=imap(RR,E2);
3130  def Ep=E1p+E2p;
3131  setring(RR);
3132  return(imap(@P,Ep));
3133}
3134
3135// reform
3136// input:
3137//   list combpolys: (v1,..,vs)
3138//      where vi are intvec.
3139//   output outcomb: (w1,..,wt)
3140//      whre wi are intvec.
3141//      All the vi without zeroes are in outcomb, and those with zeroes are
3142//         combined to form new intvec with the rest
3143proc reform(list combpolys, intvec numdens)
3144{
3145  list combp0; list combp1; int i; int j; int k; int l; list rest; intvec notfree;
3146  list free; intvec free1; int te; intvec v;  intvec w;
3147  int nummonoms=size(combpolys[1]);
3148  for(i=1;i<=size(combpolys);i++)
3149  {
3150    if(memberpos(0,combpolys[i])[1])
3151    {
3152      combp0[size(combp0)+1]=combpolys[i];
3153    }
3154    else {combp1[size(combp1)+1]=combpolys[i];}
3155  }
3156  for(i=1;i<=nummonoms;i++)
3157  {
3158    kill notfree; intvec notfree;
3159    for(j=1;j<=size(combpolys);j++)
3160    {
3161      if(combpolys[j][i]<>0)
3162      {
3163        if(notfree[1]==0){notfree[1]=combpolys[j][i];}
3164        else{notfree[size(notfree)+1]=combpolys[j][i];}
3165      }
3166    }
3167    kill free1; intvec free1;
3168    for(j=1;j<=numdens[i];j++)
3169    {
3170      if(memberpos(j,notfree)[1]==0)
3171      {
3172        if(free1[1]==0){free1[1]=j;}
3173        else{free1[size(free1)+1]=j;}
3174      }
3175      free[i]=free1;
3176    }
3177  }
3178  list amplcombp; list aux;
3179  for(i=1;i<=size(combp0);i++)
3180  {
3181    v=combp0[i];
3182    kill amplcombp; list amplcombp;
3183    amplcombp[1]=intvec(v[1]);
3184    for(j=2;j<=size(v);j++)
3185    {
3186      if(v[j]!=0)
3187      {
3188        for(k=1;k<=size(amplcombp);k++)
3189        {
3190          w=amplcombp[k];
3191          w[size(w)+1]=v[j];
3192          amplcombp[k]=w;
3193        }
3194      }
3195      else
3196      {
3197        kill aux; list aux;
3198        for(k=1;k<=size(amplcombp);k++)
3199        {
3200          for(l=1;l<=size(free[j]);l++)
3201          {
3202            w=amplcombp[k];
3203            w[size(w)+1]=free[j][l];
3204            aux[size(aux)+1]=w;
3205          }
3206        }
3207        amplcombp=aux;
3208      }
3209    }
3210    for(j=1;j<=size(amplcombp);j++)
3211    {
3212      combp1[size(combp1)+1]=amplcombp[j];
3213    }
3214  }
3215  return(combp1);
3216}
3217
3218// nonnullCrep
3219proc nonnullCrep(poly f0,ideal ida0,ideal idb0)
3220{
3221  int i;
3222  def RR=basering;
3223  setring(@P);
3224  def f=imap(RR,f0);
3225  def ida=imap(RR,ida0);
3226  def idb=imap(RR,idb0);
3227  def idaf=ida+f;
3228  int te=1;
3229  for(i=1;i<=size(idb);i++)
3230  {
3231    if(radicalmember(idb[i],idaf)==0)
3232    {
3233      te=0; break;
3234    }
3235  }
3236  setring(RR);
3237  return(te);
3238}
3239
3240// precombint
3241// input:  L: list of ideals (works in @P)
3242// output: F0: ideal of polys. F0[i] is a poly in the intersection of
3243//             all ideals in L except in the ith one, where it is not.
3244//             L=(p1,..,ps);  F0=(f1,..,fs);
3245//             F0[i] \in intersect_{j#i} p_i
3246proc precombint(list L)
3247{
3248  int i; int j; int tes;
3249  def RR=basering;
3250  setring(@P);
3251  list L0; list L1; list L2; list L3; ideal F;
3252  L0=imap(RR,L);
3253  L1[1]=L0[1]; L2[1]=L0[size(L0)];
3254  for (i=2;i<=size(L0)-1;i++)
3255  {
3256    L1[i]=intersect(L1[i-1],L0[i]);
3257    L2[i]=intersect(L2[i-1],L0[size(L0)-i+1]);
3258  }
3259  L3[1]=L2[size(L2)];
3260  for (i=2;i<=size(L0)-1;i++)
3261  {
3262    L3[i]=intersect(L1[i-1],L2[size(L0)-i]);
3263  }
3264  L3[size(L0)]=L1[size(L1)];
3265  for (i=1;i<=size(L3);i++)
3266  {
3267    option(redSB); L3[i]=std(L3[i]);
3268  }
3269  for (i=1;i<=size(L3);i++)
3270  {
3271    tes=1; j=0;
3272    while((tes) and (j<size(L3[i])))
3273    {
3274      j++;
3275      option(redSB);
3276      L0[i]=std(L0[i]);
3277      if(reduce(L3[i][j],L0[i])!=0){tes=0; F[i]=L3[i][j];}
3278    }
3279    if (tes){"ERROR a polynomial in all p_j except p_i was not found";}
3280  }
3281  setring(RR);
3282  def F0=imap(@P,F);
3283  return(F0);
3284}
3285
3286// precombinediscussion
3287// not used, can be deleted
3288// input:  list L: the LCU segment with bases for each pi component
3289// output: intvec vv:  vv[1]=(1 if the generic polynomial of the vv[2]
3290//                     component already specializes well,
3291//                     0 if combine is to be used)
3292//                     vv[2]=selind, the index for which the generic basis
3293//                     already specializes well if combine is not to be used (vv[1]=1).
3294proc precombinediscussion(L,crep)
3295{
3296  int tes=1; int selind; int i1; int j1; poly p; poly lcp; intvec vv;
3297  if (size(L)==1){vv=1,1; return(vv);}
3298  for (i1=1;i1<=size(L);i1++)
3299  {
3300    tes=1;
3301    p=L[i1][2];
3302    lcp=leadcoef(p);
3303
3304
3305    if(nonnullCrep(lcp,crep[1],crep[2]))
3306    {
3307      for(j1=1;j1<=size(L);j1++)
3308      {
3309        if(i1!=j1)
3310        {
3311          if(specswellCrep(p,L[j1][2],L[j1][1])==0){tes=0; break;}
3312        }
3313      }
3314    }
3315    else{tes=0;}
3316    if(tes){selind=i1; break;}
3317  }
3318  vv=tes,selind;
3319  return(vv);
3320}
3321
3322// minAssGTZ eliminating denominators
3323proc minGTZ(ideal N);
3324{
3325  int i; int j;
3326  def L=minAssGTZ(N);
3327  for(i=1;i<=size(L);i++)
3328  {
3329    for(j=1;j<=size(L[i]);j++)
3330    {
3331      L[i][j]=cleardenom(L[i][j]);
3332    }
3333  }
3334  return(L);
3335}
3336
3337//********************* Begin KapurSunWang *************************
3338
3339// inconsistent
3340// Input:
3341//   ideal E: of null conditions
3342//   ideal N: of non-null conditions representing V(E)\V(N)
3343// Output:
3344//   1 if V(E) \V(N) = empty
3345//   0 if not
3346proc inconsistent(ideal E, ideal N)
3347{
3348  int j;
3349  int te=1;
3350  def R=basering;
3351  setring(@P);
3352  def EP=imap(R,E);
3353  def NP=imap(R,N);
3354  poly @t;
3355  ring H=0,@t,dp;
3356  def RH=@P+H;
3357  setring(RH);
3358  def EH=imap(@P,EP);
3359  def NH=imap(@P,NP);
3360  ideal G;
3361  j=1;
3362  while((te==1) and j<=size(NH))
3363  {
3364    G=EH+(1-@t*NH[j]);
3365    option(redSB);
3366    G=std(G);
3367    if (G[1]!=1){te=0;}
3368    j++;
3369  }
3370  setring(R);
3371  return(te);
3372}
3373
3374// MDBasis: Minimal Dickson Basis
3375proc MDBasis(ideal G)
3376{
3377  int i; int j; int te=1;
3378  G=sortideal(G);
3379  ideal MD=G[1];
3380  poly lm;
3381  for (i=2;i<=size(G);i++)
3382  {
3383    te=1;
3384    lm=leadmonom(G[i]);
3385    j=1;
3386    while ((te==1) and (j<=size(MD)))
3387    {
3388      if (lm/leadmonom(MD[j])!=0){te=0;}
3389      j++;
3390    }
3391    if (te==1)
3392    {
3393      MD[size(MD)+1]=(G[i]);
3394    }
3395  }
3396  return(MD);
3397}
3398
3399// primepartZ
3400proc primepartZ(poly f);
3401{
3402  def R=basering;
3403  def cp=content(f);
3404  def fp=f/cp;
3405  return(fp);
3406}
3407
3408// LCMLC
3409proc LCMLC(ideal H)
3410{
3411  int i;
3412  def R=basering;
3413  setring(@RP);
3414  def HH=imap(R,H);
3415  poly h=1;
3416  for (i=1;i<=size(HH);i++)
3417  {
3418    h=lcm(h,HH[i]);
3419  }
3420  setring(R);
3421  def hh=imap(@RP,h);
3422  return(hh);
3423}
3424
3425// KSW: Kapur-Sun-Wang algorithm for computing a CGS
3426// Input:
3427//   F:   parametric ideal to be discussed
3428//   Options:
3429//     \"out\",0 Transforms the description of the segments into
3430//     canonical P-representation form.
3431//     \"out\",1 Original KSW routine describing the segments as
3432//     difference of varieties
3433//   The ideal must be defined on C[parameters][variables]
3434// Output:
3435//   With option \"out\",0 :
3436//     ((lpp,
3437//       (1,B,((p_1,(p_11,..,p_1k_1)),..,(p_s,(p_s1,..,p_sk_s)))),
3438//       string(lpp)
3439//      )
3440//      ,..,
3441//      (lpp,
3442//       (k,B,((p_1,(p_11,..,p_1k_1)),..,(p_s,(p_s1,..,p_sk_s)))),
3443//       string(lpp))
3444//      )
3445//     )
3446//   With option \"out\",1 ((default, original KSW) (shorter to be computed,
3447//                    but without canonical description of the segments.
3448//     ((B,E,N),..,(B,E,N))
3449proc KSW(ideal F, list #)
3450{
3451  setglobalrings();
3452  int start=timer;
3453  ideal E=ideal(0);
3454  ideal N=ideal(1);
3455  int comment=0;
3456  int out=1;
3457  int i;
3458  def L=#;
3459  if (size(L)>0)
3460  {
3461    for (i=1;i<=size(L) div 2;i++)
3462    {
3463      if (L[2*i-1]=="null"){E=L[2*i];}
3464      else
3465      {
3466        if (L[2*i-1]=="nonnull"){N=L[2*i];}
3467        else
3468        {
3469          if (L[2*i-1]=="comment"){comment=L[2*i];}
3470          else
3471          {
3472            if (L[2*i-1]=="out"){out=L[2*i];}
3473          }
3474        }
3475      }
3476    }
3477  }
3478  if (comment>0){string("Begin KSW with null = ",E," nonnull = ",N);}
3479  def CG=KSW0(F,E,N,comment);
3480  if (comment>0)
3481  {
3482    string("Number of segments in KSW (total) = ",size(CG));
3483    string("Time in KSW = ",timer-start);
3484  }
3485  if(out==0)
3486  {
3487    CG=KSWtocgsdr(CG);
3488    CG=groupKSWsegments(CG);
3489    if (comment>0)
3490    {
3491      string("Number of lpp segments = ",size(CG));
3492      string("Time in KSW + group + Prep = ",timer-start);
3493    }
3494  }
3495  if(defined(@P)){kill @P; kill @R; kill @RP;}
3496  return(CG);
3497}
3498
3499// sqf
3500// This is for releases of Singular before 3-5-1
3501// proc sqf(poly f)
3502// {
3503//  def RR=basering;
3504//  setring(@P);
3505//  def ff=imap(RR,f);
3506//  def G=sqrfree(ff);
3507//  poly fff=1;
3508//  int i;
3509//  for (i=1;i<=size(G);i++)
3510//  {
3511//    fff=fff*G[i];
3512//  }
3513//  setring(RR);
3514//   def ffff=imap(@P,fff);
3515//   return(ffff);
3516// }
3517
3518// sqf
3519proc sqf(poly f)
3520{
3521  def RR=basering;
3522  setring(@P);
3523  def ff=imap(RR,f);
3524  poly fff=sqrfree(ff,3);
3525  setring(RR);
3526  def ffff=imap(@P,fff);
3527  return(ffff);
3528}
3529
3530
3531// KSW0: Kapur-Sun-Wang algorithm for computing a CGS, called by KSW
3532// Input:
3533//   F:   parametric ideal to be discussed
3534//   Options:
3535//   The ideal must be defined on C[parameters][variables]
3536// Output:
3537proc KSW0(ideal F, ideal E, ideal N, int comment)
3538{
3539  def R=basering;
3540  int i; int j; list emp;
3541  list CGS;
3542  ideal N0;
3543  for (i=1;i<=size(N);i++)
3544  {
3545    N0[i]=sqf(N[i]);
3546  }
3547  ideal E0;
3548  for (i=1;i<=size(E);i++)
3549  {
3550    E0[i]=sqf(leadcoef(E[i]));
3551  }
3552  setring(@P);
3553  ideal E1=imap(R,E0);
3554  E1=std(E1);
3555  ideal N1=imap(R,N0);
3556  N1=std(N1);
3557  setring(R);
3558  E0=imap(@P,E1);
3559  N0=imap(@P,N1);
3560//   E0=elimrepeated(E0);
3561//   N0=elimrepeated(N0);
3562  if (inconsistent(E0,N0)==1)
3563  {
3564    return(emp);
3565  }
3566  setring(@RP);
3567  def FRP=imap(R,F);
3568  def ERP=imap(R,E);
3569  FRP=FRP+ERP;
3570  option(redSB);
3571  def GRP=std(FRP);
3572  setring(R);
3573  def G=imap(@RP,GRP);
3574  if (memberpos(1,G)[1]==1)
3575  {
3576    if(comment>1){"Basis 1 is found"; E; N;}
3577    return(E0,N0,ideal(1));
3578  }
3579  ideal Gr; ideal Gm; ideal GM;
3580  for (i=1;i<=size(G);i++)
3581  {
3582    if (variables(G[i])[1]==0){Gr[size(Gr)+1]=G[i];}
3583    else{Gm[size(Gm)+1]=G[i];}
3584  }
3585  ideal Gr0;
3586  for (i=1;i<=size(Gr);i++)
3587  {
3588    Gr0[i]=sqf(Gr[i]);
3589  }
3590
3591
3592  Gr=elimrepeated(Gr0);
3593  ideal GrN;
3594  for (i=1;i<=size(Gr);i++)
3595   {
3596    for (j=1;j<=size(N0);j++)
3597    {
3598      GrN[size(GrN)+1]=sqf(Gr[i]*N0[j]);
3599    }
3600  }
3601  if (inconsistent(E,GrN)){;}
3602  else
3603  {
3604    if(comment>1){"Basis 1 is found in a branch with arguments"; E; GrN;}
3605    CGS[size(CGS)+1]=list(E,GrN,ideal(1));
3606  }
3607  if (inconsistent(Gr,N0)){return(CGS);}
3608  GM=Gm;
3609  Gm=MDBasis(Gm);
3610  ideal H;
3611  for (i=1;i<=size(Gm);i++)
3612  {
3613    H[i]=sqf(leadcoef(Gm[i]));
3614  }
3615  H=facvar(H);
3616  poly h=sqf(LCMLC(H));
3617  if(comment>1){"H = "; H; "h = "; h;}
3618  ideal Nh=N0;
3619  if(size(N0)==0){Nh=h;}
3620  else
3621  {
3622    for (i=1;i<=size(N0);i++)
3623    {
3624      Nh[i]=sqf(N0[i]*h);
3625    }
3626  }
3627  if (inconsistent(Gr,Nh)){;}
3628  else
3629  {
3630    CGS[size(CGS)+1]=list(Gr,Nh,Gm);
3631  }
3632  poly hc=1;
3633  list KS;
3634  ideal GrHi;
3635  for (i=1;i<=size(H);i++)
3636  {
3637    kill GrHi;
3638    ideal GrHi;
3639    Nh=N0;
3640    if (i>1){hc=sqf(hc*H[i-1]);}
3641    for (j=1;j<=size(N0);j++){Nh[j]=sqf(N0[j]*hc);}
3642    if (equalideals(Gr,ideal(0))==1){GrHi=H[i];}
3643    else {GrHi=Gr,H[i];}
3644//     else {for (j=1;j<=size(Gr);j++){GrHi[size(GrHi)+1]=Gr[j]*H[i];}}
3645    if(comment>1){"Call to KSW with arguments "; GM; GrHi;  Nh;}
3646    KS=KSW0(GM,GrHi,Nh,comment);
3647    for (j=1;j<=size(KS);j++)
3648    {
3649      CGS[size(CGS)+1]=KS[j];
3650    }
3651    if(comment>1){"CGS after KSW = "; CGS;}
3652  }
3653  return(CGS);
3654}
3655
3656// KSWtocgsdr
3657proc KSWtocgsdr(list L)
3658{
3659  int i; list CG; ideal B; ideal lpp; int j; list NKrep;
3660  for(i=1;i<=size(L);i++)
3661  {
3662    B=redgbn(L[i][3],L[i][1],L[i][2]);
3663    lpp=ideal(0);
3664    for(j=1;j<=size(B);j++)
3665    {
3666      lpp[j]=leadmonom(B[j]);
3667    }
3668    NKrep=KtoPrep(L[i][1],L[i][2]);
3669    CG[i]=list(lpp,B,NKrep);
3670  }
3671  return(CG);
3672}
3673
3674// KtoPrep
3675// Computes the P-representaion of a K-representation (N,W) of a set
3676// input:
3677//    ideal E (null conditions)
3678//    ideal N (non-null conditions ideal)
3679// output:
3680//    the ((p_1,(p_11,..,p_1k_1)),..,(p_r,(p_r1,..,p_rk_r)));
3681//    the Prep of V(N) \ V(W)
3682proc KtoPrep(ideal N, ideal W)
3683{
3684  int i; int j;
3685  if (N[1]==1)
3686  {
3687    L0[1]=list(ideal(1),list(ideal(1)));
3688    return(L0);
3689  }
3690  def RR=basering;
3691  setring(@P);
3692  ideal B; int te; poly f;
3693  ideal Np=imap(RR,N);
3694  ideal Wp=imap(RR,W);
3695  list L;
3696  list L0; list T0;
3697  L0=minGTZ(Np);
3698  for(j=1;j<=size(L0);j++)
3699  {
3700    option(redSB);
3701    L0[j]=std(L0[j]);
3702  }
3703  for(i=1;i<=size(L0);i++)
3704  {
3705    if(inconsistent(L0[i],Wp)==0)
3706    {
3707      B=L0[i]+Wp;
3708      T0=minGTZ(B);
3709      option(redSB);
3710      for(j=1;j<=size(T0);j++)
3711      {
3712        T0[j]=std(T0[j]);
3713      }
3714      L[size(L)+1]=list(L0[i],T0);
3715    }
3716  }
3717  setring(RR);
3718  def LL=imap(@P,L);
3719  return(LL);
3720}
3721
3722// groupKSWsegments
3723// input:  the list of vertices of KSW
3724// output: the same terminal vertices grouped by lpp
3725proc groupKSWsegments(list T)
3726{
3727  //"T_T="; T;
3728  int i; int j;
3729  list L;
3730  list lpp; list lppor;
3731  list kk;
3732  lpp[1]=T[1][1]; j=1;
3733  lppor[1]=intvec(1);
3734  for(i=2;i<=size(T);i++)
3735  {
3736    kk=memberpos(T[i][1],lpp);
3737    if(kk[1]==0){j++; lpp[j]=T[i][1]; lppor[j]=intvec(i);}
3738    else{lppor[kk[2]][size(lppor[kk[2]])+1]=i;}
3739  }
3740  list ll;
3741  for (j=1;j<=size(lpp);j++)
3742  {
3743    kill ll; list ll;
3744    for(i=1;i<=size(lppor[j]);i++)
3745    {
3746      ll[size(ll)+1]=list(i,T[lppor[j][i]][2],T[lppor[j][i]][3]);
3747    }
3748    L[j]=list(lpp[j],ll,string(lpp[j]));
3749  }
3750  return(L);
3751}
3752
3753//********************* End KapurSunWang *************************
3754
3755//******************** Begin locus ******************************
3756
3757
3758// indepparameters
3759// Auxiliary routine to detect "Special" components of the locus
3760// Input: ideal B
3761// Output:
3762//   1 if the solutions of the ideal do not depend on the parameters
3763//   0 if they depend
3764proc indepparameters(ideal B)
3765{
3766  def R=basering;
3767  ideal v=variables(B);
3768  setring @RP;
3769  def BP=imap(R,B);
3770  def vp=imap(R,v);
3771  ideal varpar=variables(BP);
3772  int te;
3773  te=equalideals(vp,varpar);
3774  setring(R);
3775  if(te){return(1);}
3776  else{return(0);}
3777}
3778
3779
3780// dimP0: Auxiliar routine
3781// if the dimension in @P of an ideal in the parameters has dimension 0 then it returns 0
3782// else it retuns 1
3783proc dimP0(ideal N)
3784{
3785  def R=basering;
3786  setring(@P);
3787  int te=1;
3788  def NP=imap(R,N);
3789  attrib(NP,"IsSB",1);
3790  int d=dim(std(NP));
3791  if(d==0){te=0;}
3792  setring(R);
3793  return(te);
3794}
3795
3796// Auxiliar routine.
3797// input:    ideals E and F (assumed in ring @P
3798// returns: 1 if ideal E is contained in ideal F (assumed F is std basis)
3799//              0 if not
3800proc containedideal(ideal E, ideal F)
3801{
3802  int i; int t; poly f;
3803  if(equalideals(F,ideal(0)))
3804  {
3805    if(equalideals(E,ideal(0))==0){return(0);}
3806    else(return(1));
3807  }
3808  t=1; i=1;
3809  while((t==1) and (i<=size(E)))
3810  {
3811    attrib(F,"isSB",1);
3812    f=reduce(E[i],F);
3813    if(f!=0){t=0;}
3814    i++;
3815  }
3816  return(t);
3817}
3818
3819// AddCons: given a set of locally closed components of a selection of
3820//       segments of the Grobner cover, it builds the canonical P-representation
3821//       of the corresponding constructible set, including levels it they are
3822// input: a list L of a selection of segments of the Groebner cover
3823//       given a a set of components of the form
3824//       ( (p_1,(p_11,..,p_1k_1).. (p_s,(p_s1,..,p_sk_s))
3825// output: The canonical P-representation of adding the given components.
3826proc AddCons(list L)
3827{
3828  // First step: Selecting the top varieties
3829  list L1; list L2; list LL; int i; int j; int t;
3830  list Lend;
3831  for(i=1;i<=size(L);i++)
3832  {
3833    t=1;
3834    for(j=1;j<=size(L);j++)
3835    {
3836      if(i!=j)
3837      {
3838        if(containedideal(L[j][1],L[i][1])==1)
3839        {t=0;
3840         // "the ideal "; L[j][1]; "is contained in ideal "; L[i][1];
3841          j=size(L);
3842        }
3843      }
3844    }
3845    if(t==1){L1[size(L1)+1]=L[i];}
3846    else{L2[size(L2)+1]=L[i];}
3847  }
3848  // Second step: Adding segments to obtain a locally closed sets for each level
3849  int lev=1;
3850  if(size(L2)==0)
3851  {
3852     for(i=1;i<=size(L1);i++)
3853     {
3854       if(size(L1[i])>=3)
3855       {L1[i][3]=string(string(L1[i][3]),",",lev);}
3856       else{L1[i][3]=string(lev);}
3857     }
3858   return(L1);
3859  }
3860   while(size(L2)>0)
3861   {
3862     LL=addtolocalclosed(L1,L2);
3863     for(i=1;i<=size(LL[1]);i++)
3864     {
3865       if(size(LL[1][i])>=3)
3866       {LL[1][i][3]=string(string(LL[1][i][3]),",",lev);}
3867       else{LL[1][i][3]=string(lev);}
3868       Lend[size(Lend)+1]=LL[1][i];
3869     }
3870     L2=LL[2];
3871     lev++;
3872   }
3873   return(Lend);
3874}
3875
3876// input: Two lists of P-components to be added.
3877//           L1 contains the top components, and L2 the remaining components
3878//           each of the form ( (p_1,(p_11,..,p_1k_1).. (p_s,(p_s1,..,p_sk_s))
3879// output: A list of two lists:
3880//           The first one contains the P-representation of the top components added
3881//           The second contains the components that have not yet been added when
3882//           the total subset is not locally closed. If so addtolocalclosed is to be called
3883//           at new after separating the new top and remaining components in order
3884//           to compute the next level of the constructible set.
3885//           The input and the output must be in the ring @P of parameters.
3886proc  addtolocalclosed(list L1,list L2)
3887{
3888   // Second step: Adding segments to obtain a locally closed set
3889   // L1 contains the top components (ideals and descendants)
3890   // L2 contains the nontop components (ideals and descendants)
3891   list LL; int i; int j; int t; intvec Added; int mesvoltes=1; intvec alreadyadded; list LN;
3892   int k; int l; int m; ideal top; ideal hole; ideal nhole; intvec nottoadd; int t0; list h;
3893   LL=L1;
3894   LN=L2;
3895   while(mesvoltes)
3896   {
3897     //"volta";
3898     for(i=1;i<=size(L1);i++)
3899     {
3900        Added=Added,alreadyadded;
3901        Added=sort(elimrepeatedvl(Added))[1];
3902        kill alreadyadded; intvec alreadyadded;
3903        top=LL[i][1][1];
3904        j=1;
3905        while(j<=size(LL[i][2]))
3906        {
3907           kill nottoadd; intvec nottoadd;
3908           hole=LL[i][2][j];
3909           t0=1;
3910           k=1;
3911           while(t0 and k<=size(LN))
3912           {
3913              if (equalideals(hole,LN[k][1])==1)
3914              {
3915                 t0=0;
3916                  if(alreadyadded==intvec(0)){alreadyadded[1]=k;}
3917                 else{alreadyadded[size(alreadyadded)+1]=k;}
3918                 LL[i][2]=elimfromlist(LL[i][2],j);
3919                 j=j-1;
3920                 for(l=1;l<=size(LN[k][2]);l++)
3921                 {
3922                   nhole=LN[k][2][l],LL[i][1];
3923                   nhole=std(nhole);
3924                   t=1; m=1;
3925                    while(t and m<=size(LL[i][2]))
3926                    {
3927                       if(containedideal(LL[i][2][m],nhole)==1)
3928                       {
3929                         t=0;
3930                       }
3931                       m++;
3932                    }
3933                    if(t==0){nottoadd[size(nottoadd)+1]=l;}
3934                  }
3935                 for(m=1;m<=size(LN[k][2]);m++)
3936                 {
3937                     if(memberpos(m,nottoadd)[1]==0)
3938                    {
3939                       LL[i][2][size(LL[i][2])+1]=LN[k][2][m];
3940                    }
3941                 }
3942              }
3943              k++;
3944
3945           }
3946           j++;
3947        }
3948        if(size(LL[i][2])==0 and size(LL[i][1])>0){LL[i][2][1]=ideal(1);}
3949     }
3950     h=1,1;
3951     while((h[1]==1) and (alreadyadded!=intvec(0)))
3952     {
3953       h=memberpos(0,alreadyadded);
3954       if(h[1]==1){alreadyadded=elimfromlist(alreadyadded,h[2]);}
3955     }
3956     if(alreadyadded!=intvec(0))
3957     {alreadyadded=sort(elimrepeatedvl(alreadyadded))[1];}
3958     if(Added==intvec(0)){Added=alreadyadded;}
3959     else{
3960       Added=Added,alreadyadded;
3961       Added=sort(elimrepeatedvl(Added))[1];
3962     }
3963     h=1,1;
3964     while((h[1]==1) and (Added!=intvec(0)))
3965     {
3966       h=memberpos(0,Added);
3967       if(h[1]==1){Added=elimfromlist(Added,h[2]);}
3968     }
3969     if (alreadyadded==intvec(0))
3970     {
3971       mesvoltes=0;
3972     }
3973  }
3974  if(Added!=intvec(0)){Added=sort(elimrepeatedvl(Added))[1]; }
3975  if(Added!=intvec(0))
3976  {
3977    for(i=1;i<=size(Added);i++)
3978    {
3979      if(size(LN)>0){LN=elimfromlist(LN,Added[size(Added)+1-i]);}
3980    }
3981  }
3982  for (i=1;i<=size(LL);i++)
3983  {
3984    for(j=1;j<=size(LL[i][2]);j++)
3985    {
3986      hole=LL[i][2][j];
3987      for (k=1;k<=size(LL);k++)
3988      {
3989        if(k!=i)
3990        {
3991          if(containedideal(LL[k][1],hole))
3992          {
3993            LL[i][2]=elimfromlist(LL[i][2],j);
3994            for(l=1;l<=size(LL[k][2]);l++)
3995            {
3996              nhole=hole,LL[k][2][l];
3997              nhole=std(nhole);
3998              if(equalideals(nhole,ideal(1))==0)
3999              {
4000                m=1; t=1;
4001                while(t and m<size(LL[i][2]))
4002                {
4003                  if(containedideal(LL[i][2][m],nhole)){t=0;}
4004                  m++;
4005                }
4006                if(t==1){LL[i][2][size(LL[i][2])+1]=nhole;}
4007              }
4008            }
4009          }
4010        }
4011      }
4012    }
4013  }
4014  LL[1]=LL; LL[2]=LN;
4015  return(LL);
4016}
4017
4018// locus(G):  Special routine for determining the locus of points
4019//                of  objects. Given a parametric ideal J with
4020//                parameters (a_1,..a_m) and variables (x_1,..,xn),
4021//                representing the system determining
4022//                the locus of points (a_1,..,a_m)) who verify certain
4023//                properties, computing the grobcov G of
4024//                J and applying to it locus, determines the different
4025//                classes of locus components. They can be
4026//                Normal, Special, Accumulation point, Degenerate.
4027//                The output are the components given in P-canonical form
4028//                of at most 4 constructible sets: Normal, Special, Accumulation,
4029//                Degenerate.
4030//                The description of the algorithm and definitions will be
4031//                given in a forthcoming paper by Abanades, Botana, Montes Recio.
4032
4033// input:      The output G of the grobcov (in generic representation, which is the default)
4034// output:
4035//         list, the canonical P-representation of the Normal and Non-Normal locus:
4036//              The Normal locus has two kind of components: Normal and Special.
4037//              The Non-normal locus has two kind of components: Accumulation and Degenerate.
4038//              Normal components: for each point in the component,
4039//              the number of solutions in the variables is finite, and
4040//              the solutions depend on the point in the component if the component is not 0-dimensional.
4041//              Special components:  for each point in the component,
4042//              the number of solutions in the variables is finite,
4043//              the component is not 0-dimensional, but the solutions do not depend on the
4044//              values of the parameters in the component.
4045//              Accumlation points: are 0-dimensional components for which it exist
4046//              an infinite number of solutions.
4047//              Degenerate components: are components of dimension greater than 0 for which
4048//              for every point in the component there exist infinite solutions.
4049//         The output components are given as
4050//              ((p1,(p11,..p1s_1),type_1,level_1),..,(pk,(pk1,..pks_k),type_k,level_k)
4051//         The components are given in canonical P-representation of the subset.
4052//              If all levels of a class of locus are 1, then the set is locally closed. Otherwise the level
4053//              gives the depth of the component.
4054proc locus(list GG, list #)
4055"USAGE:   locus(G);
4056               The input must be the grobcov  of a parametrical ideal
4057RETURN:  The  locus.
4058               The output are the components of two constructible subsets of the locus
4059               of the parametrical system.: Normal and Non-normal.
4060               These components are
4061               given as a list of  (pi,(pi1,..pis_i),type_i,level_i) varying i,
4062               where the p's are prime ideals, the type can be: Normal, Special,
4063               Accumulation, Degenerate.
4064NOTE:      It can only be called after computing the grobcov of the
4065               parametrical ideal in generic representation ('ext',0),
4066               which is the default.
4067               The basering R, must be of the form Q[a_1,..,a_m][x_1,..,x_n].
4068KEYWORDS: geometrical locus, locus, loci.
4069EXAMPLE:  locus; shows an example"
4070{
4071  int t1=1; int t2=1;
4072  def R=basering;
4073  int moverdim=nvars(R);
4074  list Lop=#;
4075  if(size(Lop)>0){moverdim=Lop[1];}
4076  setglobalrings();
4077  list G1; list G2;
4078  def G=GG;
4079  int i; int d; int j; int k;
4080  t1=1;
4081  for(i=1;i<=size(G);i++)
4082  {
4083    attrib(G[i][1],"IsSB",1);
4084    //d=dim(std(G[i][1]));
4085    // ULL
4086    d=locusdim(G[i][2],moverdim);
4087    if(d==0){G1[size(G1)+1]=G[i];}
4088    else
4089    {
4090      if(d>0){G2[size(G2)+1]=G[i];}
4091    }
4092  }
4093  if(size(G1)==0){t1=0;}
4094  if(size(G2)==0){t2=0;}
4095  setring(@RP);
4096  if(t1)
4097  {
4098    list G1RP=imap(R,G1);
4099  }
4100  else {list G1RP;}
4101  list P1RP;
4102  ideal B;
4103  for(i=1;i<=size(G1RP);i++)
4104  {
4105     kill B;
4106     ideal B;
4107     for(k=1;k<=size(G1RP[i][3]);k++)
4108     {
4109       attrib(G1RP[i][3][k][1],"IsSB",1);
4110       G1RP[i][3][k][1]=std(G1RP[i][3][k][1]);
4111       for(j=1;j<=size(G1RP[i][2]);j++)
4112       {
4113         B[j]=reduce(G1RP[i][2][j],G1RP[i][3][k][1]);
4114       }
4115       P1RP[size(P1RP)+1]=list(G1RP[i][3][k][1],G1RP[i][3][k][2],B);
4116     }
4117  }
4118  setring(R);
4119  ideal h;
4120  if(t1)
4121  {
4122    def P1=imap(@RP,P1RP);
4123    for(i=1;i<=size(P1);i++)
4124    {
4125      for(j=1;j<=size(P1[i][3]);j++)
4126      {
4127        h=factorize(P1[i][3][j],1);
4128        P1[i][3][j]=h[1];
4129        for(k=2;k<=size(h);k++)
4130        {
4131          P1[i][3][j]=P1[i][3][j]*h[k];
4132        }
4133        //P1[i][3][j]=normalize(P1[i][3][j]);
4134      }
4135    }
4136  }
4137  else{list P1;}
4138  for(i=1;i<=size(P1);i++)
4139  {
4140    if (indepparameters(P1[i][3])==1){P1[i][3]="Special";}
4141    else{P1[i][3]="Normal";}
4142  }
4143  list P2;
4144  for(i=1;i<=size(G2);i++)
4145  {
4146    for(k=1;k<=size(G2[i][3]);k++)
4147    {
4148      P2[size(P2)+1]=list(G2[i][3][k][1],G2[i][3][k][2]);
4149    }
4150  }
4151  setring @P;
4152  // CANVIAR
4153  if(t1==1)
4154  {
4155    def C1=imap(R,P1);
4156    def L1=AddCons(C1);
4157   }
4158  else{list C1; list L1; kill P1; list P1;}
4159  if(t2==1)
4160  {
4161    def C2=imap(R,P2);
4162    def L2=AddCons(C2);
4163  }
4164  else{list L2; list C2; kill P2; list P2;}
4165    for(i=1;i<=size(L2);i++)
4166    {
4167      d=dim(std(L2[i][1]));
4168      if(d==0)
4169      {
4170        L2[i][3]=string("Accumulation,",L2[i][3]);
4171      }
4172      else{L2[i][3]=string("Degenerate,",L2[i][3]);}
4173    }
4174  list LN;
4175  if(t1==1)
4176  {
4177    for(i=1;i<=size(L1);i++){LN[size(LN)+1]=L1[i];}
4178  }
4179  if(t2==1)
4180  {
4181    for(i=1;i<=size(L2);i++){LN[size(LN)+1]=L2[i];}
4182  }
4183  setring(R);
4184  def L=imap(@P,LN);
4185  for(i=1;i<=size(L);i++){if(size(L[i][2])==0){L[i][2]=ideal(1);}}
4186  kill @R; kill @RP; kill @P;
4187  return(L);
4188}
4189example
4190{"EXAMPLE:"; echo = 2;
4191  ring R=(0,a,b),(x,y),dp;
4192  short=0;
4193  "Concoid";
4194  ideal S96=x^2+y^2-4,(b-2)*x-a*y+2*a,(a-x)^2+(b-y)^2-1;
4195  "System="; S96; " ";
4196  locus(grobcov(S96));
4197}
4198
4199
4200// locusto: Transforms the output of locus to a string that
4201//      can be read by different computational systems.
4202// input:
4203//     list L: The output of locus
4204// output:
4205//     string s: The output of locus converted to a string readable by other programs
4206proc locusto(list L)
4207"USAGE:   locusto(G);
4208          The argument must be the output of locus of a parametrical ideal
4209          It transforms the output into a string in standard form
4210          readable in many languages (Geogebra).
4211
4212RETURN: The locus in string standard form
4213NOTE:     It can only be called after computing the locus(grobcov(F)) of the
4214              parametrical ideal.
4215              The basering R, must be of the form Q[a,b,..][x,y,..].
4216KEYWORDS: geometrical locus, locus, loci.
4217EXAMPLE:  locusto; shows an example"
4218{
4219  int i; int j; int k;
4220  string s;
4221  s="[";
4222  ideal p;
4223  ideal q;
4224  for(i=1;i<=size(L);i++)
4225  {
4226    s=string(s,"[[");
4227    for (j=1;j<=size(L[i][1]);j++)
4228    {
4229      s=string(s,L[i][1][j],",");
4230    }
4231    s[size(s)]="]";
4232    s=string(s,",[");
4233    for(j=1;j<=size(L[i][2]);j++)
4234    {
4235      s=string(s,"[");
4236      for(k=1;k<=size(L[i][2][j]);k++)
4237      {
4238        s=string(s,L[i][2][j][k],",");
4239      }
4240      s[size(s)]="]";
4241      s=string(s,",");
4242    }
4243    s[size(s)]="]";
4244    s=string(s,"]");
4245    if(size(L[i])>=3)
4246    {
4247      s[size(s)]=",";
4248      s=string(s,string(L[i][3]),"]");
4249    }
4250    if(size(L[i])>=4)
4251    {
4252      s[size(s)]=",";
4253      s=string(s,string(L[i][4]),"],");
4254    }
4255    s[size(s)]="]";
4256    s=string(s,",");
4257  }
4258  s[size(s)]="]";
4259  return(s);
4260}
4261example
4262{"EXAMPLE:"; echo = 2;
4263  ring R=(0,a,b),(x,y),dp;
4264  short=0;
4265  ideal S96=x^2+y^2-4,(b-2)*x-a*y+2*a,(a-x)^2+(b-y)^2-1;
4266  "System="; S96; " ";
4267  locusto(locus(grobcov(S96)));
4268}
4269
4270// locusdg is the routine for computing the locus in dinamical geometry.
4271//    It detects automatically a possible point that is to be avoided by the mover,
4272//    whose coordinates must be the last coordinates in the definition of the ring (2 last by default,
4273//    or the dd last if the option locusdg(G,dd) is specified).
4274//    If such a point is detected, then it eliminates the segments of the grobcov that
4275//    have this point as solution.
4276//    Then it calls locus.
4277proc locusdg(list GG,list #)
4278"USAGE:  locusdg(GG) ;
4279          The argument must be the output of grobcov
4280RETURN:  The  components of the locus of points in dinamical geometry
4281NOTE:  The basering R, must be of the form Q[a][x], a=parameters,
4282          x=variables, and the mover coordinates must be the two last variables in the
4283          definition of the ring.
4284KEYWORDS: ring, locus, grobcov
4285EXAMPLE:  locusdg(GG); shows an example"
4286{
4287  def R=basering;
4288  int dd=2; int comment=0;
4289  list DD=#;
4290  if (size(DD)>1){comment=1;}
4291  if(size(DD)>0){dd=DD[1];}
4292  int i; int j; int k;
4293  def B0=GG[1][2];
4294  if (equalideals(B0,ideal(1)))
4295  {
4296    return(locus(GG));
4297  }
4298  else
4299  {
4300    int n=nvars(R);
4301    ideal vmov=var(n-1),var(n);
4302    ideal N;
4303    intvec xw; intvec yw;
4304    for(i=1;i<=n-1;i++){xw[i]=0;}
4305    xw[n]=1;
4306    for(i=1;i<=n;i++){yw[i]=0;}
4307    yw[n-1]=1;
4308    poly px; poly py;
4309    int te=1;
4310    i=1;
4311    while( te and i<=size(B0))
4312    {
4313      if((deg(B0[i],xw)==1) and (deg(B0[i])==1)){px=B0[i]; te=0;}
4314      i++;
4315    }
4316    i=1; te=1;
4317    while( te and i<=size(B0))
4318    {
4319      if((deg(B0[i],yw)==1) and (deg(B0[i])==1)){py=B0[i]; te=0;}
4320      i++;
4321    }
4322    N=px,py;
4323    setglobalrings();
4324    te=indepparameters(N);
4325    if(te)
4326    {
4327      string("locusdg detected that the mover must avoid point (",N,") in order to obtain the locus");
4328      // eliminate segments of GG where N is contained in the basis
4329      list nGP;
4330      def GP=GG;
4331      ideal BP;
4332      for(j=1;j<=size(GP);j++)
4333      {
4334        te=1; k=1;
4335        BP=GP[j][2];
4336        while((te==1) and (k<=size(N)))
4337        {
4338          if(pdivi(N[k],BP)[1]!=0){te=0;}
4339          k++;
4340        }
4341        if(te==0){nGP[size(nGP)+1]=GP[j];}
4342      }
4343   }
4344  }
4345  //"T_nGP="; nGP;
4346  kill @RP; kill @P; kill @R;
4347  return(locus(nGP,dd));
4348}
4349//      // Now eliminate components for which the basis has dim>0, and all elements non reducing to 0
4350//      // modulo N do not contain the mover coordinates
4351//      list nnGP; poly r;
4352//      for(j=1; j<=size(nGP);j++)
4353//      {
4354//        if(not(indepparameters(nGP[j][2])))
4355//        {
4356//          if(dim(std(nGP[j][1]))==0){nnGP[size(nnGP)+1]=nGP[j];}
4357//          else
4358//          {
4359//            te=1; k=1;
4360//            while(te and k<=size(nGP[2]))
4361//            {
4362//              r=pdivi(nGP[j][2][k],N)[1];
4363//              if(r==0){k++;}
4364//              else
4365//              {
4366//                if(not(subset(variables(nGP[j][2][k]),vmov )))
4367//                {
4368//                  te=0;
4369//                }
4370//                else{k++;}
4371//              }
4372//            }
4373//            if(te==1){nnGP[size(nnGP)+1]=nGP[j];}
4374//          }
4375//        }
4376//      }
4377//
4378//    }
4379//    kill @RP; kill @P; kill @R;
4380//    return(locus(nnGP));
4381//  }
4382//}
4383example
4384{"EXAMPLE:"; echo = 2;
4385  ring R=(0,a,b),(x4,x3,x2,x1),dp;
4386  ideal S=(x1-3)^2+(x2-1)^2-9,
4387             (4-x2)*(x3-3)+(x1-3)*(x4-1),
4388             (3-x1)*(x3-x1)+(4-x2)*(x4-x2),
4389             (4-x4)*a+(x3-3)*b+3*x4-4*x3,
4390             (a-x1)^2+(b-x2)^2-(x1-x3)^2-(x2-x4)^2;
4391  short=0;
4392  locusdg(grobcov(S));
4393}
4394
4395// locusdim
4396// input:
4397//    B:         ideal, a basis of a segment of the grobcov
4398//    dgdim: int, the dimension of the mover (for locusdg)
4399//                by default dgdim is equal to the number of variables
4400proc locusdim(ideal B, list #)
4401{
4402  def R=basering;
4403  int dgdim;
4404  int nv=nvars(R);
4405  if (size(#)>0){dgdim=#[1];}
4406  else {dgdim=nv;}
4407  int d;
4408  list v;
4409  ideal vi;
4410  int i;
4411  for(i=1;i<=dgdim;i++)
4412  {
4413    v[size(v)+1]=varstr(nv-dgdim+i);
4414    vi[size(v)+1]=var(nv-dgdim+i);
4415  }
4416  ideal B0;
4417  for(i=1;i<=size(B);i++)
4418  {
4419    if(subset(variables(B[i]),vi))
4420    {
4421      B0[size(B0)+1]=B[i];
4422    }
4423  }
4424  //"T_B0="; B0;
4425  //"T_v="; v;
4426  def RR=ringlist(R);
4427  def RR0=RR;
4428  RR0[2]=v;
4429  def R0=ring(RR0);
4430  //ringlist(R0);
4431  setring(R0);
4432  def B0r=imap(R,B0);
4433  B0r=std(B0r);
4434  d=dim(B0r);
4435  setring R;
4436  return(d);
4437}
4438
4439
4440//********************* End locus ****************************
4441;
Note: See TracBrowser for help on using the repository browser.