source: git/Singular/LIB/redcgs.lib @ 1288ef

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