source: git/Singular/LIB/redcgs.lib @ 4c20ee

spielwiese
Last change on this file since 4c20ee was 4c20ee, checked in by Hans Schoenemann <hannes@…>, 11 years ago
fix: new version numbers for libs
  • Property mode set to 100644
File size: 110.0 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2version="version redcgs.lib 4.0.0.0 Jun_2013 ";
3category="General purpose";
4info="
5LIBRARY:  redcgs.lib      Reduced Comprehensive Groebner Systems.
6
7OVERVIEW:
8          Comprehensive Groebner Systems. Canonical Forms.
9          The library contains Monte's algorithms to compute disjoint, reduced
10          Comprehensive Groebner Systems (CGS). A CGS is a set of pairs of
11          (segment,basis). The segments S_i are subsets of the parameter space,
12          and the bases B_i are sets of polynomials specializing to Groebner
13          bases of the specialized ideal for every point in S_i.
14
15          The purpose of the routines in this library is to obtain CGS with
16          better properties, namely disjoint segments forming a partition of
17          the parameter space and reduced bases. Reduced bases are sets of
18          polynomials that specialize to the reduced Groebner basis of the
19          specialized ideal preserving the leading power products (lpp).
20          The lpp characterize the type of solution in each segment.
21
22          A further objective is to summarize as much as possible the segments
23          with the same lpp into a single segment, and if possible to obtain
24          a final result that is canonical, i.e. independent of the algorithm
25          and only attached to the given ideal.
26
27          There are three fundamental routines in the library: mrcgs, rcgs and
28          crcgs. mrcgs (Minimal Reduced CGS) is an algorithm that packs so
29          much as it is able to do (using algorithms adhoc) the segments with
30          the same lpp, obtaining the minimal number of segments. The hypothesis
31          is that the result is also canonical, but for the moment there is no
32          proof of the uniqueness of this minimal packing. Moreover, the
33          segments that are obtained are not locally closed, i.e. there are not
34          difference of two varieties.
35
36          On the other side, Michael Wibmer has proved that for homogeneous ideals,
37          all the segments with reduced bases having the same lpp admit a unique
38          basis specializing well. For this purpose it is necessary to extend the
39          description of the elements of the bases to functions, forming sheaves
40          of polynomials instead of simple polynomials, so that the polynomials in
41          a sheaf either preserve the lpp of the corresponding polynomial of
42          the specialized Groebner basis (and then it specializes well) or
43          it specializes to 0. Moreover, in a sheaf, for every point in the
44          corresponding segment, at least one of the polynomials specializes well.
45          specializes well. And moreover Wibmer's Theorem ensures that the packed
46          segments are locally closed, that is can be described as the difference of
47          two varieties.
48
49          Using Wibmer's Theorem we proved that an affine ideal can be homogenized,
50          than discussed by mrcgs and finally de-homogenized. The bases so obtained
51          can be reduced and specialize well in the segment. If the theoretic
52          objective is reached, and all the segments of the homogenized ideal
53          have been packed, locally closed segments will be obtained.
54
55          If we only homogenize the given basis of the ideal, then we cannot ensure
56          the canonicity of the partition obtained, because there are many different
57          bases of the given ideal that can be homogenized, and the homogenized ideals
58          are not identical. This corresponds to the algorithm rcgs and is recommended
59          as the most practical routine. It provides locally closed segments and
60          is usually faster than mrcgs and crcgs. But the given partition is not
61          always canonical.
62
63          Finally it is possible to homogenize the whole affine ideal, and then
64          the packing algorithm will provide canonical segments by dehomogenizing.
65          This corresponds to crcgs routine. It provides the best description
66          of the segments and bases. In contrast crcgs algorithm is usually much
67          more time consuming and it will not always finish in a reasonable time.
68          Moreover it will contain more segments than mrcgs and possibly also more
69          than rcgs.
70
71          But the actual algorithms in the library to pack segments have some lacks.
72          They are not theoretically always able to pack the segments that we know
73          that can be packed. Nevertheless, thanks to Wibmer's Theorem, the
74          algorithms rcgs and crcgs are able to detect if the objective has not been
75          reached, and if so, to give a Warning. The warning does not invalidate the
76          output, but it only recognizes that the theoretical objective is not
77          completely reached by the actual computing methods and that some segments
78          that can be packed have not been packed with a single basis.
79
80          The routine buildtree is the first algorithm used in all the previous
81          methods providing a first disjoint CGS, and can be used if none of the
82          three fundamental algorithms of the library finishes in a reasonable time.
83
84          There are also routines to visualize better the output of the previous
85          algorithms:
86          finalcases can be applied to the list provided by buildtree to obtain the
87          CGS. The list provided by buildtree contains the whole discussion, and
88          finalcases extracts the CGS.
89          The output of buildtree can also be transformed into a file using
90          buildtreetoMaple routine that can be read in Maple. Using Monte's dpgb
91          library in Maple the output can be plotted (with the routine tplot).
92          To plot the output of mrcgs, rcgs or crcgs in Maple, the library also
93          provides the routine cantreetoMaple. The file written using it
94          and read in Maple can then be plotted with the command plotcantree and
95          printed with printcantree from the Monte's dpgb library in Maple.
96          The output of mrcgs, rcgs and crcgs is given in form of tree using
97          prime ideals in a canonical form that is described in the papers.
98          Nevertheless this canonical form is somewhat uncomfortable to be
99          interpreted. When the segments are all locally closed (and this is
100          always the case for rcgs and crcgs) the routine cantodiffcgs transforms
101          the output into a simpler form having only one list element for
102          each segment and providing the two varieties whose difference represent
103          the segment also in a canonical form.
104
105AUTHORS:  Antonio Montes , Hans Schoenemann.
106OVERVIEW: see \"Minimal Reduced Comprehensive Groebner Systems\"
107          by Antonio Montes. (http://www-ma2.upc.edu/~montes/).
108
109NOTATIONS: All given and determined polynomials and ideals are in the
110@*         basering K[a][x]; (a=parameters, x=variables)
111@*         After defining the ring and calling setglobalrings(); the rings
112@*         @R   (K[a][x]),
113@*         @P   (K[a]),
114@*         @RP   (K[x,a]) are defined globally
115@*         They are used internally and can also be used by the user.
116@*         The fundamental routines are: buildtree, mrcgs, rcgs and crcgs
117
118PROCEDURES:
119
120setglobalrings();    It is called by the fundamental routines of the library:
121                     (buildtree, mrcgs, rcgs, crcgs).
122                     After calling it, the rings @R, @P and @RP are defined
123                     globally.
124memberpos(f,J);      Returns the list of two integers: the value 0 or 1 depending
125                     on if f belongs to J or not, and the position in J (0 if it
126                     does not belong).
127subset(F,G);         If all elements of F belong to the ideal G it returns 1,
128                     and 0 otherwise.
129pdivi(f,F);          Pseudodivision of a polynomial f by an ideal F in @R. Returns a
130                     list (r,q,m) such that m*f=r+sum(q.G).
131facvar(ideal J)      Returns all the free-square factors of the elements
132                     of ideal J (non repeated). Integer factors are ignored,
133                     even 0 is ignored. It can be called from ideal @R, but
134                     the given ideal J must only contain polynomials in the
135                     parameters.
136redspec(N,W);        Given null and non-null conditions depending only on the
137                     parameters it returns a red-specification.
138pnormalform(f,N,W);  Reduces the polynomial f w.r.t. to the null condition ideal N and the
139                     non-null condition ideal W (both depending on the parameters).
140buildtree(F);        Returns a list T describing a first reduced CGS of the ideal
141                     F in K[a][x].
142buildtreetoMaple(T); Writes into a file the output of buildtree in Maple readable
143                     form.
144finalcases(T);       From the output of buildtree it provides the list
145                     of its terminal vertices. That list represents the dichotomic,
146                     reduced CGS obtained by buildtree.
147mrcgs(F);            Returns a list T describing the Minimal Reduced CGS of the
148                     ideal F of K[a][x]
149rcgs(F);             Returns a list T describing the Reduced CGS of the ideal F
150                     of K[a][x] obtained by direct homogenizing and de-homogenizing
151                     the basis of the given ideal.
152crcgs(F);            Returns a list T describing the Canonical Reduced CGS of the
153                     ideal F of K[a][x] obtained by homogenizing and de-homogenizing
154                     the initial ideal.
155cantreetoMaple)(M);  Writes into a file the output of mrcgs, rcgs or crcgs in Maple
156                     readable form.
157cantodiffcgs(list L);From the output of rcgs or crcgs (or even of mrcgs when
158                     it is possible) it returns a simpler list where the segments
159                     are given as difference of varieties.
160
161SEE ALSO: compregb_lib
162";
163
164// ************ Begin of the redCGS library *********************
165// Library redCGS
166// (Reduced Comprehesive Groebner Systems):
167// Initial data: 21-1-2008
168// Release 1:
169// Final data: 3_7-2008
170// All given and determined polynomials and ideals are in the
171// basering K[a][x];
172// After calling setglobalrings(); the rings
173//        @R   (K[a][x]),
174//        @P   (K[a]),
175//        @RP   (K[x,a]) are globally defined
176//        They are used internally and can also be called by the user;
177//        setglobalrings() is called by buildtree, so it is not required to
178//        call setglobalrings before using
179//        the fundamental routines of the library.
180
181// ************ Begin of buildtree ******************************
182
183LIB "primdec.lib";
184
185proc setglobalrings()
186"USAGE:   setglobalrings();
187          No arguments
188RETURN:   After its call the rings @R=K[a][x], @P=K[a], @RP=K[x,a] are
189          defined as global variables.
190NOTE:     It is called by the fundamental routines of the library.
191          The user does not need to call it, except when none of
192          the fundamental routines have been called and some
193          other routines of the library are used.
194          The basering R, must be of the form K[a][x], a=parameters,
195          x=variables, and should be defined previously.
196KEYWORDS: ring, rings
197EXAMPLE:  setglobalrings; shows an example"
198{
199  def @R=basering;  // must be of the form K[a][x], a=parameters, x=variables
200  def Rx=ringlist(@R);
201  def @P=ring(Rx[1]);
202  list Lx;
203  Lx[1]=0;
204  Lx[2]=Rx[2]+Rx[1][2];
205  Lx[3]=Rx[1][3];
206  Lx[4]=Rx[1][4];
207  //def @K=ring(Lx);
208  //exportto(Top,@K);  //global ring K[x,a] with the order of x extended to x,a
209  Rx[1]=0;
210  def D=ring(Rx);
211  def @RP=D+@P;
212  exportto(Top,@R);      // global ring K[a][x]
213  exportto(Top,@P);      // global ring K[a]
214  exportto(Top,@RP);     // global ring K[x,a] with product order
215  setring(@R);
216}
217example
218{ "EXAMPLE:"; echo = 2;
219  ring R=(0,a,b),(x,y,z),dp;
220  setglobalrings();
221  @R;
222  @P;
223  @RP;
224}
225
226//*************Auxilliary routines**************
227
228// cld : clears denominators of an ideal and normalizes to content 1
229//       can be used in @R or @P or @RP
230// input:
231//   ideal J (J can be also poly), but the output is an ideal;
232// output:
233//   ideal Jc (the new form of ideal J without denominators and
234//       normalized to content 1)
235proc cld(ideal J)
236{
237  if (size(J)==0){return(ideal(0));}
238  def RR=basering;
239  setring(@RP);
240  def Ja=imap(RR,J);
241  ideal Jb;
242  if (size(Ja)==0){return(ideal(0));}
243  int i;
244  def j=0;
245  for (i=1;i<=ncols(Ja);i++){if (size(Ja[i])!=0){j++; Jb[j]=cleardenom(Ja[i]);}}
246  setring(RR);
247  def Jc=imap(@RP,Jb);
248  return(Jc);
249}
250
251proc memberpos(f,J)
252"USAGE:  memberpos(f,J);
253         (f,J) expected (polynomial,ideal)
254               or       (int,list(int))
255               or       (int,intvec)
256               or       (intvec,list(intvec))
257               or       (list(int),list(list(int)))
258               or       (ideal,list(ideal))
259               or       (list(intvec),  list(list(intvec))).
260         The ring can be @R or @P or @RP or any other.
261RETURN:  The list (t,pos) t int; pos int;
262         t is 1 if f belongs to J and 0 if not.
263         pos gives the position in J (or 0 if f does not belong).
264EXAMPLE: memberpos; shows an example"
265{
266  int pos=0;
267  int i=1;
268  int j;
269  int t=0;
270  int nt;
271  if (typeof(J)=="ideal"){nt=ncols(J);}
272  else{nt=size(J);}
273  if ((typeof(f)=="poly") or (typeof(f)=="int"))
274  { // (poly,ideal)  or
275    // (poly,list(poly))
276    // (int,list(int)) or
277    // (int,intvec)
278    i=1;
279    while(i<=nt)
280    {
281      if (f==J[i]){return(list(1,i));}
282      i++;
283    }
284    return(list(0,0));
285  }
286  else
287  {
288    if ((typeof(f)=="intvec") or ((typeof(f)=="list") and (typeof(f[1])=="int")))
289    { // (intvec,list(intvec)) or
290      // (list(int),list(list(int)))
291      i=1;
292      t=0;
293      pos=0;
294      while((i<=nt) and (t==0))
295      {
296        t=1;
297        j=1;
298        if (size(f)!=size(J[i])){t=0;}
299        else
300        {
301          while ((j<=size(f)) and t)
302          {
303            if (f[j]!=J[i][j]){t=0;}
304            j++;
305          }
306        }
307        if (t){pos=i;}
308        i++;
309      }
310      if (t){return(list(1,pos));}
311      else{return(list(0,0));}
312    }
313    else
314    {
315      if (typeof(f)=="ideal")
316      { // (ideal,list(ideal))
317        i=1;
318        t=0;
319        pos=0;
320        while((i<=nt) and (t==0))
321        {
322          t=1;
323          j=1;
324          if (ncols(f)!=ncols(J[i])){t=0;}
325          else
326          {
327            while ((j<=ncols(f)) and t)
328            {
329              if (f[j]!=J[i][j]){t=0;}
330              j++;
331            }
332          }
333          if (t){pos=i;}
334          i++;
335        }
336        if (t){return(list(1,pos));}
337        else{return(list(0,0));}
338      }
339      else
340      {
341        if ((typeof(f)=="list") and (typeof(f[1])=="intvec"))
342        { // (list(intvec),list(list(intvec)))
343          i=1;
344          t=0;
345          pos=0;
346          while((i<=nt) and (t==0))
347          {
348            t=1;
349            j=1;
350            if (size(f)!=size(J[i])){t=0;}
351            else
352            {
353              while ((j<=size(f)) and t)
354              {
355                if (f[j]!=J[i][j]){t=0;}
356                j++;
357              }
358            }
359            if (t){pos=i;}
360            i++;
361          }
362          if (t){return(list(1,pos));}
363          else{return(list(0,0));}
364        }
365      }
366    }
367  }
368} example
369{ "EXAMPLE:"; echo = 2;
370  list L=(7,4,5,1,1,4,9);
371  memberpos(1,L);
372}
373
374
375proc subset(J,K)
376"USAGE:   subset(J,K);
377          (J,K)  expected (ideal,ideal)
378                   or     (list, list)
379RETURN:   1 if all the elements of J are in K, 0 if not.
380EXAMPLE:  subset; shows an example;"
381{
382  int i=1;
383  int nt;
384  if (typeof(J)=="ideal"){nt=ncols(J);}
385  else{nt=size(J);}
386  if (size(J)==0){return(1);}
387  while(i<=nt)
388  {
389    if (memberpos(J[i],K)[1]){i++;}
390    else {return(0);}
391  }
392  return(1);
393}
394example
395{ "EXAMPLE:"; echo = 2;
396  list J=list(7,3,2);
397  list K=list(1,2,3,5,7,8);
398  subset(J,K);
399}
400
401//*************Auxilliary routines**************
402
403
404// elimintfromideal: elimine the constant numbers from the ideal
405//     (designed for W, nonnull conditions)
406// input: ideal J in the ring @P
407// output:ideal K with the elements of J that are non constants, in the ring @P
408proc elimintfromideal(ideal J)
409{
410  int i;
411  int j=0;
412  ideal K;
413  if (size(J)==0){return(ideal(0));}
414  for (i=1;i<=ncols(J);i++){if (size(variables(J[i])) !=0){j++; K[j]=J[i];}}
415  return(K);
416}
417
418// simpqcoeffs : simplifies a quotient of two polynomials of @R
419//               for ring @R
420// input: two coeficients (or terms) of @R (that are considered as quotients)
421// output: the two coeficients reduced without common factors
422proc simpqcoeffs(poly n,poly m)
423{
424  def nc=content(n);
425  def mc=content(m);
426  def gc=gcd(nc,mc);
427  ideal s=n/gc,m/gc;
428  return (s);
429}
430
431
432// pdivi : pseudodivision of a polynomial f by an ideal F in @R
433//         in the ring @R
434// input:
435//   poly f0  (given in the ring @R)
436//   ideal F0 (given in the ring @R)
437// output:
438//   list (poly r, ideal q, poly mu)
439proc pdivi(poly f,ideal F)
440"USAGE:   pdivi(f,F);
441          poly f: the polynomial to be divided
442          ideal F: the divisor ideal
443RETURN:   A list (poly r, ideal q, poly m). r is the remainder of the
444          pseudodivision, q is the ideal of quotients, and m is the
445          factor by which f is to be multiplied.
446NOTE:     Pseudodivision of a polynomial f by an ideal F in @R. Returns a
447          list (r,q,m) such that m*f=r+sum(q.G).
448KEYWORDS: division, reduce
449EXAMPLE:  pdivi; shows an example"
450{
451  int i;
452  int j;
453  poly r=0;
454  poly mu=1;
455  def p=f;
456  ideal q;
457  for (i=1; i<=size(F); i++){q[i]=0;}
458  ideal lpf;
459  ideal lcf;
460  for (i=1;i<=size(F);i++){lpf[i]=leadmonom(F[i]);}
461  for (i=1;i<=size(F);i++){lcf[i]=leadcoef(F[i]);}
462  poly lpp;
463  poly lcp;
464  poly qlm;
465  poly nu;
466  poly rho;
467  int divoc=0;
468  ideal qlc;
469  while (p!=0)
470  {
471    i=1;
472    divoc=0;
473    lpp=leadmonom(p);
474    lcp=leadcoef(p);
475    while (divoc==0 and i<=size(F))
476    {
477      qlm=lpp/lpf[i];
478      if (qlm!=0)
479      {
480        qlc=simpqcoeffs(lcp,lcf[i]);
481        nu=qlc[2];
482        mu=mu*nu;
483        rho=qlc[1]*qlm;
484        p=nu*p-rho*F[i];
485        r=nu*r;
486        for (j=1;j<=size(F);j++){q[j]=nu*q[j];}
487        q[i]=q[i]+rho;
488        divoc=1;
489      }
490      else {i++;}
491    }
492    if (divoc==0)
493    {
494      r=r+lcp*lpp;
495      p=p-lcp*lpp;
496    }
497  }
498  list res=r,q,mu;
499  return(res);
500}
501example
502{ "EXAMPLE:"; echo = 2;
503  ring R=(0,a,b,c),(x,y),dp;
504  setglobalrings();
505  poly f=(ab-ac)*xy+(ab)*x+(5c);
506  ideal F=ax+b,cy+a;
507  def r=pdivi(f,F);
508  r;
509  r[3]*f-(r[2][1]*F[1]+r[2][2]*F[2])-r[1];
510}
511
512// pspol : S-poly of two polynomials in @R
513// @R
514// input:
515//   poly f  (given in the ring @R)
516//   poly g (given in the ring @R)
517// output:
518//   list (S, red):  S is the S-poly(f,g) and red is a Boolean variable
519//                if red==1 then S reduces by Buchberger 1st criterion (not used)
520proc pspol(poly f,poly g)
521{
522  def lcf=leadcoef(f);
523  def lcg=leadcoef(g);
524  def lpf=leadmonom(f);
525  def lpg=leadmonom(g);
526  def v=gcd(lpf,lpg);
527  def s=simpqcoeffs(lcf,lcg);
528  def vf=lpf/v;
529  def vg=lpg/v;
530  poly S=s[2]*vg*f-s[1]*vf*g;
531  return(S);
532}
533
534// facvar: Returns all the free-square factors of the elements
535//         of ideal J (non repeated). Integer factors are ignored,
536//         even 0 is ignored. It can be called from ideal @R, but
537//         the given ideal J must only contain poynomials in the
538//         parameters.
539//         Operates in the ring @P, but can be called from ring @R.
540// input:   ideal J
541// output:  ideal Jc: Returns all the free-square factors of the elements
542//         of ideal J (non repeated). Integer factors are ignored,
543//         even 0 is ignored. It can be called from ideal @R, but
544//         the given ideal J must only contain poynomials in the
545//         parameters.
546proc facvar(ideal J)
547"USAGE:   facvar(J);
548          J: an ideal in the parameters
549RETURN:   all the free-square factors of the elements
550          of ideal J (non repeated). Integer factors are ignored,
551          even 0 is ignored. It can be called from ideal @R, but
552          the given ideal J must only contain poynomials in the
553          parameters.
554NOTE:     Operates in the ring @P, and the ideal J must contain only
555          polynomials in the parameters, but can be called from ring @R.
556KEYWORDS: factor
557EXAMPLE:  facvar; shows an example"
558{
559  int i;
560  def RR=basering;
561  setring(@P);
562  def Ja=imap(RR,J);
563  if(size(Ja)==0){return(ideal(0));}
564  Ja=elimintfromideal(Ja); // also in ideal @P
565  ideal Jb;
566  if (size(Ja)==0){Jb=ideal(0);}
567  else
568  {
569    for (i=1;i<=ncols(Ja);i++){if(size(Ja[i])!=0){Jb=Jb,factorize(Ja[i],1);}}
570    Jb=simplify(Jb,2+4+8);
571    Jb=cld(Jb);
572    Jb=elimintfromideal(Jb); // also in ideal @P
573  }
574  setring(RR);
575  def Jc=imap(@P,Jb);
576  return(Jc);
577}
578example
579{ "EXAMPLE:"; echo = 2;
580  ring R=(0,a,b,c),(x,y,z),dp;
581  setglobalrings();
582  ideal J=a2-b2,a2-2ab+b2,abc-bc;
583  facvar(J);
584}
585
586// Wred: eliminate the factors in the polynom f that are in W
587//       in ring @RP
588// input:
589//   poly f:
590//   ideal W  of non-null conditions (already supposed that it is facvar)
591// output:
592//   poly f2  where the non-null conditions in W have been dropped from f
593proc Wred(poly f, ideal W)
594{
595  if (f==0){return(f);}
596  def RR=basering;
597  setring(@RP);
598  def ff=imap(RR,f);
599  def RPW=imap(RR,W);
600  def l=factorize(ff,2);
601  int i;
602  poly f1=1;
603  for(i=1;i<=size(l[1]);i++)
604  {
605    if ((memberpos(l[1][i],RPW)[1]) or (memberpos(-l[1][i],RPW)[1])){;}
606    else{f1=f1*((l[1][i])^(l[2][i]));}
607  }
608  setring(RR);
609  def f2=imap(@RP,f1);
610  return(f2);
611}
612
613// pnormalform: reduces a polynomial w.r.t. a red-spec dividing by N and eliminating factors in W.
614//              called in the ring @R
615//              operates in the ring @RP
616// input:
617//         poly  f
618//         ideal N  (depends only on the parameters)
619//         ideal W  (depends only on the parameters)
620//                   (N,W) must be a red-spec (depends only on the parameters)
621// output: poly f2 reduced w.r.t. to the red-spec (N,W)
622// note:   for security a lot of work is done. If (N,W) is already a red-spec it should be simplified
623proc pnormalform(poly f, ideal N, ideal W)
624"USAGE:   pnormalform(f,N,W);
625          f: the polynomial to be reduced modulo N,W (in parameters and
626             variables)
627          N: the null conditions ideal
628          W: the non-null conditions (set of irreducible polynomials, ideal)
629RETURN:   a reduced polynomial g of f, whose coefficients are reduced
630          modulo N and having no factor in W.
631NOTE:     Should be called from ring @R. Ideals N and W must be polynomials
632          in the parameters forming a red-specification (see definition)         the papers).
633KEYWORDS: division, pdivi, reduce
634EXAMPLE:  pnormalform; shows an example"
635{
636    def RR=basering;
637    setring(@RP);
638    def fa=imap(RR,f);
639    def Na=imap(RR,N);
640    def Wa=imap(RR,W);
641    option(redSB);
642    Na=groebner(Na);
643    def r=cld(reduce(fa,Na));
644    def f1=Wred(r[1],Wa);
645    setring(RR);
646    def f2=imap(@RP,f1);
647    return(f2)
648}
649example
650{ "EXAMPLE:"; echo = 2;
651  ring R=(0,a,b,c),(x,y),dp;
652  setglobalrings();
653  poly f=(b^2-1)*x^3*y+(c^2-1)*x*y^2+(c^2*b-b)*x+(a-bc)*y;
654  ideal N=(ab-c)*(a-b),(a-bc)*(a-b);
655  ideal W=a^2-b^2,bc;
656  def r=redspec(N,W);
657  pnormalform(f,r[1],r[2]);
658}
659
660// idint: ideal intersection
661//        in the ring @P.
662//        it works in an extended ring
663// input: two ideals in the ring @P
664// output the intersection of both (is not a GB)
665proc idint(ideal I, ideal J)
666{
667  def RR=basering;
668  ring T=0,t,lp;
669  def K=T+RR;
670  setring(K);
671  def Ia=imap(RR,I);
672  def Ja=imap(RR,J);
673  ideal IJ;
674  int i;
675  for(i=1;i<=size(Ia);i++){IJ[i]=t*Ia[i];}
676  for(i=1;i<=size(Ja);i++){IJ[size(Ia)+i]=(1-t)*Ja[i];}
677  ideal eIJ=eliminate(IJ,t);
678  setring(RR);
679  return(imap(K,eIJ));
680}
681
682
683// redspec: generates a red-specification
684//          called in any ring
685//          it changes to the ring @P
686// input:
687//   ideal N : the ideal of null-conditions
688//   ideal W : set of non-null polynomials: if W corresponds to no non null conditions then W=ideal(0)
689//             otherwise it should be given as an ideal.
690// returns: list (Na,Wa,DGN)
691// the completely reduced specification:
692//   Na = ideal reduced and radical of the red-spec
693//   facvar(Wa) = ideal the reduced non-null set of polynomials of the red-spec.
694//             if it corresponds to no non null conditions then it is ideal(0)
695//             otherwise the ideal is returned.
696//   DGN = the list of prime ideals associated to Na (uses primASSGTZ in "primdec.lib")
697//   none of the polynomials in facvar(Wa) are contained in none of the ideals in DGN
698//   If the given conditions are not compatible, then N=ideal(1) and DGN=list(ideal(1))
699proc redspec(ideal Ni, ideal Wi)
700"USAGE:   redspec(N,W);
701          N: null conditions ideal
702          W: set of non-null polynomials (ideal)
703RETURN:   a list (N1,W1,L1) containing a red-specification of the segment (N,W).
704          N1 is the radical reduced ideal characterizing the segment.
705          V(N1) is the Zarisky closure of the segment (N,W).
706          The segment S=V(N1) \ V(h), where h=prod(w in W1)
707          N1 is uniquely determined and no prime component of N1 contains none of
708          the polynomials in W1. The polynomials in W1 are prime and reduced
709          w.r.t. N1, and are considered non-null on the segment.
710          L1 contains the list of prime components of N1.
711NOTE:     can be called from ring @R but it works in ring @P.
712KEYWORDS: specification
713EXAMPLE:  redspec; shows an example"
714{
715  ideal Nc;
716  ideal Wc;
717  def RR=basering;
718  setring(@P);
719  def N=imap(RR,Ni);
720  def W=imap(RR,Wi);
721  ideal Wa;
722  ideal Wb;
723  if(size(W)==0){Wa=ideal(0);}
724     //when there are no non-null conditions then W=ideal(0)
725  else
726  {
727    Wa=facvar(W);
728  }
729  if (size(N)==0)
730  {
731    setring(RR);
732    Wc=imap(@P,Wa);
733    return(list(ideal(0), Wc, list(ideal(0))));
734  }
735  int i;
736  list LNb;
737  list LNa;
738  def LN=minAssGTZ(N);
739  for (i=1;i<=size(LN);i++)
740  {
741    option(redSB);
742    LNa[i]=groebner(LN[i]);
743  }
744  poly h=1;
745  if (size(Wa)!=0)
746  {
747    for(i=1;i<=size(Wa);i++){h=h*Wa[i];}
748  }
749  ideal Na;
750  intvec save_opt=option(get);
751  if (size(N)!=0 and (size(LNa)>0))
752  {
753    option(returnSB);
754    Na=intersect(LNa[1..size(LNa)]);
755    option(redSB);
756    Na=groebner(Na); // T_ is needed?
757    option(set,save_opt);
758  }
759  attrib(Na,"isSB",1);
760  if (reduce(h,Na,1)==0)
761  {
762    setring(RR);
763    Wc=imap(@P,Wa);
764    return(list (ideal(1),Wc,list(ideal(1))));
765  }
766  i=1;
767  while(i<=size(LNa))
768  {
769    if (reduce(h,LNa[i],1)==0){LNa=delete(LNa,i);}
770    else{ i++;}
771  }
772  if (size(LNa)==0)
773  {
774    setring(RR);
775    return(list(ideal(1),ideal(0),list(ideal(1))));
776  }
777  option(returnSB);
778  ideal Nb=intersect(LNa[1..size(LNa)]);
779  option(redSB);
780  Nb=groebner(Nb); // T_ is needed?
781  option(set,save_opt);
782  if (size(Wa)==0)
783  {
784    setring(RR);
785    Nc=imap(@P,Nb);
786    Wc=imap(@P,Wa);
787    LNb=imap(@P,LNa);
788    return(list(Nc,Wc,LNb));
789  }
790  Wb=ideal(0);
791  attrib(Nb,"isSB",1);
792  for (i=1;i<=size(Wa);i++){Wb[i]=reduce(Wa[i],Nb);}
793  Wb=facvar(Wb);
794  if (size(LNa)!=0)
795  {
796    setring(RR);
797    Nc=imap(@P,Nb);
798    Wc=imap(@P,Wb);
799    LNb=imap(@P,LNa);
800    return(list(Nc,Wc,LNb))
801  }
802  else
803  {
804    setring(RR);
805    Nd=imap(@P,Nb);
806    Wc=imap(@P,Wb);
807    kill LNb;
808    list LNb;
809    return(list(Nd,Wc,LNb))
810  }
811}
812example
813{ "EXAMPLE:"; echo = 2;
814  ring r=(0,a,b,c),(x,y),dp;
815  setglobalrings();
816  ideal N=(ab-c)*(a-b),(a-bc)*(a-b);
817  ideal W=a^2-b^2,bc;
818  redspec(N,W);
819}
820
821// lesspol: compare two polynomials by its leading power products
822// input:  two polynomials f,g in the ring @R
823// output: 0 if f<g,  1 if f>=g
824proc lesspol(poly f, poly g)
825{
826  if (leadmonom(f)<leadmonom(g)){return(1);}
827  else
828  {
829    if (leadmonom(g)<leadmonom(f)){return(0);}
830    else
831    {
832      if (leadcoef(f)<leadcoef(g)){return(1);}
833      else {return(0);}
834    }
835  }
836}
837
838// delfromideal: deletes the i-th polynomial from the ideal F
839proc delfromideal(ideal F, int i)
840{
841  int j;
842  ideal G;
843  if (size(F)<i){ERROR("delfromideal was called incorrect arguments");}
844  if (size(F)<=1){return(ideal(0));}
845  if (i==0){return(F)}
846  for (j=1;j<=size(F);j++)
847  {
848    if (j!=i){G[size(G)+1]=F[j];}
849  }
850  return(G);
851}
852
853// delidfromid: deletes the polynomials in J that are in I
854// input: ideals I,J
855// output: the ideal J without the polynomials in I
856proc delidfromid(ideal I, ideal J)
857{
858  int i; list r;
859  ideal JJ=J;
860  for (i=1;i<=size(I);i++)
861  {
862    r=memberpos(I[i],JJ);
863    if (r[1])
864    {
865      JJ=delfromideal(JJ,r[2]);
866    }
867  }
868  return(JJ);
869}
870
871// sortideal: sorts the polynomials in an ideal by lm in ascending order
872proc sortideal(ideal Fi)
873{
874  def RR=basering;
875  setring(@RP);
876  def F=imap(RR,Fi);
877  def H=F;
878  ideal G;
879  int i;
880  int j;
881  poly p;
882  while (size(H)!=0)
883  {
884    j=1;
885    p=H[1];
886    for (i=1;i<=size(H);i++)
887    {
888      if(lesspol(H[i],p)){j=i;p=H[j];}
889    }
890    G[size(G)+1]=p;
891    H=delfromideal(H,j);
892  }
893  setring(RR);
894  def GG=imap(@RP,G);
895  return(GG);
896}
897
898// mingb: given a basis (gb reducing) it
899// order the polynomials is ascending order and
900// eliminate the polynomials whose lpp is divisible by some
901// smaller one
902proc mingb(ideal F)
903{
904  int t; int i; int j;
905  def H=sortideal(F);
906  ideal G;
907  if (ncols(H)<=1){return(H);}
908  G=H[1];
909  for (i=2; i<=ncols(H); i++)
910  {
911    t=1;
912    j=1;
913    while (t and (j<i))
914    {
915      if((leadmonom(H[i])/leadmonom(H[j]))!=0) {t=0;}
916      j++;
917    }
918    if (t) {G[size(G)+1]=H[i];}
919  }
920  return(G);
921}
922
923
924// redgb: given a minimal bases (gb reducing) it
925// reduces each polynomial w.r.t. to the others
926proc redgb(ideal F, ideal N, ideal W)
927{
928  ideal G;
929  ideal H;
930  int i;
931  if (size(F)==0){return(ideal(0));}
932  for (i=1;i<=size(F);i++)
933  {
934    H=delfromideal(F,i);
935    G[i]=pnormalform(pdivi(F[i],H)[1],N,W);
936  }
937  return(G);
938}
939
940
941//********************Main routines for buildtree******************
942
943
944// splitspec: a new leading coefficient f is given to a red-spec
945//            then splitspec computes the two new red-spec by
946//            considering it null, and non null.
947// in ring @P
948// given f, and the red-spec (N,W)
949//     it outputs the null and the non-null red-spec adding f.
950//     if some of the output specifications has N=1 then
951//     there must be no split and buildtree must continue on
952//     the compatible red-spec
953// input:  poly f coefficient to split if needed
954//         list r=(N,W,LN) redspec
955// output: list L = list(ideal N0, ideal W0), list(ideal N1, ideal W1), cond
956proc splitspec(poly fi, list ri)
957{
958  def RR=basering;
959  def Ni=ri[1];
960  def Wi=ri[2];
961  setring(@P);
962  def f=imap(RR,fi);
963  def N=imap(RR,Ni);
964  def W=imap(RR,Wi);
965  f=Wred(f,W);
966  def N0=N;
967  def W1=W;
968  N0[size(N0)+1]=f;
969  def r0=redspec(N0,W);
970  W1[size(W1)+1]=f;
971  def r1=redspec(N,W1);
972  setring(RR);
973  def ra0=imap(@P,r0);
974  def ra1=imap(@P,r1);
975  def cond=imap(@P,f);
976  return (list(ra0,ra1,cond));
977}
978
979// discusspolys: given a basis B and a red-spec (N,W), it analyzes the
980//               leadcoef of the polynomials in B until it finds
981//               that one of them can be either null or non null.
982//               If at the end only the non null option is compatible
983//               then the reduced B has all the leadcoef non null.
984//               Else recbuildtree must split.
985// ring @R
986// input:  ideal B
987//         ideal N
988//         ideal W (a reduced-specification)
989// output: list of ((N0,W0,LN0),(N1,W1,LN1),Br,cond)
990//         cond is the condition to branch
991proc discusspolys(ideal B, list r)
992{
993  poly f;     poly f1;    poly f2;
994  poly cond;
995  def N=r[1]; def W=r[2]; def LN=r[3];
996  def Ba=B;   def F=B;
997  ideal N0=1; def W0=W;   list LN0=ideal(1);
998  def N1=N;   def W1=W;   def LN1=LN;
999  list L;
1000  list M;     list M0;    list M1;
1001  list rr;
1002  if (size(B)==0)
1003  {
1004    M0=N0,W0,LN0; // incompatible
1005    M1=N1,W1,LN1;
1006    M=M0,M1,B,poly(1);
1007    return(M);
1008  }
1009  while ((size(F)!=0) and ((N0[1]==1) or (N1[1]==1)))
1010  {
1011    f=F[1];
1012    F=delfromideal(F,1);
1013    f1=pnormalform(f,N,W);
1014    rr=memberpos(f,Ba);
1015    if (f1!=0)
1016    {
1017      Ba[rr[2]]=f1;
1018      if (pardeg(leadcoef(f1))!=0)
1019      {
1020        f2=Wred(leadcoef(f1),W);
1021        L=splitspec(f2,list(N,W,LN));
1022        N0=L[1][1]; W0=L[1][2]; LN0=L[1][3]; N1=L[2][1]; W1=L[2][2]; LN1=L[2][3];
1023        cond=L[3];
1024      }
1025    }
1026    else
1027    {
1028      Ba=delfromideal(Ba,rr[2]);
1029      N0=ideal(1); //F=ideal(0);
1030    }
1031  }
1032  M0=N0,W0,LN0;
1033  M1=N1,W1,LN1;
1034  M=M0,M1,Ba,cond;
1035  return(M);
1036}
1037
1038
1039// lcmlmonoms: computes the lcm of the leading monomials
1040//             of the polynomils f and g
1041// ring @R
1042proc lcmlmonoms(poly f,poly g)
1043{
1044  def lf=leadmonom(f);
1045  def lg=leadmonom(g);
1046  def gls=gcd(lf,lg);
1047  return((lf*lg)/gls);
1048}
1049
1050// placepairinlist
1051// input:  given a new pair of the form (i,j,lmij)
1052//         and a list of pairs of the same form
1053// ring @R
1054// output: it inserts the new pair in ascending order of lmij
1055proc placepairinlist(list pair,list P)
1056{
1057  list Pr;
1058  if (size(P)==0){Pr=insert(P,pair); return(Pr);}
1059  if (pair[3]<P[1][3]){Pr=insert(P,pair); return(Pr);}
1060  if (pair[3]>=P[size(P)][3]){Pr=insert(P,pair,size(P)); return(Pr);}
1061  kill Pr;
1062  list Pr;
1063  int j;
1064  int i=1;
1065  int loc=0;
1066  while((i<=size(P)) and (loc==0))
1067  {
1068    if (pair[3]>=P[i][3]){j=i; i++;}
1069    else{loc=1; j=i-1;}
1070  }
1071  Pr=insert(P,pair,j);
1072  return(Pr);
1073}
1074
1075// orderingpairs:
1076// input:  ideal F
1077// output: list of ordered pairs (i,j,lcmij) of F in ascending order of lcmij
1078//         if a pair verifies Buchberger 1st criterion it is not stored
1079// ring @R
1080proc orderingpairs(ideal F)
1081{
1082  int i;
1083  int j;
1084  poly lm;
1085  poly lpf;
1086  poly lpg;
1087  list P;
1088  list pair;
1089  if (size(F)<=1){return(P);}
1090  for (i=1;i<=size(F)-1;i++)
1091  {
1092    for (j=i+1;j<=size(F);j++)
1093    {
1094      lm=lcmlmonoms(F[i],F[j]);
1095      // Buchberger 1st criterion
1096      lpf=leadmonom(F[i]);
1097      lpg=leadmonom(F[j]);
1098      if (lpf*lpg!=lm)
1099      {
1100        pair=(i,j,lm);
1101        P=placepairinlist(pair,P);
1102      }
1103    }
1104  }
1105  return(P);
1106}
1107
1108// Buchberger 2nd criterion
1109// input:  integers i,j
1110//         list P of pairs of the form (i,j) not yet verified
1111// ring @R
1112proc criterion(int i, int j, list P, ideal B)
1113{
1114  def lcmij=lcmlmonoms(B[i],B[j]);
1115  int crit=0;
1116  int k=1;
1117  list ik; list jk;
1118  while ((k<=size(B)) and (crit==0))
1119  {
1120    if ((k!=i) and (k!=j))
1121    {
1122      if (i<k){ik=i,k;} else{ik=k,i;}
1123      if (j<k){jk=i,k;} else{jk=k,j;}
1124      if (not((memberpos(ik,P)[1]) or (memberpos(jk,P)[1])))
1125      {
1126        if ((lcmij)/leadmonom(B[k])!=0){crit=1;}
1127      }
1128    }
1129    k++;
1130  }
1131  return(crit);
1132}
1133
1134// discussSpolys: given a basis B and a red-spec (N,W), it analyzes the
1135//                leadcoef of the polynomials in B until it finds
1136//                that one of them can be either null or non null.
1137//                If at the end only the non null option is compatible
1138//                then the reduced B has all the leadcoef non null.
1139//                Else recbuildtree must split.
1140// ring @R
1141// input:  ideal B
1142//         ideal N
1143//         ideal W (a reduced-specification)
1144//         list  P current set of pairs of polynomials from B to be tested.
1145// output: list of (N0,W0,LN0),(N1,W1,LN1),Br,Pr,cond]
1146//         list Pr the not checked list of pairs.
1147proc discussSpolys(ideal B, list r, list P)
1148{
1149  int i; int j; int k;
1150  int npols; int nSpols; int tt;
1151  poly cond=1;
1152  poly lm; poly lpf; poly lpg;
1153  def F=B; def Pa=P; list Pa0;
1154  def N=r[1]; def W=r[2]; def LN=r[3];
1155  ideal N0=1; def W0=W; list LN0=ideal(1);
1156  def N1=N; def W1=W; def LN1=LN;
1157  ideal Bw;
1158  poly S;
1159  list L; list L0; list L1;
1160  list M; list M0; list M1;
1161  list pair;
1162  list KK; int loc;
1163  int crit;
1164  poly h;
1165  if (size(B)==0)
1166  {
1167    M0=N0,W0,LN0;
1168    M1=N1,W1,LN1;
1169    M=M0,M1,ideal(0),Pa,cond;
1170    return(M);
1171  }
1172  tt=1;
1173  i=1;
1174  while ((tt) and (i<=size(B)))
1175  {
1176    h=B[i];
1177    for (j=1;j<=npars(@R);j++)
1178    {
1179      h=subst(h,par(j),0);
1180    }
1181    if (h!=B[i]){tt=0;}
1182    i++;
1183  }
1184  if (tt)
1185  {
1186    //"T_ a non parametric system occurred";
1187    def RR=basering;
1188    def RL=ringlist(RR);
1189    RL[1]=0;
1190    def LRR=ring(RL);
1191    setring(LRR);
1192    def BP=imap(RR,B);
1193    option(redSB);
1194    BP=groebner(BP);
1195    setring(RR);
1196    B=imap(LRR,BP);
1197    M0=ideal(1),W0,LN0;
1198    M1=N1,W1,LN1;
1199    M=M0,M1,B,list(),cond;
1200    return(M);
1201  }
1202  if (size(Pa)==0){npols=size(B); Pa=orderingpairs(F); nSpols=size(Pa);}
1203  while ((size(Pa)!=0) and (N0[1]==1) or (N1[1]==1))
1204  {
1205    pair=Pa[1];
1206    i=pair[1];
1207    j=pair[2];
1208    Pa=delete(Pa,1);
1209    // Buchberger 1st criterion (not needed here, it is already eliminated
1210    // when creating the list of pairs
1211    //T_ lpf=leadmonom(F[i]);
1212    //T_ lpg=leadmonom(F[j]);
1213    //T_ if (lpf*lpg!=pair[3])
1214    //T_ {
1215      for (k=1;k<=size(Pa);k++){Pa0[k]=delete(Pa[k],3);}
1216      //crit=criterion(i,j,Pa0,F); // produces errors?
1217      crit=0;
1218      if (not(crit))
1219      {
1220        S=pspol(F[i],F[j]);
1221        KK=pdivi(S,F);
1222        S=KK[1];
1223        if (S!=0)
1224        {
1225          S=pnormalform(S,N,W);
1226          if (S!=0)
1227          {
1228            L=discusspolys(ideal(S),list(N,W,LN));
1229            N0=L[1][1];
1230            W0=L[1][2];
1231            LN0=L[1][3];
1232            N1=L[2][1];
1233            W1=L[2][2];
1234            LN1=L[2][3];
1235            S=L[3][1];
1236            cond=L[4];
1237            if (S==1)
1238            {
1239              M0=ideal(1),W0,list(ideal(1));
1240              M1=N1,W1,LN1;
1241              M=M0,M1,ideal(1),list(),cond;
1242              return(M);
1243            }
1244            if (S!=0)
1245            {
1246              F[size(F)+1]=S;
1247              npols=size(F);
1248              //"T_ number of polynoms in the basis="; npols;
1249              for (k=1;k<size(F);k++)
1250              {
1251                lm=lcmlmonoms(F[k],S);
1252                // Buchberger 1st criterion
1253                lpf=leadmonom(F[k]);
1254                lpg=leadmonom(S);
1255                if (lpf*lpg!=lm)
1256                {
1257                  pair=k,size(F),lm;
1258                  Pa=placepairinlist(pair,Pa);
1259                  nSpols=size(Pa);
1260                  //"T_ number of S-polynoms to test="; nSpols;
1261                }
1262              }
1263              if (N0[1]==1){N=N1; W=W1; LN=LN1;}
1264            }
1265          }
1266        }
1267      }
1268    //T_ }
1269  }
1270  M0=N0,W0,LN0;
1271  M1=N1,W1,LN1;
1272  M=M0,M1,F,Pa,cond;
1273  return(M);
1274}
1275
1276
1277// buildtree: Basic routine generating a first reduced CGS
1278//     it will define the rings @R, @P and @RP as global rings
1279//     and the list @T a global list that will be killed at the output
1280// input:  ideal F in ring K[a][x];
1281// output: list T of lists whose list elements are of the form
1282//         T[i]=list(list lab, boolean terminal, ideal B, ideal N, ideal W, list of ideals decomp of N,
1283//              ideal of monomials lpp);
1284// all the ideals are in the ring K[a][x];
1285proc buildtree(ideal F, list #)
1286"USAGE:   buildtree(F);
1287          F: ideal in K[a][x] (parameters and variables) to be discussed
1288RETURN:   Returns a list T describing a dichotomic discussion tree, whose
1289          content is the first discussion of the ideal F of K[a][x].
1290          The first element of the list is the root, and contains
1291            [1] label: intvec(-1)
1292            [2] number of children : int
1293            [3] the ideal F
1294            [4], [5], [6] the red-spec of the null and non-null conditions
1295                given (as option). ideal (0), ideal (0), list(ideal(0)) if
1296                no optional conditions are given.
1297            [7] the set of lpp of ideal F
1298            [8] condition that was taken to reach the vertex
1299                (poly 1, for the root).
1300          The remaning elements of the list represent vertices of the tree:
1301          with the same structure:
1302            [1] label: intvec (1,0,0,1,...) gives its position in the tree:
1303                first branch condition is taken non-null, second null,...
1304            [2] number of children (0 if it is a terminal vertex)
1305            [3] the specialized ideal with the previous assumed conditions
1306                to reach the vertex
1307            [4],[5],[6] the red-spec of the previous assumed conditions
1308                to reach the vertex
1309            [7] the set of lpp of the specialized ideal at this stage
1310            [8] condition that was taken to reach the vertex from the
1311                father's vertex (that was taken non-null if the last
1312                integer in the label is 1, and null if it is 0)
1313          The terminal vertices form a disjoint partition of the parameter space
1314          whose bases specialize to the reduced Groebner basis of the
1315          specialized ideal on each point of the segment and preserve
1316          the lpp. So they form a disjoint reduced CGS.
1317NOTE:     The basering R, must be of the form K[a][x], a=parameters,
1318          x=variables, and should be defined previously. The ideal must
1319          be defined on R.
1320          The disjoint and reduced CGS built by buildtree can be obtained
1321          from the output of buildtree by calling finalcases(T); this
1322          selects the terminal vertices.
1323          The content of buildtree can be written in a file that is readable
1324          by Maple in order to plot its content using buildtreetoMaple;
1325          The file written by buildtreetoMaple when readed in a Maple
1326          worksheet can be plotted using the dbgb routine tplot;
1327
1328KEYWORDS: CGS, disjoint, reduced, comprehensive Groebner system
1329EXAMPLE:  buildtree; shows an example"
1330{
1331  list @T;
1332  exportto(Top,@T);
1333  def @R=basering;
1334  setglobalrings();
1335  int i;
1336  int j;
1337  ideal B;
1338  poly f;
1339  poly cond=1;
1340  def N=ideal(0);
1341  def W=ideal(0);
1342  list LN;
1343  LN[1]=ideal(0);
1344  if (size(#)==2)
1345  {
1346    N=#[1];
1347    W=#[2];
1348    def LL=redspec(N,W);
1349    N=LL[1];
1350    W=LL[2];
1351    LN=LL[3];
1352    j=1;
1353    for (i=1;i<=size(F);i++)
1354    {
1355      f=pnormalform(F[i],N,W);
1356      if (f!=0){B[j]=f;j++;}
1357    }
1358  }
1359  else {B=F;}
1360  def lpp=ideal(0);
1361  if (size(B)==0){lpp=ideal(0);}
1362  else
1363  {
1364     for (i=1;i<=size(B);i++){lpp[i]=leadmonom(B[i]);}
1365    // lpp=ideal of lead power product of the polys in B
1366  }
1367  intvec lab=-1;
1368  int term=0;
1369  list root;
1370  root[1]=lab;
1371  root[2]=term;
1372  root[3]=B;
1373  root[4]=N;
1374  root[5]=W;
1375  root[6]=LN;
1376  root[7]=lpp;
1377  root[8]=cond;
1378  @T[1]=root;
1379  list P;
1380  recbuildtree(root,P);
1381  def T=@T;
1382  kill @T;
1383  return(T)
1384}
1385example
1386{ "EXAMPLE:"; echo = 2;
1387  ring R=(0,a1,a2,a3,a4),(x1,x2,x3,x4),dp;
1388  ideal F=x4-a4+a2,
1389    x1+x2+x3+x4-a1-a3-a4,
1390    x1*x3*x4-a1*a3*a4,
1391    x1*x3+x1*x4+x2*x3+x3*x4-a1*a4-a1*a3-a3*a4;
1392  def T=buildtree(F);
1393  finalcases(T);
1394  buildtreetoMaple(T,"Tb","Tb.txt");
1395}
1396
1397// recbuildtree: auxilliary recursive routine called by buildtree
1398proc recbuildtree(list v, list P)
1399{
1400  def vertex=v;
1401  int i;
1402  int j;
1403  int pos;
1404  list P0;
1405  list P1;
1406  poly f;
1407  def lab=vertex[1];
1408  if ((size(lab)>1) and (lab[1]==-1))
1409  {lab=lab[2..size(lab)];}
1410  def term=vertex[2];
1411  def B=vertex[3];
1412  def N=vertex[4];
1413  def W=vertex[5];
1414  def LN=vertex[6];
1415  def lpp=vertex[7];
1416  def cond=vertex[8];
1417  def lab0=lab;
1418  def lab1=lab;
1419  if ((size(lab)==1) and (lab[1]==-1))
1420  {
1421    lab0=0;
1422    lab1=1;
1423  }
1424  else
1425  {
1426    lab0[size(lab)+1]=0;
1427    lab1[size(lab)+1]=1;
1428  }
1429  list vertex0;
1430  list vertex1;
1431  ideal B0;
1432  ideal lpp0;
1433  ideal lpp1;
1434  ideal N0=1;
1435  def W0=ideal(0);
1436  list LN0=ideal(1);
1437  def B1=B;
1438  def N1=N;
1439  def W1=W;
1440  list LN1=LN;
1441  list L;
1442  if (size(P)==0)
1443  {
1444    L=discusspolys(B,list(N,W,LN));
1445    N0=L[1][1];
1446    W0=L[1][2];
1447    LN0=L[1][3];
1448    N1=L[2][1];
1449    W1=L[2][2];
1450    LN1=L[2][3];
1451    B1=L[3];
1452    cond=L[4];
1453  }
1454  if ((size(B1)!=0) and (N0[1]==1))
1455  {
1456    L=discussSpolys(B1,list(N1,W1,LN1),P);
1457    N0=L[1][1];
1458    W0=L[1][2];
1459    LN0=L[1][3];
1460    N1=L[2][1];
1461    W1=L[2][2];
1462    LN1=L[2][3];
1463    B1=L[3];
1464    P1=L[4];
1465    cond=L[5];
1466    lpp=ideal(0);
1467    for (i=1;i<=size(B1);i++){lpp[i]=leadmonom(B1[i]);}
1468  }
1469  vertex[3]=B1;
1470  vertex[4]=N1; // unnecessary
1471  vertex[5]=W1; // unnecessary
1472  vertex[6]=LN1;// unnecessary
1473  vertex[7]=lpp;
1474  vertex[8]=cond;
1475  if (size(@T)>0)
1476  {
1477    pos=size(@T)+1;
1478    @T[pos]=vertex;
1479  }
1480  if ((N0[1]!=1) and (N1[1]!=1))
1481  {
1482    vertex1[1]=lab1;
1483    vertex1[2]=0;
1484    vertex1[3]=B1;
1485    vertex1[4]=N1;
1486    vertex1[5]=W1;
1487    vertex1[6]=LN1;
1488    vertex1[7]=lpp1;
1489    vertex1[8]=cond;
1490    if (size(B1)==0){B0=ideal(0); lpp0=ideal(0);}
1491    else
1492    {
1493      j=1;
1494      lpp0=ideal(0);
1495      for (i=1;i<=size(B1);i++)
1496      {
1497        f=pnormalform(B1[i],N0,W0);
1498        if (f!=0){B0[j]=f; lpp0[j]=leadmonom(f);j++;}
1499      }
1500    }
1501    vertex0[1]=lab0;
1502    vertex0[2]=0;
1503    vertex0[3]=B0;
1504    vertex0[4]=N0;
1505    vertex0[5]=W0;
1506    vertex0[6]=LN0;
1507    vertex0[7]=lpp0;
1508    vertex0[8]=cond;
1509    recbuildtree(vertex0,P0);
1510    recbuildtree(vertex1,P1);
1511  }
1512  else
1513  {
1514    vertex[2]=1;
1515    B1=mingb(B1);
1516    vertex[3]=redgb(B1,N1,W1);
1517    vertex[4]=N1;
1518    vertex[5]=W1;
1519    vertex[6]=LN1;
1520    lpp=ideal(0);
1521    for (i=1;i<=size(vertex[3]);i++){lpp[i]=leadmonom(vertex[3][i]);}
1522    vertex[7]=lpp;
1523    vertex[8]=cond;
1524    @T[pos]=vertex;
1525  }
1526}
1527
1528//****************End of BuildTree*************************************
1529
1530//****************Begin BuildTree To Maple*****************************
1531
1532// buildtreetoMaple: writes the list provided by buildtree to a file
1533//    containing the table representing it in Maple
1534
1535// writes the list L=buildtree(F) to a file "writefile" that
1536// is readable by Maple whith name T
1537// input:
1538//   L: the list output by buildtree
1539//   T: the name (string) of the output table in Maple
1540//   writefile: the name of the datafile where the output is to be stored
1541// output:
1542//   the result is written on the datafile "writefile" containig
1543//   the assignement to the table with name "T"
1544proc buildtreetoMaple(list L, string T, string writefile)
1545"USAGE:   buildtreetoMaple(T, TM, writefile);
1546          T: is the list provided by buildtree,
1547          TM: is the name (string) of the table variable in Maple that will represent
1548             the output of buildtree,
1549          writefile: is the name (string) of the file where to write the content.
1550RETURN:   writes the list provided by buildtree to a file
1551          containing the table representing it in Maple.
1552KEYWORDS: buildtree, Maple
1553EXAMPLE:  buildtreetoMaple; shows an example"
1554{
1555  short=0;
1556  poly cond;
1557  int i;
1558  link LLw=":w "+writefile;
1559  string La=string("table(",T,");");
1560  write(LLw, La);
1561  close(LLw);
1562  link LLa=":a "+writefile;
1563  def RL=ringlist(@R);
1564  list p=RL[1][2];
1565  string param=string(p[1]);
1566  if (size(p)>1)
1567  {
1568    for(i=2;i<=size(p);i++){param=string(param,",",p[i]);}
1569  }
1570  list v=RL[2];
1571  string vars=string(v[1]);
1572  if (size(v)>1)
1573  {
1574    for(i=2;i<=size(v);i++){vars=string(vars,",",v[i]);}
1575  }
1576  list xord;
1577  list pord;
1578  if (RL[1][3][1][1]=="dp"){pord=string("tdeg(",param);}
1579  if (RL[1][3][1][1]=="lp"){pord=string("plex(",param);}
1580  if (RL[3][1][1]=="dp"){xord=string("tdeg(",vars);}
1581  if (RL[3][1][1]=="lp"){xord=string("plex(",vars);}
1582  write(LLa,string(T,"[[9]]:=",xord,");"));
1583  write(LLa,string(T,"[[10]]:=",pord,");"));
1584  write(LLa,string(T,"[[11]]:=true; "));
1585  list S;
1586  for (i=1;i<=size(L);i++)
1587  {
1588    if (L[i][2]==0)
1589    {
1590      cond=L[i][8];
1591      S=btcond(T,L[i],cond);
1592      write(LLa,S[1]);
1593      write(LLa,S[2]);
1594    }
1595    S=btbasis(T,L[i]);
1596    write(LLa,S);
1597    S=btN(T,L[i]);
1598    write(LLa,S);
1599    S=btW(T,L[i]);
1600    write(LLa,S);
1601    if (L[i][2]==1) {S=btterminal(T,L[i]); write(LLa,S);}
1602    S=btlpp(T,L[i]);
1603    write(LLa,S);
1604  }
1605  close(LLa);
1606}
1607example
1608{ "EXAMPLE:"; echo = 2;
1609  ring R=(0,a1,a2,a3,a4),(x1,x2,x3,x4),dp;
1610  ideal F=x4-a4+a2,
1611   x1+x2+x3+x4-a1-a3-a4,
1612   x1*x3*x4-a1*a3*a4,
1613   x1*x3+x1*x4+x2*x3+x3*x4-a1*a4-a1*a3-a3*a4;
1614  def T=buildtree(F);
1615  finalcases(T);
1616  buildtreetoMaple(T,"Tb","Tb.txt");
1617}
1618
1619// auxiliary routine called by buildtreetoMaple
1620// input:
1621//   list L: element i of the list of buildtree(F)
1622// output:
1623//   the string of T[[lab,1]]:=label; in Maple
1624proc btterminal(string T, list L)
1625{
1626  int i;
1627  string Li;
1628  string term;
1629  string coma=",";
1630  if (L[2]==0){term="false";} else {term="true";}
1631  def lab=L[1];
1632  string slab;
1633  if ((size(lab)==1) and lab[1]==-1)
1634  {slab="";coma="";} //if (size(lab)==0)
1635  else
1636  {
1637    slab=string(lab[1]);
1638    if (size(lab)>=1)
1639    {
1640      for (i=2;i<=size(lab);i++){slab=string(slab,",",lab[i]);}
1641    }
1642  }
1643  Li=string(T,"[[",slab,coma,"6]]:=",term,"; ");
1644  return(Li);
1645}
1646
1647// auxiliary routine called by buildtreetoMaple
1648// input:
1649//   list L: element i of the list of buildtree(F)
1650// output:
1651//   the string of T[[lab,3]] (basis); in Maple
1652proc btbasis(string T, list L)
1653{
1654  int i;
1655  string Li;
1656  string coma=",";
1657  def lab=L[1];
1658  string slab;
1659  if ((size(lab)==1) and lab[1]==-1)
1660  {slab="";coma="";} //if (size(lab)==0)
1661  else
1662  {
1663    slab=string(lab[1]);
1664    if (size(lab)>=1)
1665    {
1666      for (i=2;i<=size(lab);i++){slab=string(slab,",",lab[i]);}
1667    }
1668  }
1669  Li=string(T,"[[",slab,coma,"3]]:=[",L[3],"]; ");
1670  return(Li);
1671}
1672
1673// auxiliary routine called by buildtreetoMaple
1674// input:
1675//   list L: element i of the list of buildtree(F)
1676// output:
1677//   the string of T[[lab,4]] (null conditions ideal); in Maple
1678proc btN(string T, list L)
1679{
1680  int i;
1681  string Li;
1682  string coma=",";
1683  def lab=L[1];
1684  string slab;
1685  if ((size(lab)==1) and lab[1]==-1)
1686  {slab=""; coma="";}
1687  else
1688  {
1689    slab=string(lab[1]);
1690    if (size(lab)>=1)
1691    {
1692      for (i=2;i<=size(lab);i++){slab=string(slab,",",lab[i]);}
1693    }
1694  }
1695  if ((size(lab)==1) and lab[1]==-1)
1696    {Li=string(T,"[[",slab,coma,"4]]:=[ ]; ");}
1697  else
1698    {Li=string(T,"[[",slab,coma,"4]]:=[",L[4],"]; ");}
1699  return(Li);
1700}
1701
1702// auxiliary routine called by buildtreetoMaple
1703// input:
1704//   list L: element i of the list of buildtree(F)
1705// output:
1706//   the string of T[[lab,5]] (null conditions ideal); in Maple
1707proc btW(string T, list L)
1708{
1709  int i;
1710  string Li;
1711  string coma=",";
1712  def lab=L[1];
1713  string slab;
1714  if ((size(lab)==1) and lab[1]==-1)
1715  {slab=""; coma="";}
1716  else
1717  {
1718    slab=string(lab[1]);
1719    if (size(lab)>=1)
1720    {
1721      for (i=2;i<=size(lab);i++){slab=string(slab,",",lab[i]);}
1722    }
1723  }
1724  if (size(L[5])==0)
1725    {Li=string(T,"[[",slab,coma,"5]]:={ }; ");}
1726  else
1727    {Li=string(T,"[[",slab,coma,"5]]:={",L[5],"}; ");}
1728  return(Li);
1729}
1730
1731// auxiliary routine called by buildtreetoMaple
1732// input:
1733//   list L: element i of the list of buildtree(F)
1734// output:
1735//   the string of T[[lab,12]] (lpp); in Maple
1736proc btlpp(string T, list L)
1737{
1738  int i;
1739  string Li;
1740  string coma=",";;
1741  def lab=L[1];
1742  string slab;
1743  if ((size(lab)==1) and lab[1]==-1)
1744  {slab=""; coma="";}
1745  else
1746  {
1747    slab=string(lab[1]);
1748    if (size(lab)>=1)
1749    {
1750      for (i=2;i<=size(lab);i++){slab=string(slab,",",lab[i]);}
1751    }
1752  }
1753  if (size(L[7])==0)
1754  {
1755    Li=string(T,"[[",slab,coma,"12]]:=[ ]; ");
1756  }
1757  else
1758  {
1759    Li=string(T,"[[",slab,coma,"12]]:=[",L[7],"]; ");
1760  }
1761  return(Li);
1762}
1763
1764// auxiliary routine called by buildtreetoMaple
1765// input:
1766//   list L: element i of the list of buildtree(F)
1767// output:
1768//   the list of strings of (T[[lab,0]]=0,T[[lab,1]]<>0); in Maple
1769proc btcond(string T, list L, poly cond)
1770{
1771  int i;
1772  string Li1;
1773  string Li2;
1774  def lab=L[1];
1775  string slab;
1776  string coma=",";;
1777    if ((size(lab)==1) and lab[1]==-1)
1778    {slab=""; coma="";}
1779  else
1780  {
1781    slab=string(lab[1]);
1782    if (size(lab)>=1)
1783    {
1784      for (i=2;i<=size(lab);i++){slab=string(slab,",",lab[i]);}
1785    }
1786  }
1787  Li1=string(T,"[[",slab+coma,"0]]:=",L[8],"=0; ");
1788  Li2=string(T,"[[",slab+coma,"1]]:=",L[8],"<>0; ");
1789  return(list(Li1,Li2));
1790}
1791
1792//*****************End of BuildtreetoMaple*********************
1793
1794//*****************Begin of Selectcases************************
1795
1796// given an intvec with sum=n
1797// it returns the list of intvect with the sum=n+1
1798proc comp1(intvec l)
1799{
1800  list L;
1801  int p=size(l);
1802  int i;
1803  if (p==0){return(l);}
1804  if (p==1){return(list(intvec(l[1]+1)));}
1805  L[1]=intvec((l[1]+1),l[2..p]);
1806  L[p]=intvec(l[1..p-1],(l[p]+1));
1807  for (i=2;i<p;i++)
1808  {
1809    L[i]=intvec(l[1..(i-1)],(l[i]+1),l[(i+1)..p]);
1810  }
1811  return(L);
1812}
1813
1814// comp: p-compositions of n
1815// input
1816//   int n;
1817//   int p;
1818// return
1819//   the list of all intvec (p-composition of n)
1820proc comp(int n,int p)
1821{
1822  if (n<0){ERROR("comp was called with negative argument");}
1823  if (n==0){return(list(0:p));}
1824  int i;
1825  int k;
1826  list L1=comp(n-1,p);
1827  list L=comp1(L1[1]);
1828  list l;
1829  list la;
1830  for (i=2; i<=size(L1);i++)
1831  {
1832    l=comp1(L1[i]);
1833    for (k=1;k<=size(l);k++)
1834    {
1835      if(not(memberpos(l[k],L)[1]))
1836      {L[size(L)+1]=l[k];}
1837    }
1838  }
1839  return(L);
1840}
1841
1842// given the matrices of coefficients and monomials m amd m1 of
1843// two polynomials (the first one contains all the terms of f
1844// and the second only those of f
1845// it returns the list with the comon monomials and the list of coefficients
1846// of the polynomial f with zeroes if necessary.
1847proc adaptcoef(matrix m, matrix m1)
1848{
1849  int i;
1850  int j;
1851  int ncm=ncols(m);
1852  int ncm1=ncols(m1);
1853  ideal T;
1854  for (i=1;i<=ncm;i++){T[i]=m[1,i];}
1855  ideal C;
1856  for (i=1;i<=ncm;i++){C[i]=0;}
1857  for (i=1;i<=ncm;i++)
1858  {
1859    j=1;
1860    while((j<ncm1) and (m1[1,j]>m[1,i])){j++;}
1861    if (m1[1,j]==m[1,i]){C[i]=m1[2,j];}
1862  }
1863  return(list(T,C));
1864}
1865
1866// given teh ideal of non-null conditions and an intvec lambda
1867// with the exponents of each w in W
1868// it returns the polynomial prod (w_i)^(lambda_i).
1869proc WW(ideal W, intvec lambda)
1870{
1871  if (size(W)==0){return(poly(1));}
1872  poly w=1;
1873  int i;
1874  for (i=1;i<=ncols(W);i++)
1875  {
1876    w=w*(W[i])^(lambda[i]);
1877  }
1878  return(w);
1879}
1880
1881// given a polynomial f and the non-null conditions W
1882// WPred eliminates the factors in f that are in W
1883// ring @PAB
1884// input:
1885//   poly f:
1886//   ideal W  of non-null conditions (already supposed that it is facvar)
1887// output:
1888//   poly f2  where the non-null conditions in W have been dropped from f
1889proc WPred(poly f, ideal W)
1890{
1891  if (f==0){return(f);}
1892  def l=factorize(f,2);
1893  int i;
1894  poly f1=1;
1895  for(i=1;i<=size(l[1]);i++)
1896  {
1897    if (memberpos(l[1][i],W)[1]){;}
1898    else{f1=f1*((l[1][i])^(l[2][i]));}
1899  }
1900  return(f1);
1901}
1902
1903//genimage
1904// ring @R
1905//input:
1906//   poly f1, idel N1,ideal W1,poly f2, ideal N2, ideal W2
1907//   corresponding to two polynomials having the same lpp
1908//   f1 in the redspec given by N1,W1,  f2 in the redspec given by N2,W2
1909//output:
1910//   the list of (ideal GG, list(list r1, list r2))
1911//   where g an ideal whose elements have the same lpp as f1 and f2
1912//   that specialize well to f1 in N1,W1 and to f2 in N2,W2.
1913//   If it doesn't exist a genimage, then g=ideal(0).
1914proc genimage(poly f1, ideal N1, ideal W1, poly f2, ideal N2, ideal W2)
1915{
1916  int i; ideal W12;  poly ff1; poly g1=0; ideal GG;
1917  int tt=1;
1918  // detect whether f1 reduces to 0 on segment 2
1919  ff1=pnormalform(f1,N2,W2);
1920  if (ff1==0)
1921  {
1922    // detect whether N1 is included in N2
1923    def RR=basering;
1924    setring @P;
1925    def NP1=imap(RR,N1);
1926    def NP2=imap(RR,N2);
1927    poly nr;
1928    i=1;
1929    while ((tt) and (i<=size(NP1)))
1930    {
1931      nr=reduce(NP1[i],NP2);
1932      if (nr!=0){tt=0;}
1933      i++;
1934    }
1935    setring(RR);
1936  }
1937  else{tt=0;}
1938  if (tt==1)
1939  {
1940    // detect whether W1 intersect W2 is non-empty
1941    for (i=1;i<=size(W1);i++)
1942    {
1943      if (memberpos(W1[i],W2)[1])
1944      {
1945        W12[size(W12)+1]=W1[i];
1946      }
1947      else
1948      {
1949        if (nonnull(W1[i],N2,W2))
1950        {
1951          W12[size(W12)+1]=W1[i];
1952        }
1953      }
1954    }
1955    for (i=1;i<=size(W2);i++)
1956    {
1957      if (not(memberpos(W2[i],W12)[1]))
1958      {
1959        W12[size(W12)+1]=W2[i];
1960      }
1961    }
1962  }
1963  if (tt==1){g1=extendpoly(f1,N1,W12);}
1964  if (g1!=0)
1965  {
1966    //T_ "genimage has found a more generic basis (method 1)";
1967    //T_ "f1:"; f1; "N1:"; N1; "W1:"; W1;
1968    //T_ "f2:"; f2; "N2:"; N2; "W2:"; W2;
1969    //T_ "g1:"; g1;
1970    if (pnormalform(g1,N1,W1)==0)
1971    {
1972      GG=f1,g1;
1973      //T_ "A sheaf has been found (method 2)";
1974    }
1975    else
1976    {
1977      GG=g1;
1978    }
1979    return(GG);
1980  }
1981
1982  // begins the second step;
1983  int bound=6;
1984  // in ring @R
1985  int j; int g=0; int alpha; int r1; int s1=1; int s2=1;
1986  poly G;
1987  matrix qT;
1988  matrix T;
1989  ideal N10;
1990  poly GT;
1991  ideal N12=N1,N2;
1992  def varx=maxideal(1);
1993  int nx=size(varx);
1994  poly pvarx=1;
1995  for (i=1;i<=nx;i++){pvarx=pvarx*varx[i];}
1996  def m=coef(43*f1+157*f2,pvarx);
1997  def m1=coef(f1,pvarx);
1998  def m2=coef(f2,pvarx);
1999  list L1=adaptcoef(m,m1);
2000  list L2=adaptcoef(m,m2);
2001  ideal Tm=L1[1];
2002  ideal c1=L1[2];
2003  ideal c2=L2[2];
2004  poly ww1;
2005  poly ww2;
2006  poly cA1;
2007  poly cB1;
2008  matrix TT;
2009  poly H;
2010  list r;
2011  ideal q;
2012  poly mu;
2013  ideal N;
2014
2015  // in ring @PAB
2016  list Px=ringlist(@P);
2017  list v="@A","@B";
2018  Px[2]=Px[2]+v;
2019  def npx=size(Px[3][1][2]);
2020  Px[3][1][2]=1:(npx+size(v));
2021  def @PAB=ring(Px);
2022  setring(@PAB);
2023
2024  poly PH;
2025  ideal NP;
2026  list rP;
2027  def PN1=imap(@R,N1);
2028  def PW1=imap(@R,W1);
2029  def PN2=imap(@R,N2);
2030  def PW2=imap(@R,W2);
2031  def a1=imap(@R,c1);
2032  def a2=imap(@R,c2);
2033  matrix PT;
2034  ideal PN;
2035  ideal PN12=PN1,PN2;
2036  PN=liftstd(PN12,PT);
2037  list compos1;
2038  list compos2;
2039  list compos0;
2040  intvec comp0;
2041  poly w1=0;
2042  poly w2=0;
2043  poly h;
2044  poly cA=0;
2045  poly cB=0;
2046  int t=0;
2047  list l;
2048  poly h1;
2049  g=0;
2050  while ((g<=bound) and not(t))
2051  {
2052    compos0=comp(g,2);
2053    r1=1;
2054    while ((r1<=size(compos0)) and not(t))
2055    {
2056      comp0=compos0[r1];
2057      if (comp0[1]<=bound/2)
2058      {
2059        compos1=comp(comp0[1],ncols(PW1));
2060        s1=1;
2061        while ((s1<=size(compos1)) and not(t))
2062        {
2063          if (comp0[2]<=bound/2)
2064          {
2065            compos2=comp(comp0[2],ncols(PW2));
2066            s2=1;
2067            while ((s2<=size(compos2)) and not(t))
2068            {
2069              w1=WW(PW1,compos1[s1]);
2070              w2=WW(PW2,compos2[s2]);
2071              h=@A*w1*a1[1]-@B*w2*a2[1];
2072              h=reduce(h,PN);
2073              if (h==0){cA=1;cB=-1;}
2074              else
2075              {
2076                l=factorize(h,2);
2077                h1=1;
2078                for(i=1;i<=size(l[1]);i++)
2079                {
2080                  if ((memberpos(@A,variables(l[1][i]))[1]) or  (memberpos(@B,variables(l[1][i]))[1]))
2081                  {h1=h1*l[1][i];}
2082                }
2083                cA=diff(h1,@B);
2084                cB=diff(h1,@A);
2085              }
2086              if ((cA!=0) and (cB!=0) and (jet(cA,0)==cA) and (jet(cB,0)==cB))
2087              {
2088                t=1;
2089                alpha=1;
2090                while((t) and (alpha<=ncols(a1)))
2091                {
2092                  h=cA*w1*a1[alpha]+cB*w2*a2[alpha];
2093                  if (not(reduce(h,PN,1)==0)){t=0;}
2094                  alpha++;
2095                }
2096              }
2097              else{t=0;}
2098              s2++;
2099            }
2100          }
2101          s1++;
2102        }
2103      }
2104      r1++;
2105    }
2106    g++;
2107  }
2108  setring(@R);
2109  ww1=imap(@PAB,w1);
2110  ww2=imap(@PAB,w2);
2111  T=imap(@PAB,PT);
2112  N=imap(@PAB,PN);
2113  cA1=imap(@PAB,cA);
2114  cB1=imap(@PAB,cB);
2115  if (t)
2116  {
2117    G=0;
2118    for (alpha=1;alpha<=ncols(Tm);alpha++)
2119    {
2120      H=cA1*ww1*c1[alpha]+cB1*ww2*c2[alpha];
2121      setring(@PAB);
2122      PH=imap(@R,H);
2123      PN=imap(@R,N);
2124      rP=division(PH,PN);
2125      setring(@R);
2126      r=imap(@PAB,rP);
2127      if (r[2][1]!=0){ERROR("the division is not null and it should be");}
2128      q=r[1];
2129      qT=transpose(matrix(q));
2130      N10=N12;
2131      for (i=size(N1)+1;i<=size(N1)+size(N2);i++){N10[i]=0;}
2132      G=G+(cA1*ww1*c1[alpha]-(matrix(N10)*T*qT)[1,1])*Tm[alpha];
2133    }
2134    //T_ "genimage has found a more generic basis (method 2)";
2135    //T_ "f1:"; f1; "N1:"; N1; "W1:"; W1;
2136    //T_ "f2:"; f2; "N2:"; N2; "W2:"; W2;
2137    //T_ "G:"; G;
2138    GG=ideal(G);
2139  }
2140  else{GG=ideal(0);}
2141  return(GG);
2142}
2143
2144// purpose: given a polynomial f (in the reduced basis)
2145//          the null-conditions ideal N in the segment
2146//          end the set of non-null polynomials common to the segment and
2147//          a new segment,
2148//          to obtain an equivalent polynomial with a leading coefficient
2149//          that is non-null in the second segment.
2150// input:
2151// poly f:    a polynomials of the reduced basis in the segment (N,W)
2152// ideal N:   the null-conditions ideal in the segment
2153// ideal W12: the set of non-null polynomials common to the segment and
2154//            a second segment
2155proc extendpoly(poly f, ideal N, ideal W12)
2156{
2157  int bound=4;
2158  ideal cfs;
2159  ideal cfsn;
2160  ideal ppfs;
2161  poly p=f;
2162  poly fn;
2163  poly lm; poly lc;
2164  int tt=0;
2165  int i;
2166  while (p!=0)
2167  {
2168    lm=leadmonom(p);
2169    lc=leadcoef(p);
2170    cfs[size(cfs)+1]=lc;
2171    ppfs[size(ppfs)+1]=lm;
2172    p=p-lc*lm;
2173  }
2174  def lcf=cfs[1];
2175  int r1=0; int s1;
2176  def RR=basering;
2177  setring @P;
2178  list compos1;
2179  poly w1;
2180  ideal q;
2181  def lcfp=imap(RR,lcf);
2182  def W=imap(RR,W12);
2183  def Np=imap(RR,N);
2184  def cfsp=imap(RR,cfs);
2185  ideal cfspn;
2186  matrix T;
2187  ideal H=lcfp,Np;
2188  def G=liftstd(H,T);
2189  list r;
2190  while ((r1<=bound) and not(tt))
2191  {
2192    compos1=comp(r1,ncols(W));
2193    s1=1;
2194    while ((s1<=size(compos1)) and not(tt))
2195    {
2196      w1=WW(W,compos1[s1]);
2197      cfspn=ideal(0);
2198      cfspn[1]=w1;
2199      tt=1;
2200      i=2;
2201      while ((i<=size(cfsp)) and (tt))
2202      {
2203        r=division(w1*cfsp[i],G);
2204        if (r[2][1]!=0){tt=0;}
2205        else
2206        {
2207          q=r[1];
2208          cfspn[i]=(T*transpose(matrix(q)))[1,1];
2209        }
2210        i++;
2211      }
2212      s1++;
2213    }
2214    r1++;
2215  }
2216  setring RR;
2217  if (tt)
2218  {
2219    cfsn=imap(@P,cfspn);
2220    fn=0;
2221    for (i=1;i<=size(ppfs);i++)
2222    {
2223      fn=fn+cfsn[i]*ppfs[i];
2224    }
2225  }
2226  else{fn=0;}
2227  return(fn);
2228}
2229
2230// nonnull
2231// ring @P (or @R)
2232// input:
2233//   poly f
2234//   ideal N
2235//   ideal W
2236// output:
2237//   1 if f is nonnull in the segment (N,W)
2238//   0 if it can be zero
2239proc nonnull(poly f, ideal N, ideal W)
2240{
2241  int tt;
2242  ideal N0=N;
2243  N0[size(N0)+1]=f;
2244  poly h=1;
2245  int i;
2246  for (i=1;i<=size(W);i++){h=h*W[i];}
2247  def RR=basering;
2248  setring(@P);
2249  list Px=ringlist(@P);
2250  list v="@C";
2251  Px[2]=Px[2]+v;
2252  def npx=size(Px[3][1][2]);
2253  Px[3][1][1]="dp";
2254  Px[3][1][2]=1:(npx+size(v));
2255  def @PC=ring(Px);
2256  setring(@PC);
2257  def N1=imap(RR,N0);
2258  def h1=imap(RR,h);
2259  ideal G=1-@C*h1;
2260  G=G+N1;
2261  option(redSB);
2262  ideal G1=groebner(G);
2263  if (G1[1]==1){tt=1;} else{tt=0;}
2264  setring(RR);
2265  return(tt);
2266}
2267
2268// decide
2269// input:
2270//   given two corresponding polynomials g1 and g2 with the same lpp
2271//   g1 belonging to the basis in the segment N1,W1
2272//   g2 belonging to the basis in the segment N2,W2
2273// output:
2274//   an ideal (with a single polynomial of more if a sheaf is needed)
2275//   that specializes well on both segments to g1 and g2 respectivelly.
2276//   If ideal(0) is output, then no such polynomial nor sheaf exists.
2277proc decide(poly g1, ideal N1, ideal W1, poly g2, ideal N2, ideal W2)
2278{
2279  poly S;
2280  poly S1;
2281  poly S2;
2282  S=leadcoef(g2)*g1-leadcoef(g1)*g2;
2283  def RR=basering;
2284  setring(@RP);
2285  def SR=imap(RR,S);
2286  def N1R=imap(RR,N1);
2287  def N2R=imap(RR,N2);
2288  attrib(N1R,"isSB",1);
2289  attrib(N2R,"isSB",1);
2290  poly S1R=reduce(SR,N1R);
2291  poly S2R=reduce(SR,N2R);
2292  setring(RR);
2293  S1=imap(@RP,S1R);
2294  S2=imap(@RP,S2R);
2295  if ((S2==0) and (nonnull(leadcoef(g1),N2,W2))){return(ideal(g1));}
2296  if ((S1==0) and (nonnull(leadcoef(g2),N1,W1))){return(ideal(g2));}
2297  if ((S1==0) and (S2==0))
2298  {
2299    //T_ "A sheaf has been found (method 1)";
2300    return(ideal(g1,g2));
2301  }
2302  return(ideal(genimage(g1,N1,W1,g2,N2,W2)));
2303}
2304
2305// input:  the tree (list) from buildtree output
2306// output: the list of terminal vertices.
2307proc finalcases(list T)
2308"USAGE:   finalcases(T);
2309          T is the list provided by buildtree
2310RETURN:   A list with the CGS determined by buildtree.
2311          Each element of the list represents one segment
2312          of the buildtree CGS.
2313          The list elements have the following structure:
2314           [1]: label (an intvec(1,0,..)) that indicates the position
2315                in the buildtree but that is irrelevant for the CGS
2316           [2]: 1 (integer) it is also irrelevant and indicates
2317                that this was a terminal vertex in buildtree.
2318           [3]: the reduced basis of the segment.
2319           [4], [5], [6]: the red-spec of the null and non-null conditions
2320                of the segment.
2321                [4] is the null-conditions radical ideal N,
2322                [5] is the non-null polynomials set (ideal) W,
2323                [6] is the set of prime components (ideals) of N.
2324           [7]: is the set of lpp
2325           [8]: poly 1 (irrelevant) is the condition to branch (but no
2326                more branch is necessary in the discussion, so 1 is the result.
2327NOTE:     It can be called having as argument the list output by buildtree
2328KEYWORDS: buildtree, buildtreetoMaple, CGS
2329EXAMPLE:  finalcases; shows an example"
2330{
2331  int i;
2332  list L;
2333  for (i=1;i<=size(T);i++)
2334  {
2335    if (T[i][2])
2336    {L[size(L)+1]=T[i];}
2337  }
2338  return(L);
2339}
2340example
2341{ "EXAMPLE:"; echo = 2;
2342  ring R=(0,a1,a2,a3,a4),(x1,x2,x3,x4),dp;
2343  ideal F=x4-a4+a2, x1+x2+x3+x4-a1-a3-a4, x1*x3*x4-a1*a3*a4, x1*x3+x1*x4+x2*x3+x3*x4-a1*a4-a1*a3-a3*a4;
2344  def T=buildtree(F);
2345  finalcases(T);
2346}
2347
2348// input:  the list of terminal vertices of buildtree (output of finalcases)
2349// output: the same terminal vertices grouped by lpp
2350proc groupsegments(list T)
2351{
2352  int i;
2353  list L;
2354  list lpp;
2355  list lp;
2356  list ls;
2357  int n=size(T);
2358  lpp[1]=T[n][7];
2359  L[1]=list(lpp[1],list(list(T[n][1],T[n][3],T[n][4],T[n][5],T[n][6])));
2360  if (n>1)
2361  {
2362    for (i=1;i<=size(T)-1;i++)
2363    {
2364      lp=memberpos(T[n-i][7],lpp);
2365      if(lp[1]==1)
2366      {
2367        ls=L[lp[2]][2];
2368        ls[size(ls)+1]=list(T[n-i][1],T[n-i][3],T[n-i][4],T[n-i][5],T[n-i][6]);
2369        L[lp[2]][2]=ls;
2370      }
2371      else
2372      {
2373        lpp[size(lpp)+1]=T[n-i][7];
2374        L[size(L)+1]=list(T[n-i][7],list(list(T[n-i][1],T[n-i][3],T[n-i][4],T[n-i][5],T[n-i][6])));
2375      }
2376    }
2377  }
2378  return(L);
2379}
2380
2381// eliminates repeated elements form an ideal
2382proc elimrepeated(ideal F)
2383{
2384  int i;
2385  int j;
2386  ideal FF;
2387  FF[1]=F[1];
2388  for (i=2;i<=ncols(F);i++)
2389  {
2390    if (not(memberpos(F[i],FF)[1]))
2391    {
2392      FF[size(FF)+1]=F[i];
2393    }
2394  }
2395  return(FF);
2396}
2397
2398
2399// decide F is the same as decide but allows as first element a sheaf F
2400proc decideF(ideal F,ideal N,ideal W, poly f2, ideal N2, ideal W2)
2401{
2402  int i;
2403  ideal G=F;
2404  ideal g;
2405  if (ncols(F)==1) {return(decide(F[1],N,W,f2,N2,W2));}
2406  for (i=1;i<=ncols(F);i++)
2407  {
2408    G=G+decide(F[i],N,W,f2,N2,W2);
2409  }
2410  return(elimrepeated(G));
2411}
2412
2413// newredspec
2414// input:  two redspec in the form of N,W and Nj,Wj
2415// output: a redspec representing the minimal redspec segment that contains
2416//         both input segments.
2417proc newredspec(ideal N,ideal W, ideal Nj, ideal Wj)
2418{
2419  ideal nN;
2420  ideal nW;
2421  int u;
2422  def RR=basering;
2423  setring(@P);
2424  list r;
2425  def Np=imap(RR,N);
2426  def Wp=imap(RR,W);
2427  def Njp=imap(RR,Nj);
2428  def Wjp=imap(RR,Wj);
2429  Np=intersect(Np,Njp);
2430  ideal WR;
2431  for(u=1;u<=size(Wjp);u++)
2432  {
2433    if(nonnull(Wjp[u],Np,Wp)){WR[size(WR)+1]=Wjp[u];}
2434  }
2435  for(u=1;u<=size(Wp);u++)
2436  {
2437    if((not(memberpos(Wp[u],WR)[1])) and (nonnull(Wp[u],Njp,Wjp)))
2438    {
2439      WR[size(WR)+1]=Wp[u];
2440    }
2441  }
2442  r=redspec(Np,WR);
2443  option(redSB);
2444  Np=groebner(r[1]);
2445  Wp=r[2];
2446  setring(RR);
2447  nN=imap(@P,Np);
2448  nW=imap(@P,Wp);
2449  return(list(nN,nW));
2450}
2451
2452// selectcases
2453// input:
2454//   list bT: the list output by buildtree.
2455// output:
2456//   list L   it contins the list of segments allowing a common
2457//            reduced basis. The elements of L are of the form
2458//            list (lpp,B,list(list(N,W,L),..list(N,W,L)) )
2459proc selectcases(list bT)
2460{
2461  list T=groupsegments(finalcases(bT));
2462  list T0=bT[1];
2463             // first element of the list of buildtree
2464  list TT0;
2465  TT0[1]=list(T0[7],T0[3],list(list(T0[4],T0[5],T0[6])));
2466             // first element of the output of selectcases
2467  list T1=T; // the initial list; it is only actualized (split)
2468             // when a segment is completly revised (all split are
2469             // already be considered);
2470             // ( (lpp, ((lab,B,N,W,L),.. ()) ), .. (..) )
2471  list TT;   // the output list ( (lpp,B,((N,W,L),..()) ),.. (..) )
2472  // case i
2473  list S1;   // the segments in case i T1[i][2]; ( (lab,B,N,W,L),..() )
2474  list S2;   // the segments in case i that are being summarized in
2475             // actual segment ( (N,W,L),..() )
2476  list S3;   // the segments in case i that cannot be summarized in
2477             // the actual case. When the case is finished a new case
2478             // is created with them ( (lab,B,N,W,L),..() )
2479  list s3;   // list of integers s whose segment cannot be summarized
2480             // in the actual case
2481  ideal lpp; // the summarized lpp (can contain repetitions)
2482  ideal lppi;// in proecess of sumarizing lpp (can contain repetitions)
2483  ideal B;   // the summarized B (can contain polynomials with
2484             // the same lpp (sheaves))
2485  ideal Bi;  // in process of summarizing B (can contain polynomials with
2486             // the same lpp (sheaves))
2487  ideal N;   // the summarized N
2488  ideal W;   // the summarized W
2489  ideal F;   // the summarized polynomial j (can contain a sheaf instead of
2490             // a single poly)
2491  ideal FF;  // the same as F but it can be ideal(0)
2492  poly lpj;
2493  poly fj;
2494  ideal Nj;
2495  ideal Wj;
2496  ideal G;
2497  int i;     // the index of the case i in T1;
2498  int j;     // the index of the polynomial j of the basis
2499  int s;     // the index of the segment s in S1;
2500  int u;
2501  int tests; // true if al the polynomial in segment s have been generalized;
2502  list r;
2503  // initializing the new list
2504  i=1;
2505  while(i<=size(T1))
2506  {
2507    S1=T1[i][2]; // ((lab,B,N,W,L)..) of the segments in case i
2508    if (size(S1)==1)
2509    {
2510      TT[i]=list(T1[i][1],S1[1][2],list(list(S1[1][3],S1[1][4],S1[1][5])));
2511    }
2512    else
2513    {
2514      S2=list();
2515      S3=list(); // ((lab,B,N,W,L)..) of the segments in case i to
2516                 // create another segment i+1
2517      s3=list();
2518      B=S1[1][2];
2519      Bi=ideal(0);
2520      lpp=T1[i][1];
2521      j=1;
2522      tests=1;
2523      while (j<=size(S1[1][2]))
2524      { // j desings the new j-th polynomial
2525        N=S1[1][3];
2526        W=S1[1][4];
2527        F=ideal(S1[1][2][j]);
2528        s=2;
2529        while (s<=size(S1) and not(memberpos(s,s3)[1]))
2530        { // s desings the new segment s
2531          fj=S1[s][2][j];
2532          Nj=S1[s][3];
2533          Wj=S1[s][4];
2534          FF=decideF(F,N,W,fj,Nj,Wj);
2535          if (FF[1]==0)
2536          {
2537            if (@ish)
2538            {
2539              "Warning: Dealing with an homogeneous ideal";
2540              "mrcgs was not able to summarize all lpp cases into a single segment";
2541              "Please send a mail with your Problem to antonio.montes@upc.edu";
2542              "You found a counterexample of the complete success of the actual mrcgs algorithm";
2543              //"T_"; "f1:"; F; "N1:"; N; "W1:"; W; "f2:"; fj; "N2:"; Nj; "W2:"; Wj;
2544            }
2545            S3[size(S3)+1]=S1[s];
2546            s3[size(s3)+1]=s;
2547            tests=0;
2548          }
2549          else
2550          {
2551            F=FF;
2552            lpj=leadmonom(fj);
2553            r=newredspec(N,W,Nj,Wj);
2554            N=r[1];
2555            W=r[2];
2556          }
2557          s++;
2558        }
2559        if (Bi[1]==0){Bi=FF;}
2560        else
2561        {
2562          Bi=Bi+FF;
2563        }
2564        j++;
2565      }
2566      if (tests)
2567      {
2568        B=Bi;
2569        lpp=ideal(0);
2570        for (u=1;u<=size(B);u++){lpp[u]=leadmonom(B[u]);}
2571      }
2572      for (s=1;s<=size(T1[i][2]);s++)
2573      {
2574        if (not(memberpos(s,s3)[1]))
2575        {
2576          S2[size(S2)+1]=list(S1[s][3],S1[s][4],S1[s][5]);
2577        }
2578      }
2579      TT[i]=list(lpp,B,S2);
2580      // for (s=1;s<=size(s3);s++){S1=delete(S1,s);}
2581      T1[i][2]=S2;
2582      if (size(S3)>0){T1=insert(T1,list(T1[i][1],S3),i);}
2583    }
2584    i++;
2585  }
2586  for (i=1;i<=size(TT);i++){TT0[i+1]=TT[i];}
2587  return(TT0);
2588}
2589
2590//*****************End of Selectcases**************************
2591
2592//*****************Begin of CanTree****************************
2593
2594// equalideals
2595// input: 2 ideals F and G;
2596// output: 1 if they are identical (the same polynomials in the same order)
2597//         0 else
2598proc equalideals(ideal F, ideal G)
2599{
2600  int i=1; int t=1;
2601  if (size(F)!=size(G)){return(0);}
2602  while ((i<=size(F)) and (t))
2603  {
2604    if (F[i]!=G[i]){t=0;}
2605    i++;
2606  }
2607  return(t);
2608}
2609
2610// delintvec
2611// input: intvec V
2612//        int i
2613// output:
2614//        intvec W (equal to V but the coordinate i is deleted
2615proc delintvec(intvec V, int i)
2616{
2617  int j;
2618  intvec W;
2619  for (j=1;j<i;j++){W[j]=V[j];}
2620  for (j=i+1;j<=size(V);j++){W[j-1]=V[j];}
2621  return(W);
2622}
2623
2624// redtocanspec
2625// Computes the canonical specification of a redspec (N,W,L).
2626// input:
2627//    ideal N (null conditions, must be radical)
2628//    ideal W (non-null conditions ideal)
2629//    list L  must contain the radical decomposition of N.
2630// output:
2631//    the list of elements of the (ideal N1,list(ideal M11,..,ideal M1k))
2632//    determining the canonical specification of the difference of
2633//    V(N) \ V(h), where h=prod(w in W).
2634proc redtocanspec(intvec lab, int child, list rs)
2635{
2636  ideal N=rs[1]; ideal W=rs[2]; list L=rs[3];
2637  intvec labi; intvec labij;
2638  int childi;
2639  int i; int j; list L0;
2640  L0[1]=list(lab,size(L));
2641  if (W[1]==0)
2642  {
2643    for (i=1;i<=size(L);i++)
2644    {
2645      labi=lab,child+i;
2646      L0[size(L0)+1]=list(labi,1,L[i]);
2647      labij=labi,1;
2648      L0[size(L0)+1]=list(labij,0,ideal(1));
2649    }
2650    return(L0);
2651  }
2652  if (N[1]==1)
2653  {
2654    L0[1]=list(lab,1);
2655    labi=lab,child+1;
2656    L0[size(L0)+1]=list(labi,1,ideal(1));
2657    labij=labi,1;
2658    L0[size(L0)+1]=list(labij,0,ideal(1));
2659  }
2660  def RR=basering;
2661  setring(@P);
2662  ideal Np=imap(RR,N);
2663  ideal Wp=imap(RR,W);
2664  poly h=1;
2665  for (i=1;i<=size(Wp);i++){h=h*Wp[i];}
2666  list Lp=imap(RR,L);
2667  list r; list Ti; list LL;
2668  LL[1]=list(lab,size(Lp));
2669  for (i=1;i<=size(Lp);i++)
2670  {
2671    Ti=minAssGTZ(Lp[i]+h);
2672    for(j=1;j<=size(Ti);j++)
2673    {
2674      option(redSB);
2675      Ti[j]=groebner(Ti[j]);
2676    }
2677    labi=lab,child+i;
2678    childi=size(Ti);
2679    LL[size(LL)+1]=list(labi,childi,Lp[i]);
2680    for (j=1;j<=childi;j++)
2681    {
2682      labij=labi,j;
2683      LL[size(LL)+1]=list(labij,0,Ti[j]);
2684    }
2685  }
2686  LL[1]=list(lab,size(Lp));
2687  setring(RR);
2688  return(imap(@P,LL));
2689}
2690
2691// difftocanspec
2692// Computes the canonical specification of a diffspec V(N) \ V(M)
2693// input:
2694//    intvec lab: label where to hang the canspec
2695//    list  N ideal of null conditions.
2696//    ideal M ideal of the variety to be substacted
2697// output:
2698//    the list of elements determining the canonical specification of
2699//    the difference  V(N) \ V(M):
2700//      ( (intvec(i),children), ...(lab, children, prime ideal),...)
2701proc difftocanspec(intvec lab, int child, ideal N, ideal M)
2702{
2703  int i; int j; list LLL;
2704  def RR=basering;
2705  setring(@P);
2706  ideal Np=imap(RR,N);
2707  ideal Mp=imap(RR,M);
2708  def L=minAssGTZ(Np);
2709  for(j=1;j<=size(L);j++)
2710  {
2711    option(redSB);
2712    L[j]=groebner(L[j]);
2713  }
2714  intvec labi; intvec labij;
2715  int childi;
2716  list LL;
2717  if ((Mp[1]==0) or ((size(L)==1) and (L[1][1]==1)))
2718  {
2719    //LL[1]=list(lab,1);
2720    //labi=lab,1;
2721    //LL[2]=list(labi,1,ideal(1));
2722    //labij=labi,1;
2723    //LL[3]=list(labij,0,ideal(1));
2724    setring(RR);
2725    return(LLL);
2726  }
2727  list r; list Ti;
2728  def k=0;
2729  LL[1]=list(lab,0);
2730  for (i=1;i<=size(L);i++)
2731  {
2732    Ti=minAssGTZ(L[i]+Mp);
2733    for(j=1;j<=size(Ti);j++)
2734    {
2735      option(redSB);
2736      Ti[j]=groebner(Ti[j]);
2737    }
2738    if (not((size(Ti)==1) and (equalideals(L[i],Ti[1]))))
2739    {
2740      k++;
2741      labi=lab,child+k;
2742      childi=size(Ti);
2743      LL[size(LL)+1]=list(labi,childi,L[i]);
2744      for (j=1;j<=childi;j++)
2745      {
2746        labij=labi,j;
2747        LL[size(LL)+1]=list(labij,0,Ti[j]);
2748      }
2749    }
2750    else{setring(RR); return(LLL);}
2751  }
2752  if (size(LL)>0)
2753  {
2754    LL[1]=list(lab,k);
2755    setring(RR);
2756    return(imap(@P,LL));
2757  }
2758  else {setring(RR); return(LLL);}
2759}
2760
2761// tree
2762// purpose: given a label and the list L of vertices of the tree,
2763//          whose content
2764//          are of the form list(intvec lab, int children, ideal P)
2765//          to obtain the vertex and its position
2766// input:
2767//  intvec lab: label of the vertex
2768//  list:  L    the list containing the vertices
2769// output:
2770//  list   V    the vertex list(lab, children, P)
2771proc tree(intvec lab,list L)
2772{
2773  int i=0; int tt=1; list V; intvec labi;
2774  while ((i<size(L)) and (tt))
2775  {
2776    i++;
2777    labi=L[i][1];
2778    if (labi==lab)
2779    {
2780      V=list(L[i],i);
2781      tt=0;
2782    }
2783  }
2784  if (tt==0){return(V);}
2785  else{return(list(list(intvec(0)),0));}
2786}
2787
2788// GCS (generalized canonical specification)
2789// new structure of a GCS
2790
2791// L is a list of vertices V of the GCS.
2792// first vertex=list(intvec lab, int children, ideal lpp, ideal B)
2793// other vertices=list(intvec lab, int children, ideal P)
2794// the individual vertices can be accessed with the function tree
2795// by the call  V=tree(lab,L), that outputs the vertex if it exists
2796// and its position in L, or nothing if it does not exist.
2797// The first element of the list must be the root of the tree and has
2798// label lab=i, and other information.
2799
2800// example:
2801// the canonical specification
2802// V(a^2-ac-ba+c-abc) \ (union( V(b,a), V(c,a), V(b,a-c), V(c,a-b)))
2803// is represented by  the list
2804// L=((intvec(i),children=1,lpp,B),(intvec(i,1),4,ideal(a^2-ac-ba+c-abc)),
2805//    (intvec(i,1,1),0,ideal(b,a)),     (intvec(i,1,2),0,ideal(c,a)),
2806//    (intvec(i,1,3),0,ideal(b,a-c)),   (intvec(i,1,4),0,ideal(c,a-b))
2807//   )
2808// example:
2809// the canonical specification
2810// (V(a)\(union(V(c,a),V(b+c,a),V(b,a)))) union
2811// (V(b)\(union(V(b,a),V(b,a-c))))        union
2812// (V(c)\(union(V(c,a),V(c,a-b))))
2813// is represented by  the list
2814// L=((i,children=3,lpp,B),
2815//    (intvec(i,1),3,ideal(a)),
2816//    (intvec(i,1,1),0,(c,a)),(intvec(i,1,2),0,(b+c,a)),(intvec(i,1,3),0,(b,a)),
2817//    (intvec(i,2),2,ideal(b)),
2818//    (intvec(i,2,1),0,(b,a)),(intvec(i,2,2),0,(b,a-c)),
2819//    (intvec(i,3),2,ideal(c)),
2820//    (intvec(i,3,1),0,(c,a)),(intvec(i,3,2),0,(c,a-b))
2821//   )
2822// If L is the list in the last example, the call
2823// tree(intvec(i,2,1),L) will output   ((intvec(i,2,1),0,(b,a)),7)
2824
2825// GCS
2826// input: list T is supposed to be an element L[i] of selectcases:
2827//        T= list( ideal lpp, ideal B, list(N,W,L),.., list(N,W,L))
2828// output: the list L of vertices being the GCS of the addition of
2829//         all the segments in T.
2830//         list(list(intvec lab, int children, ideal lpp, ideal B),
2831//              list(intvec lab, int children, ideal P),..
2832//         )
2833proc GCS(intvec lab, list case)
2834{
2835  int i; int ii; int t;
2836  list @L;
2837  @L[1]=list(lab,0,case[1],case[2]);
2838  exportto(Top,@L);
2839  int j;
2840  list u; intvec labu; int childu;
2841  list v; intvec labv; int childv;
2842  list T=case[3];
2843  for (j=1;j<=size(T);j++)
2844  {
2845    t=addcase(lab,T[j]);
2846    deletebrotherscontaining(lab);
2847  }
2848  relabelingindices(lab,lab);
2849  list L=@L;
2850  kill @L;
2851  return(L);
2852}
2853
2854// sorbylab:
2855// pupose: given the list of mrcgs to order is by increasing label
2856proc sortbylab(list L)
2857{
2858  int n=L[1][2];
2859  int i; int j;
2860  list H=L;
2861  list LL;
2862  list L1;
2863  //LL[1]=L[1];
2864  //H=delete(H,1);
2865  while (size(H)!=0)
2866  {
2867    j=1;
2868    L1=H[1];
2869    for (i=1;i<=size(H);i++)
2870    {
2871      if(lesslab(H[i],L1)){j=i;L1=H[j];}
2872    }
2873    LL[size(LL)+1]=L1;
2874    H=delete(H,j);
2875  }
2876  return(LL);
2877}
2878
2879// lesslab
2880// purpose: given two elements of the list of mrcgs it
2881// returns 1 if the label of the first is less than that of the second
2882proc lesslab(list l1, list l2)
2883{
2884  intvec lab1=l1[1];
2885  intvec lab2=l2[1];
2886  int n1=size(lab1);
2887  int n2=size(lab2);
2888  int n=n1;
2889  if (n2<n1){n=n2;}
2890  int tt=0;
2891  int j=1;
2892  while ((lab1[j]==lab2[j]) and (j<n)){j++;}
2893  if (lab1[j]<lab2[j]){tt=1;}
2894  if ((j==n) and (lab1[j]==lab2[j]) and (n2>n1)){tt=1;}
2895  return(tt);
2896}
2897
2898// cantree
2899// input:  the list provided by selectcases
2900// output: the list providing the canonicaltree
2901proc cantree(list S)
2902{
2903  string method=" ";
2904  list T0=S[1];
2905    // first element of the list of selectcases
2906  int i; int j;
2907  list L;
2908  list T;
2909  L[1]=list(intvec(0),size(S)-1,T0[1],T0[2],T0[3][1],method);
2910  for (i=2;i<=size(S);i++)
2911  {
2912    T=GCS(intvec(i-1),S[i]);
2913    T=sortbylab(T);
2914    for (j=1;j<=size(T);j++)
2915    {L[size(L)+1]=T[j];}
2916  }
2917  return(L);
2918}
2919
2920// addcase
2921// recursive routine that adds to the list @L, (an alredy GCS)
2922// a new redspec rs=(N,W,L);
2923// and returns the test t whose value is
2924// 0 if the new canspec is not to be hung to the fathers vertex,
2925// 1 if yes.
2926proc addcase(intvec labu, list rs)
2927{
2928  int i; int j; int childu; ideal Pu;
2929  list T; int nchildu;
2930  def N=rs[1]; def W=rs[2]; def PN=rs[3];
2931  ideal NN; ideal MM;
2932  int tt=1;
2933  poly h=1; for (i=1;i<=size(W);i++){h=h*W[i];}
2934  list u=tree(labu,@L); childu=u[1][2];
2935  list v; intvec labv; int childv; list w; intvec labw;
2936  if (childu>0)
2937  {
2938    v=firstchild(u[1][1]);
2939    while(v[2][1]!=0)
2940    {
2941      labv=v[1][1];
2942      w=firstchild(labv);
2943      while(w[2][1]!=0)
2944      {
2945        labw=w[1][1];
2946        if(addcase(labw,rs)==0)
2947        {tt=0;}
2948        w=nextbrother(labw);
2949      }
2950      u=tree(labu,@L);
2951      childu=u[1][2];
2952      v=nextbrother(v[1][1]);
2953    }
2954    deletebrotherscontaining(labu);
2955    relabelingindices(labu,labu);
2956  }
2957  if (tt==1)
2958  {
2959    u=tree(labu,@L);
2960    nchildu=lastchildrenindex(labu);
2961    if (size(labu)==1)
2962    {
2963      T=redtocanspec(labu,nchildu,rs);
2964      tt=0;
2965    }
2966    else
2967    {
2968      NN=N;
2969      if (containedP(u[1][3],N)){tt=0;}
2970      for (i=1;i<=size(u[1][3]);i++)
2971      {
2972        NN[size(NN)+1]=u[1][3][i];
2973      }
2974      MM=NN;
2975      MM[size(MM)+1]=h;
2976      T=difftocanspec(labu,nchildu,NN,MM);
2977    }
2978    if (size(T)>0)
2979    {
2980      @L[u[2]][2]=@L[u[2]][2]+T[1][2];
2981      for (i=2;i<=size(T);i++){@L[size(@L)+1]=T[i];}
2982      if (size(labu)>1)
2983      {
2984        simplifynewadded(labu);
2985      }
2986    }
2987    else{tt=1;}
2988  }
2989  return(tt);
2990}
2991
2992// reduceR
2993// reduces the polynomial f w.r.t. N, in the ring @P
2994proc reduceR(poly f, ideal N)
2995{
2996  def RR=basering;
2997  setring(@P);
2998  def fP=imap(RR,f);
2999  def NP=imap(RR,N);
3000  attrib(NP,"isSB",1);
3001  def rp=reduce(fP,NP);
3002  setring(RR);
3003  return(imap(@P,rp));
3004}
3005
3006// containedP
3007// returns 1 if ideal Pu is contained in ideal Pv
3008// returns 0 if not
3009// in ring @P
3010proc containedP(ideal Pu,ideal Pv)
3011{
3012  int t=1;
3013  int n=size(Pu);
3014  int i=0;
3015  poly r=0;
3016  while ((t) and (i<n))
3017  {
3018    i++;
3019    r=reduceR(Pu[i],Pv);
3020    if (r!=0){t=0;}
3021  }
3022  return(t);
3023}
3024
3025// simplifynewadded
3026// auxiliary routine of addcase
3027// when a new redspec is added to a non terminal vertex,
3028// it is applied to simplify the addition.
3029// When Pu==Pv, the children of w are hung from u fathers
3030// and deleted the whole new addition.
3031// Finally, deletebrotherscontaining is applied to u fathers
3032// in order to eliminate branches contained.
3033proc simplifynewadded(intvec labu)
3034{
3035  int t; int ii; int k; int kk; int j;
3036  intvec labfu=delintvec(labu,size(labu)); list fu; int childfu;
3037  list u=tree(labu,@L); int childu=u[1][2]; ideal Pu=u[1][3];
3038  list v; intvec labv; int childv; ideal Pv;
3039  list w; intvec labw; intvec nlab; list ww;
3040  if (childu>0)
3041  {
3042    v=firstchild(u[1][1]); labv=v[1][1]; childv=v[1][2]; Pv=v[1][3];
3043    ii=0;
3044    t=0;
3045    while ((not(t)) and (ii<childu))
3046    {
3047      ii++;
3048      if (equalideals(Pu,Pv))
3049      {
3050        fu=tree(labfu,@L);
3051        childfu=fu[1][2];
3052        j=lastchildrenindex(fu[1][1])+1;
3053        k=0;
3054        w=firstchild(v[1][1]);
3055        childv=v[1][2];
3056        for (kk=1;kk<=childv;kk++)
3057        {
3058          if (kk<childv){ww=nextbrother(w[1][1]);}
3059          nlab=labfu,j;
3060          @L[w[2]][1]=nlab;
3061          j++;
3062          if (kk<childv){w=ww;}
3063        }
3064        childfu=fu[1][2]+childv-1;
3065        @L[fu[2]][2]=childfu;
3066        @L[v[2]][2]=0;
3067        t=1;
3068        deleteverts(labu);
3069      }
3070    }
3071  }
3072  deletebrotherscontaining(labfu);
3073}
3074
3075// given the label labfu of the vertex fu it returns the last
3076// int of the label of the last existing children.
3077// if no child exists, then it ouputs 0.
3078proc lastchildrenindex(intvec labfu)
3079{
3080  int i;
3081  int lastlabi; intvec labi; intvec labfi;
3082  int lastlab=0;
3083  for (i=1;i<=size(@L);i++)
3084  {
3085    labi=@L[i][1];
3086    if (size(labi)>1)
3087    {
3088      labfi=delintvec(labi,size(labi));
3089      if (labfu==labfi)
3090      {
3091        lastlabi=labi[size(labi)];
3092        if (lastlab<lastlabi)
3093        {
3094          lastlab=lastlabi;
3095        }
3096      }
3097    }
3098  }
3099  return(lastlab);
3100}
3101
3102// given the vertex u it provides the next brother of u.
3103// if it does not exist, then it ouputs v=list(list(intvec(0)),0)
3104proc nextbrother(intvec labu)
3105{
3106  list L; int i; int j; list next;
3107  int lastlabu=labu[size(labu)];
3108  intvec labfu=delintvec(labu,size(labu));
3109  int lastlabi; intvec labi; intvec labfi;
3110  for (i=1;i<=size(@L);i++)
3111  {
3112    labi=@L[i][1];
3113    if (size(labi)>1)
3114    {
3115      labfi=delintvec(labi,size(labi));
3116      if (labfu==labfi)
3117      {
3118        lastlabi=labi[size(labi)];
3119        if (lastlabu<lastlabi)
3120        {L[size(L)+1]=list(lastlabi,list(@L[i],i));}
3121      }
3122    }
3123  }
3124  if (size(L)==0){return(list(intvec(0),0));}
3125  next=L[1];
3126  for (i=2;i<=size(L);i++)
3127  {
3128    if (L[i][1]<next[1]){next=L[i];}
3129  }
3130  return(next[2]);
3131}
3132
3133// gives the first child of vertex fu
3134proc firstchild(labfu)
3135{
3136  intvec labfu0=labfu;
3137  labfu0[size(labfu0)+1]=0;
3138  return(nextbrother(labfu0));
3139}
3140
3141// purpose: eliminate the children vertices of fu and all its descendents
3142// whose prime ideal Pu contains a prime ideal Pv of some brother vertex w.
3143proc deletebrotherscontaining(intvec labfu)
3144{
3145  int i; int t;
3146  list fu=tree(labfu,@L);
3147  int childfu=fu[1][2];
3148  list u; intvec labu; ideal Pu;
3149  list v; intvec labv; ideal Pv;
3150  u=firstchild(labfu);
3151  for (i=1;i<=childfu;i++)
3152  {
3153    labu=u[1][1];
3154    Pu=u[1][3];
3155    v=firstchild(fu[1][1]);
3156    t=1;
3157    while ((t) and (v[2]!=0))
3158    {
3159      labv=v[1][1];
3160      Pv=v[1][3];
3161      if (labu!=labv)
3162      {
3163        if (containedP(Pv,Pu))
3164        {
3165          deleteverts(labu);
3166          fu=tree(labfu,@L);
3167          @L[fu[2]][2]=fu[1][2]-1;
3168          t=0;
3169        }
3170      }
3171      if (t!=0)
3172      {
3173        v=nextbrother(v[1][1]);
3174      }
3175    }
3176    if (i<childfu)
3177    {
3178      u=nextbrother(u[1][1]);
3179    }
3180  }
3181}
3182
3183// purpose: delete all descendent vertices from u included u
3184// from the list @L.
3185// It must be noted that after the operation, the number of children
3186// in fathers vertex must be decreased in 1 unitity. This operation is not
3187// performed inside this recursive routine.
3188proc deleteverts(intvec labu)
3189{
3190  int i; int ii; list v; intvec labv;
3191  list u=tree(labu,@L);
3192  int childu=u[1][2];
3193  @L=delete(@L,u[2]);
3194  if (childu>0)
3195  {
3196    v=firstchild(labu);
3197    labv=v[1][1];
3198    for (ii=1;ii<=childu;ii++)
3199    {
3200      deleteverts(labv);
3201      if (ii<childu)
3202      {
3203        v=nextbrother(v[1][1]);
3204        labv=v[1][1];
3205      }
3206    }
3207  }
3208}
3209
3210// purpose: starting from vertex olab (initially nlab=olab)
3211// relabels the vertices of @L to be consecutive
3212proc relabelingindices(intvec olab, intvec nlab)
3213{
3214  int i;
3215  intvec nlabi; intvec labv;
3216  list u=tree(olab,@L);
3217  int childu=u[1][2];
3218  list v;
3219  if (childu==0){@L[u[2]][1]=nlab;}
3220  else
3221  {
3222    v=firstchild(u[1][1]);
3223    @L[u[2]][1]=nlab;
3224    i=1;
3225    while(v[2]!=0)
3226    {
3227      labv=v[1][1];
3228      nlabi=nlab,i;
3229      relabelingindices(labv,nlabi);
3230      v=nextbrother(labv);
3231      i++;
3232    }
3233  }
3234}
3235
3236// mrcgs
3237// fundamental routine giving the
3238// "Minimal Reduced Comprehensive Groebner System"
3239// input: F = ideal in ring R=K[a][x]
3240// output: a list L representing the tree of the mrcgs.
3241proc mrcgs(ideal F, list #)
3242"USAGE:   mrcgs(F);
3243          F is the ideal from which to obtain the Minimal Reduced CGS.
3244          Alternatively, as option:
3245          mrcgs(F,L);
3246          where L is a list of the null conditions ideal N, and W the set of
3247          non-null polynomials (ideal). If this option is set, the ideals N and W
3248          must depend only on the parameters and the parameter space is
3249          reduced to V(N) \ V(h), where h=prod(w), for w in W.
3250          A reduced specification of (N,W) will be computed and used to
3251          restrict the parameter-space. The output will omit the known restrictions
3252          given as option.
3253RETURN:   The list representing the Minimal Reduced CGS.
3254          The description given here is identical for rcgs and crcgs.
3255          The elements of the list T computed by mrcgs are lists representing
3256          a rooted tree.
3257          Each element has as the two first entries with the following content:@*
3258           [1]: The label (intvec) representing the position in the rooted
3259                tree:  0 for the root (and this is a special element)
3260                       i for the root of the segment i
3261                       (i,...) for the children of the segment i
3262           [2]: the number of children (int) of the vertex.
3263          There thus three kind of vertices:
3264           1) the root (first element labelled 0),
3265           2) the vertices labelled with a single integer i,
3266           3) the rest of vertices labelled with more indices.
3267          Description of the root. Vertex type 1)
3268           There is a special vertex (the first one) whose content is
3269           the following:
3270             [3] lpp of the given ideal
3271             [4] the given ideal
3272             [5] the red-spec of the (optional) given null and non-null conditions
3273                 (see redspec for the description)
3274             [6] MRCGS (to remember which algorithm has been used). If the
3275                 algorithm used is rcgs of crcgs then this will be stated
3276                 at this vertex (RCGS or CRCGS).
3277           Description of vertices type 2). These are the vertices that
3278           initiate a segment, and are labelled with a single integer.
3279             [3] lpp (ideal) of the reduced basis. If they are repeated lpp's this
3280                 will correspond to a sheaf.
3281             [4] the reduced basis (ideal) of the segment.
3282           Description of vertices type 3). These vertices have as first
3283           label i and descend form vertex i in the position of the label
3284           (i,...). They contain moreover a unique prime ideal in the parameters
3285           and form ascending chains of ideals.
3286          How is to be read the mrcgs tree? The vertices with an even number of
3287          integers in the label are to be considered as additive and those
3288          with an odd number of integers in the label are to be considered as
3289          substraction. As an example consider the following vertices:
3290          v1=((i),2,lpp,B),
3291          v2=((i,1),2,P_{(i,1)}),
3292          v3=((i,1,1),2,P_{(i,1,1)},
3293          v4=((i,1,1,1),1,P_{(i,1,1,1)},
3294          v5=((i,1,1,1,1),0,P_{(i,1,1,1,1)},
3295          v6=((i,1,1,2),1,P_{(i,1,1,2)},
3296          v7=((i,1,1,2,1),0,P_{(i,1,1,2,1)},
3297          v8=((i,1,2),0,P_{(i,1,2)},
3298          v9=((i,2),1,P_{(i,2)},
3299          v10=((i,2,1),0,P_{(i,2,1)},
3300          They represent the segment:
3301          (V(i,1)\(((V(i,1,1) \ ((V(i,1,1,1) \ V(i,1,1,1,1)) u (V(i,1,1,2) \ V(i,1,1,2,1)))))
3302          u V(i,1,2)) u (V(i,2) \ V(i,2,1))
3303          and can also be represented by
3304          (V(i,1) \ (V(i,1,1) u V(i,1,2))) u
3305          (V(i,1,1,1) \ V(i,1,1,1)) u
3306          (V(i,1,1,2) \ V(i,1,1,2,1)) u
3307          (V(i,2) \ V(i,2,1))
3308          where V(i,j,..) = V(P_{(i,j,..)}
3309NOTE:     There are three fundamental routines in the library: mrcgs, rcgs and crcgs.
3310          mrcgs (Minimal Reduced CGS) is an algorithm that packs so much as it
3311          is able to do (using algorithms adhoc) the segments with the same lpp,
3312          obtaining the minimal number of segments. The hypothesis is that this
3313          is also canonical, but for the moment there is no proof of the uniqueness
3314          of that minimal packing. Moreover, the segments that are obtained are not
3315          locally closed, i.e. there are not always the difference of two varieties,
3316          but can be a union of differences.
3317          The output can be visualized using cantreetoMaple, that will
3318          write a file with the content of mrcgs that can be read in Maple
3319          and plotted using the Maple plotcantree routine of the Monte's dpgb library
3320          You can also try the routine cantodiffcgs when the segments are all
3321          difference of two varieties to have a simpler view of the output.
3322          But it will give an error if the output is not locally closed.
3323KEYWORDS: rcgs, crcgs, buildtree, cantreetoMaple, cantodiffcgs
3324EXAMPLE:  mrcgs; shows an example"
3325{
3326  int i=1;
3327  int @ish=1;
3328  exportto(Top,@ish);
3329  while((@ish) and (i<=size(F)))
3330  {
3331    @ish=ishomog(F[i]);
3332    i++;
3333  }
3334  list L=buildtree(F, #);
3335  list S=selectcases(L);
3336  list T=cantree(S);
3337  T[1][6]="MRCGS";
3338  T[1][4]=F;
3339  for (i=1;i<=size(F);i++)
3340  {
3341    T[1][3][i]=leadmonom(F[i]);
3342  }
3343  if (size(#)>0)
3344  {
3345    ideal N=#[1];
3346    ideal W=#[2];
3347    T=reduceconds(T,N,W);
3348  }
3349  kill @ish;
3350  return(T);
3351}
3352example
3353{ "EXAMPLE:"; echo = 2;
3354  ring R=(0,b,c,d,e,f),(x,y),dp;
3355  ideal F=x^2+b*y^2+2*c*x*y+2*d*x+2*e*y+f, 2*x+2*c*y+2*d, 2*b*y+2*c*x+2*e;
3356  def T=mrcgs(F);
3357  T;
3358  cantreetoMaple(T,"Tm","Tm.txt");
3359  //cantodiffcgs(T); // has non locally closed segments
3360  ring R=(0,a1,a2,a3,a4),(x1,x2,x3,x4),dp;
3361  ideal F2=x4-a4+a2, x1+x2+x3+x4-a1-a3-a4, x1*x3*x4-a1*a3*a4, x1*x3+x1*x4+x2*x3+x3*x4-a1*a4-a1*a3-a3*a4;
3362  def T2=mrcgs(F2);
3363  T2;
3364  cantreetoMaple(T2,"T2m","T2m.txt");
3365  cantodiffcgs(T2);
3366}
3367
3368// reduceconds: when null and nonnull conditions are specified it
3369//              takes the output of cantree and reduces the tree
3370//              assuming the null and nonnull conditions
3371// input: list T (the output of cantree computed with null and nonull conditions
3372//        ideal N: null conditions
3373//        ideal W: non-null conditions
3374// output: the list T assuming the null and non-null conditions
3375proc reduceconds(list T,ideal N,ideal W)
3376{
3377  int i; intvec lab; intvec labfu; list fu; int j; int t;
3378  list @L=T;
3379  exportto(Top,@L);
3380  int n=size(W);
3381  for (i=2;i<=size(@L);i++)
3382  {
3383    t=0; j=0;
3384    while ((not(t)) and (j<n))
3385    {
3386      j++;
3387      if (size(@L[i][1])>1)
3388      {
3389        if (memberpos(W[j],@L[i][3])[1])
3390        {
3391          t=1;
3392          @L[i][3]=ideal(1);
3393        }
3394      }
3395    }
3396  }
3397  for (i=2;i<=size(@L);i++)
3398  {
3399    if (size(@L[i][1])>1)
3400    {
3401      @L[i][3]=delidfromid(N,@L[i][3]);
3402    }
3403  }
3404  for (i=2;i<=size(@L);i++)
3405  {
3406    if ((size(@L[i][1])>1) and (size(@L[i][1]) mod 2==1) and (equalideals(@L[i][3],ideal(0))))
3407    {
3408      lab=@L[i][1];
3409      labfu=delintvec(lab,size(lab));
3410      fu=tree(labfu,@L);
3411      @L[fu[2]][2]=@L[fu[2]][2]-1;
3412      deleteverts(lab);
3413    }
3414  }
3415  for (j=2; j<=size(@L); j++)
3416  {
3417    if (@L[j][2]>0)
3418    {
3419      deletebrotherscontaining(@L[j][1]);
3420    }
3421  }
3422  for (i=1;i<=@L[1][2];i++)
3423  {
3424    relabelingindices(intvec(i),intvec(i));
3425  }
3426  list TT=@L;
3427  kill @L;
3428  return(TT);
3429}
3430
3431//**************End of cantree******************************
3432
3433//**************Begin of CanTreeTo Maple********************
3434
3435// cantreetoMaple
3436// input:  list L: the output of cantree
3437//         string T: the name of the table of Maple that represents L
3438//                   in Maple
3439//         string writefile: the name of the file where the table T
3440//                           is written
3441proc cantreetoMaple(list L, string T, string writefile)
3442"USAGE:   cantreetoMaple(T, TM, writefile);
3443          T: is the list provided by mrcgs or crcgs or crcgs,
3444          TM: is the name (string) of the table variable in Maple that will represent
3445             the output of the fundamental routines,
3446          writefile: is the name (string) of the file where to write the content.
3447RETURN:   writes the list provided by mrcgs or crcgs or crcgs to a file
3448          containing the table representing it in Maple.
3449NOTE:     It can be called from the output of mrcgs or rcgs of crcgs
3450KEYWORDS: mrcgs, rcgs, crcgs, Maple
3451EXAMPLE:  cantreetoMaple; shows an example"
3452{
3453  short=0;
3454  int i;
3455  list L0=L[1];
3456  int numcases=L0[2];
3457  link LLw=":w "+writefile;
3458  string La=string("table(",T,");");
3459  write(LLw, La);
3460  close(LLw);
3461  link LLa=":a "+writefile;
3462  def RL=ringlist(@R);
3463  list p=RL[1][2];
3464  string param=string(p[1]);
3465  if (size(p)>1)
3466  {
3467    for(i=2;i<=size(p);i++){param=string(param,",",p[i]);}
3468  }
3469  list v=RL[2];
3470  string vars=string(v[1]);
3471  if (size(v)>1)
3472  {
3473    for(i=2;i<=size(v);i++){vars=string(vars,",",v[i]);}
3474  }
3475  list xord;
3476  list pord;
3477  if (RL[1][3][1][1]=="dp"){pord=string("tdeg(",param);}
3478  else
3479  {
3480    if (RL[1][3][1][1]=="lp"){pord=string("plex(",param);}
3481  }
3482  if (RL[3][1][1]=="dp"){xord=string("tdeg(",vars);}
3483  else
3484  {
3485    if (RL[3][1][1]=="lp"){xord=string("plex(",vars);}
3486  }
3487  write(LLa,string(T,"[[___xord]]:=",xord,");"));
3488  write(LLa,string(T,"[[___pord]]:=",pord,");"));
3489  //write(LLa,string(T,"[[11]]:=true; "));
3490  list S;
3491  S=string(T,"[[0]]:=",numcases,";");
3492  write(LLa,S);
3493  S=string(T,"[[___method]]:=",L[1][6],";");
3494  // Method L[1][6];
3495  write(LLa,S);
3496  S=string(T,"[[___basis]]:=[",L0[4],"];");
3497  write(LLa,S);
3498  S=string(T,"[[___nullcond]]:=[",L0[5][1],"];");
3499  write(LLa,S);
3500  S=string(T,"[[___notnullcond]]:={",L0[5][2],"};");
3501  write(LLa,S);
3502  for (i=1;i<=numcases;i++)
3503  {
3504    S=ctlppbasis(T,L,intvec(i));
3505    write(LLa,S[1]);
3506    write(LLa,S[2]);
3507    write(LLa,S[3]);
3508    //write(LLa,S[4]);
3509    ctrecwrite(LLa, L, T, intvec(i),S[4]);
3510  }
3511  close(LLa);
3512}
3513example
3514{ "EXAMPLE:"; echo = 2;
3515  ring R=(0,b,c,d,e,f),(x,y),dp;
3516  ideal F=x^2+b*y^2+2*c*x*y+2*d*x+2*e*y+f, 2*x+2*c*y+2*d, 2*b*y+2*c*x+2*e;
3517  def T=mrcgs(F);
3518  T;
3519  cantreetoMaple(T,"Tm","Tm.txt");
3520}
3521
3522// ctlppbasis: auxiliary cantreetoMaple routine
3523// input:
3524//   string T: the name of the table in Maple
3525//   intvec lab: the label of the case
3526//   ideal B: the basis of the case
3527// output:
3528//   the string of T[[lab]] (basis); in Maple
3529proc ctlppbasis(string T, list L, intvec lab)
3530{
3531  list u;
3532  intvec lab0=lab,0;
3533  u=tree(lab,L);
3534  list Li;
3535  Li[1]=string(T,"[[",lab,",___lpp]]:=[",u[1][3],"]; ");
3536  Li[2]=string(T,"[[",lab,"]]:=[",u[1][4],"]; ");
3537  Li[3]=string(T,"[[",lab0,"]]:=",u[1][2],"; ");
3538  Li[4]=u[1][2];
3539  return(Li);
3540}
3541
3542// ctlppbasis: auxiliary cantreetoMaple routine
3543// recursive routine to write all elements
3544proc ctrecwrite(LLa, list L, string T, intvec lab, int n)
3545{
3546  int i;
3547  intvec labi; intvec labi0;
3548  string S;
3549  list u;
3550  for (i=1;i<=n;i++)
3551  {
3552    labi=lab,i;
3553    u=tree(labi,L);
3554    S=string(T,"[[",labi,"]]:=[",u[1][3],"];");
3555    write(LLa,S);
3556    labi0=labi,0;
3557    S=string(T,"[[",labi0,"]]:=",u[1][2],";");
3558    write(LLa,S);
3559    ctrecwrite(LLa, L, T, labi, u[1][2]);
3560  }
3561}
3562
3563//**************End of CanTreeTo Maple********************
3564
3565//**************Begin homogenizing************************
3566
3567// ishomog:
3568// Purpose: test if a polynomial is homogeneous in the variables or not
3569// input:  poly f
3570// output  1 if f is homogeneous, 0 if not
3571proc ishomog(f)
3572{
3573  int i; poly r; int d; int dr;
3574  if (f==0){return(1);}
3575  d=deg(f); dr=d; r=f;
3576  while ((d==dr) and (r!=0))
3577  {
3578    r=r-lead(r);
3579    dr=deg(r);
3580  }
3581  if (r==0){return(1);}
3582  else{return(0);}
3583}
3584
3585proc rcgs(ideal F, list #)
3586"USAGE:   rcgs(F);
3587          F is the ideal from which to obtain the Reduced CGS.
3588          rcgs(F,L);
3589          where L is a list of the null conditions ideal N, and W the set of
3590          non-null polynomials (ideal). If this option is set, the ideals N and W
3591          must depend only on the parameters and the parameter space is
3592          reduced to V(N) \ V(h), where h=prod(w), for w in W.
3593          A reduced specification of (N,W) will be computed and used to
3594          restrict the parameter-space. The output will omit the known restrictions
3595          given as option.
3596RETURN:   The list representing the Reduced CGS.
3597          The description given here is analogous as for mrcgs and crcgs.
3598          The elements of the list T computed by rcgs are lists representing
3599          a rooted tree.
3600          Each element has as the two first entries with the following content:@*
3601           [1]: The label (intvec) representing the position in the rooted
3602                tree:  0 for the root (and this is a special element)
3603                       i for the root of the segment i
3604                       (i,...) for the children of the segment i
3605           [2]: the number of children (int) of the vertex.
3606          There thus three kind of vertices:
3607           1) the root (first element labelled 0),
3608           2) the vertices labelled with a single integer i,
3609           3) the rest of vertices labelled with more indices.
3610          Description of the root. Vertex type 1)
3611           There is a special vertex (the first one) whose content is
3612           the following:
3613             [3] lpp of the given ideal
3614             [4] the given ideal
3615             [5] the red-spec of the (optional) given null and non-null conditions
3616                 (see redspec for the description)
3617             [6] RCGS (to remember which algorithm has been used). If the
3618                 algorithm used is mrcgs or crcgs then this will be stated
3619                 at this vertex (mrcgs or CRCGS).
3620           Description of vertices type 2). These are the vertices that
3621           initiate a segment, and are labelled with a single integer.
3622             [3] lpp (ideal) of the reduced basis. If they are repeated lpp's this
3623                 will correspond to a sheaf.
3624             [4] the reduced basis (ideal) of the segment.
3625           Description of vertices type 3). These vertices have as first
3626           label i and descend form vertex i in the position of the label
3627           (i,...). They contain moreover a unique prime ideal in the parameters
3628           and form ascending chains of ideals.
3629          How is to be read the rcgs tree? The vertices with an even number of
3630          integers in the label are to be considered as additive and those
3631          with an odd number of integers in the label are to be considered as
3632          substraction. As an example consider the following vertices:
3633          v1=((i),2,lpp,B),
3634          v2=((i,1),2,P_{(i,1)}),
3635          v3=((i,1,1),0,P_{(i,1,1)}, v4=((i,1,2),0,P_{(i,1,1)}),
3636          v5=((i,2),2,P_{(i,2)},
3637          v6=((i,2,1),0,P_{(i,2,1)}, v7=((i,2,2),0,P_{(i,2,2)}
3638          They represent the segment:
3639          (V(i,1)\(V(i,1,1) u V(i,1,2))) u
3640          (V(i,2)\(V(i,2,1) u V(i,2,2)))
3641          where V(i,j,..) = V(P_{(i,j,..)}
3642NOTE:     There are three fundamental routines in the library: mrcgs, rcgs and crcgs.
3643          rcgs (Reduced CGS) is an algorithm that first homogenizes the
3644          basis of the given ideal then applies mrcgs and finally de-homogenizes
3645          and reduces the resulting bases. (See the note of mrcgs).
3646          As a result of Wibmer's Theorem, the resulting segments are
3647          locally closed (i.e. difference of varieties). Nevertheless, the
3648          output is not completely canonical as the homogeneous ideal considered
3649          is not the homogenized ideal of the given ideal but only the ideal
3650          obtained by homogenizing the given basis.
3651
3652          The output can be visualized using cantreetoMaple, that will
3653          write a file with the content of mrcgs that can be read in Maple
3654          and plotted using the Maple plotcantree routine of the Monte's dpgb library
3655          You can also use the routine cantodiffcgs as the segments are all
3656          difference of two varieties to have a simpler view of the output.
3657KEYWORDS: rcgs, crcgs, buildtree, cantreetoMaple, cantodiffcgs
3658EXAMPLE:  rcgs; shows an example"
3659{
3660  ideal N;
3661  ideal W;
3662  int j; int i;
3663  poly f;
3664  if (size(#)==2)
3665  {
3666    N=#[1];
3667    W=#[2];
3668  }
3669  i=1; int postred=0;
3670  int ish=1;
3671  while ((ish) and (i<=size(F)))
3672  {
3673    ish=ishomog(F[i]);
3674    i++;
3675  }
3676  if (ish){return(mrcgs(F, #));}
3677  def RR=basering;
3678  list RRL=ringlist(RR);
3679  if (RRL[3][1][1]!="dp"){ERROR("the order must be dp");}
3680  poly @t;
3681  ring H=0,@t,dp;
3682  def RH=RR+H;
3683  setring(RH);
3684  setglobalrings();
3685  def FH=imap(RR,F);
3686  list u; ideal B; ideal lpp; intvec lab;
3687  FH=homog(FH,@t);
3688  def Nh=imap(RR,N);
3689  def Wh=imap(RR,W);
3690  list L;
3691  if ((size(Nh)>0) or (size(Wh)>0))
3692  {
3693    L=mrcgs(FH,list(Nh,Wh));
3694  }
3695  else
3696  {
3697    L=mrcgs(FH);
3698  }
3699  L[1][3]=subst(L[1][3],@t,1);
3700  L[1][4]=subst(L[1][4],@t,1);
3701  for (i=1; i<=L[1][2]; i++)
3702  {
3703    lab=intvec(i);
3704    u=tree(lab,L);
3705    postred=difflpp(u[1][3]);
3706    B=sortideal(subst(L[u[2]][4],@t,1));
3707    lpp=sortideal(subst(L[u[2]][3],@t,1));
3708    if (memberpos(1,B)[1]){B=ideal(1); lpp=ideal(1);}
3709    if (postred)
3710    {
3711      lpp=ideal(0);
3712      B=postredgb(mingb(B));
3713      for (j=1;j<=size(B);j++){lpp[j]=leadmonom(B[j]);}
3714    }
3715    else{"Sheaves present, not reduced bases in the case with:";lpp;}
3716    L[u[2]][4]=B;
3717    L[u[2]][3]=lpp;
3718  }
3719  setring(RR);
3720  setglobalrings();
3721  list LL=imap(RH,L);
3722  LL[1][6]="RCGS";
3723  return(LL);
3724}
3725example
3726{ "EXAMPLE:"; echo = 2;
3727  ring R=(0,b,c,d,e,f),(x,y),dp;
3728  ideal F=x^2+b*y^2+2*c*x*y+2*d*x+2*e*y+f, 2*x+2*c*y+2*d, 2*b*y+2*c*x+2*e;
3729  def T=rcgs(F);
3730  T;
3731  cantreetoMaple(T,"Tr","Tr.txt");
3732  cantodiffcgs(T);
3733}
3734
3735proc difflpp(ideal lpp)
3736{
3737  int t=1; int i;
3738  poly lp1=lpp[1];
3739  poly lp;
3740  i=2;
3741  while ((i<=size(lpp)) and (t))
3742  {
3743    lp=lpp[i];
3744    if (lp==lp1){t=0;}
3745    lp1=lp;
3746    i++;
3747  }
3748  return(t);
3749}
3750
3751// redgb: given a minimal bases (gb reducing) it
3752// reduces each polynomial w.r.t. to the others
3753proc postredgb(ideal F)
3754{
3755  ideal G;
3756  ideal H;
3757  int i;
3758  if (size(F)==0){return(ideal(0));}
3759  for (i=1;i<=size(F);i++)
3760  {
3761    H=delfromideal(F,i);
3762    G[i]=pdivi(F[i],H)[1];
3763  }
3764  return(G);
3765}
3766
3767proc crcgs(ideal F, list #)
3768"USAGE:   crcgs(F);
3769          F is the ideal from which to obtain the Canonical Reduced CGS.
3770          crcgs(F,L);
3771          where L is a list of the null conditions ideal N, and W the set of
3772          non-null polynomials (ideal). If this option is set, the ideals N and W
3773          must depend only on the parameters and the parameter space is
3774          reduced to V(N) \ V(h), where h=prod(w), for w in W.
3775          A reduced specification of (N,W) will be computed and used to
3776          restrict the parameter-space. The output will omit the known restrictions
3777          given as option.
3778RETURN:   The list representing the Canonical Reduced CGS.
3779          The description given here is identical for mrcgs and rcgs.
3780          The elements of the list T computed by crcgs are lists representing
3781          a rooted tree.
3782          Each element has as the two first entries with the following content:@*
3783           [1]: The label (intvec) representing the position in the rooted
3784                tree:  0 for the root (and this is a special element)
3785                       i for the root of the segment i
3786                       (i,...) for the children of the segment i
3787           [2]: the number of children (int) of the vertex.
3788          There thus three kind of vertices:
3789           1) the root (first element labelled 0),
3790           2) the vertices labelled with a single integer i,
3791           3) the rest of vertices labelled with more indices.
3792          Description of the root. Vertex type 1)
3793           There is a special vertex (the first one) whose content is
3794           the following:
3795             [3] lpp of the given ideal
3796             [4] the given ideal
3797             [5] the red-spec of the (optional) given null and non-null conditions
3798                 (see redspec for the description)
3799             [6] mrcgs (to remember which algorithm has been used). If the
3800                 algorithm used is rcgs of crcgs then this will be stated
3801                 at this vertex (RCGS or CRCGS).
3802           Description of vertices type 2). These are the vertices that
3803           initiate a segment, and are labelled with a single integer.
3804             [3] lpp (ideal) of the reduced basis. If they are repeated lpp's this
3805                 will correspond to a sheaf.
3806             [4] the reduced basis (ideal) of the segment.
3807           Description of vertices type 3). These vertices have as first
3808           label i and descend form vertex i in the position of the label
3809           (i,...). They contain moreover a unique prime ideal in the parameters
3810           and form ascending chains of ideals.
3811          How is to be read the mrcgs tree? The vertices with an even number of
3812          integers in the label are to be considered as additive and those
3813          with an odd number of integers in the label are to be considered as
3814          substraction. As an example consider the following vertices:
3815          v1=((i),2,lpp,B),
3816          v2=((i,1),2,P_{(i,1)}),
3817          v3=((i,1,1),0,P_{(i,1,1)}, v4=((i,1,2),0,P_{(i,1,1)}),
3818          v5=((i,2),2,P_{(i,2)},
3819          v6=((i,2,1),0,P_{(i,2,1)}, v7=((i,2,2),0,P_{(i,2,2)}
3820          They represent the segment:
3821          (V(i,1)\(V(i,1,1) u V(i,1,2))) u
3822          (V(i,2)\(V(i,2,1) u V(i,2,2)))
3823          where V(i,j,..) = V(P_{(i,j,..)}
3824NOTE:     There are three fundamental routines in the library: mrcgs, rcgs and crcgs.
3825          crcgs (Canonical Reduced CGS) is an algorithm that first homogenizes the
3826          the given ideal then applies mrcgs and finally de-homogenizes
3827          and reduces the resulting bases. (See the note of mrcgs).
3828          As a result of Wibmer's Theorem, the resulting segments are
3829          locally closed (i.e. difference of varieties) and the partition is
3830          canonical as the homogenized ideal is uniquely associated to the given
3831          ideal not depending of the given basis.
3832
3833          Nevertheless the computations to do are usually more time consuming
3834          and so it is preferable to compute first the rcgs and only if
3835          it success you can try crcgs.
3836
3837          The output can be visualized using cantreetoMaple, that will
3838          write a file with the content of crcgs that can be read in Maple
3839          and plotted using the Maple plotcantree routine of the Monte's dpgb library
3840          You can also use the routine cantodiffcgs as the segments are all
3841          difference of two varieties to have a simpler view of the output.
3842KEYWORDS: mrcgs, rcgs, buildtree, cantreetoMaple, cantodiffcgs
3843EXAMPLE:  mrcgs; shows an example"
3844{
3845  int ish=1; int i=1;
3846  while ((ish) and (i<=size(F)))
3847  {
3848    ish=ishomog(F[i]);
3849    i++;
3850  }
3851  if (ish){return(mrcgs(F, #));}
3852  list L;
3853  def RR=basering;
3854  setglobalrings();
3855  setring(@RP);
3856  ideal FP=imap(RR,F);
3857  option(redSB);
3858  def G=groebner(FP);
3859  setring(RR);
3860  def GR=imap(@RP,G);
3861  kill @RP;
3862  kill @P;
3863  L=rcgs(GR, #);
3864  L[1][6]="CRCGS";
3865  return(L);
3866}
3867example
3868{ "EXAMPLE:"; echo = 2;
3869  ring R=(0,b,c,d,e,f),(x,y),dp;
3870  ideal F=x^2+b*y^2+2*c*x*y+2*d*x+2*e*y+f, 2*x+2*c*y+2*d, 2*b*y+2*c*x+2*e;
3871  def T=crcgs(F);
3872  T;
3873  cantreetoMaple(T,"Tc","Tc.txt");
3874  cantodiffcgs(T);
3875}
3876
3877//purpose ideal intersection called in @R and computed in @P
3878proc idintR(ideal N, ideal M)
3879{
3880  def RR=basering;
3881  setring(@P);
3882  def Np=imap(RR,N);
3883  def Mp=imap(RR,M);
3884  def Jp=idint(Np,Mp);
3885  setring(RR);
3886  return(imap(@P,Jp));
3887}
3888
3889//purpose reduced groebner basis called in @R and computed in @P
3890proc gbR(ideal N)
3891{
3892  def RR=basering;
3893  setring(@P);
3894  def Np=imap(RR,N);
3895  option(redSB);
3896  Np=groebner(Np);
3897  setring(RR);
3898  return(imap(@P,Np));
3899}
3900
3901// purpose: given the output of a locally closed CGS (i.e. from rcgs or crcgs)
3902//          it returns the segments as difference of varieties.
3903proc cantodiffcgs(list L)
3904"USAGE:   canttodiffcgs(T);
3905          T: is the list provided by mrcgs or crcgs or crcgs,
3906RETURN:   The list transforming the content of these routines to a simpler
3907          output where each segment corresponds to a single element of the list
3908          that is described as difference of two varieties.
3909
3910          The first element of the list is identical to the first element
3911          of the list provided by the corresponding cgs algorithm, and
3912          contains general information on the call (see mrcgs).
3913          The remaining elements are lists of 4 elements,
3914          representing segments. These elements are
3915           [1]: the lpp of the segment
3916           [2]: the basis of the segment
3917           [3]; the ideal of the first variety (radical)
3918           [4]; the ideal of the second variety (radical)
3919          The segment is V([3]) \ V([4]).
3920
3921NOTE:     It can be called from the output of mrcgs or rcgs of crcgs
3922KEYWORDS: mrcgs, rcgs, crcgs, Maple
3923EXAMPLE:  cantodiffcgs; shows an example"
3924{
3925  int i; int j; int k; int depth; list LL; list u; list v; list w;
3926  ideal N; ideal Nn; ideal M; ideal Mn; ideal N0; ideal W0;
3927  LL[1]=L[1];
3928  N0=L[1][5][1];
3929  W0=L[1][5][2];
3930  def RR=basering;
3931  setring(@P);
3932  def N0P=imap(RR,N0);
3933  def W0P=imap(RR,N0);
3934  ideal NP;
3935  ideal MP;
3936  setring(RR);
3937  for (i=2;i<=size(L);i++)
3938  {
3939    depth=size(L[i][1]);
3940    if (depth>3){ERROR("the given CGS has non locally closed segments");}
3941  }
3942  for (i=1;i<=L[1][2];i++)
3943  {
3944    N=ideal(1);
3945    M=ideal(1);
3946    u=tree(intvec(i),L);
3947    for (j=1;j<=u[1][2];j++)
3948    {
3949      v=tree(intvec(i,j),L);
3950      Nn=v[1][3];
3951      N=idintR(N,Nn);
3952      for (k=1;k<=v[1][2];k++)
3953      {
3954        w=tree(intvec(i,j,k),L);
3955        Mn=w[1][3];
3956        M=idintR(M,Mn);
3957      }
3958    }
3959    setring(@P);
3960    def NP=imap(RR,N);
3961    def MP=imap(RR,M);
3962    MP=MP+N0P;
3963    for (j=1;j<=size(W0P);j++){MP=MP+ideal(W0P[j]);}
3964    NP=NP+N0P;
3965    NP=gbR(NP);
3966    MP=gbR(MP);
3967    setring(RR);
3968    N=imap(@P,NP);
3969    M=imap(@P,MP);
3970    LL[i+1]=list(u[1][3],u[1][4],N,M);
3971  }
3972  return(LL);
3973}
3974example
3975{ "EXAMPLE:"; echo = 2;
3976  ring R=(0,b,c,d,e,f),(x,y),dp;
3977  ideal F=x^2+b*y^2+2*c*x*y+2*d*x+2*e*y+f, 2*x+2*c*y+2*d, 2*b*y+2*c*x+2*e;
3978  def T=crcgs(F);
3979  T;
3980  cantreetoMaple(T,"Tc","Tc.txt");
3981  cantodiffcgs(T);
3982}
3983
3984//**************End homogenizing************************
Note: See TracBrowser for help on using the repository browser.