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

spielwiese
Last change on this file since f62abb was f62abb, checked in by Hans Schoenemann <hannes@…>, 10 years ago
new version of grobcov.lib
  • Property mode set to 100644
File size: 124.5 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  def 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  exportto(Top,@R);      // global ring K[a][x]
209  exportto(Top,@P);      // global ring K[a]
210  exportto(Top,@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  @R;
218  @P;
219  @RP;
220ringlist(@R);
221ringlist(@P);
222ringlist(@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  def nc=content(n);
428  def mc=content(m);
429  def 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(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  def RR=basering;
1225  setring(@P);
1226  def Lp=imap(RR,L);
1227  int i; int j;
1228  ideal ida=ideal(1); ideal idb=ideal(1); list Lb; ideal N;
1229  for (i=1;i<=size(Lp);i++)
1230  {
1231    option(returnSB);
1232    N=Lp[i][1];
1233    ida=intersect(ida,N);
1234    Lb=Lp[i][2];
1235    for(j=1;j<=size(Lb);j++)
1236    {
1237      idb=intersect(idb,Lb[j]);
1238    }
1239  }
1240  def La=list(ida,idb);
1241  setring(RR);
1242  return(imap(@P,La));
1243}
1244
1245// input: F a parametric ideal in Q[a][x]
1246// output: a rComprehensive Groebner System disjoint and reduced.
1247//      It uses Kapur-Sun-Wang algorithm, and with the options
1248//      can compute the homogenization before  (('can',0) or ( 'can',1))
1249//      and dehomogenize the result.
1250proc cgsdr(ideal F, list #)
1251"USAGE: cgsdr(F); To compute a disjoint, reduced CGS.
1252          cgsdr is the starting point of the fundamental routine grobcov.
1253          Inside grobcov it is used only with options 'can' set to 0,1 and
1254          not with options ('can',2).
1255          It is to be used if only a disjoint reduced CGS is required.
1256          F: ideal in Q[a][x] (parameters and variables) to be discussed.
1257
1258          Options: To modify the default options, pairs of arguments
1259          -option name, value- of valid options must be added to the call.
1260
1261          Options:
1262            \"can\",0-1-2: The default value is \"can\",2. In this case no
1263                homogenization is done. With option (\"can\",0) the given
1264                basis is homogenized, and with option (\"can\",1) the
1265                whole given ideal is homogenized before computing the
1266                cgs and dehomogenized after.
1267                with option (\"can\",0) the homogenized basis is used
1268                with option (\"can\",1) the homogenized ideal is used
1269                with option (\"can\",2) the given basis is used
1270            \"null\",ideal E: The default is (\"null\",ideal(0)).
1271            \"nonnull\",ideal N: The default (\"nonnull\",ideal(1)).
1272                When options 'null' and/or 'nonnull' are given, then
1273                the parameter space is restricted to V(E)\V(N).
1274            \"comment\",0-1: The default is (\"comment\",0). Setting (\"comment\",1)
1275                will provide information about the development of the
1276                computation.
1277            \"out\",0-1: 1 (default) the output segments are given as
1278                as difference of varieties.
1279                0: the output segments are given in P-representation
1280                and the segments grouped by lpp
1281                With options (\"can\",0) and (\"can\",1) the option (\"out\",1)
1282                is set to (out,0) because it is not compatible.
1283          One can give none or whatever of these options.
1284          With the default options (\"can\",2,\"out\",1), only the
1285          Kapur-Sun-Wang algorithm is computed. This is very effectif
1286          but is only the starting point for the computation.
1287          When grobcov is computed, the call to cgsdr inside uses
1288          specific options that are more expensive ("can",0-1,"out",0).
1289RETURN:   Returns a list T describing a reduced and disjoint
1290          Comprehensive Groebner System (CGS),
1291          With option (\"out\",0)
1292           the segments are grouped by
1293           leading power products (lpp) of the reduced Groebner
1294           basis and given in P-representation.
1295           The returned list is of the form:
1296           (
1297             (lpp, (num,basis,segment),...,(num,basis,segment),lpp),
1298             ..,,
1299             (lpp, (num,basis,segment),...,(num,basis,segment),lpp)
1300           )
1301           The bases are the reduced Groebner bases (after normalization)
1302           for each point of the corresponding segment.
1303
1304           The third element of each lpp segment is the lpp of the
1305           used ideal in the CGS as a string:
1306            with option (\"can\",0) the homogenized basis is used
1307            with option (\"can\",1) the homogenized ideal is used
1308            with option (\"can\",2) the given basis is used
1309
1310          With option (\"out\",1) (default)
1311           only KSW is applied and segments are given as
1312           difference of varieties and are not grouped
1313           The returned list is of the form:
1314           (
1315             (E,N,B),..(E,N,B)
1316           )
1317           E is the null variety
1318           N is the nonnull variety
1319           segment = V(E)\V(N)
1320           B is the reduced Groebner basis
1321
1322NOTE:     The basering R, must be of the form Q[a][x], a=parameters,
1323          x=variables, and should be defined previously, and the ideal
1324          defined on R.
1325KEYWORDS: CGS, disjoint, reduced, Comprehensive Groebner System
1326EXAMPLE:  cgsdr; shows an example"
1327{
1328  int te;
1329  def RR=basering;
1330  if(defined(@P)){te=1;}
1331  else{te=0; setglobalrings();}
1332  // INITIALIZING OPTIONS
1333  int i; int j;
1334  int can=2;
1335  int out=1;
1336  poly f;
1337  ideal B;
1338  def E=ideal(0);
1339  def N=ideal(1);
1340  int comment=0;
1341  int start=timer;
1342  list L=#;
1343  for(i=1;i<=size(L) div 2;i++)
1344  {
1345    if(L[2*i-1]=="null"){E=L[2*i];}
1346    else
1347    {
1348      if(L[2*i-1]=="nonnull"){N=L[2*i];}
1349      else
1350      {
1351        if(L[2*i-1]=="comment"){comment=L[2*i];}
1352        else
1353        {
1354          if(L[2*i-1]=="can"){can=L[2*i];}
1355          else
1356          {
1357            if(L[2*i-1]=="out"){out=L[2*i];}
1358          }
1359        }
1360      }
1361    }
1362  }
1363  //if(can==2){out=1;}
1364  B=F;
1365  if ((printlevel) and (comment==0)){comment=printlevel;}
1366  if((can<2) and (out>0)){"Option out,1 is not compatible with can,0,1"; out=0;}
1367  // DEFINING OPTIONS
1368  list LL;
1369  LL[1]="can";     LL[2]=can;
1370  LL[3]="comment"; LL[4]=comment;
1371  LL[5]="out";     LL[6]=out;
1372  LL[7]="null";    LL[8]=E;
1373  LL[9]="nonnull"; LL[10]=N;
1374  if(comment>=1)
1375  {
1376    string("Begin cgsdr with options: ",LL);
1377  }
1378  int ish;
1379  for (i=1;i<=size(B);i++){ish=ishomog(B[i]); if(ish==0){break;};}
1380  if (ish)
1381  {
1382    if(comment>0){string("The given system is homogneous");}
1383    def GS=KSW(B,LL);
1384    //can=0;
1385  }
1386  else
1387  {
1388  // ACTING DEPENDING ON OPTIONS
1389  if(can==2)
1390  {
1391    // WITHOUT HOMOHGENIZING
1392    if(comment>0){string("Option of cgsdr: do not homogenize");}
1393    def GS=KSW(B,LL);
1394    setglobalrings();
1395  }
1396  else
1397  {
1398    if(can==1)
1399    {
1400      // COMPUTING THE HOMOGOENIZED IDEAL
1401      if(comment>0){string("Homogenizing the whole ideal: option can=1");}
1402      list RRL=ringlist(RR);
1403      RRL[3][1][1]="dp";
1404      def Pa=ring(RRL[1]);
1405      list Lx;
1406      Lx[1]=0;
1407      Lx[2]=RRL[2]+RRL[1][2];
1408      Lx[3]=RRL[1][3];
1409      Lx[4]=RRL[1][4];
1410      RRL[1]=0;
1411      def D=ring(RRL);
1412      def RP=D+Pa;
1413      setring(RP);
1414      def B1=imap(RR,B);
1415      option(redSB);
1416      B1=std(B1);
1417      setring(RR);
1418      def B2=imap(RP,B1);
1419    }
1420    else
1421    { // (can=0)
1422       if(comment>0){string("Homogenizing the basis: option can=0");}
1423      def B2=B;
1424    }
1425    // COMPUTING HOMOGENIZED CGS
1426    poly @t;
1427    ring H=0,@t,dp;
1428    def RH=RR+H;
1429    setring(RH);
1430    setglobalrings();
1431    def BH=imap(RR,B2);
1432    def LH=imap(RR,LL);
1433    for (i=1;i<=size(BH);i++)
1434    {
1435      BH[i]=homog(BH[i],@t);
1436    }
1437    if (comment>=1){string("Homogenized system = "); BH;}
1438    def GSH=KSW(BH,LH);
1439    setglobalrings();
1440    // DEHOMOGENIZING THE RESULT
1441    if(out==0)
1442    {
1443      for (i=1;i<=size(GSH);i++)
1444      {
1445        GSH[i][1]=subst(GSH[i][1],@t,1);
1446        for(j=1;j<=size(GSH[i][2]);j++)
1447        {
1448          GSH[i][2][j][2]=subst(GSH[i][2][j][2],@t,1);
1449        }
1450      }
1451    }
1452    else
1453    {
1454      for (i=1;i<=size(GSH);i++)
1455      {
1456        GSH[i][3]=subst(GSH[i][3],@t,1);
1457        GSH[i][7]=subst(GSH[i][7],@t,1);
1458      }
1459    }
1460    setring(RR);
1461    def GS=imap(RH,GSH);
1462    }
1463
1464
1465    setglobalrings();
1466    if(out==0)
1467    {
1468      for (i=1;i<=size(GS);i++)
1469      {
1470        GS[i][1]=postredgb(mingb(GS[i][1]));
1471        for(j=1;j<=size(GS[i][2]);j++)
1472        {
1473          GS[i][2][j][2]=postredgb(mingb(GS[i][2][j][2]));
1474        }
1475      }
1476    }
1477    else
1478    {
1479      for (i=1;i<=size(GS);i++)
1480      {
1481        if(GS[i][2]==1)
1482        {
1483          GS[i][3]=postredgb(mingb(GS[i][3]));
1484          GS[i][7]=postredgb(mingb(GS[i][7]));
1485        }
1486      }
1487    }
1488  }
1489  if(te==0){kill @P; kill @R; kill @RP;}
1490  return(GS);
1491}
1492example
1493{ "EXAMPLE:"; echo = 2;
1494  "Casas conjecture for degree 4";
1495  ring R=(0,a0,a1,a2,a3,a4),(x1,x2,x3),dp;
1496  ideal F=x1^4+(4*a3)*x1^3+(6*a2)*x1^2+(4*a1)*x1+(a0),
1497          x1^3+(3*a3)*x1^2+(3*a2)*x1+(a1),
1498          x2^4+(4*a3)*x2^3+(6*a2)*x2^2+(4*a1)*x2+(a0),
1499          x2^2+(2*a3)*x2+(a2),
1500          x3^4+(4*a3)*x3^3+(6*a2)*x3^2+(4*a1)*x3+(a0),
1501          x3+(a3);
1502  cgsdr(F);
1503}
1504
1505// input:  internal routine called by cgsdr at the end to group the
1506//            lpp segments and improve the output
1507// output: grouped segments by lpp obtained in cgsdr
1508proc grsegments(list T)
1509{
1510  int i;
1511  list L;
1512  list lpp;
1513  list lp;
1514  list ls;
1515  int n=size(T);
1516  lpp[1]=T[n][1];
1517  L[1]=list(lpp[1],list(list(T[n][2],T[n][3],T[n][4])));
1518  if (n>1)
1519  {
1520    for (i=1;i<=size(T)-1;i++)
1521    {
1522      lp=memberpos(T[n-i][1],lpp);
1523      if(lp[1]==1)
1524      {
1525        ls=L[lp[2]][2];
1526        ls[size(ls)+1]=list(T[n-i][2],T[n-i][3],T[n-i][4]);
1527        L[lp[2]][2]=ls;
1528      }
1529      else
1530      {
1531        lpp[size(lpp)+1]=T[n-i][1];
1532        L[size(L)+1]=list(T[n-i][1],list(list(T[n-i][2],T[n-i][3],T[n-i][4])));
1533      }
1534    }
1535  }
1536  return(L);
1537}
1538
1539// idcontains
1540// input: ideal p, ideal q
1541// output: 1 if p contains q,  0 otherwise
1542// If the routine is to be called from the top, a previous call to
1543// setglobalrings() is needed.
1544proc idcontains(ideal p, ideal q)
1545{
1546  int t; int i;
1547  t=1; i=1;
1548  def RR=basering;
1549  setring(@P);
1550  def P=imap(RR,p);
1551  def Q=imap(RR,q);
1552  attrib(P,"isSB",1);
1553  poly r;
1554  while ((t) and (i<=size(Q)))
1555  {
1556    r=reduce(Q[i],P);
1557    if (r!=0){t=0;}
1558    i++;
1559  }
1560  setring(RR);
1561  return(t);
1562}
1563
1564// selectminindeals
1565//   given a list of ideals returns the list of integers corresponding
1566//   to the minimal ideals in the list
1567// input: L (list of ideals)
1568// output: the list of integers corresponding to the minimal ideals in L
1569// If the routine is to be called from the top, a previous call to
1570// setglobalrings() is needed.
1571proc selectminideals(list L)
1572{
1573  if (size(L)==0){return(L)};
1574  def RR=basering;
1575  setring(@P);
1576  def Lp=imap(RR,L);
1577  int i; int j; int t; intvec notsel;
1578  list P;
1579  for (i=1;i<=size(Lp);i++)
1580  {
1581    if(memberpos(i,notsel)[1])
1582    {
1583      i++;
1584      if(i>size(Lp)){break;}
1585    }
1586    t=1;
1587    j=1;
1588    while ((t) and (j<=size(Lp)))
1589    {
1590      if (i==j){j++;}
1591      if ((j<=size(Lp)) and (memberpos(j,notsel)[1]==0))
1592      {
1593
1594        if (idcontains(Lp[i],Lp[j]))
1595        {
1596          notsel[size(notsel)+1]=i;
1597          t=0;
1598        }
1599      }
1600      j++;
1601    }
1602    if (t){P[size(P)+1]=i;}
1603  }
1604  setring(RR);
1605  return(P);
1606}
1607
1608// LCUnion
1609// Given a list of the P-representations of disjoint locally closed segments
1610// for which we know that the union is also locally closed
1611// it returns the P-representation of its union
1612// input:  L list of segments in P-representation
1613//      ((p_j^i,(p_j1^i,...,p_jk_j^i | j=1..t_i)) | i=1..s )
1614//      where i represents a segment
1615// output: P-representation of the union
1616//       ((P_j,(P_j1,...,P_jk_j | j=1..t)))
1617// If the routine is to be called from the top, a previous call to
1618// setglobalrings() is needed.
1619// Auxiliary routine called by grobcov and addcons
1620// A previous call to setglobarings() is needed if it is to be used at the top.
1621proc LCUnion(list LL)
1622{
1623  def RR=basering;
1624  setring(@P);
1625  int care;
1626  def L=imap(RR,LL);
1627  int i; int j; int k; list H; list C; list T;
1628  list L0; list P0; list P; list Q0; list Q;  intvec Qi;
1629  if(not(defined(@Q2))){list @Q2;}
1630  else{kill @Q2; list @Q2;}
1631  exportto(Top,@Q2);
1632  for (i=1;i<=size(L);i++)
1633  {
1634    for (j=1;j<=size(L[i]);j++)
1635    {
1636      P0[size(P0)+1]=L[i][j][1];
1637      L0[size(L0)+1]=intvec(i,j);
1638    }
1639  }
1640  Q0=selectminideals(P0);
1641  //"T_3Q0="; Q0;
1642  kill P; list P;
1643  for (i=1;i<=size(Q0);i++)
1644  {
1645    Qi=L0[Q0[i]];
1646    Q[size(Q)+1]=Qi;
1647      P[size(P)+1]=L[Qi[1]][Qi[2]];
1648  }
1649  @Q2=Q;
1650  if(size(P)==0)
1651  {
1652    setring(RR);
1653    list TT;
1654    return(TT);
1655  }
1656  // P is the list of the maximal components of the union
1657  //   with the corresponding initial holes.
1658  // Q is the list of intvec positions in L of the first element of the P's
1659  //   Its elements give (num of segment, num of max component (=min ideal))
1660  for (k=1;k<=size(Q);k++)
1661  {
1662    H=P[k][2]; // holes of P[k][1]
1663    for (i=1;i<=size(L);i++)
1664    {
1665      if (i!=Q[k][1])
1666      {
1667        for (j=1;j<=size(L[i]);j++)
1668        {
1669          C[size(C)+1]=L[i][j];
1670          C[size(C)][3]=intvec(i,j);
1671        }
1672      }
1673    }
1674    if(size(P[k])>=3){T[size(T)+1]=list(Q[k],P[k][1],addpart(H,C),P[k][3]);}
1675    else{T[size(T)+1]=list(Q[k],P[k][1],addpart(H,C));}
1676  }
1677  @Q2=sortpairs(@Q2);
1678  setring(RR);
1679  def TT=imap(@P,T);
1680  return(TT);
1681}
1682
1683// Auxiliary routine
1684// called by LCUnion to modify the holes of a primepart of the union
1685// by the addition of the segments that do not correspond to that part
1686// Works on @P ring.
1687// Input:
1688//   H=(p_i1,..,p_is) the holes of a component to be transformed by the addition of
1689//        the segments C that do not correspond to that component
1690//   C=((q_1,(q_11,..,q_1l_1),pos1),..,(q_k,(q_k1,..,q_kl_k),posk))
1691// posi=(i,j) position of the component
1692//        the list of segments to be added to the holes
1693proc addpart(list H, list C)
1694{
1695  list Q; int i; int j; int k; int l; int t; int t1;
1696  Q=H; intvec notQ; list QQ; list addq;
1697  // @Q2=list of (i,j) positions of the components that have been aded to some hole of the maximal ideals
1698  //          plus those of the components added to the holes.
1699  ideal q;
1700  i=1;
1701  while (i<=size(Q))
1702  {
1703    if (memberpos(i,notQ)[1]==0)
1704    {
1705      q=Q[i];
1706      t=1; j=1;
1707      while ((t) and (j<=size(C)))
1708      {
1709        if (equalideals(q,C[j][1]))
1710        {
1711          @Q2[size(@Q2)+1]=C[j][3];
1712          t=0;
1713          for (k=1;k<=size(C[j][2]);k++)
1714          {
1715            t1=1;
1716            //kill addq;
1717            //list addq;
1718            l=1;
1719            while((t1) and (l<=size(Q)))
1720            {
1721              if ((l!=i) and (memberpos(l,notQ)[1]==0))
1722              {
1723                if (idcontains(C[j][2][k],Q[l]))
1724                {
1725                  t1=0;
1726                }
1727              }
1728              l++;
1729            }
1730            if (t1)
1731            {
1732              addq[size(addq)+1]=C[j][2][k];
1733              @Q2[size(@Q2)+1]=C[j][3];
1734            }
1735          }
1736          if((size(notQ)==1) and (notQ[1]==0)){notQ[1]=i;}
1737          else {notQ[size(notQ)+1]=i;}
1738        }
1739        j++;
1740      }
1741      if (size(addq)>0)
1742      {
1743        for (k=1;k<=size(addq);k++)
1744        {
1745          Q[size(Q)+1]=addq[k];
1746        }
1747        kill addq;
1748        list addq;
1749      }
1750      //print("Q="); Q; print("notQ="); notQ;
1751    }
1752    i++;
1753  }
1754  for (i=1;i<=size(Q);i++)
1755  {
1756    if(memberpos(i,notQ)[1]==0)
1757    {
1758      QQ[size(QQ)+1]=Q[i];
1759    }
1760  }
1761  if (size(QQ)==0){QQ[1]=ideal(1);}
1762  return(addpartfine(QQ,C));
1763}
1764
1765// Auxiliary routine called by addpart to finish the modification of the holes of a primepart
1766// of the union by the addition of the segments that do not correspond to
1767// that part.
1768// Works on @P ring.
1769proc addpartfine(list H, list C0)
1770{
1771  int i; int j; int k; int te; intvec notQ; int l; list sel; int used;
1772  intvec jtesC;
1773  if ((size(H)==1) and (equalideals(H[1],ideal(1)))){return(H);}
1774  if (size(C0)==0){return(H);}
1775  def RR=basering;
1776  setring(@P);
1777  list newQ; list nQ; list Q; list nQ1; list Q0;
1778  def Q1=imap(RR,H);
1779  //Q1=sortlistideals(Q1);
1780  def C=imap(RR,C0);
1781  while(equallistideals(Q0,Q1)==0)
1782  {
1783    Q0=Q1;
1784    i=0;
1785    Q=Q1;
1786    kill notQ; intvec notQ;
1787    while(i<size(Q))
1788    {
1789      i++;
1790      for(j=1;j<=size(C);j++)
1791      {
1792        te=idcontains(Q[i],C[j][1]);
1793        if(te)
1794        {
1795          for(k=1;k<=size(C[j][2]);k++)
1796          {
1797            if(idcontains(Q[i],C[j][2][k]))
1798            {
1799              te=0; break;
1800            }
1801          }
1802          if (te)
1803          {
1804            used++;
1805            if ((size(notQ)==1) and (notQ[1]==0)){notQ[1]=i;}
1806            else{notQ[size(notQ)+1]=i;}
1807            kill newQ; list newQ;
1808            for(k=1;k<=size(C[j][2]);k++)
1809            {
1810              nQ=minGTZ(Q[i]+C[j][2][k]);
1811              for(l=1;l<=size(nQ);l++)
1812              {
1813                option(redSB);
1814                nQ[l]=std(nQ[l]);
1815                newQ[size(newQ)+1]=nQ[l];
1816              }
1817            }
1818            sel=selectminideals(newQ);
1819            kill nQ1; list nQ1;
1820            for(l=1;l<=size(sel);l++)
1821            {
1822              nQ1[l]=newQ[sel[l]];
1823            }
1824            newQ=nQ1;
1825            for(l=1;l<=size(newQ);l++)
1826            {
1827              Q[size(Q)+1]=newQ[l];
1828            }
1829            break;
1830          }
1831        }
1832      }
1833    }
1834    kill Q1; list Q1;
1835    for(i=1;i<=size(Q);i++)
1836    {
1837      if(memberpos(i,notQ)[1]==0)
1838      {
1839        Q1[size(Q1)+1]=Q[i];
1840      }
1841    }
1842    sel=selectminideals(Q1);
1843    kill nQ1; list nQ1;
1844    for(l=1;l<=size(sel);l++)
1845    {
1846      nQ1[l]=Q1[sel[l]];
1847    }
1848    Q1=nQ1;
1849  }
1850  setring(RR);
1851  //if(used>0){string("addpartfine was ", used, " times used");}
1852  return(imap(@P,Q1));
1853}
1854
1855// Auxiliary routine for grobcov: ideal F is assumed to be homogeneous
1856// gcover
1857// input: ideal F: a generating set of a homogeneous ideal in Q[a][x]
1858//    list #: optional
1859// output: the list
1860//   S=((lpp, generic basis, Prep, Crep),..,(lpp, generic basis, Prep, Crep))
1861//      where a Prep is ( (p1,(p11,..,p1k_1)),..,(pj,(pj1,..,p1k_j)) )
1862//            a Crep is ( ida, idb )
1863proc gcover(ideal F,list #)
1864{
1865  int i; int j; int k; ideal lpp; list GPi2; list pairspP; ideal B; int ti;
1866  int i1; int tes; int j1; int selind; int i2; int m;
1867  list prep; list crep; list LCU; poly p; poly lcp; ideal FF;
1868  list lpi;
1869  string lpph;
1870  list L=#;
1871  int canop=1;
1872  int extop=1;
1873  int repop=0;
1874  ideal E=ideal(0);;
1875  ideal N=ideal(1);;
1876  int comment;
1877  for(i=1;i<=size(L) div 2;i++)
1878  {
1879    if(L[2*i-1]=="can"){canop=L[2*i];}
1880    else
1881    {
1882      if(L[2*i-1]=="ext"){extop=L[2*i];}
1883      else
1884      {
1885        if(L[2*i-1]=="rep"){repop=L[2*i];}
1886        else
1887        {
1888          if(L[2*i-1]=="null"){E=L[2*i];}
1889          else
1890          {
1891            if(L[2*i-1]=="nonnull"){N=L[2*i];}
1892            else
1893            {
1894              if (L[2*i-1]=="comment"){comment=L[2*i];}
1895            }
1896          }
1897        }
1898      }
1899    }
1900  }
1901  list GS; list GP;
1902  def RR=basering;
1903  GS=cgsdr(F,L); // "null",NW[1],"nonnull",NW[2],"cgs",CGS,"comment",comment);
1904  setglobalrings();
1905  int start=timer;
1906  GP=GS;
1907  ideal lppr;
1908  list LL;
1909  list S;
1910  poly sp;
1911  ideal BB;
1912  for (i=1;i<=size(GP);i++)
1913  {
1914    kill LL;
1915    list LL;
1916    lpp=GP[i][1];
1917    GPi2=GP[i][2];
1918    lpph=GP[i][3];
1919    kill pairspP; list pairspP;
1920    for(j=1;j<=size(GPi2);j++)
1921    {
1922      pairspP[size(pairspP)+1]=GPi2[j][3];
1923    }
1924    LCU=LCUnion(pairspP);
1925    kill prep; list prep;
1926    kill crep; list crep;
1927    for(k=1;k<=size(LCU);k++)
1928    {
1929      prep[k]=list(LCU[k][2],LCU[k][3]);
1930      B=GPi2[LCU[k][1][1]][2]; // ATENTION last 1 has been changed to [2]
1931      LCU[k][1]=B;
1932    }
1933    //"Deciding if combine is needed";
1934    kill BB;
1935    ideal BB;
1936    tes=1; m=1;
1937    while((tes) and (m<=size(LCU[1][1])))
1938    {
1939      j=1;
1940      while((tes) and (j<=size(LCU)))
1941      {
1942        k=1;
1943        while((tes) and (k<=size(LCU)))
1944        {
1945          if(j!=k)
1946          {
1947            sp=pnormalf(pspol(LCU[j][1][m],LCU[k][1][m]),LCU[k][2],N);
1948            if(sp!=0){tes=0;}
1949          }
1950          k++;
1951        }        //setglobalrings();
1952        if(tes)
1953        {
1954          BB[m]=LCU[j][1][m];
1955        }
1956        j++;
1957      }
1958      if(tes==0){break;}
1959      m++;
1960    }
1961    crep=PtoCrep(prep);
1962    if(tes==0)
1963    {
1964      // combine is needed
1965      kill B; ideal B;
1966      for (j=1;j<=size(LCU);j++)
1967      {
1968        LL[j]=LCU[j][2];
1969      }
1970      if (size(LCU)>1)
1971      {
1972        FF=precombint(LL);
1973      }
1974      for (k=1;k<=size(lpp);k++)
1975      {
1976        kill L; list L;
1977        for (j=1;j<=size(LCU);j++)
1978        {
1979          L[j]=list(LCU[j][2],LCU[j][1][k]);
1980        }
1981        if (size(LCU)>1)
1982        {
1983          B[k]=combine(L,FF);
1984        }
1985        else{B[k]=L[1][2];}
1986      }
1987    }
1988    else{B=BB;}
1989    for(j=1;j<=size(B);j++)
1990    {
1991      B[j]=pnormalf(B[j],crep[1],crep[2]);
1992    }
1993    S[i]=list(lpp,B,prep,crep,lpph);
1994    if(comment>=1)
1995    {
1996      lpi[size(lpi)+1]=string("[",i,"]");
1997      lpi[size(lpi)+1]=S[i][1];
1998    }
1999  }
2000  if(comment>=1)
2001  {
2002    string("Time in LCUnion + combine = ",timer-start);
2003    if(comment>=2){string("lpp=",lpi)};
2004  }
2005  if(defined(@P)==1){kill @P; kill @RP; kill @R;}
2006  return(S);
2007}
2008
2009// grobcov
2010// input:
2011//    ideal F: a parametric ideal in Q[a][x], where a are the parameters
2012//             and x the variables
2013//    list #: (options) list("null",N,"nonnull",W,"can",0-1,ext",0-1, "rep",0-1-2)
2014//            where
2015//            N is the null conditions ideal (if desired)
2016//            W is the ideal of non-null conditions (if desired)
2017//            The value of \"can\"i s 1 by default and can be set to 0 if we do not
2018//            need to obtain the canonical GC, but only a GC.
2019//            The value of \"ext\" is 0 by default and so the generic representation
2020//             of the bases is given. It can be set to 1, and then the full
2021//             representation of the bases is given.
2022//            The value of \"rep\" is 0 by default, and then the segments
2023//            are given in canonical P-representation. It can be set to 1
2024//            and then they are given in canonical C-representation.
2025//            If it is set to 2, then both representations are given.
2026// output:
2027//    list S: ((lpp,basis,(idp_1,(idp_11,..,idp_1s_1))), ..
2028//             (lpp,basis,(idp_r,(idp_r1,..,idp_rs_r))) ) where
2029//            each element of S corresponds to a lpp-segment
2030//            given by the lpp, the basis, and the P-representation of the segment
2031proc grobcov(ideal F,list #)
2032"USAGE:   grobcov(F); This is the fundamental routine of the
2033          library. It computes the Groebner cover of a parametric ideal
2034          (see (*) Montes A., Wibmer M., Groebner Bases for Polynomial
2035          Systems with parameters. JSC 45 (2010) 1391-1425.)
2036          The Groebner cover of a parametric ideal consist of a set of
2037          pairs(S_i,B_i), where the S_i are disjoint locally closed
2038          segments of the parameter space, and the B_i are the reduced
2039          Groebner bases of the ideal on every point of S_i.
2040
2041          The ideal F must be defined on a parametric ring Q[a][x].
2042          Options: To modify the default options, pair of arguments
2043          -option name, value- of valid options must be added to the call.
2044
2045          Options:
2046            \"null\",ideal E: The default is (\"null\",ideal(0)).
2047            \"nonnull\",ideal N: The default (\"nonnull\",ideal(1)).
2048                When options \"null\" and/or \"nonnull\" are given, then
2049                the parameter space is restricted to V(E)\V(N).
2050            \"can\",0-1: The default is (\"can\",1). With the default option
2051                the homogenized ideal is computed before obtaining the
2052                Groebner cover, so that the result is the canonical
2053                Groebner cover. Setting (\"can\",0) only homogenizes the
2054                basis so the result is not exactly canonical, but the
2055                computation is shorter.
2056            \"ext\",0-1: The default is (\"ext\",0). With the default
2057                (\"ext\",0), only the generic representation is computed
2058                (single polynomials, but not specializing to non-zero at
2059                each point of the segment. With option (\"ext\",1) the
2060                full representation of the bases is computed (possible
2061                sheaves) and sometimes a simpler result is obtained.
2062            \"rep\",0-1-2: The default is (\"rep\",0) and then the segments
2063                are given in canonical P-representation. Option (\"rep\",1)
2064                represents the segments in canonical C-representation,
2065                and option (\"rep\",2) gives both representations.
2066            \"comment\",0-3: The default is (\"comment\",0). Setting
2067                \"comment\" higher will provide information about the
2068                development of the computation.
2069          One can give none or whatever of these options.
2070RETURN:   The list
2071          (
2072           (lpp_1,basis_1,segment_1,lpph_1),
2073           ...
2074           (lpp_s,basis_s,segment_s,lpph_s)
2075          )
2076
2077          The lpp are constant over a segment and correspond to the
2078          set of lpp of the reduced Groebner basis for each point
2079          of the segment.
2080          The lpph corresponds to the lpp of the homogenized ideal
2081          and is different for each segment. It is given as a string.
2082
2083          Basis: to each element of lpp corresponds an I-regular function given
2084          in full representation (by option (\"ext\",1)) or in
2085          generic representation (default option (\"ext\",0)). The
2086          I-regular function is the corresponding element of the reduced
2087          Groebner basis for each point of the segment with the given lpp.
2088          For each point in the segment, the polynomial or the set of
2089          polynomials representing it, if they do not specialize to 0,
2090          then after normalization, specializes to the corresponding
2091          element of the reduced Groebner basis. In the full representation
2092          at least one of the polynomials representing the I-regular
2093          function specializes to non-zero.
2094
2095          With the default option (\"rep\",0) the representation of the
2096          segment is the P-representation.
2097          With option (\"rep\",1) the representation of the segment is
2098          the C-representation.
2099          With option (\"rep\",2) both representations of the segment are
2100          given.
2101
2102          The P-representation of a segment is of the form
2103          ((p_1,(p_11,..,p_1k1)),..,(p_r,(p_r1,..,p_rkr))
2104          representing the segment U_i (V(p_i) \ U_j (V(p_ij))),
2105          where the p's are prime ideals.
2106
2107          The C-representation of a segment is of the form
2108          (E,N) representing V(E)\V(N), and the ideals E and N are
2109          radical and N contains E.
2110
2111NOTE: The basering R, must be of the form Q[a][x], a=parameters,
2112          x=variables, and should be defined previously. The ideal must
2113          be defined on R.
2114KEYWORDS: Groebner cover, parametric ideal, canonical, discussion of
2115          parametric ideal.
2116EXAMPLE:  grobcov; shows an example"
2117{
2118  list S; int i; int ish=1; list GBR; list BR; int j; int k;
2119  ideal idp; ideal idq; int s; ideal ext; list SS;
2120  ideal E; ideal N; int canop;  int extop; int repop;
2121  int comment=0; int m;
2122  def RR=basering;
2123  setglobalrings();
2124  list L0=#;
2125  int out=0;
2126  L0[size(L0)+1]="res"; L0[size(L0)+1]=ideal(1);
2127  // default options
2128  int start=timer;
2129  E=ideal(0);
2130  N=ideal(1);
2131  canop=1; // canop=0 for homogenizing the basis but not the ideal (not canonical)
2132           // canop=1 for working with the homogenized ideal
2133  repop=0; // repop=0 for representing the segments in Prep
2134           // repop=1 for representing the segments in Crep
2135           // repop=2 for representing the segments in Prep and Crep
2136  extop=0; // extop=0 if only generic representation of the bases are to be computed
2137           // extop=1 if the full representation of the bases are to be computed
2138  for(i=1;i<=size(L0) div 2;i++)
2139  {
2140    if(L0[2*i-1]=="can"){canop=L0[2*i];}
2141    else
2142    {
2143      if(L0[2*i-1]=="ext"){extop=L0[2*i];}
2144      else
2145      {
2146        if(L0[2*i-1]=="rep"){repop=L0[2*i];}
2147        else
2148        {
2149          if(L0[2*i-1]=="null"){E=L0[2*i];}
2150          else
2151          {
2152            if(L0[2*i-1]=="nonnull"){N=L0[2*i];}
2153            else
2154            {
2155              if (L0[2*i-1]=="comment"){comment=L0[2*i];}
2156            }
2157          }
2158        }
2159      }
2160    }
2161  }
2162  if(not((canop==0) or (canop==1)))
2163  {
2164    string("Option can = ",canop," is not supported. It is changed to can = 1");
2165    canop=1;
2166  }
2167  for(i=1;i<=size(L0) div 2;i++)
2168  {
2169    if(L0[2*i-1]=="can"){L0[2*i]=canop;}
2170  }
2171  if ((printlevel) and (comment==0)){comment=printlevel;}
2172  list LL;
2173  LL[1]="can";     LL[2]=canop;
2174  LL[3]="comment"; LL[4]=comment;
2175  LL[5]="out";     LL[6]=0;
2176  LL[7]="null";    LL[8]=E;
2177  LL[9]="nonnull"; LL[10]=N;
2178  LL[11]="ext";    LL[12]=extop;
2179  LL[13]="rep";    LL[14]=repop;
2180  if (comment>=1)
2181  {
2182    string("Begin grobcov with options: ",LL);
2183  }
2184  kill S;
2185  def S=gcover(F,LL);
2186  // NOW extend
2187  if(extop)
2188  {
2189    S=extend(S,LL);
2190  }
2191  else
2192  {
2193    // NOW representation of the segments by option repop
2194    list Si; list nS;
2195    if(repop==0)
2196    {
2197      for(i=1;i<=size(S);i++)
2198      {
2199        Si=list(S[i][1],S[i][2],S[i][3],S[i][5]);
2200        nS[size(nS)+1]=Si;
2201      }
2202      kill S;
2203      def S=nS;
2204    }
2205    else
2206    {
2207      if(repop==1)
2208      {
2209        for(i=1;i<=size(S);i++)
2210        {
2211          Si=list(S[i][1],S[i][2],S[i][4],S[i][5]);
2212          nS[size(nS)+1]=Si;
2213        }
2214        kill S;
2215        def S=nS;
2216      }
2217      else
2218      {
2219        for(i=1;i<=size(S);i++)
2220        {
2221          Si=list(S[i][1],S[i][2],S[i][3],S[i][4],S[i][5]);
2222          nS[size(nS)+1]=Si;
2223        }
2224        kill S;
2225        def S=nS;
2226      }
2227    }
2228  }
2229  if (comment>=1)
2230  {
2231    string("Time in grobcov = ", timer-start);
2232    string("Number of segments of grobcov = ", size(S));
2233  }
2234  if(defined(@P)==1){kill @R; kill @P; kill @RP;}
2235  return(S);
2236}
2237example
2238{ "EXAMPLE:"; echo = 2;
2239  "Casas conjecture for degree 4";
2240  ring R=(0,a0,a1,a2,a3,a4),(x1,x2,x3),dp;
2241  ideal F=x1^4+(4*a3)*x1^3+(6*a2)*x1^2+(4*a1)*x1+(a0),
2242          x1^3+(3*a3)*x1^2+(3*a2)*x1+(a1),
2243          x2^4+(4*a3)*x2^3+(6*a2)*x2^2+(4*a1)*x2+(a0),
2244          x2^2+(2*a3)*x2+(a2),
2245          x3^4+(4*a3)*x3^3+(6*a2)*x3^2+(4*a1)*x3+(a0),
2246          x3+(a3);
2247  grobcov(F);
2248}
2249
2250// Input. GC the grobcov of an ideal in generic representation of the
2251//        bases computed with option option ("rep",2).
2252// Output The grobcov in full representation.
2253// Option ("comment",1) shows the time.
2254// Can be called from the top
2255proc extend(list GC, list #);
2256"USAGE:   extend(GC); When the grobcov of an ideal has been computed
2257          with the default option (\"ext\",0) and the explicit option
2258          (\"rep\",2) (which is not the default), then one can call
2259          extend (GC) (and options) to obtain the full representation
2260          of the bases. With the default option (\"ext\",0) only the
2261          generic representation of the bases are computed, and one can
2262          obtain the full representation using extend.
2263            \"rep\",0-1-2: The default is (\"rep\",0) and then the segments
2264                are given in canonical P-representation. Option (\"rep\",1)
2265                represents the segments in canonical C-representation,
2266                and option (\"rep\",2) gives both representations.
2267            \"comment\",0-1: The default is (\"comment\",0). Setting
2268                \"comment\" higher will provide information about the
2269                time used in the computation.
2270          One can give none or whatever of these options.
2271RETURN:   The list
2272          (
2273           (lpp_1,basis_1,segment_1,lpph_1),
2274           ...
2275           (lpp_s,basis_s,segment_s,lpph_s)
2276          )
2277
2278          The lpp are constant over a segment and correspond to the
2279          set of lpp of the reduced Groebner basis for each point
2280          of the segment.
2281          The lpph corresponds to the lpp of the homogenized ideal
2282          and is different for each segment. It is given as a string.
2283
2284          Basis: to each element of lpp corresponds an I-regular function given
2285          in full representation. The
2286          I-regular function is the corresponding element of the reduced
2287          Groebner basis for each point of the segment with the given lpp.
2288          For each point in the segment, the polynomial or the set of
2289          polynomials representing it, if they do not specialize to 0,
2290          then after normalization, specializes to the corresponding
2291          element of the reduced Groebner basis. In the full representation
2292          at least one of the polynomials representing the I-regular
2293          function specializes to non-zero.
2294
2295          With the default option (\"rep\",0) the segments are given
2296          in P-representation.
2297          With option (\"rep\",1) the segments are given
2298          in C-representation.
2299          With option (\"rep\",2) both representations of the segments are
2300          given.
2301
2302          The P-representation of a segment is of the form
2303          ((p_1,(p_11,..,p_1k1)),..,(p_r,(p_r1,..,p_rkr))
2304          representing the segment U_i (V(p_i) \ U_j (V(p_ij))),
2305          where the p's are prime ideals.
2306
2307          The C-representation of a segment is of the form
2308          (E,N) representing V(E)\V(N), and the ideals E and N are
2309          radical and N contains E.
2310
2311NOTE: The basering R, must be of the form Q[a][x], a=parameters,
2312          x=variables, and should be defined previously. The ideal must
2313          be defined on R.
2314KEYWORDS: Groebner cover, parametric ideal, canonical, discussion of
2315          parametric ideal, full representation.
2316EXAMPLE:  extend; shows an example"
2317{
2318  list L=#;
2319  list S=GC;
2320  ideal idp;
2321  ideal idq;
2322  int i; int j; int m; int s;
2323  m=0; i=1;
2324  while((i<=size(S)) and (m==0))
2325  {
2326    if(typeof(S[i][2])=="list"){m=1;}
2327    i++;
2328  }
2329  if(m==1){"Warning! grobcov has already extended bases"; return(S);}
2330  if(size(GC[1])!=5){"Warning! extend make sense only when grobcov has been called with options 'rep',2,'ext',0"; " "; return();}
2331  int repop=0;
2332  int start3=timer;
2333  int comment;
2334  for(i=1;i<=size(L) div 2;i++)
2335  {
2336    if(L[2*i-1]=="comment"){comment=L[2*i];}
2337    else
2338    {
2339      if(L[2*i-1]=="rep"){repop=L[2*i];}
2340    }
2341  }
2342  poly leadc;
2343  poly ext;
2344  int te=0;
2345  list SS;
2346  def R=basering;
2347  if (defined(@R)){te=1;}
2348  else{setglobalrings();}
2349  // Now extend
2350  for (i=1;i<=size(S);i++)
2351  {
2352    m=size(S[i][2]);
2353     for (j=1;j<=m;j++)
2354    {
2355      idp=S[i][4][1];
2356      idq=S[i][4][2];
2357      if (size(idp)>0)
2358      {
2359        leadc=leadcoef(S[i][2][j]);
2360        kill ext;
2361        def ext=extend0(S[i][2][j],idp,idq);
2362        if (typeof(ext)=="poly")
2363        {
2364          S[i][2][j]=pnormalf(ext,idp,idq);
2365        }
2366        else
2367        {
2368          if(size(ext)==1)
2369          {
2370            S[i][2][j]=ext[1];
2371          }
2372          else
2373          {
2374            kill SS; list SS;
2375            for(s=1;s<=size(ext);s++)
2376            {
2377              ext[s]=pnormalf(ext[s],idp,idq);
2378            }
2379            for(s=1;s<=size(S[i][2]);s++)
2380            {
2381              if(s!=j){SS[s]=S[i][2][s];}
2382              else{SS[s]=ext;}
2383            }
2384            S[i][2]=SS;
2385          }
2386        }
2387      }
2388    }
2389  }
2390  // NOW representation of the segments by option repop
2391  list Si; list nS;
2392  if (repop==0)
2393  {
2394    for(i=1;i<=size(S);i++)
2395    {
2396      Si=list(S[i][1],S[i][2],S[i][3],S[i][5]);
2397      nS[size(nS)+1]=Si;
2398    }
2399    S=nS;
2400  }
2401  else
2402  {
2403    if (repop==1)
2404    {
2405      for(i=1;i<=size(S);i++)
2406      {
2407        Si=list(S[i][1],S[i][2],S[i][4],S[i][5]);
2408        nS[size(nS)+1]=Si;
2409      }
2410      S=nS;
2411    }
2412    else
2413    {
2414      for(i=1;i<=size(S);i++)
2415      {
2416        Si=list(S[i][1],S[i][2],S[i][3],S[i][4],S[i][5]);
2417        nS[size(nS)+1]=Si;
2418      }
2419
2420    }
2421  }
2422  if(comment>=1){string("Time in extend = ",timer-start3);}
2423  if(te==0){kill @R; kill @RP; kill @P;}
2424  return(S);
2425}
2426example
2427{
2428  ring R=(0,a0,b0,c0,a1,b1,c1,a2,b2,c2),(x), dp;
2429  short=0;
2430  ideal S=a0*x^2+b0*x+c0,
2431          a1*x^2+b1*x+c1,
2432          a2*x^2+b2*x+c2;
2433  "System S="; S;
2434
2435  def GCS=grobcov(S,"rep",2,"comment",1);
2436  "grobcov(S,'rep',2,'comment',1)="; GCS;
2437  def FGC=extend(GCS,"rep",0,"comment",1);
2438  "Full representation="; FGC;
2439}
2440
2441// Auxiliary routine
2442// nonzerodivisor
2443// input:
2444//    poly g in K[a],
2445//    list P=(p_1,..p_r) representing a minimal prime decomposition
2446// output
2447//    poly f such that f notin p_i for all i and
2448//           g-f in p_i for all i such that g notin p_i
2449proc nonzerodivisor(poly gr, list Pr)
2450{
2451  def RR=basering;
2452  setring(@P);
2453  def g=imap(RR,gr);
2454  def P=imap(RR,Pr);
2455  int i; int k;  list J; ideal F;
2456  def f=g;
2457  ideal Pi;
2458  for (i=1;i<=size(P);i++)
2459  {
2460    option(redSB);
2461    Pi=std(P[i]);
2462    //attrib(Pi,"isSB",1);
2463    if (reduce(g,Pi,1)==0){J[size(J)+1]=i;}
2464  }
2465  for (i=1;i<=size(J);i++)
2466  {
2467    F=ideal(1);
2468    for (k=1;k<=size(P);k++)
2469    {
2470      if (k!=J[i])
2471      {
2472        F=idint(F,P[k]);
2473      }
2474    }
2475    f=f+F[1];
2476  }
2477  setring(RR);
2478  def fr=imap(@P,f);
2479  return(fr);
2480}
2481
2482// Auxiliary routine
2483// deltai
2484// input:
2485//   int i:
2486//   list LPr: (p1,..,pr) of prime components of an ideal in K[a]
2487// output:
2488//   list (fr,fnr) of two polynomials that are equal on V(pi)
2489//       and fr=0 on V(P) \ V(pi), and fnr is nonzero on V(pj) for all j.
2490proc deltai(int i, list LPr)
2491{
2492  def RR=basering;
2493  setring(@P);
2494  def LP=imap(RR,LPr);
2495  int j; poly p;
2496  def F=ideal(1);
2497  poly f;
2498  poly fn;
2499  ideal LPi;
2500  for (j=1;j<=size(LP);j++)
2501  {
2502    if (j!=i)
2503    {
2504      F=idint(F,LP[j]);
2505    }
2506  }
2507  p=0; j=1;
2508  while ((p==0) and (j<=size(F)))
2509  {
2510    LPi=LP[i];
2511    attrib(LPi,"isSB",1);
2512    p=reduce(F[j],LPi);
2513    j++;
2514  }
2515  f=F[j-1];
2516  fn=nonzerodivisor(f,LP);
2517  setring(RR);
2518  def fr=imap(@P,f);
2519  def fnr=imap(@P,fn);
2520  return(list(fr,fnr));
2521}
2522
2523// Auxiliary routine
2524// combine
2525// input: a list of pairs ((p1,P1),..,(pr,Pr)) where
2526//    ideal pi is a prime component
2527//    poly Pi is the polynomial in Q[a][x] on V(pi)\ V(Mi)
2528//    (p1,..,pr) are the prime decomposition of the lpp-segment
2529//    list crep =(ideal ida,ideal idb): the Crep of the segment.
2530//    list Pci of the intersecctions of all pj except the ith one
2531// output:
2532//    poly P on an open and dense set of V(p_1 int ... p_r)
2533proc combine(list L, ideal F)
2534{
2535  // ATTENTION REVISE AND USE Pci and F
2536  int i; poly f;
2537  f=0;
2538  for(i=1;i<=size(L);i++)
2539  {
2540    f=f+F[i]*L[i][2];
2541  }
2542//   f=elimconstfac(f);
2543  f=primepartZ(f);
2544  return(f);
2545}
2546
2547// Auxiliary routine
2548// elimconstfac: eliminate the factors in the polynom f that are in K[a]
2549// input:
2550//   poly f:
2551//   list L: of components of the segment
2552// output:
2553//   poly f2  where the factors of f in K[a] that are non-null on any component
2554//   have been dropped from f
2555proc elimconstfac(poly f)
2556{
2557  int cond; int i; int j; int t;
2558  if (f==0){return(f);}
2559  def RR=basering;
2560  setring(@R);
2561  def ff=imap(RR,f);
2562  def l=factorize(ff,0);
2563  poly f1=1;
2564  for(i=2;i<=size(l[1]);i++)
2565  {
2566      f1=f1*(l[1][i])^(l[2][i]);
2567  }
2568  setring(RR);
2569  def f2=imap(@R,f1);
2570  return(f2);
2571};
2572
2573//Auxiliary routine
2574// nullin
2575// input:
2576//   poly f:  a polynomial in Q[a]
2577//   ideal P: an ideal in Q[a]
2578//   called from ring @R
2579// output:
2580//   t:  with value 1 if f reduces modulo P, 0 if not.
2581proc nullin(poly f,ideal P)
2582{
2583  int t;
2584  def RR=basering;
2585  setring(@P);
2586  def f0=imap(RR,f);
2587  def P0=imap(RR,P);
2588  attrib(P0,"isSB",1);
2589  if (reduce(f0,P0,1)==0){t=1;}
2590  else{t=0;}
2591  setring(RR);
2592  return(t);
2593}
2594
2595// Auxiliary routine
2596// monoms
2597// Input: A polynomial f
2598// Output: The list of leading terms
2599proc monoms(poly f)
2600{
2601  list L;
2602  poly lm; poly lc; poly lp; poly Q; poly mQ;
2603  def p=f;
2604  int i=1;
2605  while (p!=0)
2606  {
2607    lm=lead(p);
2608    p=p-lm;
2609    lc=leadcoef(lm);
2610    lp=leadmonom(lm);
2611    L[size(L)+1]=list(lc,lp);
2612    i++;
2613  }
2614  return(L);
2615}
2616
2617// Auxiliary routine called by extend
2618// extend0
2619// input:
2620//   poly f: a generic polynomial in the basis
2621//   ideal idp: such that ideal(S)=idp
2622//   ideal idq: such that S=V(idp)\V(idq)
2623////   NW the list of ((N1,W1),..,(Ns,Ws)) of red-rep of the grouped
2624////      segments in the lpp-segment  NO MORE USED
2625// output:
2626proc extend0(poly f, ideal idp, ideal idq)
2627{
2628  matrix CC; poly Q; list NewMonoms;
2629  int i;  int j;  poly fout; ideal idout;
2630  list L=monoms(f);
2631  int nummonoms=size(L)-1;
2632  Q=L[1][1];
2633  if (nummonoms==0){return(f);}
2634  for (i=2;i<=size(L);i++)
2635  {
2636    CC=matrix(extendcoef(L[i][1],Q,idp,idq));
2637    NewMonoms[i-1]=list(CC,L[i][2]);
2638  }
2639  if (nummonoms==1)
2640  {
2641    for(j=1;j<=ncols(NewMonoms[1][1]);j++)
2642    {
2643      fout=NewMonoms[1][1][2,j]*L[1][2]+NewMonoms[1][1][1,j]*NewMonoms[1][2];
2644      //fout=pnormalf(fout,idp,W);
2645      if(ncols(NewMonoms[1][1])>1){idout[j]=fout;}
2646    }
2647    if(ncols(NewMonoms[1][1])==1){return(fout);} else{return(idout);}
2648  }
2649  else
2650  {
2651    list cfi;
2652    list coefs;
2653    for (i=1;i<=nummonoms;i++)
2654    {
2655      kill cfi; list cfi;
2656      for(j=1;j<=ncols(NewMonoms[i][1]);j++)
2657      {
2658        cfi[size(cfi)+1]=NewMonoms[i][1][2,j];
2659      }
2660      coefs[i]=cfi;
2661    }
2662    def indexpolys=findindexpolys(coefs);
2663    for(i=1;i<=size(indexpolys);i++)
2664    {
2665      fout=L[1][2];
2666      for(j=1;j<=nummonoms;j++)
2667      {
2668        fout=fout+(NewMonoms[j][1][1,indexpolys[i][j]])/(NewMonoms[j][1][2,indexpolys[i][j]])*NewMonoms[j][2];
2669      }
2670      fout=cleardenom(fout);
2671      if(size(indexpolys)>1){idout[i]=fout;}
2672    }
2673    if (size(indexpolys)==1){return(fout);} else{return(idout);}
2674  }
2675}
2676
2677// Auxiliary routine
2678// findindexpolys
2679// input:
2680//   list coefs=( (q11,..,q1r_1),..,(qs1,..,qsr_1) )
2681//               of denominators of the monoms
2682// output:
2683//   list ind=(v_1,..,v_t) of intvec
2684//        each intvec v=(i_1,..,is) corresponds to a polynomial in the sheaf
2685//        that will be built from it in extend procedure.
2686proc findindexpolys(list coefs)
2687{
2688  int i; int j; intvec numdens;
2689  for(i=1;i<=size(coefs);i++)
2690  {
2691    numdens[i]=size(coefs[i]);
2692  }
2693  def RR=basering;
2694  setring(@P);
2695  def coefsp=imap(RR,coefs);
2696  ideal cof; list combpolys; intvec v; int te; list mp;
2697  for(i=1;i<=size(coefsp);i++)
2698  {
2699    cof=ideal(0);
2700    for(j=1;j<=size(coefsp[i]);j++)
2701    {
2702      cof[j]=factorize(coefsp[i][j],3);
2703    }
2704    coefsp[i]=cof;
2705  }
2706  for(j=1;j<=size(coefsp[1]);j++)
2707  {
2708    v[1]=j;
2709    te=1;
2710    for (i=2;i<=size(coefsp);i++)
2711    {
2712      mp=memberpos(coefsp[1][j],coefsp[i]);
2713      if(mp[1])
2714      {
2715        v[i]=mp[2];
2716      }
2717      else{v[i]=0;}
2718    }
2719    combpolys[j]=v;
2720  }
2721  combpolys=reform(combpolys,numdens);
2722  setring(RR);
2723  return(combpolys);
2724}
2725
2726// Auxiliary routine
2727// extendcoef: given Q,P in K[a] where P/Q specializes on an open and dense subset
2728//      of the whole V(p1 int...int pr), it returns a basis of the module
2729//      of all syzygies equivalent to P/Q,
2730proc extendcoef(poly P, poly Q, ideal idp, ideal idq)
2731{
2732  def RR=basering;
2733  setring(@P);
2734  def PL=ringlist(@P);
2735  PL[3][1][1]="dp";
2736  def P1=ring(PL);
2737  setring(P1);
2738  ideal idp0=imap(RR,idp);
2739  option(redSB);
2740  qring q=std(idp0);
2741  poly P0=imap(RR,P);
2742  poly Q0=imap(RR,Q);
2743  ideal PQ=Q0,-P0;
2744  module C=syz(PQ);
2745  setring(@P);
2746  def idp1=imap(RR,idp);
2747  def idq1=imap(RR,idq);
2748  def C1=matrix(imap(q,C));
2749  def redC=selectregularfun(C1,idp1,idq1);
2750  setring(RR);
2751  def CC=imap(@P,redC);
2752  return(CC);
2753}
2754
2755// Auxiliary routine
2756// selectregularfun
2757// input:
2758//   list L of the polynomials matrix CC
2759//      (we assume that one of them is non-null on V(N)\V(M))
2760//   ideal N, ideal M: ideals representing the locally closed set V(N)\V(M)
2761// assume to work in @P
2762proc selectregularfun(matrix CC, ideal NN, ideal MM)
2763{
2764  int numcombused;
2765  def RR=basering;
2766  setring(@P);
2767  def C=imap(RR,CC);
2768  def N=imap(RR,NN);
2769  def M=imap(RR,MM);
2770  if (ncols(C)==1){return(C);}
2771
2772  int i; int j; int k; list c; intvec ci; intvec c0; intvec c1;
2773  list T; list T0; list T1; list LL; ideal N1;ideal M1; int te=0;
2774  for(i=1;i<=ncols(C);i++)
2775  {
2776    if((C[1,i]!=0) and (C[2,i]!=0))
2777    {
2778      if(c0==intvec(0)){c0[1]=i;}
2779      else{c0[size(c0)+1]=i;}
2780    }
2781  }
2782  def C1=submat(C,1..2,c0);
2783  for (i=1;i<=ncols(C1);i++)
2784  {
2785    c=comb(ncols(C1),i);
2786    for(j=1;j<=size(c);j++)
2787    {
2788      ci=c[j];
2789      numcombused++;
2790      if(i==1){N1=N+C1[2,j]; M1=M;}
2791      if(i>1)
2792      {
2793        kill c0; intvec c0 ; kill c1; intvec c1;
2794        c1=ci[size(ci)];
2795        for(k=1;k<size(ci);k++){c0[k]=ci[k];}
2796        T0=searchinlist(c0,LL);
2797        T1=searchinlist(c1,LL);
2798        N1=T0[1]+T1[1];
2799        M1=intersect(T0[2],T1[2]);
2800      }
2801      T=list(ci,PtoCrep(Prep(N1,M1)));
2802      LL[size(LL)+1]=T;
2803      if(equalideals(T[2][1],ideal(1))){te=1; break;}
2804    }
2805    if(te){break;}
2806  }
2807  ci=T[1];
2808  def Cs=submat(C1,1..2,ci);
2809  setring(RR);
2810  return(imap(@P,Cs));
2811}
2812
2813// Auxiliary routine
2814// searchinlist
2815// input:
2816//   intvec c:
2817//   list L=( (c1,T1),..(ck,Tk) )
2818//      where the c's are assumed to be intvects
2819// output:
2820//   object T with index c
2821proc searchinlist(intvec c,list L)
2822{
2823  int i; list T;
2824  for(i=1;i<=size(L);i++)
2825  {
2826    if (L[i][1]==c)
2827    {
2828      T=L[i][2];
2829      break;
2830    }
2831  }
2832  return(T);
2833}
2834
2835// Auxiliary routine
2836// comb: the list of combinations of elements (1,..n) of order p
2837proc comb(int n, int p)
2838{
2839  list L; list L0;
2840  intvec c; intvec d;
2841  int i; int j; int last;
2842  if ((n<0) or (n<p))
2843  {
2844    return(L);
2845  }
2846  if (p==1)
2847  {
2848    for (i=1;i<=n;i++)
2849    {
2850      c=i;
2851      L[size(L)+1]=c;
2852    }
2853    return(L);
2854  }
2855  else
2856  {
2857    L0=comb(n,p-1);
2858    for (i=1;i<=size(L0);i++)
2859    {
2860      c=L0[i]; d=c;
2861      last=c[size(c)];
2862      for (j=last+1;j<=n;j++)
2863      {
2864        d[size(c)+1]=j;
2865        L[size(L)+1]=d;
2866      }
2867    }
2868    return(L);
2869  }
2870}
2871
2872// Auxiliary routine
2873// selectminsheaves
2874// Input: L=((v_11,..,v_1k_1),..,(v_s1,..,v_sk_s))
2875//    where:
2876//    The s lists correspond to the s coefficients of the polynomial f
2877//    (v_i1,..,v_ik_i) correspond to the k_i intvec v_ij of the
2878//    spezializations of the jth rekpresentant (Q,P) of the ith coefficient
2879//    v_ij is an intvec of size equal to the number of little segments
2880//    forming the lpp-segment of 0,1, where 1 represents that it specializes
2881//    to non-zedro an the whole little segment and 0 if not.
2882// Output: S=(w_1,..,w_j)
2883//    where the w_l=(n_l1,..,n_ls) are intvec of length size(L), where
2884//    n_lt fixes which element of (v_t1,..,v_tk_t) is to be
2885//    choosen to form the tth (Q,P) for the lth element of the sheaf
2886//    representing the I-regular function.
2887// The selection is done to obtian the minimal number of elements
2888//    of the sheaf that specializes to non-null everywhere.
2889proc selectminsheaves(list L)
2890{
2891  list C=allsheaves(L);
2892  return(smsheaves(C[1],C[2]));
2893}
2894
2895// Auxiliary routine
2896// smsheaves
2897// Input:
2898//   list C of all the combrep
2899//   list L of the intvec that correesponds to each element of C
2900// Output:
2901//   list LL of the subsets of C that cover all the subsegments
2902//   (the union of the corresponding L(C) has all 1).
2903proc smsheaves(list C, list L)
2904{
2905  int i; int i0; intvec W;
2906  int nor; int norn;
2907  intvec p;
2908  int sp=size(L[1]); int j0=1;
2909  for (i=1;i<=sp;i++){p[i]=1;}
2910  while (p!=0)
2911  {
2912    i0=0; nor=0;
2913    for (i=1; i<=size(L); i++)
2914    {
2915      norn=numones(L[i],pos(p));
2916      if (nor<norn){nor=norn; i0=i;}
2917    }
2918    W[j0]=i0;
2919    j0++;
2920    p=actualize(p,L[i0]);
2921  }
2922  list LL;
2923  for (i=1;i<=size(W);i++)
2924  {
2925    LL[size(LL)+1]=C[W[i]];
2926  }
2927  return(LL);
2928}
2929
2930// Auxiliary routine
2931// allsheaves
2932// Input: L=((v_11,..,v_1k_1),..,(v_s1,..,v_sk_s))
2933//    where:
2934//    The s lists correspond to the s coefficients of the polynomial f
2935//    (v_i1,..,v_ik_i) correspond to the k_i intvec v_ij of the
2936//    spezializations of the jth rekpresentant (Q,P) of the ith coefficient
2937//    v_ij is an intvec of size equal to the number of little segments
2938//    forming the lpp-segment of 0,1, where 1 represents that it specializes
2939//    to non-zero on the whole little segment and 1 if not.
2940// Output:
2941//    (list LL, list LLS)  where
2942//    LL is the list of all combrep
2943//    LLS is the list of intvec of the corresponding elements of LL
2944proc allsheaves(list L)
2945{
2946  intvec V; list LL; intvec W; int r; intvec U;
2947  int i; int j; int k;
2948  int s=size(L[1][1]); // s = number of little segments of the lpp-segment
2949  list LLS;
2950  for (i=1;i<=size(L);i++)
2951  {
2952    V[i]=size(L[i]);
2953  }
2954  LL=combrep(V);
2955  for (i=1;i<=size(LL);i++)
2956  {
2957    W=LL[i];   // size(W)= number of coefficients of the polynomial
2958    kill U; intvec U;
2959    for (j=1;j<=s;j++)
2960    {
2961      k=1; r=1; U[j]=1;
2962      while((r==1) and (k<=size(W)))
2963      {
2964        if(L[k][W[k]][j]==0){r=0; U[j]=0;}
2965        k++;
2966      }
2967    }
2968    LLS[i]=U;
2969  }
2970  return(list(LL,LLS));
2971}
2972
2973// Auxiliary routine
2974// numones
2975// Input:
2976//   intvec v of (0,1) in each position
2977//   intvec pos: the positions to test
2978// Output:
2979//   int nor: the nuber of 1 of v in the positions given by pos.
2980proc numones(intvec v, intvec pos)
2981{
2982  int i; int n;
2983  for (i=1;i<=size(pos);i++)
2984  {
2985    if (v[pos[i]]==1){n++;}
2986  }
2987  return(n);
2988}
2989
2990// Auxiliary routine
2991// pos
2992// Input:  intvec p of zeros and ones
2993// Output: intvec W of the positions where p has ones.
2994proc pos(intvec p)
2995{
2996  int i;
2997  intvec W; int j=1;
2998  for (i=1; i<=size(p); i++)
2999  {
3000    if (p[i]==1){W[j]=i; j++;}
3001  }
3002  return(W);
3003}
3004
3005// Auxiliary routine
3006// actualize: actualizes zeroes of p
3007// Input:
3008//   intvec p: of zeroes and ones
3009//   intvec c: of zeroes and ones (of the same length)
3010// Output;
3011//   intvec pp: of zeroes and ones, where a 0 stays in pp[i] if either
3012//   already p[i]==0 or c[i]==1.
3013proc actualize(intvec p, intvec c)
3014{
3015  int i; intvec pp=p;
3016  for (i=1;i<=size(p);i++)
3017  {
3018    if ((pp[i]==1) and (c[i]==1)){pp[i]=0;}
3019  }
3020  return(pp);
3021}
3022
3023// Auxiliary routine
3024// combrep
3025// Input: V=(n_1,..,n_i)
3026// Output: L=(v_1,..,v_p) where p=prod_j=1^i (n_j)
3027//    is the list of all intvec v_j=(v_j1,..,v_ji) where 1<=v_jk<=n_i
3028proc combrep(intvec V)
3029{
3030  list L; list LL;
3031  int i; int j; int k;  intvec W;
3032  if (size(V)==1)
3033  {
3034    for (i=1;i<=V[1];i++)
3035    {
3036      L[i]=intvec(i);
3037    }
3038    return(L);
3039  }
3040  for (i=1;i<size(V);i++)
3041  {
3042    W[i]=V[i];
3043  }
3044  LL=combrep(W);
3045  for (i=1;i<=size(LL);i++)
3046  {
3047    W=LL[i];
3048    for (j=1;j<=V[size(V)];j++)
3049    {
3050      W[size(V)]=j;
3051      L[size(L)+1]=W;
3052    }
3053  }
3054  return(L);
3055}
3056
3057// Auxiliary routine
3058proc reducemodN(poly f,ideal E)
3059{
3060  def RR=basering;
3061  setring(@RPt);
3062  def fa=imap(RR,f);
3063  def Ea=imap(RR,E);
3064  attrib(Ea,"isSB",1);
3065  // option(redSB);
3066  // Ea=std(Ea);
3067  fa=reduce(fa,Ea);
3068  setring(RR);
3069  def f1=imap(@RPt,fa);
3070  return(f1);
3071}
3072
3073// Auxiliary routine
3074// intersp: computes the intersection of the ideals in S in @P
3075proc intersp(list S)
3076{
3077  def RR=basering;
3078  setring(@P);
3079  def SP=imap(RR,S);
3080  option(returnSB);
3081  def NP=intersect(SP[1..size(SP)]);
3082  setring(RR);
3083  return(imap(@P,NP));
3084}
3085
3086// Auxiliary routine
3087// radicalmember
3088proc radicalmember(poly f,ideal ida)
3089{
3090  int te;
3091  def RR=basering;
3092  setring(@P);
3093  def fp=imap(RR,f);
3094  def idap=imap(RR,ida);
3095  poly @t;
3096  ring H=0,@t,dp;
3097  def PH=@P+H;
3098  setring(PH);
3099  def fH=imap(@P,fp);
3100  def idaH=imap(@P,idap);
3101  idaH[size(idaH)+1]=1-@t*fH;
3102  option(redSB);
3103  def G=std(idaH);
3104  if (G==1){te=1;} else {te=0;}
3105  setring(RR);
3106  return(te);
3107}
3108
3109// Auxiliary routine
3110// NonNull: returns 1 if the poly f is nonnull on V(E)\V(N), 0 otherwise.
3111proc NonNull(poly f, ideal E, ideal N)
3112{
3113  int te=1; int i;
3114  def RR=basering;
3115  setring(@P);
3116  def fp=imap(RR,f);
3117  def Ep=imap(RR,E);
3118  def Np=imap(RR,N);
3119  ideal H;
3120  ideal Ef=Ep+fp;
3121  for (i=1;i<=size(Np);i++)
3122  {
3123    te=radicalmember(Np[i],Ef);
3124    if (te==0){break;}
3125  }
3126  setring(RR);
3127  return(te);
3128}
3129
3130// Auxiliary routine
3131// selectextendcoef
3132// input:
3133//    matrix CC: CC=(p_a1 .. p_ar_a)
3134//                  (q_a1 .. q_ar_a)
3135//            the matrix of elements of a coefficient in oo[a].
3136//    (ideal ida, ideal idb): the canonical representation of the segment S.
3137// output:
3138//    list caout
3139//            the minimum set of elements of CC needed such that at least one
3140//            of the q's is non-null on S, as well as the C-rep of of the
3141//            points where the q's are null on S.
3142//            The elements of caout are of the form (p,q,prep);
3143proc selectextendcoef(matrix CC, ideal ida, ideal idb)
3144{
3145  def RR=basering;
3146  setring(@P);
3147  def ca=imap(RR,CC);
3148  def E0=imap(RR,ida);
3149  ideal E;
3150  def N=imap(RR,idb);
3151  int r=ncols(ca);
3152  int i; int te=1; list com; int j; int k; intvec c; list prep;
3153  list cs; list caout;
3154  i=1;
3155  while ((i<=r) and (te))
3156  {
3157    com=comb(r,i);
3158    j=1;
3159    while((j<=size(com)) and (te))
3160    {
3161      E=E0;
3162      c=com[j];
3163      for (k=1;k<=i;k++)
3164      {
3165        E=E+ca[2,c[k]];
3166      }
3167      prep=Prep(E,N);
3168      if (i==1)
3169      {
3170        cs[j]=list(ca[1,j],ca[2,j],prep);
3171      }
3172      if ((size(prep)==1) and (equalideals(prep[1][1],ideal(1))))
3173      {
3174        te=0;
3175        for(k=1;k<=size(c);k++)
3176        {
3177          caout[k]=cs[c[k]];
3178        }
3179      }
3180      j++;
3181    }
3182    i++;
3183  }
3184  if (te){"error: extendcoef does not extend to the whole S";}
3185  setring(RR);
3186  return(imap(@P,caout));
3187}
3188
3189// Auxiliary routine
3190// input:
3191//   ideal E1: in some basering (depends only on the parameters)
3192//   ideal E2: in some basering (depends only on the parameters)
3193// output:
3194//   ideal Ep=E1+E2; computed in P
3195proc plusP(ideal E1,ideal E2)
3196{
3197  def RR=basering;
3198  setring(@P);
3199  def E1p=imap(RR,E1);
3200  def E2p=imap(RR,E2);
3201  def Ep=E1p+E2p;
3202  setring(RR);
3203  return(imap(@P,Ep));
3204}
3205
3206// Auxiliary routine
3207// reform
3208// input:
3209//   list combpolys: (v1,..,vs)
3210//      where vi are intvec.
3211//   output outcomb: (w1,..,wt)
3212//      whre wi are intvec.
3213//      All the vi without zeroes are in outcomb, and those with zeroes are
3214//         combined to form new intvec with the rest
3215proc reform(list combpolys, intvec numdens)
3216{
3217  list combp0; list combp1; int i; int j; int k; int l; list rest; intvec notfree;
3218  list free; intvec free1; int te; intvec v;  intvec w;
3219  int nummonoms=size(combpolys[1]);
3220  for(i=1;i<=size(combpolys);i++)
3221  {
3222    if(memberpos(0,combpolys[i])[1])
3223    {
3224      combp0[size(combp0)+1]=combpolys[i];
3225    }
3226    else {combp1[size(combp1)+1]=combpolys[i];}
3227  }
3228  for(i=1;i<=nummonoms;i++)
3229  {
3230    kill notfree; intvec notfree;
3231    for(j=1;j<=size(combpolys);j++)
3232    {
3233      if(combpolys[j][i]<>0)
3234      {
3235        if(notfree[1]==0){notfree[1]=combpolys[j][i];}
3236        else{notfree[size(notfree)+1]=combpolys[j][i];}
3237      }
3238    }
3239    kill free1; intvec free1;
3240    for(j=1;j<=numdens[i];j++)
3241    {
3242      if(memberpos(j,notfree)[1]==0)
3243      {
3244        if(free1[1]==0){free1[1]=j;}
3245        else{free1[size(free1)+1]=j;}
3246      }
3247      free[i]=free1;
3248    }
3249  }
3250  list amplcombp; list aux;
3251  for(i=1;i<=size(combp0);i++)
3252  {
3253    v=combp0[i];
3254    kill amplcombp; list amplcombp;
3255    amplcombp[1]=intvec(v[1]);
3256    for(j=2;j<=size(v);j++)
3257    {
3258      if(v[j]!=0)
3259      {
3260        for(k=1;k<=size(amplcombp);k++)
3261        {
3262          w=amplcombp[k];
3263          w[size(w)+1]=v[j];
3264          amplcombp[k]=w;
3265        }
3266      }
3267      else
3268      {
3269        kill aux; list aux;
3270        for(k=1;k<=size(amplcombp);k++)
3271        {
3272          for(l=1;l<=size(free[j]);l++)
3273          {
3274            w=amplcombp[k];
3275            w[size(w)+1]=free[j][l];
3276            aux[size(aux)+1]=w;
3277          }
3278        }
3279        amplcombp=aux;
3280      }
3281    }
3282    for(j=1;j<=size(amplcombp);j++)
3283    {
3284      combp1[size(combp1)+1]=amplcombp[j];
3285    }
3286  }
3287  return(combp1);
3288}
3289
3290// Auxiliary routine
3291// nonnullCrep
3292proc nonnullCrep(poly f0,ideal ida0,ideal idb0)
3293{
3294  int i;
3295  def RR=basering;
3296  setring(@P);
3297  def f=imap(RR,f0);
3298  def ida=imap(RR,ida0);
3299  def idb=imap(RR,idb0);
3300  def idaf=ida+f;
3301  int te=1;
3302  for(i=1;i<=size(idb);i++)
3303  {
3304    if(radicalmember(idb[i],idaf)==0)
3305    {
3306      te=0; break;
3307    }
3308  }
3309  setring(RR);
3310  return(te);
3311}
3312
3313// Auxiliary routine
3314// precombint
3315// input:  L: list of ideals (works in @P)
3316// output: F0: ideal of polys. F0[i] is a poly in the intersection of
3317//             all ideals in L except in the ith one, where it is not.
3318//             L=(p1,..,ps);  F0=(f1,..,fs);
3319//             F0[i] \in intersect_{j#i} p_i
3320proc precombint(list L)
3321{
3322  int i; int j; int tes;
3323  def RR=basering;
3324  setring(@P);
3325  list L0; list L1; list L2; list L3; ideal F;
3326  L0=imap(RR,L);
3327  L1[1]=L0[1]; L2[1]=L0[size(L0)];
3328  for (i=2;i<=size(L0)-1;i++)
3329  {
3330    L1[i]=intersect(L1[i-1],L0[i]);
3331    L2[i]=intersect(L2[i-1],L0[size(L0)-i+1]);
3332  }
3333  L3[1]=L2[size(L2)];
3334  for (i=2;i<=size(L0)-1;i++)
3335  {
3336    L3[i]=intersect(L1[i-1],L2[size(L0)-i]);
3337  }
3338  L3[size(L0)]=L1[size(L1)];
3339  for (i=1;i<=size(L3);i++)
3340  {
3341    option(redSB); L3[i]=std(L3[i]);
3342  }
3343  for (i=1;i<=size(L3);i++)
3344  {
3345    tes=1; j=0;
3346    while((tes) and (j<size(L3[i])))
3347    {
3348      j++;
3349      option(redSB);
3350      L0[i]=std(L0[i]);
3351      if(reduce(L3[i][j],L0[i])!=0){tes=0; F[i]=L3[i][j];}
3352    }
3353    if (tes){"ERROR a polynomial in all p_j except p_i was not found";}
3354  }
3355  setring(RR);
3356  def F0=imap(@P,F);
3357  return(F0);
3358}
3359
3360
3361// Auxiliary routine
3362// minAssGTZ eliminating denominators
3363proc minGTZ(ideal N);
3364{
3365  int i; int j;
3366  def L=minAssGTZ(N);
3367  for(i=1;i<=size(L);i++)
3368  {
3369    for(j=1;j<=size(L[i]);j++)
3370    {
3371      L[i][j]=cleardenom(L[i][j]);
3372    }
3373  }
3374  return(L);
3375}
3376
3377//********************* Begin KapurSunWang *************************
3378
3379// Auxiliary routine
3380// inconsistent
3381// Input:
3382//   ideal E: of null conditions
3383//   ideal N: of non-null conditions representing V(E)\V(N)
3384// Output:
3385//   1 if V(E) \V(N) = empty
3386//   0 if not
3387proc inconsistent(ideal E, ideal N)
3388{
3389  int j;
3390  int te=1;
3391  def R=basering;
3392  setring(@P);
3393  def EP=imap(R,E);
3394  def NP=imap(R,N);
3395  poly @t;
3396  ring H=0,@t,dp;
3397  def RH=@P+H;
3398  setring(RH);
3399  def EH=imap(@P,EP);
3400  def NH=imap(@P,NP);
3401  ideal G;
3402  j=1;
3403  while((te==1) and j<=size(NH))
3404  {
3405    G=EH+(1-@t*NH[j]);
3406    option(redSB);
3407    G=std(G);
3408    if (G[1]!=1){te=0;}
3409    j++;
3410  }
3411  setring(R);
3412  return(te);
3413}
3414
3415// Auxiliary routine
3416// MDBasis: Minimal Dickson Basis
3417proc MDBasis(ideal G)
3418{
3419  int i; int j; int te=1;
3420  G=sortideal(G);
3421  ideal MD=G[1];
3422  poly lm;
3423  for (i=2;i<=size(G);i++)
3424  {
3425    te=1;
3426    lm=leadmonom(G[i]);
3427    j=1;
3428    while ((te==1) and (j<=size(MD)))
3429    {
3430      if (lm/leadmonom(MD[j])!=0){te=0;}
3431      j++;
3432    }
3433    if (te==1)
3434    {
3435      MD[size(MD)+1]=(G[i]);
3436    }
3437  }
3438  return(MD);
3439}
3440
3441// Auxiliary routine
3442// primepartZ
3443proc primepartZ(poly f);
3444{
3445  def R=basering;
3446  def cp=content(f);
3447  def fp=f/cp;
3448  return(fp);
3449}
3450
3451// LCMLC
3452proc LCMLC(ideal H)
3453{
3454  int i;
3455  def R=basering;
3456  setring(@RP);
3457  def HH=imap(R,H);
3458  poly h=1;
3459  for (i=1;i<=size(HH);i++)
3460  {
3461    h=lcm(h,HH[i]);
3462  }
3463  setring(R);
3464  def hh=imap(@RP,h);
3465  return(hh);
3466}
3467
3468// KSW: Kapur-Sun-Wang algorithm for computing a CGS
3469// Input:
3470//   F:   parametric ideal to be discussed
3471//   Options:
3472//     \"out\",0 Transforms the description of the segments into
3473//     canonical P-representation form.
3474//     \"out\",1 Original KSW routine describing the segments as
3475//     difference of varieties
3476//   The ideal must be defined on C[parameters][variables]
3477// Output:
3478//   With option \"out\",0 :
3479//     ((lpp,
3480//       (1,B,((p_1,(p_11,..,p_1k_1)),..,(p_s,(p_s1,..,p_sk_s)))),
3481//       string(lpp)
3482//      )
3483//      ,..,
3484//      (lpp,
3485//       (k,B,((p_1,(p_11,..,p_1k_1)),..,(p_s,(p_s1,..,p_sk_s)))),
3486//       string(lpp))
3487//      )
3488//     )
3489//   With option \"out\",1 ((default, original KSW) (shorter to be computed,
3490//                    but without canonical description of the segments.
3491//     ((B,E,N),..,(B,E,N))
3492proc KSW(ideal F, list #)
3493{
3494  setglobalrings();
3495  int start=timer;
3496  ideal E=ideal(0);
3497  ideal N=ideal(1);
3498  int comment=0;
3499  int out=1;
3500  int i;
3501  def L=#;
3502  if (size(L)>0)
3503  {
3504    for (i=1;i<=size(L) div 2;i++)
3505    {
3506      if (L[2*i-1]=="null"){E=L[2*i];}
3507      else
3508      {
3509        if (L[2*i-1]=="nonnull"){N=L[2*i];}
3510        else
3511        {
3512          if (L[2*i-1]=="comment"){comment=L[2*i];}
3513          else
3514          {
3515            if (L[2*i-1]=="out"){out=L[2*i];}
3516          }
3517        }
3518      }
3519    }
3520  }
3521  if (comment>0){string("Begin KSW with null = ",E," nonnull = ",N);}
3522  def CG=KSW0(F,E,N,comment);
3523  if (comment>0)
3524  {
3525    string("Number of segments in KSW (total) = ",size(CG));
3526    string("Time in KSW = ",timer-start);
3527  }
3528  if(out==0)
3529  {
3530    CG=KSWtocgsdr(CG);
3531    CG=groupKSWsegments(CG);
3532    if (comment>0)
3533    {
3534      string("Number of lpp segments = ",size(CG));
3535      string("Time in KSW + group + Prep = ",timer-start);
3536    }
3537  }
3538  if(defined(@P)){kill @P; kill @R; kill @RP;}
3539  return(CG);
3540}
3541
3542// Auxiliary routine
3543// sqf
3544// This is for releases of Singular before 3-5-1
3545// proc sqf(poly f)
3546// {
3547//  def RR=basering;
3548//  setring(@P);
3549//  def ff=imap(RR,f);
3550//  def G=sqrfree(ff);
3551//  poly fff=1;
3552//  int i;
3553//  for (i=1;i<=size(G);i++)
3554//  {
3555//    fff=fff*G[i];
3556//  }
3557//  setring(RR);
3558//   def ffff=imap(@P,fff);
3559//   return(ffff);
3560// }
3561
3562// Auxiliary routine
3563// sqf
3564proc sqf(poly f)
3565{
3566  def RR=basering;
3567  setring(@P);
3568  def ff=imap(RR,f);
3569  poly fff=sqrfree(ff,3);
3570  setring(RR);
3571  def ffff=imap(@P,fff);
3572  return(ffff);
3573}
3574
3575
3576// Auxiliary routine
3577// KSW0: Kapur-Sun-Wang algorithm for computing a CGS, called by KSW
3578// Input:
3579//   F:   parametric ideal to be discussed
3580//   Options:
3581//   The ideal must be defined on C[parameters][variables]
3582// Output:
3583proc KSW0(ideal F, ideal E, ideal N, int comment)
3584{
3585  def R=basering;
3586  int i; int j; list emp;
3587  list CGS;
3588  ideal N0;
3589  for (i=1;i<=size(N);i++)
3590  {
3591    N0[i]=sqf(N[i]);
3592  }
3593  ideal E0;
3594  for (i=1;i<=size(E);i++)
3595  {
3596    E0[i]=sqf(leadcoef(E[i]));
3597  }
3598  setring(@P);
3599  ideal E1=imap(R,E0);
3600  E1=std(E1);
3601  ideal N1=imap(R,N0);
3602  N1=std(N1);
3603  setring(R);
3604  E0=imap(@P,E1);
3605  N0=imap(@P,N1);
3606//   E0=elimrepeated(E0);
3607//   N0=elimrepeated(N0);
3608  if (inconsistent(E0,N0)==1)
3609  {
3610    return(emp);
3611  }
3612  setring(@RP);
3613  def FRP=imap(R,F);
3614  def ERP=imap(R,E);
3615  FRP=FRP+ERP;
3616  option(redSB);
3617  def GRP=std(FRP);
3618  setring(R);
3619  def G=imap(@RP,GRP);
3620  if (memberpos(1,G)[1]==1)
3621  {
3622    if(comment>1){"Basis 1 is found"; E; N;}
3623    list KK; KK[1]=list(E0,N0,ideal(1));
3624    return(KK);
3625   }
3626  ideal Gr; ideal Gm; ideal GM;
3627  for (i=1;i<=size(G);i++)
3628  {
3629    if (variables(G[i])[1]==0){Gr[size(Gr)+1]=G[i];}
3630    else{Gm[size(Gm)+1]=G[i];}
3631  }
3632  ideal Gr0;
3633  for (i=1;i<=size(Gr);i++)
3634  {
3635    Gr0[i]=sqf(Gr[i]);
3636  }
3637
3638
3639  Gr=elimrepeated(Gr0);
3640  ideal GrN;
3641  for (i=1;i<=size(Gr);i++)
3642   {
3643    for (j=1;j<=size(N0);j++)
3644    {
3645      GrN[size(GrN)+1]=sqf(Gr[i]*N0[j]);
3646    }
3647  }
3648  if (inconsistent(E,GrN)){;}
3649  else
3650  {
3651    if(comment>1){"Basis 1 is found in a branch with arguments"; E; GrN;}
3652    CGS[size(CGS)+1]=list(E,GrN,ideal(1));
3653  }
3654  if (inconsistent(Gr,N0)){return(CGS);}
3655  GM=Gm;
3656  Gm=MDBasis(Gm);
3657  ideal H;
3658  for (i=1;i<=size(Gm);i++)
3659  {
3660    H[i]=sqf(leadcoef(Gm[i]));
3661  }
3662  H=facvar(H);
3663  poly h=sqf(LCMLC(H));
3664  if(comment>1){"H = "; H; "h = "; h;}
3665  ideal Nh=N0;
3666  if(size(N0)==0){Nh=h;}
3667  else
3668  {
3669    for (i=1;i<=size(N0);i++)
3670    {
3671      Nh[i]=sqf(N0[i]*h);
3672    }
3673  }
3674  if (inconsistent(Gr,Nh)){;}
3675  else
3676  {
3677    CGS[size(CGS)+1]=list(Gr,Nh,Gm);
3678  }
3679  poly hc=1;
3680  list KS;
3681  ideal GrHi;
3682  for (i=1;i<=size(H);i++)
3683  {
3684    kill GrHi;
3685    ideal GrHi;
3686    Nh=N0;
3687    if (i>1){hc=sqf(hc*H[i-1]);}
3688    for (j=1;j<=size(N0);j++){Nh[j]=sqf(N0[j]*hc);}
3689    if (equalideals(Gr,ideal(0))==1){GrHi=H[i];}
3690    else {GrHi=Gr,H[i];}
3691//     else {for (j=1;j<=size(Gr);j++){GrHi[size(GrHi)+1]=Gr[j]*H[i];}}
3692    if(comment>1){"Call to KSW with arguments "; GM; GrHi;  Nh;}
3693    KS=KSW0(GM,GrHi,Nh,comment);
3694    for (j=1;j<=size(KS);j++)
3695    {
3696      CGS[size(CGS)+1]=KS[j];
3697    }
3698    if(comment>1){"CGS after KSW = "; CGS;}
3699  }
3700  return(CGS);
3701}
3702
3703// Auxiliary routine
3704// KSWtocgsdr
3705proc KSWtocgsdr(list L)
3706{
3707  int i; list CG; ideal B; ideal lpp; int j; list NKrep;
3708  for(i=1;i<=size(L);i++)
3709  {
3710    B=redgbn(L[i][3],L[i][1],L[i][2]);
3711    lpp=ideal(0);
3712    for(j=1;j<=size(B);j++)
3713    {
3714      lpp[j]=leadmonom(B[j]);
3715    }
3716    NKrep=KtoPrep(L[i][1],L[i][2]);
3717    CG[i]=list(lpp,B,NKrep);
3718  }
3719  return(CG);
3720}
3721
3722// Auxiliary routine
3723// KtoPrep
3724// Computes the P-representaion of a K-representation (N,W) of a set
3725// input:
3726//    ideal E (null conditions)
3727//    ideal N (non-null conditions ideal)
3728// output:
3729//    the ((p_1,(p_11,..,p_1k_1)),..,(p_r,(p_r1,..,p_rk_r)));
3730//    the Prep of V(N) \ V(W)
3731proc KtoPrep(ideal N, ideal W)
3732{
3733  int i; int j;
3734  if (N[1]==1)
3735  {
3736    L0[1]=list(ideal(1),list(ideal(1)));
3737    return(L0);
3738  }
3739  def RR=basering;
3740  setring(@P);
3741  ideal B; int te; poly f;
3742  ideal Np=imap(RR,N);
3743  ideal Wp=imap(RR,W);
3744  list L;
3745  list L0; list T0;
3746  L0=minGTZ(Np);
3747  for(j=1;j<=size(L0);j++)
3748  {
3749    option(redSB);
3750    L0[j]=std(L0[j]);
3751  }
3752  for(i=1;i<=size(L0);i++)
3753  {
3754    if(inconsistent(L0[i],Wp)==0)
3755    {
3756      B=L0[i]+Wp;
3757      T0=minGTZ(B);
3758      option(redSB);
3759      for(j=1;j<=size(T0);j++)
3760      {
3761        T0[j]=std(T0[j]);
3762      }
3763      L[size(L)+1]=list(L0[i],T0);
3764    }
3765  }
3766  setring(RR);
3767  def LL=imap(@P,L);
3768  return(LL);
3769}
3770
3771// Auxiliary routine
3772// groupKSWsegments
3773// input:  the list of vertices of KSW
3774// output: the same terminal vertices grouped by lpp
3775proc groupKSWsegments(list T)
3776{
3777  //"T_T="; T;
3778  int i; int j;
3779  list L;
3780  list lpp; list lppor;
3781  list kk;
3782  lpp[1]=T[1][1]; j=1;
3783  lppor[1]=intvec(1);
3784  for(i=2;i<=size(T);i++)
3785  {
3786    kk=memberpos(T[i][1],lpp);
3787    if(kk[1]==0){j++; lpp[j]=T[i][1]; lppor[j]=intvec(i);}
3788    else{lppor[kk[2]][size(lppor[kk[2]])+1]=i;}
3789  }
3790  list ll;
3791  for (j=1;j<=size(lpp);j++)
3792  {
3793    kill ll; list ll;
3794    for(i=1;i<=size(lppor[j]);i++)
3795    {
3796      ll[size(ll)+1]=list(i,T[lppor[j][i]][2],T[lppor[j][i]][3]);
3797    }
3798    L[j]=list(lpp[j],ll,string(lpp[j]));
3799  }
3800  return(L);
3801}
3802
3803//********************* End KapurSunWang *************************
3804
3805//******************** Begin locus ******************************
3806
3807// indepparameters
3808// Auxiliary routine to detect "Special" components of the locus
3809// Input: ideal B
3810// Output:
3811//   1 if the solutions of the ideal do not depend on the parameters
3812//   0 if they depend
3813proc indepparameters(ideal B)
3814{
3815  def R=basering;
3816  ideal v=variables(B);
3817  setring @RP;
3818  def BP=imap(R,B);
3819  def vp=imap(R,v);
3820  ideal varpar=variables(BP);
3821  int te;
3822  te=equalideals(vp,varpar);
3823  setring(R);
3824  if(te){return(1);}
3825  else{return(0);}
3826}
3827
3828// dimP0: Auxiliary routine
3829// if the dimension in @P of an ideal in the parameters has dimension 0 then it returns 0
3830// else it retuns 1
3831proc dimP0(ideal N)
3832{
3833  def R=basering;
3834  setring(@P);
3835  int te=1;
3836  def NP=imap(R,N);
3837  attrib(NP,"IsSB",1);
3838  int d=dim(std(NP));
3839  if(d==0){te=0;}
3840  setring(R);
3841  return(te);
3842}
3843
3844// Auxiliary routine.
3845// input:    ideals E and F (assumed in ring @P
3846// returns: 1 if ideal E is contained in ideal F (assumed F is std basis)
3847//              0 if not
3848proc containedideal(ideal E, ideal F)
3849{
3850  int i; int t; poly f;
3851  if(equalideals(F,ideal(0)))
3852  {
3853    if(equalideals(E,ideal(0))==0){return(0);}
3854    else(return(1));
3855  }
3856  t=1; i=1;
3857  while((t==1) and (i<=size(E)))
3858  {
3859    attrib(F,"isSB",1);
3860    f=reduce(E[i],F);
3861    if(f!=0){t=0;}
3862    i++;
3863  }
3864  return(t);
3865}
3866
3867// addcons: given a set of locally closed sets given in P-representation,
3868//       (particularly a subset of components of a selection of segments
3869//       of the Grobner cover), it builds the canonical P-representation
3870//       of the corresponding constructible set, of its union, including levels it they are.
3871// input: a list L of disjoint segments (for exmple a selection of segments of the Groebner cover)
3872//       of the form
3873//       ( ( (p1_1,(p1_11,..,p1_1k_1).. (p1_s,(p1_s1,..,p1_sk_s)),..,
3874//         ( (pn_1,(pn_11,..,pn_1j_1).. (pn_s,(pn_s1,..,pn_sj_s))   )
3875// output: The canonical P-representation of the  constructible set resulting by
3876//       adding the given components.
3877//       The first element of each component can be ignored. It is only for internal use.
3878//       The fifth element of each component is the level of the constructible set
3879//       of the component.
3880//       It is no need a previous call to setglobalrings()
3881proc addcons(list L)
3882"USAGE:   addcons(  ( ( (p1_1,(p1_11,..,p1_1k_1).. (p1_s,(p1_s1,..,p1_sk_s)),..,
3883  ( (pn_1,(pn_11,..,pn_1j_1).. (pn_s,(pn_s1,..,pn_sj_s))   )   )
3884  a list L of locally closed sets in P-representation
3885RETURN: the canonical P-representation of the constructible set of the union.
3886NOTE:   It is called internally by the routines locus, locusdg,
3887
3888KEYWORDS: P-representation, constructible set
3889EXAMPLE:  adccons; shows an example"
3890{
3891  int te;
3892  if(defined(@P)){te=1;}
3893  else{setglobalrings();}
3894  list notadded; list P0;
3895  int i; int j; int k; int l;
3896  intvec v; intvec v1; intvec v0;
3897  ideal J; list K;
3898  for(i=1;i<=size(L);i++)
3899  {
3900    for(j=1;j<=size(L[i]);j++)
3901    {
3902        v=i,j;
3903        notadded[size(notadded)+1]=v;
3904    }
3905  }
3906  //"T_notadded="; notadded;
3907  int level=1;
3908  list P=L;
3909  list LL;
3910  list Ln;
3911  //int cont=0;
3912  while(size(notadded)>0)
3913  {
3914    kill notadded; list notadded;
3915    for(i=1;i<=size(P);i++)
3916    {
3917      for(j=1;j<=size(P[i]);j++)
3918      {
3919          v=i,j;
3920          notadded[size(notadded)+1]=v;
3921      }
3922    }
3923    //"T_notadded="; notadded;
3924     //cont++;
3925     P0=P;
3926     Ln=LCUnion(P);
3927     //"T_Ln="; Ln;
3928     notadded=minuselements(notadded,@Q2);
3929     //"T_@Q2="; @Q2;
3930     //"T_notadded="; notadded;
3931     for(i=1;i<=size(Ln);i++)
3932     {
3933       //Ln[i][4]=  ; JA HAURIA DE VENIR DE LCUnion
3934       Ln[i][5]=level;
3935       LL[size(LL)+1]=Ln[i];
3936     }
3937     i=0;j=0;
3938     v=0,0;
3939     v0=0,0;
3940     kill P; list P;
3941     for(l=1;l<=size(notadded);l++)
3942     {
3943       v1=notadded[l];
3944       if(v1[1]<>v0[1]){i++;j=1; P[i]=K;} // list P[i];
3945       else
3946       {
3947         if(v1[2]<>v0[2])
3948         {
3949           j=j+1;
3950         }
3951       }
3952       v=i,j;
3953       //"T_v1="; v1;
3954       P[i][j]=K; P[i][j][1]=J; P[i][j][2]=K;
3955       P[i][j][1]=P0[v1[1]][v1[2]][1];
3956       //"T_P0[v1[1]][v1[2]][2]="; P0[v1[1]][v1[2]][2];
3957       //"T_size(P0[v1[1]][v1[2]][2])="; size(P0[v1[1]][v1[2]][2]);
3958       for(k=1;k<=size(P0[v1[1]][v1[2]][2]);k++)
3959       {
3960         P[i][j][2][k]=P0[v1[1]][v1[2]][2][k];
3961         //string("T_P[",i,"][",j,"][2][",k,"]="); P[i][j][2][k];
3962       }
3963       v0=v1;
3964       //"T_P_1="; P;
3965     }
3966     //"T_P="; P;
3967     level++;
3968     //if(cont>3){break;}
3969     //kill notadded; list notadded;
3970  }
3971  if(defined(@Q2)){kill @Q2;}
3972  if(te==0){kill @P; kill @R; kill @RP;}
3973  //"T_LL_sortida addcons="; LL; "Fi sortida";
3974  return(LL);
3975}
3976example
3977{
3978  "EXAMPLE:"; echo = 2;
3979   ring R=(0,a,b),(x1,y1,x2,y2,p,r),dp;
3980   ideal S93=(a+1)^2+b^2-(p+1)^2,
3981                    (a-1)^2+b^2-(1-r)^2,
3982                    a*y1-b*x1-y1+b,
3983                    a*y2-b*x2+y2-b,
3984                    -2*y1+b*x1-(a+p)*y1+b,
3985                    2*y2+b*x2-(a+r)*y2-b,
3986                    (x1+1)^2+y1^2-(x2-1)^2-y2^2;
3987  short=0;
3988  "System S93="; S93; " ";
3989  def GC93=grobcov(S93);
3990  "grobcov(S93)="; GC93; " ";
3991  int i;
3992  list H;
3993  for(i=1;i<=size(GC93);i++){H[i]=GC93[i][3];}
3994  "H="; H;
3995  "addcons(H)="; addcons(H);
3996}
3997
3998// Takes a list of intvec and sorts it and eliminates repeated elements.
3999// Auxiliary routine used in addcons
4000proc sortpairs(L)
4001{
4002  def L1=sort(L);
4003  def L2=elimrepeated(L1[1]);
4004  return(L2);
4005}
4006
4007// Eliminates the pairs of L1 that are also in L2.
4008// Auxiliary routine used in addcons
4009proc minuselements(list L1,list L2)
4010{
4011  int i;
4012  list L3;
4013  for (i=1;i<=size(L1);i++)
4014  {
4015    if(not(memberpos(L1[i],L2)[1])){L3[size(L3)+1]=L1[i];}
4016  }
4017  return(L3);
4018}
4019
4020// locus0(G): Private routine used by locus (the public routine), that
4021//                builds the diferent components.
4022// input:      The output G of the grobcov (in generic representation, which is the default option)
4023// output:
4024//         list, the canonical P-representation of the Normal and Non-Normal locus:
4025//              The Normal locus has two kind of components: Normal and Special.
4026//              The Non-normal locus has two kind of components: Accumulation and Degenerate.
4027//              This routine is compemented by locus that calls it in order to eliminate problems
4028//              with degenerate points of the mover.
4029//         The output components are given as
4030//              ((p1,(p11,..p1s_1),type_1,level_1),..,(pk,(pk1,..pks_k),type_k,level_k)
4031//         The components are given in canonical P-representation of the subset.
4032//              If all levels of a class of locus are 1, then the set is locally closed. Otherwise the level
4033//              gives the depth of the component.
4034proc locus0(list GG, list #)
4035{
4036  int t1=1; int t2=1;
4037  def R=basering;
4038  int moverdim=nvars(R);
4039  list HHH;
4040  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);}
4041  list Lop=#;
4042  if(size(Lop)>0){moverdim=Lop[1];}
4043  setglobalrings();
4044  list G1; list G2;
4045  def G=GG;
4046  list Q1; list Q2;
4047  int i; int d; int j; int k;
4048  t1=1;
4049  for(i=1;i<=size(G);i++)
4050  {
4051    attrib(G[i][1],"IsSB",1);
4052    d=locusdim(G[i][2],moverdim);
4053    if(d==0){G1[size(G1)+1]=G[i];}
4054    else
4055    {
4056      if(d>0){G2[size(G2)+1]=G[i];}
4057    }
4058  }
4059  if(size(G1)==0){t1=0;}
4060  if(size(G2)==0){t2=0;}
4061  setring(@RP);
4062  if(t1)
4063  {
4064    list G1RP=imap(R,G1);
4065  }
4066  else {list G1RP;}
4067  list P1RP;
4068  ideal B;
4069  for(i=1;i<=size(G1RP);i++)
4070  {
4071     kill B;
4072     ideal B;
4073     for(k=1;k<=size(G1RP[i][3]);k++)
4074     {
4075       attrib(G1RP[i][3][k][1],"IsSB",1);
4076       G1RP[i][3][k][1]=std(G1RP[i][3][k][1]);
4077       for(j=1;j<=size(G1RP[i][2]);j++)
4078       {
4079         B[j]=reduce(G1RP[i][2][j],G1RP[i][3][k][1]);
4080       }
4081       P1RP[size(P1RP)+1]=list(G1RP[i][3][k][1],G1RP[i][3][k][2],B);
4082     }
4083  }
4084  setring(R);
4085  ideal h;
4086  if(t1)
4087  {
4088    def P1=imap(@RP,P1RP);
4089    for(i=1;i<=size(P1);i++)
4090    {
4091      for(j=1;j<=size(P1[i][3]);j++)
4092      {
4093        h=factorize(P1[i][3][j],1);
4094        P1[i][3][j]=h[1];
4095        for(k=2;k<=size(h);k++)
4096        {
4097          P1[i][3][j]=P1[i][3][j]*h[k];
4098        }
4099      }
4100    }
4101  }
4102  else{list P1;}
4103  ideal BB;
4104  for(i=1;i<=size(P1);i++)
4105  {
4106    if (indepparameters(P1[i][3])==1){P1[i][3]="Special";}
4107    else{P1[i][3]="Normal";}
4108  }
4109  list P2;
4110  for(i=1;i<=size(G2);i++)
4111  {
4112    for(k=1;k<=size(G2[i][3]);k++)
4113    {
4114      P2[size(P2)+1]=list(G2[i][3][k][1],G2[i][3][k][2]);
4115    }
4116  }
4117  list l;
4118  for(i=1;i<=size(P1);i++){Q1[i]=l; Q1[i][1]=P1[i];} P1=Q1;
4119  for(i=1;i<=size(P2);i++){Q2[i]=l; Q2[i][1]=P2[i];} P2=Q2;
4120
4121  setring @P;
4122  ideal J;
4123  if(t1==1)
4124  {
4125    def C1=imap(R,P1);
4126    def L1=addcons(C1);
4127   }
4128  else{list C1; list L1; kill P1; list P1;}
4129  if(t2==1)
4130  {
4131    def C2=imap(R,P2);
4132    def L2=addcons(C2);
4133  }
4134  else{list L2; list C2; kill P2; list P2;}
4135    for(i=1;i<=size(L2);i++)
4136    {
4137      J=std(L2[i][2]);
4138      d=dim(J); // AQUI
4139      if(d==0)
4140      {
4141        L2[i][4]=string("Accumulation",L2[i][4]);
4142      }
4143      else{L2[i][4]=string("Degenerate",L2[i][4]);}
4144    }
4145  list LN;
4146  if(t1==1)
4147  {
4148    for(i=1;i<=size(L1);i++){LN[size(LN)+1]=L1[i];}
4149  }
4150  if(t2==1)
4151  {
4152    for(i=1;i<=size(L2);i++){LN[size(LN)+1]=L2[i];}
4153  }
4154  setring(R);
4155  def L=imap(@P,LN);
4156  for(i=1;i<=size(L);i++){if(size(L[i][2])==0){L[i][2]=ideal(1);}}
4157  kill @R; kill @RP; kill @P;
4158  list LL;
4159  for(i=1;i<=size(L);i++)
4160  {
4161    LL[i]=l;
4162    LL[i]=elimfromlist(L[i],1);
4163  }
4164  return(LL);
4165}
4166
4167// locus0dg(G): Private routine used by locusdg (the public routine), that
4168//                builds the diferent components used in Dynamical Geometry
4169// input:      The output G of the grobcov (in generic representation, which is the default option)
4170// output:
4171//         list, the canonical P-representation of the Relevant components of the locus in Dynamical Geometry,
4172//              i.e. the Normal and Accumulation components.
4173//              This routine is compemented by locusdg that calls it in order to eliminate problems
4174//              with degenerate points of the mover.
4175//         The output components are given as
4176//              ((p1,(p11,..p1s_1),type_1,level_1),..,(pk,(pk1,..pks_k),type_k,level_k)
4177//              whwre type_i is always "Relevant".
4178//         The components are given in canonical P-representation of the subset.
4179//              If all levels of a class of locus are 1, then the set is locally closed. Otherwise the level
4180//              gives the depth of the component.
4181proc locus0dg(list GG, list #)
4182{
4183  int t1=1; int t2=1; int ojo;
4184  def R=basering;
4185  int moverdim=nvars(R);
4186  list HHH;
4187  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);}
4188  list Lop=#;
4189  if(size(Lop)>0){moverdim=Lop[1];}
4190  setglobalrings();
4191  list G1; list G2;
4192  def G=GG;
4193  list Q1; list Q2;
4194  int i; int d; int j; int k;
4195  t1=1;
4196  for(i=1;i<=size(G);i++)
4197  {
4198    attrib(G[i][1],"IsSB",1);
4199    d=locusdim(G[i][2],moverdim);
4200    if(d==0){G1[size(G1)+1]=G[i];}
4201    else
4202    {
4203      if(d>0){G2[size(G2)+1]=G[i];}
4204    }
4205  }
4206  if(size(G1)==0){t1=0;}
4207  if(size(G2)==0){t2=0;}
4208  setring(@RP);
4209  if(t1)
4210  {
4211    list G1RP=imap(R,G1);
4212  }
4213  else {list G1RP;}
4214  list P1RP;
4215  ideal B;
4216  for(i=1;i<=size(G1RP);i++)
4217  {
4218     kill B;
4219     ideal B;
4220     for(k=1;k<=size(G1RP[i][3]);k++)
4221     {
4222       attrib(G1RP[i][3][k][1],"IsSB",1);
4223       G1RP[i][3][k][1]=std(G1RP[i][3][k][1]);
4224       for(j=1;j<=size(G1RP[i][2]);j++)
4225       {
4226         B[j]=reduce(G1RP[i][2][j],G1RP[i][3][k][1]);
4227       }
4228       P1RP[size(P1RP)+1]=list(G1RP[i][3][k][1],G1RP[i][3][k][2],B);
4229     }
4230  }
4231  setring(R);
4232  ideal h;
4233  if(t1)
4234  {
4235    def P1=imap(@RP,P1RP);
4236    for(i=1;i<=size(P1);i++)
4237    {
4238      for(j=1;j<=size(P1[i][3]);j++)
4239      {
4240        h=factorize(P1[i][3][j],1);
4241        P1[i][3][j]=h[1];
4242        for(k=2;k<=size(h);k++)
4243        {
4244          P1[i][3][j]=P1[i][3][j]*h[k];
4245        }
4246      }
4247    }
4248  }
4249  else{list P1;}
4250  ideal BB;
4251  for(i=1;i<=size(P1);i++)
4252  {
4253    if (indepparameters(P1[i][3])==1){P1[i][3]="Special";}
4254    else{P1[i][3]="Relevant";}
4255  }
4256  list P2;
4257  for(i=1;i<=size(G2);i++)
4258  {
4259    for(k=1;k<=size(G2[i][3]);k++)
4260    {
4261      P2[size(P2)+1]=list(G2[i][3][k][1],G2[i][3][k][2]);
4262    }
4263  }
4264  list l;
4265  for(i=1;i<=size(P1);i++){Q1[i]=l; Q1[i][1]=P1[i];} P1=Q1;
4266  for(i=1;i<=size(P2);i++){Q2[i]=l; Q2[i][1]=P2[i];} P2=Q2;
4267
4268  setring @P;
4269  ideal J;
4270  if(t1==1)
4271  {
4272    def C1=imap(R,P1);
4273    def L1=addcons(C1);
4274   }
4275  else{list C1; list L1; kill P1; list P1;}
4276  if(t2==1)
4277  {
4278    def C2=imap(R,P2);
4279    def L2=addcons(C2);
4280  }
4281  else{list L2; list C2; kill P2; list P2;}
4282    for(i=1;i<=size(L2);i++)
4283    {
4284      J=std(L2[i][2]);
4285      d=dim(J); // AQUI
4286      if(d==0)
4287      {
4288        L2[i][4]=string("Relevant",L2[i][4]);
4289      }
4290      else{L2[i][4]=string("Degenerate",L2[i][4]);}
4291    }
4292  list LN;
4293  list ll; list l0;
4294  if(t1==1)
4295  {
4296    for(i=1;i<=size(L1);i++)
4297    {
4298      if(L1[i][4]=="Relevant")
4299      {
4300       LN[size(LN)+1]=l0;
4301       LN[size(LN)][1]=L1[i];
4302     }
4303    }
4304  }
4305  if(t2==1)
4306  {
4307    for(i=1;i<=size(L2);i++)
4308    {
4309      if(L2[i][4]=="Relevant")
4310      {
4311        LN[size(LN)+1]=l0;
4312        LN[size(LN)][1]=L2[i];
4313      }
4314    }
4315  }
4316  list LNN;
4317  kill ll; list ll; list lll; list llll;
4318  for(i=1;i<=size(LN);i++)
4319  {
4320      LNN[size(LNN)+1]=l0;
4321      ll=LN[i][1]; lll[1]=ll[2]; lll[2]=ll[3]; lll[3]=ll[4]; LNN[size(LNN)][1]=lll;
4322  }
4323  kill LN; list LN;
4324  LN=addcons(LNN);
4325  if(size(LN)==0){ojo=1;}
4326  setring(R);
4327  if(ojo==1){list L;}
4328  else
4329  {
4330    def L=imap(@P,LN);
4331    for(i=1;i<=size(L);i++){if(size(L[i][2])==0){L[i][2]=ideal(1);}}
4332  }
4333  kill @R; kill @RP; kill @P;
4334  list LL;
4335  for(i=1;i<=size(L);i++)
4336  {
4337    LL[i]=l;
4338    LL[i]=elimfromlist(L[i],1);
4339  }
4340  return(LL);
4341}
4342
4343
4344//  locus(G):  Special routine for determining the locus of points
4345//                 of  geometrical constructions. Given a parametric ideal J with
4346//                 parameters (a_1,..a_m) and variables (x_1,..,xn),
4347//                 representing the system determining
4348//                 the locus of points (a_1,..,a_m) who verify certain
4349//                 properties, computing the grobcov G of
4350//                 J and applying to it locus, determines the different
4351//                 classes of locus components. The components can be
4352//                 Normal, Special, Accumulation, Degenerate.
4353//                 The output are the components given in P-canonical form
4354//                 of at most 4 constructible sets: Normal, Special, Accumulation,
4355//                 Degenerate.
4356//                 The description of the algorithm and definitions is
4357//                 given in a forthcoming paper by Abanades, Botana, Montes, Recio.
4358//                 Usually locus problems have mover coordinates, variables and tracer coordinates.
4359//                 The mover coordinates are to be placed as the last variables, and by default,
4360//                 its number is 2. If one consider locus problems in higer dimensions, the number of
4361//                 mover coordinates (placed as the last variables) is to be given as an option.
4362//
4363//  input:      The output G of the grobcov (in generic representation, which is the default option for grobcov)
4364//  output:
4365//          list, the canonical P-representation of the Normal and Non-Normal locus:
4366//               The Normal locus has two kind of components: Normal and Special.
4367//               The Non-normal locus has two kind of components: Accumulation and Degenerate.
4368//               Normal components: for each point in the component,
4369//               the number of solutions in the variables is finite, and
4370//               the solutions depend on the point in the component if the component is not 0-dimensional.
4371//               Special components:  for each point in the component,
4372//               the number of solutions in the variables is finite,
4373//               the component is not 0-dimensional, but the solutions do not depend on the
4374//               values of the parameters in the component.
4375//               Accumlation points: are 0-dimensional components for which it exist
4376//               an infinite number of solutions.
4377//               Degenerate components: are components of dimension greater than 0 for which
4378//               for every point in the component there exist infinite solutions.
4379//          The output components are given as
4380//               ((p1,(p11,..p1s_1),type_1,level_1),..,(pk,(pk1,..pks_k),type_k,level_k)
4381//          The components are given in canonical P-representation of the subset.
4382//               If all levels of a class of locus are 1, then the set is locally closed. Otherwise the level
4383//               gives the depth of the component of the constructible set.
4384proc locus(list GG, list #)
4385  "USAGE:   locus(G);
4386                 The input must be the grobcov  of a parametrical ideal
4387  RETURN:  The  locus.
4388                 The output are the components of four constructible subsets of the locus
4389                 of the parametrical system: Normal , Special, Accumulation and Degenerate.
4390                 These components are
4391                 given as a list of  (pi,(pi1,..pis_i),type_i,level_i) varying i,
4392                 where the p's are prime ideals, the type can be: Normal, Special,
4393                 Accumulation, Degenerate.
4394  NOTE:      It can only be called after computing the grobcov of the
4395                 parametrical ideal in generic representation ('ext',0),
4396                 which is the default.
4397                 The basering R, must be of the form Q[a_1,..,a_m][x_1,..,x_n].
4398  KEYWORDS: geometrical locus, locus, loci.
4399  EXAMPLE:  locus; shows an example"
4400{
4401  def R=basering;
4402  int dd=2; int comment=0;
4403  list DD=#;
4404  if (size(DD)>1){comment=1;}
4405  if(size(DD)>0){dd=DD[1];}
4406  int i; int j; int k;
4407  def B0=GG[1][2];
4408  if (equalideals(B0,ideal(1)))
4409  {
4410    return(locus0(GG));
4411  }
4412  else
4413  {
4414    int n=nvars(R);
4415    ideal vmov=var(n-1),var(n);
4416    ideal N;
4417    intvec xw; intvec yw;
4418    for(i=1;i<=n-1;i++){xw[i]=0;}
4419    xw[n]=1;
4420    for(i=1;i<=n;i++){yw[i]=0;}
4421    yw[n-1]=1;
4422    poly px; poly py;
4423    int te=1;
4424    i=1;
4425    while( te and i<=size(B0))
4426    {
4427      if((deg(B0[i],xw)==1) and (deg(B0[i])==1)){px=B0[i]; te=0;}
4428      i++;
4429    }
4430    i=1; te=1;
4431    while( te and i<=size(B0))
4432    {
4433      if((deg(B0[i],yw)==1) and (deg(B0[i])==1)){py=B0[i]; te=0;}
4434      i++;
4435    }
4436    N=px,py;
4437    setglobalrings();
4438    te=indepparameters(N);
4439    if(te)
4440    {
4441      string("locus detected that the mover must avoid point (",N,") in order to obtain the correct locus");
4442      // eliminates segments of GG where N is contained in the basis
4443      list nGP;
4444      def GP=GG;
4445      ideal BP;
4446      for(j=1;j<=size(GP);j++)
4447      {
4448        te=1; k=1;
4449        BP=GP[j][2];
4450        while((te==1) and (k<=size(N)))
4451        {
4452          if(pdivi(N[k],BP)[1]!=0){te=0;}
4453          k++;
4454        }
4455        if(te==0){nGP[size(nGP)+1]=GP[j];}
4456      }
4457   }
4458  }
4459  kill @RP; kill @P; kill @R;
4460  return(locus0(nGP,dd));
4461}
4462example
4463{"EXAMPLE:"; echo = 2;
4464  ring R=(0,a,b),(x4,x3,x2,x1),dp;
4465  ideal S=(x1-3)^2+(x2-1)^2-9,
4466             (4-x2)*(x3-3)+(x1-3)*(x4-1),
4467             (3-x1)*(x3-x1)+(4-x2)*(x4-x2),
4468             (4-x4)*a+(x3-3)*b+3*x4-4*x3,
4469             (a-x1)^2+(b-x2)^2-(x1-x3)^2-(x2-x4)^2;
4470  short=0;
4471  locus(grobcov(S)); " ";
4472  kill R;
4473  ring R=(0,a,b),(x,y),dp;
4474  short=0;
4475  "Concoid";
4476  ideal S96=x^2+y^2-4,(b-2)*x-a*y+2*a,(a-x)^2+(b-y)^2-1;
4477  "System="; S96; " ";
4478  locus(grobcov(S96));
4479  kill R; ring R=(0,x,y),(x1,x2),dp;
4480  ideal S=-(x - 5)*(x1 - 1) - (x2 - 2)*(y - 2),
4481              (x1 - 5)^2 + (x2 - 2)^2 - 4,
4482              -2*(x - 5)*(x2 - 2) + 2*(x1 - 5)*(y - 2);
4483 "System="; S;
4484  locus(grobcov(S)); " ";
4485  ideal S1=-(x - x1)*(x1 - 4) + (x2 - y)*(x2 - 4),
4486                (x1 - 4)^2 + (x2 - 2)^2 - 4,
4487                -2*(x1 - 4)*(2*x2 - y - 4) - 2*(x - 2*x1 + 4)*(x2 - 2);
4488 "System="; S1;
4489  locus(grobcov(S1));
4490}
4491
4492//  locusdg(G):  Special routine for determining the locus of points
4493//                 of  geometrical constructions. Given a parametric ideal J with
4494//                 parameters (a_1,..a_m) and variables (x_1,..,xn),
4495//                 representing the system determining
4496//                 the locus of points (a_1,..,a_m) who verify certain
4497//                 properties, computing the grobcov G of
4498//                 J and applying to it locus, determines the different
4499//                 classes of locus components. The components can be
4500//                 Normal, Special, Accumulation point, Degenerate.
4501//                 The output are the components given in P-canonical form
4502//                 of at most 4 constructible sets: Normal, Special, Accumulation,
4503//                 Degenerate.
4504//                 The description of the algorithm and definitions is
4505//                 given in a forthcoming paper by Abanades, Botana, Montes, Recio.
4506//                 Usually locus problems have mover coordinates, variables and tracer coordinates.
4507//                 The mover coordinates are to be placed as the last variables, and by default,
4508//                 its number is 2. If onw consider locus problems in higer dimensions, the number of
4509//                 mover coordinates (placed as the last variables) is to be given as an option.
4510//
4511//  input:      The output G of the grobcov (in generic representation, which is the default option for grobcov)
4512//  output:
4513//          list, the canonical P-representation of the Normal and Non-Normal locus:
4514//               The Normal locus has two kind of components: Normal and Special.
4515//               The Non-normal locus has two kind of components: Accumulation and Degenerate.
4516//               Normal components: for each point in the component,
4517//               the number of solutions in the variables is finite, and
4518//               the solutions depend on the point in the component if the component is not 0-dimensional.
4519//               Special components:  for each point in the component,
4520//               the number of solutions in the variables is finite,
4521//               the component is not 0-dimensional, but the solutions do not depend on the
4522//               values of the parameters in the component.
4523//               Accumlation points: are 0-dimensional components for which it exist
4524//               an infinite number of solutions.
4525//               Degenerate components: are components of dimension greater than 0 for which
4526//               for every point in the component there exist infinite solutions.
4527//          The output components are given as
4528//               ((p1,(p11,..p1s_1),type_1,level_1),..,(pk,(pk1,..pks_k),type_k,level_k)
4529//          The components are given in canonical P-representation of the subset.
4530//               If all levels of a class of locus are 1, then the set is locally closed. Otherwise the level
4531//               gives the depth of the component of the constructible set.
4532proc locusdg(list GG, list #)
4533  "USAGE:   locus(G);
4534                 The input must be the grobcov  of a parametrical ideal
4535  RETURN:  The  locus.
4536                 The output are the components of two constructible subsets of the locus
4537                 of the parametrical system.: Normal and Non-normal.
4538                 These components are
4539                 given as a list of  (pi,(pi1,..pis_i),type_i,level_i) varying i,
4540                 where the p's are prime ideals, the type can be: Normal, Special,
4541                 Accumulation, Degenerate.
4542  NOTE:      It can only be called after computing the grobcov of the
4543                 parametrical ideal in generic representation ('ext',0),
4544                 which is the default.
4545                 The basering R, must be of the form Q[a_1,..,a_m][x_1,..,x_n].
4546  KEYWORDS: geometrical locus, locus, loci.
4547  EXAMPLE:  locusdg; shows an example"
4548{
4549  def R=basering;
4550  int dd=2; int comment=0;
4551  list DD=#;
4552  if (size(DD)>1){comment=1;}
4553  if(size(DD)>0){dd=DD[1];}
4554  int i; int j; int k;
4555  def B0=GG[1][2];
4556  if (equalideals(B0,ideal(1)))
4557  {
4558    return(locus0dg(GG));
4559  }
4560  else
4561  {
4562    int n=nvars(R);
4563    ideal vmov=var(n-1),var(n);
4564    ideal N;
4565    intvec xw; intvec yw;
4566    for(i=1;i<=n-1;i++){xw[i]=0;}
4567    xw[n]=1;
4568    for(i=1;i<=n;i++){yw[i]=0;}
4569    yw[n-1]=1;
4570    poly px; poly py;
4571    int te=1;
4572    i=1;
4573    while( te and i<=size(B0))
4574    {
4575      if((deg(B0[i],xw)==1) and (deg(B0[i])==1)){px=B0[i]; te=0;}
4576      i++;
4577    }
4578    i=1; te=1;
4579    while( te and i<=size(B0))
4580    {
4581      if((deg(B0[i],yw)==1) and (deg(B0[i])==1)){py=B0[i]; te=0;}
4582      i++;
4583    }
4584    N=px,py;
4585    setglobalrings();
4586    te=indepparameters(N);
4587    if(te)
4588    {
4589      string("locus detected that the mover must avoid point (",N,") in order to obtain the correct locus");
4590      // eliminates segments of GG where N is contained in the basis
4591      list nGP;
4592      def GP=GG;
4593      ideal BP;
4594      for(j=1;j<=size(GP);j++)
4595      {
4596        te=1; k=1;
4597        BP=GP[j][2];
4598        while((te==1) and (k<=size(N)))
4599        {
4600          if(pdivi(N[k],BP)[1]!=0){te=0;}
4601          k++;
4602        }
4603        if(te==0){nGP[size(nGP)+1]=GP[j];}
4604      }
4605   }
4606  }
4607  //"T_nGP="; nGP;
4608  kill @RP; kill @P; kill @R;
4609  return(locus0dg(nGP,dd));
4610}
4611example
4612{"EXAMPLE:"; echo = 2;
4613  ring R=(0,a,b),(x4,x3,x2,x1),dp;
4614  ideal S=(x1-3)^2+(x2-1)^2-9,
4615             (4-x2)*(x3-3)+(x1-3)*(x4-1),
4616             (3-x1)*(x3-x1)+(4-x2)*(x4-x2),
4617             (4-x4)*a+(x3-3)*b+3*x4-4*x3,
4618             (a-x1)^2+(b-x2)^2-(x1-x3)^2-(x2-x4)^2;
4619  short=0;
4620  locus(grobcov(S)); " ";
4621  kill R;
4622  ring R=(0,a,b),(x,y),dp;
4623  short=0;
4624  "Concoid";
4625  ideal S96=x^2+y^2-4,(b-2)*x-a*y+2*a,(a-x)^2+(b-y)^2-1;
4626  "System="; S96; " ";
4627  locusdg(grobcov(S96));
4628  kill R; ring R=(0,x,y),(x1,x2),dp;
4629  ideal S=-(x - 5)*(x1 - 1) - (x2 - 2)*(y - 2),
4630              (x1 - 5)^2 + (x2 - 2)^2 - 4,
4631              -2*(x - 5)*(x2 - 2) + 2*(x1 - 5)*(y - 2);
4632 "System="; S;
4633  locusdg(grobcov(S)); " ";
4634  ideal S1=-(x - x1)*(x1 - 4) + (x2 - y)*(x2 - 4),
4635                (x1 - 4)^2 + (x2 - 2)^2 - 4,
4636                -2*(x1 - 4)*(2*x2 - y - 4) - 2*(x - 2*x1 + 4)*(x2 - 2);
4637 "System="; S1;
4638  locusdg(grobcov(S1));
4639}
4640
4641// locusto: Transforms the output of locus to a string that
4642//      can be read by different computational systems.
4643// input:
4644//     list L: The output of locus
4645// output:
4646//     string s: The output of locus converted to a string readable by other programs
4647proc locusto(list L)
4648"USAGE:   locusto(L);
4649          The argument must be the output of locus of a parametrical ideal
4650          It transforms the output into a string in standard form
4651          readable in many languages (Geogebra).
4652RETURN: The locus in string standard form
4653NOTE:     It can only be called after computing the locus(grobcov(F)) of the
4654              parametrical ideal.
4655              The basering R, must be of the form Q[a,b,..][x,y,..].
4656KEYWORDS: geometrical locus, locus, loci.
4657EXAMPLE:  locusto; shows an example"
4658{
4659  int i; int j; int k;
4660  string s="["; string sf="]"; string st=s+sf;
4661  if(size(L)==0){return(st);}
4662  ideal p;
4663  ideal q;
4664  for(i=1;i<=size(L);i++)
4665  {
4666    s=string(s,"[[");
4667    for (j=1;j<=size(L[i][1]);j++)
4668    {
4669      s=string(s,L[i][1][j],",");
4670    }
4671    s[size(s)]="]";
4672    s=string(s,",[");
4673    for(j=1;j<=size(L[i][2]);j++)
4674    {
4675      s=string(s,"[");
4676      for(k=1;k<=size(L[i][2][j]);k++)
4677      {
4678        s=string(s,L[i][2][j][k],",");
4679      }
4680      s[size(s)]="]";
4681      s=string(s,",");
4682    }
4683    s[size(s)]="]";
4684    s=string(s,"]");
4685    if(size(L[i])>=3)
4686    {
4687      s[size(s)]=",";
4688      s=string(s,string(L[i][3]),"]");
4689    }
4690    if(size(L[i])>=4)
4691    {
4692      s[size(s)]=",";
4693      s=string(s,string(L[i][4]),"],");
4694    }
4695    s[size(s)]="]";
4696    s=string(s,",");
4697  }
4698  s[size(s)]="]";
4699  return(s);
4700}
4701example
4702{"EXAMPLE:"; echo = 2;
4703  ring R=(0,a,b),(x,y),dp;
4704  short=0;
4705  ideal S96=x^2+y^2-4,(b-2)*x-a*y+2*a,(a-x)^2+(b-y)^2-1;
4706  "System="; S96; " ";
4707  locusto(locus(grobcov(S96)));
4708}
4709
4710// Auxiliary routione
4711// locusdim
4712// input:
4713//    B:         ideal, a basis of a segment of the grobcov
4714//    dgdim: int, the dimension of the mover (for locusdg)
4715//                by default dgdim is equal to the number of variables
4716proc locusdim(ideal B, list #)
4717{
4718  def R=basering;
4719  int dgdim;
4720  int nv=nvars(R);
4721  if (size(#)>0){dgdim=#[1];}
4722  else {dgdim=nv;}
4723  int d;
4724  list v;
4725  ideal vi;
4726  int i;
4727  for(i=1;i<=dgdim;i++)
4728  {
4729    v[size(v)+1]=varstr(nv-dgdim+i);
4730    vi[size(v)+1]=var(nv-dgdim+i);
4731  }
4732  ideal B0;
4733  for(i=1;i<=size(B);i++)
4734  {
4735    if(subset(variables(B[i]),vi))
4736    {
4737      B0[size(B0)+1]=B[i];
4738    }
4739  }
4740  //"T_B0="; B0;
4741  //"T_v="; v;
4742  def RR=ringlist(R);
4743  def RR0=RR;
4744  RR0[2]=v;
4745  def R0=ring(RR0);
4746  //ringlist(R0);
4747  setring(R0);
4748  def B0r=imap(R,B0);
4749  B0r=std(B0r);
4750  d=dim(B0r);
4751  setring R;
4752  return(d);
4753}
4754
4755// locusdgto: Transforms the output of locus to a string that
4756//      can be read by different computational systems.
4757// input:
4758//     list L: The output of locus
4759// output:
4760//     string s: The output of locus converted to a string readable by other programs
4761//                   Outputs only the relevant dynamical geometry components.
4762//                   Without unnecessary parenthesis
4763proc locusdgto(list LL)
4764{
4765  def RR=basering;
4766  int i; int j; int k; int short0=short; int ojo;
4767  int te=0;
4768  if(defined(@P)){te=1;}
4769  else{setglobalrings();}
4770  setring @P;
4771  short=0;
4772  if(size(LL)==0){ojo=1; list L;}
4773  else
4774  {
4775    def L=imap(RR,LL);
4776  }
4777  string s="["; string sf="]"; string st=s+sf;
4778  if(size(L)==0){return(st);}
4779  ideal p;
4780  ideal q;
4781  for(i=1;i<=size(L);i++)
4782  {
4783    if(L[i][3]=="Relevant")
4784    {
4785      s=string(s,"[[");
4786      for (j=1;j<=size(L[i][1]);j++)
4787      {
4788        s=string(s,L[i][1][j],",");
4789      }
4790      s[size(s)]="]";
4791      s=string(s,",[");
4792      for(j=1;j<=size(L[i][2]);j++)
4793      {
4794        s=string(s,"[");
4795        for(k=1;k<=size(L[i][2][j]);k++)
4796        {
4797          s=string(s,L[i][2][j][k],",");
4798        }
4799        s[size(s)]="]";
4800        s=string(s,",");
4801      }
4802      s[size(s)]="]";
4803      s=string(s,"]");
4804      s[size(s)]="]";
4805      s=string(s,",");
4806    }
4807  }
4808  if(s=="["){s="[]";}
4809  else{s[size(s)]="]";}
4810  setring(RR);
4811  short=short0;
4812  if(te==0){kill @P; kill @R; kill @RP;}
4813  return(s);
4814}
4815
4816//********************* End locus ****************************
4817;
Note: See TracBrowser for help on using the repository browser.