source: git/Singular/LIB/grobcov.lib @ 20f2239

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