source: git/Singular/LIB/grobcov.lib @ 1b81fb5

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