sympy / sympy

A computer algebra system written in pure Python
https://sympy.org/
Other
13.07k stars 4.47k forks source link

factor_list sometimes generates PolificationFailed errors with algebraic extensions #25592

Open Plasmath opened 1 year ago

Plasmath commented 1 year ago

When factoring certain polynomials with factor_list while using an algebraic extension, specifically those of the form (_+_*extension)*polynomial, sympy will raise a PolificationFailed: can't construct a polynomial from _+_*extension error. I think that the factor_list function is attempting to turn the constant factor into a polynomial.

Note that these polynomials are factored correctly within the factor function, so this is an error exclusive to factor_list.

Examples

from sympy import *
x = Symbol("x")
poly = x-x*sqrt(5)
print(factor_list(poly, extension = sqrt(5)))

gives PolificationFailed: can't construct a polynomial from 1 - sqrt(5), when it should output (1-sqrt(5), [(x,1)])

from sympy import *
x = Symbol("x")
poly = (36+2*sqrt(301))*(x**2 - 301)
print(factor(poly, extension = sqrt(301)))

gives PolificationFailed: can't construct a polynomial from 36 + 7*sqrt(301), when it should output (36+2*sqrt(301), [(x + sqrt(301),1), (x - sqrt(301),1)])

oscarbenjamin commented 1 year ago

This kind of situation comes up a lot. Maybe it should be possible to construct a Poly with no generators. In context the call is:

ipdb> p _opt
{'extension': {sqrt(5)}, 'domain': QQ<sqrt(5)>, 'auto': False, 'expand': True}
ipdb> p f
1 - sqrt(5)

So we try to construct a Poly whose domain should be QQ<sqrt(5)> but with generators unspecified. No generators are needed because the expression is an element of the ground domain already.

Alternatively the generators should be tracked and passed in somewhere around here: https://github.com/sympy/sympy/blob/2f80497c7e83d889748df102e9a0c126fdbaeab5/sympy/polys/polytools.py#L6200-L6204

spirosmaggioros commented 10 months ago

Try to use the Poly() constructor for the polynomial

from sympy import Poly, sqrt, Symbol, factor_list, factor

x = Symbol('x')
poly = Poly(x-x*sqrt(5))
print(factor_list(poly, extension = sqrt(5)))