source: git/Singular/LIB/absfact.lib @ fa932ac

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