source: git/Singular/LIB/absfact.lib @ 731e67e

spielwiese
Last change on this file since 731e67e was 731e67e, checked in by Hans Schönemann <hannes@…>, 18 years ago
*hannes: format, typos in docu git-svn-id: file:///usr/local/Singular/svn/trunk@9316 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 17.8 KB
Line 
1version="$Id: absfact.lib,v 1.5 2006-07-18 15:48:09 Singular Exp $";
2category="Factorization";
3info="
4LIBRARY: absfact.lib   Absolute factorization for characteristic 0
5AUTHORS: Wolfram Decker,       decker at math.uni-sb.de
6         Gregoire Lecerf,      lecerf at math.uvsq.fr
7         Gerhard Pfister,      pfister at mathematik.uni-kl.de
8
9OVERVIEW:
10 A library for computing the absolute factorization of multivariate
11 polynomials f with coefficients in a field K of characteristic zero.
12 Using Trager's idea, the implemented algorithm computes an absolutely
13 irreducible factor by factorizing over some finite extension field L
14 (which is chosen such that V(f) has a smooth point with coordinates in L).
15 Then a minimal extension field is determined making use of the
16 Rothstein-Trager partial fraction decomposition algorithm. See [Cheze
17 and Lecerf, Lifting and recombination techniques for absolute
18 factorization].
19
20KEYWORDS: factorization, absolute factorization.
21
22PROCEDURES:
23  absFactorize(f);        absolute factorization of poly
24";
25
26////////////////////////////////////////////////////////////////////
27static proc partialDegree(poly p, int i)
28"USAGE:  partialDegree(p,i);   p poly, i int
29RETURN: int, the degree of p in the i-th variable
30"
31{
32  int n = nvars(basering);
33  intvec tmp;
34  tmp[n] = 0;
35  tmp[i] = 1;
36  return(deg(p,tmp));
37}
38////////////////////////////////////////////////////////////////////
39static proc belongTo(string s, list l)
40"USAGE:  belongTo(s,l);   s string, l list
41RETURN: 1 if s belongs to l, 0 otherwise
42"
43{
44  string tmp;
45  for(int i = 1; i <= size(l); i++) {
46    tmp = l[i];
47    if (tmp == s) {
48      return(1);
49    }
50  }
51  return(0);
52}
53////////////////////////////////////////////////////////////////////
54static proc variableWithSmallestPositiveDegree(poly p)
55"USAGE:  variableWithSmallestPositiveDegree(p);  p poly
56RETURN: int;  0 if p is constant. Otherwise, the index of the
57        variable which has the smallest positive degree in p.
58"
59{
60  int n = nvars(basering);
61  int v = 0;
62  int d = deg(p);
63  int d_loc;
64  for(int i = 1; i <= n; i++) {
65    d_loc = partialDegree(p, i);
66    if (d_loc >= 1 and d_loc <= d) {
67      v = i;
68      d = d_loc;
69    }
70  }
71  return(v);
72}
73////////////////////////////////////////////////////////////////////
74static proc smallestProperSimpleFactor(poly p)
75"USAGE:  smallestProperSimpleFactor(p);   p poly
76RETURN: poly:  a proper irreducible simple factor of p of smallest
77        degree. If no such factor exists, 0 is returned.
78"
79{
80  list p_facts = factorize(p);
81  int s = size(p_facts[1]);
82  int d = deg(p)+1;
83  poly q = 0;
84  poly f;
85  int e;
86  for(int i = 1; i <= s; i = i + 1) {
87    f = p_facts[1][i];
88    e = deg(f);
89    if (e >= 1 and e < d and p_facts[2][i] == 1) {
90      q = f / leadcoef(f);
91      d = e;
92    }
93  }
94  return(q);
95}
96////////////////////////////////////////////////////////////////////
97static proc smallestProperFactor(poly p)
98"USAGE:  smallestProperFactor(p);   p poly
99RETURN: poly:  a proper irreducible factor of p of smallest degree.
100        If p is constant, 0 is returned.
101"
102{
103  list p_facts = factorize(p);
104  int s = size(p_facts[1]);
105  int d = deg(p)+1;
106  poly q = 0;
107  poly f;
108  int e;
109  for(int i = 1; i <= s; i = i + 1) {
110    f = p_facts[1][i];
111    e = deg(f);
112    if (e >= 1 and e < d) {
113      q = f / leadcoef(f);
114      d = e;
115    }
116  }
117  return(q);
118}
119////////////////////////////////////////////////////////////////////
120static proc extensionContainingSmoothPoint(poly p, int m)
121"USAGE:  extensionContainingSmoothPoint(p,m);  p poly, m int
122RETURN: poly:  an irreducible univariate polynomial that defines an
123        algebraic extension of the current ground field that contains
124        a smooth point of the hypersurface defined by p=0.
125"
126{
127  int n = nvars(basering) - 1;
128  poly q = 0;
129  int i;
130  list a;
131  for(i=1;i<=n+1;i++){a[i] = 0;}
132  a[m] = var(n+1);
133  // The list a is to be taken with random entries in [-e, e].
134  // Every 10 * n trial, e is incremented by 1.
135  int e = 1;
136  int nbtrial = 0;
137  map h;
138  while (q == 0) {
139    h = basering, a[1..n+1];
140    q = smallestProperSimpleFactor(h(p));
141    for(i = 1; i  <= n ; i = i + 1) {
142      if (i != m) {
143        a[i] = random(-e, e);
144      }
145    }
146    nbtrial++;
147    if (nbtrial >= 10 * n) {
148      e = e + 1;
149      nbtrial = 0;
150    }
151  }
152  return(q);
153}
154////////////////////////////////////////////////////////////////////
155static proc RothsteinTragerResultant(poly g, poly f, int m)
156"USAGE:  RothsteinTragerResultant(g,f,m);  g,f poly, m int
157RETURN: poly
158NOTE:   To be called by the RothsteinTrager procedure only.
159"
160{
161  def MPz = basering;
162  int n = nvars(MPz) - 1;
163  int d = partialDegree(f, m);
164  poly df = diff(f, var(m));
165  list a;
166  int i;
167  for(i=1;i<=n+1;i++){ a[i] = 0; }
168  a[m] = var(m);
169  poly q = 0;
170  int e = 1;
171  int nbtrial = 0;
172  map h;
173  while (q == 0) {
174    h = MPz, a[1..n+1];
175    q = resultant(h(f), h(df) * var(n+1) - h(g), var(m));
176    if (deg(q) == d) {
177      return(q/leadcoef(q));
178    }
179    q = 0;
180    for(i = 1; i  <= n ; i = i + 1) {
181      if (i != m) {
182        a[i] = random(-e, e);
183      }
184    }
185    nbtrial++;
186    if (nbtrial >= 10 * n) {
187      e = e + 1;
188      nbtrial = 0;
189    }
190  }
191}
192////////////////////////////////////////////////////////////////////
193static proc RothsteinTrager(list g, poly p, int m, int expectedDegQ)
194"USAGE:  RothsteinTrager(g,p,m,d);  g list, p poly, m,d int
195RETURN: list L consisting of two entries of type poly
196NOTE:   the return value is the Rothstein-Trager partial fraction
197        decomposition of the quotient s/p, where s is a generic linear
198        combination of the elements of g. The genericity via d
199        (the expected degree of L[1]).
200"
201{
202  def MPz = basering;
203  int n = nvars(MPz) - 1;
204  poly dp = diff(p, var(m));
205  int r = size(g);
206  list a;
207  int i;
208  for(i=1;i<=r;i++){a[i] = 0;}
209  a[r] = 1;
210  int nbtrial = 0;
211  int e = 1;
212  poly s;
213  poly q;
214  while (1)
215  {
216    s = 0;
217    for(i = 1; i <= r; i++){s = s + a[i] * g[i];}
218    q = RothsteinTragerResultant(s, p, m);
219    q = smallestProperFactor(q);
220    if (deg(q) == expectedDegQ)
221    {
222      // Go into the quotient by q(z)=0
223      ring MP_z = (0,var(n+1)), (x(1..n)), dp;
224      list lMP_z = ringlist(MP_z);
225      lMP_z[1][4] = ideal(imap(MPz,q));
226      list tmp = ringlist(MPz)[2];
227      lMP_z[2] = list(tmp[1..n]);
228      def MPq = ring(lMP_z);
229      setring(MPq);
230      poly f = gcd(imap(MPz, p), par(1) * imap(MPz, dp) - imap(MPz, s));
231      f = f / leadcoef(f);
232      setring(MPz);
233      return(list(q, imap(MPq, f)));
234    }
235    for(i = 1; i  <= r ; i++) {
236      a[i] = random(-e, e);
237    }
238    nbtrial++;
239    if (nbtrial >= 10 * r) {
240      e = e + 1;
241      nbtrial = 0;
242    }
243  }
244}
245////////////////////////////////////////////////////////////////////
246static proc absFactorizeIrreducible(poly p)
247"USAGE:   absFactorizeIrreducible(p);   p poly
248ASSUME:  p is an irreducible polynomial that does not depend on the last
249         variable @z of the basering.
250RETURN:  list L of two polynomials: q=L[1] is an irreducible polynomial of
251         minimal degree in @z such that p has an absolute factor
252         over K[@z]/<q>, and f represents such an absolute factor.
253"
254{
255  int dblevel = printlevel - voice + 2;
256  dbprint(dblevel,"Entering absfact.lib::absFactorizeIrreducible with ",p);
257  def MPz = basering;
258  int d = deg(p);
259  int n = nvars(MPz) - 1;
260
261  if (d < 1) {
262    return(list(var(n+1), p));
263  }
264  int m = variableWithSmallestPositiveDegree(p);
265  // var(m) is now considered as the main variable.
266
267  poly q = extensionContainingSmoothPoint(p, m);
268  int r = deg(q);
269  if (r == 1) {
270    return(list(var(n+1), p));
271  }
272
273  // Go into the quotient by q(z)=0
274  ring MP_z = (0,var(n+1)), (x(1..n)), dp;
275  list lMP_z = ringlist(MP_z);
276  lMP_z[1][4] = ideal(imap(MPz,q));
277  list tmp = ringlist(MPz)[2];
278  lMP_z[2] = list(tmp[1..n]);
279  def MPq = ring(lMP_z);
280  setring(MPq);
281  dbprint(dblevel-1,"Factoring in algebraic extension");
282  // "Factoring p in the algebraic extension...";
283  poly p_loc = imap(MPz, p);
284  poly f = smallestProperSimpleFactor(p_loc);
285  int degf = deg(f);
286
287  if (degf == d) {
288    setring(MPz);
289    return(list(var(n+1), p));
290  }
291
292  if (degf * r == d) {
293    setring(MPz);
294    return(list(q, imap(MPq, f)));
295  }
296  dbprint(dblevel-1,"Absolutely irreducible factor found");
297  dbprint(dblevel,"Minimizing field extension");
298  // "Need to find a minimal extension";
299  poly co_f = p_loc / f;
300  poly e = diff(f, var(m)) * co_f;
301  setring(MPz);
302  poly e = imap(MPq, e);
303  list g;
304  int i;
305  for(i = 1; i <= r; i++)
306  {
307    g[i] = subst(e, var(n+1), 0);
308    e = diff(e, var(n+1));
309  }
310  return(RothsteinTrager(g, p, m, d / degf));
311}
312
313////////////////////////////////////////////////////////////////////
314proc absFactorize(poly p, list #)
315"USAGE:  absFactorize(p [,s]);   p poly, s string
316ASSUME: coefficient field is the field of rational numbers or a
317        transcendental extension thereof
318RETURN: ring @code{R} which is obtained from the current basering
319        by adding a new parameter (if a string @code{s} is given as a
320        second input, the new parameter gets this string as name). The ring
321        @code{R} comes with a list @code{absolute_factors} with the
322        following entries:
323@format
324    absolute_factors[1]: ideal   (the absolute factors)
325    absolute_factors[2]: intvec  (the multiplicities)
326    absolute_factors[3]: ideal   (the minimal polynomials)
327    absolute_factors[4]: int     (total number of nontriv. absolute factors)
328@end format
329        The entry @code{absolute_factors[1][1]} is a constant, the
330        entry @code{absolute_factors[3][1]} is the parameter added to the
331        current ring.@*
332        Each of the remaining entries @code{absolute_factors[1][j]} stands for
333        a class of conjugated absolute factors. The corresponding entry
334        @code{absolute_factors[3][j]} is the minimal polynomial of the
335        field extension over which the factor is minimally defined (its degree
336        is the number of conjugates in the class). If the entry
337        @code{absolute_factors[3][j]} coincides with @code{absolute_factors[3][1]},
338        no field extension was necessary for the @code{j}th (class of)
339        absolute factor(s).
340NOTE:   All factors are presented denominator- and content-free. The constant
341        factor (first entry) is chosen such that the product of all (!) the
342        (denominator- and content-free) absolute factors of @code{p} equals
343        @code{p / absolute_factors[1][1]}.
344SEE ALSO: factorize, absPrimdecGTZ
345EXAMPLE: example absFactorize; shows an example
346"
347{
348  int dblevel = printlevel - voice + 2;
349  dbprint(dblevel,"Entering absfact.lib::absFactorize with ",p);
350  def MP = basering;
351  int i;
352  if (char(MP) != 0) {
353    ERROR("// absfact.lib::absFactorize is only implemented for "+
354          "characteristic 0");
355  }
356  if(minpoly!=0) {
357    ERROR("// absfact.lib::absFactorize is not implemented for algebraic "
358          +"extensions");
359  }
360
361  int n = nvars(MP);
362  int pa=npars(MP);
363  list lMP= ringlist(MP);
364  intvec vv,vk;
365  for(i=1;i<=n;i++){vv[i]=1;}
366  vk=vv,1;
367
368  //if the basering has parameters, add the parameters to the variables
369  //takes care about coefficients and possible denominators
370  if(pa>0)
371  {
372    poly qh=cleardenom(p);
373    if (p==0) {
374      number cok=0;
375    }
376    else {
377      number cok=leadcoef(p)/leadcoef(qh);
378    }
379    p=qh;
380    string sp;
381    for(i=1;i<=npars(basering);i++)
382    {
383      sp=string(par(i));
384      sp=sp[2..size(sp)-1];
385      lMP[2][n+i]=sp;
386      vv=vv,1;
387    }
388    lMP[1]=0;
389    n=n+npars(MP);
390  }
391
392  // MPz is obtained by adding the new variable @z to MP
393  // ordering is wp(1...1)
394  // All the above subroutines work in MPz
395  string newvar;
396  if(size(#)>0)
397    {
398      if(typeof(#[1])=="string")
399        {
400          newvar=#[1];
401        }
402      else
403      {
404        newvar = "a";
405      }
406    }
407  else
408    {
409      newvar = "a";
410    }
411  if (newvar=="a")
412    {
413      if(belongTo(newvar, lMP[2])||defined(a)){newvar = "b";}
414      if(belongTo(newvar, lMP[2])||defined(b)){newvar = "c";}
415      if(belongTo(newvar, lMP[2])||defined(c)){newvar = "@c";}
416      while(belongTo(newvar, lMP[2])) {
417       newvar = "@" + newvar;
418      }
419    }
420  lMP[2][n+1] = newvar;
421
422  // new ordering
423  vv=vv,1;
424  list orst;
425  orst[1]=list("wp",vv);
426  orst[2]=list("C",0);
427  lMP[3]=orst;
428
429  def MPz = ring(lMP);
430  setring(MPz);
431  poly p=imap(MP,p);
432
433  // special treatment in the homogeneous case, dropping one variable
434  // by substituting the first variable by 1
435  int ho=homog(p);
436  if(ho)
437    {
438      int dh=deg(p);
439      p=subst(p,var(1),1);
440      int di=deg(p);
441    }
442  list rat_facts = factorize(p);
443  int s = size(rat_facts[1]);
444  list tmpf; // absolute factors
445  intvec tmpm; // respective multiplicities
446  tmpf[1] = list(var(n+1), leadcoef(imap(MP,p)));
447  tmpm[1] = 1;
448  poly tmp;
449  for(i = 2; i <= s; i++) {
450    tmp = rat_facts[1][i];
451    tmp = tmp / leadcoef(tmp);
452    tmpf[i] = absFactorizeIrreducible(tmp);
453    tmpm[i] = rat_facts[2][i];
454  }
455  // the homogeneous case, homogenizing the result
456  // the new variable has to have degree 0
457  // need to change the ring
458  if(ho)
459    {
460      list ll=ringlist(MPz);
461      vv[size(vv)]=0;
462      ll[3][1][2]=vv;
463      def MPhelp=ring(ll);
464      setring(MPhelp);
465      list tmpf=imap(MPz,tmpf);
466      for(i=2;i<=size(tmpf);i++)
467        {
468          tmpf[i][2]=homog(tmpf[i][2],var(1));
469        }
470      if(dh>di)
471        {
472          tmpf[size(tmpf)+1]=list(var(n+1),var(1));
473          tmpm[size(tmpm)+1]=dh-di;
474        }
475      setring(MPz);
476      tmpf=imap(MPhelp,tmpf);
477    }
478  // in case of parameters we have to go back to the old ring
479  // taking care about constant factors
480  if(pa)
481    {
482      n=nvars(MP);
483      list lM=ringlist(MP);
484      orst[1]=list("wp",vk);
485      orst[2]=list("C",0);
486      lM[2][n+1] = newvar;
487      lM[3]=orst;
488      def MPout=ring(lM);
489      setring(MPout);
490      list tmpf=imap(MPz,tmpf);
491      number cok=imap(MP,cok);
492      tmpf[1][2]=cok*tmpf[1][2];
493    }
494  else
495    {
496      def MPout=MPz;
497    }
498  // if we want the output as string
499  if(size(#)>0)
500    {
501      if(typeof(#[1])=="int")
502        {
503          if(#[1]==77)
504            {  // undocumented feature for Gerhard's absPrimdecGTZ
505              if (size(tmpf)<2){ list abs_fac = list(var(n+1),poly(1)); }
506              else { list abs_fac=tmpf[2..size(tmpf)]; }
507              abs_fac=abs_fac,newvar;
508              return(string(abs_fac));
509            }
510        }
511    }
512  // preparing the output for SINGULAR standard
513  // a list: factors(ideal),multiplicities(intvec),minpolys(ideal),
514  // number of factors in the absolute factorization
515  // the output(except the coefficient) should have no denominators
516  // and no content
517  ideal facts,minpols;
518  intvec mults;
519  int nfacts;
520  number co=1;
521  minpols[1]=tmpf[1][1];
522  facts[1]=tmpf[1][2];     //the coefficient
523  for(i=2;i<=size(tmpf);i++)
524    {
525      minpols[i]=cleardenom(tmpf[i][1]);
526      facts[i]=cleardenom(tmpf[i][2]);
527      co=co*(leadcoef(tmpf[i][2])/leadcoef(facts[i]))^(deg(minpols[i])*tmpm[i]);
528    }
529  facts[1]=facts[1]*co;
530  for(i=1;i<=size(tmpm);i++)
531    {
532      mults[i]=tmpm[i];
533    }
534  for(i=2;i<=size(mults);i++)
535    {
536      nfacts=nfacts+mults[i]*deg(minpols[i]);
537    }
538  list absolute_factors=facts,mults,minpols,nfacts;
539
540  // create ring with extra parameter `newvar` for output:
541  setring(MP);
542  list Lout=ringlist(MP);
543  if(!pa)
544    {
545      list Lpar=list(char(MP),list(newvar),list(list("lp",intvec(1))),ideal(0));
546    }
547  else
548    {
549      list Lpar=Lout[1];
550      Lpar[2][size(Lpar[2])+1]=newvar;
551      vv=Lpar[3][1][2];
552      vv=vv,1;
553      Lpar[3][1][2]=vv;
554    }
555  Lout[1]=Lpar;
556  def MPo=ring(Lout);
557  setring(MPo);
558  list absolute_factors=imap(MPout,absolute_factors);
559  export absolute_factors;
560  setring(MP);
561
562  dbprint( printlevel-voice+3,"
563// 'absFactorize' created a ring, in which a list absolute_factors (the
564// absolute factors) is stored.
565// To access the list of absolute factors, type (if the name S was assigned
566// to the return value):
567        setring(S); absolute_factors; ");
568  return(MPo);
569}
570example
571{
572  "EXAMPLE:"; echo = 2;
573  ring R = (0), (x,y), lp;
574  poly p = (-7*x^2 + 2*x*y^2 + 6*x + y^4 + 14*y^2 + 47)*(5x2+y2)^3*(x-y)^4;
575  def S = absFactorize(p) ;
576  setring(S);
577  absolute_factors;
578}
579
580/*
581  ring r=0,(x,t),dp;
582  poly p=x^4+(t^3-2t^2-2t)*x^3-(t^5-2t^4-t^2-2t-1)*x^2
583         -(t^6-4t^5+t^4+6t^3+2t^2)*x+(t^6-4t^5+2t^4+4t^3+t^2);
584  def S = absFactorize(p,"s");
585  setring(S);
586  absolute_factors;
587
588  ring r1=(0,a,b),(x,y),dp;
589  poly p=(a3-a2b+27ab3-27b4)/(a+b5)*x2+(a2+27b3)*y;
590  def S = absFactorize(p);
591  setring(S);
592  absolute_factors;
593
594  ring r2=0,(x,y,z,w),dp;
595  poly f=(x2+y2+z2)^2+w4;
596  def S =absFactorize(f);
597  setring(S);
598  absolute_factors;
599
600ring r=0,(x),dp;
601poly p=0;
602def S = absFactorize(p);
603setring(S);
604absolute_factors;
605
606ring r=0,(x),dp;
607poly p=7/11;
608def S = absFactorize(p);
609setring(S);
610absolute_factors;
611
612ring r=(0,a,b),(x,y),dp;
613poly p=0;
614def S = absFactorize(p);
615setring(S);
616absolute_factors;
617
618ring r=(0,a,b),(x,y),dp;
619poly p=(a+1)/b;
620def S = absFactorize(p);
621setring(S);
622absolute_factors;
623
624ring r=(0,a,b),(x,y),dp;
625poly p=(a+1)/b*x;
626def S = absFactorize(p,"s");
627setring(S);
628absolute_factors;
629
630ring r=(0,a,b),(x,y),dp;
631poly p=(a+1)/b*x + 1;
632def S = absFactorize(p,"s");
633setring(S);
634absolute_factors;
635
636ring r=(0,a,b),(x,y),dp;
637poly p=(a+1)/b*x + y;
638def S = absFactorize(p,"s");
639setring(S);
640absolute_factors;
641
642ring r=0,(x,t),dp;
643poly p=x^4+(t^3-2t^2-2t)*x^3-(t^5-2t^4-t^2-2t-1)*x^2
644       -(t^6-4t^5+t^4+6t^3+2t^2)*x+(t^6-4t^5+2t^4+4t^3+t^2);
645def S = absFactorize(p,"s");
646setring(S);
647absolute_factors;
648
649ring r1=(0,a,b),(x,y),dp;
650poly p=(a3-a2b+27ab3-27b4)/(a+b5)*x2+(a2+27b3)*y;
651def S = absFactorize(p);
652setring(S);
653absolute_factors;
654
655ring r2=0,(x,y,z,w),dp;
656poly f=(x2+y2+z2)^2+w4;
657def S =absFactorize(f);
658setring(S);
659absolute_factors;
660
661ring r3=0,(x,y,z,w),dp;
662poly f=(x2+y2+z2)^4+w8;
663def S =absFactorize(f);
664setring(S);
665absolute_factors;
666
667ring r4=0,(x,y),dp;
668poly f=y6-(2x2-2x-14)*y4-(4x3+35x2-6x-47)*y2+14x4-12x3-94x2;
669def S=absFactorize(f);
670setring(S);
671absolute_factors;
672
673ring R1 = 0, x, dp;
674def S1 = absFactorize(x4-2);
675setring(S1);
676absolute_factors;
677
678ring R3 = 0, (x,y), dp;
679poly f = x2y4+y6+2x3y2+2xy4-7x4+7x2y2+14y4+6x3+6xy2+47x2+47y2;
680def S3 = absFactorize(f);
681setring(S3);
682absolute_factors;
683
684ring R4 = 0, (x,y), dp;
685poly f = y4+2*xy2-7*x2+14*y2+6*x+47;
686def S4 = absFactorize(f);
687setring(S4);
688absolute_factors;
689
690*/
Note: See TracBrowser for help on using the repository browser.