source: git/Singular/LIB/grobcov.lib @ 7c7a10

spielwiese
Last change on this file since 7c7a10 was 7c7a10, checked in by Hans Schoenemann <hannes@…>, 3 years ago
chg: size(ringlist(..)..) -> nvars/npars/ring_list(..)
  • Property mode set to 100644
File size: 197.7 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2version="version grobcov.lib 4.2.0  February_2021 "; // $Id$;
3           // version N12;  February 2021;
4
5info="
6LIBRARY:  grobcov.lib
7          \"Groebner Cover for parametric ideals.\",
8          Comprehensive Groebner Systems, Groebner Cover,
9          Canonical Forms,  Parametric Polynomial Systems,
10          Automatic Deduction of Geometric Theorems,
11          Dynamic Geometry, Loci, Envelope, Constructible sets.
12          See: A. Montes A, M. Wibmer,
13          \"Groebner Bases for Polynomial Systems with parameters\",
14          Journal of Symbolic Computation 45 (2010) 1391-1425.
15          (https://www.mat.upc.edu//en/people/antonio.montes/).
16
17IMPORTANT: Recently published book:
18
19           A. Montes. \" The Groebner Cover\":
20           Springer, Algorithms and Computation in Mathematics 27 (2019)
21           ISSN 1431-1550
22           ISBN 978-3-030-03903-5
23           ISBN 978-3-030-03904-2  (e-Book)
24           Springer Nature Switzerland AG 2018
25
26           https://www.springer.com/gp/book/9783030039035
27
28           The book can also be used as a user manual of all
29           the  routines included in this library.
30           It defines and proves all the theoretic results used
31           in the library,  and shows examples of all the routines.
32           There are many previous papers related to the subject,
33           and the book actualices all the contents.
34
35AUTHORS:  Antonio Montes (Universitat Politecnica de Catalunya),
36          Hans Schoenemann (Technische Universitaet Kaiserslautern).
37
38OVERVIEW: In 2010, the library was designed to contain
39          Montes-Wibmer's algorithm for computing the
40          Canonical Groebner Cover of a  parametric ideal.
41          The central  routine is grobcov.
42          Given  a  parametric ideal, grobcov outputs
43          its Canonical  Groebner Cover, consisting of a set
44          of triplets of (lpp, basis,  segment). The basis
45          (after normalization) is the reduced  Groebner basis
46          for each point of the segment. The segments
47          are disjoint, locally closed and  correspond to
48          constant lpp (leading power product) of the basis,
49          and are represented in canonical representation.
50          The segments cover the  whole parameter space.
51          The output is canonical, it only depends on the
52          given parametric ideal and the monomial order,
53          because the segments  have
54          different lpph of the homogenized system.
55          This is much more than a simple Comprehensive
56          Groebner System.  The algorithm grobcov allows
57          options to solve  partially the problem when the
58          whole automatic algorithm  does not finish in
59          reasonable time. Its existence was proved for the
60          first time by Michael Wibmer \"Groebner bases for
61          families of affine or projective schemes\",
62          JSC, 42,803-834 (2007).
63
64          grobcov uses a first algorithm cgsdr that outputs a
65          disjoint  reduced Comprehensive Groebner System
66          with constant lpp. For this purpose, in this library,
67          the implemented algorithm is Kapur-Sun-Wang
68          algorithm, because it is actually the most efficient
69          algorithm known for this purpose.
70          D. Kapur, Y. Sun, and D.K. Wang \"A New Algorithm
71          for  Computing Comprehensive Groebner Systems\".
72          Proceedings of ISSAC'2010, ACM Press, (2010), 29-36.
73
74         The library has evolved to include new applications of
75          the  Groebner Cover, and new theoretical developments
76          have been done.
77
78          A routine locus has been included to compute
79          loci of points, and determining the taxonomy of the
80          components.
81          Additional routines to transform the output to string
82          (locusdg,  locusto) are also included and used in the
83          Dynamic Geometry software  GeoGebra. They were
84          described in:
85          M.A. Abanades, F. Botana, A. Montes, T. Recio:
86          \''An Algebraic Taxonomy  for Locus Computation in
87          Dynamic Geometry\''.
88          Computer-Aided Design 56 (2014) 22-33.
89
90          Routines for determining the generalized envelope of a family
91          of hypersurfaces (envelop, AssocTanToEnv,
92          FamElemsToEnvCompPoints) are also included.
93
94          It also includes procedures for
95          Automatic Deduction of Geometric Theorems (ADGT).
96
97          The actual version also includes a
98          routine (ConsLevels) for computing the canonical form
99          of a constructible set, given as a union of locally
100          closed sets. It determines the canonical
101          levels of a constructible set. It is described in:
102          J.M. Brunat, A. Montes, \"Computing the canonical
103          representation of constructible sets\".
104          Math.  Comput. Sci. (2016) 19: 165-178.
105          A complementary routine Levels transforms the output
106          of ConsLevels into the proper locally closed sets
107          forming the levels of the constructible.
108          Antoher complementary routine Grob1Levels
109          has been included to select the locally closed sets of
110          the segments of the grobcov that correspond to basis
111          different from 1, add them together and return
112          the canonical form of this constructible set.
113          More recently (2019) given two locally closed sets
114          in canonical form the new routine DifConsLCSets
115          determines a set of locally closed sets equivalent to
116          the difference them. The description of the
117          routine is submitted to the Journal of Symbolic Computation.
118          This routine can be also used internally by ADGT
119          with the option \"neg\",1 . With this option
120          DifConsLCSets is used for the negative
121          hypothesis and thesis in ADGT.
122
123          The last version N11 (2021) has improved the routines for locus
124          and allows to determine a parametric locus.
125
126          This version was finished on 1/2/2021,
127
128NOTATIONS: Before calling any routine of the library grobcov,
129          the user  must define the ideal Q[a][x], and all the
130          input polynomials and  ideals defined on it.
131          Internally the routines define and use also other
132          ideals: Q[a], Q[x,a] and so on.
133
134PROCEDURES:
135
136grobcov(F);  Is the basic routine giving the canonical Groebner
137          Cover of the parametric ideal F.  This routine accepts
138          many options, that allow to obtain results even when
139          the canonical  computation does not finish in
140          reasonable time.
141
142cgsdr(F); Is the procedure for obtaining a first disjoint,
143          reduced  Comprehensive Groebner  System that is
144          used in grobcov, but can also be used independently
145          if only a CGS is required. It is a more efficient routine
146          than buildtree (the own routine of 2010 that  is no
147          more available).
148          Now, Kapur-Sun-Wang (KSW) algorithm is used.
149
150pdivi(f,F); Performs a pseudodivision of a parametric
151          polynomial by  a parametric ideal.
152
153pnormalf(f,E,N); Reduces a parametric polynomial f over V(E) \ V(N).
154          E is the null ideal and N the non-null ideal over the parameters.
155
156Crep(N,M); Computes the canonical C-representation of V(N) \ V(M).
157          It can be called in Q[a] or in Q[a][x],
158          but the ideals N,M can only  contain parameters of Q[a].
159
160Prep(N,M); Computes the canonical P-representation of V(N) \ V(M).
161          It can be called in Q[a]  or in Q[a][x],
162          but the ideals N,M can only contain parameters of Q[a].
163
164PtoCrep(L)  Starting from the canonical Prep of a locally closed
165          set  computes its Crep.
166
167extendpoly(f,p,q); Given the generic representation f of an
168          I-regular function F defined by poly f on V(p) \ V(q)
169          it returns its full representation.
170
171extendGC(GC); When the grobcov of an ideal has been
172          computed  with the default option (\"ext\",0) and the
173          explicit option (\"rep\",2) (which is not the default),
174          then one  can call extendGC(GC) (and options) to obtain
175          the full representation of  the bases. With the default
176          option (\"ext\",0) only the generic representation of
177          the bases is computed, and one can obtain the full
178          representation using extendGC.
179
180locus(G); Special routine for determining the geometrical
181          locus of points verifying given conditions. To use it, the
182          ring R=(0,a1,..,ap,x1,..xn),(u1,..um,v1..vn),lp;
183          must be declared, where
184          (a1,..ap) are parameters (optative),
185          (x1,..xn) are the variabes of the tracer point,
186          (u1,..,um) are auxiliary variables,
187          (v1,..,vn) are the mover variables.
188          Then the input to locus must be the
189          parametric ideal F defined in R.
190
191          locus provides all the components of the locus and
192          determines their taxonomy, that can be:
193           \"Normal\", \"Special\", \"Accumulation\",
194          \"Degenerate\".
195          The mover variables are the last n variables.
196          The user can ventually restrict them to a subset of them
197          for geometrical reasons but this can change the true
198          taxonomy.
199          locus also allows to determine a parmetric locus
200          depending on p parameters a1,..ap using then
201          the option \"numpar\",p.
202
203locusdg(G); Is a special routine that determines the
204          \"Relevant\" components of the locus in dynamic
205          geometry. It is to be called to the output of locus
206          and selects from it the \"Normal\", and\"Accumulation\"
207          components.
208
209envelop(F,C); Special routine for determining the envelop
210          of a family of hyper-surfaces F  in
211          Q[x1,..,xn][t1,..,tm] depending on an ideal of
212          constraints C in Q[t1,..,tm]. It computes the
213          locus of the envelop, and detemines the
214          different components as well as their taxonomies:
215          \"Normal\", \"Special\", \"Accumulation\",
216          \"Degenerate\". (See help for locus).
217
218locusto(L); Transforms the output of locus, locusdg,
219          envelop into a string  that can be reed  from
220          different computational systems.
221
222stdlocus(F); Simple procedure to determine the components
223          of the locus, alternative to  locus that uses only
224          standard GB computation. Cannot determine the
225          taxonomy of  the irreducible components.
226
227AssocTanToEnv(F,C,E); Having computed an envelop
228          component E of a family of hyper-surfaces F,
229          with constraints C, it returns the parameter values
230          of the associated tangent  hyper-surface of the
231          family passing at one point of the envelop component E.
232
233FamElemsAtEnvCompPoints(F,C,E) Having computed an
234          envelop component E of a family of hyper-surfaces F,
235          with constraints C, it returns the parameter values of
236          all the  hyper-surfaces of the family passing at one
237          point of the envelop component E.
238
239discrim(f,x); Determines the factorized discriminant of a
240          degree 2 polynomial in the variable x. The polynomial
241          can be defined on any ring where x is a variable.
242          The polynomial f can depend on  parameters and
243          variables.
244
245WLemma(F,A); Given an ideal F in Q[a][x] and an ideal A
246          in Q[a], it returns the list (lpp,B,S)  were B is the
247          reduced Groebner basis of the specialized F over
248          the segment S, subset of V(A) with top A,
249          determined by Wibmer's Lemma.
250          S is determined in P-representation
251          (or optionally in C-representation). The basis is
252          given by I-regular functions.
253
254WLCGS(F);  Given a parametric ideal F in Q[a][x]
255          determines a CGS in full-representation using WLemma
256
257intersectpar(L); Auxiliary routine. Given a list of ideals definend on K[a][x]
258         it determines the intersection of all of them in K[x,a]
259
260ADGT(H,T,H1,T1); Given 4 ideals H,T,H1,T1 in Q[a][x], corresponding to
261        a problem of Automatic Deduction of Geometric Theorems,
262        it determines the supplementary conditions over the parameters
263        for the Proposition (H and not H1) => (T and not T1) to be a
264        Theorem.
265        If H1=1 then H1 is not considered, and analogously for T1.
266
267ConsLevels(A); Given a list of locally colsed sets, constructs the
268        canonical representation of the levels of A an its complement.
269
270Levels(L); Transforms the output of ConsLevels
271          into the proper Levels of  the constructible set.
272
273Grob1Levels(G); From the output of grobcov, Grob1Levels selects the segments
274        of G with basis different from 1 (having solutions), and determines
275        the levels of the constructible set formed by them.
276
277DifConsLCSets(A,B); given the canonical forms of the constructible sets A and B,
278         A=[a1,a2,..,ak],  B=[b1,b2,...,bj], DifConsLCSets returns a list of
279         locally closed sets of the set A minus B, that can be transformed into the
280         canonical form of A minus B applying ConsLevels.
281
282SEE ALSO: compregb_lib
283";
284
285LIB "polylib.lib";
286LIB "primdec.lib";
287LIB "qhmoduli.lib";
288
289// ************ Begin of the grobcov library *********************
290
291// Development of the library:
292// Library grobcov.lib
293// (Groebner Cover):
294// Release 0: (public)
295// Initial data: 21-1-2008
296// Uses buildtree for cgsdr
297// Final data: 3-7-2008
298// Release 2: (prived)
299// Initial data: 6-9-2009
300// Last version using buildtree for cgsdr
301// Final data: 25-10-2011
302// Release B: (prived)
303// Initial data: 1-7-2012
304// Uses both buildtree and KSW for cgsdr
305// Final data: 4-9-2012
306// Release D. Includes routine locus
307// Release G: (public)
308// Initial data: 4-9-2012
309// Uses KSW algorithm for cgsdr
310// Final data: 21-11-2013
311// Release K: Includes routine envelop
312// Release L: (public)
313// New routine ConsLevels: 25-1-2016
314// New routine Levels: 25-1-2016
315// New routine Grob1Levels: 25-1-2016
316// Updated locus: 10-7-2015 (uses ConsLevels)
317// Release M: (public)
318// New routines for computing the envelope of a family of
319//    hyper-surfaces and associated questions: 22-4-2016: 20-9-2016
320// New routine WLemma for computing the result of
321//    Wibmer's Lemma:  19-9-2016
322// Final data October 2016
323// Updated locus (messages)
324// Final data Mars 2017
325// Release N4: (public)
326// New routine ADGT for Automatic Discovery of Geometric Theorems: 21-1-2018
327// Final data February 2018
328// Release N8: July 2019. Actualized versions of the routines and options
329// Release N9: December 2019. New routine DifConsLCSets,
330// Updated also ADGT to use as option DifConsLCSets
331// Release N10: May 2020.
332// Updated locus. New determination of the taxonomies
333// Release N11: February 2021.
334// Improved the routines for locus. Accept parametric locus as option.
335
336//*************Auxiliary routines**************
337
338// elimintfromideal: elimine the constant numbers from an ideal
339//        (designed for W, nonnull conditions)
340// Input: ideal J
341// Output:ideal K with the elements of J that are non constants, in the
342//        ring Q[x1,..,xm]
343static proc elimintfromideal(ideal J)
344{
345  int i;
346  int j=0;
347  ideal K;
348  if (size(J)==0){return(ideal(0));}
349  for (i=1;i<=ncols(J);i++){if (size(variables(J[i])) !=0){j++; K[j]=J[i];}}
350  return(K);
351}
352
353// elimfromlistel: elimine the ideal J from the list L
354// Input: list L;  list of ideals
355//           ideal J;  a possible element of L
356// Output:ideal K with the elements of L different from J
357//        ring Q[x1,..,xm]
358static proc elimidealfromlist(list L,ideal J)
359{
360  int i;
361  int j=0;
362  list K;
363  if (size(L)==0){return(L);}
364  for (i=1;i<=size(L);i++)
365  {
366    if (not(equalideals(J,L[i])))
367    {
368      j++;
369      K[j]=L[i];
370    }
371  }
372  return(K);
373}
374
375// delfromideal: deletes the i-th polynomial from the ideal F
376//    Works in any kind of ideal
377static proc delfromideal(ideal F, int i)
378{
379  int j;
380  ideal G;
381  if (size(F)<i){ERROR("delfromideal was called with incorrect arguments");}
382  if (size(F)<=1){return(ideal(0));}
383  if (i==0){return(F)};
384  for (j=1;j<=ncols(F);j++)
385  {
386    if (j!=i){G[ncols(G)+1]=F[j];}
387  }
388  return(G);
389}
390
391// delidfromid: deletes the polynomials in J that are in I
392// Input: ideals I, J
393// Output: the ideal J without the polynomials in I
394//   Works in any kind of ideal
395static proc delidfromid(ideal I, ideal J)
396{
397  int i; list r;
398  ideal JJ=J;
399  for (i=1;i<=size(I);i++)
400  {
401    r=memberpos(I[i],JJ);
402    if (r[1])
403    {
404      JJ=delfromideal(JJ,r[2]);
405    }
406  }
407  return(JJ);
408}
409
410// eliminates the ith element from a list or an intvec
411static proc elimfromlist(l, int i)
412{
413  if(typeof(l)=="list"){list L;}
414  if (typeof(l)=="intvec"){intvec L;}
415  if (typeof(l)=="ideal"){ideal L;}
416  int j;
417  if((size(l)==0) or (size(l)==1 and i!=1)){return(l);}
418  if (size(l)==1 and i==1){return(L);}
419  // L=l[1];
420  if(i>1)
421  {
422    for(j=1;j<=i-1;j++)
423    {
424      L[size(L)+1]=l[j];
425    }
426  }
427  for(j=i+1;j<=size(l);j++)
428  {
429    L[size(L)+1]=l[j];
430  }
431  return(L);
432}
433
434// eliminates repeated elements form an ideal or matrix or module or intmat or bigintmat
435static proc elimrepeated(F)
436{
437  int i;
438  int nt;
439  if (typeof(F)=="ideal"){nt=ncols(F);}
440  else{nt=size(F);}
441
442  def FF=F;
443  FF=F[1];
444  for (i=2;i<=nt;i++)
445  {
446    if (not(memberpos(F[i],FF)[1]))
447    {
448      FF[size(FF)+1]=F[i];
449    }
450  }
451  return(FF);
452}
453
454// equalideals
455// Input: ideals F and G;
456// Output: 1 if they are identical (the same polynomials in the same order)
457//         0 else
458static proc equalideals(ideal F, ideal G)
459{
460  int i=1; int t=1;
461  if (size(F)!=size(G)){return(0);}
462  while ((i<=size(F)) and (t==1))
463  {
464      if (F[i]!=G[i]){t=0;}
465    i++;
466  }
467  return(t);
468}
469
470// returns 1 if the two lists of ideals are equal and 0 if not
471static proc equallistideals(list L, list M)
472{
473  int t; int i;
474  if (size(L)!=size(M)){return(0);}
475  else
476  {
477    t=1;
478    if (size(L)>0)
479    {
480      i=1;
481      while ((t) and (i<=size(L)))
482      {
483        if (equalideals(L[i],M[i])==0){t=0;}
484        i++;
485      }
486    }
487    return(t);
488  }
489}
490
491// idcontains
492// Input: ideal p, ideal q
493// Output: 1 if p contains q,  0 otherwise
494// If the routine is to be called from the top, a previous call to
495static proc idcontains(ideal p, ideal q)
496{
497  int t; int i;
498  t=1; i=1;
499  def P=p; def Q=q;
500  attrib(P,"isSB",1);
501  poly r;
502  while ((t) and (i<=size(Q)))
503  {
504    r=reduce(Q[i],P,5);
505    if (r!=0){t=0;}
506    i++;
507  }
508  return(t);
509}
510
511// selectminideals
512//   given a list of ideals returns the list of integers corresponding
513//   to the minimal ideals in the list
514// Input: L (list of ideals)
515// Output: the list of integers corresponding to the minimal ideals in L
516//   Works in Q[u_1,..,u_m]
517static proc selectminideals(list L)
518{
519  list P; int i; int j; int t;
520  if(size(L)==0){return(L)};
521  if(size(L)==1){P[1]=1; return(P);}
522  for (i=1;i<=size(L);i++)
523  {
524    t=1;
525    j=1;
526    while ((t) and (j<=size(L)))
527    {
528      if (i!=j)
529      {
530        if(idcontains(L[i],L[j])==1)
531        {
532          t=0;
533        }
534      }
535      j++;
536    }
537    if (t){P[size(P)+1]=i;}
538  }
539  return(P);
540}
541
542static proc memberpos(f,J)
543//"USAGE:  memberpos(f,J);
544//         (f,J) expected (polynomial,ideal)
545//               or       (int,list(int))
546//               or       (int,intvec)
547//               or       (intvec,list(intvec))
548//               or       (list(int),list(list(int)))
549//               or       (ideal,list(ideal))
550//               or       (list(intvec),  list(list(intvec))).
551//         Works in any kind of ideals
552//RETURN:  The list (t,pos) t int; pos int;
553//         t is 1 if f belongs to J and 0 if not.
554//         pos gives the position in J (or 0 if f does not belong).
555//EXAMPLE: memberpos; shows an example"
556{
557  int pos=0;
558  int i=1;
559  int j;
560  int t=0;
561  int nt;
562  if (typeof(J)=="ideal"){nt=ncols(J);}
563  else{nt=size(J);}
564  if ((typeof(f)=="poly") or (typeof(f)=="int"))
565  { // (poly,ideal)  or
566    // (poly,list(poly))
567    // (int,list(int)) or
568    // (int,intvec)
569    i=1;
570    while(i<=nt)
571    {
572      if (f==J[i]){return(list(1,i));}
573      i++;
574    }
575    return(list(0,0));
576  }
577  else
578  {
579    if ((typeof(f)=="intvec") or ((typeof(f)=="list") and (typeof(f[1])=="int")))
580    { // (intvec,list(intvec)) or
581      // (list(int),list(list(int)))
582      i=1;
583      t=0;
584      pos=0;
585      while((i<=nt) and (t==0))
586      {
587        t=1;
588        j=1;
589        if (size(f)!=size(J[i])){t=0;}
590        else
591        {
592          while ((j<=size(f)) and t)
593          {
594            if (f[j]!=J[i][j]){t=0;}
595            j++;
596          }
597        }
598        if (t){pos=i;}
599        i++;
600      }
601      if (t){return(list(1,pos));}
602      else{return(list(0,0));}
603    }
604    else
605    {
606      if (typeof(f)=="ideal")
607      { // (ideal,list(ideal))
608        i=1;
609        t=0;
610        pos=0;
611        while((i<=nt) and (t==0))
612        {
613          t=1;
614          j=1;
615          if (ncols(f)!=ncols(J[i])){t=0;}
616          else
617          {
618            while ((j<=ncols(f)) and t)
619            {
620              if (f[j]!=J[i][j]){t=0;}
621              j++;
622            }
623          }
624          if (t){pos=i;}
625          i++;
626        }
627        if (t){return(list(1,pos));}
628        else{return(list(0,0));}
629      }
630      else
631      {
632        if ((typeof(f)=="list") and (typeof(f[1])=="intvec"))
633        { // (list(intvec),list(list(intvec)))
634          i=1;
635          t=0;
636          pos=0;
637          while((i<=nt) and (t==0))
638          {
639            t=1;
640            j=1;
641            if (size(f)!=size(J[i])){t=0;}
642            else
643            {
644              while ((j<=size(f)) and t)
645              {
646                if (f[j]!=J[i][j]){t=0;}
647                j++;
648              }
649            }
650            if (t){pos=i;}
651            i++;
652          }
653          if (t){return(list(1,pos));}
654          else{return(list(0,0));}
655        }
656      }
657    }
658  }
659}
660//example
661//{ "EXAMPLE:"; echo = 2;
662//  list L=(7,4,5,1,1,4,9);
663//  memberpos(1,L);
664//}
665
666// Auxiliary routine
667// pos
668// Input:  intvec p of zeros and ones
669// Output: intvec W of the positions where p has ones.
670static proc pos(intvec p)
671{
672  int i;
673  intvec W; int j=1;
674  for (i=1; i<=size(p); i++)
675  {
676    if (p[i]==1){W[j]=i; j++;}
677  }
678  return(W);
679}
680
681// Input:
682//  A,B: lists of ideals
683// Output:
684//   1 if both lists of ideals are equal, or 0 if not
685static proc equallistsofideals(list A, list B)
686{
687 int i;
688 int tes=0;
689 if (size(A)!=size(B)){return(tes);}
690 tes=1; i=1;
691 while(tes==1 and i<=size(A))
692 {
693   if (equalideals(A[i],B[i])==0){tes=0; return(tes);}
694   i++;
695 }
696 return(tes);
697}
698
699// Input:
700//  A,B:  lists of P-rep, i.e. of the form [p_i,[p_{i1},..,p_{ij_i}]]
701// Output:
702//   1 if both lists of P-reps are equal, or 0 if not
703static proc equallistsA(list A, list B)
704{
705  int tes=0;
706  if(equalideals(A[1],B[1])==0){return(tes);}
707  tes=equallistsofideals(A[2],B[2]);
708  return(tes);
709}
710
711// Input:
712//  A,B:  lists lists of of P-rep, i.e. of the form [[p_1,[p_{11},..,p_{1j_1}]] .. [p_i,[p_{i1},..,p_{ij_i}]]
713// Output:
714//   1 if both lists of lists of P-rep are equal, or 0 if not
715static proc equallistsAall(list A,list B)
716{
717 int i; int tes;
718 if(size(A)!=size(B)){return(tes);}
719 tes=1; i=1;
720 while(tes and i<=size(A))
721 {
722   tes=equallistsA(A[i],B[i]);
723   i++;
724 }
725 return(tes);
726}
727
728// idint: ideal intersection
729//        in the ring @P.
730//        it works in an extended ring
731// input: two ideals in the ring @P
732// output the intersection of both (is not a GB)
733static proc idint(ideal I, ideal J)
734{
735  def RR=basering;
736  ring T=0,t,lp;
737  def K=T+RR;
738  setring(K);
739  def Ia=imap(RR,I);
740  def Ja=imap(RR,J);
741  ideal IJ;
742  int i;
743  for(i=1;i<=size(Ia);i++){IJ[i]=t*Ia[i];}
744  for(i=1;i<=size(Ja);i++){IJ[size(Ia)+i]=(1-t)*Ja[i];}
745  ideal eIJ=eliminate(IJ,t);
746  setring(RR);
747  return(imap(K,eIJ));
748}
749
750//purpose ideal intersection called in @R and computed in @P
751static proc idintR(ideal N, ideal M)
752{
753  def RR=basering;
754  def Rx=ringlist(RR);
755  def P=ring(Rx[1]);
756  setring(P);
757  def Np=imap(RR,N);
758  def Mp=imap(RR,M);
759  def Jp=idint(Np,Mp);
760  setring(RR);
761  return(imap(P,Jp));
762}
763
764// Auxiliary routine
765// comb: the list of combinations of elements (1,..n) of order p
766static proc comb(int n, int p)
767{
768  list L; list L0;
769  intvec c; intvec d;
770  int i; int j; int last;
771  if ((n<0) or (n<p))
772  {
773    return(L);
774  }
775  if (p==1)
776  {
777    for (i=1;i<=n;i++)
778    {
779      c=i;
780      L[size(L)+1]=c;
781    }
782    return(L);
783  }
784  else
785  {
786    L0=comb(n,p-1);
787    for (i=1;i<=size(L0);i++)
788    {
789      c=L0[i]; d=c;
790      last=c[size(c)];
791      for (j=last+1;j<=n;j++)
792      {
793        d[size(c)+1]=j;
794        L[size(L)+1]=d;
795      }
796    }
797    return(L);
798  }
799}
800
801// Auxiliary routine
802// combrep
803// Input: V=(n_1,..,n_i)
804// Output: L=(v_1,..,v_p) where p=prod_j=1^i (n_j)
805//    is the list of all intvec v_j=(v_j1,..,v_ji) where 1<=v_jk<=n_i
806static proc combrep(intvec V)
807{
808  list L; list LL;
809  int i; int j; int k;  intvec W;
810  if (size(V)==1)
811  {
812    for (i=1;i<=V[1];i++)
813    {
814      L[i]=intvec(i);
815    }
816    return(L);
817  }
818  for (i=1;i<size(V);i++)
819  {
820    W[i]=V[i];
821  }
822  LL=combrep(W);
823  for (i=1;i<=size(LL);i++)
824  {
825    W=LL[i];
826    for (j=1;j<=V[size(V)];j++)
827    {
828      W[size(V)]=j;
829      L[size(L)+1]=W;
830    }
831  }
832  return(L);
833}
834
835// input ideal J, ideal K
836// output 1 if all the polynomials in J are members of K
837//            0 if not
838 proc subset(J,K)
839//"USAGE:   subset(J,K);
840//          (J,K)  expected (ideal,ideal)
841//                  or     (list, list)
842//RETURN:   1 if all the elements of J are in K, 0 if not.
843//EXAMPLE:  subset; shows an example;"
844{
845  int i=1;
846  int nt;
847  if (typeof(J)=="ideal"){nt=ncols(J);}
848  else{nt=size(J);}
849  if (size(J)==0){return(1);}
850  while(i<=nt)
851  {
852    if (memberpos(J[i],K)[1]){i++;}
853    else {return(0);}
854  }
855  return(1);
856}
857//example
858//{ "EXAMPLE:"; echo = 2;
859//  list J=list(7,3,2);
860//  list K=list(1,2,3,5,7,8);
861//  subset(J,K);
862//}
863
864// cld : clears denominators of an ideal and normalizes to content 1
865//        can be used in @R or @P or @RP
866// input:
867//        ideal J (J can be also poly), but the output is an ideal;
868// output:
869//        ideal Jc (the new form of ideal J without denominators and
870//        normalized to content 1)
871static proc cld(ideal J)
872{
873  if (size(J)==0){return(ideal(0));}
874  int te=0;
875  def RR=basering;
876  def Rx=ringlist(RR);
877  if(size(Rx[1])==4)
878  {
879    te=1;
880    def P=ring(Rx[1]);
881    Rx[1]=0;
882    def D=ring(Rx);
883    def RP=D+P;
884    setring(RP);
885    def Ja=imap(RR,J);
886  }
887  else{ def Ja=J;}
888  ideal Jb;
889  if (size(Ja)==0){setring(RR); return(ideal(0));}
890  int i;
891  def j=0;
892  for (i=1;i<=ncols(Ja);i++){if (size(Ja[i])!=0){j++; Jb[j]=cleardenom(Ja[i]);}}
893  if(te==1)
894  {
895    setring(RR);
896    def Jc=imap(RP,Jb);
897  }
898  else{def Jc=Jb;}
899  // if(te){kill @R; kill @RP; kill @P;}
900  return(Jc);
901};
902
903// simpqcoeffs : simplifies a quotient of two polynomials
904// input: two coefficients (or terms), that are considered as a quotient
905// output: the two coefficients reduced without common factors
906static proc simpqcoeffs(poly n,poly m)
907{
908  def nc=content(n);
909  def mc=content(m);
910  def gc=gcd(nc,mc);
911  ideal s=n/gc,m/gc;
912  return (s);
913}
914
915//*****************************
916
917// pdivi : pseudodivision of a parametric polynomial f by a parametric ideal F in Q[a][x].
918// input:
919//   poly  f
920//   ideal F
921// output:
922//   list (poly r, ideal q, poly mu)
923//   mu*f=sum(q_i*F_i)+r
924//   no monomial of r is divisible by no lpp of F
925proc pdivi(poly f,ideal F)
926"USAGE: pdivi(poly f,ideal F);
927          poly f: the polynomial in Q[a][x] to be divided
928          ideal F: the divisor ideal in Q[a][x].
929          (a=parameters, x=variables).
930RETURN: A list (poly r, ideal q, poly m). r is the remainder
931          of the pseudodivision, q is the set of quotients,
932          and m is the coefficient factor by which f is to
933          be multiplied.
934NOTE: pseudodivision of a poly f by an ideal F in Q[a][x].
935          Returns a list (r,q,m) such that
936          m*f=r+sum(q.F),
937          and no lpp of a divisor divides a pp of r.
938KEYWORDS: division; reduce
939EXAMPLE:  pdivi; shows an example"
940{
941  F=simplify(F,2);
942  int i;
943  int j;
944  poly v=1;
945  for(i=1;i<=nvars(basering);i++){v=v*var(i);}
946  poly r=0;
947  poly mu=1;
948  def p=f;
949  ideal q;
950  for (i=1; i<=ncols(F); i++){q[i]=0;};
951  ideal lpf;
952  ideal lcf;
953  for (i=1;i<=ncols(F);i++){lpf[i]=leadmonom(F[i]);}
954  for (i=1;i<=ncols(F);i++){lcf[i]=leadcoef(F[i]);}
955  poly lpp;
956  poly lcp;
957  poly qlm;
958  poly nu;
959  poly rho;
960  int divoc=0;
961  ideal qlc;
962  while (p!=0)
963  {
964    i=1;
965    divoc=0;
966    lpp=leadmonom(p);
967    lcp=leadcoef(p);
968    while (divoc==0 and i<=size(F))
969    {
970      qlm=lpp/lpf[i];
971      if (qlm!=0)
972      {
973        qlc=simpqcoeffs(lcp,lcf[i]);
974        //string("T_i=",i,";  qlc=",qlc);
975        nu=qlc[2];
976        mu=mu*nu;
977        rho=qlc[1]*qlm;
978        //"T_nu="; nu; "mu="; mu; "rho="; rho;
979        p=nu*p-rho*F[i];
980        r=nu*r;
981        for (j=1;j<=size(F);j++){q[j]=nu*q[j];}
982        q[i]=q[i]+rho;
983        //"T_q[i]="; q[i];
984        divoc=1;
985      }
986      else {i++;}
987    }
988    if (divoc==0)
989    {
990      r=r+lcp*lpp;
991      p=p-lcp*lpp;
992    }
993    //"T_r="; r; "p="; p;
994  }
995  list res=r,q,mu;
996  return(res);
997}
998example
999{ "RXAMPLE:";echo = 2;
1000  // Division of a polynom by an ideal
1001
1002  if(defined(R)){kill R;}
1003  ring R=(0,a,b,c),(x,y),dp;
1004  short=0;
1005
1006  // Divisor
1007  poly f=(ab-ac)*xy+(ab)*x+(5c);
1008
1009  // Dividends
1010  ideal F=ax+b,
1011       cy+a;
1012
1013  // (Remainder, quotients, factor)
1014  def r=pdivi(f,F);
1015  r;
1016
1017  // Verifying the division
1018  r[3]*f-(r[2][1]*F[1]+r[2][2]*F[2]+r[1]);
1019}
1020
1021//*****************************
1022
1023// pspol : S-poly of two polynomials in @R
1024// @R
1025// input:
1026//   poly f (given in the ring @R)
1027//   poly g (given in the ring @R)
1028// output:
1029//   list (S, red):  S is the S-poly(f,g) and red is a Boolean variable
1030//                if red then S reduces by Buchberger 1st criterion
1031//                (not used)
1032static proc pspol(poly f,poly g)
1033{
1034  def lcf=leadcoef(f);
1035  def lcg=leadcoef(g);
1036  def lpf=leadmonom(f);
1037  def lpg=leadmonom(g);
1038  def v=gcd(lpf,lpg);
1039  def s=simpqcoeffs(lcf,lcg);
1040  def vf=lpf/v;
1041  def vg=lpg/v;
1042  poly S=s[2]*vg*f-s[1]*vf*g;
1043  return(S);
1044}
1045
1046// facvar: Returns all the free-square factors of the elements
1047//         of ideal J (non repeated). Integer factors are ignored,
1048//         even 0 is ignored. It can be called from ideal Q[a][x], but
1049//         the given ideal J must only contain poynomials in the
1050//         parameters a.
1051//         Operates in the ring Q[a], but can be called from ring Q[a][x],
1052// input:  ideal J
1053// output: ideal Jc: Returns all the free-square factors of the elements
1054//         of ideal J (non repeated). Integer factors are ignored,
1055//         even 0 is ignored.
1056static proc facvar(ideal J)
1057//"USAGE:   facvar(J);
1058//          J: an ideal in the parameters
1059//RETURN:   all the free-square factors of the elements
1060//          of ideal J (non repeated). Integer factors are ignored,
1061//          even 0 is ignored. It can be called from ideal @R, but
1062//          the given ideal J must only contain poynomials in the
1063//          parameters.
1064//NOTE:     Operates in the ring @P, and the ideal J must contain only
1065//          polynomials in the parameters, but can be called from ring @R.
1066//KEYWORDS: factor
1067//EXAMPLE:  facvar; shows an example"
1068{
1069  int i;
1070  def RR=basering;
1071  def Rx=ringlist(RR);
1072  def P=ring(Rx[1]);
1073  setring(P);
1074  def Ja=imap(RR,J);
1075  if(size(Ja)==0){setring(RR); return(ideal(0));}
1076  Ja=elimintfromideal(Ja); // also in ideal @P
1077  ideal Jb;
1078  if (size(Ja)==0){Jb=ideal(0);}
1079  else
1080  {
1081    for (i=1;i<=ncols(Ja);i++){if(size(Ja[i])!=0){Jb=Jb,factorize(Ja[i],1);}}
1082    Jb=simplify(Jb,2+4+8);
1083    Jb=cld(Jb);
1084    Jb=elimintfromideal(Jb); // also in ideal @P
1085  }
1086  setring(RR);
1087  def Jc=imap(P,Jb);
1088  return(Jc);
1089}
1090//example
1091//{ "EXAMPLE:"; echo = 2;
1092//  ring R=(0,a,b,c),(x,y,z),dp;
1093//  setglobalrings();
1094//  ideal J=a2-b2,a2-2ab+b2,abc-bc;
1095//  facvar(J);
1096//}
1097
1098// Ered: eliminates the factors in the polynom f that are non-null.
1099//       In ring Q[a][x]
1100// input:
1101//   poly f:
1102//   ideal E  of null-conditions
1103//   ideal N  of non-null conditions
1104//        (E,N) represents V(E) \ V(N),
1105//        Ered eliminates the non-null factors of f in V(E) \ V(N)
1106// output:
1107//   poly f2  where the non-null conditions have been dropped from f
1108static proc Ered(poly f,ideal E, ideal N)
1109{
1110  def RR=basering;
1111  if((f==0) or (equalideals(N,ideal(1)))){ return(f);}
1112  def v=variables(f);
1113  int i;
1114  poly X=1;
1115  for(i=1;i<=size(v);i++){X=X*v[i];}
1116  matrix M=coef(f,X);
1117  list Mc;
1118  for(i=1;i<=ncols(M);i++){Mc[i]=M[2,i];}
1119  // "T_M="; M;
1120  // "T_Mc=";Mc;
1121
1122  poly g=M[2,1];
1123  if (size(M)!=2)
1124  {
1125    for(i=2;i<=size(M) div 2;i++)
1126    {
1127      g=gcd(g,M[2,i]);
1128    }
1129  }
1130  // "T_g="; g;
1131  if (g==1){ return(f);}
1132  else
1133  {
1134    def wg=factorize(g);
1135    // "T_wg="; wg;
1136    if (wg[1][1]==1){ return(f);}
1137    else
1138    {
1139      poly simp=1;
1140      int te;
1141      for(i=1;i<=size(wg[1]);i++)
1142      {
1143        te=inconsistent(E+wg[1][i],N);
1144        if(te)
1145        {
1146          simp=simp*(wg[1][i])^(wg[2][i]);
1147        }
1148      }
1149    }
1150    if (simp==1){ return(f);}
1151    else
1152    {
1153      //def simp0=imap(P,simp);
1154      def f2=f/simp;
1155      return(f2);
1156    }
1157  }
1158}
1159
1160//*******************
1161
1162// pnormalf: reduces a polynomial f wrt a V(E) \ V(N)
1163//           dividing by E and eliminating factors in N.
1164//           called in the ring @R,
1165//           operates in the ring @RP.
1166// input:
1167//         poly  f
1168//         ideal E  (depends only on the parameters)
1169//         ideal N  (depends only on the parameters)
1170//                  (E,N) represents V(E) \ V(N)
1171//         optional:
1172// output: poly f2 reduced wrt to V(E) \ V(N)
1173proc pnormalf(poly f, ideal E, ideal N)
1174"USAGE: pnormalf(poly f,ideal E,ideal N);
1175          f: the polynomial in Q[a][x]  (a=parameters,
1176          x=variables) to be reduced modulo V(E) \ V(N)
1177          of a segment in Q[a].
1178          E: the null conditions ideal in Q[a]
1179          N: the non-null conditions in Q[a]
1180RETURN: a reduced polynomial g of f, whose coefficients are
1181          reduced modulo E and having no factor in N.
1182NOTE: Should be called from ring Q[a][x]. Ideals E and N must
1183          be given by polynomials in Q[a].
1184KEYWORDS: division; pdivi; reduce
1185EXAMPLE: pnormalf; shows an example"
1186{
1187    def RR=basering;
1188    int te=0;
1189    def Rx=ringlist(RR);
1190    def P=ring(Rx[1]);
1191    Rx[1]=0;
1192    def D=ring(Rx);
1193    def RP=D+P;
1194    setring(RP);
1195    def fa=imap(RR,f);
1196    def Ea=imap(RR,E);
1197    def Na=imap(RR,N);
1198    option(redSB);
1199    Ea=std(Ea);
1200    def r=cld(reduce(fa,Ea));
1201    poly f1=r[1];
1202    setring RR;
1203    def f2=imap(RP,f1);
1204    f2=Ered(f2,E,N);
1205    //setring(RR);
1206    //def f2=imap(RP,f1);
1207    // if(te==0){kill @R; kill @RP; kill @P;}
1208    return(f2)
1209};
1210example
1211{ "EXAMPLE:"; echo = 2;
1212
1213if(defined(R)){kill R;}
1214ring R=(0,a,b,c),(x,y),dp;
1215short=0;
1216
1217// parametric polynom
1218poly f=(b^2-1)*x^3*y+(c^2-1)*x*y^2+(c^2*b-b)*x+(a-bc)*y;
1219// ideals defining V(p)\V(q)
1220ideal p=c-1;
1221ideal q=a-b;
1222
1223// pnormaform of f on V(p) \ V(q)
1224pnormalf(f,p,q);
1225}
1226
1227//*******************
1228
1229// lesspol: compare two polynomials by its leading power products
1230// input:  two polynomials f,g in the ring @R
1231// output: 0 if f<g,  1 if f>=g
1232static proc lesspol(poly f, poly g)
1233{
1234  if (leadmonom(f)<leadmonom(g)){return(1);}
1235  else
1236  {
1237    if (leadmonom(g)<leadmonom(f)){return(0);}
1238    else
1239    {
1240      if (leadcoef(f)<leadcoef(g)){return(1);}
1241      else {return(0);}
1242    }
1243  }
1244};
1245
1246// sortideal: sorts the polynomials in an ideal by lm in ascending order
1247static proc sortideal(ideal Fi)
1248{
1249  def RR=basering;
1250  def Rx=ringlist(RR);
1251  def P=ring(Rx[1]);
1252  Rx[1]=0;
1253  def D=ring(Rx);
1254  def RP=D+P;
1255  setring(RP);
1256  def F=imap(RR,Fi);
1257  def H=F;
1258  ideal G;
1259  int i;
1260  int j;
1261  poly p;
1262  while (size(H)!=0)
1263  {
1264    j=1;
1265    p=H[1];
1266    for (i=1;i<=ncols(H);i++)
1267    {
1268      if(lesspol(H[i],p)){j=i;p=H[j];}
1269    }
1270    G[ncols(G)+1]=p;
1271    H=delfromideal(H,j);
1272    H=simplify(H,2);
1273  }
1274  setring(RR);
1275  def GG=imap(RP,G);
1276  GG=simplify(GG,2);
1277  return(GG);
1278}
1279
1280// mingb: given a basis (gb reducing) it
1281// order the polynomials in ascending order and
1282// eliminates the polynomials whose lpp are divisible by some
1283// smaller one
1284static proc mingb(ideal F)
1285{
1286  int t; int i; int j;
1287  def H=sortideal(F);
1288  ideal G;
1289  if (ncols(H)<=1){return(H);}
1290  G=H[1];
1291  for (i=2; i<=ncols(H); i++)
1292  {
1293    t=1;
1294    j=1;
1295    while (t and (j<i))
1296    {
1297      if((leadmonom(H[i])/leadmonom(H[j]))!=0) {t=0;}
1298      j++;
1299    }
1300    if (t) {G[size(G)+1]=H[i];}
1301  }
1302  return(G);
1303}
1304
1305// redgbn: given a minimal basis (gb reducing) it
1306// reduces each polynomial wrt to V(E) \ V(N)
1307static proc redgbn(ideal F, ideal E, ideal N)
1308{
1309  int te=0;
1310  ideal G=F;
1311  ideal H;
1312  int i;
1313  if (size(G)==0){return(ideal(0));}
1314  for (i=1;i<=size(G);i++)
1315  {
1316    H=delfromideal(G,i);
1317    G[i]=pnormalf(pdivi(G[i],H)[1],E,N);
1318    G[i]=primepartZ(G[i]);
1319  }
1320  // if(te==1){setglobalrings();}
1321  return(G);
1322}
1323
1324//**************Begin homogenizing************************
1325
1326// ishomog:
1327// Purpose: test if a polynomial is homogeneous in the variables or not
1328// input:  poly f
1329// output  1 if f is homogeneous, 0 if not
1330static proc ishomog(f)
1331{
1332  int i; poly r; int d; int dr;
1333  if (f==0){return(1);}
1334  d=deg(f); dr=d; r=f;
1335  while ((d==dr) and (r!=0))
1336  {
1337    r=r-lead(r);
1338    dr=deg(r);
1339  }
1340  if (r==0){return(1);}
1341  else{return(0);}
1342}
1343
1344// postredgb: given a minimal basis (gb reducing) it
1345// reduces each polynomial wrt to the others
1346static proc postredgb(ideal F)
1347{
1348  int te=0;
1349  ideal G;
1350  ideal H;
1351  int i;
1352  if (size(F)==0){return(ideal(0));}
1353  for (i=1;i<=size(F);i++)
1354  {
1355    H=delfromideal(F,i);
1356    G[i]=pdivi(F[i],H)[1];
1357  }
1358  return(G);
1359}
1360
1361
1362//purpose reduced Groebner basis called in @R and computed in @P
1363static proc gbR(ideal N)
1364{
1365  def RR=basering;
1366  def Rx=ringlist(RR);
1367  def P=ring(Rx[1]);
1368  setring(P);
1369  def Np=imap(RR,N);
1370  option(redSB);
1371  Np=std(Np);
1372  setring(RR);
1373  return(imap(P,Np));
1374}
1375
1376//**************End homogenizing************************
1377
1378//**************Begin of Groebner Cover*****************
1379
1380// incquotient
1381// incremental quotient
1382// Input: ideal N: a Groebner basis of an ideal
1383//        poly f:
1384// Output: Na = N:<f>
1385static proc incquotient(ideal N, poly f)
1386{
1387  poly g; int i;
1388  ideal Nb; ideal Na=N;
1389  if (size(Na)==1)
1390  {
1391    g=gcd(Na[1],f);
1392    if (g!=1)
1393    {
1394      Na[1]=Na[1]/g;
1395    }
1396    attrib(Na,"IsSB",1);
1397    return(Na);
1398  }
1399  def P=basering;
1400  poly @t;
1401  ring H=0,@t,lp;
1402  def HP=H+P;
1403  setring(HP);
1404  def fh=imap(P,f);
1405  def Nh=imap(P,N);
1406  ideal Nht;
1407  for (i=1;i<=size(Nh);i++)
1408  {
1409    Nht[i]=Nh[i]*@t;
1410  }
1411  attrib(Nht,"isSB",1);
1412  def fht=(1-@t)*fh;
1413  option(redSB);
1414  Nht=std(Nht,fht);
1415  ideal Nc; ideal v;
1416  for (i=1;i<=size(Nht);i++)
1417  {
1418    v=variables(Nht[i]);
1419    if(memberpos(@t,v)[1]==0)
1420    {
1421      Nc[size(Nc)+1]=Nht[i]/fh;
1422    }
1423  }
1424  setring(P);
1425  ideal HH;
1426  def Nd=imap(HP,Nc); Nb=Nd;
1427  option(redSB);
1428  Nb=std(Nd);
1429  return(Nb);
1430}
1431
1432// Auxiliary routine to define an order for ideals
1433// Returns 1 if the ideal a is shoud precede ideal b by sorting them in idbefid order
1434//             2 if the the contrary happen
1435//             0 if the order is not relevant
1436static proc idbefid(ideal a, ideal b)
1437{
1438  poly fa; poly fb; poly la; poly lb;
1439  int te=1; int i; int j;
1440  int na=size(a);
1441  int nb=size(b);
1442  int nm;
1443  if (na<=nb){nm=na;} else{nm=nb;}
1444  for (i=1;i<=nm; i++)
1445  {
1446    fa=a[i]; fb=b[i];
1447    while((fa!=0) or (fb!=0))
1448    {
1449      la=lead(fa);
1450      lb=lead(fb);
1451      fa=fa-la;
1452      fb=fb-lb;
1453      la=leadmonom(la);
1454      lb=leadmonom(lb);
1455      if(leadmonom(la+lb)!=la){return(1);}
1456      else{if(leadmonom(la+lb)!=lb){return(2);}}
1457    }
1458  }
1459  if(na<nb){return(1);}
1460  else
1461  {
1462    if(na>nb){return(2);}
1463    else{return(0);}
1464  }
1465}
1466
1467// sort a list of ideals using idbefid
1468static proc sortlistideals(list L)
1469{
1470  int i; int j; int n;
1471  ideal a; ideal b;
1472  list LL=L;
1473  list NL;
1474  int k; int te;
1475  i=1;
1476  while(size(LL)>0)
1477  {
1478    k=1;
1479    for(j=2;j<=size(LL);j++)
1480    {
1481      te=idbefid(LL[k],LL[j]);
1482      if (te==2){k=j;}
1483    }
1484    NL[size(NL)+1]=LL[k];
1485    n=size(LL);
1486    if (n>1){LL=elimfromlist(LL,k);} else{LL=list();}
1487  }
1488  return(NL);
1489}
1490
1491// Crep
1492// Computes the C-representation of V(N) \ V(M).
1493// input:
1494//    ideal N (null ideal) (not necessarily radical nor maximal)
1495//    ideal M (hole ideal) (not necessarily containing N)
1496// output:
1497//    the list (a,b) of the canonical ideals
1498//    the Crep of V(N) \ V(M)
1499// Assumed to be called in the ring Q[a] or Q[x]
1500proc Crep(ideal N, ideal M)
1501"USAGE:  Crep(ideal N,ideal M);
1502        ideal N (null ideal) (not necessarily radical nor
1503        maximal) in Q[a]. (a=parameters, x=variables).
1504        ideal M (hole ideal) (not necessarily containing N)
1505        in Q[a]. To be called in a ring Q[a][x] or a ring Q[a].
1506        But the ideals can contain only the parameters
1507        in Q[a].
1508RETURN: The canonical C-representation [P,Q] of the
1509        locally closed set, formed by a pair of radical
1510        ideals with P included in Q, representing the set
1511        V(P) \ V(Q) = V(N) \ V(M)
1512KEYWORDS: locally closed set; canoncial form
1513EXAMPLE:  Crep; shows an example"
1514{
1515  int te;
1516  def RR=basering;
1517  def Rx=ringlist(RR);
1518  if(size(Rx[1])==4)
1519  { te=1;
1520    def P=ring(Rx[1]);
1521  }
1522  if(te==1)
1523  {
1524    setring(P); ideal Np=imap(RR,N); ideal Mp=imap(RR,M);
1525  }
1526  else {te=0; def Np=N; def Mp=M;}
1527  def La=Crep0(Np,Mp);
1528  if(size(La)==0)
1529  {
1530    if(te==1) {setring(RR); list LL;}
1531    if(te==0){list LL;}
1532    return(LL);
1533  }
1534  else
1535  {
1536    if(te==1) {setring(RR); def LL=imap(P,La);}
1537    if(te==0){def LL=La;}
1538  return(LL);
1539  }
1540}
1541example
1542{ "EXAMPLE:"; echo = 2;
1543  short=0;
1544  if(defined(R)){kill R;}
1545  ring R=0,(a,b,c),lp;
1546  ideal p=a*b;
1547  ideal q=a,b-2;
1548
1549  // C-representation of V(p) \ V(q)
1550  Crep(p,q);
1551}
1552
1553// Crep0
1554// Computes the C-representation of V(N) \ V(M).
1555// input:
1556//    ideal N (null ideal) (not necessarily radical nor maximal)
1557//    ideal M (hole ideal) (not necessarily containing N)
1558// output:
1559//    the list (a,b) of the canonical ideals
1560//    the Crep0 of V(N) \ V(M)
1561// Assumed to be called in a ring Q[x] (example @P)
1562static proc Crep0(ideal N, ideal M)
1563{
1564  list l;
1565  ideal Np=std(N);
1566  if (equalideals(Np,ideal(1)))
1567  {
1568    l=ideal(1),ideal(1);
1569    return(l);
1570  }
1571  int i;
1572  list L;
1573  ideal Q=Np+M;
1574  ideal P=ideal(1);
1575  L=minGTZ(Np);
1576  for(i=1;i<=size(L);i++)
1577  {
1578    L[i]=std(L[i]);
1579    if(idcontains(L[i],Q)==0)
1580    {
1581      P=intersect(P,L[i]);
1582    }
1583  }
1584  P=std(P);
1585  Q=std(radical(Q+P));
1586  if(equalideals(P,Q)){return(l);}
1587  list T=P,Q;
1588  return(T);
1589}
1590
1591// Prep
1592// Computes the P-representation of V(N) \ V(M).
1593// input:
1594//    ideal N (null ideal) (not necessarily radical nor maximal)
1595//    ideal M (hole ideal) (not necessarily containing N)
1596// output:
1597//    the ((p_1,(p_11,p_1k_1)),..,(p_r,(p_r1,p_rk_r)));
1598//    the Prep of V(N) \ V(M)
1599// Assumed to be called in the ring ring Q[a][x]. But the data must only contain parameters.
1600proc Prep(ideal N, ideal M)
1601"USAGE: Prep(ideal N,ideal M);
1602       ideal N (null ideal) (not necessarily radical nor
1603       maximal) in Q[a]. (a=parameters, x=variables).
1604       ideal M (hole ideal) (not necessarily containing N)
1605       in Q[a]. To be called in a ring Q[a][x] or a ring
1606       Q[a]. But the ideals can contain only the
1607       parameters in Q[a].
1608RETURN: The canonical P-representation of the locally closed
1609       set V(N) \ V(M)
1610       Output: [Comp_1, .. , Comp_s ] where
1611       Comp_i=[p_i,[p_i1,..,p_is_i]]
1612KEYWORDS: locally closed set; canoncial form
1613EXAMPLE:  Prep; shows an example"
1614{
1615  int te;
1616  def RR=basering;
1617  def Rx=ringlist(RR);
1618  if(size(Rx[1])==4)
1619  {
1620    def P=ring(Rx[1]);
1621    te=1; setring(P); ideal Np=imap(RR,N); ideal Mp=imap(RR,M);
1622  }
1623  else {te=0; def Np=N; def Mp=M;}
1624  def La=Prep0(Np,Mp);
1625  if(te==1) {setring(RR); def LL=imap(P,La); }
1626  if(te==0){def LL=La;}
1627  return(LL);
1628}
1629example
1630{ "EXAMPLE:"; echo = 2;
1631  short=0;
1632  if(defined(R)){kill R;}
1633  ring R=0,(a,b,c),lp;
1634  ideal p=a*b;;
1635  ideal q=a,b-1;
1636
1637  // P-representation of V(p) \ V(q)
1638  Prep(p,q);
1639}
1640
1641// Prep0
1642// Computes the P-representation of V(N) \ V(M).
1643// input:
1644//    ideal N (null ideal) (not necessarily radical nor maximal)
1645//    ideal M (hole ideal) (not necessarily containing N)
1646// output:
1647//    the ((p_1,(p_11,p_1k_1)),..,(p_r,(p_r1,p_rk_r)));
1648//    the Prep of V(N) \ V(M)
1649// Assumed to be called in a ring Q[x] (example @P)
1650static proc Prep0(ideal N, ideal M)
1651{
1652  int te;
1653  if (N[1]==1)
1654  {
1655    return(list(list(ideal(1),list(ideal(1)))));
1656  }
1657  int i; int j; list L0;
1658  list Ni=minGTZ(N);
1659  list prep;
1660  for(j=1;j<=size(Ni);j++)
1661  {
1662    option(redSB);
1663    Ni[j]=std(Ni[j]);
1664  }
1665  list Mij;
1666  for (i=1;i<=size(Ni);i++)
1667  {
1668    Mij=minGTZ(Ni[i]+M);
1669    for(j=1;j<=size(Mij);j++)
1670    {
1671      option(redSB);
1672      Mij[j]=std(Mij[j]);
1673    }
1674    if ((size(Mij)==1) and (equalideals(Ni[i],Mij[1])==1)){;}
1675    else
1676    {
1677        prep[size(prep)+1]=list(Ni[i],Mij);
1678    }
1679  }
1680  //"T_before="; prep;
1681  if (size(prep)==0){prep=list(list(ideal(1),list(ideal(1))));}
1682  //"T_Prep="; prep;
1683  //def Lout=CompleteA(prep,prep);
1684  //"T_Lout="; Lout;
1685  return(prep);
1686}
1687
1688// PtoCrep
1689// Computes the C-representation from the P-representation.
1690// input:
1691//    list ((p_1,(p_11,p_1k_1)),..,(p_r,(p_r1,p_rk_r)));
1692//         the P-representation of V(N) \ V(M)
1693// output:
1694//    list (ideal ida, ideal idb)
1695//    the C-representaion of V(N) \ V(M) = V(ida) \ V(idb)
1696// Assumed to be called in the ring Q[a] or Q[x]
1697proc PtoCrep(list L)
1698"USAGE: PtoCrep(list L)
1699       list L=  [ Comp_1, .. , Comp_s ] where
1700       list Comp_i=[p_i,[p_i1,..,p_is_i] ], is the
1701       P-representation of a locally closed set
1702       V(N) \ V(M). To be called in a ring Q[a][x]
1703       or a ring Q[a]. But the ideals can contain
1704       only the parameters in Q[a].
1705RETURN:The canonical C-representation [P,Q] of the
1706       locally closed set. A pair of radical ideals with
1707       P included in Q, representing the
1708       set V(P) \ V(Q)
1709KEYWORDS: locally closed set; canoncial form
1710EXAMPLE:  PtoCrep; shows an example"
1711{
1712  int te;
1713  def RR=basering;
1714  def Rx=ringlist(RR);
1715  if(size(Rx[1])==0){return(PtoCrep0(L));}
1716  else
1717  {
1718    def P=ring(Rx[1]);
1719    setring(P);
1720    list Lp=imap(RR,L);
1721    def LLp=PtoCrep0(Lp);
1722    setring(RR);
1723    def LL=imap(P,LLp);
1724    return(LL);
1725  }
1726}
1727example
1728{
1729echo = 2;
1730//EXAMPLE:
1731
1732if(defined(R)){kill R;}
1733ring R=0,(a,b,c),lp;
1734short=0;
1735
1736ideal p=a*(a^2+b^2+c^2-25);
1737ideal q=a*(a-3),b-4;
1738
1739// C-representaion of V(p) \ V(q)
1740def Cr=Crep(p,q);
1741Cr;
1742
1743// P-representation of V(p) \ V(q)
1744def L=Prep(p,q);
1745L;
1746
1747PtoCrep(L);
1748}
1749
1750// PtoCrep0
1751// Computes the C-representation from the P-representation.
1752// input:
1753//    list ((p_1,(p_11,p_1k_1)),..,(p_r,(p_r1,p_rk_r)));
1754//         the P-representation of V(N) \ V(M)
1755// output:
1756//    list (ideal ida, ideal idb)
1757//    the C-representation of V(N) \ V(M) = V(ida) \ V(idb)
1758// Assumed to be called in a ring Q[x] (example @P)
1759static proc PtoCrep0(list L)
1760{
1761  int te=0;
1762  def Lp=L;
1763  int i; int j;
1764  ideal ida=ideal(1); ideal idb=ideal(1); list Lb; ideal N;
1765  for (i=1;i<=size(Lp);i++)
1766  {
1767    option(returnSB);
1768    //"T_Lp[i]="; Lp[i];
1769    N=Lp[i][1];
1770    Lb=Lp[i][2];
1771    //"T_Lb="; Lb;
1772    ida=intersect(ida,N);
1773    for(j=1;j<=size(Lb);j++)
1774    {
1775      idb=intersect(idb,Lb[j]);
1776    }
1777  }
1778  //idb=radical(idb);
1779  def La=list(ida,idb);
1780  return(La);
1781}
1782
1783// input: F a parametric ideal in Q[a][x]
1784// output: a disjoint and reduced Groebner System.
1785//      It uses Kapur-Sun-Wang algorithm, and with the options
1786//      can compute the homogenization before  (('can',0) or ( 'can',1))
1787//      and dehomogenize the result.
1788proc cgsdr(ideal F, list #)
1789"USAGE: cgsdr(ideal F);
1790       F: ideal in Q[a][x] (a=parameters, x=variables) to be
1791       discussed. Computes a disjoint, reduced Comprehensive
1792       Groebner System (CGS). cgsdr is the starting point of
1793       the fundamental routine grobcov.
1794       The basering R, must be of the form Q[a][x],
1795       (a=parameters, x=variables),
1796       and should be defined previously.
1797RETURN: Returns a list T describing a reduced and disjoint
1798       Comprehensive Groebner System (CGS). The output
1799       is a list of  (full,hole,basis), where the  ideals
1800       full and hole represent the segment V(full) \ V(hole).
1801       With option (\"out\",0) the segments are grouped
1802       by leading power products (lpp) of the reduced
1803       Groebner basis and given in P-representation.
1804       The returned list is of the form:
1805        [ [lpp, [num,basis,segment],...,
1806                [num,basis,segment],lpph],  ... ,
1807          [lpp, [num,basis,segment],...,
1808                [num,basis,segment],lpph] ].
1809       The bases are the reduced Groebner bases (after
1810       normalization) for each point of the corresponding
1811       segment. The third element lpph of each lpp
1812       segment is the lpp of the homogenized ideal
1813       used ideal in the CGS  as a string, that
1814       is shown only when option  (\"can\",1) is used.
1815       With option (\"can\",0) the homogenized basis is used.
1816       With option (\"can\",1) the homogenized ideal is used.
1817       With option (\"can\",2) the given basis is used.
1818       With option (\"out\",1) (default) only KSW is applied and
1819       segments are given as difference of varieties and are
1820       not grouped The returned list is of the form:
1821       [[E,N,B],..[E,N,B]]
1822       E is the top variety
1823       N is the hole variety.
1824       Segment = V(E) \ V(N)
1825       B is the reduced Groebner basis
1826OPTIONS:  An option is a pair of arguments: string, integer.
1827       To modify the default options, pairs of arguments
1828       -option name, value- of valid options must be
1829       added to the call. Inside grobcov the default option
1830       is \"can\",1. It can be used also with option
1831       \"can\",0 but then the output is not the canonical
1832       Groebner Cover. grobcov cannot be used with
1833       option \"can\",2.
1834       When cgsdr is called directly, the options are
1835       \"can\",0-1-2: The default value is \"can\",2.
1836       In this case no homogenization is done. With option
1837       (\"can\",0) the given basis is homogenized,
1838       and with option (\"can\",1) the whole given ideal
1839       is homogenized before computing the cgs
1840       and dehomogenized after.
1841       With option (\"can\",0) the homogenized basis is used.
1842       With option (\"can\",1) the homogenized ideal is used.
1843       With option (\"can\",2) the given basis is used.
1844       \"null\",ideal E: The default is (\"null\",ideal(0)).
1845       \"nonnull\",ideal N: The default (\"nonnull\",ideal(1)).
1846       When options \"null\" and/or \"nonnull\" are given,
1847       then the parameter space is restricted to V(E) \ V(N).
1848       \"comment\",0-1: The default is (\"comment\",0).
1849       Setting (\"comment\",1) will provide information
1850       about the development of the computation.
1851       \"out\",0-1: (default is 1) the output segments are
1852       given as as difference of varieties.
1853       With option \"out\",0 the output segments are
1854       given in P-representation and  the segments
1855       grouped by lpp.
1856       With options (\"can\",0) and (\"can\",1) the option
1857       (\"out\",1) is set to (\"out\",0) because
1858       it is not compatible.
1859       One can give none or whatever of these options.
1860       With the default options (\"can\",2,\"out\",1),
1861       only the Kapur-Sun-Wang algorithm is computed.
1862       The algorithm used is:
1863          D. Kapur, Y. Sun, and D.K. Wang \"A New Algorithm
1864          for  Computing Comprehensive Groebner Systems\".
1865          Proceedings of ISSAC'2010, ACM Press, (2010), 29-36.
1866       It is very efficient but is only the starting point
1867       for the computation of grobcov.
1868       When grobcov is computed, the call to cgsdr
1869       inside uses specific options that are
1870       more expensive (\"can\",0-1,\"out\",0).
1871KEYWORDS: CGS; disjoint; reduced; Comprehensive Groebner System
1872EXAMPLE:  cgsdr; shows an example"
1873{
1874  int te;
1875  def RR=basering;
1876  def Rx=ringlist(RR);
1877  def P=ring(Rx[1]);
1878  // if(size(Rx[1])==4){te=1; Rx[1]=0; def D=ring(Rx); def RP=D+P;}
1879  // else{te=0;} //setglobalrings();}
1880  // INITIALIZING OPTIONS
1881  int i; int j;
1882  def E=ideal(0);
1883  def N=ideal(1);
1884  int comment=0;
1885  int can=2;
1886  int out=1;
1887  poly f;
1888  ideal B;
1889  int start=timer;
1890  list L=#;
1891  for(i=1;i<=size(L) div 2;i++)
1892  {
1893    if(L[2*i-1]=="null"){E=L[2*i];}
1894    else
1895    {
1896      if(L[2*i-1]=="nonnull"){N=L[2*i];}
1897      else
1898      {
1899        if(L[2*i-1]=="comment"){comment=L[2*i];}
1900        else
1901        {
1902          if(L[2*i-1]=="can"){can=L[2*i];}
1903          else
1904          {
1905            if(L[2*i-1]=="out"){out=L[2*i];}
1906          }
1907        }
1908      }
1909    }
1910  }
1911  //if(can==2){out=1;}
1912  B=F;
1913  if ((printlevel) and (comment==0)){comment=printlevel;}
1914  if((can<2) and (out>0)){"Option out,1 is not compatible with can,0,1"; out=0;}
1915  // DEFINING OPTIONS
1916  list LL;
1917  LL[1]="can";     LL[2]=can;
1918  LL[3]="comment"; LL[4]=comment;
1919  LL[5]="out";     LL[6]=out;
1920  LL[7]="null";    LL[8]=E;
1921  LL[9]="nonnull"; LL[10]=N;
1922  if(comment>=1)
1923  {
1924    " "; string("Begin cgsdr with options: ",LL);
1925  }
1926  int ish;
1927  for (i=1;i<=size(B);i++){ish=ishomog(B[i]); if(ish==0){break;};}
1928  if (ish)
1929  {
1930    if(comment>0){" "; string("The given system is homogneous");}
1931    def GS=KSW(B,LL);
1932    //can=0;
1933  }
1934  else
1935  {
1936  // ACTING DEPENDING ON OPTIONS
1937  if(can==2)
1938  {
1939    // WITHOUT HOMOHGENIZING
1940    if(comment>0){" "; string("Option of cgsdr: do not homogenize");}
1941    def GS=KSW(B,LL);
1942    // setglobalrings();
1943  }
1944  else
1945  {
1946    if(can==1)
1947    {
1948      // COMPUTING THE HOMOGOENIZED IDEAL
1949      if(comment>0){" "; string("Homogenizing the whole ideal: option can=1");}
1950      list RRL=ringlist(RR);
1951      RRL[3][1][1]="dp";
1952      def Pa=ring(RRL[1]);
1953      list Lx;
1954      Lx[1]=0;
1955      Lx[2]=RRL[2]+RRL[1][2];
1956      Lx[3]=RRL[1][3];
1957      Lx[4]=RRL[1][4];
1958      RRL[1]=0;
1959      def D=ring(RRL);
1960      def RP=D+Pa;
1961      setring(RP);
1962      def B1=imap(RR,B);
1963      option(redSB);
1964      if(comment>0){" ";string("Basis before computing its std basis="); B1;}
1965      B1=std(B1);
1966      if(comment>0){" ";string("Basis after computing its std basis="); B1;}
1967      setring(RR);
1968      def B2=imap(RP,B1);
1969    }
1970    else
1971    { // (can=0)
1972       if(comment>0){" "; string( "Homogenizing the basis: option can=0");}
1973      def B2=B;
1974    }
1975    // COMPUTING HOMOGENIZED CGS
1976    poly @t;
1977    ring H=0,@t,dp;
1978    def RH=RR+H;
1979    setring(RH);
1980    // setglobalrings();
1981    def BH=imap(RR,B2);
1982    def LH=imap(RR,LL);
1983    //"T_BH="; BH;
1984    //"T_LH="; LH;
1985    for (i=1;i<=size(BH);i++)
1986    {
1987      BH[i]=homog(BH[i],@t);
1988    }
1989    if (comment>0){" "; string("Homogenized system = "); BH;}
1990    def RHx=ringlist(RH);
1991    def PH=ring(RHx[1]);
1992    RHx[1]=0;
1993    def DH=ring(RHx);
1994    def RPH=DH+PH;
1995    def GSH=KSW(BH,LH);
1996    //"T_GSH="; GSH;
1997    //setglobalrings();
1998    // DEHOMOGENIZING THE RESULT
1999    if(out==0)
2000    {
2001      for (i=1;i<=size(GSH);i++)
2002      {
2003        GSH[i][1]=subst(GSH[i][1],@t,1);
2004        for(j=1;j<=size(GSH[i][2]);j++)
2005        {
2006          GSH[i][2][j][2]=subst(GSH[i][2][j][2],@t,1);
2007        }
2008      }
2009    }
2010    else
2011    {
2012      for (i=1;i<=size(GSH);i++)
2013      {
2014        GSH[i][3]=subst(GSH[i][3],@t,1);
2015        GSH[i][7]=subst(GSH[i][7],@t,1);
2016      }
2017    }
2018    setring(RR);
2019    def GS=imap(RH,GSH);
2020    }
2021    // setglobalrings();
2022    if(out==0)
2023    {
2024      for (i=1;i<=size(GS);i++)
2025      {
2026        GS[i][1]=postredgb(mingb(GS[i][1]));
2027        for(j=1;j<=size(GS[i][2]);j++)
2028        {
2029          GS[i][2][j][2]=postredgb(mingb(GS[i][2][j][2]));
2030        }
2031      }
2032    }
2033    else
2034    {
2035      for (i=1;i<=size(GS);i++)
2036      {
2037        if(GS[i][2]==1)
2038        {
2039          GS[i][3]=postredgb(mingb(GS[i][3]));
2040          if (typeof(GS[i][7])=="ideal")
2041          { GS[i][7]=postredgb(mingb(GS[i][7]));}
2042        }
2043      }
2044    }
2045  }
2046  return(GS);
2047}
2048example
2049{
2050echo = 2;
2051// EXAMPLE:
2052// Casas conjecture for degree 4:
2053
2054// Casas-Alvero conjecture states that on a field of characteristic 0,
2055// if a polynomial of degree n in x has a common root whith each of its
2056// n-1 derivatives (not assumed to be the same), then it is of the form
2057// P(x) = k(x + a)^n, i.e. the common roots must all be the same.
2058
2059if(defined(R)){kill R;}
2060ring R=(0,a0,a1,a2,a3,a4),(x1,x2,x3),dp;
2061short=0;
2062
2063ideal F=x1^4+(4*a3)*x1^3+(6*a2)*x1^2+(4*a1)*x1+(a0),
2064         x1^3+(3*a3)*x1^2+(3*a2)*x1+(a1),
2065         x2^4+(4*a3)*x2^3+(6*a2)*x2^2+(4*a1)*x2+(a0),
2066         x2^2+(2*a3)*x2+(a2),
2067         x3^4+(4*a3)*x3^3+(6*a2)*x3^2+(4*a1)*x3+(a0),
2068         x3+(a3);
2069
2070cgsdr(F);
2071}
2072
2073// input:  internal routine called by cgsdr at the end to group the
2074//            lpp segments and improve the output
2075// output: grouped segments by lpp obtained in cgsdr
2076static proc grsegments(list T)
2077{
2078  int i;
2079  list L;
2080  list lpp;
2081  list lp;
2082  list ls;
2083  int n=size(T);
2084  lpp[1]=T[n][1];
2085  L[1]=list(lpp[1],list(list(T[n][2],T[n][3],T[n][4])));
2086  if (n>1)
2087  {
2088    for (i=1;i<=size(T)-1;i++)
2089    {
2090      lp=memberpos(T[n-i][1],lpp);
2091      if(lp[1]==1)
2092      {
2093        ls=L[lp[2]][2];
2094        ls[size(ls)+1]=list(T[n-i][2],T[n-i][3],T[n-i][4]);
2095        L[lp[2]][2]=ls;
2096      }
2097      else
2098      {
2099        lpp[size(lpp)+1]=T[n-i][1];
2100        L[size(L)+1]=list(T[n-i][1],list(list(T[n-i][2],T[n-i][3],T[n-i][4])));
2101      }
2102    }
2103  }
2104  return(L);
2105}
2106
2107// LCUnion
2108// Given a list of the P-representations of locally closed segments
2109// for which we know that the union is also locally closed
2110// it returns the P-representation of its union
2111// input:  L list of segments in P-representation
2112//      ((p_j^i,(p_j1^i,...,p_jk_j^i | j=1..t_i)) | i=1..s )
2113//      where i represents a segment
2114// output: P-representation of the union
2115//       ((P_j,(P_j1,...,P_jk_j | j=1..t)))
2116static proc LCUnion(list LL)
2117{
2118  def RR=basering;
2119  def Rx=ringlist(RR);
2120  def PP=ring(Rx[1]);
2121  setring(PP);
2122  def L=imap(RR,LL);
2123  int i; int j; int k; list H; list C; list T;
2124  list L0; list P0; list P; list Q0; list Q;
2125  for (i=1;i<=size(L);i++)
2126  {
2127    for (j=1;j<=size(L[i]);j++)
2128    {
2129      P0[size(P0)+1]=L[i][j][1];
2130      L0[size(L0)+1]=intvec(i,j);
2131    }
2132  }
2133  Q0=selectminideals(P0);
2134  for (i=1;i<=size(Q0);i++)
2135  {
2136    Q[i]=L0[Q0[i]];
2137    P[i]=L[Q[i][1]][Q[i][2]];
2138  }
2139  //"T_P="; P;
2140  // P is the list of the maximal components of the union
2141  //   with the corresponding initial holes.
2142  // Q is the list of intvec positions in L of the first element of the P's
2143  //   Its elements give (num of segment, num of max component (=min ideal))
2144  for (k=1;k<=size(Q);k++)
2145  {
2146    H=P[k][2]; // holes of P[k][1]
2147    for (i=1;i<=size(L);i++)
2148    {
2149      if (i!=Q[k][1])
2150      {
2151        for (j=1;j<=size(L[i]);j++)
2152        {
2153          C[size(C)+1]=L[i][j];
2154        }
2155      }
2156    }
2157    T[size(T)+1]=list(Q[k],P[k][1],addpart(H,C));
2158  }
2159  setring(RR);
2160  def TT=imap(PP,T);
2161  return(TT);
2162}
2163
2164// LCUnionN
2165// Given a list of the P-representations of locally closed segments
2166// for which we know that the union is also locally closed
2167// it returns the P-representation of its union
2168// input:  L list of segments in P-representation
2169//      ((p_j^i,(p_j1^i,...,p_jk_j^i | j=1..t_i)) | i=1..s )
2170//      where i represents a segment
2171// output: P-representation of the union
2172//       ((P_j,(P_j1,...,P_jk_j | j=1..t)))
2173static proc LCUnionN(list L)
2174{
2175  int i; int j; int k; list H; list C; list T;
2176  list L0; list P0; list P; list Q0; list Q;
2177  //"T_L="; L;
2178  for (i=1;i<=size(L);i++)
2179  {
2180    P0[size(P0)+1]=L[i][1];
2181    for (j=1;j<=size(L[i]);j++)
2182    {
2183      L0[size(L0)+1]=intvec(i,j);
2184    }
2185  }
2186  //"T_P0="; P0;
2187  Q0=selectminideals(P0);
2188  //"T_Q0="; Q0;
2189  for (i=1;i<=size(Q0);i++)
2190  {
2191    //Q[i]=L0[Q0[i]];
2192    P[i]=L[Q0[i][1]];// [Q[i][2]];
2193  }
2194  //"T_P="; P;
2195  // P is the list of the maximal components of the union
2196  //   with the corresponding initial holes.
2197  // Q is the list of intvec positions in L of the first element of the P's
2198  //   Its elements give (num of segment, num of max component (=min ideal))
2199  // list C;
2200  for (k=1;k<=size(Q0);k++)
2201  {
2202    kill C; list C;
2203    H=P[k][2]; // holes of P[k][1]
2204    for (i=1;i<=size(L);i++)
2205    {
2206      if (i!=Q0[k]) // (i!=Q0[k])
2207      {
2208        //for (j=1;j<=size(L[i]);j++)
2209        //{
2210          C[size(C)+1]=L[i];
2211        //}
2212      }
2213    }
2214    T[size(T)+1]=list(P[k][1],addpart(H,C)); // Q0[k],
2215  }
2216  return(T);
2217}
2218
2219
2220// Auxiliary routine
2221// called by LCUnion to modify the holes of a primepart of the union
2222// by the addition of the segments that do not correspond to that part
2223// Works on Q[a] ring.
2224// Input:
2225//   H=(p_i1,..,p_is) the holes of a component to be transformed by the addition of
2226//        the segments C that do not correspond to that component
2227//   C=((q_1,(q_11,..,q_1l_1),pos1),..,(q_k,(q_k1,..,q_kl_k),posk))
2228// posi=(i,j) position of the component
2229//        the list of segments to be added to the holes
2230static proc addpart(list H, list C)
2231{
2232  list Q; int i; int j; int k; int l; int t; int t1;
2233  Q=H; intvec notQ; list QQ; list addq;
2234  //          plus those of the components added to the holes.
2235  ideal q;
2236  i=1;
2237  while (i<=size(Q))
2238  {
2239    if (memberpos(i,notQ)[1]==0)
2240    {
2241      q=Q[i];
2242      t=1; j=1;
2243      while ((t) and (j<=size(C)))
2244      {
2245        if (equalideals(q,C[j][1]))
2246        {
2247          t=0;
2248          for (k=1;k<=size(C[j][2]);k++)
2249          {
2250            t1=1;
2251            l=1;
2252            while((t1) and (l<=size(Q)))
2253            {
2254              if ((l!=i) and (memberpos(l,notQ)[1]==0))
2255              {
2256                if (idcontains(C[j][2][k],Q[l]))
2257                {
2258                  t1=0;
2259                }
2260              }
2261              l++;
2262            }
2263            if (t1)
2264            {
2265              addq[size(addq)+1]=C[j][2][k];
2266            }
2267          }
2268          if((size(notQ)==1) and (notQ[1]==0)){notQ[1]=i;}
2269          else {notQ[size(notQ)+1]=i;}
2270        }
2271        j++;
2272      }
2273      if (size(addq)>0)
2274      {
2275        for (k=1;k<=size(addq);k++)
2276        {
2277          Q[size(Q)+1]=addq[k];
2278        }
2279        kill addq;
2280        list addq;
2281      }
2282    }
2283    i++;
2284  }
2285  for (i=1;i<=size(Q);i++)
2286  {
2287    if(memberpos(i,notQ)[1]==0)
2288    {
2289      QQ[size(QQ)+1]=Q[i];
2290    }
2291  }
2292  if (size(QQ)==0){QQ[1]=ideal(1);}
2293  return(addpartfine(QQ,C));
2294}
2295
2296// Auxiliary routine called by addpart to finish the modification of the holes of a primepart
2297// of the union by the addition of the segments that do not correspond to
2298// that part.
2299// Works on Q[a] ring.
2300static proc addpartfine(list H, list C0)
2301{
2302  //"T_H="; H;
2303  int i; int j; int k; int te; intvec notQ; int l; list sel;
2304  intvec jtesC;
2305  if ((size(H)==1) and (equalideals(H[1],ideal(1)))){return(H);}
2306  if (size(C0)==0){return(H);}
2307  list newQ; list nQ; list Q; list nQ1; list Q0;
2308  def Q1=H;
2309  //Q1=sortlistideals(Q1,idbefid);
2310  def C=C0;
2311  while(equallistideals(Q0,Q1)==0)
2312  {
2313    Q0=Q1;
2314    i=0;
2315    Q=Q1;
2316    kill notQ; intvec notQ;
2317    while(i<size(Q))
2318    {
2319      i++;
2320      for(j=1;j<=size(C);j++)
2321      {
2322        te=idcontains(Q[i],C[j][1]);
2323        if(te)
2324        {
2325          for(k=1;k<=size(C[j][2]);k++)
2326          {
2327            if(idcontains(Q[i],C[j][2][k]))
2328            {
2329              te=0; break;
2330            }
2331          }
2332          if (te)
2333          {
2334            if ((size(notQ)==1) and (notQ[1]==0)){notQ[1]=i;}
2335            else{notQ[size(notQ)+1]=i;}
2336            kill newQ; list newQ;
2337            for(k=1;k<=size(C[j][2]);k++)
2338            {
2339              nQ=minGTZ(Q[i]+C[j][2][k]);
2340              for(l=1;l<=size(nQ);l++)
2341              {
2342                option(redSB);
2343                nQ[l]=std(nQ[l]);
2344                newQ[size(newQ)+1]=nQ[l];
2345              }
2346            }
2347            sel=selectminideals(newQ);
2348            kill nQ1; list nQ1;
2349            for(l=1;l<=size(sel);l++)
2350            {
2351              nQ1[l]=newQ[sel[l]];
2352            }
2353            newQ=nQ1;
2354            for(l=1;l<=size(newQ);l++)
2355            {
2356              Q[size(Q)+1]=newQ[l];
2357            }
2358            break;
2359          }
2360        }
2361      }
2362    }
2363    kill Q1; list Q1;
2364    for(i=1;i<=size(Q);i++)
2365    {
2366      if(memberpos(i,notQ)[1]==0)
2367      {
2368        Q1[size(Q1)+1]=Q[i];
2369      }
2370    }
2371    sel=selectminideals(Q1);
2372    kill nQ1; list nQ1;
2373    for(l=1;l<=size(sel);l++)
2374    {
2375      nQ1[l]=Q1[sel[l]];
2376    }
2377    Q1=nQ1;
2378  }
2379  if(size(Q1)==0){Q1=ideal(1),ideal(1);}
2380  return(Q1);
2381}
2382
2383// Auxiliary rutine for gcover
2384// Deciding if combine is needed
2385// input: list LCU=( (basis1, p_1, (p11,..p1s1)), .. (basisr, p_r, (pr1,..prsr))
2386// output: (tes); if tes==1 then combine is needed, else not.
2387static proc needcombine(list LCU,ideal N)
2388{
2389  //"Deciding if combine is needed";;
2390  ideal BB;
2391  int tes=0; int m=1; int j; int k; poly sp;
2392  while((tes==0) and (m<=size(LCU[1][1])))
2393  {
2394    j=1;
2395    while((tes==0) and (j<=size(LCU)))
2396    {
2397      k=1;
2398      while((tes==0) and (k<=size(LCU)))
2399      {
2400        if(j!=k)
2401        {
2402          sp=pnormalf(pspol(LCU[j][1][m],LCU[k][1][m]),LCU[k][2],N);
2403          if(sp!=0){tes=1;}
2404        }
2405        k++;
2406      }
2407      j++;
2408    }
2409    if(tes){break;}
2410    m++;
2411  }
2412  return(tes);
2413}
2414
2415// Auxiliary routine
2416// precombine
2417// input:  L: list of ideals (works in @P)
2418// output: F0: ideal of polys. F0[i] is a poly in the intersection of
2419//             all ideals in L except in the ith one, where it is not.
2420//             L=(p1,..,ps);  F0=(f1,..,fs);
2421//             F0[i] \in intersect_{j#i} p_i
2422static proc precombine(list L)
2423{
2424  int i; int j; int tes;
2425  def RR=basering;
2426  def Rx=ringlist(RR);
2427  def P=ring(Rx[1]);
2428  setring(P);
2429  list L0; list L1; list L2; list L3; ideal F;
2430  L0=imap(RR,L);
2431  L1[1]=L0[1]; L2[1]=L0[size(L0)];
2432  for (i=2;i<=size(L0)-1;i++)
2433  {
2434    L1[i]=intersect(L1[i-1],L0[i]);
2435    L2[i]=intersect(L2[i-1],L0[size(L0)-i+1]);
2436  }
2437  L3[1]=L2[size(L2)];
2438  for (i=2;i<=size(L0)-1;i++)
2439  {
2440    L3[i]=intersect(L1[i-1],L2[size(L0)-i]);
2441  }
2442  L3[size(L0)]=L1[size(L1)];
2443  for (i=1;i<=size(L3);i++)
2444  {
2445    option(redSB); L3[i]=std(L3[i]);
2446  }
2447  for (i=1;i<=size(L3);i++)
2448  {
2449    tes=1; j=0;
2450    while((tes) and (j<size(L3[i])))
2451    {
2452      j++;
2453      option(redSB);
2454      L0[i]=std(L0[i]);
2455      if(reduce(L3[i][j],L0[i],5)!=0){tes=0; F[i]=L3[i][j];}
2456    }
2457    if (tes){"ERROR a polynomial in all p_j except p_i was not found";}
2458  }
2459  setring(RR);
2460  def F0=imap(P,F);
2461  return(F0);
2462}
2463
2464// Auxiliary routine
2465// combine
2466// input: a list of pairs ((p1,P1),..,(pr,Pr)) where
2467//    ideal pi is a prime component
2468//    poly Pi is the polynomial in Q[a][x] on V(pi) \ V(Mi)
2469//    (p1,..,pr) are the prime decomposition of the lpp-segment
2470//    list crep =(ideal ida,ideal idb): the Crep of the segment.
2471//    list Pci of the intersecctions of all pj except the ith one
2472// output:
2473//    poly P on an open and dense set of V(p_1 int ... p_r)
2474static proc combine(list L, ideal F)
2475{
2476  // ATTENTION REVISE AND USE Pci and F
2477  int i; poly f;
2478  f=0;
2479  for(i=1;i<=size(L);i++)
2480  {
2481    f=f+F[i]*L[i][2];
2482  }
2483//   f=elimconstfac(f);
2484  f=primepartZ(f);
2485  return(f);
2486}
2487
2488// Central routine for grobcov: ideal F is assumed to be homogeneous
2489// gcover
2490// input: ideal F: a generating set of a homogeneous ideal in Q[a][x]
2491//    list #: optional
2492// output: the list
2493//   S=((lpp, generic basis, Prep, Crep),..,(lpp, generic basis, Prep, Crep))
2494//      where a Prep is ( (p1,(p11,..,p1k_1)),..,(pj,(pj1,..,p1k_j)) )
2495//            a Crep is ( ida, idb )
2496static proc gcover(ideal F,list #)
2497{
2498  int i; int j; int k; ideal lpp; list GPi2; list pairspP; ideal B; int ti;
2499  int i1; int tes; int j1; int selind; int i2; //int m;
2500  list prep; list crep; list LCU; poly p; poly lcp; ideal FF;
2501  list lpi;
2502  def RR=basering;
2503  string lpph;
2504  list L=#;
2505  int canop=1;
2506  int extop=1;
2507  int repop=0;
2508  ideal E=ideal(0);;
2509  ideal N=ideal(1);;
2510  int comment;
2511  for(i=1;i<=size(L) div 2;i++)
2512  {
2513    if(L[2*i-1]=="can"){canop=L[2*i];}
2514    else
2515    {
2516      if(L[2*i-1]=="ext"){extop=L[2*i];}
2517      else
2518      {
2519        if(L[2*i-1]=="rep"){repop=L[2*i];}
2520        else
2521        {
2522          if(L[2*i-1]=="null"){E=L[2*i];}
2523          else
2524          {
2525            if(L[2*i-1]=="nonnull"){N=L[2*i];}
2526            else
2527            {
2528              if (L[2*i-1]=="comment"){comment=L[2*i];}
2529            }
2530          }
2531        }
2532      }
2533    }
2534  }
2535  list GS; list GP;
2536  GS=cgsdr(F,L); // "null",NW[1],"nonnull",NW[2],"cgs",CGS,"comment",comment);
2537  int start=timer;
2538  GP=GS;
2539  ideal lppr;
2540  list LL;
2541  list S;
2542  poly sp;
2543  for (i=1;i<=size(GP);i++)
2544  {
2545    kill LL;
2546    list LL;
2547    lpp=GP[i][1];
2548    GPi2=GP[i][2];
2549    lpph=GP[i][3];
2550    kill pairspP; list pairspP;
2551    for(j=1;j<=size(GPi2);j++)
2552    {
2553      pairspP[size(pairspP)+1]=GPi2[j][3];
2554    }
2555    LCU=LCUnion(pairspP);
2556    kill prep; list prep;
2557    kill crep; list crep;
2558    for(k=1;k<=size(LCU);k++)
2559    {
2560      prep[k]=list(LCU[k][2],LCU[k][3]);
2561      B=GPi2[LCU[k][1][1]][2]; // ATENTION last 1 has been changed to [2]
2562      LCU[k][1]=B;
2563    }
2564    //"Deciding if combine is needed";
2565    crep=PtoCrep(prep);
2566    if(size(LCU)>1){tes=1;}
2567    else
2568    {
2569      tes=0;
2570      for(k=1;k<=size(B);k++){B[k]=pnormalf(B[k],crep[1],crep[2]);}
2571    }
2572    if(tes)
2573    {
2574      // combine is needed
2575      kill B; ideal B;
2576      for (j=1;j<=size(LCU);j++)
2577      {
2578        LL[j]=LCU[j][2];
2579      }
2580      FF=precombine(LL);
2581      for (k=1;k<=size(lpp);k++)
2582      {
2583        kill L; list L;
2584        for (j=1;j<=size(LCU);j++)
2585        {
2586          L[j]=list(LCU[j][2],LCU[j][1][k]);
2587        }
2588        B[k]=combine(L,FF);
2589      }
2590    }
2591    for(j=1;j<=size(B);j++)
2592    {
2593      B[j]=pnormalf(B[j],crep[1],crep[2]);
2594    }
2595    S[i]=list(lpp,B,prep,crep,lpph);
2596    if(comment>=1)
2597    {
2598      lpi[size(lpi)+1]=string("[",i,"]");
2599      lpi[size(lpi)+1]=S[i][1];
2600    }
2601  }
2602  if(comment>=1)
2603  {
2604    string("Time in LCUnion + combine = ",timer-start);
2605    if(comment>=2){string("lpp=",lpi)};
2606  }
2607  return(S);
2608}
2609
2610// grobcov
2611// input:
2612//    ideal F: a parametric ideal in Q[a][x], (a=parameters, x=variables).
2613//    list #: (options) list("null",N,"nonnull",W,"can",0-1,ext",0-1, "rep",0-1-2)
2614//            where
2615//            N is the null conditions ideal (if desired)
2616//            W is the ideal of non-null conditions (if desired)
2617//            The value of \"can\" is 1 by default and can be set to 0 if we do not
2618//            need to obtain the canonical GC, but only a GC.
2619//            The value of \"ext\" is 0 by default and so the generic representation
2620//             of the bases is given. It can be set to 1, and then the full
2621//             representation of the bases is given.
2622//            The value of \"rep\" is 0 by default, and then the segments
2623//            are given in canonical P-representation. It can be set to 1
2624//            and then they are given in canonical C-representation.
2625//            If it is set to 2, then both representations are given.
2626// output:
2627//    list S: ((lpp,basis,(idp_1,(idp_11,..,idp_1s_1))), ..
2628//             (lpp,basis,(idp_r,(idp_r1,..,idp_rs_r))) ) where
2629//            each element of S corresponds to a lpp-segment
2630//            given by the lpp, the basis, and the P-representation of the segment
2631proc grobcov(ideal F,list #)
2632"USAGE: grobcov(ideal F[,options]);
2633       F: ideal in Q[a][x] (a=parameters, x=variables) to be
2634       discussed.This is the fundamental routine of the
2635       library. It computes the Groebner Cover of a parametric
2636       ideal F in Q[a][x]. See
2637       A. Montes , M. Wibmer, \"Groebner Bases for Polynomial
2638       Systems with parameters\".
2639       JSC 45 (2010) 1391-1425.)
2640       or the not yet published book
2641       A. Montes. \" The Groebner Cover\" (Discussing
2642       Parametric Polynomial Systems).
2643       The Groebner Cover of a parametric ideal F consist
2644       of a set of pairs(S_i,B_i), where the S_i are disjoint
2645       locally closed segments of the parameter space,
2646       and the B_i are the reducedGroebner bases of the
2647       ideal on every point of S_i. The ideal F must be
2648       defined on a parametric ring Q[a][x] (a=parameters,
2649       x=variables).
2650RETURN: The list  [[lpp_1,basis_1,segment_1],  ...,
2651       [lpp_s,basis_s,segment_s]]
2652       optionally  [[ lpp_1,basis_1,segment_1,lpph_1],  ...,
2653       [lpp_s,basis_s,segment_s,lpph_s]]
2654       The lpp are constant over a segment and
2655       correspond to the set of lpp of the reduced
2656       Groebner basis for each point of the segment.
2657       With option (\"showhom\",1) the lpph will be
2658       shown: The lpph corresponds to the lpp of the
2659       homogenized ideal and is different for each
2660       segment. It is given as a string, and shown
2661       only for information. With the default option
2662       \"can\",1, the segments have different lpph.
2663       Basis: to each element of lpp corresponds
2664       an I-regular function given in full
2665       representation (by option (\"ext\",1)) or
2666       in generic representation (default option (\"ext\",0)).
2667       The I-regular function is the corresponding
2668       element of the reduced Groebner basis for
2669       each point of the segment with the given lpp.
2670       For each point in the segment, the polynomial
2671       or the set of polynomials  representing it,
2672       if they do not specialize to 0, then after
2673       normalization, specializes to the corresponding
2674       element of the reduced Groebner basis.
2675       In the full representation at least one of the
2676       polynomials representing the I-regular function
2677       specializes to non-zero.
2678       With the default option (\"rep\",0) the
2679       representation of the segment is the
2680       P-representation.
2681       With option (\"rep\",1) the representation
2682       of the segment is the C-representation.
2683       With option (\"rep\",2) both representations
2684       of the segment are given.
2685       The P-representation of a segment is of the form
2686       [[p_1,[p_11,..,p_1k1]],..,[p_r,[p_r1,..,p_rkr]]]
2687       representing the segment
2688       Union_i ( V(p_i) \ ( Union_j V(p_ij) ) ),
2689       where the p's are prime ideals.
2690       The C-representation of a segment is of the form
2691       (E,N) representing V(E) \ V(N), and the ideals E
2692       and N are radical and N contains E.
2693OPTIONS: An option is a pair of arguments: string,
2694       integer. To modify the default options, pairs
2695       of arguments -option name, value- of valid options
2696       must be added to the call.
2697       \"null\",ideal E: The default is (\"null\",ideal(0)).
2698       \"nonnull\",ideal N: The default is
2699       (\"nonnull\",ideal(1)).
2700       When options \"null\" and/or \"nonnull\" are given,
2701       then the parameter space is restricted to V(E) \ V(N).
2702       \"can\",0-1: The default is (\"can\",1).
2703       With the default option the homogenized
2704       ideal is computed before obtaining the Groebner
2705       Cover, so that the result is the canonical Groebner
2706       Cover. Setting (\"can\",0) only homogenizes the
2707       basis so the result is not exactly canonical,
2708       but the computation is shorter.
2709       \"ext\",0-1: The default is (\"ext\",0).
2710       With the default (\"ext\",0), only the generic
2711       representation of the bases is computed
2712       (single polynomials, but not specializing
2713       to non-zero for every point of the segment.
2714       With option (\"ext\",1) the full representation
2715       of the bases is computed (possible sheaves)
2716       and sometimes a simpler result is obtained,
2717       but the computation is more time consuming.
2718       \"rep\",0-1-2: The default is (\"rep\",0)
2719       and then the segments are given in canonical
2720       P-representation.
2721       Option (\"rep\",1) represents the segments
2722       in canonical C-representation, and
2723       option (\"rep\",2) gives both representations.
2724       \"comment\",0-3: The default is (\"comment\",0).
2725       Setting \"comment\" higher will provide
2726       information about the development of the
2727       computation.
2728       \"showhom\",0-1: The default is (\"showhom\",0).
2729       Setting \"showhom\",1 will output the set
2730       of lpp of the homogenized ideal of each segment
2731       as last element. One can give none or whatever
2732       of these options.
2733NOTE:    The basering R, must be of the form Q[a][x],
2734       (a=parameters, x=variables), and
2735       should be defined previously. The ideal
2736       must be defined on R.
2737KEYWORDS: Groebner cover; parametric ideal; canonical; discussion of parametric ideal
2738EXAMPLE:  grobcov; shows an example"
2739{
2740  list S; int i; int ish=1; list GBR; list BR; int j; int k;
2741  ideal idp; ideal idq; int s; ideal ext; list SS;
2742  ideal E; ideal N; int canop;  int extop; int repop;
2743  int comment=0; int m;
2744  def RR=basering;
2745  def Rx=ringlist(RR);
2746  def P=ring(Rx[1]);
2747  Rx[1]=0;
2748  def D=ring(Rx);
2749  def RP=D+P;
2750  list L0=#;
2751  list Se;
2752  int out=0;
2753  int showhom=0;
2754  int hom;
2755  L0[size(L0)+1]="res"; L0[size(L0)+1]=ideal(1);
2756  // default options
2757  int start=timer;
2758  E=ideal(0);
2759  N=ideal(1);
2760  canop=1; // canop=0 for homogenizing the basis but not the ideal (not canonical)
2761           // canop=1 for working with the homogenized ideal
2762  repop=0; // repop=0 for representing the segments in Prep
2763           // repop=1 for representing the segments in Crep
2764           // repop=2 for representing the segments in Prep and Crep
2765  extop=0; // extop=0 if only generic representation of the bases are to be computed
2766           // extop=1 if the full representation of the bases are to be computed
2767  for(i=1;i<=size(L0) div 2;i++)
2768  {
2769    if(L0[2*i-1]=="can"){canop=L0[2*i];}
2770    else
2771    {
2772      if(L0[2*i-1]=="ext"){extop=L0[2*i];}
2773      else
2774      {
2775        if(L0[2*i-1]=="rep"){repop=L0[2*i];}
2776        else
2777        {
2778          if(L0[2*i-1]=="null"){E=L0[2*i];}
2779          else
2780          {
2781            if(L0[2*i-1]=="nonnull"){N=L0[2*i];}
2782            else
2783            {
2784              if (L0[2*i-1]=="comment"){comment=L0[2*i];}
2785              else
2786              {
2787                if (L0[2*i-1]=="showhom"){showhom=L0[2*i];}
2788              }
2789            }
2790          }
2791        }
2792      }
2793    }
2794  }
2795  if(not((canop==0) or (canop==1)))
2796  {
2797    string("Option can = ",canop," is not supported. It is changed to can = 1");
2798    canop=1;
2799  }
2800  for(i=1;i<=size(L0) div 2;i++)
2801  {
2802    if(L0[2*i-1]=="can"){L0[2*i]=canop;}
2803  }
2804  if ((printlevel) and (comment==0)){comment=printlevel;}
2805  list LL;
2806  LL[1]="can";     LL[2]=canop;
2807  LL[3]="comment"; LL[4]=comment;
2808  LL[5]="out";     LL[6]=0;
2809  LL[7]="null";    LL[8]=E;
2810  LL[9]="nonnull"; LL[10]=N;
2811  LL[11]="ext";    LL[12]=extop;
2812  LL[13]="rep";    LL[14]=repop;
2813  LL[15]="showhom";    LL[16]=showhom;
2814  if (comment>=1)
2815  {
2816    string("Begin grobcov with options: ",LL);
2817  }
2818  kill S;
2819  def S=gcover(F,LL);
2820  // NOW extendGC
2821  if(extop)
2822  {
2823    S=extendGC(S,LL);
2824  }
2825  // NOW repop and showhom
2826  list Si; list nS;
2827  for(i=1;i<=size(S);i++)
2828  {
2829    if(repop==0){Si=list(S[i][1],S[i][2],S[i][3]);}
2830    if(repop==1){Si=list(S[i][1],S[i][2],S[i][4]);}
2831    if(repop==2){Si=list(S[i][1],S[i][2],S[i][3],S[i][4]);}
2832    if(showhom==1){Si[size(Si)+1]=S[i][5];}
2833    nS[size(nS)+1]=Si;
2834  }
2835  S=nS;
2836  if (comment>=1)
2837  {
2838    string("Time in grobcov = ", timer-start);
2839    string("Number of segments of grobcov = ", size(S));
2840  }
2841  return(S);
2842}
2843example
2844{
2845echo = 2;
2846// EXAMPLE 1:
2847// Casas conjecture for degree 4:
2848
2849// Casas-Alvero conjecture states that on a field of characteristic 0,
2850// if a polynomial of degree n in x has a common root whith each of its
2851// n-1 derivatives (not assumed to be the same), then it is of the form
2852// P(x) = k(x + a)^n, i.e. the common roots must all be the same.
2853
2854if(defined(R)){kill R;}
2855ring R=(0,a0,a1,a2,a3,a4),(x1,x2,x3),dp;
2856short=0;
2857
2858ideal F=x1^4+(4*a3)*x1^3+(6*a2)*x1^2+(4*a1)*x1+(a0),
2859         x1^3+(3*a3)*x1^2+(3*a2)*x1+(a1),
2860         x2^4+(4*a3)*x2^3+(6*a2)*x2^2+(4*a1)*x2+(a0),
2861         x2^2+(2*a3)*x2+(a2),
2862         x3^4+(4*a3)*x3^3+(6*a2)*x3^2+(4*a1)*x3+(a0),
2863         x3+(a3);
2864
2865grobcov(F);
2866
2867// EXAMPLE 2
2868// M. Rychlik robot;
2869// Complexity and Applications of Parametric Algorithms of
2870// Computational Algebraic Geometry.;
2871// In: Dynamics of Algorithms, R. de la Llave, L. Petzold and J. Lorenz eds.;
2872// IMA Volumes in Mathematics and its Applications,
2873// Springer-Verlag 118: 1-29 (2000).;
2874// (18. Mathematical robotics: Problem 4, two-arm robot).
2875
2876if (defined(R)){kill R;}
2877ring R=(0,a,b,l2,l3),(c3,s3,c1,s1), dp;
2878short=0;
2879
2880ideal S12=a-l3*c3-l2*c1,b-l3*s3-l2*s1,c1^2+s1^2-1,c3^2+s3^2-1;
2881S12;
2882
2883grobcov(S12);
2884}
2885
2886// Auxiliary routine called by extendGC
2887// extendpoly
2888// input:
2889//   poly f: a generic polynomial in the basis
2890//   ideal idp: such that ideal(S)=idp
2891//   ideal idq: such that S=V(idp) \ V(idq)
2892////   NW the list of ((N1,W1),..,(Ns,Ws)) of red-rep of the grouped
2893////      segments in the lpp-segment  NO MORE USED
2894// output:
2895proc extendpoly(poly f, ideal idp, ideal idq)
2896"USAGE: extendGC(poly f,ideal p,ideal q);
2897       f is a polynomial in Q[a][x] in generic representation
2898       of an I-regular function F defined on the locally
2899       closed segment S=V(p) \ V(q).
2900       p,q are ideals in Q[a], representing the Crep of
2901       segment S.
2902RETURN: the extended representation of F in S.
2903       It can consist of a single polynomial or a set of
2904       polynomials when needed.
2905NOTE: The basering R, must be of the form Q[a][x],
2906       (a=parameters,x=variables), and should be
2907       defined previously. The ideals must be defined on R.
2908KEYWORDS: Groebner cover; parametric ideal; locally closed set;
2909       parametric ideal; generic representation; full representation;
2910       I-regular function
2911EXAMPLE:  extendpoly; shows an example"
2912{
2913  int te=0;
2914  def RR=basering;
2915  def Rx=ringlist(RR);
2916  def P=ring(Rx[1]);
2917  Rx[1]=0;
2918  def D=ring(Rx);
2919  def RP=D+P;
2920  matrix CC; poly Q; list NewMonoms;
2921  int i;  int j;  poly fout; ideal idout;
2922  list L=monoms(f);
2923  int nummonoms=size(L)-1;
2924  Q=L[1][1];
2925  if (nummonoms==0){return(f);}
2926  for (i=2;i<=size(L);i++)
2927  {
2928    CC=matrix(extendcoef(L[i][1],Q,idp,idq));
2929    NewMonoms[i-1]=list(CC,L[i][2]);
2930  }
2931  if (nummonoms==1)
2932  {
2933    for(j=1;j<=ncols(NewMonoms[1][1]);j++)
2934    {
2935      fout=NewMonoms[1][1][2,j]*L[1][2]+NewMonoms[1][1][1,j]*NewMonoms[1][2];
2936      //fout=pnormalf(fout,idp,W);
2937      if(ncols(NewMonoms[1][1])>1){idout[j]=fout;}
2938    }
2939    if(ncols(NewMonoms[1][1])==1)
2940    {
2941      return(fout);
2942    }
2943    else
2944    {
2945      return(idout);
2946    }
2947  }
2948  else
2949  {
2950    list cfi;
2951    list coefs;
2952    for (i=1;i<=nummonoms;i++)
2953    {
2954      kill cfi; list cfi;
2955      for(j=1;j<=ncols(NewMonoms[i][1]);j++)
2956      {
2957        cfi[size(cfi)+1]=NewMonoms[i][1][2,j];
2958      }
2959      coefs[i]=cfi;
2960    }
2961    def indexpolys=findindexpolys(coefs);
2962    for(i=1;i<=size(indexpolys);i++)
2963    {
2964      fout=L[1][2];
2965      for(j=1;j<=nummonoms;j++)
2966      {
2967        fout=fout+(NewMonoms[j][1][1,indexpolys[i][j]])/(NewMonoms[j][1][2,indexpolys[i][j]])*NewMonoms[j][2];
2968      }
2969      fout=cleardenom(fout);
2970      if(size(indexpolys)>1){idout[i]=fout;}
2971    }
2972    if (size(indexpolys)==1)
2973    {
2974      return(fout);
2975    }
2976    else
2977    {
2978      return(idout);
2979    }
2980  }
2981}
2982example
2983{
2984echo = 2;
2985// EXAMPLE 1
2986
2987if(defined(R)){kill R;}
2988ring R=(0,a1,a2),(x),lp;
2989short=0;
2990
2991poly f=(a1^2-4*a1+a2^2-a2)*x+(a1^4-16*a1+a2^3-4*a2);
2992ideal p=a1*a2;
2993ideal q=a2^2-a2,a1*a2,a1^2-4*a1;
2994
2995extendpoly(f,p,q);
2996
2997// EXAMPLE 2
2998
2999if (defined(R)){kill R;}
3000ring R=(0,a0,b0,c0,a1,b1,c1,a2,b2,c2),(x), dp;
3001short=0;
3002
3003poly f=(b1*a2*c2-c1*a2*b2)*x+(-a1*c2^2+b1*b2*c2+c1*a2*c2-c1*b2^2);
3004ideal p=
3005  (-a0*b1*c2+a0*c1*b2+b0*a1*c2-b0*c1*a2-c0*a1*b2+c0*b1*a2),
3006  (a1^2*c2^2-a1*b1*b2*c2-2*a1*c1*a2*c2+a1*c1*b2^2+b1^2*a2*c2-b1*c1*a2*b2+c1^2*a2^2),
3007  (a0*a1*c2^2-a0*b1*b2*c2-a0*c1*a2*c2+a0*c1*b2^2+b0*b1*a2*c2-b0*c1*a2*b2
3008  - c0*a1*a2*c2+c0*c1*a2^2),
3009  (a0^2*c2^2-a0*b0*b2*c2-2*a0*c0*a2*c2+a0*c0*b2^2+b0^2*a2*c2-b0*c0*a2*b2+c0^2*a2^2),
3010  (a0*a1*c1*c2-a0*b1^2*c2+a0*b1*c1*b2-a0*c1^2*a2+b0*a1*b1*c2-b0*a1*c1*b2
3011  -c0*a1^2*c2+c0*a1*c1*a2),
3012  (a0^2*c1*c2-a0*b0*b1*c2-a0*c0*a1*c2+a0*c0*b1*b2-a0*c0*c1*a2+b0^2*a1*c2
3013  -b0*c0*a1*b2+c0^2*a1*a2),
3014  (a0^2*c1^2-a0*b0*b1*c1-2*a0*c0*a1*c1+a0*c0*b1^2+b0^2*a1*c1-b0*c0*a1*b1+c0^2*a1^2),
3015  (2*a0*a1*b1*c1*c2-a0*a1*c1^2*b2-a0*b1^3*c2+a0*b1^2*c1*b2-a0*b1*c1^2*a2
3016  -b0*a1^2*c1*c2+b0*a1*b1^2*c2-b0*a1*b1*c1*b2+b0*a1*c1^2*a2-c0*a1^2*b1*c2+c0*a1^2*c1*b2);
3017
3018ideal q=
3019  (-a1*c2+c1*a2),
3020  (-a1*b2+b1*a2),
3021  (-a0*c2+c0*a2),
3022  (-a0*b2+b0*a2),
3023  (-a0*c1+c0*a1),
3024  (-a0*b1+b0*a1),
3025  (-a1*b1*c2+a1*c1*b2),
3026  (-a0*b1*c2+a0*c1*b2),
3027  (-a0*b0*c2+a0*c0*b2),
3028  (-a0*b0*c1+a0*c0*b1);
3029
3030extendpoly(f,p,q);
3031}
3032
3033// if L is a list(ideal,ideal)  return 1 else returns 0;
3034static proc typeofCrep(L)
3035{
3036  if(typeof(L)!="list"){return(0);}
3037  if(size(L)!=2){return(0);}
3038  if((typeof(L[1])!="ideal") or (typeof(L[2])!="ideal")){return(0);}
3039  return(1);
3040}
3041
3042// Input. GC the grobcov of an ideal in generic representation of the
3043//        bases computed with option option ("rep",2).
3044// Output The grobcov in full representation.
3045// Option ("comment",1) shows the time.
3046// Can be called from the top
3047proc extendGC(list GC)
3048"USAGE: extendGC(list GC);
3049       list GC must the grobcov of a parametric ideal computed
3050       with option \"rep\",2. It determines the full
3051       representation.
3052       The default option of grobcov provides the bases in
3053       generic representation (the I-regular functions forming
3054       the bases are then given by a single polynomial.
3055       They can specialize to zero for some points of the
3056       segments, but in general, it is sufficient for many
3057       purposes. Nevertheless the I-regular functions allow a
3058       full representation given by a set of polynomials
3059       specializing to the value of the function (after
3060       normalization) or to zero, but at least one of the
3061       polynomials specializes to non-zero. The full
3062       representation can be obtained by computing
3063       the grobcov with option \"ext\",1. (The default
3064       option there is \"ext\",0).
3065       With option \"ext\",1 the computation can be
3066       much more time consuming, but the result can
3067       be simpler.
3068       Alternatively, one can compute the full representation
3069       of the bases after computing grobcov with the default
3070       option for \"ext\" and the option \"rep\",2,
3071       that outputs both the Prep and the Crep of the
3072       segments, and then call \"extendGC\" to its output.
3073RETURN: When calling extendGC(grobcov(S,\"rep\",2)) the
3074       result is of the form
3075       [[[lpp_1,basis_1,segment_1,lpph_1], ... ,
3076           [lpp_s,basis_s,segment_s,lpph_s]] ],
3077       where each function of the basis can be given
3078       by an ideal of representants.
3079NOTE: The basering R, must be of the form Q[a][x],
3080       (a=parameters, x=variables),
3081       and should be defined previously. The ideal
3082       must be defined on R.
3083KEYWORDS: Groebner cover; parametric ideal; canonical,
3084       discussion of parametric ideal; full representation
3085EXAMPLE:  extendGC; shows an example"
3086{
3087  int te;
3088  def RR=basering;
3089  def Rx=ringlist(RR);
3090  def P=ring(Rx[1]);
3091  Rx[1]=0;
3092  def D=ring(Rx);
3093  def RP=D+P;
3094  list S=GC;
3095  ideal idp;
3096  ideal idq;
3097  int i; int j; int m; int s; int k;
3098  m=0; i=1;
3099  while((i<=size(S)) and (m==0))
3100  {
3101    if(typeof(S[i][2])=="list"){m=1;}
3102    i++;
3103  }
3104  if(m==1)
3105  {
3106    "Warning! grobcov has already extended bases";
3107    return(S);
3108  }
3109  if(typeofCrep(S[1][3])){k=3;}
3110  else{if(typeofCrep(S[1][4])){k=4;};}
3111  if(k==0)
3112  {
3113    "Warning! extendGC make sense only when grobcov has been called with option 'rep',1 or 'rep',2";
3114    // if(te==0){kill @R; kill @RP; kill @P;}
3115    return(S);
3116  }
3117  poly leadc;
3118  poly ext;
3119  list SS;
3120  // Now extendGC
3121  for (i=1;i<=size(S);i++)
3122  {
3123    m=size(S[i][2]);
3124     for (j=1;j<=m;j++)
3125    {
3126      idp=S[i][k][1];
3127      idq=S[i][k][2];
3128      if (size(idp)>0)
3129      {
3130        leadc=leadcoef(S[i][2][j]);
3131        kill ext;
3132        def ext=extendpoly(S[i][2][j],idp,idq);
3133        if (typeof(ext)=="poly")
3134        {
3135          S[i][2][j]=pnormalf(ext,idp,idq);
3136        }
3137        else
3138        {
3139          if(size(ext)==1)
3140          {
3141            S[i][2][j]=ext[1];
3142          }
3143          else
3144          {
3145            kill SS; list SS;
3146            for(s=1;s<=size(ext);s++)
3147            {
3148              ext[s]=pnormalf(ext[s],idp,idq);
3149            }
3150            for(s=1;s<=size(S[i][2]);s++)
3151            {
3152              if(s!=j){SS[s]=S[i][2][s];}
3153              else{SS[s]=ext;}
3154            }
3155            S[i][2]=SS;
3156          }
3157        }
3158      }
3159    }
3160  }
3161  return(S);
3162}
3163example
3164{
3165echo = 2;
3166// EXAMPLE
3167
3168if(defined(R)){kill R;}
3169ring R=(0,a0,b0,c0,a1,b1,c1),(x), dp;
3170short=0;
3171
3172ideal S=a0*x^2+b0*x+c0,
3173          a1*x^2+b1*x+c1;
3174
3175def GCS=grobcov(S,"rep",2);
3176// grobcov(S) with both P and C representations
3177GCS;
3178
3179def FGC=extendGC(GCS,"rep",1);
3180// Full representation
3181FGC;
3182}
3183
3184// Auxiliary routine
3185// nonzerodivisor
3186// input:
3187//    poly g in Q[a],
3188//    list P=(p_1,..p_r) representing a minimal prime decomposition
3189// output
3190//    poly f such that f notin p_i for all i and
3191//           g-f in p_i for all i such that g notin p_i
3192static proc nonzerodivisor(poly gr, list Pr)
3193{
3194  def RR=basering;
3195  def Rx=ringlist(RR);
3196  def P=ring(Rx[1]);
3197  setring(P);
3198  def g=imap(RR,gr);
3199  def P=imap(RR,Pr);
3200  int i; int k;  list J; ideal F;
3201  def f=g;
3202  ideal Pi;
3203  for (i=1;i<=size(P);i++)
3204  {
3205    option(redSB);
3206    Pi=std(P[i]);
3207    //attrib(Pi,"isSB",1);
3208    if (reduce(g,Pi,5)==0){J[size(J)+1]=i;}
3209  }
3210  for (i=1;i<=size(J);i++)
3211  {
3212    F=ideal(1);
3213    for (k=1;k<=size(P);k++)
3214    {
3215      if (k!=J[i])
3216      {
3217        F=idint(F,P[k]);
3218      }
3219    }
3220    f=f+F[1];
3221  }
3222  setring(RR);
3223  def fr=imap(P,f);
3224  return(fr);
3225}
3226
3227//Auxiliary routine
3228// nullin
3229// input:
3230//   poly f:  a polynomial in Q[a]
3231//   ideal P: an ideal in Q[a]
3232//   called from ring @R
3233// output:
3234//   t:  with value 1 if f reduces modulo P, 0 if not.
3235static proc nullin(poly f,ideal P)
3236{
3237  int t;
3238  def RR=basering;
3239  def Rx=ringlist(RR);
3240  def P=ring(Rx[1]);
3241  setring(P);
3242  def f0=imap(RR,f);
3243  def P0=imap(RR,P);
3244  attrib(P0,"isSB",1);
3245  if (reduce(f0,P0,5)==0){t=1;}
3246  else{t=0;}
3247  setring(RR);
3248  return(t);
3249}
3250
3251// Auxiliary routine
3252// monoms
3253// Input: A polynomial f
3254// Output: The list of leading terms
3255static proc monoms(poly f)
3256{
3257  list L;
3258  poly lm; poly lc; poly lp; poly Q; poly mQ;
3259  def p=f;
3260  int i=1;
3261  while (p!=0)
3262  {
3263    lm=lead(p);
3264    p=p-lm;
3265    lc=leadcoef(lm);
3266    lp=leadmonom(lm);
3267    L[size(L)+1]=list(lc,lp);
3268    i++;
3269  }
3270  return(L);
3271}
3272
3273
3274// Auxiliary routine
3275// findindexpolys
3276// input:
3277//   list coefs=( (q11,..,q1r_1),..,(qs1,..,qsr_1) )
3278//               of denominators of the monoms
3279// output:
3280//   list ind=(v_1,..,v_t) of intvec
3281//        each intvec v=(i_1,..,is) corresponds to a polynomial in the sheaf
3282//        that will be built from it in extend procedures.
3283static proc findindexpolys(list coefs)
3284{
3285  int i; int j; intvec numdens;
3286  for(i=1;i<=size(coefs);i++)
3287  {
3288    numdens[i]=size(coefs[i]);
3289  }
3290//  def RR=basering;
3291//  def Rx=ringlist(RR);
3292//  def P=ring(Rx[1]);
3293//  setring(P);
3294//  def coefsp=imap(RR,coefs);
3295  def coefsp=coefs;
3296  ideal cof; list combpolys; intvec v; int te; list mp;
3297  for(i=1;i<=size(coefsp);i++)
3298  {
3299    cof=ideal(0);
3300    for(j=1;j<=size(coefsp[i]);j++)
3301    {
3302      cof[j]=factorize(coefsp[i][j],3);
3303    }
3304    coefsp[i]=cof;
3305  }
3306  for(j=1;j<=size(coefsp[1]);j++)
3307  {
3308    v[1]=j;
3309    te=1;
3310    for (i=2;i<=size(coefsp);i++)
3311    {
3312      mp=memberpos(coefsp[1][j],coefsp[i]);
3313      if(mp[1])
3314      {
3315        v[i]=mp[2];
3316      }
3317      else{v[i]=0;}
3318    }
3319    combpolys[j]=v;
3320  }
3321  combpolys=reform(combpolys,numdens);
3322  //"T_combpolys="; combpolys;
3323  //setring(RR);
3324  //def combpolysT=imap(P,combpolys);
3325 // return(combpolysT);
3326 return(combpolys);
3327}
3328
3329// Auxiliary routine
3330// extendcoef: given Q,P in Q[a] where P/Q specializes on an open and dense subset
3331//      of the whole V(p1 int...int pr), it returns a basis of the module
3332//      of all syzygies equivalent to P/Q,
3333static proc extendcoef(poly fP, poly fQ, ideal idp, ideal idq)
3334{
3335  def RR=basering;
3336  def Rx=ringlist(RR);
3337  def P=ring(Rx[1]);
3338  setring(P);
3339  def PL=ringlist(P);
3340  PL[3][1][1]="dp";
3341  def P1=ring(PL);
3342  setring(P1);
3343  ideal idp0=imap(RR,idp);
3344  option(redSB);
3345  qring q=std(idp0);
3346  poly P0=imap(RR,fP);
3347  poly Q0=imap(RR,fQ);
3348  ideal PQ=Q0,-P0;
3349  module C=syz(PQ);
3350  setring(P);
3351  def idp1=imap(RR,idp);
3352  def idq1=imap(RR,idq);
3353  def C1=matrix(imap(q,C));
3354  def redC=selectregularfun(C1,idp1,idq1);
3355  setring(RR);
3356  def CC=imap(P,redC);
3357  return(CC);
3358}
3359
3360// Auxiliary routine
3361// selectregularfun
3362// input:
3363//   list L of the polynomials matrix CC
3364//      (we assume that one of them is non-null on V(N) \ V(M))
3365//   ideal N, ideal M: ideals representing the locally closed set V(N) \ V(M)
3366// assume to work in @P
3367static proc selectregularfun(matrix C, ideal N, ideal M)
3368{
3369  int numcombused;
3370//   def RR=basering;
3371//   def Rx=ringlist(RR);
3372//   def P=ring(Rx[1]);
3373//   setring(P);
3374//   def C=imap(RR,CC);
3375//   def N=imap(RR,NN);
3376//   def M=imap(RR,MM);
3377  if (ncols(C)==1){return(C);}
3378
3379  int i; int j; int k; list c; intvec ci; intvec c0; intvec c1;
3380  list T; list T0; list T1; list LL; ideal N1;ideal M1; int te=0;
3381  for(i=1;i<=ncols(C);i++)
3382  {
3383    if((C[1,i]!=0) and (C[2,i]!=0))
3384    {
3385      if(c0==intvec(0)){c0[1]=i;}
3386      else{c0[size(c0)+1]=i;}
3387    }
3388  }
3389  def C1=submat(C,1..2,c0);
3390  for (i=1;i<=ncols(C1);i++)
3391  {
3392    c=comb(ncols(C1),i);
3393    for(j=1;j<=size(c);j++)
3394    {
3395      ci=c[j];
3396      numcombused++;
3397      if(i==1){N1=N+C1[2,j]; M1=M;}
3398      if(i>1)
3399      {
3400        kill c0; intvec c0 ; kill c1; intvec c1;
3401        c1=ci[size(ci)];
3402        for(k=1;k<size(ci);k++){c0[k]=ci[k];}
3403        T0=searchinlist(c0,LL);
3404        T1=searchinlist(c1,LL);
3405        N1=T0[1]+T1[1];
3406        M1=intersect(T0[2],T1[2]);
3407      }
3408      T=list(ci,PtoCrep0(Prep0(N1,M1)));
3409      LL[size(LL)+1]=T;
3410      if(equalideals(T[2][1],ideal(1))){te=1; break;}
3411    }
3412    if(te){break;}
3413  }
3414  ci=T[1];
3415  def Cs=submat(C1,1..2,ci);
3416//  setring(RR);
3417//  return(imap(P,Cs));
3418  return(Cs);
3419}
3420
3421// Auxiliary routine
3422// searchinlist
3423// input:
3424//   intvec c:
3425//   list L=( (c1,T1),..(ck,Tk) )
3426//      where the c's are assumed to be intvects
3427// output:
3428//   object T with index c
3429static proc searchinlist(intvec c,list L)
3430{
3431  int i; list T;
3432  for(i=1;i<=size(L);i++)
3433  {
3434    if (L[i][1]==c)
3435    {
3436      T=L[i][2];
3437      break;
3438    }
3439  }
3440  return(T);
3441}
3442
3443// Auxiliary routine
3444// selectminsheaves
3445// Input: L=((v_11,..,v_1k_1),..,(v_s1,..,v_sk_s))
3446//    where:
3447//    The s lists correspond to the s coefficients of the polynomial f
3448//    (v_i1,..,v_ik_i) correspond to the k_i intvec v_ij of the
3449//    spezializations of the jth rekpresentant (Q,P) of the ith coefficient
3450//    v_ij is an intvec of size equal to the number of little segments
3451//    forming the lpp-segment of 0,1, where 1 represents that it specializes
3452//    to non-zedro an the whole little segment and 0 if not.
3453// Output: S=(w_1,..,w_j)
3454//    where the w_l=(n_l1,..,n_ls) are intvec of length size(L), where
3455//    n_lt fixes which element of (v_t1,..,v_tk_t) is to be
3456//    choosen to form the tth (Q,P) for the lth element of the sheaf
3457//    representing the I-regular function.
3458// The selection is done to obtian the minimal number of elements
3459//    of the sheaf that specializes to non-null everywhere.
3460static proc selectminsheaves(list L)
3461{
3462  list C=allsheaves(L);
3463  return(smsheaves(C[1],C[2]));
3464}
3465
3466// Auxiliary routine
3467// smsheaves
3468// Input:
3469//   list C of all the combrep
3470//   list L of the intvec that correesponds to each element of C
3471// Output:
3472//   list LL of the subsets of C that cover all the subsegments
3473//   (the union of the corresponding L(C) has all 1).
3474static proc smsheaves(list C, list L)
3475{
3476  int i; int i0; intvec W;
3477  int nor; int norn;
3478  intvec p;
3479  int sp=size(L[1]); int j0=1;
3480  for (i=1;i<=sp;i++){p[i]=1;}
3481  while (p!=0)
3482  {
3483    i0=0; nor=0;
3484    for (i=1; i<=size(L); i++)
3485    {
3486      norn=numones(L[i],pos(p));
3487      if (nor<norn){nor=norn; i0=i;}
3488    }
3489    W[j0]=i0;
3490    j0++;
3491    p=actualize(p,L[i0]);
3492  }
3493  list LL;
3494  for (i=1;i<=size(W);i++)
3495  {
3496    LL[size(LL)+1]=C[W[i]];
3497  }
3498  return(LL);
3499}
3500
3501// Auxiliary routine
3502// allsheaves
3503// Input: L=((v_11,..,v_1k_1),..,(v_s1,..,v_sk_s))
3504//    where:
3505//    The s lists correspond to the s coefficients of the polynomial f
3506//    (v_i1,..,v_ik_i) correspond to the k_i intvec v_ij of the
3507//    spezializations of the jth rekpresentant (Q,P) of the ith coefficient
3508//    v_ij is an intvec of size equal to the number of little segments
3509//    forming the lpp-segment of 0,1, where 1 represents that it specializes
3510//    to non-zero on the whole little segment and 1 if not.
3511// Output:
3512//    (list LL, list LLS)  where
3513//    LL is the list of all combrep
3514//    LLS is the list of intvec of the corresponding elements of LL
3515static proc allsheaves(list L)
3516{
3517  intvec V; list LL; intvec W; int r; intvec U;
3518  int i; int j; int k;
3519  int s=size(L[1][1]); // s = number of little segments of the lpp-segment
3520  list LLS;
3521  for (i=1;i<=size(L);i++)
3522  {
3523    V[i]=size(L[i]);
3524  }
3525  LL=combrep(V);
3526  for (i=1;i<=size(LL);i++)
3527  {
3528    W=LL[i];   // size(W)= number of coefficients of the polynomial
3529    kill U; intvec U;
3530    for (j=1;j<=s;j++)
3531    {
3532      k=1; r=1; U[j]=1;
3533      while((r==1) and (k<=size(W)))
3534      {
3535        if(L[k][W[k]][j]==0){r=0; U[j]=0;}
3536        k++;
3537      }
3538    }
3539    LLS[i]=U;
3540  }
3541  return(list(LL,LLS));
3542}
3543
3544// Auxiliary routine
3545// numones
3546// Input:
3547//   intvec v of (0,1) in each position
3548//   intvec pos: the positions to test
3549// Output:
3550//   int nor: the nuber of 1 of v in the positions given by pos.
3551static proc numones(intvec v, intvec pos)
3552{
3553  int i; int n;
3554  for (i=1;i<=size(pos);i++)
3555  {
3556    if (v[pos[i]]==1){n++;}
3557  }
3558  return(n);
3559}
3560
3561// Auxiliary routine
3562// actualize: actualizes zeroes of p
3563// Input:
3564//   intvec p: of zeroes and ones
3565//   intvec c: of zeroes and ones (of the same length)
3566// Output;
3567//   intvec pp: of zeroes and ones, where a 0 stays in pp[i] if either
3568//   already p[i]==0 or c[i]==1.
3569static proc actualize(intvec p, intvec c)
3570{
3571  int i; intvec pp=p;
3572  for (i=1;i<=size(p);i++)
3573  {
3574    if ((pp[i]==1) and (c[i]==1)){pp[i]=0;}
3575  }
3576  return(pp);
3577}
3578
3579// Auxiliary routine
3580// intersp: computes the intersection of the ideals in S in @P
3581static proc intersp(list S)
3582{
3583  def RR=basering;
3584  def Rx=ringlist(RR);
3585  def P=ring(Rx[1]);
3586  setring(P);
3587  def SP=imap(RR,S);
3588  option(returnSB);
3589  def NP=intersect(SP[1..size(SP)]);
3590  setring(RR);
3591  return(imap(P,NP));
3592}
3593
3594// Auxiliary routine
3595// radicalmember
3596static proc radicalmember(poly f,ideal ida)
3597{
3598  int te;
3599  def RR=basering;
3600  def Rx=ringlist(RR);
3601  def P=ring(Rx[1]);
3602  setring(P);
3603  def fp=imap(RR,f);
3604  def idap=imap(RR,ida);
3605  poly @t;
3606  ring H=0,@t,dp;
3607  def PH=P+H;
3608  setring(PH);
3609  def fH=imap(P,fp);
3610  def idaH=imap(P,idap);
3611  idaH[size(idaH)+1]=1-@t*fH;
3612  option(redSB);
3613  def G=std(idaH);
3614  if (G==1){te=1;} else {te=0;}
3615  setring(RR);
3616  return(te);
3617}
3618
3619// Auxiliary routine
3620// selectextendcoef
3621// input:
3622//    matrix CC: CC=(p_a1 .. p_ar_a)
3623//                  (q_a1 .. q_ar_a)
3624//            the matrix of elements of a coefficient in oo[a].
3625//    (ideal ida, ideal idb): the canonical representation of the segment S.
3626// output:
3627//    list caout
3628//            the minimum set of elements of CC needed such that at least one
3629//            of the q's is non-null on S, as well as the C-rep of of the
3630//            points where the q's are null on S.
3631//            The elements of caout are of the form (p,q,prep);
3632static proc selectextendcoef(matrix CC, ideal ida, ideal idb)
3633{
3634  def RR=basering;
3635  def Rx=ringlist(RR);
3636  def P=ring(Rx[1]);
3637  setring(P);
3638  def ca=imap(RR,CC);
3639  def E0=imap(RR,ida);
3640  ideal E;
3641  def N=imap(RR,idb);
3642  int r=ncols(ca);
3643  int i; int te=1; list com; int j; int k; intvec c; list prep;
3644  list cs; list caout;
3645  i=1;
3646  while ((i<=r) and (te))
3647  {
3648    com=comb(r,i);
3649    j=1;
3650    while((j<=size(com)) and (te))
3651    {
3652      E=E0;
3653      c=com[j];
3654      for (k=1;k<=i;k++)
3655      {
3656        E=E+ca[2,c[k]];
3657      }
3658      prep=Prep(E,N);
3659      if (i==1)
3660      {
3661        cs[j]=list(ca[1,j],ca[2,j],prep);
3662      }
3663      if ((size(prep)==1) and (equalideals(prep[1][1],ideal(1))))
3664      {
3665        te=0;
3666        for(k=1;k<=size(c);k++)
3667        {
3668          caout[k]=cs[c[k]];
3669        }
3670      }
3671      j++;
3672    }
3673    i++;
3674  }
3675  if (te){"error: extendcoef does not extend to the whole S";}
3676  setring(RR);
3677  return(imap(P,caout));
3678}
3679
3680// Auxiliary routine
3681// plusP
3682// Input:
3683//   ideal E1: in some basering (depends only on the parameters)
3684//   ideal E2: in some basering (depends only on the parameters)
3685// Output:
3686//   ideal Ep=E1+E2; computed in @P
3687static proc plusP(ideal E1,ideal E2)
3688{
3689  def RR=basering;
3690  def Rx=ringlist(RR);
3691  def P=ring(Rx[1]);
3692  setring(P);
3693  def E1p=imap(RR,E1);
3694  def E2p=imap(RR,E2);
3695  def Ep=E1p+E2p;
3696  setring(RR);
3697  return(imap(P,Ep));
3698}
3699
3700// Auxiliary routine
3701// reform
3702// input:
3703//   list combpolys: (v1,..,vs)
3704//      where vi are intvec.
3705//   output outcomb: (w1,..,wt)
3706//      whre wi are intvec.
3707//      All the vi without zeroes are in outcomb, and those with zeroes are
3708//         combined to form new intvec with the rest
3709static proc reform(list combpolys, intvec numdens)
3710{
3711  list combp0; list combp1; int i; int j; int k; int l; list rest; intvec notfree;
3712  list free; intvec free1; int te; intvec v;  intvec w;
3713  int nummonoms=size(combpolys[1]);
3714  for(i=1;i<=size(combpolys);i++)
3715  {
3716    if(memberpos(0,combpolys[i])[1])
3717    {
3718      combp0[size(combp0)+1]=combpolys[i];
3719    }
3720    else {combp1[size(combp1)+1]=combpolys[i];}
3721  }
3722  for(i=1;i<=nummonoms;i++)
3723  {
3724    kill notfree; intvec notfree;
3725    for(j=1;j<=size(combpolys);j++)
3726    {
3727      if(combpolys[j][i]<>0)
3728      {
3729        if(notfree[1]==0){notfree[1]=combpolys[j][i];}
3730        else{notfree[size(notfree)+1]=combpolys[j][i];}
3731      }
3732    }
3733    kill free1; intvec free1;
3734    for(j=1;j<=numdens[i];j++)
3735    {
3736      if(memberpos(j,notfree)[1]==0)
3737      {
3738        if(free1[1]==0){free1[1]=j;}
3739        else{free1[size(free1)+1]=j;}
3740      }
3741      free[i]=free1;
3742    }
3743  }
3744  list amplcombp; list aux;
3745  for(i=1;i<=size(combp0);i++)
3746  {
3747    v=combp0[i];
3748    kill amplcombp; list amplcombp;
3749    amplcombp[1]=intvec(v[1]);
3750    for(j=2;j<=size(v);j++)
3751    {
3752      if(v[j]!=0)
3753      {
3754        for(k=1;k<=size(amplcombp);k++)
3755        {
3756          w=amplcombp[k];
3757          w[size(w)+1]=v[j];
3758          amplcombp[k]=w;
3759        }
3760      }
3761      else
3762      {
3763        kill aux; list aux;
3764        for(k=1;k<=size(amplcombp);k++)
3765        {
3766          for(l=1;l<=size(free[j]);l++)
3767          {
3768            w=amplcombp[k];
3769            w[size(w)+1]=free[j][l];
3770            aux[size(aux)+1]=w;
3771          }
3772        }
3773        amplcombp=aux;
3774      }
3775    }
3776    for(j=1;j<=size(amplcombp);j++)
3777    {
3778      combp1[size(combp1)+1]=amplcombp[j];
3779    }
3780  }
3781  return(combp1);
3782}
3783
3784// Auxiliary routine
3785// precombint
3786// input:  L: list of ideals (works in @P)
3787// output: F0: ideal of polys. F0[i] is a poly in the intersection of
3788//             all ideals in L except in the ith one, where it is not.
3789//             L=(p1,..,ps);  F0=(f1,..,fs);
3790//             F0[i] \in intersect_{j#i} p_i
3791static proc precombint(list L)
3792{
3793  int i; int j; int tes;
3794  def RR=basering;
3795  def Rx=ringlist(RR);
3796  def P=ring(Rx[1]);
3797  setring(P);
3798  list L0; list L1; list L2; list L3; ideal F;
3799  L0=imap(RR,L);
3800  L1[1]=L0[1]; L2[1]=L0[size(L0)];
3801  for (i=2;i<=size(L0)-1;i++)
3802  {
3803    L1[i]=intersect(L1[i-1],L0[i]);
3804    L2[i]=intersect(L2[i-1],L0[size(L0)-i+1]);
3805  }
3806  L3[1]=L2[size(L2)];
3807  for (i=2;i<=size(L0)-1;i++)
3808  {
3809    L3[i]=intersect(L1[i-1],L2[size(L0)-i]);
3810  }
3811  L3[size(L0)]=L1[size(L1)];
3812  for (i=1;i<=size(L3);i++)
3813  {
3814    option(redSB); L3[i]=std(L3[i]);
3815  }
3816  for (i=1;i<=size(L3);i++)
3817  {
3818    tes=1; j=0;
3819    while((tes) and (j<size(L3[i])))
3820    {
3821      j++;
3822      option(redSB);
3823      L0[i]=std(L0[i]);
3824      if(reduce(L3[i][j],L0[i],5)!=0){tes=0; F[i]=L3[i][j];}
3825    }
3826    if (tes){"ERROR a polynomial in all p_j except p_i was not found";}
3827  }
3828  setring(RR);
3829  def F0=imap(P,F);
3830  return(F0);
3831}
3832
3833// Auxiliary routine
3834// minAssGTZ eliminating denominators
3835static proc minGTZ(ideal N);
3836{
3837  int i; int j;
3838  def L=minAssGTZ(N);
3839  for(i=1;i<=size(L);i++)
3840  {
3841    for(j=1;j<=size(L[i]);j++)
3842    {
3843      L[i][j]=cleardenom(L[i][j]);
3844    }
3845  }
3846  return(L);
3847}
3848
3849//********************* Begin KapurSunWang *************************
3850
3851// Auxiliary routine
3852// inconsistent
3853// Input:
3854//   ideal E: of null conditions
3855//   ideal N: of non-null conditions representing V(E) \ V(N)
3856// Output:
3857//   1 if V(E) \ V(N) = empty
3858//   0 if not
3859//   Uses Rabinowiitz trick
3860static proc inconsistent(ideal E, ideal N)
3861{
3862  int j;
3863  int te=1;
3864  int tt;
3865  def RR=basering;
3866  def Rx=ringlist(RR);
3867  if(size(Rx[1])==4)
3868  {
3869    tt=1;
3870    def P=ring(Rx[1]);
3871    setring(P);
3872    def EP=imap(RR,E);
3873    def NP=imap(RR,N);
3874  }
3875  else
3876  {
3877    def EP=E;
3878    def NP=N;
3879  }
3880  poly @t;
3881  ring H=0,@t,dp;
3882  if(tt==1)
3883  {
3884    def RH=P+H;
3885   setring(RH);
3886   def EH=imap(P,EP);
3887   def NH=imap(P,NP);
3888  }
3889  else
3890  {
3891    def RH=RR+H;
3892    setring(RH);
3893    def EH=imap(RR,EP);
3894    def NH=imap(RR,NP);
3895  }
3896  ideal G;
3897  j=1;
3898  while((te==1) and j<=size(NH))
3899  {
3900    G=EH+(1-@t*NH[j]);
3901    option(redSB);
3902    G=std(G);
3903    if (G[1]!=1){te=0;}
3904    j++;
3905  }
3906  setring(RR);
3907  return(te);
3908}
3909
3910// Auxiliary routine
3911// MDBasis: Minimal Dickson Basis
3912static proc MDBasis(ideal G)
3913{
3914  int i; int j; int te=1;
3915  G=sortideal(G);
3916  ideal MD=G[1];
3917  poly lm;
3918  for (i=2;i<=size(G);i++)
3919  {
3920    te=1;
3921    lm=leadmonom(G[i]);
3922    j=1;
3923    while ((te==1) and (j<=size(MD)))
3924    {
3925      if (lm/leadmonom(MD[j])!=0){te=0;}
3926      j++;
3927    }
3928    if (te==1)
3929    {
3930      MD[size(MD)+1]=(G[i]);
3931    }
3932  }
3933  return(MD);
3934}
3935
3936// Auxiliary routine
3937// primepartZ
3938static proc primepartZ(poly f);
3939{
3940  def cp=content(f);
3941  def fp=f/cp;
3942  return(fp);
3943}
3944
3945// LCMLC
3946static proc LCMLC(ideal H)
3947{
3948  int i;
3949  def RR=basering;
3950  def Rx=ringlist(RR);
3951  def P=ring(Rx[1]);
3952  Rx[1]=0;
3953  def D=ring(Rx);
3954  def RP=D+P;
3955  setring(RP);
3956  def HH=imap(RR,H);
3957  poly h=1;
3958  for (i=1;i<=size(HH);i++)
3959  {
3960    h=lcm(h,HH[i]);
3961  }
3962  setring(RR);
3963  def hh=imap(RP,h);
3964  return(hh);
3965}
3966
3967// KSW: Kapur-Sun-Wang algorithm for computing a CGS
3968// Input:
3969//   F:   parametric ideal to be discussed
3970//   Options:
3971//     \"out\",0 Transforms the description of the segments into
3972//     canonical P-representation form.
3973//     \"out\",1 Original KSW routine describing the segments as
3974//     difference of varieties
3975//   The ideal must be defined on C[parameters][variables]
3976// Output:
3977//   With option \"out\",0 :
3978//     ((lpp,
3979//       (1,B,((p_1,(p_11,..,p_1k_1)),..,(p_s,(p_s1,..,p_sk_s)))),
3980//       string(lpp)
3981//      )
3982//      ,..,
3983//      (lpp,
3984//       (k,B,((p_1,(p_11,..,p_1k_1)),..,(p_s,(p_s1,..,p_sk_s)))),
3985//       string(lpp))
3986//      )
3987//     )
3988//   With option \"out\",1 ((default, original KSW) (shorter to be computed,
3989//                    but without canonical description of the segments.
3990//     ((B,E,N),..,(B,E,N))
3991static proc KSW(ideal F, list #)
3992{
3993//   def RR=basering;
3994//   def Rx=ringlist(RR);
3995//   def P=ring(Rx[1]);
3996//   Rx[1]=0;
3997//   def D=ring(Rx);
3998//   def RP=D+p;
3999//   // setglobalrings();
4000  int start=timer;
4001  ideal E=ideal(0);
4002  ideal N=ideal(1);
4003  int comment=0;
4004  int out=1;
4005  int i;
4006  def L=#;
4007  if(size(L)>0)
4008  {
4009    for (i=1;i<=size(L) div 2;i++)
4010    {
4011      if (L[2*i-1]=="null"){E=L[2*i];}
4012      else
4013      {
4014        if (L[2*i-1]=="nonnull"){N=L[2*i];}
4015        else
4016        {
4017          if (L[2*i-1]=="comment"){comment=L[2*i];}
4018          else
4019          {
4020            if (L[2*i-1]=="out"){out=L[2*i];}
4021          }
4022        }
4023      }
4024    }
4025  }
4026  if (comment>0){string("Begin KSW with null = ",E," nonnull = ",N);}
4027  def CG=KSW0(F,E,N,comment);
4028  if (comment>0)
4029  {
4030    string("Number of segments in KSW (total) = ",size(CG));
4031    string("Time in KSW = ",timer-start);
4032  }
4033  if(out==0)
4034  {
4035    CG=KSWtocgsdr(CG);
4036    //"T_CG="; CG;
4037    if( size(CG)>0)
4038    {
4039      CG=groupKSWsegments(CG);
4040      if (comment>0)
4041      {
4042        string("Number of lpp segments = ",size(CG));
4043        string("Time in KSW + group + Prep = ",timer-start);
4044      }
4045    }
4046  }
4047  return(CG);
4048}
4049
4050// Auxiliary routine
4051// sqf
4052static proc sqf(poly f)
4053{
4054  def RR=basering;
4055  def Rx=ringlist(RR);
4056  def P=ring(Rx[1]);
4057  setring(P);
4058  def ff=imap(RR,f);
4059  poly fff=sqrfree(ff,3);
4060  setring(RR);
4061  def ffff=imap(P,fff);
4062  return(ffff);
4063}
4064
4065// Auxiliary routine
4066// KSW0: Kapur-Sun-Wang algorithm for computing a CGS, called by KSW
4067// Input:
4068//   F:   parametric ideal to be discussed
4069//   Options:
4070//   The ideal must be defined on C[parameters][variables]
4071// Output:
4072static proc KSW0(ideal F, ideal E, ideal N, int comment)
4073{
4074  def RR=basering;
4075  def Rx=ringlist(RR);
4076  def P=ring(Rx[1]);
4077  Rx[1]=0;
4078  def D=ring(Rx);
4079  def RP=D+P;
4080  int i; int j; list emp;
4081  list CGS;
4082  ideal N0;
4083  for (i=1;i<=size(N);i++)
4084  {
4085    N0[i]=sqf(N[i]);
4086  }
4087  ideal E0;
4088  for (i=1;i<=size(E);i++)
4089  {
4090    E0[i]=sqf(leadcoef(E[i]));
4091  }
4092  setring(P);
4093  ideal E1=imap(RR,E0);
4094  E1=std(E1);
4095  ideal N1=imap(RR,N0);
4096  N1=std(N1);
4097  setring(RR);
4098  E0=imap(P,E1);
4099  N0=imap(P,N1);
4100  if (inconsistent(E0,N0)==1)
4101  {
4102    return(emp);
4103  }
4104  setring(RP);
4105  def FRP=imap(RR,F);
4106  def ERP=imap(RR,E);
4107  FRP=FRP+ERP;
4108  option(redSB);
4109  def GRP=std(FRP);
4110  setring(RR);
4111  def G=imap(RP,GRP);
4112  if (memberpos(1,G)[1]==1)
4113  {
4114    if(comment>1){"Basis 1 is found"; E; N;}
4115    list KK; KK[1]=list(E0,N0,ideal(1));
4116    return(KK);
4117   }
4118  ideal Gr; ideal Gm; ideal GM;
4119  for (i=1;i<=size(G);i++)
4120  {
4121    if (variables(G[i])[1]==0){Gr[size(Gr)+1]=G[i];}
4122    else{Gm[size(Gm)+1]=G[i];}
4123  }
4124  ideal Gr0;
4125  for (i=1;i<=size(Gr);i++)
4126  {
4127    Gr0[i]=sqf(Gr[i]);
4128  }
4129
4130
4131  Gr=elimrepeated(Gr0);
4132  ideal GrN;
4133  for (i=1;i<=size(Gr);i++)
4134   {
4135    for (j=1;j<=size(N0);j++)
4136    {
4137      GrN[size(GrN)+1]=sqf(Gr[i]*N0[j]);
4138    }
4139  }
4140  if (inconsistent(E,GrN)){;}
4141  else
4142  {
4143    if(comment>1){"Basis 1 is found in a branch with arguments"; E; GrN;}
4144    CGS[size(CGS)+1]=list(E,GrN,ideal(1));
4145  }
4146  if (inconsistent(Gr,N0)){return(CGS);}
4147  GM=Gm;
4148  Gm=MDBasis(Gm);
4149  ideal H;
4150  for (i=1;i<=size(Gm);i++)
4151  {
4152    H[i]=sqf(leadcoef(Gm[i]));
4153  }
4154  H=facvar(H);
4155  poly h=sqf(LCMLC(H));
4156  if(comment>1){"H = "; H; "h = "; h;}
4157  ideal Nh=N0;
4158  if(size(N0)==0){Nh=h;}
4159  else
4160  {
4161    for (i=1;i<=size(N0);i++)
4162    {
4163      Nh[i]=sqf(N0[i]*h);
4164    }
4165  }
4166  if (inconsistent(Gr,Nh)){;}
4167  else
4168  {
4169    CGS[size(CGS)+1]=list(Gr,Nh,Gm);
4170  }
4171  poly hc=1;
4172  list KS;
4173  ideal GrHi;
4174  for (i=1;i<=size(H);i++)
4175  {
4176    kill GrHi;
4177    ideal GrHi;
4178    Nh=N0;
4179    if (i>1){hc=sqf(hc*H[i-1]);}
4180    for (j=1;j<=size(N0);j++){Nh[j]=sqf(N0[j]*hc);}
4181    if (equalideals(Gr,ideal(0))==1){GrHi=H[i];}
4182    else {GrHi=Gr,H[i];}
4183    if(comment>1){"Call to KSW with arguments "; GM; GrHi;  Nh;}
4184    KS=KSW0(GM,GrHi,Nh,comment);
4185    for (j=1;j<=size(KS);j++)
4186    {
4187      CGS[size(CGS)+1]=KS[j];
4188    }
4189    if(comment>1){"CGS after KSW = "; CGS;}
4190  }
4191  return(CGS);
4192}
4193
4194// Auxiliary routine
4195// KSWtocgsdr
4196static proc KSWtocgsdr(list L)
4197{
4198  int i; list CG; ideal B; ideal lpp; int j; list NKrep;
4199  for(i=1;i<=size(L);i++)
4200  {
4201    B=redgbn(L[i][3],L[i][1],L[i][2]);
4202    lpp=ideal(0);
4203    for(j=1;j<=size(B);j++)
4204    {
4205      lpp[j]=leadmonom(B[j]);
4206    }
4207    NKrep=KtoPrep(L[i][1],L[i][2]);
4208    CG[i]=list(lpp,B,NKrep);
4209  }
4210  return(CG);
4211}
4212
4213// Auxiliary routine
4214// KtoPrep
4215// Computes the P-representaion of a K-representation (N,W) of a set
4216// input:
4217//    ideal E (null conditions)
4218//    ideal N (non-null conditions ideal)
4219// output:
4220//    the ((p_1,(p_11,..,p_1k_1)),..,(p_r,(p_r1,..,p_rk_r)));
4221//    the Prep of V(N) \ V(W)
4222static proc KtoPrep(ideal N, ideal W)
4223{
4224  int i; int j;
4225  if (N[1]==1)
4226  {
4227    L0[1]=list(ideal(1),list(ideal(1)));
4228    return(L0);
4229  }
4230  def RR=basering;
4231  def Rx=ringlist(RR);
4232  def P=ring(Rx[1]);
4233  setring(P);
4234  ideal B; int te; poly f;
4235  ideal Np=imap(RR,N);
4236  ideal Wp=imap(RR,W);
4237  list L;
4238  list L0; list T0;
4239  L0=minGTZ(Np);
4240  for(j=1;j<=size(L0);j++)
4241  {
4242    option(redSB);
4243    L0[j]=std(L0[j]);
4244  }
4245  for(i=1;i<=size(L0);i++)
4246  {
4247    if(inconsistent(L0[i],Wp)==0)
4248    {
4249      B=L0[i]+Wp;
4250      T0=minGTZ(B);
4251      option(redSB);
4252      for(j=1;j<=size(T0);j++)
4253      {
4254        T0[j]=std(T0[j]);
4255      }
4256      L[size(L)+1]=list(L0[i],T0);
4257    }
4258  }
4259  setring(RR);
4260  def LL=imap(P,L);
4261  return(LL);
4262}
4263
4264// Auxiliary routine
4265// groupKSWsegments
4266// input:  the list of vertices of KSW
4267// output: the same terminal vertices grouped by lpp
4268static proc groupKSWsegments(list T)
4269{
4270  int i; int j;
4271  list L;
4272  list lpp; list lppor;
4273  list kk;
4274  lpp[1]=T[1][1]; j=1;
4275  lppor[1]=intvec(1);
4276  for(i=2;i<=size(T);i++)
4277  {
4278    kk=memberpos(T[i][1],lpp);
4279    if(kk[1]==0){j++; lpp[j]=T[i][1]; lppor[j]=intvec(i);}
4280    else{lppor[kk[2]][size(lppor[kk[2]])+1]=i;}
4281  }
4282  list ll;
4283  for (j=1;j<=size(lpp);j++)
4284  {
4285    kill ll; list ll;
4286    for(i=1;i<=size(lppor[j]);i++)
4287    {
4288      ll[size(ll)+1]=list(i,T[lppor[j][i]][2],T[lppor[j][i]][3]);
4289    }
4290    L[j]=list(lpp[j],ll,string(lpp[j]));
4291  }
4292  return(L);
4293}
4294
4295//********************* End KapurSunWang *************************
4296
4297//********************* Begin ConsLevels ***************************
4298
4299static proc zeroone(int n)
4300{
4301  list L; list L2;
4302  intvec e; intvec e2; intvec e3;
4303  int j;
4304  if(n==1)
4305  {
4306    e[1]=0;
4307    L[1]=e;
4308    e[1]=1;
4309    L[2]=e;
4310    return(L);
4311  }
4312  if(n>1)
4313  {
4314    L=zeroone(n-1);
4315    for(j=1;j<=size(L);j++)
4316    {
4317      e2=L[j];
4318      e3=e2;
4319      e3[size(e3)+1]=0;
4320      L2[size(L2)+1]=e3;
4321      e3=e2;
4322      e3[size(e3)+1]=1;
4323      L2[size(L2)+1]=e3;
4324    }
4325  }
4326  return(L2);
4327}
4328
4329// Auxiliary routine
4330// subsets: the list of subsets of (1,..n)
4331static proc subsets(int n)
4332{
4333  list L; list L1;
4334  int i; int j;
4335  L=zeroone(n);
4336  intvec e; intvec e1;
4337  for(i=1;i<=size(L);i++)
4338  {
4339    e=L[i];
4340    kill e1; intvec e1;
4341    for(j=1;j<=n;j++)
4342    {
4343      if(e[n+1-j]==1)
4344      {
4345        if(e1==intvec(0)){e1[1]=j;}
4346        else{e1[size(e1)+1]=j};
4347      }
4348    }
4349    L1[i]=e1;
4350  }
4351  return(L1);
4352}
4353
4354// Input a list A of locally closed sets in C-rep
4355// Output a list B of a simplified list of A
4356static proc SimplifyUnion(list A)
4357{
4358  int i; int j;
4359  list L=A;
4360  int n=size(L);
4361  if(n<2){return(A);}
4362  intvec w;
4363  for(i=1;i<=size(L);i++)
4364  {
4365    for(j=1;j<=size(L);j++)
4366    {
4367      if(i != j)
4368      {
4369        if(equalideals(L[i][2],L[j][1])==1)
4370        {
4371          L[i][2]=L[j][2];
4372          w[size(w)+1]=j;
4373        }
4374      }
4375    }
4376  }
4377  if(size(w)>0)
4378  {
4379    for(i=1; i<=size(w);i++)
4380    {
4381      j=w[size(w)+1-i];
4382      L=elimfromlist(L, j);
4383    }
4384  }
4385  ideal T=ideal(1);
4386  intvec v;
4387  for(i=1;i<=size(L);i++)
4388  {
4389    if(equalideals(L[i][2],ideal(1)))
4390    {
4391      v[size(v)+1]=i;
4392      T=intersect(T,L[i][1]);
4393    }
4394  }
4395  if(size(v)>0)
4396  {
4397    for(i=1; i<=size(v);i++)
4398    {
4399      j=v[size(v)+1-i];
4400      L=elimfromlist(L, j);
4401    }
4402  }
4403  if(equalideals(T,ideal(1))==0){L[size(L)+1]=list(std(T),ideal(1))};
4404  return(L);
4405}
4406
4407// input list A=[[p1,q1],...,[pn,qn]] :
4408//                    the list of segments of a constructible set S, where each [pi,qi] is given in C-representation
4409// output list [topA,C]
4410//       where topA is the closure of A
4411//                 C is the list of segments of the complement of A given in C-representation
4412static proc FirstLevel(list A)
4413{
4414  int n=size(A);
4415  list T=zeroone(n);
4416  ideal P; ideal Q;
4417  list Cb;  ideal Cc=1;
4418  int i; int j;
4419  intvec t;
4420  ideal topA=1;
4421  list C;
4422  for(i=1;i<=n;i++)
4423  {
4424    topA=intersect(topA,A[i][1]);
4425  }
4426  //topA=std(topA);
4427  for(i=2; i<=size(T);i++)
4428  {
4429    t=T[i];
4430    //"T_t"; t;
4431    P=0; Q=1;
4432    for(j=1;j<=n;j++)
4433    {
4434      if(t[n+1-j]==1)
4435      {
4436        P=P+A[j][2];
4437      }
4438      else
4439      {
4440        Q=intersect(Q,A[j][1]);
4441      }
4442    }
4443    Cb=Crep0(P,Q);
4444    //"T_Cb="; Cb;
4445    if(size(Cb)!=0)
4446    {
4447      if( Cb[1][1]<>1)
4448      {
4449        C[size(C)+1]=Cb;
4450      }
4451    }
4452  }
4453  if(size(C)>1){C=SimplifyUnion(C);}
4454  return(list(topA,C));
4455}
4456
4457// Input:
4458// Output:
4459static proc ConstoPrep(list L)
4460{
4461  list L1;
4462  int i; int j;
4463  list aux;
4464  for(i=1;i<=size(L);i++)
4465  {
4466    aux=Prep(L[i][2][1],L[i][2][2]);
4467    L1[size(L1)+1]=list(L[i][1],aux);
4468  }
4469  return(L1);
4470}
4471
4472
4473// Input:
4474//     list A =  [[P1,Q1], .. [Pn,Qn]]
4475//                  A constructible set as union of locally closed sets represented by pairs of ideals
4476// Output:
4477//     list L =[p1,p2,p3,...,pk]
4478//        where pi is the ideal of the closure of level i alternatively of  A or its complement
4479//        Note: the levels of A are [p1,p2], [p3,p4], [p5,p6],...
4480//                 the levels of C are [p2,p3],[p4,p5], ...
4481//                 expressed in C-representation
4482//    Assumed to be called in the ring Q[a]
4483proc ConsLevels(list A0)
4484"USAGE: ConsLevels(list L);
4485       L=[[P1,Q1],...,[Ps,Qs]] is a list of lists of of pairs of
4486       ideals represening the constructible set
4487       S=V(P1) \ V(Q1) u ... u V(Ps) \ V(Qs).
4488       To be called in a ring Q[a][x] or a ring Q[a]. But the
4489       ideals can contain only the parameters in Q[a].
4490RETURN: The list of ideals [a1,a2,...,at] representing the
4491       closures of the canonical levels of S and its
4492       complement C wrt to the closure of S. The
4493       canonical levels of S are represented by theirs
4494       Crep. So we have:
4495       Levels of S:  [a1,a2],[a3,a4],...
4496       Levels of C:  [a2,a3],[a4,a5],...
4497       S=V(a1) \ V(a2) u V(a3) \ V(a4) u ...
4498       C=V(a2 \ V(a3) u V(a4) \ V(a5) u ...
4499       The expression of S can be obtained from the
4500       output of ConsLevels by
4501       the call to Levels.
4502NOTE: The algorithm was described in
4503       J.M. Brunat, A. Montes. \"Computing the canonical
4504       representation of constructible sets.\"
4505       Math.  Comput. Sci. (2016) 19: 165-178.
4506KEYWORDS: constructible set; locally closed set; canonical form
4507EXAMPLE:  ConsLevels; shows an example"
4508{
4509  int te;
4510  def RR=basering;
4511  def Rx=ringlist(RR);
4512  if(size(Rx[1])==4)
4513  {
4514    te=1;
4515    def P=ring(Rx[1]);
4516    setring P;
4517    list A=imap(RR,A0);
4518  }
4519  // if(defined(@P)){te=1; setring(@P); list A=imap(RR,A0);}
4520  else {te=0; def A=A0;}
4521
4522  list L; list C;
4523  list B; list T; int i;
4524  for(i=1; i<=size(A);i++)
4525  {
4526    T=Crep0(A[i][1],A[i][2]);
4527    B[size(B)+1]=T;
4528  }
4529  list K;
4530  while(size(B)>0)
4531  {
4532    K=FirstLevel(B);
4533    //"T_K="; K;
4534    L[size(L)+1]=K[1];
4535    B=K[2];
4536   }
4537  L[size(L)+1]=ideal(1);
4538  if(te==1) {setring(RR); def LL=imap(P,L);}
4539  if(te==0){def LL=L;}
4540  return(LL);
4541}
4542example
4543{
4544echo = 2;
4545// EXAMPLE:
4546
4547if(defined(R)){kill R;}
4548ring R=0,(x,y,z),lp;
4549short=0;
4550
4551ideal P1=(x^2+y^2+z^2-1);
4552ideal Q1=z,x^2+y^2-1;
4553ideal P2=y,x^2+z^2-1;
4554ideal Q2=z*(z+1),y,x*(x+1);
4555ideal P3=x;
4556ideal Q3=5*z-4,5*y-3,x;
4557
4558list Cr1=Crep(P1,Q1);
4559list Cr2=Crep(P2,Q2);
4560list Cr3=Crep(P3,Q3);
4561list L=list(Cr1,Cr2,Cr3);
4562L;
4563
4564def LL=ConsLevels(L);
4565LL;
4566
4567def LLL=Levels(LL);
4568LLL;
4569}
4570
4571// Converts the output of ConsLevels, given by the set of closures of the Levels of the constructible S
4572//     to an expression where the Levels are apparent.
4573// Input: The output of ConsLevels of the form
4574//    [A1,A2,..,Ak], where the Ai's are the closures of the levels.
4575// Output: An expression of the form
4576//      L1=[[1,[A1,A2]],[3,[A3,A4]],..,[2l-1,[A_{2l-1},A_{2l}]]] the list of Levels of S
4577proc Levels(list L)
4578"USAGE: Levels(list L);
4579       The input list L must be the output of the call to the
4580       routine ConsLevels of a constructible set:
4581       L=[a1,a2,..,ak], where the a's are the closures
4582       of the levels, determined by ConsLevels.
4583       Levels selects the levels of the
4584       constructible set. To be called in a ring Q[a][x]
4585       or a ring Q[a]. But the ideals can contain
4586       only the parameters in Q[a].
4587RETURN: The levels of the constructible set:
4588       Lc=[ [1,[a1,a2]],[3,[a3,a4]],..,
4589           [2l-1,[a_{2l-1},a_{2l}]] ]
4590       the list of  levels of S
4591KEYWORDS: constructible sets; canonical form
4592EXAMPLE:  Levels shows an example"
4593{
4594  int n=size(L) div 2;
4595  int i;
4596  list L1; list L2;
4597  for(i=1; i<=n;i++)
4598  {
4599    L1[size(L1)+1]=list(2*i-1,list(L[2*i-1],L[2*i]));
4600  }
4601  return(L1);
4602}
4603example
4604{
4605echo = 2;
4606// EXAMPLE:
4607
4608if(defined(R)){kill R;}
4609ring R=0,(x,y,z),lp;
4610short=0;
4611
4612ideal P1=(x^2+y^2+z^2-1);
4613ideal Q1=z,x^2+y^2-1;
4614ideal P2=y,x^2+z^2-1;
4615ideal Q2=z*(z+1),y,x*(x+1);
4616ideal P3=x;
4617ideal Q3=5*z-4,5*y-3,x;
4618
4619list Cr1=Crep(P1,Q1);
4620list Cr2=Crep(P2,Q2);
4621list Cr3=Crep(P3,Q3);
4622list L=list(Cr1,Cr2,Cr3);
4623L;
4624
4625def LL=ConsLevels(L);
4626LL;
4627
4628def LLL=Levels(LL);
4629LLL;
4630}
4631
4632proc DifConsLCSets(list A, list B)
4633"USAGE: DifConsLCSets(list A,list B);
4634       Input: The input lists A and B must be each one
4635       the canonical representations of the respective constructible sets,
4636       i.e. outputs of the routine ConsLevels for a constructible set,
4637       or from the routine Grob1Levels applied to the
4638       output of grobcov.
4639         A=[a1,a2,..,ak],
4640         B=[b1,b2,..,bj],
4641       where the a's and the b's are the closures
4642       of the levels of the constructible and the complements
4643       determined by ConsLevels (or GrobLevels)
4644
4645       To be called in a ring Q[a][x]
4646       or a ring Q[a]. But the ideals can contain
4647       only the parameters in Q[a].
4648RETURN: A list of locally closed sets equivalent to the difference  S= A "\" B.
4649       Lc=[ [1][p1,q1]] [[2][p2,q2]]..],
4650       For obtaining the canonical representation into levels of
4651       the constructible A "\" B one have to apply ConsLevels and
4652       then optatively Levels.
4653
4654KEYWORDS: constructible sets; canonical form
4655EXAMPLE:   DifConsLCSets shows an example"
4656{
4657  int n; int m; int t; int i; int j; int k;
4658  ideal ABup;
4659  ideal ABdw;
4660  if (size(B) mod 2==1){B[size(B)+1]=ideal(1);}
4661  if (size(A) mod 2==1){A[size(A)+1]=ideal(1);}
4662  //"T_A=";A;
4663 // "T_B="; B;
4664  n=size(A) div 2;
4665  m=(size(B) div 2)-1;
4666  //string("T_n=",n);
4667  //string("T_m=",m);
4668  list L;
4669  list M;
4670  list ABupC;
4671  //list LL;
4672  for(i=1;i<=n;i++)
4673  {
4674    //string("T_i=",i);
4675    t=1;
4676    j=0;
4677    //list L;
4678    while (t==1 and j<=m)
4679    {
4680      //string("T_j=",j);
4681      ABdw=intersectpar(list(A[2*i],B[2*j+1]));
4682      //"T_ABdw="; ABdw;
4683      ABup=A[2*i-1];
4684      //"T_ABup1="; ABup;
4685      if(j>0)
4686      {
4687        for(k=1;k<=size(B[2*j]);k++)
4688        {
4689          ABup[size(ABup)+1]=B[2*j][k];
4690        }
4691      }
4692      //"T_ABup2="; ABup;
4693      ABupC=Crep(ABup,ideal(1));
4694      //"T_ABupC="; ABupC;
4695      ABup=ABupC[1];
4696       //"T_ABup="; ABup;
4697      if(ABup==1){t=0;}
4698     //if(equalideals(ABup,ideal(1))){t=0;}
4699      else
4700      {
4701        M=Crep(ABup,ABdw);
4702        //"T_M="; M;
4703        //if(not(equalideals(M[1],ideal(1)))) {L[size(L)+1]=M;}
4704        if(not(size(M)==0)) {L[size(L)+1]=M;}
4705      }
4706      //"L="; L;
4707      j++;
4708    }
4709    //LL[size(LL)+1]=L;
4710  }
4711  return(L);
4712}
4713example
4714{
4715echo = 2;
4716// EXAMPLE:
4717
4718if(defined(R)){kill R;}
4719ring R=(0,x,y,z,t),(x1,y1),lp;
4720ideal a1=x;
4721ideal a2=x,y;
4722ideal a3=x,y,z;
4723ideal a4=x,y,z,t;
4724
4725ideal b1=y;
4726ideal b2=y,z;
4727ideal b3=y,z,t;
4728ideal b4=1;
4729
4730list L1=a1,a2,a3,a4;
4731list L2=b1,b2,b3,b4;
4732
4733L1;
4734L2;
4735
4736def LL=DifConsLCSets(L1,L2);
4737LL;
4738
4739def LLL=ConsLevels(LL);
4740LLL;
4741
4742def LLLL=Levels(LLL);
4743LLLL;
4744}
4745
4746//**************************** End ConstrLevels ******************
4747
4748//******************** Begin locus and envelop ******************************
4749
4750// Routines for defining different rings acting in the basic ring RR=Q[a,x][u,v], in lp order, where
4751// a= parameters of the locus problem
4752// x= tracer variables
4753// u= auxiiary variables
4754// v= mover variables
4755
4756// Transforms the ringlist of Q[x_1,..,x_j] into the ringlist of Q[x_1,..,x_{n-1},x_{m+1},..,x_j]
4757//  I.e., deletes the varibles x_n  to x_m
4758// To be used with the  same order for all variables
4759static proc  Ldelnm(list LQx,int  n,int  m)
4760{
4761  int i;
4762  int npara= m- n+1;
4763  def RR=basering;
4764  def LR=LQx;
4765  int nt=size(LR[2]);
4766  def L1=LR[2];
4767  for(i=n;i<= m;i++) {L1=delete(L1,n);}
4768  LR[2]=L1;
4769  intvec v;
4770  for(i=1;i<=nt-npara;i++){v[i]=1;}
4771  LR[3][1][2]=v;
4772  return(LR);
4773}
4774
4775// Transforms the ringlist of Q[a][x] into the ringlist of Q[a,x]
4776// To be used with the same lp order
4777proc La_xToLax(list La_x)
4778{
4779  if(typeof(La_x[1])==typeof(0)){return(La_x);}
4780  list Lax=La_x[1];
4781  if(Lax[1]=0){return(La_x);}
4782  list Va=Lax[2];
4783  int na=size(Lax[2]);
4784  //"na=";na;
4785  list Vx=La_x[2];
4786  list Vax=Va+Vx;
4787  int nx=size(Vx);
4788  //"nx="; nx;
4789  intvec vv;
4790  int i;
4791  for(i=1;i<=na+nx;i++){vv[i]=1;}
4792  Lax[2]=Vax;
4793  Lax[3][1][2]=vv;
4794  return(Lax);
4795}
4796
4797// Transforms the ringlist of Q[a,x] into the ringlist of Q[a][x]
4798// To be used with the same lp order
4799proc LaxToLa_x(list Lax,int nx)
4800{
4801  //"T_Lax=",Lax;
4802  int nax=size(Lax[2]);
4803  int na=nax-nx;
4804  if(na==0){return(Lax);}
4805  else
4806  {
4807    //string("T_ na=",na,", nx=",nx);
4808    list La_x;
4809    list Vax=Lax[2];
4810    list Va;
4811    list Vx;
4812    int i;
4813    for(i=1;i<=na;i++){Va[size(Va)+1]=Vax[i];}
4814    intvec vva;
4815    for(i=1;i<=na;i++){vva[i]=1;}
4816    intvec vvx;
4817    for(i=1;i<=nx;i++){Vx[size(Vx)+1]=Vax[na+i];}
4818    for(i=1;i<=nx;i++){vvx[i]=1;}
4819    La_x[1]=Lax;
4820    La_x[1][2]=Va;
4821    La_x[1][3][1][2]=vva;
4822    La_x[2]=Vx;
4823    list lax3;
4824    lax3=Lax[3];
4825    lax3[1][2]=vvx;
4826    La_x[3]=lax3;
4827    La_x[4]=Lax[4];
4828    return(La_x);
4829  }
4830}
4831
4832//  // Transforms the ringlist of Q[a,x] into the ringlist of Q[a][x]
4833//  // To be used with the same lp order
4834//  proc LaxToLa_x(list Lax,int nx)
4835//  {
4836//    //"T_Lax=",Lax;
4837//    int nax=size(Lax[2]);
4838//    int na=nax-nx;
4839//    if(na==0){return(Lax);}
4840//    else
4841//    {
4842//      //string("T_ na=",na,", nx=",nx);
4843//      list La_x;
4844//      list Vax=Lax[2];
4845//      list Va;
4846//      list Vx;
4847//      int i;
4848//      for(i=1;i<=na;i++){Va[size(Va)+1]=Vax[i];}
4849//      intvec vva;
4850//      for(i=1;i<=na;i++){vva[i]=1;}
4851//      intvec vvx;
4852//      for(i=1;i<=nx;i++){Vx[size(Vx)+1]=Vax[na+i];}
4853//      for(i=1;i<=nx;i++){vvx[i]=1;}
4854//      La_x[1]=Lax;
4855//      La_x[1][2]=Va;
4856//      La_x[1][3][1][2]=vva;
4857//      La_x[2]=Vx;
4858//      list lax3;
4859//      lax3=Lax[3];
4860//      lax3[1][2]=vvx;
4861//      La_x[3]=lax3;
4862//      La_x[4]=Lax[4];
4863//      return(La_x);
4864//    }
4865//  }
4866
4867//  proc Lax_uvToLa_v(list Lax_uv,int na, int nv)
4868//  {
4869//    int i;
4870//    def Lax=Lax_uv[1];
4871//    int nax=size(Lax[2]);
4872//    int nuv=size(Lax_uv[2]);
4873//    def La=Lax;
4874//    list La2;
4875//    if(na===0){
4876//      list Luv=Lax_uv;
4877//      Luv[1]=0;
4878//      list Lv=
4879//      ;
4880//
4881//    }
4882//    for(i=1;i<=na;i++){}
4883//  }
4884
4885// Transforms the set of ringlists of Q[a] and Q[x] into the ringlist of Q[a][x]
4886// To be used with the same lp order
4887proc LaLxToLa_x(list La,list Lx)
4888{
4889  if(size(La)==0){return(Lx);}
4890  def L1=La;
4891  def L2=Lx;
4892  list L;
4893  L[1]=L1;
4894  L[2]=L2[2];
4895  L[3]=L2[3];
4896  L[4]=L2[4];
4897  return(L);
4898}
4899
4900// Transforms the ringlist of Q[a,x] into the ring of Q[a]
4901//  proc LaxToLa(list Lax, int na)
4902//  {
4903//    int ntot=size(Lax[2]);
4904//    list La=Lax;
4905//    int i;
4906//    list V;
4907//    for(i=1;i<=ntot-na;i++){V[i]=Lax[2][na+i];}
4908//    La[2]=V;
4909//    intvec vv;
4910//    for(i=1;i<=ntot-na;i++){vv[i]=1;}
4911//    La[3][1][2]=vv;
4912//    return(La);
4913//  }
4914
4915
4916// Transforms the set of ringlists of Q[a] and Q[x] into the ringlist of Q[a,x]
4917// To be used with the same lp order
4918proc LaLxToLax(list La,list Lx)
4919{
4920  list L=LaLxToLa_x(La,Lx);
4921  list Lax=La_xToLax(L);
4922  return(Lax);
4923}
4924
4925// Transforms the ringlist of Q[a,x] into the ringlist of Q[a]
4926// To be used with the same lp order
4927proc LaxToLa(list Lax,int na)
4928{
4929  list La;
4930  if(na==0){return(La);}
4931  else
4932  {
4933    La=Lax;
4934    list La2;
4935    for(i=1;i<=na;i++){La2[i]=Lax[2][i];}
4936    La[2]=La2;
4937    intvec va;
4938    for(i=1;i<=na;i++){va[i]=1;}
4939    La[3][1][2]=va;
4940    return(La);
4941  }
4942}
4943
4944// Transforms the ringlist of Q[a,x][u,v] into the ringlist of Q[a][v]
4945// To be used with the same lp order
4946proc Lax_uvToLa_v(list Lax_uv,int na, int nv)
4947{
4948  //string("T_na=",na,"; nv=",nv);
4949  int i;
4950  list Lax=Lax_uv[1];
4951  int nax=size(Lax[2]);
4952  int nuv=size(Lax_uv[2]);
4953  list Lv=Lax_uv;
4954  int nx=nax-na;
4955  int nu=nuv-nv;
4956  Lv[1]=0;
4957  list Lv2;
4958  intvec vv;
4959  for(i=1;i<=nv;i++){Lv2[i]=Lv[2][nu+i];}
4960  for(i=1;i<=nv;i++){vv[nu+i]=1;}
4961  Lv[2]=Lv2;
4962  Lv[3][1][2]=vv;
4963  if(na==0){return(Lv);}
4964  else
4965  {
4966    list La=Lax;
4967    list La2;
4968    intvec va;
4969    for(i=1;i<=na;i++){La2[i]=Lax[2][i];}
4970    for(i=1;i<=na; i++){va[i]=1;}
4971    La[2]=La2;
4972    La[3][1][2]=va;
4973    //"T_La="; La;
4974    //"T_Lv="; Lv;
4975    list La_v=LaLxToLa_x(La,Lv);
4976    return(La_v);
4977  }
4978}
4979
4980// Transforms the ringlist of Q[a,x] [u,v]into the ringlist of Q[x,u,a,v]
4981// To be used with the same lp order
4982proc Lax_uvToLxuav(list Lax_uv, int na, int nv)
4983{
4984  //string("T_na=",na,"; nv=",nv);
4985  int i;
4986  //"T_Lax_uv="; Lax_uv;
4987  int nax=size(Lax_uv[1][2]);
4988  int nuv=size(Lax_uv[2]);
4989  int nx=nax-na;
4990  int nu=nuv-nv;
4991  //string("T_nax=",nax,"; nuv=",nuv,"; nx=",nx,"; nu=",nu);
4992  list Lxuav=Lax_uv[1];
4993  list L2;
4994  for(i=1;i<=nx;i++){L2[i]=Lax_uv[1][2][na+i];}
4995  for(i=1;i<=nu;i++){L2[nx+i]=Lax_uv[2][i];}
4996  for(i=1;i<=na;i++){L2[nx+nu+i]=Lax_uv[1][2][i];}
4997  for(i=1;i<=nv;i++){L2[nx+nu+na+i]=Lax_uv[2][nu+i];}
4998  Lxuav[2]=L2;
4999  intvec vv;
5000  for(i=1;i<=nax+nuv;i++){vv[i]=1;}
5001  Lxuav[3][1][2]=vv;
5002  return(Lxuav);
5003}
5004
5005
5006
5007// indepparameters
5008// Auxiliary routine to detect 'Special' components of the locus
5009// Input: ideal B
5010// Output:
5011//   1 if the ideal does not depend on the parameters
5012//   0 if they depend
5013static proc indepparameters(ideal B)
5014{
5015  def RR=basering;
5016  list Rx=ringlist(RR);
5017  def P=ring(Rx[1]);
5018  Rx[1]=0;
5019  def D=ring(Rx);
5020  def RP=D+P;
5021    // if(defined(@P)){kill @P; kill @RP; kill @R;}
5022   //  setglobalrings();
5023   ideal v=variables(B);
5024  setring RP;
5025  def BP=imap(RR,B);
5026  def vp=imap(RR,v);
5027  ideal varpar=variables(BP);
5028  int te;
5029  te=equalideals(vp,varpar);
5030  setring(RR);
5031  // kill @P; kill @RP; kill @R;
5032  if(te){return(1);}
5033  else{return(0);}
5034}
5035
5036// indepparameterspoly
5037// Auxiliary routine to detect 'Special' components of the locus
5038// Input: ideal B
5039// Output:
5040//   1 if the solutions of the ideal (or poly) does not depend on the parameters
5041//   0 if they depend
5042static proc indepparameterspoly(B)
5043{
5044  def RR=basering;
5045  list Rx=ringlist(RR);
5046  def P=ring(Rx[1]);
5047  Rx[1]=0;
5048  def D=ring(Rx);
5049  def RP=D+P;
5050    // if(defined(@P)){kill @P; kill @RP; kill @R;}
5051   //  setglobalrings();
5052   ideal v=variables(B);
5053  setring RP;
5054  def BP=imap(RR,B);
5055  def vp=imap(RR,v);
5056  ideal varpar=variables(BP);
5057  int te;
5058  te=equalideals(vp,varpar);
5059  setring(RR);
5060  // kill @P; kill @RP; kill @R;
5061  if(te){return(1);}
5062  else{return(0);}
5063}
5064
5065// dimP0: Auxiliary routine
5066// if the dimension in @P of an ideal in the parameters has dimension 0 then it returns 0
5067// else it returns 1
5068static proc dimP0(ideal N)
5069{
5070  def RR=basering;
5071  def Rx=ringlist(RR);
5072  def P=ring(Rx[1]);
5073  setring P;
5074  // if(defined(@P)){ kill @P; kill @RP; kill @R;}
5075  // setglobalrings();
5076  // setring(@P);
5077  int te=1;
5078  def NP=imap(RR,N);
5079  attrib(NP,"IsSB",1);
5080  int d=dim(std(NP));
5081  //"T_d="; d;
5082  if(d==0){te=0;}
5083  setring(RR);
5084  return(te);
5085}
5086
5087//  DimPar(E,nax,nx):
5088//  Auxilliary routine of locus2 determining the dimension of a component of the locus in
5089//  the ring Q[a][x]
5090 static proc DimPar(ideal E,nax,nx)
5091 {
5092   //" ";"T_E in DimPar="; E;
5093   def RRH=basering;
5094   def RHx=ringlist(RRH);
5095   def P=ring(RHx[1]);
5096   list Lax=ringlist(P);
5097   //"Lax="; Lax;
5098   //int nax=size(Lax[2]);
5099   int na=nax-nx;
5100   //string("T_na=",na,"; nx=",nx);
5101   list La_x=LaxToLa_x(Lax,nx);
5102   //"T_La_x="; La_x;
5103   def Qa_x=ring(La_x);
5104   setring(Qa_x);
5105   //setring(P);
5106   def E2=std(imap(RRH,E));
5107   //"T_E2 in DimPar="; E2;
5108   attrib(E2,"IsSB",1);
5109   def d=dim(E2);
5110   //string("T_d in DimPar=", d);" ";
5111   setring RRH;
5112   return(d);
5113 }
5114
5115//     DimComp
5116//     Auxilliary routine of locus2 determining the dimension of a parametric ideal
5117//     it is identical to DimPar but adds infromation about the character of the component
5118 static proc DimComp(ideal PA, int nax,int nx)
5119 {
5120//     def RR=basering;
5121//     list Rx=ringlist(RR);
5122//     int nax=size(Rx[1][2]);
5123//     int na=nax-nx;
5124//     def P=ring(Rx[1]);
5125//     setring(P);
5126//     list Lout;
5127//     def CP=imap(RR,PA);
5128//     attrib(CP,"IsSB",1);
5129//     int d=dim(std(CP));
5130
5131   list Lout;
5132   int d=DimPar(PA,nax,nx);
5133   if(d==nax-1){Lout[1]=d;Lout[2]="Degenerate"; }
5134   else {Lout[1]=d; Lout[2]="Accumulation";}
5135   //"T_Lout="; Lout;
5136   setring RR;
5137   return(Lout);
5138}
5139
5140// Takes a list of intvec and sorts it and eliminates repeated elements.
5141// Auxiliary routine
5142static proc sortpairs(L)
5143{
5144  def L1=sort(L);
5145  def L2=elimrepeated(L1[1]);
5146  return(L2);
5147}
5148
5149// Eliminates the pairs of L1 that are also in L2.
5150// Auxiliary routine
5151static proc minuselements(list L1,list L2)
5152{
5153  int i;
5154  list L3;
5155  for (i=1;i<=size(L1);i++)
5156  {
5157    if(not(memberpos(L1[i],L2)[1])){L3[size(L3)+1]=L1[i];}
5158  }
5159  return(L3);
5160}
5161
5162static proc determineF(ideal A,poly F,ideal E)
5163{
5164  int env; int i;
5165  def RR=basering;
5166  def RH=ringlist(RR);
5167  def H=RH;
5168  H[1]=0;
5169  H[2]=RH[1][2]+RH[2];
5170  int n=size(H[2]);
5171  intvec ll;
5172  for(i=1;i<=n;i++)
5173  {
5174    ll[i]=1;
5175  }
5176  H[3][1][1]="lp";
5177  H[3][1][2]=ll;
5178  def RRH=ring(H);
5179
5180        //" ";string("Anti-image of Special component = ", GGG);
5181
5182   setring(RRH);
5183   list LL;
5184   def AA=imap(RR,A);
5185   def FH=imap(RR,F);
5186   def EH=imap(RR,E);
5187   ideal M=std(AA+FH);
5188   def rh=reduce(EH,M,5);
5189   //"T_AA="; AA; "T_FH="; FH; "T_EH="; EH; "T_rh="; rh;
5190   if(rh==0){env=1;} else{env=0;}
5191   setring RR;
5192          //L0[3]=env;
5193    //"T_env="; env;
5194    return(env);
5195}
5196
5197
5198
5199// locus2(G,F,moverdim,vmov,na):
5200//                Private routine used by locus (the public routine), that
5201//                builds the different component, and inputs for locus2
5202// input:      G= grobcov(S), already computed inside locus
5203//                F= the ideal defining the locus problem (G is the grobcov of F and has been
5204//                moverdim=number of mover variables
5205//                vmov= the ideal of the mover variables
5206//                already determined by locus.
5207//                na= number of parameteres of the locus problem (usually=0);
5208//                The arguments are determined by locus, and passed to locus2.
5209// output:
5210//         list, the canonical P-representation of the Normal and Non-Normal locus:
5211//              The Normal locus has two kind of components: Normal and Special.
5212//              The Non-normal locus has two kind of components: Accumulation and Degenerate.
5213//              This routine is compemented by locus that calls it in order to eliminate problems
5214//              with degenerate points of the mover.
5215//         The output components are given as
5216//              ((p1,(p11,..p1s_1),type_1,level_1),..,(pk,(pk1,..pks_k),type_k,level_k)
5217//         The components are given in canonical P-representation of the subset.
5218//              If all levels of a class of locus are 1, then the set is locally closed. Otherwise the level
5219//              gives the depth of the component.
5220static proc locus2(list G, ideal F, int moverdim, ideal vmov, int na)
5221{
5222   int st=timer;
5223   list Snor; list Snonor;
5224   int d; int i; int j; //int mt=0;
5225   def RR=basering;
5226   def Rx=ringlist(RR);
5227   def RP=ring(Rx[1]);
5228   def LP=ringlist(RP);
5229   int nax=size(LP[2]);
5230   int nx=nax-na;
5231   int nv=moverdim;
5232   int tax=1;
5233   list GG=G;
5234   int n=size(Rx[1][2]);
5235   for(i=1;i<=size(GG);i++)
5236   {
5237     attrib(GG[i][1],"IsSB",1);
5238     GG[i][1]=std(GG[i][1]);
5239     d=dim(GG[i][1]);
5240     if(d==0)
5241     {
5242       for(j=1;j<=size(GG[i][3]);j++)
5243       {
5244         Snor[size(Snor)+1]=GG[i][3][j];
5245       }
5246     }
5247     else
5248     {
5249       if(d>0)
5250       {
5251         for(j=1;j<=size(GG[i][3]);j++)
5252         {
5253           Snonor[size(Snonor)+1]=GG[i][3][j];
5254        }
5255       }
5256     }
5257   }
5258   //"T_Snor="; Snor;
5259   //"T_Snonor="; Snonor;
5260   int tnor=size(Snor); int tnonor=size(Snonor);
5261   setring RP;
5262   list SnorP;
5263   list SnonorP;
5264   if(tnor)
5265   {
5266     SnorP=imap(RR,Snor);
5267     st=timer;
5268     SnorP=LCUnionN(SnorP);
5269   }
5270   if(tnonor)
5271   {
5272     SnonorP=imap(RR,Snonor);
5273     SnonorP=LCUnionN(SnonorP);
5274   }
5275   //"T_SnorP after LCUnion="; SnorP;
5276   // "T_SnonorP  after LCUnion="; SnonorP;
5277   setring RR;
5278   ideal C;  list N;  list BAC; list AI;
5279   list NSC; list DAC;
5280   list L;
5281   ideal B;
5282   int k;
5283   int j0; int k0; int te;
5284   poly kkk=1;
5285   ideal AI0;
5286   int dimP;
5287
5288   if(tnor)
5289   {
5290     Snor=imap(RP,SnorP);
5291     for(i=1;i<=size(Snor);i++)
5292     {
5293       C=Snor[i][1];
5294       N=Snor[i][2];
5295       dimP=DimPar(C,nax,nx);
5296        //"T_G="; G;
5297       AI=NS(F,G,C,N,moverdim,na,vmov,dimP);
5298       Snor[i][size(Snor[i])+1]=AI;
5299     }
5300     for(i=1;i<=size(Snor);i++)
5301     {
5302       L[size(L)+1]=Snor[i];
5303     }
5304    }
5305    ideal AINN;
5306   if(tnonor)
5307   {
5308     Snonor=imap(RP,SnonorP);
5309     //"T_Snonor="; Snonor;
5310     //"T_G="; G;
5311     for(i=1;i<=size(Snonor);i++)
5312     {
5313       DAC=DimComp(Snonor[i][1],nax,nx);
5314       Snonor[i][size(Snonor[i])+1]=DAC;
5315     }
5316     for(i=1;i<=size(Snonor);i++)
5317     {
5318       L[size(L)+1]=Snonor[i];
5319     }
5320   }
5321  return(L);
5322}
5323
5324// Auxilliary algorithm of locus2.
5325//           The algorithm searches the basis corresponding to C, in the grobcov.
5326//           It reduces the basis modulo the component.
5327//           The result is the reduced basis BR.
5328//           For each hole of the component
5329//              it searches the segment where the hole is included
5330//              and selects the polynomials from its basis
5331//              only dependent on the variables.
5332//              These polynomials are non-null in an open set of
5333//              the component, and are included in the list NoNul of non-null factors
5334// input: F: the ideal of the locus problem
5335//           G the grobcov of F
5336//           C the top of a component of normal points
5337//           N the holes of the component
5338// output: (d,tax,a)
5339//           where d is the dimension of the anti-image
5340//           a is the anti-image of the component and
5341//           tax is the taxonomy \"Normal\" if d is equal to the dimension of C
5342//           and \"Special\" if it is smaller.
5343//           When a normal point component has degree greater than 9, then the
5344//           taxonomy is not determined, and (n,'normal', 0) is returned as third
5345//           element of the component. (n is the dimension of the space).
5346static proc NS(ideal F,list G, ideal C, list N, int nv, int na,ideal vmov,int dimC)
5347{
5348  // Initializing and defining rings
5349   int i; int j; int k; int te; int j0;int k0; int m;
5350   def RR=basering;
5351   def Lax_uv=ringlist(RR);
5352   Lax_uv[3][1][1]="lp";
5353   int nax=size(Lax_uv[1][2]);
5354   int nuv=size(Lax_uv[2]);
5355   int nx=nax-na;
5356   int nu=nuv-nv;
5357   //"Lax_uv="; Lax_uv;
5358    def Lax=Lax_uv[1];
5359    def Qax=ring(Lax);                                  // ring Q[a,x]
5360   //"T_Lax="; Lax;
5361   def La_x=LaxToLa_x(Lax,nx);                   // ring Q[a][x]
5362   //"T_La_x="; La_x;
5363   def  La_v=Lax_uvToLa_v(Lax_uv,na,nv);    // ring Q[a][v]
5364   //"T_La_v="; La_v;
5365   def  Lxuav=Lax_uvToLxuav(Lax_uv,na,nv);
5366  //"T_Lxuav="; Lxuav;
5367
5368
5369  // old rings
5370  def Rx=ringlist(RR);
5371  def Lx=Rx;
5372  def P=ring(Rx[1]);                 // ring Q[a,x]]
5373  Lx[1]=0;
5374  def D=ring(Lx);                     // ring Q[u,v]
5375  def PR0=P+D;                       // ring Q[a,x,u,v]
5376  def PRx=ringlist(PR0);
5377  PRx[3][2][1]="lp";
5378  // "T_PRx="; PRx;
5379  def PR=ring(PRx);                 // ring Q[a,x,u,v]  in lex order
5380  // end of old rings
5381
5382  for(i=1;i<=nv;i++)
5383  {
5384    vmov[size(vmov)+1]=var(i+nuv-nv);
5385  }
5386  //string("T_nv=",nv,"  moverdim=",nv);
5387  int ddeg; int dp;
5388  list LK;
5389  ideal bu;                               // ideal of all variables   (u)
5390  for(i=1;i<=nv;i++){bu[i]=var(i);}
5391  ideal mv;
5392   for(i=1;i<=nv;i++){mv[size(mv)+1]=var(i);}
5393
5394   // Searching the basis associated to C
5395   j=2; te=1;
5396   while((te) and (j<=size(G)))
5397   {
5398      k=1;
5399      while((te) and (k<=size(G[j][3])))
5400      {
5401        if (equalideals(C,G[j][3][k][1])){j0=j; k0=k; te=0;}
5402        k++;
5403      }
5404      j++;
5405   }
5406   if(te==1){"ERROR";}
5407   def B=G[j0][2];  // Aixo aniria be per les nonor
5408   //"T_B=G[j0][2]="; B;
5409   //string("T_k0=",k0," G[",j0,"]="); G[j0];
5410
5411   // Searching the elements in Q[v_m]  on basis differents from B that are nul there
5412   // and cannot become 0 on the antiimage of B. They are placed on NoNul
5413   list NoNul;
5414   ideal BNoNul;
5415   ideal covertop;           // basis of the segment where a hole of C is the top
5416   int te1;
5417   for(i=1;i<=size(N);i++)
5418   {
5419     j=2; te=1;
5420     while(te and j<=size(G))
5421     {
5422       if(j!=j0)
5423       {
5424         k=1;
5425         while(te and k<=size(G[j][3]))
5426         {
5427           covertop=G[j][3][k][1];
5428           if(equalideals(covertop,N[i]))
5429           {
5430             te=0; te1=1; BNoNul=G[j][2];
5431            }
5432           else
5433           {
5434             if(redPbasis(covertop,N[i]))
5435             {
5436               te=0; te1=1; m=1;
5437               while( te1 and m<=size(G[j][3][k][2]) )
5438               {
5439                 if(equalideals(G[j][3][k][2][m] ,N[i] )==1){te1=0;}
5440                 m++;
5441               }
5442             }
5443             if(te1==1){ BNoNul=G[j][2];}
5444           }
5445           k++;
5446         }
5447
5448         if((te==0) and (te1==1))
5449         {
5450          // Selecting the elements independent of the parameters,
5451          // They will be non null on the segment
5452           for(m=1;m<=size(BNoNul);m++)
5453           {
5454             if(indepparameterspoly(BNoNul[m]))
5455             {
5456                NoNul[size(NoNul)+1]=BNoNul[m];
5457             }
5458           }
5459         }
5460       }
5461       j++;
5462    }
5463  }
5464
5465  // Adding F to B
5466  for(i=1;i<=size(F);i++)
5467  {
5468    B[size(B)+1]=F[i];
5469  }
5470
5471  def E=NoNul;
5472  poly kkk=1;
5473  if(size(E)==0){E[1]=kkk;}
5474
5475  // Avoiding computations that are too expensive for obtaining
5476  //   the anti-image of normal point components
5477  setring(P);
5478  def CP=imap(RR,C);
5479  ddeg=deg(CP);
5480  setring(RR);
5481  // if(n+nv>10 or ddeg>=10){LK=n,ideal(0),"normal"; return(LK);}
5482  if(ddeg>=10){LK=nv,ideal(0),"normal"; return(LK);}  // 8 instead of 10 ?
5483
5484  // Reducing  basis B modulo C  in the ring PR      lex(x,u)
5485  // setring(PR);
5486
5487  def Qxuav=ring(Lxuav);
5488  setring(Qxuav);
5489  def BR=imap(RR,B);
5490  ideal vamov;
5491  for(i=nx+nu+1;i<=nax+nuv;i++){vamov[size(vamov)+1]=var(i);}
5492
5493  //BR=std(BR);
5494  def CC=imap(RR,C);
5495  for(i=1;i<=size(CC);i++){BR[size(BR)+1]=CC[i];}
5496  BR=std(BR);
5497 // for(i=1;i<=size(CC);i++){BR[size(BR)+1]=CC[i];}
5498  attrib(CC,"IsSB",1);
5499  ideal AIM;
5500 // "T_BR="; BR;
5501  for(i=1;i<=size(BR);i++){if(subset(variables(BR[i]),vamov)){AIM[size(AIM)+1]=BR[i];}}
5502  //"T_AIM="; AIM;
5503
5504  list La_v0=imap(RR,La_v);
5505  def Qa_v=ring(La_v0);
5506  setring Qa_v;
5507  def AIMa_v=imap(Qxuav,AIM);
5508  AIMa_v=std(AIMa_v);
5509  int dimAIM=dim(AIMa_v);
5510  //"T_AIMa_v="; AIMa_v;
5511  //string("T_dimAIM=",dimAIM);
5512  setring(RR);
5513  def AIMRR=imap(Qa_v,AIMa_v);
5514  string TaxComp;
5515  if(dimAIM==dimC){TaxComp="Normal";}
5516  else{TaxComp="Special";}
5517  list NSA=dimAIM,TaxComp,AIMRR;
5518  return(NSA);
5519}
5520
5521static proc DimM(ideal KKM, int na, int nv)
5522{
5523  def RR=basering;
5524  list L;
5525  int i;
5526  def Rx=ringlist(RR);
5527
5528  for(i=1;i<=nv;i++)
5529  {
5530    L[i]=Rx[2][nv-nm+i];
5531  }
5532  Rx[2]=L;
5533  intvec iv;
5534  for(i=1;i<=nm;i++){iv[i]=1;}
5535  Rx[3][1][2]=iv;
5536   def DM=ring(Rx);
5537  //"Rx="; Rx;
5538  setring(DM);
5539  ideal KKMD=imap(RR,KKM);
5540  attrib(KKMD,"IsSB",1);
5541  KKMD=std(KKMD);
5542  int d=dim(KKMD);
5543  setring(RR);
5544  def KAIM=imap(DM,KKMD);
5545  list LAIM=d,KAIM;
5546 // "T_LAIM="; LAIM;
5547  return(LAIM);
5548}
5549
5550// Procedure using only standard GB in lex(x,a) order to obtain the
5551//    component of the locus.
5552//    It is not so fine as locus and cannot evaluate the taxonomy, but
5553//    it is much simpler and efficient.
5554// input: ideal S for determining the locus
5555// output: the irreducible components of the locus
5556//    Data must be given in Q[a][x]
5557proc stdlocus(ideal F)
5558"USAGE: stdlocus(ideal F)
5559       The input ideal must be the set equations defining the locus.
5560       Calling sequence: locus(F);
5561       The input ring must be a parametrical ideal in Q[x][u],
5562       (x=tracer variables, u=remaining variables).
5563       (Inverts the concept of parameters and variables of the ring).
5564       Special routine for determining the locus of points of  a geometrical construction.
5565       Given a parametric ideal F representing the system determining the locus of points (x)
5566       which verify certain properties, the call to stdlocus(F)
5567       determines the different irreducible components of the locus.
5568       This is a simple routine, using only standard Groebner basis computation,
5569       elimination and prime decomposition instead of using grobcov.
5570       It does not determine the taxonomy, nor the holes of the components
5571RETURN:The output is a list of the tops of the components [C_1, .. , C_n] of the locus.
5572       Each component is given its top ideal p_i.
5573NOTE: The input must be the locus system.
5574KEYWORDS: geometrical locus; locus
5575EXAMPLE: stdlocus; shows an example"
5576{
5577  int i; int te;
5578  def RR=basering;
5579  list Rx=ringlist(RR);
5580  int n=npars(RR);  // size(Rx[1][2]);
5581  int nv=nvars(RR);
5582  ideal vpar;
5583  ideal vvar;
5584  //"T_n="; n;
5585   //"T_nv="; nv;
5586  for(i=1;i<=n;i++){vpar[size(vpar)+1]=par(i);}
5587  for(i=1;i<=nv;i++){vvar[size(vvar)+1]=var(i);}
5588  //string("T_vpar = ", vpar," vvar = ",vvar);
5589  def P=ring(Rx[1]);
5590  Rx[1]=0;
5591  def D=ring(Rx);
5592  def RP=D+P;
5593  list Lx=ringlist(RP);
5594  setring(RP);
5595  def FF=imap(RR,F);
5596  def vvpar=imap(RR,vpar);
5597  //string("T_vvpar = ",vvpar);
5598  ideal B=std(FF);
5599  //"T_B="; B;
5600  ideal Bel;
5601  //"T_vvpar="; vvpar;
5602  for(i=1;i<=size(B);i++)
5603  {
5604    if(subset(variables(B[i]),vvpar)) {Bel[size(Bel)+1]=B[i];}
5605  }
5606  //"T_Bel="; Bel;
5607  list H;
5608  list FH;
5609  H=minAssGTZ(Bel);
5610  int t1;
5611  if(size(H)==0){t1=1;}
5612  setring RR;
5613  list empt;
5614  if(t1==1){return(empt);}
5615  else
5616  {
5617    def HH=imap(RP,H);
5618    return(HH);
5619  }
5620}
5621example
5622{
5623  "EXAMPLE:"; echo = 2;
5624if(defined(R)){kill R;}
5625ring R=(0,x,y),(x1,y1),dp;
5626short=0;
5627
5628// Concoid
5629ideal S96=x1 ^2+y1 ^2-4,(x-2)*x1 -x*y1 +2*x,(x-x1 )^2+(y-y1 )^2-1;
5630
5631stdlocus(S96);
5632}
5633
5634//  locus(F):  Special routine for determining the locus of points
5635//                 of  geometrical constructions.
5636//  input:      The ideal of the locus equations defined in the
5637//                 ring Q[a1,..,ap,x1,..xn][u1,..um,v1,..vn]
5638//  output:
5639//          The output components are given as
5640//               ((p1,(p11,..p1s_1),tax_1),..,(pk,(pk1,..pks_k),tax_k)
5641//               Elements 1 and 2 represent the P-canonical form of the component.
5642//               The third element tax is:
5643//                 for normal point components, tax=(d,taxonomy,anti-image)
5644//                    being d=dimension of the anti-image on the mover variables,
5645//                           taxonomy='Normal'  or  'Special', and
5646//                           anti-image=ideal of the anti-image over the mover variables
5647//                                which by default are taken to be the last n variables.
5648//                 for non-normal point components, tax =(d,taxonomy)
5649//                    being d=dimension of the component  and
5650//                           taxonomy='Accumulation' or 'Degenerate'.
5651//          The components are given in canonical P-representation of the subset.         l
5652//          The normal locus has two kind of components: Normal and Special.
5653//            Normal component:
5654//            - each point in the component has 0-dimensional anti-image.
5655//            - the anti-image in the mover coordinates is equal to the dimension of the component.
5656//            Special component:
5657//            - each point in the component has 0-dimensional anti-image.
5658//            - the anti-image on the mover variables is smaller than the dimension of the component.
5659//          The non-normal locus has two kind of components: Accumulation and Degenerate.
5660//           Accumulation points:
5661//             - each point in the component has anti-image of dimension greater than 0.
5662//             - the component has dimension less than n-1.
5663//           Degenerate components:
5664//             - each point in the component has anti-image of dimension greater than 0.
5665//             - the component has dimension n-1.
5666//           When a normal point component has degree greater than 9, then the
5667//           taxonomy is not determined, and (n,'normal', 0) is returned as third
5668//           element of the component. (n is the dimension of the space).
5669proc locus(ideal F, list #)
5670"USAGE:  locus(ideal F [,options])
5671        Special routine for determining the locus of points of
5672        a geometrical construction.
5673INPUT:  The input ideal must be the ideal of the set equations
5674        defining the locus, defined in the ring
5675        ring Q(0,a1,..,ap,x1,..xn)(u1,..um,v1,..vn),lp;
5676        Calling sequence:
5677        locus(F [,options]);
5678        a=fixed parameters,x=tracer variables, u=auxiliary variables, v=mover variables.
5679        The parameters a are optative. If they are used, then the option \"numpar\=,np
5680        must be declared, being np the number of fixed parameters.
5681        The tracer variables are x1,..xn, where n is the dimension of the space.
5682        By default, the mover variables are the last n variables.
5683        Its number can be forced by the user to the last
5684        k variables by adding the option \"moverdim\",k.
5685        Nevertheless, this option is recommended only
5686        to experiment, and can provide incorrect taxonomies.
5687        The remaining variables are auxiliary.
5688OPTIONS: An option is a pair of arguments: string, integer.
5689        To modify the default options, pairs of arguments
5690        -option name, value- of valid options must be added to
5691        the call.The algorithm allows the following options as
5692        pair of arguments:
5693
5694        \"numpar\", np  in order to consider the first np parameters of the ring
5695        to be fixed parameters of the locus, being the tracer variables
5696        the remaining parameters.
5697        To be used for a paramteric locus. (New in release N12).
5698
5699        \"moverdim\", k  to force the mover-variables to be the last
5700         k variables. This determines the antiimage and its dimension.
5701        By defaulat k is equal to the last n variables,
5702        We can experiment with a different value,
5703        but this can produce an error in the character
5704         \"Normal\" or \"Special\" of a locus component.
5705
5706        \"grobcov\", G, where G is the list of a previous computed grobcov(F).
5707        It is to be used when we modify externally the grobcov,
5708        for example to obtain the real grobcov.
5709
5710        \"comments\", c: by default it is 0, but it can be set to 1.
5711RETURN: The output is a list of the components:
5712        ((p1,(p11,..p1s_1),tax_1), .., (pk,(pk1,..pks_k),tax_k)
5713        Elements 1 and 2 of a component represent the
5714        P-canonical form of the component.
5715        The third element tax is:
5716          for normal point components,
5717            tax=(d,taxonomy,anti-image) being
5718             d=dimension of the anti-image on the mover variables,
5719             taxonomy=\"Normal\"  or  \"Special\" and
5720             anti-image=ideal of the anti-image over the mover
5721             variables.
5722          for non-normal point components,
5723            tax =(d,taxonomy) being
5724             d=dimension of the component  and
5725             taxonomy=\"Accumulation\" or \"Degenerate\".
5726        The components are given in canonical P-representation.
5727        The normal locus has two kind of components:
5728          Normal and Special.
5729          Normal component:
5730           - each point in the component has 0-dimensional
5731              anti-image.
5732           - the anti-image in the mover coordinates is equal
5733              to the dimension of the component
5734          Special component:
5735           - each point in the component has 0-dimensional
5736              anti-image.
5737           - the anti-image in the mover coordinates has dimension
5738              smaller than the dimension of the component
5739        The non-normal locus has two kind of components:
5740          Accumulation and Degenerate.
5741          Accumulation component:
5742           - each point in the component has anti-image of
5743              dimension greater than 0.
5744           - the component has dimension less than n-1.
5745         Degenerate components:
5746           - each point in the component has anti-image
5747              of dimension greater than 0.
5748           - the component has dimension n-1.
5749       When a normal point component has degree greater than 9,
5750         then the taxonomy is not determined, and (n,'normal', 0)
5751         is returned as third element of the component. (n is the
5752         dimension of the tracer space).
5753
5754       Given a parametric ideal F representing the system F
5755       determining the locus of points (x) which verify certain
5756       properties, the call to locus(F) determines the different
5757       classes of locus components, following the taxonomy
5758       defined in the book:
5759       A. Montes. \"The Groebner Cover\"
5760       A previous paper gives particular definitions
5761       for loci in 2d.
5762       M. Abanades, F. Botana, A. Montes, T. Recio,
5763       \"An Algebraic Taxonomy for Locus Computation
5764       in Dynamic Geometry\",
5765       Computer-Aided Design 56 (2014) 22-33.
5766NOTE: The input must be the locus system.
5767KEYWORDS: geometrical locus; locus; dynamic geometry
5768EXAMPLE: locus; shows an example"
5769{
5770  int tes=0; int i;  int m; int mm; // int n;
5771  def RR=basering;
5772  list GG;
5773  //Options
5774  list DD=#;
5775  int nax=npars(RR);              // number of parameters + tracer variables
5776  int nuv=nvars(RR);                                 // number of variables
5777  int na=0; int nx=nax;
5778  int moverdim=nx;                                  // number of tracer variables
5779  if(moverdim>nuv){moverdim=nuv;}
5780//  int version=2;
5781  int comment=0;
5782  int tax=1;
5783  ideal Fm;
5784  for(i=1;i<=(size(DD) div 2);i++)
5785  {
5786    if(DD[2*i-1]=="numpar"){na=DD[2*i]; nx=nax-na; moverdim=nx;}
5787    if(DD[2*i-1]=="comment"){comment=DD[2*i];}
5788    if(DD[2*i-1]=="grobcov"){GG=DD[2*i];}
5789  }
5790  for(i=1;i<=(size(DD) div 2);i++)
5791  {
5792    if(DD[2*i-1]=="moverdim"){moverdim=DD[2*i];}
5793  }
5794  int nv=moverdim;
5795  if(moverdim>nuv){moverdim=nuv;}
5796
5797  ideal vmov;
5798  //string("T_nuv=",nuv,"; moverdim=",moverdim);
5799  for(i=1;i<=moverdim;i++){vmov[size(vmov)+1]=var(i+nuv-moverdim);}
5800  if(size(GG)==0){GG=grobcov(F);}
5801  int j; int k; int te;
5802  def B0=GG[1][2];
5803  def H0=GG[1][3][1][1];
5804  list nGP;
5805  if (equalideals(B0,ideal(1)) )
5806  {return(locus2(GG,F,moverdim,vmov,na));}
5807  else
5808  {
5809    ideal vB;
5810    ideal N;
5811    for(i=1;i<=size(B0);i++)
5812    {
5813      if(subset(variables(B0[i]),vmov)){N[size(N)+1]=B0[i];}
5814    }
5815    attrib(N,"IsSB",1);
5816    N=std(N);
5817    if((size(N))>=2)
5818    {
5819       //def dN=dim(N);
5820       te=indepparameters(N);
5821       if(te)
5822       {
5823         string("locus detected that the mover must avoid points (",N,") in order to obtain the correct locus");" ";
5824         //eliminates segments of GG where N is contained in the basis
5825         nGP[1]=GG[1];
5826         nGP[1][1]=ideal(1);
5827         nGP[1][2]=ideal(1);
5828         def GP=GG;
5829         ideal BP;
5830         ideal fBP;
5831         for(j=2;j<=size(GP);j++)
5832         {
5833           te=1; k=1;
5834           BP=GP[j][2];
5835          // eliminating multiple factors in the polynomials of BP
5836           for(mm=1;mm<=size(BP);mm++)
5837           {
5838             fBP=factorize(BP[mm],1);
5839             BP[mm]=1;
5840             for(m=1;m<=size(fBP);m++)
5841             {
5842               BP[mm]=BP[mm]*fBP[m];
5843             }
5844           }
5845           // end eliminating multiple factors
5846           while((te==1) and (k<=size(N)))
5847           {
5848             if(pdivi(N[k],BP)[1]!=0){te=0;}
5849             k++;
5850           }
5851           if(te==0){nGP[size(nGP)+1]=GP[j];}
5852         }
5853       }
5854    }
5855    else
5856    {
5857      nGP=GG;
5858      " ";string("Unavoidable ",moverdim,"-dimensional locus");
5859      list L; return(L);
5860    }
5861  }
5862
5863//  if(comment>0){"Input for locus2 GB="; nGP; "input for locus  F="; F;}
5864//  if(version==2)
5865//  {
5866//    "T_nGP enter for locus2="; nGP;
5867//    def LL=locus2(nGP,F,moverdim,vmov,na);
5868//  }
5869//  else{ def LL=locus0(nGP,moverdim,vmov);  }
5870
5871  def LL=locus2(nGP,F,moverdim,vmov,na);
5872
5873  return(LL);
5874}
5875example
5876{ "EXAMPLE:"; echo = 2;
5877
5878// EXAMPLE 1
5879
5880// Conchoid, Pascal's Limacon.
5881
5882//  1. Given a circle: x1^2+y1^2-4
5883//  2. and a mover point M(x1,y1) on it
5884//  3. Consider the fix point P(0,2) on the circle
5885//  4. Consider the line l passing through M and P
5886//  5. The tracer T(x,y) are the points on l at fixed distance 1 to M.
5887
5888if(defined(R)){kill R;}
5889ring R=(0,x,y),(x1,y1),dp;
5890short=0;
5891
5892// Concoid
5893ideal S96=x1 ^2+y1 ^2-4,(x-2)*x1 -x*y1 +2*x,(x-x1 )^2+(y-y1 )^2-1;
5894
5895locus(S96);
5896
5897// EXAMPLE 2
5898
5899// Consider two parallel planes z1=-1 and z1=1, and two orthogonal parabolas on them.
5900// Determine the locus generated by the lines that rely the two parabolas
5901// through the points having parallel tangent vectors.
5902
5903if(defined(R)){kill R;}
5904ring R=(0,x,y,z),(x2,y2,z2,z1,y1,x1,lam), lp;
5905short=0;
5906
5907ideal L=z1+1,
5908        x1^2-y1,
5909        z2-1,
5910        y2^2-x2,
5911        4*x1*y2-1,
5912        x-x1-lam*(x2-x1),
5913        y-y1-lam*(y2-y1),
5914        z-z1-lam*(z2-z1);
5915
5916locus(L);  // uses "moverdim",3
5917// Observe the choose of the mover variables: the last 3 variables y1,x1,lam
5918// If we choose x1,y1,z1 instead, the taxonomy becomes "Special" because
5919// z1=-1 is fix and do not really correspond to the mover variables.
5920
5921// EXAMPLE 3 of parametric locus:
5922
5923// Determining the equation of a general ellipse;
5924// Uncentered elipse;
5925
5926// Parameters  (a,b,a0,b0,p):
5927//   a=large semiaxis, b=small semiaxis,
5928//   (a0,b0) = center of the ellipse,
5929//   (a1,b1) and (2*a0-a1,2*b0-b1) the focus,
5930//   p the slope of the line of the a-axis of the ellipse.
5931
5932// Determine the equation of the ellipse.
5933
5934// We must use the option "numpar",5 in order to consider
5935// the first 5 parameters as free parameters for the locus
5936
5937// Auxiliary variabes:
5938//  d1=distance from focus (a1,b1) to the mover point M(x1,y1),
5939//  d2=distance from focus (a2,b2) to the mover point M(x1,y1),
5940//  f=focus distance= distance from (a0,b0) to (a1,b1).
5941
5942// Mover point (x1,y1) = tracer point (x,y).
5943
5944if(defined(R1)){kill R1;}
5945ring R1=(0,a,b,a0,b0,p,x,y),(d1,d2,f,a1,b1,x1,y1),lp;
5946
5947ideal F3=b1-b0-p*(a1-a0),
5948          //b2-b0+p*(a1-a0),
5949          //a1+a2-2*a0,
5950          //b1+b2-2*b0,
5951          f^2-(a1-a0)^2-(b1-b0)^2,
5952          f^2-a^2-b^2,
5953          (x1-a1)^2+(y1-b1)^2-d1^2,
5954          (x1-2*a0+a1)^2+(y1-2*b0+b1)^2-d2^2,
5955          d1+d2-2*a,
5956          x-x1,
5957          y-y1;
5958
5959def G3=grobcov(F3);
5960
5961def Loc3=locus(F3,"grobcov",G3,"numpar",5); Loc3;
5962
5963// General ellipse:
5964
5965def C=Loc3[1][1][1];
5966C;
5967
5968// Centered ellipse of semiaxes (a,b):
5969
5970def C0=subst(C,a0,0,b0,0,p,0);
5971C0;
5972}
5973
5974//  locusdg(G):  Special routine for determining the locus of points
5975//                 of  geometrical constructions in Dynamic Geometry.
5976//                 It is to be applied to the output of locus and selects
5977//                 as 'Relevant' the 'Normal' and the 'Accumulation'
5978//                 components.
5979//  input:      The output of locus(S);
5980//  output:
5981//          list, the canonical P-representation of the 'Relevant' components of the locus.
5982//          The output components are given as
5983//               ((p1,(p11,..p1s_1),type_1,level_1),..,(pk,(pk1,..pks_k),type_k,level_k)
5984//          The components are given in canonical P-representation of the subset.
5985//               If all levels of a class of locus are 1, then the set is locally closed. Otherwise the level
5986//               gives the depth of the component of the constructible set.
5987proc locusdg(list L)
5988"USAGE: locusdg(list L)
5989       Calling sequence:
5990       locusdg(locus(S)).
5991RETURN: The output is the list of the \"Relevant\" components of the
5992       locus in Dynamic Geometry [C1,..,C:m], where
5993       C_i= [p_i,[p_i1,..p_is_i], \"Relevant\", level_i]
5994       The \"Relevant\" components are \"Normal\" and
5995       \"Accumulation\" components of the locus. (See help
5996       for locus).
5997KEYWORDS: geometrical locus; locus; dynamic geometry
5998EXAMPLE: locusdg; shows an example"
5999{
6000  list LL;
6001  int i;
6002  for(i=1;i<=size(L);i++)
6003  {
6004    if(typeof(L[i][3][2])=="string")
6005    {
6006      if((L[i][3][2]=="Normal") or (L[i][3][2]=="Accumulation")){L[i][3][2]="Relevant"; LL[size(LL)+1]=L[i];}
6007    }
6008  }
6009  return(LL);
6010}
6011example
6012{ "EXAMPLE:"; echo = 2;
6013if(defined(R)){kill R;};
6014ring R=(0,a,b),(x,y),dp;
6015short=0;
6016
6017// Concoid
6018ideal S96=x^2+y^2-4,(b-2)*x-a*y+2*a,(a-x)^2+(b-y)^2-1;
6019
6020def L96=locus(S96);
6021L96;
6022
6023locusdg(L96);
6024}
6025
6026// locusto: Transforms the output of locus, locusdg, envelop
6027//             into a string that can be reed from different computational systems.
6028// input:
6029//     list L: The output of locus or locusdg or envelop.
6030// output:
6031//     string s: Converts the input into a string readable by other programs
6032proc locusto(list L)
6033"USAGE: locusto(list L);
6034       The argument must be the output of locus or locusdg or
6035       envelop. It transforms the output into a string in standard
6036       form readable in other languages, not only Singular
6037       (Geogebra).
6038RETURN: The locus in string standard form
6039NOTE: It can only be called after computing either
6040        - locus(F)                -> locusto( locus(F) )
6041        - locusdg(locus(F))  -> locusto( locusdg(locus(F)) )
6042        - envelop(F,C)         -> locusto( envelop(F,C) )
6043KEYWORDS: geometrical locus; locus; envelop
6044EXAMPLE:  locusto; shows an example"
6045{
6046  int i; int j; int k;
6047  string s="["; string sf="]"; string st=s+sf;
6048  if(size(L)==0){return(st);}
6049  ideal p;
6050  ideal q;
6051  for(i=1;i<=size(L);i++)
6052  {
6053    s=string(s,"[[");
6054    for (j=1;j<=size(L[i][1]);j++)
6055    {
6056      s=string(s,L[i][1][j],",");
6057    }
6058    s[size(s)]="]";
6059    s=string(s,",[");
6060    for(j=1;j<=size(L[i][2]);j++)
6061    {
6062      s=string(s,"[");
6063      for(k=1;k<=size(L[i][2][j]);k++)
6064      {
6065        s=string(s,L[i][2][j][k],",");
6066      }
6067      s[size(s)]="]";
6068      s=string(s,",");
6069    }
6070    s[size(s)]="]";
6071    s=string(s,"]");
6072    if(size(L[i])>=3)
6073    {
6074      s=string(s,",[");
6075      if(typeof(L[i][3])=="string")
6076      {
6077        s=string(s,string(L[i][3]),"]]");
6078      }
6079      else
6080      {
6081        for(k=1;k<=size(L[i][3]);k++)
6082        {
6083          s=string(s,"[",L[i][3][k],"],");
6084        }
6085        s[size(s)]="]";
6086        s=string(s,"]");
6087      }
6088    }
6089    if(size(L[i])>=4)
6090    {
6091      s[size(s)]=",";
6092      s=string(s,string(L[i][4]),"],");
6093    }
6094    s[size(s)]="]";
6095    s=string(s,",");
6096  }
6097  s[size(s)]="]";
6098  return(s);
6099}
6100example
6101{ "EXAMPLE:"; echo = 2;
6102if(defined(R)){kill R;}
6103ring R=(0,x,y),(x1,y1),dp;
6104short=0;
6105
6106ideal S=x1^2+y1^2-4,(y-2)*x1-x*y1+2*x,(x-x1)^2+(y-y1)^2-1;
6107def L=locus(S);
6108locusto(L);
6109
6110locusto(locusdg(L));
6111}
6112
6113// envelop
6114// Input:
6115//   poly F: the polynomial defining the family of hypersurfaces in ring R=0,(x_1,..,x_n),(u_1,..,u_m),lp;
6116//   ideal C=g1,..,g_{n-1}:  the set of constraints;
6117//   options.
6118// Output: the components of the envolvent;
6119proc envelop(poly F, ideal C, list #)
6120"USAGE: envelop(poly F,ideal C[,options]);
6121       poly F must represent the family of hyper-surfaces for
6122       which on want to compute its envelop. ideal C must be
6123       the ideal of restrictions on the variables defining the
6124       family, and should contain less polynomials than the
6125       number of variables. (x_1,..,x_n) are the variables of
6126       the hyper-surfaces of F, that are considered as
6127       parameters of the parametric ring. (u_1,..,u_m) are
6128       the parameteres of the hyper-surfaces, that are
6129       considered as variables of the parametric ring.
6130       In the actual version, parametric envelope are accepted.
6131       To include fixed parameters a1,..ap, to the problem, one must
6132       declare them as the first parameters of the ring. if the
6133       the number of free parameters is p, the option \"numpar\",p
6134       is required.
6135       Calling sequence:
6136       ring R=(0,a1,..,ap,x_1,..,x_n),(u_1,..,u_m),lp;
6137       poly F=F(a1,..ap,x_1,..,x_n,u_1,..,u_m);
6138       ideal C=g_1(a1,..,ap,u_1,..u_m),..,g_s(a1,..ap,u_1,..u_m);
6139       envelop(F,C[,options]);   where s<m.
6140       x1,..,xn are the tracer variables.
6141       u_1,..,u_m are the auxiliary variables.
6142       a1,..,ap are the fixed parameters if they exist
6143       If the problem is a parametric envelope, and a's exist,
6144       then the option \"numpar\",p  m must be given.
6145       By default the las n variables are the mover variables.
6146       See the EXAMPLE of parametric envelop by calling
6147       example envelop,
6148RETURN: The output is a list of the components [C_1, .. , C_n]
6149       of the locus. Each component is given by
6150       Ci=[pi,[pi1,..pi_s_i],tax] where
6151       pi,[pi1,..pi_s_i] is the canonical P-representation of
6152       the component.
6153       Concerning tax: (see help for locus)
6154       For normal-point components is
6155         tax=[d,taxonomy,anti-image], being
6156         d=dimension of the anti-image
6157         taxonomy=\"Normal\" or \"Special\"
6158         anti-image=values of the mover corresponding
6159         to the component
6160       For non-normal-point components is
6161         tax=[d,taxonomy]
6162         d=dimension of the component
6163         taxonomy=\"Accumulation\" or \"Degenerate\".
6164OPTIONS: An option is a pair of arguments: string, integer.
6165       To modify the default options,
6166       pairs of arguments -option name, value- of valid options
6167       must be added to the call.
6168
6169       The algorithm allows the following options as pair of arguments:
6170       \"comments\", c: by default it is 0, but it can be set to 1.
6171       \"anti-image\", a: by default a=1 and the anti-image is
6172       shown also for \"Normal\" components.
6173       For a=0, it is not shown.
6174       \"moverdim\", k: by default it is equal to n, the number of
6175       x-tracer variables.
6176       \"numpar\",p  when fixed parameters are included
6177NOTE: grobcov and locus are called internally.
6178       The basering R, must be of the form Q[a,x][u]
6179       (x=variables, u=auxiliary variables), (a fixed parameters).
6180       This routine uses the generalized definition of envelop
6181       introduced in the book
6182       A. Montes. \"The Groebner Cover\" (Discussing Parametric
6183       Polynomial Systems) not yet published.
6184KEYWORDS: geometrical locus; locus; envelop
6185EXAMPLE:  envelop; shows an example"
6186{
6187  def RR=basering;
6188  list LRR=ringlist(RR);
6189  int nax=size(LRR[1][2]);
6190  int nuv=size(LRR[2]);
6191
6192  list DD=#;
6193  int na=0;
6194  int nx=nax;
6195  int nu=0;
6196  int nv=nuv;
6197  int i; int j; int k;
6198  //string("T_ nax=",nax,"; nx=",nx,"; nuv=",nuv,"; nv=",nv);
6199  int tnumpar=0;
6200  // int tnumvar=0;
6201  //"T_DD="; DD;
6202  for(i=1;i<=size(DD) div 2;i++)
6203  {
6204    if(DD[2*i-1]=="numpar"){na=DD[2*i];tnumpar=1;}
6205    // if(DD[2*i-1]=="numvar"){nv=DD[2*i];tnumvar=1;}
6206  }
6207  if(tnumpar==0){DD[size(DD)+1]="numpar";  DD[size(DD)+1]=na;}
6208  // if(tnumvar==0){DD[size(DD)+1]="numvar";  DD[size(DD)+1]=nv;}
6209  nx=nax-na;
6210  nu=nuv-nv;
6211  //string("T_ nax=",nax,"; nx=",nx,"; nuv=",nuv,"; nv=",nv);
6212  ideal Vnv;
6213  ideal Vnonv;
6214  for(i=1;i<=nu;i++){Vnonv[size(Vnonv)+1]=var(i);}
6215  //"T_Vnonv="; Vnonv;
6216  for(i=nu+1;i<=nuv;i++){Vnv[size(Vnv)+1]=var(i);}
6217  //"T_Vnv="; Vnv;
6218  ideal Cnor;
6219  ideal Cr=F;
6220  for(i=1;i<=size(C);i++)
6221  {
6222    if(subset(variables(C[i]),Vnonv)){Cnor[size(Cnor)+1]=C[i];}
6223    else{Cr[size(Cr)+1]=C[i];}
6224  }
6225  int nr=size(Cr);
6226  //string("T_nr=", nr,"; nv=",nv);
6227  if(nr>0)
6228  {
6229    matrix M[nr][nr];
6230    def cc=comb(nv,nr);
6231    //"T_cc="; cc;
6232    //string("T_nv=",nv," nr=",nr);
6233    poly J;
6234    for(k=1;k<=size(cc);k++)
6235    {
6236      for(i=1;i<=nr;i++)
6237      {
6238        for(j=1;j<=nr;j++)
6239        {
6240          M[i,j]=diff(Cr[i],var(cc[k][j]));
6241        }
6242      }
6243      J=det(M);
6244      Cr[size(Cr)+1]=J;
6245    }
6246  }
6247  ideal S=Cnor;
6248  for(i=1;i<=size(C);i++){S[size(S)+1]=C[i];}
6249  for(i=1;i<=size(Cr);i++){S[size(S)+1]=Cr[i];}
6250  //"T_S="; S;
6251  def L=locus(S,DD);
6252  return(L);
6253}
6254example
6255{ "EAXMPLE:"; echo=2;
6256
6257// EXAMPLE 1
6258// Steiner Deltoid
6259// 1. Consider the circle x1^2+y1^2-1=0, and a mover point M(x1,y1) on it.
6260// 2. Consider the triangle A(0,1), B(-1,0), C(1,0).
6261// 3. Consider lines passing through M perpendicular to two sides of ABC triangle.
6262// 4. Determine the envelope of the lines above.
6263
6264if(defined(R)){kill R;}
6265ring R=(0,x,y),(x1,y1,x2,y2),lp;
6266short=0;
6267
6268ideal C=(x1)^2+(y1)^2-1,
6269             x2+y2-1,
6270             x2-y2-x1+y1;
6271matrix M[3][3]=x,y,1,x2,y2,1,x1,0,1;
6272poly F=det(M);
6273
6274// The lines of family F are
6275F;
6276
6277// The conditions C are
6278C;
6279
6280envelop(F,C);
6281
6282// EXAMPLE 2
6283// Parametric envelope
6284
6285// Let c be the circle centered at the origin O(0,0) and having radius 1.
6286// M(x1,y1) be a mover point gliding on c.
6287// Let A(a0,b0) be a parametric fixed point:
6288// Consider the set of lines parallel to the line AO passing thoug M.
6289
6290// Determine the envelope of these lines
6291
6292// We let the fixed point A coordinates as free parameters of the envelope.
6293// We have to declare the existence of two parameters when
6294// defining the ring in which we call envelop,
6295// and set a0,b0 as the first variables of the parametric ring
6296// The ring is thus
6297
6298if(defined(R1)){kill R1;}
6299ring R1=(0,a0,b0,x,y),(x1,y1),lp;
6300short=0;
6301
6302// The lines are  F1
6303poly F1=b0*(x-x1)-a0*(y-y1);
6304
6305// and the mover is on the circle c
6306ideal C1=x1^2+y1^2-1;
6307// The call is thus
6308
6309def E1=envelop(F1,C1,"numpar",2);
6310E1;
6311
6312// The interesting first component  EC1 is
6313def EC1=E1[1][1][1];
6314EC1;
6315
6316// that is equivalent to  (a0*y-b0*x)^2-a0^2-b0^2.
6317// As expected it consists of the two lines
6318//    a0*y-b0*x - sqrt(a0^2+b0^2),
6319//    a0*y-b0*x + sqrt(a0^2+b0^2),
6320// parallel to the line OM passing at the
6321// points of the circle in the line perpendicular to OA.
6322
6323// EXAMPLE 3
6324// Parametric envelope
6325
6326// Let c be the circle centered at the origin O(a1,b1) and having radiusr,
6327// where a1,b1,r are fixed parameters
6328// M(x1,y1) be a mover point gliding on c.
6329// Let A(a0,b0) be a parametric fixed point:
6330// Consider the set of lines parallel to the line AO passing thoug M.
6331
6332// Determine the envelope of these lines
6333
6334// We let the fixed point A,point M and r as free parameters of the envelope.
6335// We have to declare the existence of 5 parameters when
6336// defining the ring in which we call envelop,
6337// and set a0,b0,a1,b1,r as the first variables of the parametric ring
6338// The ring is thus
6339
6340if(defined(R1)){kill R1;}
6341ring R1=(0,a0,b0,a1,b1,r,x,y),(x1,y1),lp;
6342short=0;
6343
6344// The lines are  F1
6345poly F1=b0*(x-x1)-a0*(y-y1);
6346
6347// and the mover is on the circle c
6348ideal C1=(x1-a1)^2+(y1-b1)^2-r^2;
6349// The call is thus
6350
6351def E1=envelop(F1,C1,"numpar",5);
6352E1;
6353
6354// The interesting first component  EC1 is
6355def EC1=E1[1][1][1];
6356EC1;
6357
6358// which corresponds to the product of two lines
6359// parallel to the line AM and intercepting the circle
6360// on the intersection of the line perpendicuar
6361// to line AM passing through A
6362}
6363
6364proc AssocTanToEnv(poly F,ideal C, ideal E,list #)
6365"USAGE: AssocTanToEnv(poly F,ideal C,ideal E);
6366       poly F must be the family of hyper-surfaces whose
6367       envelope is analyzed. It must be defined in the ring
6368       R=Q[x_1.,,x_n][u_1,..,u_m],
6369       ideal C must be the ideal of restrictions
6370       in the variables u1,..um for defining the family.
6371       C must contain less  polynomials than m.
6372       ideal E must be a component of
6373       envelop(F,C), previously computed.
6374       (x_1,..,x_n) are the variables of the hypersurfaces
6375       of F, that are considered as parameters of the
6376       parametric ring. (u_1,..,u_m) are the parameteres
6377       of the hyper-surfaces, that are considered as variables
6378       of the parametric ring. Having computed an envelop
6379       component E of a family of hyper-surfaces F,
6380       with constraints C, it returns the parameter values
6381       of the associated tangent hyper-surface of the
6382       family passing at one point of the envelop component E.
6383       Calling sequence:  (s<m)
6384       ring R=(0,x_1,..,x_n),(u_1,..,u_m),lp;
6385       poly F=F(x_1,..,x_n,u_1,..,u_m);
6386       ideal C=g_1(u_1,..u_m),..,g_s(u_1,..u_m);
6387       poly E(x_1,..,x_n);
6388       AssocTanToEnv(F,C,E,[,options]);
6389RETURN: list [lpp,basis,segment]. The basis determines
6390       the associated tangent hyper-surface at a point of
6391       the envelop component E. The segment is given in Prep.
6392       See book
6393       A. Montes. \"The Groebner Cover\":
6394OPTIONS: \"moreinfo\",n  n=0 is the default option, and
6395       only the segment of the top of the component is shown.
6396       n=1  makes the result to shown all the segments.
6397NOTE:  grobcov is called internally.
6398KEYWORDS: geometrical locus; locus; envelop; associated tangent
6399EXAMPLE:  AssocTanToEnv; shows an example"
6400{
6401  def RR=basering;
6402  int tes=0; int i;   int j;  int k; int m;
6403  int d;
6404  int dp;
6405  ideal EE=E;
6406  int moreinfo=0;
6407  ideal BBB;
6408  //Options
6409//    list DD=#;
6410  ideal vmov;
6411  int nv=nvars(RR);
6412  for(i=1;i<=nv;i++){vmov[size(vmov)+1]=var(i);}
6413//  int numpars=npars(RR);
6414//  int version=0;
6415//  if(nv<4){version=1;}
6416  int comment=0;
6417  int familyinfo=0;
6418  ideal Fm;
6419//    for(i=1;i<=(size(DD) div 2);i++)
6420//    {
6421//      if(DD[2*i-1]=="vmov"){vmov=DD[2*i];}
6422//  //    if(DD[2*i-1]=="version"){version=DD[2*i];}
6423//      if(DD[2*i-1]=="comment"){comment=DD[2*i];}
6424//      if(DD[2*i-1]=="familyinfo"){familyinfo=DD[2*i];}
6425//      if(DD[2*i-1]=="moreinfo"){moreinfo=DD[2*i];}
6426//    };
6427//    DD=list("vmov",vmov,"comment",comment); // ,"version",version
6428  int ng=size(C);
6429  ideal S=F;
6430  for(i=1;i<=size(C);i++){S[size(S)+1]=C[i];}
6431  int s=nv-ng;
6432  if(s>0)
6433  {
6434    matrix M[ng+1][ng+1];
6435    def cc=comb(nv,ng+1);
6436    poly J;
6437    for(k=1;k<=size(cc);k++)
6438    {
6439      for(j=1;j<=ng+1;j++)
6440      {
6441        M[1,j]=diff(F,var(cc[k][j]));
6442      }
6443      for(i=1;i<=ng;i++)
6444      {
6445        for(j=1;j<=ng+1;j++)
6446        {
6447          M[i+1,j]=diff(C[i],var(cc[k][j]));
6448        }
6449      }
6450      J=det(M);
6451      S[size(S)+1]=J;
6452    }
6453 }
6454 for(i=1;i<=size(EE);i++)
6455 {
6456   S[size(S)+1]=EE[i];
6457 }
6458 //if(comment>0){"System S before grobcov ="; S;}
6459 //"T_S="; S;
6460  def G=grobcov(S); // ,DD
6461  //"T_G=";G;
6462  list GG;
6463  for(i=2;i<=size(G);i++)
6464  {
6465    GG[size(GG)+1]=G[i];
6466  }
6467  G=GG;
6468  //"T_G=";G;
6469  if(moreinfo>0){return(G);}
6470  else
6471  {
6472    int t=0;
6473    list HH;
6474    i=1;
6475    while(t==0 and i<=size(G))
6476    {
6477      //string("T_G[",i,"][3][1][1][1]="); G[i][3][1][1][1];
6478      //string("T_EE="); EE;
6479      if(equalideals(G[i][3][1][1],EE))
6480      {
6481         t=1;
6482         HH=G[i];
6483      }
6484      i++;
6485    }
6486    return(HH);
6487  }
6488  return(G);
6489}
6490example
6491{ "EXAMPLE:"; echo = 2;
6492if(defined(R)){kill R;}
6493ring R=(0,x,y),(r,s,y1,x1),lp;
6494
6495poly F=(x-x1)^2+(y-y1)^2-r;
6496ideal g=(x1-2*(s+r))^2+(y1-s)^2-s;
6497
6498def E=envelop(F,g);
6499E;
6500
6501def A=AssocTanToEnv(F,g,E[1][1][1]);
6502A;
6503
6504def M1=coef(A[2][1],x1);
6505def M2=coef(A[2][2],y1);
6506def M3=coef(A[2][3],s);
6507def M4=coef(A[2][4],r);
6508
6509"x1=";-M1[2,2]/M1[2,1];
6510
6511"y1=";-M2[2,2]/M2[2,1];
6512
6513"s=";-M3[2,2]/M3[2,1];
6514
6515"r=";-M4[2,2]/M4[2,1];
6516}
6517
6518proc FamElemsAtEnvCompPoints(poly F,ideal C, ideal E,list #)
6519"USAGE: FamElemsAtEnvCompPoints(poly F,ideal C,poly E);
6520       poly F must be the family of hyper-surfaces whose
6521       envelope is analyzed. It must be defined in the ring
6522       R=Q[x_1.,,x_n][u_1,..,u_m],
6523       ideal C must be the ideal of restrictions on the
6524       variables u1,..um.
6525       Must contain less polynomials than m.
6526       ideal E must be a component of
6527       envelop(F,C), previously computed.
6528       After computing the envelop of a family of
6529       hyper-surfaces F, with constraints C,
6530       Consider a component with top E. The call to
6531       FamElemsAtEnvCompPoints(F,C,E)
6532       returns the parameter values of the
6533       set of all hyper-surfaces of the family passing at
6534       one point of the envelop component E.
6535       Calling sequence:
6536       ring R=(0,x_1,..,x_n),(u_1,..,u_m),lp;
6537       poly F=F(x_1,..,x_n,u_1,..,u_m);
6538       ideal C=g_1(u_1,..u_m),..,g_s(u_1,..u_m);
6539       poly E(x_1,..,x_n);
6540       FamElemsAtEnvCompPoints(F,C,E[,options]);
6541RETURN: list [lpp,basis,segment]. The basis determines
6542       the parameter values of the of hyper-surfaces that
6543       pass at a fixed point of the envelop component E.
6544       The lpp determines the dimension of the set.
6545       The segment is the component and is given in Prep.
6546       Fixing the values of (x_1,..,x_n) inside E, the basis
6547       allows to detemine the values of the parameters
6548       (u_1,..u_m), of the hyper-surfaces passing at a point
6549       of E. See the book
6550       A. Montes. \"The Groebner Cover\" (Discussing
6551       Parametric Polynomial Systems).
6552OPTIONS: \"moreinfo\",n  n=0 is the default option, and
6553       only the segment of the top of the component is shown.
6554       n=1  makes the result to shown all the segments.
6555NOTE: grobcov is called internally.
6556       The basering R, must be of the form Q[a][x]
6557       (a=parameters, x=variables).
6558KEYWORDS: geometrical locus; locus; envelop; associated tangent
6559EXAMPLE:  FamElemsAtEnvCompPoints; shows an example"
6560{
6561  int i;
6562  int moreinfo=0;
6563  int familyinfo=0;
6564  int comment=0;
6565  int numpar=0;
6566  ideal vmov;
6567  list DD=#;
6568  for(i=1;i<=(size(DD) div 2);i++)
6569  {
6570    if(DD[2*i-1]=="vmov"){vmov=DD[2*i];}
6571    if(DD[2*i-1]=="comment"){comment=DD[2*i];}
6572    if(DD[2*i-1]=="familyinfo"){familyinfo=DD[2*i];}
6573    if(DD[2*i-1]=="moreinfo"){moreinfo=DD[2*i];}
6574    if(DD[2*i-1]=="numpar"){numpar=DD[2*i];}
6575  };
6576  ideal S=C;
6577  ideal EE=E;
6578  S[size(S)+1]=F;
6579  //S[size(S)+1]=E;
6580  for(i=1;i<=size(E);i++){S[size(S)+1]=E[i];}
6581  def G=grobcov(S);
6582  list GG;
6583  for(i=2; i<=size(G); i++)
6584  {
6585    GG[size(GG)+1]=G[i];
6586  }
6587
6588
6589  if(moreinfo>0){return(GG);}
6590  else
6591  {
6592    int t=0;
6593    list HH;
6594    i=1;
6595    while(t==0 and i<=size(G))
6596    {
6597      //string("T_G[",i,"][3][1][1][1]="); G[i][3][1][1][1];
6598      //string("T_EE="); EE;
6599      if(G[i][3][1][1][1]==E)
6600      {
6601         t=1;
6602         HH=G[i];
6603      }
6604      i++;
6605    }
6606    return(HH);
6607  }
6608}
6609example
6610{ "EXAMPLE:"; echo = 2;
6611 if(defined(R)){kill R;}
6612 ring R=(0,x,y),(t),dp;
6613 short=0;
6614 poly F=(x-5*t)^2+y^2-9*t^2;
6615 ideal C;
6616
6617 def Env=envelop(F,C);
6618 Env;
6619
6620// E is a component of the envelope:
6621 def E=Env[1][1][1];
6622 E;
6623
6624 def A=AssocTanToEnv(F,C,E);
6625 A;
6626
6627// The basis of the parameter values of the associated
6628//    tangent component is
6629A[2][1];
6630
6631// Thus t=-(5/12)*y, and  the associated tangent family
6632//    element at (x,y) is
6633
6634 subst(F,t,-(5/12)*y);
6635
6636 def FE=FamElemsAtEnvCompPoints(F,C,E);
6637 FE;
6638
6639 factorize(FE[2][1]);
6640
6641// Thus the unique family element passing through the envelope point (x,y)
6642// corresponds to the value of t of the Associated Tangent
6643
6644// EXAMPLE:
6645 if(defined(R)){kill R;}
6646 ring R=(0,x,y),(r,s,y1,x1),lp;
6647
6648 poly F=(x-x1)^2+(y-y1)^2-r;
6649 ideal g=(x1-2*(s+r))^2+(y1-s)^2-s;
6650
6651 def E=envelop(F,g);
6652 E;
6653
6654 def A=AssocTanToEnv(F,g,E[1][1][1]);
6655 A;
6656
6657 def M1=coef(A[2][1],x1);
6658 def M2=coef(A[2][2],y1);
6659 def M3=coef(A[2][3],s);
6660 def M4=coef(A[2][4],r);
6661
6662// The parameter values corresponding to the family
6663//    element tangent at point (x,y) of the envelope are:
6664 "x1=";-M1[2,2]/M1[2,1];
6665
6666 "y1=";-M2[2,2]/M2[2,1];
6667
6668 "s=";-M3[2,2]/M3[2,1];
6669
6670 "r=";-M4[2,2]/M4[2,1];
6671
6672// Now detect if there are other family elements passing at this point:
6673 def FE=FamElemsAtEnvCompPoints(F,g,E[1][1][1]);
6674 FE;
6675
6676// FE[1] is the set of lpp. It has dimension 4-2=2.
6677//     Thus there are points of the envelope at which
6678//     they pass infinitely many circles of the family.
6679//     To separe the points of the envelope further analysis must be done.
6680}
6681
6682// discrim
6683proc discrim(poly F0, poly x0)
6684"USAGE: discrim(f,x);
6685       poly f: the polynomial in Q[a][x] or Q[x] of degree 2 in x
6686       poly x: can be a variable or a parameter of the ring.
6687RETURN: the factorized discriminant of f wrt x for discussing
6688        its sign
6689KEYWORDS: second degree; solve
6690EXAMPLE:  discrim; shows an example"
6691{
6692  def RR=basering;
6693  def Rx=ringlist(RR);
6694  def P=ring(Rx[1]);
6695  Rx[1]=0;
6696  def D=ring(Rx);
6697  def RP=D+P;
6698  int i;
6699  int te;
6700  int d;  int dd;
6701  if(size(ringlist(RR)[1])>0)
6702  {
6703    te=1;
6704    // setglobalrings();
6705    setring RP;
6706    poly F=imap(RR,F0);
6707    poly X=imap(RR,x0);
6708  }
6709  else
6710  {poly F=F0; poly X=x0;}
6711  matrix M=coef(F,X);
6712  d=deg(M[1,1]);
6713  if(d>2){"Degree is higher than 2. No discriminant"; setring RR; return();}
6714    poly dis=(M[2,2])^2-4*M[2,1]*M[2,3];
6715    def disp=factorize(dis,0);
6716    if(te==0){return(disp);}
6717    else
6718    {
6719      setring RR;
6720      def disp0=imap(RP,disp);
6721      return(disp0);
6722    }
6723}
6724example
6725{ "EXAMPLE:"; echo = 2;
6726if(defined(R)){kill R;}
6727ring R=(0,a,b,c),(x,y),dp;
6728short=0;
6729poly f=a*x^2*y+b*x*y+c*y;
6730
6731discrim(f,x);
6732}
6733
6734// AddLocus: auxilliary routine for locus0 that computes the components of the constructible:
6735// Input:  the list of locally closed sets to be added, each with its type as third argument
6736//     L=[ [LC[11],..,LC[1k_1],.., [LC[r1],..,LC[rk_r] ] where
6737//            LC[1]=[p1,[p11,..,p1k],typ]
6738// Output:  the list of components of the constructible union of L, with the type of the corresponding top
6739//               and the level of the constructible
6740//     L4= [[v1,p1,[p11,..,p1l],typ_1,level]_1 ,.. [vs,ps,[ps1,..,psl],typ_s,level_s]
6741static proc AddLocus(list L)
6742{
6743  list L1; int i; int j;  list L2; list L3;
6744  list l1; list l2;
6745  intvec v;
6746  for(i=1; i<=size(L); i++)
6747  {
6748    for(j=1;j<=size(L[i]);j++)
6749    {
6750      l1[1]=L[i][j][1];
6751      l1[2]=L[i][j][2];
6752      l2[1]=l1[1];
6753      if(size(L[i][j])>2){l2[3]=L[i][j][3];}
6754      v[1]=i; v[2]=j;
6755      l2[2]=v;
6756      L1[size(L1)+1]=l1;
6757      L2[size(L2)+1]=l2;
6758    }
6759  }
6760  L3=LocusConsLevels(L1);
6761  list L4; int level;
6762  ideal p1; ideal pp1; int t; int k; int k0; string typ; list l4;
6763  for(i=1;i<=size(L3);i++)
6764  {
6765    level=L3[i][1];
6766    for(j=1;j<=size(L3[i][2]);j++)
6767    {
6768      p1=L3[i][2][j][1];
6769      t=1; k=1;
6770      while((t==1) and (k<=size(L2)))
6771      {
6772        pp1=L2[k][1];
6773        if(equalideals(p1,pp1)){t=0; k0=k;}
6774        k++;
6775      }
6776      if(t==0)
6777      {
6778        v=L2[k0][2];
6779        l4[1]=v; l4[2]=p1; l4[3]=L3[i][2][j][2];  l4[5]=level;
6780        if(size(L2[k0])>2){l4[4]=L2[k0][3];}
6781        L4[size(L4)+1]=l4;
6782      }
6783      else{"ERROR p1 NOT FOUND";}
6784    }
6785  }
6786  return(L4);
6787}
6788
6789// Input L: list of components in P-rep to be added
6790//         [  [[p_1,[p_11,..,p_1,r1]],..[p_k,[p_k1,..,p_kr_k]]  ]
6791// Output:
6792//          list of lists of levels of the different locally closed sets of
6793//          the canonical P-rep of the constructible.
6794//          [  [level_1,[ [Comp_11,..Comp_1r_1] ] ], .. ,
6795//             [level_s,[ [Comp_s1,..Comp_sr_1] ]
6796//          ]
6797//          where level_i=i,   Comp_ij=[ p_i,[p_i1,..,p_it_i] ] is a prime component.
6798// LocusConsLevels: given a set of components of locally closed sets in P-representation, it builds the
6799//       canonical P-representation of the corresponding constructible set of its union,
6800//       including levels it they are.
6801static proc LocusConsLevels(list L)
6802{
6803  list Lc; list Sc;
6804  int i;
6805  for(i=1;i<=size(L);i++)
6806  {
6807    Sc=PtoCrep0(list(L[i]));
6808    Lc[size(Lc)+1]=Sc;
6809  }
6810  list S=ConsLevels(Lc);
6811  S=Levels(S);
6812  list Sout;
6813  list Lev;
6814  for(i=1;i<=size(S);i++)
6815  {
6816    Lev=list(S[i][1],Prep(S[i][2][1],S[i][2][2]));
6817    Sout[size(Sout)+1]=Lev;
6818  }
6819  return(Sout);
6820}
6821
6822// used in NS
6823// returns 0 if E does not reduce modulo N
6824// returns 1 if it reduces
6825static proc redPbasis(ideal E, ideal N)
6826{
6827  int i;
6828  def RR=basering;
6829  def Rx=ringlist(RR);
6830  def Lx=Rx;
6831  def P=ring(Rx[1]);
6832  setring P;
6833  def EP=imap(RR,E);
6834  def NP=imap(RR,N);
6835  NP=std(NP);
6836  list L;
6837  int red=1;
6838  i=1;
6839  while(red and (i<=size(EP)))
6840  {
6841    if(reduce(EP[i],NP,5)!=0){red=0;}
6842    i++;
6843  }
6844  setring RR;
6845  return(red);
6846}
6847
6848
6849//******************** End locus and envelop ******************************
6850
6851//********************* Begin WLemma **********************
6852
6853// input ideal F in @R
6854//          ideal a in @R but only depending on parameters
6855//          F is a generating ideal in V(a);
6856// output:  ideal b in @R but depending only on parameters
6857//              ideal G=GBasis(F) in V(a) \ V(b)
6858proc WLemma(ideal F,ideal a, list #)
6859"USAGE: WLemma(F,A[,options]);
6860       The first argument ideal F in Q[x_1,..,x_n][u_1,..,u_m];
6861       The second argument ideal A in Q[x_1,..,x_n].
6862       Calling sequence:
6863       ring R=(0,x_1,..,x_n),(u_1,..,u_m),lp;
6864       ideal  F=f_1(x_1,..,x_n,u_1,..,u_m),..,
6865           f_s(x_1,..,x_n,u_1,..,u_m);
6866       ideal A=g_1(u_1,..u_m),..,g_s(u_1,..u_m);
6867       list # : Options
6868       Calling sequence:
6869       WLemma(F,A[,options]);
6870
6871       Given the ideal F  and ideal A
6872       it returns the list (lpp,B,S)  were B is the
6873       reduced Groebner basis of the specialized F over
6874       the segment S, subset of V(A) with top A,
6875       determined by Wibmer's Lemma.
6876       S is determined in P-representation
6877       (or optionally in C-representation). The basis is
6878       given by I-regular functions.
6879OPTIONS: either (\"rep\", 0) or (\"rep\",1) the representation of
6880       the resulting segment, by default is
6881       0 =P-representation, (default) but can be set to
6882       1=C-representation.
6883RETURN: list of [lpp,B,S] =
6884       [leading power product, basis,segment],
6885       being B the reduced Groebner Basis given by
6886       I-regular functions in full representation, of
6887       the specialized ideal F on the segment S,
6888       subset of V(A) with top A.
6889       given in P- or C-representation.
6890       It is the result of Wibmer's Lemma. See
6891       A. Montes , M. Wibmer, \"Groebner Bases for
6892       Polynomial Systems with parameters\".
6893       JSC 45 (2010) 1391-1425.)
6894       or the book
6895       A. Montes. \"The Groebner Cover\" (Discussing
6896       Parametric Polynomial Systems).
6897
6898NOTE: The basering R, must be of the form Q[a][x]
6899      (a=parameters, x=variables).
6900KEYWORDS: Wibmer's Lemma
6901EXAMPLE:  WLemma; shows an example"
6902{
6903  list L=#;
6904  int rep=0;
6905  int i; int j;
6906  if(size(L)>0)
6907  {
6908    for(i=1;i<=size(L) div 2;i++)
6909    {
6910      if(L[2*i-1]=="rep"){rep=L[2*i];}
6911    }
6912  }
6913  def RR=basering;
6914  def Rx=ringlist(RR);
6915  def P=ring(Rx[1]);
6916  Rx[1]=0;
6917  def D=ring(Rx);
6918  def RP=D+P;
6919  setring(RP);
6920  ideal FF=imap(RR,F);
6921  FF=std(FF);
6922  ideal AA=imap(RR,a);
6923  AA=std(AA);
6924  FF=FF,AA;
6925  FF=std(FF);
6926  ideal FFa;
6927  poly r;
6928  for(i=1; i<=size(FF);i++)
6929  {
6930    r=reduce(FF[i],AA);
6931    if(r!=0){FFa[size(FFa)+1]=r;}
6932  }
6933  // FFa is GB(F+a,>xa)
6934  setring RR;
6935  ideal Fa=imap(RP,FFa);
6936  ideal AAA=imap(RP,AA);
6937  ideal lppFa;
6938  ideal lcFa;
6939  for(i=1;i<=size(Fa);i++)
6940  {
6941    lppFa[size(lppFa)+1]=leadmonom(Fa[i]);
6942    lcFa[size(lcFa)+1]=leadcoef(Fa[i]);
6943  }
6944  // "T_lppFa="; lppFa;
6945  // "T_lcFa="; lcFa;
6946  setring RP;
6947  ideal lccr=imap(RR,lppFa);
6948  lccr=std(lccr);
6949  setring RR;
6950  ideal lcc=imap(RP,lccr);
6951  list J; list Jx;
6952  ideal Jci;
6953  ideal Jxi;
6954  list B;
6955  // "T_lcc="; lcc;
6956  for(i=1;i<=size(lcc);i++)
6957  {
6958    kill Jci; ideal Jci; kill Jxi; ideal Jxi;
6959    for(j=1;j<=size(Fa);j++)
6960    {
6961      if(lppFa[j]==lcc[i])
6962      {
6963        Jci[size(Jci)+1]=lcFa[j];
6964        Jxi[size(Jxi)+1]=Fa[j];
6965      }
6966    }
6967    J[size(J)+1]=Jci;
6968    B[size(B)+1]=Jxi;
6969  }
6970 // "T_J="; J;
6971  if(size(J)>0)
6972  {
6973    setring P;
6974    list Jp=imap(RR,J);
6975    ideal JL=product(Jp);
6976    // JL=prod(lc(Fa))
6977    def AAAA=imap(RR,AAA);
6978    // "T_AAA="; AAA;
6979    // "T_JLA="; JLA;
6980    def CPR=Crep(AAAA, JL);
6981    def PPR=Prep(AAAA,JL);
6982  }
6983  setring RR;
6984  if(size(J)>0)
6985  {
6986    def JLA=imap(P,JL);
6987    def PR=imap(P,PPR);
6988    def CR=imap(P,CPR);
6989    // PR=Prep(a,b)
6990    // CR=Crep(a,b)
6991    for(i=1;i<=size(B);i++)
6992    {
6993      for(j=1;j<=size(B[i]);j++)
6994      {
6995        B[i][j]=pnormalf(B[i][j],CR[1],CR[2]);
6996      }
6997      B[i]=elimrepeated(B[i]);
6998    }
6999     // B=reduced basis on CR
7000     //"T_PR="; PR;
7001     //"T_CR="; CR;
7002     //"T_B="; B;
7003    if(rep==1){return(list(lcc,B,CR));}
7004    else{return(list(lcc,B,PR));}
7005  }
7006  else
7007  {
7008    "PIP";
7009    lcc=ideal(0);
7010    B=ideal(0);
7011    list NN;
7012    NN[1]=list(AAA,ideal(1));
7013    return(list(lcc,B,NN));
7014  }
7015}
7016example
7017{ "EXAMPLE:"; echo = 2;
7018if(defined(RE)){kill RE;}
7019ring RE=(0,a,b,c,d,e,f),(x,y),lp;
7020ideal F=a*x^2+b*x*y+c*y^2,d*x^2+e*x*y+f*y^2;
7021ideal A=a*e-b*d;
7022
7023WLemma(F,A);
7024
7025WLemma(F,A,"rep",1);
7026}
7027
7028// Detect if ideal J is in the list of ideals L
7029// Input ideal J,  list L
7030// Output:  1 if J is in L, and 0 if not
7031static proc idinlist(ideal J,list L)
7032{
7033  int i=0;
7034  int te=0;
7035  while(te==0 and i<=size(L)-1)
7036  {
7037    i++;
7038    if(equalideals(J,L[i])){te=1;}
7039  }
7040  return(te);
7041}
7042
7043// input ideal F in Kˆa][x]
7044// output:  a disjoint CGS in full representation of the ideal F using Wibmer's Lemma WLemma
7045proc WLcgs(ideal F)
7046USAGE: WLcgs(ideal F)
7047       // WLemma(F,A[,options]);
7048       ideal F in Q[x_1,..,x_n][u_1,..,u_m];
7049       ring R=(0,x_1,..,x_n),(u_1,..,u_m),lp;
7050       ideal  F=f_1(x_1,..,x_n,u_1,..,u_m),..,
7051           f_s(x_1,..,x_n,u_1,..,u_m);
7052       list # : Options
7053       Calling sequence:
7054       WLcgs(ideal F)
7055
7056       Given the ideal F
7057       it returns the list of (lpp,B,S)[i] of the grobcov.
7058       B[i] is the reduced Groebner basis in full-representation of the specialized F over
7059       the segments S[i],
7060       S is determined in P-representation
7061       (or optionally in C-representation). The basis is
7062       given by I-regular functions in full-representation
7063OPTIONS: either (\"rep\", 0) or (\"rep\",1) the representation of
7064       the resulting segment, by default is
7065       0 =P-representation, (default) but can be set to
7066       1=C-representation.
7067RETURN: list of [lpp,B,S][i] =
7068       [leading power product, basis,segment],
7069       being B[i] the reduced Groebner Basis given by
7070       I-regular functions in full representation, of
7071       the specialized ideal F on the segment S[i],
7072       given in P-representation.
7073       It is the result of Wibmer's Lemma. See
7074       A. Montes , M. Wibmer, \"Groebner Bases for
7075       Polynomial Systems with parameters\".
7076       JSC 45 (2010) 1391-1425.)
7077       or the book
7078       A. Montes. \"The Groebner Cover\" (Discussing
7079       Parametric Polynomial Systems).
7080
7081NOTE: The basering R, must be of the form Q[a][x]
7082      (a=parameters, x=variables).
7083KEYWORDS: Wibmer's Lemma
7084EXAMPLE:  WLcgs; shows an example"
7085{
7086  int i,j;
7087  list Etot;
7088  Etot[1]=ideal(0);
7089  list Epend=Etot;
7090  list G;
7091  list G0;
7092  list N;
7093  ideal a;
7094  while (size(Epend)>0)
7095  {
7096    a=Epend[1];
7097    Epend=elimidealfromlist(Epend,a);
7098    G0=WLemma(F,a);
7099    if(size(G0)>0)
7100    {
7101      G[size(G)+1]=G0;
7102      //"T_G0="; G0;
7103      N=G0[3][1][2];
7104      //"T_N="; N;
7105      for(i=1;i<=size(N);i++)
7106      {
7107        if(not(equalideals(N[i],ideal(1)) or idinlist(N[i],Etot)))
7108        {
7109          Etot[size(Etot)+1]=N[i];
7110          Epend[size(Epend)+1]=N[i];
7111        }
7112        //"T_i="; i;
7113      }
7114      //"T_Etot="; Etot;
7115      //"T_Epend=";Epend;
7116    }
7117  }
7118  return(G);
7119}
7120example
7121{ "EXAMPLE:"; echo = 2;
7122 if(defined(RRR)){kill RRR;}
7123 ring RRR=(0,b,c,d,e,f),(x,y,t),lp;
7124 short=0;
7125 ideal S=x^2+2*c*x*y+2*d*x*t+b*y^2+2*e*y*t+f*t^2,
7126            x+c*y+d*t,c*x+b*y+e*t;
7127 grobcov(S);
7128 WLcgs(S);
7129}
7130
7131
7132//********************* End WLemma ************************
7133
7134
7135// Not used
7136static proc redbasis(ideal B, ideal C)
7137{
7138  int i;
7139  def RR=basering;
7140  def Rx=ringlist(RR);
7141  def Lx=Rx;
7142  def P=ring(Rx[1]);
7143  Lx[1]=0;
7144  def D=ring(Lx);
7145  def RP=D+P;
7146  setring RP;
7147  ideal BB=imap(RR,B);
7148  ideal CC=imap(RR,C);
7149  attrib(CC,"IsSB",1);
7150  CC=std(CC);
7151  for(i=1;i<=size(BB);i++)
7152  {
7153    BB[i]=reduce(BB[i],CC);
7154  }
7155  setring(RR);
7156  def BBB=imap(RP,BB);
7157  return(BBB);
7158}
7159
7160
7161// not used
7162// Input: ideals E, N
7163// Output: the ideal N without the polynomials in E
7164//   Works in any kind of ideal
7165static proc idminusid(ideal E,ideal N)
7166{
7167  int i; int j;
7168  ideal h;
7169  int te=1;
7170  for(i=1; i<=size(N);i++)
7171  {
7172    te=1;
7173    for(j=1;j<=size(E);j++)
7174    {
7175      if(N[i]==E[j]){te=0;}
7176    }
7177    if(te==1){h[size(h)+1]=N[i];}
7178  }
7179  return(h);
7180}
7181
7182// not used
7183// eliminar els factors de cada polinomi de F que estiguin a N\ E
7184static proc simpB(ideal F,ideal E,ideal N)
7185{
7186  ideal FF;
7187  poly ff;
7188  int i; int j;
7189  ideal J=idminusid(E,N);
7190  //"T_J="; J;
7191  for(i=1;i<=size(F);i++)
7192  {
7193    for(j=1;j<=size(J);j++)
7194    {
7195      ff=elimfacsinP(F[i],J[j]);
7196    }
7197    FF[size(FF)+1]=ff;
7198  }
7199  return(FF);
7200}
7201
7202// used in simpB that is not used
7203static proc elimfacsinP(poly f,poly g)
7204{
7205  def RR=basering;
7206  def Rx=ringlist(RR);
7207  int i; int j;
7208  int n=size(Rx[1][2]);
7209  def Lx=Rx;
7210  Lx[1]=0;
7211  def D=ring(Lx);
7212  def P=ring(Rx[1]);
7213  def RP=D+P;
7214  setring P;
7215  ideal vp;
7216  for(i=1;i<=n;i++)
7217  {
7218    vp[size(vp)+1]=var(i);
7219  }
7220  setring RP;
7221  def gg=imap(RR,g);
7222  ideal vpr=imap(P,vp);
7223  poly ff=imap(RR,f);
7224  def L=factorize(ff);
7225  def L1=L[1];
7226  poly p=1;
7227  for(i=1;i<=size(L1);i++)
7228  {
7229    if(L1[i]==gg){;}
7230    else{p=p*L1[i];}
7231  }
7232  setring RR;
7233  def pp=imap(RP,p);
7234  return(pp);
7235}
7236
7237//****************************** Begin ADGT *************************
7238
7239// used in ADGT
7240// Given G=grobcov(F,"rep",1) to have the GC in C-representation,
7241// Grob1Levels determines the canonical levels of the constructible subset
7242// of the parameter space for which there exist solutions of F
7243// To be called in Q[a][x]
7244proc Grob1Levels(list G)
7245"USAGE: Grob1Levels(list G);
7246       G is the output of grobcov(F,\"rep\",1)
7247       for obtaining the segments in C-rep.
7248       Then Grob!Levels, selects the set of segments S of G having solutions
7249       (i.e. with basis different from 1), and determines the canonical levels
7250       of this constructible set.
7251       To be called in a ring Q[a][x].
7252RETURN: The list of ideals
7253       [a1,a2,...,at]
7254       representing the closures of the canonical levels of S
7255       and its complement C wrt to the closure of S.
7256
7257       The levels of S and C are
7258       Levels of S:  [a1,a2],[a3,a4],...
7259       Levels of C:  [a2,a3],[a4,a5],...
7260       S=V(a1) \ V(a2) u V(a3) \ V(a4) u ...
7261       C=V(a2 \ V(a3) u V(a4) \ V(a5) u ...
7262       The expression of S can be obtained from the
7263       output of Grob1Levels by
7264       the call to Levels.
7265NOTE: The algorithm was described in
7266       J.M. Brunat, A. Montes. \"Computing the canonical
7267       representation of constructible sets.\"
7268       Math.  Comput. Sci. (2016) 19: 165-178.
7269KEYWORDS: constructible set; locally closed set; canonical form
7270EXAMPLE:  Grob1Levels; shows an example"
7271{
7272  int i;
7273  list S;
7274  def RR=basering;
7275  def Rx=ringlist(RR);
7276  def P=ring(Rx[1]);
7277  setring(RR);
7278  for(i=1;i<=size(G);i++)     // select the segments with solutions
7279  {
7280    if(not(G[i][1][1][1]==1))
7281    {
7282      S[size(S)+1]=G[i][3];
7283    }
7284  }
7285  if(size(S)==0)
7286  {
7287    list L;
7288    L[1]=1;
7289  }
7290  else
7291  {
7292    setring P;
7293    def SP=imap(RR,S);
7294    list LP=ConsLevels(SP);   // construct the levels of the constructible
7295    setring RR;
7296    def L=imap(P,LP);
7297  }
7298  return(L);
7299}
7300example
7301{ "EAXMPLE:"; echo = 2;
7302if (defined(R)) {kill R;}
7303ring R=(0,x,y),(x1,y1,x2,y2),lp;
7304ideal F=-y*x1+(x-1)*y1+y,
7305         (x-1)*(x1+1)+y*y1,
7306         -y*x2+(x+1)*y2-y,
7307         (x+1)*(x2-1)+y*y2,
7308         (x1-x)^2+y1^2-(x1-x)^2-y2^2;
7309
7310def G=grobcov(F,"rep",1);
7311G;
7312
7313def L=Grob1Levels(G);
7314L;
7315
7316def LL=Levels(L);
7317LL;
7318}
7319
7320// Auxiliary rutine for intersecting ideal only in the parameters a
7321// when the ideals are defined in Q[a][x]
7322proc intersectpar(list S)
7323"USAGE: interectpar(list of ideals S)
7324    list S=ideal I1,...,ideal Ik;
7325RETURN: The intersection of the ideals I1 ...  Ik  in Q[x,a]
7326NOTE: The routine is called in Q[a][x],
7327    The ideals I1,..,Ik can be ideals depending only on [a] or on [x,a]
7328EXAMPLE: intersectpar shows an example"
7329{
7330  def RR=basering;
7331  def Rx=ringlist(RR);
7332  def P=ring(Rx[1]);
7333  Rx[1]=0;
7334  def D=ring(Rx);
7335  def RP=D+P;
7336  setring(RP);
7337  def SP=imap(RR,S);
7338  //"T_SP="; SP;
7339  //"T_typeof(SP[1])="; typeof(SP[1]);
7340  ideal EP;
7341  EP=SP[1];
7342  int i;
7343  for(i=2;i<=size(SP);i++)
7344  {
7345    EP=intersect(EP,SP[i]);
7346  }
7347  //def EP=intersect(SPL);
7348  setring RR;
7349  def E=imap(RP,EP);
7350  return(E);
7351}
7352example
7353{ "EAXMPLE:"; echo = 2;
7354if(defined(R)){kill R;}
7355ring R=(0,x,y,z),(x1,y1,z1),lp;
7356
7357ideal I1=x+y*z*x1;
7358ideal I2=x-y*z*y1;
7359ideal I3=x+y+z*z1;
7360list S=I1,I2,I3;
7361S;
7362
7363intersectpar(S);
7364}
7365
7366proc ADGT(ideal H,ideal T,ideal H1,ideal T1,list #)
7367"USAGE: ADGT(ideal H, ideal T, ideal H1,ideal T1[,options]);
7368      H: ideal in Q[a][x] hypothesis
7369      T: ideal in Q[a][x] thesis
7370      H1: ideal in Q[a][x] negative hypothesis, only dependent on [a]
7371      T1: ideal in Q[a][x] negative thesis
7372           of the Proposition (H and not H1) => (T and not T1)
7373RETURN: The list  [[1,S1],[2,S2],..],
7374       S1, S2, .. represent the set of parameter values
7375       that must be verified as supplementary
7376       conditions for the Proposition to become a Theorem.
7377       They are given by default in Prep.
7378       If the proposition is generally true,
7379       (the proposition is already a theorem), then
7380       the generic segment of the internal grobcov
7381       called is also returned to provide information
7382       about the values of the variables determined
7383       for every value of the parameters.
7384       If the propsition is false for every values of the
7385       parameters, then the emply list is returned.
7386OPTIONS: An option is a pair of arguments: string,
7387       integer. To modify the default options, pairs
7388       of arguments -option name, value- of valid options
7389       must be added to the call.
7390       Option \"rep\",0-1: The default is (\"rep\",0)
7391       and then the segments are given in canonical
7392       P-representation.
7393       Option (\"rep\",1) represents the segments
7394       in canonical C-representation,
7395       Option \"gseg\",0-1: The default is \"gseg\",1
7396       and then when the proposition is generally true,
7397       ADGT outputs a second element which is the
7398       \"generic segment\" to provide supplementary information.
7399       With option \"gseg\",0 this is avoided.
7400       Option \"neg\", 0,1:  The default is \"neg\",0
7401       With option  \"neg\",0  Rabinovitch trick is used for negative hypothesis and thesis
7402       With option  \"neg\",1  Difference of constructible sets is used instead.
7403NOTE:  The basering R, must be of the form Q[a][x],
7404       (a=parameters, x=variables), and
7405       should be defined previously. The ideals
7406       must be defined on R.
7407KEYWORDS: Automatic Deduction; Automatic Demonstration; Geometric Theorems
7408EXAMPLE:  ADGT shows an example"
7409{
7410  int i; int j;
7411  def RR=basering;
7412  def Rx=ringlist(RR);
7413  def P=ring(Rx[1]);
7414  Rx[1]=0;
7415  def D=ring(Rx);
7416  def RP=D+P;
7417  setring RR;
7418  list Lopt=#;
7419  int start=timer;
7420  // options
7421  int rep=0;
7422  int gseg=1;
7423  int neg=0;
7424
7425  for(i=1;i<=size(Lopt) div 2;i++)
7426  {
7427    if(Lopt[2*i-1]=="rep"){rep=Lopt[2*i];}
7428    if(Lopt[2*i-1]=="gseg"){gseg=Lopt[2*i];}
7429    if(Lopt[2*i-1]=="neg"){neg=Lopt[2*i];}
7430  }
7431  // begin proc
7432
7433  if(neg==0)
7434  {
7435  // Default option "neg",0  uses Rabinovitch for negative hyothesis and thesis
7436  // Option "neg",1  uses Diference of constructive sets for negative hyothesis and thesis
7437  if(equalideals(T1,ideal(1))) //nonnullT==0)
7438  {
7439    def F=H;
7440    for(i=1;i<=size(T);i++)
7441    {
7442      F[size(F)+1]=T[i];
7443    }
7444    list G2;
7445    if(not(equalideals(H1,ideal(1))))  //nonnullH==1)
7446    {
7447      G2=grobcov(F,"nonnull",H1,"rep",1);
7448    }
7449    else
7450    {
7451      G2=grobcov(F,"rep",1);
7452    }
7453  }
7454  else
7455  {
7456    def F=H;
7457    for(i=1;i<=size(T1);i++)
7458    {
7459      F[size(F)+1]=T1[i];
7460    }
7461    list G3=grobcov(F,"rep",1);
7462    def L0=Grob1Levels(G3);
7463    setring P;
7464    def LP=imap(RR,L0);
7465    def H1P=imap(RR,H1);
7466    if(not(equalideals(H1P,ideal(1))))  //nonnullH==1)
7467    {
7468      i=1;
7469      while(i<=size(LP))
7470      {
7471        if(i mod 2==1)
7472        {
7473          LP[i]=intersect(LP[i],H1P);
7474        }
7475        i++;
7476      }
7477    }
7478    setring RR;
7479    L0=imap(P,LP);
7480    F=H;
7481    for(i=1;i<=size(T);i++)
7482    {
7483      F[size(F)+1]=T[i];
7484    }
7485    def G2=grobcov(F,"nonnull",L0[1],"rep",1);
7486    list G1;
7487    int m=size(L0);
7488    int r=m div 2;
7489    if(m mod 2==0){r=r-1;}
7490    //"L0="; L0;
7491     for(i=1;i<=r;i++)
7492    {
7493      G1=grobcov(F,"null",L0[2*i],"nonnull",L0[2*i+1],"rep",1);
7494      for(j=1;j<=size(G1);j++)
7495      {
7496        if(not(equalideals(G1[j][1],ideal(1))))
7497        {
7498          G2[size(G2)+1]=G1[j];
7499        }
7500      }
7501    }
7502  }
7503  if(size(G2)==0)
7504  {
7505    list L;
7506    // L[1]=1;
7507  }
7508  else
7509  {
7510    list L=Levels(Grob1Levels(G2));
7511    if(rep==0 and size(L)>0)
7512    {
7513      setring P;
7514      def LFP=imap(RR,L);
7515      // list LFP1=LFP;
7516      for(i=1;i<=size(LFP);i++)
7517      {
7518        LFP[i][2]=Prep(LFP[i][2][1],LFP[i][2][2]);
7519      }
7520      setring RR;
7521      L=imap(P,LFP);
7522    }
7523    if(equalideals(G2[1][3][1][1],0) and not(equalideals(G2[1][1],ideal(1))))
7524    {
7525      list GL=G2[1];
7526      list LL=GL[3];
7527      if(rep==0)
7528      {
7529        setring P;
7530        def LLP=imap(RR,LL);
7531        LLP=Prep(LLP[1],LLP[2]);
7532        setring RR;
7533        LL=imap(P,LLP);
7534        GL[3]=LL;
7535      }
7536      if(gseg==1)
7537      {
7538        L[size(L)+1]=list("Generic segment",GL);
7539      }
7540    }
7541  }
7542  return(L);
7543  }
7544  else
7545  {
7546    if (neg==1)
7547    {
7548      def LL=ADGTDif(H,T,H1,T1,#);
7549      return(LL);
7550    }
7551  }
7552}
7553example
7554{ "EXAMPLE:"; echo = 2;
7555// Determine the supplementary conditions
7556// for the non-degenerate  triangle A(-1,0), B(1,0), C(x,y)
7557// to have an ortic non-degenerate isosceles triangle
7558
7559if(defined(R)){kill R;}
7560ring R=(0,x,y),(x2,y2,x1,y1),lp;
7561
7562// Hypothesis H: the triangle  A1(x1,y1), B1(x2,y2), C1(x,0), is the
7563// orthic triangle of ABC
7564
7565ideal H=-y*x1+(x-1)*y1+y,
7566        (x-1)*(x1+1)+y*y1,
7567        -y*x2+(x+1)*y2-y,
7568        (x+1)*(x2-1)+y*y2;
7569
7570// Thesis T: the orthic triangle is isosceles
7571 ideal T=(x1-x)^2+y1^2-(x2-x)^2-y2^2;
7572
7573// Negative Hypothesis H1: ABC is non-degenerate
7574ideal H1=y;
7575
7576// Negative Thesis T1: the orthic triangle is non-degenerate
7577ideal T1=x*(y1-y2)-y*(x1-x2)+x1*y2-x2*y1;
7578
7579// Complementary conditions for the
7580// Proposition (H and not H1) => (T and not T1)
7581// to be true
7582
7583ADGT(H,T,H1,T1);
7584
7585// Now using diference of constructible sets for negative hypothesis and thesis
7586
7587ADGT(H,T,H1,T1,"neg",1);
7588
7589// The results are identical using both methods for the negative propositions
7590// - Rabinovitch or
7591// - DifConsLCSets
7592
7593// EXAMPLE 2
7594
7595// Automatic Theorem Proving.
7596// The nine points circle theorem.
7597
7598// Vertices of the triangle: A(-2,0), B(2,0), C(2a,2b)
7599
7600// Heigth foot: A1(x1,y1),
7601// Heigth foot: B1(x2,y2),
7602// Heigth foot: C1(2a,0)
7603
7604// Middle point BC:  A2(a+1,b)
7605// Middle point CA:  B2 (a-1,b)
7606// Middle point AB:  C2(0,0)
7607
7608// Ortocenter:   O(2x0,2y0)
7609// Middle point of A and O:  A3(x0-1,y0)
7610// Middle point of B and O:  B3(x0+1,y0)
7611// Middle point of C and O:  C3(x0+a,y0+b)
7612
7613// Nine points circle: c:=(X-x3)^2+(Y-y3)^2-r2
7614
7615if (defined(R1)){kill R1;}
7616ring R1=(0,a,b),(x1,y1,x2,y2,x0,y0,x3,y3,r2),dp;
7617short=0;
7618
7619ideal H=-x1*b+(a-1)*y1+2*b,
7620      (a-1)*x1+b*y1+2*a-2,
7621      -x2*b+(a+1)*y2-2*b,
7622      (a+1)*x2+b*y2-2*a-2,
7623      -x0*y1+(x1+2)*y0-y1,
7624      -x0*y2+(x2-2)*y0+y2;
7625
7626ideal T=(x1-2*x3)^2+(y1-2*y3)^2-r2,
7627       (a+1-2*x3)^2+(b-2*y3)^2-r2,
7628       (x0-1-2*x3)^2+(y0-2*y3)^2-r2,
7629       (x2-2*x3)^2+(y2-2*y3)^2-r2,
7630       (a-1-2*x3)^2+(b-2*y3)^2-r2,
7631       (x0+1-2*x3)^2+(y0-2*y3)^2-r2,
7632       (2*a-2*x3)^2+4*y3^2-r2,
7633       4*x3^2+4*y3^2-r2,
7634       (x0+a-2*x3)^2+(y0+b-2*y3)^2-r2;
7635
7636ADGT(H,T,b,1);
7637
7638// Thus the nine point circle theorem is true for all real points excepting b=0.
7639}
7640
7641static proc ADGTDif(ideal H,ideal T,ideal H1,ideal T1,list #)
7642{
7643  int i; int j;
7644  def RR=basering;
7645  def Rx=ringlist(RR);
7646  def P=ring(Rx[1]);
7647  Rx[1]=0;
7648  def D=ring(Rx);
7649  def RP=D+P;
7650  setring RR;
7651  list Lopt=#;
7652  int start=timer;
7653  // options
7654  int rep=0;
7655  int gseg=1;
7656  list LLL;
7657  for(i=1;i<=size(Lopt) div 2;i++)
7658  {
7659    if(Lopt[2*i-1]=="rep"){rep=Lopt[2*i];}
7660    else{if(Lopt[2*i-1]=="gseg"){gseg=Lopt[2*i];}}
7661  }
7662  // begin proc
7663    def F=H;
7664    for(i=1;i<=size(T);i++)
7665    {
7666      F[size(F)+1]=T[i];
7667    }
7668    list G2=grobcov(F,"rep",1);
7669    def L2=Grob1Levels(G2);
7670    //"L2="; L2;
7671    ideal FN=T1;
7672    if(not(equalideals(H1,ideal(1))))
7673    {
7674      list FNH1=FN,H1;
7675      FN=intersectpar(FNH1);
7676    }
7677    if(not(equalideals(FN,ideal(1))))
7678    {
7679      for(i=1;i<=size(FN);i++)
7680      {
7681        F[size(F)+1]=FN[i];
7682      }
7683      list G3=grobcov(F,"rep",1);
7684      def L3=Grob1Levels(G3);
7685      //"L3="; L3;
7686    }
7687    def LL=DifConsLCSets(L2,L3);
7688    //"LL="; LL;
7689    LL=ConsLevels(LL);
7690    LL=Levels(LL);
7691     //"LL="; LL;
7692    if(rep==1){return(LL);}
7693    else
7694    {
7695      for(i=1;i<=size(LL);i++)
7696      {
7697         LL[i][2]=Prep(LL[i][2][1],LL[i][2][2]);
7698      }
7699    }
7700    return(LL);
7701}
7702
7703//****************************** End ADGT *************************
7704;
Note: See TracBrowser for help on using the repository browser.