source: git/Singular/LIB/absfact.lib @ 334c21f

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