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

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