#1867: suggested way to fix #1705 -- factoring multivariate polynomials over
finite fields is broken in Singular
---------------------------------+------------------------------------------
 Reporter:  was                  |        Owner:  malb      
     Type:  defect               |       Status:  new       
 Priority:  major                |    Milestone:  sage-3.4.1
Component:  commutative algebra  |   Resolution:            
 Keywords:                       |  
---------------------------------+------------------------------------------
Old description:

> There is a standard algorithm to factor polynomials over a non-prime
> field that reduces the problem to factoring over a prime field and using
> gcd over the non-prime field.  It seems that gcd works fine over non-
> prime fields in Singular, as does factoring over prime fields, so this
> should work for us.   Probably singular doesn't do this because either it
> is slower or it is too much of a pain to implement in Singular (which
> isn't much of a language), or maybe they just don't care about this
> problem.
>
> Anyway, to start this off, here is a sample session that illustrates the
> idea:
> {{{
> sage: k.<a> = GF(9)
> sage: R.<x,y> = PolynomialRing(k)
> sage: f = (x-a)*(y-a)
> sage: f.factor()
> Traceback (most recent call last):
> ...
> NotImplementedError: factorization of multivariate polynomials over non-
> prime fields explicitly disabled due to bugs in Singular
> sage: singular(f)
> sage: x*y+(-a)*x+(-a)*y+(a+1)
> x*y + ( - a)*x + ( - a)*y + (a + 1)
> sage: singular(f).factorH()
> [1]:
>    _[1]=1
>    _[2]=x*y+(-a)*x+(-a)*y+(a+1)
> [2]:
>    1,1
> sage: g = f*(x-a^3)*(y-a^3); g
> x^2*y^2 - x^2*y - x*y^2 - x^2 + x*y - y^2 + x + y + 1
> sage: gg = GF(3)['x,y'](repr(g))    # why doesn't change ring or coerce
> work
> sage: F = gg.factor()
> sage: factor1 = R(F[0][0])
> sage: factor2 = R(F[1][0])
> sage: factor1.gcd(f)
> (a)*y + ( - a - 1)
> sage: factor2.gcd(f)
> (a)*x + ( - a - 1)
>
> }}}

New description:

 NOTE: This ticket depends on #5068, which is done.

 There is a standard algorithm to factor polynomials over a non-prime field
 that reduces the problem to factoring over a prime field and using gcd
 over the non-prime field.  It seems that gcd works fine over non-prime
 fields in Singular, as does factoring over prime fields, so this should
 work for us.   Probably singular doesn't do this because either it is
 slower or it is too much of a pain to implement in Singular (which isn't
 much of a language), or maybe they just don't care about this problem.

 Anyway, to start this off, here is a sample session that illustrates the
 idea:
 {{{
 sage: k.<a> = GF(9)
 sage: R.<x,y> = PolynomialRing(k)
 sage: f = (x-a)*(y-a)
 sage: f.factor()
 Traceback (most recent call last):
 ...
 NotImplementedError: factorization of multivariate polynomials over non-
 prime fields explicitly disabled due to bugs in Singular
 sage: singular(f)
 sage: x*y+(-a)*x+(-a)*y+(a+1)
 x*y + ( - a)*x + ( - a)*y + (a + 1)
 sage: singular(f).factorH()
 [1]:
    _[1]=1
    _[2]=x*y+(-a)*x+(-a)*y+(a+1)
 [2]:
    1,1
 sage: g = f*(x-a^3)*(y-a^3); g
 x^2*y^2 - x^2*y - x*y^2 - x^2 + x*y - y^2 + x + y + 1
 sage: gg = GF(3)['x,y'](repr(g))    # why doesn't change ring or coerce
 work
 sage: F = gg.factor()
 sage: factor1 = R(F[0][0])
 sage: factor2 = R(F[1][0])
 sage: factor1.gcd(f)
 (a)*y + ( - a - 1)
 sage: factor2.gcd(f)
 (a)*x + ( - a - 1)

 }}}

Comment (by was):

 I have attached a patch that:

  * fully implements this idea.  This works with dramatically higher
 probability than singular itself.  Singular usually gives wrong answers,
 whereas with this code it seems right "about 99% of the time".  E.g., this
 runs for a long time before finding a problem:
 {{{
 k.<a> = GF(3^2); R.<x,y> = PolynomialRing(k)
 for i in range(500):
     v = [R.random_element() for _ in range(3)]; print i; assert
 prod(v).factor(proof=False).prod() == prod(v)

 1
 ...
 328
 boom!
 AssertionError: bug in Singular factoring an auxiliary polynomial over
 GF(p): bad multiplicity (1, 2)
 }}}

 and



  * found bugs in factorization over GF(p) -- see ticket #5068.  Added a
 proof flag, and *only* allow factoring if proof=False.

 I think this should go into sage because:
    1. It works massively better than singular currently does over GF(q).
    2. Even if singular does fix say factoring, maybe they will only fix
 GF(p) factorization and not GF(p^e).  Then this code will make factoring
 over GF(p^e) work too.
    3. If we ever implement our own factorization then this code means we
 only have to implement GF(p), at least for starters.  It would be very
 nice if we at least had *some* implementation that works, even if is slow.
    4. This patch adds some useful functions such as map_coefficients
 (which has the same api as the corresponding function in sage-combinat),
 and _norm_over_nonprime_finite_field.


 ---

 TEST CODE:

 {{{
 k.<a> = GF(3^5); R.<x,y> = PolynomialRing(k)
 for i in range(100):
     v = [R.random_element() for _ in range(2)]; print i; assert
 prod(v).factor(False).prod() == prod(v)
 #good


 k.<a> = GF(997^2); R.<x,y> = PolynomialRing(k)
 for i in range(100):
     v = [R.random_element() for _ in range(2)]; print i; assert
 prod(v).factor(False).prod() == prod(v)
 #good


 k.<a> = GF(4); R.<x,y,z> = PolynomialRing(k)
 for i in range(100):
     v = [R.random_element() for _ in range(2)]; print i; assert
 prod(v).factor(False).prod() == prod(v)

 # HORRIBLE:
 sage: k.<a> = GF(4); R.<x,y,z> = PolynomialRing(k)
 sage: for i in range(100):
 ....:         v = [R.random_element() for _ in range(2)]; print i; assert
 prod(v).factor(False).prod() == prod(v)
 ....:
 0
 1
 ...
 30
 convertFacCF2NTLGF2X: coefficient not immidiate!
 [immediately exits sage!]


 k.<a> = GF(7^2); R.<x,y> = PolynomialRing(k)
 for i in range(100):
     v = [R.random_element() for _ in range(3)]; print i; assert
 prod(v).factor(False).prod() == prod(v)
 #good


 k.<a> = GF(7^2); R.<x,y,z> = PolynomialRing(k)
 for i in range(100):
     v = [R.random_element() for _ in range(2)]; print i; assert
 prod(v).factor(False).prod() == prod(v)
 #good

 k.<a> = GF(3^6); R.<x,y> = PolynomialRing(k)
 for i in range(100):
     v = [R.random_element() for _ in range(2)]; print i; assert
 prod(v).factor(False).prod() == prod(v)
 #good

 }}}

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/1867#comment:2>
Sage <http://sagemath.org/>
Sage - Open Source Mathematical Software: Building the Car Instead of 
Reinventing the Wheel
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/sage-trac?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to