source: git/Singular/LIB/solve.lib @ e480be8

spielwiese
Last change on this file since e480be8 was e480be8, checked in by Sachin <sachinkm308@…>, 5 years ago
replacing execute with create_ring (5)
  • Property mode set to 100644
File size: 57.9 KB
Line 
1////////////////////////////////////////////////////////////////////////////
2version="version solve.lib 4.1.2.0 Feb_2019 "; // $Id$
3category="Symbolic-numerical solving";
4info="
5LIBRARY: solve.lib     Complex Solving of Polynomial Systems
6AUTHOR:  Moritz Wenk,  email: wenk@mathematik.uni-kl.de
7         Wilfred Pohl, email: pohl@mathematik.uni-kl.de
8
9PROCEDURES:
10laguerre_solve(p,[..]); find all roots of univariate polynomial p
11solve(i,[..]);          all roots of 0-dim. ideal i using triangular sets
12ures_solve(i,[..]);     find all roots of 0-dimensional ideal i with resultants
13mp_res_mat(i,[..]);     multipolynomial resultant matrix of ideal i
14interpolate(p,v,d);     interpolate polynomial from evaluation points i and results j
15fglm_solve(i,[..]);     find roots of 0-dim. ideal using FGLM and lex_solve
16lex_solve(i,p,[..]);    find roots of reduced lexicographic standard basis
17simplexOut(l);          prints solution of simplex in nice format
18triangLf_solve(l,[..]); find roots using triangular sys. (factorizing Lazard)
19triangM_solve(l,[..]);  find roots of given triangular system (Moeller)
20triangL_solve(l,[..]);  find roots using triangular system (Lazard)
21triang_solve(l,p,[..]); find roots of given triangular system
22";
23
24LIB "triang.lib";    // needed for triang_solve
25LIB "ring.lib";      // needed for changeordTo
26
27///////////////////////////////////////////////////////////////////////////////
28
29proc laguerre_solve( poly f, list # )
30"USAGE:   laguerre_solve(f [, m, l, n, s] ); f = polynomial,@*
31         m, l, n, s = integers (control parameters of the method)@*
32 m: precision of output in digits ( 4 <= m), if basering is not ring of
33      complex numbers;
34 l: precision of internal computation in decimal digits ( l >=8 )
35      only if the basering is not complex or complex with smaller precision;@*
36 n: control of multiplicity of roots or of splitting of f into
37      squarefree factors
38      n < 0, no split of f (good, if all roots are simple)
39      n >= 0, try to split
40      n = 0, return only different roots
41      n > 0, find all roots (with multiplicity)
42 s: s != 0, returns ERROR if  | f(root) | > 0.1^m (when computing in the
43      current ring)
44 ( default: m, l, n, s = 8, 30, 1, 0 )
45ASSUME:  f is a univariate polynomial;@*
46         basering has characteristic 0 and is either complex or without
47         parameters.
48RETURN:  list of (complex) roots of the polynomial f, depending on n. The
49         entries of the result are of type@*
50          string: if the basering is not complex,@*
51          number: otherwise.
52NOTE:    If printlevel >0: displays comments ( default = 0 ).
53         If s != 0 and if the procedure stops with ERROR, try a higher
54         internal precision m.
55EXAMPLE: example laguerre_solve; shows an example
56"
57{
58  if (char(basering)!=0){ERROR("characteristic of basering not 0");}
59  if ((charstr(basering)[1]=="0") and (npars(basering)!=0))
60    {ERROR("basering has parameters");}
61  int OLD_COMPLEX=0;
62  int iv=checkv(f);  // check for variable appearing in f
63  if(iv==0){ERROR("Wrong polynomial!");}
64  poly v=var(iv);    // f univariate in v
65
66  int solutionprec=8;// set the control
67  int numberprec=30;
68  int splitcontrol=1;
69  int rootcheck=0;
70  if(size(#)>0){solutionprec=#[1];if(solutionprec<4){solutionprec=4;}}
71  if(size(#)>1){numberprec=#[2];if(numberprec<8){numberprec=8;}}
72  if(solutionprec>numberprec){numberprec=solutionprec;}
73  if(size(#)>2){splitcontrol=#[3];}
74  if(size(#)>3){rootcheck=#[4];}
75  int prot=printlevel-voice+2;
76  int ringprec=0;
77
78  poly p=divzero(f,iv); // divide out zeros as solution
79  int iz=deg(f)-deg(p); // multiplicity of zero solution
80  if(prot!=0)
81  {
82    string pout;
83    string nl=newline;
84    pout="//BEGIN laguerre_solve";
85    if(iz!=0){pout=pout+nl+"//zeros: divide out "+string(iz);}
86    dbprint(prot,pout);
87  }
88  string ss,tt,oo;
89  ss="";oo=ss;
90  if(npars(basering)==1)
91  {
92    if(OLD_COMPLEX)
93    {
94      tt="1,"+string(par(1));
95      if(tt==charstr(basering))
96      {ss=tt;ringprec=system("getPrecDigits");}
97    }
98    else
99    {
100      tt=charstr(basering);
101      if(size(tt)>7)
102      {
103        if(string(tt[1..7])=="complex")
104        {
105          ss=tt;
106          ringprec=system("getPrecDigits");
107        }
108      }
109    }
110  }
111
112  list roots,simple;
113  if(deg(p)==0) // only zero was root
114  {
115    roots=addzero(roots,ss,iz,splitcontrol);
116    if(prot!=0){dbprint(prot,"//END laguerre_solve");}
117    return(roots);
118  }
119
120  if(prot!=0)// more informations
121  {
122    pout="//control: complex ring with precision "+string(numberprec);
123    if(size(ss)==0){pout=pout+nl+
124        "//         basering not complex, hence solutiontype string";
125    if(solutionprec<numberprec){pout=pout+nl+
126        "//         with precision "+string(solutionprec);}}
127    if(splitcontrol<0){pout=pout+nl+ "//       no spliting";}
128    if(splitcontrol==0){pout=pout+nl+"//       output without multiple roots";}
129    if(rootcheck){pout=pout+nl+
130        "//         check roots with precision "+string(solutionprec);}
131    dbprint(prot,pout);
132  }
133
134  def rn = basering;// set the complex ground field
135  if (ringprec<numberprec)
136  {
137    tt="ring lagc=(complex,"+string(numberprec)+","+string(numberprec)+
138       "),"+string(var(iv))+",lp;";
139    execute(tt);
140    poly p=imap(rn,p);
141    poly v=var(1);
142  }
143  int ima=0;
144  if(size(ss)!=0){ima=checkim(p);}
145  number prc=0.1;// set precision of the solution
146  prc=prc^solutionprec;
147  if(prot!=0)
148  {
149    if(ringprec<numberprec){pout="//working in:  "+tt;}
150    if((size(ss)!=0)&&(ima!=0)){pout=pout+nl+
151        "//         polynomial has complex coefficients";}
152    dbprint(prot,pout);
153  }
154
155  int i1=1;
156  int i2=1;
157  ideal SPLIT=p;
158  if(splitcontrol>=0)// splitting
159  {
160    if(prot!=0){dbprint(prot,"//split in working ring:");}
161    SPLIT=splitsqrfree(p,v);
162    i1=size(SPLIT);
163    if((i1==1)&&(charstr(rn)=="0"))
164    {
165      if(prot!=0){dbprint(prot,"//split exact in basering:");}
166      setring rn;
167      if(v>1)
168      {
169        ideal SQQQQ=splitsqrfree(p,v);
170        setring lagc;
171        SPLIT=imap(rn,SQQQQ);
172      }
173      else
174      {
175        oo="ring exa=0,"+string(var(1))+",lp;";
176        execute(oo);
177        ideal SQQQQ=splitsqrfree(imap(rn,p),var(1));
178        setring lagc;
179        SPLIT=imap(exa,SQQQQ);
180        kill exa;
181      }
182      i1=size(SPLIT);
183    }
184    if(prot!=0)
185    {
186      if(i1>1)
187      {
188        int i3=deg(SPLIT[1]);
189        pout="//results of split(the squarefree factors):";
190        if(i3>0){pout=pout+nl+
191           "//  multiplicity "+string(i2)+", degree "+string(i3);}
192        while(i2<i1)
193        {
194          i2++;
195          i3=deg(SPLIT[i2]);
196          if(i3>0){pout=pout+nl+
197             "//  multiplicity "+string(i2)+", degree "+string(i3);}
198        }
199        dbprint(prot,pout);
200        i2=1;
201      }
202      else
203      {
204        if(charstr(rn)=="0"){dbprint(prot,"// polynomial is squarefree");}
205        else{dbprint(prot,"//split without result");}
206      }
207    }
208  }
209
210  p=SPLIT[1];// the first part
211  if(deg(p)>0)
212  {
213    roots=laguerre(p,numberprec,1);// the ring is already complex, hence numberprec is dummy
214    if((size(roots)==0)||(string(roots[1])=="0")){ERROR("laguerre: no roots found");}
215    if(rootcheck){checkroots(p,v,roots,ima,prc);}
216  }
217  while(i2<i1)
218  {
219    i2++;
220    p=SPLIT[i2];// the part with multiplicity i2
221    if(deg(p)>0)
222    {
223      simple=laguerre(p,numberprec,1);
224      if((size(simple)==0)||(string(simple[1])=="0")){ERROR("laguerre: no roots found");}
225      if(rootcheck){checkroots(p,v,simple,ima,prc);}
226      if(splitcontrol==0)// no multiple roots
227      {
228        roots=roots+simple;
229      }
230      else// multiple roots
231      {
232        roots=roots+makemult(simple,i2);
233      }
234    }
235  }
236
237  if((solutionprec<numberprec)&&(size(ss)==0))// shorter output
238  {
239    oo="ring lout=(complex,"+string(solutionprec)+",1),"
240    +string(var(1))+",lp;";
241    execute(oo);
242    list roots=imap(lagc,roots);
243    roots=transroots(roots);
244    if(iz>0){roots=addzero(roots,ss,iz,splitcontrol);}
245    if(prot!=0){dbprint(prot,"//END laguerre_solve");}
246    return(roots);
247  }
248  if(size(ss)==0){roots=transroots(roots);}// transform to string
249  else         // or map in basering
250  {
251    if(ringprec<numberprec)
252    {
253      setring rn;
254      list roots=imap(lagc,roots);
255    }
256  }
257  if(iz>0){roots=addzero(roots,ss,iz,splitcontrol);}
258  if(prot!=0){dbprint(prot,"//END laguerre_solve");}
259  return(roots);
260}
261example
262{
263    "EXAMPLE:";echo=2;
264    // Find all roots of an univariate polynomial using Laguerre's method:
265    ring rs1= 0,(x,y),lp;
266    poly f = 15x5 + x3 + x2 - 10;
267    // 10 digits precision
268    laguerre_solve(f,10);
269
270    // Now with complex coefficients,
271    // internal precision is 30 digits (default)
272    printlevel=2;
273    ring rsc= (real,10,i),x,lp;
274    poly f = (15.4+i*5)*x^5 + (25.0e-2+i*2)*x^3 + x2 - 10*i;
275    list l = laguerre_solve(f);
276    l;
277    // check result, value of substituted polynomial should be near to zero
278    // remember that l contains a list of strings
279    // in the case of a different ring
280    subst(f,x,l[1]);
281    subst(f,x,l[2]);
282}
283//////////////////////////////////////////////////////////////////////////////
284//                subprocedures for laguerre_solve
285/*
286*  if p depends only on var(i)
287*       returns i
288*  otherwise    0
289*/
290static proc checkv(poly p)
291{
292  int n=nvars(basering);
293  int i=0;
294  int v;
295
296  while (n>0)
297  {
298    if ((p-subst(p,var(n),0))!=0)
299    {
300      i++;
301      if (i>1){return(0);}
302      v=n;
303    }
304    n--;
305  }
306  return(v);
307}
308/*
309*  if p has only real coefficients
310*       returns 0
311*  otherwise    1
312*/
313static proc checkim(poly p)
314{
315  poly q=p;
316
317  while(q!=0)
318  {
319    if(impart(leadcoef(q))!=0){return(1);}
320    q=q-lead(q);
321  }
322  return(0);
323}
324/*
325*  make multiplicity m
326*/
327static proc makemult(list si,int m)
328{
329  int k0=0;
330  int k1=size(si);
331  int k2,k3;
332  number ro;
333  list msi;
334
335  for(k2=1;k2<=k1;k2++)
336  {
337    ro=si[k2];
338    for(k3=m;k3>0;k3--){k0++;msi[k0]=ro;}
339  }
340  return(msi);
341}
342/*
343*  returns 1 for n<1
344*/
345static proc cmp1(number n)
346{
347  number r=repart(n);
348  number i=impart(n);
349  number c=r*r+i*i;
350  if(c>1){return(1);}
351  else{return(0);}
352}
353/*
354*  exact division of polys f/g
355*  (should be internal)
356*/
357static proc exdiv(poly f,poly g,poly v)
358{
359  int d1=deg(f);
360  int d2=deg(g);
361  poly r0=f;
362  poly rf=0;
363  poly h;
364  number n,m;
365
366  m=leadcoef(g);
367  while ((r0!=0)&&(d1>=d2))
368  {
369    n=leadcoef(r0)/m;
370    h=n*v^(d1-d2);
371    rf=rf+h;
372    r0=r0-h*g;
373    d1=deg(r0);
374  }
375  return(cleardenom(rf));
376}
377/*
378*  p is univariant in x
379*  perform a split of p into squarefree factors
380*  such that the returned ideal 'split' consists of
381*  the faktors, i.e.
382*    p = n * product ( split[i]^i ) , n a number
383*/
384static proc splitsqrfree(poly p, poly x)
385{
386  int dd=deg(p);
387  if(dd==1){return(p);}
388  int i=1;
389  int j;
390  ideal h,split;
391  poly high;
392
393  h=interred(ideal(p,diff(p,x)));
394  if(deg(h[1])==0){return(p);}
395  high=h[1];
396  split[1]=exdiv(p,high,x);
397  while(1)
398  {
399    h=interred(ideal(split[i],high));
400    j=deg(h[1]);
401    if(j==0){return(p);}
402    if(deg(h[1])==deg(split[i]))
403    {
404      split=split,split[i];
405      split[i]=1;
406    }
407    else
408    {
409      split[i]=exdiv(split[i],h[1],x);
410      split=split,h[1];
411      dd=dd-deg(split[i])*i;
412    }
413    j=j*(i+1);
414    if(j==dd){break;}
415    if(j>dd){return(p);}
416    high=exdiv(high,h[1],x);
417    if(deg(high)==0){return(p);}
418    i++;
419  }
420  return(split);
421}
422/*
423*  see checkroots
424*/
425static proc nerr(number n,number m)
426{
427  int r;
428  number z=0;
429  number nr=repart(n);
430  number ni=impart(n);
431  if(nr<z){nr=z-nr;}
432  if(ni<z){ni=nr-ni;}
433  else{ni=nr+ni;}
434  if(ni<m){r=0;}
435  else{r=1;}
436  return(r);
437}
438/*
439*  returns ERROR for nerr(p(r[i]))>=pr
440*/
441static proc checkroots(poly p,poly v,list r,int ima,number pr)
442{
443  int i=0;
444  int j;
445  number n,m;
446  ideal li;
447
448  while(i<size(r))
449  {
450    i++;
451    n=r[i];
452    j=cmp1(n);
453    if(j!=0){li[1]=v/n-1;m=1;}
454    else{li[1]=v-n;m=n;}
455    if((ima==0)&&(impart(n)!=0))
456    {
457      i++;
458      n=r[i];
459      if(j!=0){li[1]=li[1]*(v/n-1);}
460      else{li[1]=li[1]*(v-n);m=m*n;}
461    }
462    attrib(li,"isSB",1);
463    n=leadcoef(reduce(p,li));n=n/m;
464    if(n!=0)
465    {if(nerr(n,pr)!=0){ERROR("Unsufficient accuracy!");}}
466  }
467}
468/*
469*  transforms thr result to string
470*/
471static proc transroots(list r)
472{
473  int i=size(r);
474  while (i>0)
475  {
476    r[i]=string(r[i]);
477    i--;
478  }
479  return(r);
480}
481/*
482* returns a polynomial without zeroroots
483*/
484static proc divzero(poly f,int iv)
485{
486  poly p=f;
487  poly q=p;
488  poly r;
489  while(p==q)
490  {
491    q=p/var(iv);
492    r=q*var(iv);
493    if(r==p){p=q;}
494  }
495  return(p);
496}
497/*
498*  add zeros to solution
499*/
500static proc addzero(list zz,string ss,int iz,int a)
501{
502    int i=1;
503    int j=size(zz);
504
505    if(size(ss)==0){zz[j+1]="0";}
506    else{zz[j+1]=number(0);}
507    if(a==0){return(zz);}
508    while(i<iz)
509    {
510      i++;
511      if(size(ss)==0){zz[j+i]="0";}
512      else{zz[j+i]=number(0);}
513    }
514    return(zz);
515}
516///////////////////////////////////////////////////////////////////////////////
517
518proc solve( ideal G, list # )
519"USAGE:   solve(G [, m, n [, l]] [,\"oldring\"] [,\"nodisplay\"] ); G = ideal,
520         m, n, l = integers (control parameters of the method), outR ring,@*
521         m: precision of output in digits ( 4 <= m) and of the generated ring
522            of complex numbers;
523         n: control of multiplicity
524            n = 0, return all different roots
525            n != 0, find all roots (with multiplicity)
526         l: precision of internal computation in decimal digits ( l >=8 )
527            only if the basering is not complex or complex with smaller
528            precision, @*
529         [default: (m,n,l) = (8,0,30), or if only (m,n) are set explicitly
530          with n!=0, then (m,n,l) = (m,n,60) ]
531ASSUME:  the ideal is 0-dimensional;@*
532         basering has characteristic 0 and is either complex or without
533         parameters;
534RETURN:  (1) If called without the additional parameter @code{\"oldring\"}: @*
535         ring @code{R} with the same number of variables but with complex
536         coefficients (and precision m). @code{R} comes with a list
537         @code{SOL} of numbers, in which complex roots of G are stored: @*
538         * If n  = 0, @code{SOL} is the list of all different solutions, each
539         of them being represented by a list of numbers. @*
540         * If n != 0, @code{SOL} is a list of two list: SOL[i][1] is the list
541         of all different solutions with the multiplicity SOL[i][2].@*
542         SOL is ordered w.r.t. multiplicity (the smallest first). @*
543         (2) If called with the additional parameter @code{\"oldring\"}, the
544         procedure looks for an appropriate ring (at top level) in which
545         the solutions can be stored (interactive). @*
546         The user may then select an appropriate ring and choose a name for
547         the output list in this ring. The list is exported directly to the
548         selected ring and the return value is a string \"result exported to\"
549         + name of the selected ring.
550NOTE:    If the problem is not 0-dim. the procedure stops with ERROR. If the
551         ideal G is not a lexicographic Groebner basis, the lexicographic
552         Groebner basis is computed internally (Hilbert driven).  @*
553         The computed solutions are displayed, unless @code{solve} is called
554         with the additional parameter @code{\"nodisplay\"}.
555EXAMPLE: example solve; shows an example
556"
557{
558// test if basering admissible
559  if (char(basering)!=0){ERROR("characteristic of basering not 0");}
560  if ((charstr(basering)[1]=="0") and (npars(basering)!=0))
561  { ERROR("basering has parameters"); }
562
563// some global settings and control
564  int oldr, nodisp, ii, jj;
565  list LL;
566  int outprec = 8;
567  int mu = 0;
568  int prec = 30;
569  // check additional parameters...
570  if (size(#)>0)
571  {
572    int sofar=1;
573    if (typeof(#[1])=="int")
574    {
575      outprec = #[1];
576      if (outprec<4){outprec = 4;}
577      if (size(#)>1)
578      {
579        if (typeof(#[2])=="int")
580        {
581          mu = #[2];
582          if (size(#)>2)
583          {
584            if (typeof(#[3])=="int")
585            {
586              prec = #[3];
587              if (prec<8){prec = 8;}
588            }
589            else
590            {
591              if(mu!=0){prec = 60;}
592              if (#[3]=="oldring"){ oldr=1; }
593              if (#[3]=="nodisplay"){ nodisp=1; }
594            }
595            sofar=3;
596          }
597        }
598        else
599        {
600          if (#[2]=="oldring"){ oldr=1; }
601          if (#[2]=="nodisplay"){ nodisp=1; }
602        }
603        sofar=2;
604      }
605    }
606    else
607    {
608      if (#[1]=="oldring"){ oldr=1; }
609      if (#[1]=="nodisplay"){ nodisp=1; }
610    }
611    for (ii=sofar+1;ii<=size(#);ii++)
612    { // check for additional strings
613      if (typeof(#[ii])=="string")
614      {
615        if (#[ii]=="oldring"){ oldr=1; }
616        if (#[ii]=="nodisplay"){ nodisp=1; }
617      }
618    }
619  }
620  if (outprec>prec){prec = outprec;}
621  // if interaktive version is chosen -- choice of basering (Top::`outR`)
622  // and name for list of solutions (outL):
623  if (oldr==1)
624  {
625    list Out;
626    LL=names(Top);
627    for (ii=1;ii<=size(LL);ii++)
628    {
629      if (typeof(`LL[ii]`)=="ring")
630      {
631        if (find(charstr(`LL[ii]`),"complex,"+string(outprec)))
632        {
633          jj++;
634          Out[jj]=LL[ii];
635        }
636      }
637    }
638    if (size(Out)>0)
639    {
640      print("// *** You may select between the following rings for storing "+
641            "the list of");
642      print("// *** complex solutions:");
643      Out;
644      print("// *** Enter the number of the chosen ring");
645      print("// ***  (0: none of them => new ring created and returned)");
646      string chosen;
647      while (chosen=="") { chosen=read(""); }
648      execute("def tchosen = "+chosen);
649      if (typeof(tchosen)=="int")
650      {
651        if ((tchosen>0) and (tchosen<=size(Out)))
652        {
653          string outR = Out[tchosen];
654          print("// *** You have chosen the ring "+ outR +". In this ring"
655                +" the following objects");
656          print("//*** are defined:");
657          listvar(Top::`outR`);
658          print("// *** Enter a name for the list of solutions (different "+
659                "from existing names):");
660          string outL;
661          while (outL==""){ outL=read(""); }
662        }
663      }
664    }
665    else
666    {
667      print("No appropriate ring for storing the list of solutions found " +
668             "=> new ring created and returned");
669    }
670    if (not(defined(outR))) { oldr=0; }
671  }
672
673//  string rinC = nameof(basering)+"C";
674  string sord = ordstr(basering);
675  int nv = nvars(basering);
676  def rin = basering;
677  intvec ovec = option(get);
678  option(redSB);
679  option(returnSB);
680  int sb = attrib(G,"isSB");
681  int lp = 0;
682  if (size(sord)==size("C,lp()"+string(nv)))
683  {
684    lp = find(sord,"lp");
685  }
686
687// ERROR
688  if (sb){if (dim(G)!=0){ERROR("ideal not zero-dimensional");}}
689
690// the trivial homogeneous case (unique solution: (0,...0))
691  if (homog(G))
692  {
693    if (sb==0)
694    {
695      def dphom=changeordTo(rin,"dp"); setring dphom;
696      ideal G = std(imap(rin,G));
697      if (dim(G)!=0){ERROR("ideal not zero-dimensional");}
698      int vdG=vdim(G);
699    }
700    if (oldr!=1)
701    {
702      ring rinC = create_ring("(complex,"+string(outprec)+")", "("+varstr(basering)+")", "lp");
703      list SOL;
704      if (mu==0){SOL[1] = zerolist(nv);}
705      else{SOL[1] = list(zerolist(nv),list(vdG));}
706      export SOL;
707      if (nodisp==0) { print(SOL); }
708      option(set,ovec);
709      dbprint( printlevel-voice+3,"
710// 'solve' created a ring, in which a list SOL of numbers (the complex solutions)
711// is stored.
712// To access the list of complex solutions, type (if the name R was assigned
713// to the return value):
714        setring R; SOL; ");
715      return(rinC);
716    }
717    else
718    {
719      setring (Top::`outR`);
720      list SOL;
721      if (mu==0){SOL[1] = zerolist(nv);}
722      else{SOL[1] = list(zerolist(nv),list(vdG));}
723      execute("def "+outL + "=SOL;");
724      execute("export "+outL+";");
725      if (nodisp==0) { print(SOL); }
726      option(set,ovec);
727      kill SOL;
728      return("result exported to "+outR+" as list "+outL);
729    }
730  }
731
732// look for reduced standard basis in lex
733  if (sb*lp==0)
734  {
735    if (sb==0)
736    {
737      def dphilb=changeordTo(rin,"dp"); setring dphilb;
738      ideal G = imap(rin,G);
739      G = std(G);
740      if (dim(G)!=0){ERROR("ideal not zero-dimensional");}
741    }
742    else
743    {
744      def dphilb = basering;
745      G=interred(G);
746      attrib(G,"isSB",1);
747    }
748    def lexhilb=changeordTo(rin,"lp"); setring lexhilb;
749    option(redTail);
750    ideal H = fglm(dphilb,G);
751    kill dphilb;
752    H = simplify(H,2);
753    if (lp){setring rin;}
754    else
755    {
756      def lplex=changeordTo(rin,"lp"); setring lplex;
757    }
758    ideal H = imap(lexhilb,H);
759    kill lexhilb;
760  }
761  else{ideal H = interred(G);}
762
763// only 1 variable
764  def hr = basering;
765  if (nv==1)
766  {
767    if ((mu==0) and (charstr(basering)[1]=="0"))
768    { // special case
769      list L = laguerre_solve(H[1],prec,prec,mu,0); // list of strings
770      if (oldr!=1)
771      {
772        ring rinC = create_ring("(complex,"+string(outprec)+")", "("+varstr(basering)+")", "lp");
773        list SOL;
774        for (ii=1; ii<=size(L); ii++ ) { execute("SOL[ii]=number("+L[ii]+");"); }
775        export SOL;
776        if (nodisp==0) { print(SOL); }
777        option(set,ovec);
778        dbprint( printlevel-voice+3,"
779// 'solve' created a ring, in which a list SOL of numbers (the complex solutions)
780// is stored.
781// To access the list of complex solutions, type (if the name R was assigned
782// to the return value):
783        setring R; SOL; ");
784        return(rinC);
785      }
786      else
787      {
788        setring (Top::`outR`);
789        list SOL;
790        for (ii=1; ii<=size(L); ii++ ) { execute("SOL[ii]="+L[ii]+";"); }
791        execute("def "+outL + "=SOL;");
792        execute("export "+outL+";");
793        if (nodisp==0) { print(SOL); }
794        option(set,ovec);
795        kill SOL;
796        return("result exported to "+outR+" as list "+outL);
797      }
798    }
799    else
800    {
801      ring internC = create_ring("(complex,"+string(prec)+")", "("+varstr(basering)+")", "lp");
802      ideal H = imap(hr,H);
803      list sp = splittolist(splitsqrfree(H[1],var(1)));
804      jj = size(sp);
805      while(jj>0)
806      {
807        sp[jj][1] = laguerre(sp[jj][1],prec,1);
808        jj--;
809      }
810      setring hr;
811      if (oldr!=1)
812      {
813        ring rinC = create_ring("(complex,"+string(outprec)+")", "("+varstr(basering)+")", "lp");
814        list SOL;
815        list sp=imap(internC,sp);
816        if(mu!=0){ SOL=sp; }
817        else
818        {
819          jj = size(sp);
820          SOL=sp[jj][1];
821          while(jj>1)
822          {
823            jj--;
824            SOL = sp[jj][1]+SOL;
825          }
826        }
827        export SOL;
828        if (nodisp==0) { print(SOL); }
829        option(set,ovec);
830        dbprint( printlevel-voice+3,"
831// 'solve' created a ring, in which a list SOL of numbers (the complex solutions)
832// is stored.
833// To access the list of complex solutions, type (if the name R was assigned
834// to the return value):
835        setring R; SOL; ");
836        return(rinC);
837      }
838      else
839      {
840        setring (Top::`outR`);
841        list SOL;
842        list sp=imap(internC,sp);
843        if(mu!=0){ SOL=sp; }
844        else
845        {
846          jj = size(sp);
847          SOL=sp[jj][1];
848          while(jj>1)
849          {
850            jj--;
851            SOL = sp[jj][1]+SOL;
852          }
853        }
854        kill sp;
855        execute("def "+outL + "=SOL;");
856        execute("export "+outL+";");
857        if (nodisp==0) { print(SOL); }
858        option(set,ovec);
859        kill SOL;
860        return("result exported to "+outR+" as list "+outL);
861      }
862    }
863  }
864
865// the triangular sets (not univariate case)
866  attrib(H,"isSB",1);
867  if (mu==0)
868  {
869    list sp = triangMH(H); // faster, but destroy multiplicity
870  }
871  else
872  {
873    list sp = triangM(H);
874  }
875
876//   create the complex ring and map the result
877  if (outprec<prec)
878  {
879    ring internC = create_ring("(complex,"+string(prec)+")", "("+varstr(hr)+")", "lp");
880  }
881  else
882  {
883    ring rinC = create_ring("(complex,"+string(outprec)+")", "("+varstr(basering)+")", "lp");
884  }
885  list triC = imap(hr,sp);
886
887// solve the tridiagonal systems
888  int js = size(triC);
889  list ret1;
890  if (mu==0)
891  {
892    ret1 = trisolve(list(),triC[1],prec);
893    while (js>1)
894    {
895      ret1 = trisolve(list(),triC[js],prec)+ret1;
896      js--;
897    }
898  }
899  else
900  {
901    ret1 = mutrisolve(list(),triC[1],prec);
902    while (js>1)
903    {
904      ret1 = addlist(mutrisolve(list(),triC[js],prec),ret1,1);
905      js--;
906    }
907    ret1 = finalclear(ret1);
908  }
909
910// final computations
911  option(set,ovec);
912  if (outprec==prec)
913  { // we are in ring rinC
914    if (oldr!=1)
915    {
916      list SOL=ret1;
917      export SOL;
918      if (nodisp==0) { print(SOL); }
919      dbprint( printlevel-voice+3,"
920// 'solve' created a ring, in which a list SOL of numbers (the complex solutions)
921// is stored.
922// To access the list of complex solutions, type (if the name R was assigned
923// to the return value):
924        setring R; SOL; ");
925      return(rinC);
926    }
927    else
928    {
929      setring (Top::`outR`);
930      list SOL=imap(rinC,ret1);
931      execute("def "+outL + "=SOL;");
932      execute("export "+outL+";");
933      if (nodisp==0) { print(SOL); }
934      kill SOL;
935      return("result exported to "+outR+" as list "+outL);
936    }
937  }
938  else
939  {
940    if (oldr!=1)
941    {
942      ring rinC = create_ring("(complex,"+string(outprec)+")", "("+varstr(basering)+")", "lp");
943      list SOL=imap(internC,ret1);
944      export SOL;
945      if (nodisp==0) { print(SOL); }
946      dbprint( printlevel-voice+3,"
947// 'solve' created a ring, in which a list SOL of numbers (the complex solutions)
948// is stored.
949// To access the list of complex solutions, type (if the name R was assigned
950// to the return value):
951        setring R; SOL; ");
952      return(rinC);
953    }
954    else
955    {
956      setring (Top::`outR`);
957      list SOL=imap(internC,ret1);
958      execute("def "+outL + "=SOL;");
959      execute("export "+outL+";");
960      if (nodisp==0) { print(SOL); }
961      kill SOL;
962      return("result exported to "+outR+" as list "+outL);
963    }
964  }
965}
966example
967{
968    "EXAMPLE:";echo=2;
969    // Find all roots of a multivariate ideal using triangular sets:
970    int d,t,s = 4,3,2 ;
971    int i;
972    ring A=0,x(1..d),dp;
973    poly p=-1;
974    for (i=d; i>0; i--) { p=p+x(i)^s; }
975    ideal I = x(d)^t-x(d)^s+p;
976    for (i=d-1; i>0; i--) { I=x(i)^t-x(i)^s+p,I; }
977    I;
978    // the multiplicity is
979    vdim(std(I));
980    def AC=solve(I,6,0,"nodisplay");  // solutions should not be displayed
981    // list of solutions is stored in AC as the list SOL (default name)
982    setring AC;
983    size(SOL);               // number of different solutions
984    SOL[5];                  // the 5th solution
985    // you must start with char. 0
986    setring A;
987    def AC1=solve(I,6,1,"nodisplay");
988    setring AC1;
989    size(SOL);               // number of different multiplicities
990    SOL[1][1][1];            // a solution with
991    SOL[1][2];               // multiplicity 1
992    SOL[2][1][1];            // a solution with
993    SOL[2][2];               // multiplicity 12
994    // the number of different solutions is equal to
995    size(SOL[1][1])+size(SOL[2][1]);
996    // the number of complex solutions (counted with multiplicities) is
997    size(SOL[1][1])*SOL[1][2]+size(SOL[2][1])*SOL[2][2];
998}
999//////////////////////////////////////////////////////////////////////////////
1000//                subprocedures for solve
1001
1002
1003/*
1004* return one zero-solution
1005*/
1006static proc zerolist(int nv)
1007{
1008  list ret;
1009  int i;
1010  number o=0;
1011
1012  for (i=nv;i>0;i--){ret[i] = o;}
1013  return(ret);
1014}
1015
1016/* ----------------------- check solution ----------------------- */
1017static proc multsol(list ff, int c)
1018{
1019  int i,j;
1020
1021  i = 0;
1022  j = size(ff);
1023  while (j>0)
1024  {
1025    if(c){i = i+ff[j][2]*size(ff[j][1]);}
1026    else{i = i+size(ff[j][1]);}
1027    j--;
1028  }
1029  return(i);
1030}
1031
1032/*
1033* the inputideal A => zero ?
1034*/
1035static proc checksol(ideal A, list lr)
1036{
1037  int d = nvars(basering);
1038  list ro;
1039  ideal re,h;
1040  int i,j,k;
1041
1042  for (i=size(lr);i>0;i--)
1043  {
1044    ro = lr[i];
1045    for (j=d;j>0;j--)
1046    {
1047      re[j] = var(j)-ro[j];
1048    }
1049    attrib(re,"isSB",1);
1050    k = size(reduce(A,re,5));
1051    if (k){return(i);}
1052  }
1053  return(0);
1054}
1055
1056/*
1057*  compare 2 solutions: returns 0 for equal
1058*/
1059static proc cmpn(list a,list b)
1060{
1061  int ii;
1062
1063  for(ii=size(a);ii>0;ii--){if(a[ii]!=b[ii]) break;}
1064  return(ii);
1065}
1066
1067/*
1068*  delete equal solutions in the list
1069*/
1070static proc delequal(list r, int w)
1071{
1072  list h;
1073  int i,j,k,c;
1074
1075  if (w)
1076  {
1077    k = size(r);
1078    h = r[k][1];
1079    k--;
1080    while (k>0)
1081    {
1082      h = r[k][1]+h;
1083      k--;
1084    }
1085  }
1086  else{h = r;}
1087  k=size(h);
1088  i=1;
1089  while(i<k)
1090  {
1091    j=k;
1092    while(j>i)
1093    {
1094      c=cmpn(h[i],h[j]);
1095      if(c==0)
1096      {
1097        h=delete(h,j);
1098        k--;
1099      }
1100      j--;
1101    }
1102    i++;
1103  }
1104  return(h);
1105}
1106
1107/* ----------------------- substitution ----------------------- */
1108/*
1109* instead of subst(T,var(v),n), much faster
1110*   need option(redSB) !
1111*/
1112static proc linreduce(ideal T, int v, number n)
1113{
1114  ideal re = var(v)-n;
1115  attrib (re,"isSB",1);
1116  return (reduce(T,re));
1117}
1118
1119/* ----------------------- triangular solution ----------------------- */
1120/*
1121* solution of one tridiagonal system T
1122*   with precision prec
1123*   T[1] is univariant in var(1)
1124*   list o is empty for the first call
1125*/
1126static proc trisolve(list o, ideal T, int prec)
1127{
1128  list lroots,ll;
1129  ideal S;
1130  int i,d;
1131
1132  d = size(T);
1133  S = interred(ideal(T[1],diff(T[1],var(d))));
1134  if (deg(S[1]))
1135  {
1136    T[1] = exdiv(T[1],S[1],var(d));
1137  }
1138  ll = laguerre(T[1],prec,1);
1139  for (i=size(ll);i>0;i--){ll[i] = list(ll[i])+o;}
1140  if (d==1){return(ll);}
1141  for (i=size(ll);i>0;i--)
1142  {
1143    S = linreduce(ideal(T[2..d]),d,ll[i][1]);
1144    lroots = trisolve(ll[i],S,prec)+lroots;
1145  }
1146  return(lroots);
1147}
1148
1149/* ------------------- triangular solution (mult) ------------------- */
1150/*
1151*  recompute equal solutions w.r.t. multiplicity
1152*/
1153static proc finalclear(list b)
1154{
1155  list a = b;
1156  list r;
1157  int i,l,ju,j,k,ku,mu,c;
1158
1159// a[i] only
1160  i = 1;
1161  while (i<=size(a))
1162  {
1163    ju = size(a[i][1]);
1164    j = 1;
1165    while (j<=ju)
1166    {
1167      mu = 1;
1168      k = j+1;
1169      while (k<=ju)
1170      {
1171        c = cmpn(a[i][1][j],a[i][1][k]);
1172        if (c==0)
1173        {
1174          a[i][1] = delete(a[i][1],k);
1175          ju--;
1176          mu++;
1177        }
1178        else{k++;}
1179      }
1180      if (mu>1)
1181      {
1182        r[1] = a[i];
1183        r[1][1] = list(a[i][1][j]);
1184        a[i][1] = delete(a[i][1],j);
1185        a = addlist(r,a,mu);
1186        ju--;
1187      }
1188      else{j++;}
1189    }
1190    if (ju==0){a = delete(a,i);}
1191    else{i++;}
1192  }
1193// a[i], a[l]
1194  i = 1;
1195  while (i<size(a))
1196  {
1197    ju = size(a[i][1]);
1198    l = i+1;
1199    while (l<=size(a))
1200    {
1201      ku = size(a[l][1]);
1202      j = 1;
1203      while (j<=ju)
1204      {
1205        mu = 0;
1206        k = 1;
1207        while (k<=ku)
1208        {
1209          c = cmpn(a[i][1][j],a[l][1][k]);
1210          if (c==0)
1211          {
1212            mu = a[i][2]+a[l][2];
1213            r[1] = a[l];
1214            r[1][1] = list(a[l][1][k]);
1215            r[1][2] = mu;
1216            a[l][1] = delete(a[l][1],k);
1217            a = addlist(r,a,1);
1218            ku--;
1219            break;
1220          }
1221          else{k++;}
1222        }
1223        if (mu)
1224        {
1225          a[i][1] = delete(a[i][1],j);
1226          ju--;
1227        }
1228        else{j++;}
1229      }
1230      if (ku){l++;}
1231      else
1232      {
1233        a = delete(a,l);
1234      }
1235    }
1236    if (ju){i++;}
1237    else
1238    {
1239      a = delete(a,i);
1240    }
1241  }
1242  return(a);
1243}
1244
1245/*
1246* convert to list
1247*/
1248static proc splittolist(ideal sp)
1249{
1250  int j = size(sp);
1251  list spl = list(list(sp[j],j));
1252
1253  j--;
1254  while (j>0)
1255  {
1256    if (deg(sp[j]))
1257    {
1258      spl = list(list(sp[j],j))+spl;
1259    }
1260    j--;
1261  }
1262  return(spl);
1263}
1264
1265/*
1266*  multiply the multiplicity
1267*/
1268static proc multlist(list a, int m)
1269{
1270  int i;
1271  for (i=size(a);i>0;i--){a[i][2] = a[i][2]*m;}
1272  return(a);
1273}
1274
1275/*
1276*  a+b w.r.t. to multiplicity as ordering
1277*    (programming like spolys)
1278*/
1279static proc addlist(list a, list b, int m)
1280{
1281  int i,j,k,l,s;
1282  list r = list();
1283
1284  if (m>1){a = multlist(a,m);}
1285  k = size(a);
1286  l = size(b);
1287  i = 1;
1288  j = 1;
1289  while ((i<=k)&&(j<=l))
1290  {
1291    s = a[i][2]-b[j][2];
1292    if (s>=0)
1293    {
1294      r = r+list(b[j]);
1295      j++;
1296      if (s==0)
1297      {
1298        s = size(r);
1299        r[s][1] = r[s][1]+a[i][1];
1300        i++;
1301      }
1302    }
1303    else
1304    {
1305      r = r+list(a[i]);
1306      i++;
1307    }
1308  }
1309  if (i>k)
1310  {
1311    if (j<=l){r = r+list(b[j..l]);}
1312  }
1313  else{r = r+list(a[i..k]);}
1314  return(r);
1315}
1316
1317/*
1318* solution of one tridiagonal system T with multiplicity
1319*   with precision prec
1320*   T[1] is univariant in var(1)
1321*   list o is empty for the first call
1322*/
1323static proc mutrisolve(list o, ideal T, int prec)
1324{
1325  list lroots,ll,sp;
1326  ideal S,h;
1327  int i,d,m,z;
1328
1329  d = size(T);
1330  sp = splittolist(splitsqrfree(T[1],var(d)));
1331  if (d==1){return(l_mutrisolve(sp,o,prec));}
1332  z = size(sp);
1333  while (z>0)
1334  {
1335    m = sp[z][2];
1336    ll = laguerre(sp[z][1],prec,1);
1337    i = size(ll);
1338    while(i>0)
1339    {
1340      h = linreduce(ideal(T[2..d]),d,ll[i]);
1341      if (size(lroots))
1342      {
1343        lroots = addlist(mutrisolve(list(ll[i])+o,h,prec),lroots,m);
1344      }
1345      else
1346      {
1347        lroots = mutrisolve(list(ll[i])+o,h,prec);
1348        if (m>1){lroots=multlist(lroots,m);}
1349      }
1350      i--;
1351    }
1352    z--;
1353  }
1354  return(lroots);
1355}
1356
1357/*
1358*  the last call, we are ready
1359*/
1360static proc l_mutrisolve(list sp, list o, int prec)
1361{
1362  list lroots,ll;
1363  int z,m,i;
1364
1365  z = size(sp);
1366  while (z>0)
1367  {
1368    m = sp[z][2];
1369    ll = laguerre(sp[z][1],prec,1);
1370    for (i=size(ll);i>0;i--){ll[i] = list(ll[i])+o;}
1371    if (size(lroots))
1372    {
1373      lroots = addlist(list(list(ll,m)),lroots,1);
1374    }
1375    else
1376    {
1377      lroots = list(list(ll,m));
1378    }
1379    z--;
1380  }
1381  return(lroots);
1382}
1383///////////////////////////////////////////////////////////////////////////////
1384
1385proc ures_solve( ideal gls, list # )
1386"USAGE:   ures_solve(i [, k, p] ); i = ideal, k, p = integers
1387   k=0: use sparse resultant matrix of Gelfand, Kapranov and Zelevinsky, @*
1388   k=1: use resultant matrix of Macaulay which works only for
1389          homogeneous ideals,@*
1390   p>0: defines precision of the long floats for internal computation
1391          if the basering is not complex (in decimal digits),
1392   (default: k=0, p=30)
1393ASSUME:  i is a zerodimensional ideal given by a quadratic system, that is,@*
1394         nvars(basering) = ncols(i) = number of vars actually occurring in i,
1395RETURN:  If the ground field is the field of complex numbers: list of numbers
1396         (the complex roots of the polynomial system i=0). @*
1397         Otherwise: ring @code{R} with the same number of variables but with
1398         complex coefficients (and precision p). @code{R} comes with a list
1399         @code{SOL} of numbers, in which complex roots of the polynomial
1400         system i are stored: @*
1401EXAMPLE: example ures_solve; shows an example
1402"
1403{
1404  int typ=0;// defaults
1405  int prec=30;
1406
1407  if ( size(#) > 0 )
1408  {
1409    typ= #[1];
1410    if ( typ < 0 || typ > 1 )
1411    {
1412      ERROR("Valid values for second parameter k are:
1413                   0: use sparse Resultant (default)
1414                   1: use Macaulay Resultant");
1415    }
1416  }
1417  if ( size(#) > 1 )
1418  {
1419    prec= #[2];
1420    if ( prec < 8 )
1421    {
1422      prec = 8;
1423    }
1424  }
1425
1426  list LL=uressolve(gls,typ,prec,1);
1427  int sizeLL=size(LL);
1428  if (sizeLL==0)
1429  {
1430    dbprint(printlevel-voice+3,"No solution found!");
1431    return(list());
1432  }
1433  if (typeof(LL[1][1])=="string")
1434  {
1435    int ii,jj;
1436    int nv=size(LL[1]);
1437    ring rinC = create_ring("(complex,"+string(prec)+",I)", "("+varstr(basering)+")", "lp");
1438    list SOL,SOLnew;
1439    for (ii=1; ii<=sizeLL; ii++)
1440    {
1441      SOLnew=list();
1442      for (jj=1; jj<=nv; jj++)
1443      {
1444        execute("SOLnew["+string(jj)+"]="+LL[ii][jj]+";");
1445      }
1446      SOL[ii]=SOLnew;
1447    }
1448    kill SOLnew;
1449    export SOL;
1450    dbprint( printlevel-voice+3,"
1451// 'ures_solve' created a ring, in which a list SOL of numbers (the complex
1452// solutions) is stored.
1453// To access the list of complex solutions, type (if the name R was assigned
1454// to the return value):
1455        setring R; SOL; ");
1456    return(rinC);
1457  }
1458  else
1459  {
1460    return(LL);
1461  }
1462}
1463example
1464{
1465    "EXAMPLE:";echo=2;
1466    // compute the intersection points of two curves
1467    ring rsq = 0,(x,y),lp;
1468    ideal gls=  x2 + y2 - 10, x2 + xy + 2y2 - 16;
1469    def R=ures_solve(gls,0,16);
1470    setring R; SOL;
1471}
1472///////////////////////////////////////////////////////////////////////////////
1473
1474proc mp_res_mat( ideal i, list # )
1475"USAGE:   mp_res_mat(i [, k] ); i ideal, k integer,
1476    k=0: sparse resultant matrix of Gelfand, Kapranov and Zelevinsky,@*
1477    k=1: resultant matrix of Macaulay (k=0 is default)
1478ASSUME:  The number of elements in the input system must be the number of
1479         variables in the basering plus one;
1480         if k=1 then i must be homogeneous.
1481RETURN:  module representing the multipolynomial resultant matrix
1482EXAMPLE: example mp_res_mat; shows an example
1483"
1484{
1485  int typ=0;
1486
1487  if ( size(#) > 0 )
1488  {
1489    typ= #[1];
1490    if ( typ < 0 || typ > 1 )
1491    {
1492      ERROR("Valid values for third parameter are:
1493                   0: sparse resultant (default)
1494                   1: Macaulay resultant");
1495    }
1496  }
1497  return(mpresmat(i,typ));
1498}
1499example
1500{
1501    "EXAMPLE:";echo=2;
1502    // compute resultant matrix in ring with parameters (sparse resultant matrix)
1503    ring rsq= (0,u0,u1,u2),(x1,x2),lp;
1504    ideal i= u0+u1*x1+u2*x2,x1^2 + x2^2 - 10,x1^2 + x1*x2 + 2*x2^2 - 16;
1505    module m = mp_res_mat(i);
1506    print(m);
1507    // computing sparse resultant
1508    det(m);
1509
1510    // compute resultant matrix (Macaulay resultant matrix)
1511    ring rdq= (0,u0,u1,u2),(x0,x1,x2),lp;
1512    ideal h=  homog(imap(rsq,i),x0);
1513    h;
1514
1515    module m = mp_res_mat(h,1);
1516    print(m);
1517    // computing Macaulay resultant (should be the same as above!)
1518    det(m);
1519
1520    // compute numerical sparse resultant matrix
1521    setring rsq;
1522    ideal ir= 15+2*x1+5*x2,x1^2 + x2^2 - 10,x1^2 + x1*x2 + 2*x2^2 - 16;
1523    module mn = mp_res_mat(ir);
1524    print(mn);
1525    // computing sparse resultant
1526    det(mn);
1527}
1528///////////////////////////////////////////////////////////////////////////////
1529
1530proc interpolate( ideal p, ideal w, int d )
1531"USAGE:   interpolate(p,v,d); p,v=ideals of numbers, d=integer
1532ASSUME:  Ground field K is the field of rational numbers, p and v are lists
1533         of elements of the ground field K with p[j] != -1,0,1, size(p) = n
1534         (= number of vars) and size(v)=N=(d+1)^n.
1535RETURN:  poly f, the unique polynomial f of degree n*d with prescribed values
1536         v[i] at the points p(i)=(p[1]^(i-1),..,p[n]^(i-1)), i=1,..,N.
1537NOTE:    mainly useful when n=1, i.e. f is satisfying f(p^(i-1)) = v[i],
1538         i=1..d+1.
1539SEE ALSO: vandermonde.
1540EXAMPLE: example interpolate; shows an example
1541"
1542{
1543    return(vandermonde(p,w,d));
1544}
1545example
1546{
1547    "EXAMPLE:";  echo=2;
1548    ring r1 = 0,(x),lp;
1549    // determine f with deg(f) = 4 and
1550    // v = values of f at points 3^0, 3^1, 3^2, 3^3, 3^4
1551    ideal v=16,0,11376,1046880,85949136;
1552    interpolate( 3, v, 4 );
1553}
1554
1555///////////////////////////////////////////////////////////////////////////////
1556// changed for Singular 3
1557// Return value is now a list: (rlist, rn@)
1558static proc psubst( int d, int dd, int n, list resl,
1559                    ideal fi, int elem, int nv, int prec, int rn@, list rlist)
1560{
1561    //   nv: number of ring variables         (fixed value)
1562    // elem: number of elements in ideal fi   (fixed value)
1563    //   fi: input ideal                      (fixed value)
1564    //   rl: output list of roots
1565    // resl: actual list of roots
1566    //    n:
1567    //   dd: actual element of fi
1568    //    d: actual variable
1569
1570    list LL;
1571    int pdebug;
1572    int olddd=dd;
1573
1574    dbprint(printlevel-voice+2, "// 0 step "+string(dd)+" of "+string(elem) );
1575
1576    if ( dd <= elem )
1577    {
1578        int loop = 1;
1579        int k;
1580        list lsr,lh;
1581        poly ps;
1582        int thedd;
1583
1584        dbprint( printlevel-voice+1,"// 1 dd = "+string(dd) );
1585
1586        thedd=0;
1587        while ( (dd+1 <= elem) && loop )
1588        {
1589            ps= fi[dd+1];
1590
1591            if ( n-1 > 0 )
1592            {
1593                dbprint( printlevel-voice,
1594                    "// 2 ps=fi["+string(dd+1)+"]"+" size="
1595                        +string(size(coeffs(ps,var(n-1))))
1596                        +"  leadexp(ps)="+string(leadexp(ps)) );
1597
1598                if ( size(coeffs(ps,var(n-1))) == 1 )
1599                {
1600                    dd++;
1601                    // hier Leading-Exponent pruefen???
1602                    // oder ist das Polynom immer als letztes in der Liste?!?
1603                    // leadexp(ps)
1604                }
1605                else
1606                {
1607                    loop=0;
1608                }
1609            }
1610            else
1611            {
1612                dbprint( printlevel-voice,
1613                    "// 2 ps=fi["+string(dd+1)+"]"+"  leadexp(ps)="
1614                        +string(leadexp(ps)) );
1615                dd++;
1616            }
1617        }
1618        thedd=dd;
1619        ps= fi[thedd];
1620
1621        dbprint( printlevel-voice+1,
1622            "// 3    fi["+string(thedd-1)+"]"+"  leadexp(fi[thedd-1])="
1623                +string(leadexp(fi[thedd-1])) );
1624        dbprint( printlevel-voice+1,
1625            "// 3 ps=fi["+string(thedd)+"]"+"  leadexp(ps)="
1626                +string(leadexp(ps)) );
1627
1628        for ( k= nv; k > nv-d; k-- )
1629        {
1630            dbprint( printlevel-voice,
1631                "// 4 subst(fi["+string(thedd)+"],"
1632                    +string(var(k))+","+string(resl[k])+");" );
1633            ps = subst(ps,var(k),resl[k]);
1634        }
1635
1636        dbprint( printlevel-voice, "// 5 substituted ps="+string(ps) );
1637
1638        if ( ps != 0 )
1639        {
1640            lsr= laguerre_solve( ps, prec, prec, 0 );
1641        }
1642        else
1643        {
1644            dbprint( printlevel-voice+1,"// 30 ps == 0, thats not cool...");
1645            lsr=list(number(0));
1646        }
1647
1648        dbprint( printlevel-voice+1,
1649         "// 6 laguerre_solve found roots: lsr["+string(size(lsr))+"]" );
1650
1651        if ( size(lsr) > 1 )
1652        {
1653            dbprint( printlevel-voice+1,
1654                "// 10 checking roots found before, range "
1655                    +string(dd-olddd)+" -- "+string(dd) );
1656            dbprint( printlevel-voice+1,
1657                "// 10 thedd = "+string(thedd) );
1658
1659            int i,j,l;
1660            int ls=size(lsr);
1661            int lss;
1662            poly pss;
1663            list nares;
1664            int rroot;
1665            int nares_size;
1666
1667
1668            for ( i = 1; i <= ls; i++ ) // lsr[1..ls]
1669            {
1670                rroot=1;
1671
1672                if ( pdebug>=2 )
1673                {"// 13 root lsr["+string(i)+"] = "+string(lsr[i]);}
1674                for ( l = 0; l <= dd-olddd; l++ )
1675                {
1676                    if ( l+olddd != thedd )
1677                    {
1678                        if ( pdebug>=2 )
1679                        {"// 11 checking ideal element "+string(l+olddd);}
1680                        ps=fi[l+olddd];
1681                        if ( pdebug>=3 )
1682                        {"// 14 ps=fi["+string(l+olddd)+"]";}
1683                        for ( k= nv; k > nv-d; k-- )
1684                        {
1685                            if ( pdebug>=3 )
1686                            {
1687                                "// 11 subst(fi["+string(olddd+l)+"],"
1688                                    +string(var(k))+","+string(resl[k])+");";
1689                            }
1690                            ps = subst(ps,var(k),resl[k]);
1691
1692                        }
1693
1694                        pss=subst(ps,var(k),lsr[i]); // k=nv-d
1695                        if ( pdebug>=3 )
1696                        { "// 15 0 == "+string(pss); }
1697                        if ( pss != 0 )
1698                        {
1699                            if ( system("complexNearZero",
1700                                        leadcoef(pss),
1701                                        prec) )
1702                            {
1703                                if ( pdebug>=2 )
1704                                { "// 16 root "+string(i)+" is a real root"; }
1705                            }
1706                            else
1707                            {
1708                                if ( pdebug>=2 )
1709                                { "// 17 0 == "+string(pss); }
1710                                rroot=0;
1711                            }
1712                        }
1713
1714                    }
1715                }
1716
1717                if ( rroot == 1 ) // add root to list ?
1718                {
1719                    if ( size(nares) > 0 )
1720                    {
1721                        nares=nares[1..size(nares)],lsr[i];
1722                    }
1723                    else
1724                    {
1725                        nares=lsr[i];
1726                    }
1727                    if ( pdebug>=2 )
1728                    { "// 18 added root to list nares"; }
1729                }
1730            }
1731
1732            nares_size=size(nares);
1733            if ( nares_size == 0 )
1734            {
1735                "Numerical problem: No root found...";
1736                "Output may be incorrect!";
1737                nares=list(number(0));
1738            }
1739
1740            if ( pdebug>=1 )
1741            { "// 20 found <"+string(size(nares))+"> roots"; }
1742
1743            for ( i= 1; i <= nares_size; i++ )
1744            {
1745                resl[nv-d]= nares[i];
1746
1747                if ( dd < elem )
1748                {
1749                    if ( i > 1 )
1750                    {
1751                        rn@++;
1752                    }
1753                    LL = psubst( d+1, dd+1, n-1, resl, fi, elem, nv, prec,
1754                                 rn@, rlist );
1755                    rlist = LL[1];
1756                    rn@ = LL[2];
1757                }
1758                else
1759                {
1760                   if ( i > 1 ) {  rn@++; }  //bug found by O.Labs
1761                   if ( pdebug>=1 )
1762                   {"// 30_1 <"+string(rn@)+"> "+string(size(resl))+" <-----";}
1763                   if ( pdebug>=2 ){ resl; }
1764                   rlist[rn@]=resl;
1765                }
1766            }
1767        }
1768        else
1769        {
1770            if ( pdebug>=2 )
1771            { "// 21 found root to be: "+string(lsr[1]); }
1772            resl[nv-d]= lsr[1];
1773
1774            if ( dd < elem )
1775            {
1776                LL= psubst( d+1, dd+1, n-1, resl, fi, elem, nv, prec,
1777                            rn@, rlist );
1778                rlist = LL[1];
1779                rn@ = LL[2];
1780            }
1781            else
1782            {
1783                if ( pdebug>=1 )
1784                { "// 30_2 <"+string(rn@)+"> "+string(size(resl))+" <-----";}
1785                if ( pdebug>=2 )
1786                { resl; }
1787                rlist[rn@]=resl;
1788            }
1789        }
1790    }
1791    return(list(rlist,rn@));
1792}
1793
1794///////////////////////////////////////////////////////////////////////////////
1795
1796proc fglm_solve( ideal fi, list # )
1797"USAGE:   fglm_solve(i [, p] ); i ideal, p integer
1798ASSUME:  the ground field has char 0.
1799RETURN:  ring @code{R} with the same number of variables but with complex
1800         coefficients (and precision p). @code{R} comes with a list
1801         @code{rlist} of numbers, in which the complex roots of i are stored.@*
1802         p>0: gives precision of complex numbers in decimal digits [default:
1803         p=30].
1804NOTE:    The procedure uses a standard basis of i to determine all complex
1805         roots of i.
1806EXAMPLE: example fglm_solve; shows an example
1807"
1808{
1809    int prec=30;
1810
1811    if ( size(#)>=1  && typeof(#[1])=="int")
1812    {
1813        prec=#[1];
1814    }
1815
1816    def R = lex_solve(stdfglm(fi),prec);
1817    dbprint( printlevel-voice+3,"
1818// 'fglm_solve' created a ring, in which a list rlist of numbers (the
1819// complex solutions) is stored.
1820// To access the list of complex solutions, type (if the name R was assigned
1821// to the return value):
1822        setring R; rlist; ");
1823    return(R);
1824}
1825example
1826{
1827    "EXAMPLE:";echo=2;
1828    ring r = 0,(x,y),lp;
1829    // compute the intersection points of two curves
1830    ideal s =  x2 + y2 - 10, x2 + xy + 2y2 - 16;
1831    def R = fglm_solve(s,10);
1832    setring R; rlist;
1833}
1834
1835///////////////////////////////////////////////////////////////////////////////
1836
1837proc lex_solve( ideal fi, list # )
1838"USAGE:   lex_solve( i[,p] ); i=ideal, p=integer,
1839  p>0: gives precision of complex numbers in decimal digits (default: p=30).
1840ASSUME:  i is a reduced lexicographical Groebner bases of a zero-dimensional
1841         ideal, sorted by increasing leading terms.
1842RETURN:  ring @code{R} with the same number of variables but with complex
1843         coefficients (and precision p). @code{R} comes with a list
1844         @code{rlist} of numbers, in which the complex roots of i are stored.
1845EXAMPLE: example lex_solve; shows an example
1846"
1847{
1848    int prec=30;
1849    list LL;
1850
1851    if ( size(#)>=1  && typeof(#[1])=="int")
1852    {
1853        prec=#[1];
1854    }
1855
1856    if ( !defined(pdebug) ) { int pdebug; }
1857    def oring= basering;
1858
1859    // change the ground field to complex numbers
1860    string nrings= "ring RC =(complex,"+string(prec)
1861        +"),("+varstr(basering)+"),lp;";
1862    execute(nrings);
1863
1864    // map fi from old to new ring
1865    ideal fi= imap(oring,fi);
1866
1867    int idelem= size(fi);
1868    int nv= nvars(basering);
1869    int i,j,k,lis;
1870    list resl,li;
1871
1872    if ( !defined(rlist) )
1873    {
1874        list rlist;
1875        export rlist;
1876    }
1877
1878    li= laguerre_solve(fi[1],prec,prec,0);
1879    lis= size(li);
1880
1881    dbprint(printlevel-voice+2,"// laguerre found roots: "+string(size(li)));
1882    int rn@;
1883
1884    for ( j= 1; j <= lis; j++ )
1885    {
1886        dbprint(printlevel-voice+1,"// root "+string(j) );
1887        rn@++;
1888        resl[nv]= li[j];
1889        LL = psubst( 1, 2, nv-1, resl, fi, idelem, nv, prec, rn@, rlist );
1890        rlist=LL[1];
1891        rn@=LL[2];
1892    }
1893
1894    dbprint( printlevel-voice+3,"
1895// 'lex_solve' created a ring, in which a list rlist of numbers (the
1896// complex solutions) is stored.
1897// To access the list of complex solutions, type (if the name R was assigned
1898// to the return value):
1899        setring R; rlist; ");
1900
1901    return(RC);
1902}
1903example
1904{
1905    "EXAMPLE:";echo=2;
1906    ring r = 0,(x,y),lp;
1907    // compute the intersection points of two curves
1908    ideal s =  x2 + y2 - 10, x2 + xy + 2y2 - 16;
1909    def R = lex_solve(stdfglm(s),10);
1910    setring R; rlist;
1911}
1912
1913///////////////////////////////////////////////////////////////////////////////
1914
1915proc triangLf_solve( ideal fi, list # )
1916"USAGE:   triangLf_solve(i [, p] ); i ideal, p integer,
1917         p>0: gives precision of complex numbers in digits (default: p=30).
1918ASSUME:  the ground field has char 0;  i is a zero-dimensional ideal
1919RETURN:  ring @code{R} with the same number of variables but with complex
1920         coefficients (and precision p). @code{R} comes with a list
1921         @code{rlist} of numbers, in which the complex roots of i are stored.
1922NOTE:    The procedure uses a triangular system (Lazard's Algorithm with
1923         factorization) computed from a standard basis to determine
1924         recursively all complex roots of the input ideal i with Laguerre's
1925         algorithm.
1926EXAMPLE: example triangLf_solve; shows an example
1927"
1928{
1929    int prec=30;
1930
1931    if ( size(#)>=1  && typeof(#[1])=="int")
1932    {
1933        prec=#[1];
1934    }
1935
1936    def R=triang_solve(triangLfak(stdfglm(fi)),prec);
1937    dbprint( printlevel-voice+3,"
1938// 'triangLf_solve' created a ring, in which a list rlist of numbers (the
1939// complex solutions) is stored.
1940// To access the list of complex solutions, type (if the name R was assigned
1941// to the return value):
1942        setring R; rlist; ");
1943    return(R);
1944}
1945example
1946{
1947    "EXAMPLE:";echo=2;
1948    ring r = 0,(x,y),lp;
1949    // compute the intersection points of two curves
1950    ideal s = x2 + y2 - 10, x2 + xy + 2y2 - 16;
1951    def R = triangLf_solve(s,10);
1952    setring R; rlist;
1953}
1954
1955///////////////////////////////////////////////////////////////////////////////
1956
1957proc triangM_solve( ideal fi, list # )
1958"USAGE:   triangM_solve(i [, p ] ); i=ideal, p=integer,
1959         p>0: gives precision of complex numbers in digits (default: p=30).
1960ASSUME:  the ground field has char 0;@*
1961         i zero-dimensional ideal
1962RETURN:  ring @code{R} with the same number of variables but with complex
1963         coefficients (and precision p). @code{R} comes with a list
1964         @code{rlist} of numbers, in which the complex roots of i are stored.
1965NOTE:    The procedure uses a triangular system (Moellers Algorithm) computed
1966         from a standard basis  of input ideal i to determine recursively all
1967         complex roots with Laguerre's algorithm.
1968EXAMPLE: example triangM_solve; shows an example
1969"
1970{
1971    int prec=30;
1972
1973    if ( size(#)>=1  && typeof(#[1])=="int")
1974    {
1975        prec=#[1];
1976    }
1977
1978    def R = triang_solve(triangM(stdfglm(fi)),prec);
1979    dbprint( printlevel-voice+3,"
1980// 'triangM_solve' created a ring, in which a list rlist of numbers (the
1981// complex solutions) is stored.
1982// To access the list of complex solutions, type (if the name R was assigned
1983// to the return value):
1984        setring R; rlist; ");
1985    return(R);
1986}
1987example
1988{
1989    "EXAMPLE:";echo=2;
1990    ring r = 0,(x,y),lp;
1991    // compute the intersection points of two curves
1992    ideal s =  x2 + y2 - 10, x2 + xy + 2y2 - 16;
1993    def R = triangM_solve(s,10);
1994    setring R; rlist;
1995}
1996
1997///////////////////////////////////////////////////////////////////////////////
1998
1999proc triangL_solve( ideal fi, list # )
2000"USAGE:   triangL_solve(i [, p] ); i=ideal, p=integer,@*
2001         p>0: gives precision of complex numbers in digits (default: p=30).
2002ASSUME:  the ground field has char 0; i is a zero-dimensional ideal.
2003RETURN:  ring @code{R} with the same number of variables, but with complex
2004         coefficients (and precision p). @code{R} comes with a list
2005         @code{rlist} of numbers, in which the complex roots of i are stored.
2006NOTE:    The procedure uses a triangular system (Lazard's Algorithm) computed
2007         from a standard basis of input ideal i to determine recursively all
2008         complex roots with Laguerre's algorithm.
2009EXAMPLE: example triangL_solve; shows an example
2010"
2011{
2012    int prec=30;
2013
2014    if ( size(#)>=1  && typeof(#[1])=="int")
2015    {
2016        prec=#[1];
2017    }
2018
2019    def R=triang_solve(triangL(stdfglm(fi)),prec);
2020    dbprint( printlevel-voice+3,"
2021// 'triangL_solve' created a ring, in which a list rlist of numbers (the
2022// complex solutions) is stored.
2023// To access the list of complex solutions, type (if the name R was assigned
2024// to the return value):
2025        setring R; rlist; ");
2026    return(R);
2027}
2028example
2029{
2030    "EXAMPLE:";echo=2;
2031    ring r = 0,(x,y),lp;
2032    // compute the intersection points of two curves
2033    ideal s =  x2 + y2 - 10, x2 + xy + 2y2 - 16;
2034    def R = triangL_solve(s,10);
2035    setring R; rlist;
2036}
2037
2038
2039///////////////////////////////////////////////////////////////////////////////
2040
2041proc triang_solve( list lfi, int prec, list # )
2042"USAGE:   triang_solve(l,p [,d] ); l=list, p,d=integers@*
2043         l is a list of finitely many triangular systems, such that the union of
2044         their varieties equals the variety of the initial ideal.@*
2045         p>0: gives precision of complex numbers in digits,@*
2046         d>0: gives precision (1<d<p) for near-zero-determination,@*
2047         (default: d=1/2*p).
2048ASSUME:  the ground field has char 0;@*
2049         l was computed using the algorithm of Lazard or the algorithm of
2050         Moeller (see triang.lib).
2051RETURN:  ring @code{R} with the same number of variables, but with complex
2052         coefficients (and precision p). @code{R} comes with a list
2053         @code{rlist} of numbers, in which the complex roots of l are stored.@*
2054EXAMPLE: example triang_solve; shows an example
2055"
2056{
2057    def oring= basering;
2058    list LL;
2059
2060    // change the ground field to complex numbers
2061    string nrings= "ring RC =(complex,"+string(prec)
2062        +",I),("+varstr(basering)+"),lp;";
2063    execute(nrings);
2064
2065    // list with entry 0 (number)
2066    number nn=0;
2067
2068    // set number of digits for zero-comparison of roots
2069    if ( !defined(myCompDigits) )
2070    {
2071        int myCompDigits;
2072    }
2073    if ( size(#)>=1  && typeof(#[1])=="int" )
2074    {
2075        myCompDigits=#[1];
2076    }
2077    else
2078    {
2079        myCompDigits=(system("getPrecDigits"));
2080    }
2081
2082    dbprint( printlevel-voice+2,"// myCompDigits="+string(myCompDigits) );
2083
2084    int idelem;
2085    int nv= nvars(basering);
2086    int i,j,lis;
2087    list resu,li;
2088
2089    if ( !defined(rlist) )
2090    {
2091        list rlist;
2092        export rlist;
2093    }
2094
2095    int rn@=0;
2096
2097    // map the list
2098    list lfi= imap(oring,lfi);
2099    int slfi= size(lfi);
2100
2101    ideal fi;
2102    for ( i= 1; i <= slfi; i++ )
2103    {
2104        // map fi from old to new ring
2105        fi= lfi[i]; //imap(oring,lfi[i]);
2106
2107        idelem= size(fi);
2108
2109        // solve fi[1]
2110        li= laguerre_solve(fi[1],myCompDigits,myCompDigits,0);
2111        lis= size(li);
2112
2113        dbprint( printlevel-voice+2,"// laguerre found roots: "+string(lis) );
2114
2115        for ( j= 1; j <= lis; j++ )
2116        {
2117            dbprint( printlevel-voice+2,"// root "+string(j) );
2118            rn@++;
2119            resu[nv]= li[j];
2120            LL = psubst( 1, 2, nv-1, resu, fi, idelem, nv, myCompDigits,
2121                         rn@, rlist );
2122            rlist = LL[1];
2123            rn@ = LL[2];
2124        }
2125    }
2126
2127    dbprint( printlevel-voice+3,"
2128// 'triang_solve' created a ring, in which a list rlist of numbers (the
2129// complex solutions) is stored.
2130// To access the list of complex solutions, type (if the name R was assigned
2131// to the return value):
2132        setring R; rlist; ");
2133
2134    return(RC);
2135}
2136example
2137{
2138    "EXAMPLE:";echo=2;
2139    ring r = 0,(x,y),lp;
2140    // compute the intersection points of two curves
2141    ideal s=  x2 + y2 - 10, x2 + xy + 2y2 - 16;
2142    def R=triang_solve(triangLfak(stdfglm(s)),10);
2143    setring R; rlist;
2144}
2145
2146///////////////////////////////////////////////////////////////////////////////
2147
2148proc simplexOut(list l)
2149"USAGE:   simplexOut(l); l list
2150ASSUME:  l is the output of simplex.
2151RETURN:  Nothing. The procedure prints the computed solution of simplex
2152         (as strings) in a nice format.
2153SEE ALSO: simplex
2154EXAMPLE: example simplexOut; shows an example
2155"
2156{
2157  int i,j;
2158  matrix m= l[1];
2159  intvec iposv= l[3];
2160  int icase= l[2];
2161
2162  int cols= ncols(m);
2163  int rows= nrows(m);
2164
2165  int N= l[6];
2166
2167  if ( 1 == icase )  // objective function is unbound
2168  {
2169    "objective function is unbound";
2170    return();
2171  }
2172  if ( -1 == icase )  // no solution satisfies the given constraints
2173  {
2174    "no solution satisfies the given constraints";
2175    return();
2176  }
2177  if ( -2 == icase )  // other error
2178  {
2179    "an error occurred during simplex computation!";
2180    return();
2181  }
2182
2183  for ( i = 1; i <= rows; i++ )
2184  {
2185    if (i == 1)
2186    {
2187      "z = "+string(m[1][1]);
2188    }
2189    else
2190    {
2191      if ( iposv[i-1] <= N )
2192      {
2193        "x"+string(iposv[i-1])+" = "+string(m[i,1]);
2194      }
2195//        else
2196//        {
2197//               "Y"; iposv[i-1]-N+1;
2198//        }
2199    }
2200  }
2201}
2202example
2203{
2204  "EXAMPLE:";echo=2;
2205  ring r = (real,10),(x),lp;
2206
2207  // consider the max. problem:
2208  //
2209  //    maximize  x(1) + x(2) + 3*x(3) - 0.5*x(4)
2210  //
2211  //  with constraints:   x(1) +          2*x(3)          <= 740
2212  //                             2*x(2)          - 7*x(4) <=   0
2213  //                               x(2) -   x(3) + 2*x(4) >=   0.5
2214  //                      x(1) +   x(2) +   x(3) +   x(4)  =   9
2215  //
2216  matrix sm[5][5]=   0, 1, 1, 3,-0.5,
2217                   740,-1, 0,-2, 0,
2218                     0, 0,-2, 0, 7,
2219                   0.5, 0,-1, 1,-2,
2220                     9,-1,-1,-1,-1;
2221
2222  int n = 4;  // number of constraints
2223  int m = 4;  // number of variables
2224  int m1= 2;  // number of <= constraints
2225  int m2= 1;  // number of >= constraints
2226  int m3= 1;  // number of == constraints
2227
2228  list sol=simplex(sm, n, m, m1, m2, m3);
2229  simplexOut(sol);
2230}
2231
2232
2233// local Variables: ***
2234// c-set-style: bsd ***
2235// End: ***
Note: See TracBrowser for help on using the repository browser.