Univariate polynomial base class¶
AUTHORS:
William Stein: first version
Martin Albrecht: added singular coercion
Robert Bradshaw: moved Polynomial_generic_dense to Cython
Miguel Marco: implemented resultant in the case where PARI fails
Simon King: used a faster way of conversion from the base ring
Kwankyu Lee (2013-06-02): enhanced
quo_rem()
Julian Rueth (2012-05-25,2014-05-09): fixed is_squarefree() for imperfect fields, fixed division without remainder over QQbar; added
_cache_key
for polynomials with unhashable coefficientsSimon King (2013-10): implemented copying of
PolynomialBaseringInjection
Bruno Grenet (2014-07-13): enhanced
quo_rem()
Kiran Kedlaya (2016-03): added root counting
Edgar Costa (2017-07): added rational reconstruction
Kiran Kedlaya (2017-09): added reciprocal transform, trace polynomial
David Zureick-Brown (2017-09): added is_weil_polynomial
Sebastian Oehms (2018-10): made
roots()
andfactor()
work over more cases of proper integral domains (see Issue #26421)
- class sage.rings.polynomial.polynomial_element.ConstantPolynomialSection[source]¶
Bases:
Map
This class is used for conversion from a polynomial ring to its base ring.
Since Issue #9944, it calls the
constant_coefficient()
method, which can be optimized for a particular polynomial type.EXAMPLES:
sage: P0.<y_1> = GF(3)[] sage: P1.<y_2,y_1,y_0> = GF(3)[] sage: P0(-y_1) 2*y_1 sage: phi = GF(3).convert_map_from(P0); phi Generic map: From: Univariate Polynomial Ring in y_1 over Finite Field of size 3 To: Finite Field of size 3 sage: type(phi) <class 'sage.rings.polynomial.polynomial_element.ConstantPolynomialSection'> sage: phi(P0.one()) 1 sage: phi(y_1) Traceback (most recent call last): ... TypeError: y_1 is not a constant polynomial
>>> from sage.all import * >>> P0 = GF(Integer(3))['y_1']; (y_1,) = P0._first_ngens(1) >>> P1 = GF(Integer(3))['y_2, y_1, y_0']; (y_2, y_1, y_0,) = P1._first_ngens(3) >>> P0(-y_1) 2*y_1 >>> phi = GF(Integer(3)).convert_map_from(P0); phi Generic map: From: Univariate Polynomial Ring in y_1 over Finite Field of size 3 To: Finite Field of size 3 >>> type(phi) <class 'sage.rings.polynomial.polynomial_element.ConstantPolynomialSection'> >>> phi(P0.one()) 1 >>> phi(y_1) Traceback (most recent call last): ... TypeError: y_1 is not a constant polynomial
P0.<y_1> = GF(3)[] P1.<y_2,y_1,y_0> = GF(3)[] P0(-y_1) phi = GF(3).convert_map_from(P0); phi type(phi) phi(P0.one()) phi(y_1)
- class sage.rings.polynomial.polynomial_element.Polynomial[source]¶
Bases:
CommutativePolynomial
A polynomial.
EXAMPLES:
sage: R.<y> = QQ['y'] sage: S.<x> = R['x'] sage: S Univariate Polynomial Ring in x over Univariate Polynomial Ring in y over Rational Field sage: f = x*y; f y*x sage: type(f) <class 'sage.rings.polynomial.polynomial_element.Polynomial_generic_dense'> sage: p = (y+1)^10; p(1) 1024
>>> from sage.all import * >>> R = QQ['y']; (y,) = R._first_ngens(1) >>> S = R['x']; (x,) = S._first_ngens(1) >>> S Univariate Polynomial Ring in x over Univariate Polynomial Ring in y over Rational Field >>> f = x*y; f y*x >>> type(f) <class 'sage.rings.polynomial.polynomial_element.Polynomial_generic_dense'> >>> p = (y+Integer(1))**Integer(10); p(Integer(1)) 1024
R.<y> = QQ['y'] S.<x> = R['x'] S f = x*y; f type(f) p = (y+1)^10; p(1)
- _add_(right)[source]¶
Add two polynomials.
EXAMPLES:
sage: R = ZZ['x'] sage: p = R([1,2,3,4]) sage: q = R([4,-3,2,-1]) sage: p + q # indirect doctest 3*x^3 + 5*x^2 - x + 5
>>> from sage.all import * >>> R = ZZ['x'] >>> p = R([Integer(1),Integer(2),Integer(3),Integer(4)]) >>> q = R([Integer(4),-Integer(3),Integer(2),-Integer(1)]) >>> p + q # indirect doctest 3*x^3 + 5*x^2 - x + 5
R = ZZ['x'] p = R([1,2,3,4]) q = R([4,-3,2,-1]) p + q # indirect doctest
- _lmul_(left)[source]¶
Multiply
self
on the left by a scalar.EXAMPLES:
sage: R.<x> = ZZ[] sage: f = (x^3 + x + 5) sage: f._lmul_(7) 7*x^3 + 7*x + 35 sage: 7*f 7*x^3 + 7*x + 35
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = (x**Integer(3) + x + Integer(5)) >>> f._lmul_(Integer(7)) 7*x^3 + 7*x + 35 >>> Integer(7)*f 7*x^3 + 7*x + 35
R.<x> = ZZ[] f = (x^3 + x + 5) f._lmul_(7) 7*f
- _rmul_(right)[source]¶
Multiply
self
on the right by a scalar.EXAMPLES:
sage: R.<x> = ZZ[] sage: f = (x^3 + x + 5) sage: f._rmul_(7) 7*x^3 + 7*x + 35 sage: f*7 7*x^3 + 7*x + 35
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = (x**Integer(3) + x + Integer(5)) >>> f._rmul_(Integer(7)) 7*x^3 + 7*x + 35 >>> f*Integer(7) 7*x^3 + 7*x + 35
R.<x> = ZZ[] f = (x^3 + x + 5) f._rmul_(7) f*7
- _mul_(right)[source]¶
EXAMPLES:
sage: R.<x> = ZZ[] sage: (x - 4) * (x^2 - 8*x + 16) x^3 - 12*x^2 + 48*x - 64 sage: C.<t> = PowerSeriesRing(ZZ) sage: D.<s> = PolynomialRing(C) sage: z = (1 + O(t)) + t*s^2 sage: z*z t^2*s^4 + (2*t + O(t^2))*s^2 + 1 + O(t) ## More examples from trac 2943, added by Kiran S. Kedlaya 2 Dec 09 sage: C.<t> = PowerSeriesRing(Integers()) sage: D.<s> = PolynomialRing(C) sage: z = 1 + (t + O(t^2))*s + (t^2 + O(t^3))*s^2 sage: z*z (t^4 + O(t^5))*s^4 + (2*t^3 + O(t^4))*s^3 + (3*t^2 + O(t^3))*s^2 + (2*t + O(t^2))*s + 1
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> (x - Integer(4)) * (x**Integer(2) - Integer(8)*x + Integer(16)) x^3 - 12*x^2 + 48*x - 64 >>> C = PowerSeriesRing(ZZ, names=('t',)); (t,) = C._first_ngens(1) >>> D = PolynomialRing(C, names=('s',)); (s,) = D._first_ngens(1) >>> z = (Integer(1) + O(t)) + t*s**Integer(2) >>> z*z t^2*s^4 + (2*t + O(t^2))*s^2 + 1 + O(t) ## More examples from trac 2943, added by Kiran S. Kedlaya 2 Dec 09 >>> C = PowerSeriesRing(Integers(), names=('t',)); (t,) = C._first_ngens(1) >>> D = PolynomialRing(C, names=('s',)); (s,) = D._first_ngens(1) >>> z = Integer(1) + (t + O(t**Integer(2)))*s + (t**Integer(2) + O(t**Integer(3)))*s**Integer(2) >>> z*z (t^4 + O(t^5))*s^4 + (2*t^3 + O(t^4))*s^3 + (3*t^2 + O(t^3))*s^2 + (2*t + O(t^2))*s + 1
R.<x> = ZZ[] (x - 4) * (x^2 - 8*x + 16) C.<t> = PowerSeriesRing(ZZ) D.<s> = PolynomialRing(C) z = (1 + O(t)) + t*s^2 z*z C.<t> = PowerSeriesRing(Integers()) D.<s> = PolynomialRing(C) z = 1 + (t + O(t^2))*s + (t^2 + O(t^3))*s^2 z*z
- _mul_trunc_(right, n)[source]¶
Return the truncated multiplication of two polynomials up to
n
.This is the default implementation that does the multiplication and then truncate! There are custom implementations in several subclasses:
EXAMPLES:
sage: R = QQ['x']['y'] sage: y = R.gen() sage: x = R.base_ring().gen() sage: p1 = 1 - x*y + 2*y**3 sage: p2 = -1/3 + y**5 sage: p1._mul_trunc_(p2, 5) -2/3*y^3 + 1/3*x*y - 1/3
>>> from sage.all import * >>> R = QQ['x']['y'] >>> y = R.gen() >>> x = R.base_ring().gen() >>> p1 = Integer(1) - x*y + Integer(2)*y**Integer(3) >>> p2 = -Integer(1)/Integer(3) + y**Integer(5) >>> p1._mul_trunc_(p2, Integer(5)) -2/3*y^3 + 1/3*x*y - 1/3
R = QQ['x']['y'] y = R.gen() x = R.base_ring().gen() p1 = 1 - x*y + 2*y**3 p2 = -1/3 + y**5 p1._mul_trunc_(p2, 5)
Todo
implement a generic truncated Karatsuba and use it here.
- adams_operator(*args, **kwds)[source]¶
Deprecated: Use
adams_operator_on_roots()
instead. See Issue #36396 for details.
- adams_operator_on_roots(n, monic=False)[source]¶
Return the polynomial whose roots are the \(n\)-th powers of the roots of
self
.INPUT:
n
– integermonic
– boolean (default:False
) if set toTrue
, force the output to be monic
EXAMPLES:
sage: # needs sage.libs.pari sage.libs.singular sage: f = cyclotomic_polynomial(30) sage: f.adams_operator_on_roots(7) == f True sage: f.adams_operator_on_roots(6) == cyclotomic_polynomial(5)**2 True sage: f.adams_operator_on_roots(10) == cyclotomic_polynomial(3)**4 True sage: f.adams_operator_on_roots(15) == cyclotomic_polynomial(2)**8 True sage: f.adams_operator_on_roots(30) == cyclotomic_polynomial(1)**8 True sage: x = polygen(QQ) sage: f = x^2 - 2*x + 2 sage: f.adams_operator_on_roots(10) # needs sage.libs.singular x^2 + 1024
>>> from sage.all import * >>> # needs sage.libs.pari sage.libs.singular >>> f = cyclotomic_polynomial(Integer(30)) >>> f.adams_operator_on_roots(Integer(7)) == f True >>> f.adams_operator_on_roots(Integer(6)) == cyclotomic_polynomial(Integer(5))**Integer(2) True >>> f.adams_operator_on_roots(Integer(10)) == cyclotomic_polynomial(Integer(3))**Integer(4) True >>> f.adams_operator_on_roots(Integer(15)) == cyclotomic_polynomial(Integer(2))**Integer(8) True >>> f.adams_operator_on_roots(Integer(30)) == cyclotomic_polynomial(Integer(1))**Integer(8) True >>> x = polygen(QQ) >>> f = x**Integer(2) - Integer(2)*x + Integer(2) >>> f.adams_operator_on_roots(Integer(10)) # needs sage.libs.singular x^2 + 1024
# needs sage.libs.pari sage.libs.singular f = cyclotomic_polynomial(30) f.adams_operator_on_roots(7) == f f.adams_operator_on_roots(6) == cyclotomic_polynomial(5)**2 f.adams_operator_on_roots(10) == cyclotomic_polynomial(3)**4 f.adams_operator_on_roots(15) == cyclotomic_polynomial(2)**8 f.adams_operator_on_roots(30) == cyclotomic_polynomial(1)**8 x = polygen(QQ) f = x^2 - 2*x + 2 f.adams_operator_on_roots(10) # needs sage.libs.singular
When
self
is monic, the output will have leading coefficient \(\pm1\) depending on the degree, but we can force it to be monic:sage: R.<a,b,c> = ZZ[] sage: x = polygen(R) sage: f = (x - a) * (x - b) * (x - c) sage: f.adams_operator_on_roots(3).factor() # needs sage.libs.singular (-1) * (x - c^3) * (x - b^3) * (x - a^3) sage: f.adams_operator_on_roots(3, monic=True).factor() # needs sage.libs.singular (x - c^3) * (x - b^3) * (x - a^3)
>>> from sage.all import * >>> R = ZZ['a, b, c']; (a, b, c,) = R._first_ngens(3) >>> x = polygen(R) >>> f = (x - a) * (x - b) * (x - c) >>> f.adams_operator_on_roots(Integer(3)).factor() # needs sage.libs.singular (-1) * (x - c^3) * (x - b^3) * (x - a^3) >>> f.adams_operator_on_roots(Integer(3), monic=True).factor() # needs sage.libs.singular (x - c^3) * (x - b^3) * (x - a^3)
R.<a,b,c> = ZZ[] x = polygen(R) f = (x - a) * (x - b) * (x - c) f.adams_operator_on_roots(3).factor() # needs sage.libs.singular f.adams_operator_on_roots(3, monic=True).factor() # needs sage.libs.singular
- add_bigoh(prec)[source]¶
Return the power series of precision at most
prec
got by adding \(O(q^\text{prec})\) to self, where \(q\) is its variable.EXAMPLES:
sage: R.<x> = ZZ[] sage: f = 1 + 4*x + x^3 sage: f.add_bigoh(7) 1 + 4*x + x^3 + O(x^7) sage: f.add_bigoh(2) 1 + 4*x + O(x^2) sage: f.add_bigoh(2).parent() Power Series Ring in x over Integer Ring
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = Integer(1) + Integer(4)*x + x**Integer(3) >>> f.add_bigoh(Integer(7)) 1 + 4*x + x^3 + O(x^7) >>> f.add_bigoh(Integer(2)) 1 + 4*x + O(x^2) >>> f.add_bigoh(Integer(2)).parent() Power Series Ring in x over Integer Ring
R.<x> = ZZ[] f = 1 + 4*x + x^3 f.add_bigoh(7) f.add_bigoh(2) f.add_bigoh(2).parent()
- all_roots_in_interval(a=None, b=None)[source]¶
Return
True
if the roots of this polynomial are all real and contained in the given interval.EXAMPLES:
sage: # needs sage.libs.pari sage: R.<x> = PolynomialRing(ZZ) sage: pol = (x - 1)^2 * (x - 2)^2 * (x - 3) sage: pol.all_roots_in_interval(1, 3) True sage: pol.all_roots_in_interval(1.01, 3) False sage: pol = chebyshev_T(5, x) sage: pol.all_roots_in_interval(-1, 1) True sage: pol = chebyshev_T(5, x/2) sage: pol.all_roots_in_interval(-1, 1) False sage: pol.all_roots_in_interval() True
>>> from sage.all import * >>> # needs sage.libs.pari >>> R = PolynomialRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> pol = (x - Integer(1))**Integer(2) * (x - Integer(2))**Integer(2) * (x - Integer(3)) >>> pol.all_roots_in_interval(Integer(1), Integer(3)) True >>> pol.all_roots_in_interval(RealNumber('1.01'), Integer(3)) False >>> pol = chebyshev_T(Integer(5), x) >>> pol.all_roots_in_interval(-Integer(1), Integer(1)) True >>> pol = chebyshev_T(Integer(5), x/Integer(2)) >>> pol.all_roots_in_interval(-Integer(1), Integer(1)) False >>> pol.all_roots_in_interval() True
# needs sage.libs.pari R.<x> = PolynomialRing(ZZ) pol = (x - 1)^2 * (x - 2)^2 * (x - 3) pol.all_roots_in_interval(1, 3) pol.all_roots_in_interval(1.01, 3) pol = chebyshev_T(5, x) pol.all_roots_in_interval(-1, 1) pol = chebyshev_T(5, x/2) pol.all_roots_in_interval(-1, 1) pol.all_roots_in_interval()
- any_irreducible_factor(degree=None, assume_squarefree=False, assume_equal_deg=False, ext_degree=None)[source]¶
Return an irreducible factor of this polynomial.
INPUT:
degree
–None
or positive integer (default:None
). Used for polynomials over finite fields. IfNone
, returns the the first factor found (usually the smallest). Otherwise, attempts to return an irreducible factor ofself
of chosen degreedegree
.assume_squarefree
– boolean (default:False
); Used for polynomials over finite fields. IfTrue
, this polynomial is assumed to be squarefree.assume_equal_deg
– boolean (default:False
); Used for polynomials over finite fields. IfTrue
, this polynomial is assumed to be the product of irreducible polynomials of degree equal todegree
.ext_degree
– positive integer orNone
(default); used for polynomials over finite fields. If notNone
only returns irreducible factors ofself
whose degree dividesext_degree
.
EXAMPLES:
sage: # needs sage.rings.finite_rings sage: F = GF(163) sage: R.<x> = F[] sage: f = (x + 40)^3 * (x^5 + 76*x^4 + 93*x^3 + 112*x^2 + 22*x + 27)^2 * (x^6 + 50*x^5 + 143*x^4 + 162*x^2 + 109*x + 140) sage: f.any_irreducible_factor() x + 40 sage: f.any_irreducible_factor(degree=5) x^5 + 76*x^4 + 93*x^3 + 112*x^2 + 22*x + 27
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> F = GF(Integer(163)) >>> R = F['x']; (x,) = R._first_ngens(1) >>> f = (x + Integer(40))**Integer(3) * (x**Integer(5) + Integer(76)*x**Integer(4) + Integer(93)*x**Integer(3) + Integer(112)*x**Integer(2) + Integer(22)*x + Integer(27))**Integer(2) * (x**Integer(6) + Integer(50)*x**Integer(5) + Integer(143)*x**Integer(4) + Integer(162)*x**Integer(2) + Integer(109)*x + Integer(140)) >>> f.any_irreducible_factor() x + 40 >>> f.any_irreducible_factor(degree=Integer(5)) x^5 + 76*x^4 + 93*x^3 + 112*x^2 + 22*x + 27
# needs sage.rings.finite_rings F = GF(163) R.<x> = F[] f = (x + 40)^3 * (x^5 + 76*x^4 + 93*x^3 + 112*x^2 + 22*x + 27)^2 * (x^6 + 50*x^5 + 143*x^4 + 162*x^2 + 109*x + 140) f.any_irreducible_factor() f.any_irreducible_factor(degree=5)
When the polynomial is known to be squarefree we can optimise the call by setting
assume_squarefree
to beTrue
:sage: # needs sage.rings.finite_rings sage: F = GF(163) sage: R.<x> = F[] sage: g = (x - 1) * (x^3 + 7*x + 161) sage: g.any_irreducible_factor(assume_squarefree=True) x + 162 sage: g.any_irreducible_factor(degree=3, assume_squarefree=True) x^3 + 7*x + 161
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> F = GF(Integer(163)) >>> R = F['x']; (x,) = R._first_ngens(1) >>> g = (x - Integer(1)) * (x**Integer(3) + Integer(7)*x + Integer(161)) >>> g.any_irreducible_factor(assume_squarefree=True) x + 162 >>> g.any_irreducible_factor(degree=Integer(3), assume_squarefree=True) x^3 + 7*x + 161
# needs sage.rings.finite_rings F = GF(163) R.<x> = F[] g = (x - 1) * (x^3 + 7*x + 161) g.any_irreducible_factor(assume_squarefree=True) g.any_irreducible_factor(degree=3, assume_squarefree=True)
If we ask for an irreducible factor which does not exist, the function will throw a
ValueError
:sage: # needs sage.rings.finite_rings sage: F = GF(163) sage: R.<x> = F[] sage: g = (x - 1) * (x^3 + 7*x + 161) sage: g.any_irreducible_factor(degree=2, assume_squarefree=True) Traceback (most recent call last): ... ValueError: no irreducible factor of degree 2 could be computed from x^4 + 162*x^3 + 7*x^2 + 154*x + 2
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> F = GF(Integer(163)) >>> R = F['x']; (x,) = R._first_ngens(1) >>> g = (x - Integer(1)) * (x**Integer(3) + Integer(7)*x + Integer(161)) >>> g.any_irreducible_factor(degree=Integer(2), assume_squarefree=True) Traceback (most recent call last): ... ValueError: no irreducible factor of degree 2 could be computed from x^4 + 162*x^3 + 7*x^2 + 154*x + 2
# needs sage.rings.finite_rings F = GF(163) R.<x> = F[] g = (x - 1) * (x^3 + 7*x + 161) g.any_irreducible_factor(degree=2, assume_squarefree=True)
If we assume that the polynomial is product of irreducible polynomials of the same degree, we must also supply the degree:
sage: # needs sage.rings.finite_rings sage: F = GF(163) sage: R.<x> = F[] sage: h = (x + 57) * (x + 98) * (x + 117) * (x + 145) sage: h.any_irreducible_factor(degree=1, assume_equal_deg=True) # random x + 98 sage: h.any_irreducible_factor(assume_equal_deg=True) Traceback (most recent call last): ... ValueError: degree must be known if distinct degree factorisation is assumed
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> F = GF(Integer(163)) >>> R = F['x']; (x,) = R._first_ngens(1) >>> h = (x + Integer(57)) * (x + Integer(98)) * (x + Integer(117)) * (x + Integer(145)) >>> h.any_irreducible_factor(degree=Integer(1), assume_equal_deg=True) # random x + 98 >>> h.any_irreducible_factor(assume_equal_deg=True) Traceback (most recent call last): ... ValueError: degree must be known if distinct degree factorisation is assumed
# needs sage.rings.finite_rings F = GF(163) R.<x> = F[] h = (x + 57) * (x + 98) * (x + 117) * (x + 145) h.any_irreducible_factor(degree=1, assume_equal_deg=True) # random h.any_irreducible_factor(assume_equal_deg=True)
Also works for extension fields and even characteristic:
sage: F.<z4> = GF(2^4) sage: R.<x> = F[] sage: f = (x + z4^3 + z4^2)^4 * (x^2 + z4*x + z4) * (x^2 + (z4^3 + z4^2 + z4)*x + z4^2 + z4 + 1) sage: f.any_irreducible_factor() x + z4^3 + z4^2 sage: f.any_irreducible_factor(degree=2) # random x^2 + (z4^3 + z4^2 + z4)*x + z4^2 + z4 + 1
>>> from sage.all import * >>> F = GF(Integer(2)**Integer(4), names=('z4',)); (z4,) = F._first_ngens(1) >>> R = F['x']; (x,) = R._first_ngens(1) >>> f = (x + z4**Integer(3) + z4**Integer(2))**Integer(4) * (x**Integer(2) + z4*x + z4) * (x**Integer(2) + (z4**Integer(3) + z4**Integer(2) + z4)*x + z4**Integer(2) + z4 + Integer(1)) >>> f.any_irreducible_factor() x + z4^3 + z4^2 >>> f.any_irreducible_factor(degree=Integer(2)) # random x^2 + (z4^3 + z4^2 + z4)*x + z4^2 + z4 + 1
F.<z4> = GF(2^4) R.<x> = F[] f = (x + z4^3 + z4^2)^4 * (x^2 + z4*x + z4) * (x^2 + (z4^3 + z4^2 + z4)*x + z4^2 + z4 + 1) f.any_irreducible_factor() f.any_irreducible_factor(degree=2) # random
We can also use this function for polynomials which are not defined over finite fields, but this simply falls back to a slow method of factorisation:
sage: R.<x> = ZZ[] sage: f = 3*x^4 + 2*x^3 sage: f.any_irreducible_factor() 3*x + 2
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = Integer(3)*x**Integer(4) + Integer(2)*x**Integer(3) >>> f.any_irreducible_factor() 3*x + 2
R.<x> = ZZ[] f = 3*x^4 + 2*x^3 f.any_irreducible_factor()
- any_root(ring=None, degree=None, assume_squarefree=False, assume_equal_deg=False)[source]¶
Return a root of this polynomial in the given ring.
INPUT:
ring
– the ring in which a root is sought; by default this is the coefficient ringdegree
–None
or nonzero integer; used for polynomials over finite fields. Return a root of degreeabs(degree)
over the ground field. If negative, also assumes that all factors of this polynomial are of degreeabs(degree)
. IfNone
, returns a root of minimal degree contained within the given ring.assume_squarefree
– boolean; used for polynomials over finite fields. IfTrue
, this polynomial is assumed to be squarefree.assume_equal_deg
– boolean; used for polynomials over finite fields. IfTrue
, all factors of this polynomial are assumed to have degreedegree
. Note thatdegree
must be set.
Warning
Negative degree input will be deprecated. Instead use
assume_equal_deg
.Note
For finite fields,
any_root()
is non-deterministic when finding linear roots of a polynomial over the base ring. However, ifdegree
is greater than one, orring
is an extension of the base ring, then the root computed is found by attempting to return a root after factorisation. Roots found in this way are deterministic. This may change in the future. For all other rings or fields, roots are found by first fully-factoringself
and the output is deterministic.EXAMPLES:
sage: # needs sage.rings.finite_rings sage: R.<x> = GF(11)[] sage: f = 7*x^7 + 8*x^6 + 4*x^5 + x^4 + 6*x^3 + 10*x^2 + 8*x + 5 sage: f.any_root() 2 sage: f.factor() (7) * (x + 9) * (x^6 + 10*x^4 + 6*x^3 + 5*x^2 + 2*x + 2) sage: f = x^6 + 10*x^4 + 6*x^3 + 5*x^2 + 2*x + 2 sage: root = f.any_root(GF(11^6, 'a')) sage: roots = sorted(f.roots(GF(11^6, 'a'), multiplicities=False)) sage: roots [10*a^5 + 2*a^4 + 8*a^3 + 9*a^2 + a, a^5 + a^4 + 7*a^3 + 2*a^2 + 10*a, 9*a^5 + 5*a^4 + 10*a^3 + 8*a^2 + 3*a + 1, 2*a^5 + 8*a^4 + 3*a^3 + 6*a + 2, a^5 + 3*a^4 + 8*a^3 + 2*a^2 + 3*a + 4, 10*a^5 + 3*a^4 + 8*a^3 + a^2 + 10*a + 4] sage: root in roots True sage: # needs sage.rings.finite_rings sage: g = (x-1) * (x^2 + 3*x + 9) * (x^5 + 5*x^4 + 8*x^3 + 5*x^2 + 3*x + 5) sage: g.any_root(ring=GF(11^10, 'b'), degree=1) 1 sage: root = g.any_root(ring=GF(11^10, 'b'), degree=2) sage: roots = (x^2 + 3*x + 9).roots(ring=GF(11^10, 'b'), multiplicities=False) sage: root in roots True sage: root = g.any_root(ring=GF(11^10, 'b'), degree=5) sage: roots = (x^5 + 5*x^4 + 8*x^3 + 5*x^2 + 3*x + 5).roots(ring=GF(11^10, 'b'), multiplicities=False) sage: root in roots True
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> R = GF(Integer(11))['x']; (x,) = R._first_ngens(1) >>> f = Integer(7)*x**Integer(7) + Integer(8)*x**Integer(6) + Integer(4)*x**Integer(5) + x**Integer(4) + Integer(6)*x**Integer(3) + Integer(10)*x**Integer(2) + Integer(8)*x + Integer(5) >>> f.any_root() 2 >>> f.factor() (7) * (x + 9) * (x^6 + 10*x^4 + 6*x^3 + 5*x^2 + 2*x + 2) >>> f = x**Integer(6) + Integer(10)*x**Integer(4) + Integer(6)*x**Integer(3) + Integer(5)*x**Integer(2) + Integer(2)*x + Integer(2) >>> root = f.any_root(GF(Integer(11)**Integer(6), 'a')) >>> roots = sorted(f.roots(GF(Integer(11)**Integer(6), 'a'), multiplicities=False)) >>> roots [10*a^5 + 2*a^4 + 8*a^3 + 9*a^2 + a, a^5 + a^4 + 7*a^3 + 2*a^2 + 10*a, 9*a^5 + 5*a^4 + 10*a^3 + 8*a^2 + 3*a + 1, 2*a^5 + 8*a^4 + 3*a^3 + 6*a + 2, a^5 + 3*a^4 + 8*a^3 + 2*a^2 + 3*a + 4, 10*a^5 + 3*a^4 + 8*a^3 + a^2 + 10*a + 4] >>> root in roots True >>> # needs sage.rings.finite_rings >>> g = (x-Integer(1)) * (x**Integer(2) + Integer(3)*x + Integer(9)) * (x**Integer(5) + Integer(5)*x**Integer(4) + Integer(8)*x**Integer(3) + Integer(5)*x**Integer(2) + Integer(3)*x + Integer(5)) >>> g.any_root(ring=GF(Integer(11)**Integer(10), 'b'), degree=Integer(1)) 1 >>> root = g.any_root(ring=GF(Integer(11)**Integer(10), 'b'), degree=Integer(2)) >>> roots = (x**Integer(2) + Integer(3)*x + Integer(9)).roots(ring=GF(Integer(11)**Integer(10), 'b'), multiplicities=False) >>> root in roots True >>> root = g.any_root(ring=GF(Integer(11)**Integer(10), 'b'), degree=Integer(5)) >>> roots = (x**Integer(5) + Integer(5)*x**Integer(4) + Integer(8)*x**Integer(3) + Integer(5)*x**Integer(2) + Integer(3)*x + Integer(5)).roots(ring=GF(Integer(11)**Integer(10), 'b'), multiplicities=False) >>> root in roots True
# needs sage.rings.finite_rings R.<x> = GF(11)[] f = 7*x^7 + 8*x^6 + 4*x^5 + x^4 + 6*x^3 + 10*x^2 + 8*x + 5 f.any_root() f.factor() f = x^6 + 10*x^4 + 6*x^3 + 5*x^2 + 2*x + 2 root = f.any_root(GF(11^6, 'a')) roots = sorted(f.roots(GF(11^6, 'a'), multiplicities=False)) roots root in roots # needs sage.rings.finite_rings g = (x-1) * (x^2 + 3*x + 9) * (x^5 + 5*x^4 + 8*x^3 + 5*x^2 + 3*x + 5) g.any_root(ring=GF(11^10, 'b'), degree=1) root = g.any_root(ring=GF(11^10, 'b'), degree=2) roots = (x^2 + 3*x + 9).roots(ring=GF(11^10, 'b'), multiplicities=False) root in roots root = g.any_root(ring=GF(11^10, 'b'), degree=5) roots = (x^5 + 5*x^4 + 8*x^3 + 5*x^2 + 3*x + 5).roots(ring=GF(11^10, 'b'), multiplicities=False) root in roots
- args()[source]¶
Return the generator of this polynomial ring, which is the (only) argument used when calling
self
.EXAMPLES:
sage: R.<x> = QQ[] sage: x.args() (x,)
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> x.args() (x,)
R.<x> = QQ[] x.args()
A constant polynomial has no variables, but still takes a single argument.
sage: R(2).args() (x,)
>>> from sage.all import * >>> R(Integer(2)).args() (x,)
R(2).args()
- base_extend(R)[source]¶
Return a copy of this polynomial but with coefficients in
R
, if there is a natural map from the coefficient ring ofself
toR
.EXAMPLES:
sage: R.<x> = QQ[] sage: f = x^3 - 17*x + 3 sage: f.base_extend(GF(7)) Traceback (most recent call last): ... TypeError: no such base extension sage: f.change_ring(GF(7)) x^3 + 4*x + 3
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) - Integer(17)*x + Integer(3) >>> f.base_extend(GF(Integer(7))) Traceback (most recent call last): ... TypeError: no such base extension >>> f.change_ring(GF(Integer(7))) x^3 + 4*x + 3
R.<x> = QQ[] f = x^3 - 17*x + 3 f.base_extend(GF(7)) f.change_ring(GF(7))
- base_ring()[source]¶
Return the base ring of the parent of
self
.EXAMPLES:
sage: R.<x> = ZZ[] sage: x.base_ring() Integer Ring sage: (2*x + 3).base_ring() Integer Ring
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> x.base_ring() Integer Ring >>> (Integer(2)*x + Integer(3)).base_ring() Integer Ring
R.<x> = ZZ[] x.base_ring() (2*x + 3).base_ring()
- change_ring(R)[source]¶
Return a copy of this polynomial but with coefficients in
R
, if at all possible.INPUT:
R
– a ring or morphism
EXAMPLES:
sage: K.<z> = CyclotomicField(3) # needs sage.rings.number_field sage: f = K.defining_polynomial() # needs sage.rings.number_field sage: f.change_ring(GF(7)) # needs sage.rings.finite_rings sage.rings.number_field x^2 + x + 1
>>> from sage.all import * >>> K = CyclotomicField(Integer(3), names=('z',)); (z,) = K._first_ngens(1)# needs sage.rings.number_field >>> f = K.defining_polynomial() # needs sage.rings.number_field >>> f.change_ring(GF(Integer(7))) # needs sage.rings.finite_rings sage.rings.number_field x^2 + x + 1
K.<z> = CyclotomicField(3) # needs sage.rings.number_field f = K.defining_polynomial() # needs sage.rings.number_field f.change_ring(GF(7)) # needs sage.rings.finite_rings sage.rings.number_field
sage: # needs sage.rings.number_field sage: K.<z> = CyclotomicField(3) sage: R.<x> = K[] sage: f = x^2 + z sage: f.change_ring(K.embeddings(CC)[1]) # needs sage.rings.real_mpfr x^2 - 0.500000000000000 - 0.866025403784438*I
>>> from sage.all import * >>> # needs sage.rings.number_field >>> K = CyclotomicField(Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> R = K['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) + z >>> f.change_ring(K.embeddings(CC)[Integer(1)]) # needs sage.rings.real_mpfr x^2 - 0.500000000000000 - 0.866025403784438*I
# needs sage.rings.number_field K.<z> = CyclotomicField(3) R.<x> = K[] f = x^2 + z f.change_ring(K.embeddings(CC)[1]) # needs sage.rings.real_mpfr
>>> from sage.all import * >>> # needs sage.rings.number_field >>> K = CyclotomicField(Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> R = K['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) + z >>> f.change_ring(K.embeddings(CC)[Integer(1)]) # needs sage.rings.real_mpfr x^2 - 0.500000000000000 - 0.866025403784438*I
# needs sage.rings.number_field K.<z> = CyclotomicField(3) R.<x> = K[] f = x^2 + z f.change_ring(K.embeddings(CC)[1]) # needs sage.rings.real_mpfr
sage: R.<x> = QQ[] sage: f = x^2 + 1 sage: f.change_ring(QQ.embeddings(CC)[0]) # needs sage.rings.real_mpfr x^2 + 1.00000000000000
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) + Integer(1) >>> f.change_ring(QQ.embeddings(CC)[Integer(0)]) # needs sage.rings.real_mpfr x^2 + 1.00000000000000
R.<x> = QQ[] f = x^2 + 1 f.change_ring(QQ.embeddings(CC)[0]) # needs sage.rings.real_mpfr
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) + Integer(1) >>> f.change_ring(QQ.embeddings(CC)[Integer(0)]) # needs sage.rings.real_mpfr x^2 + 1.00000000000000
R.<x> = QQ[] f = x^2 + 1 f.change_ring(QQ.embeddings(CC)[0]) # needs sage.rings.real_mpfr
- change_variable_name(var)[source]¶
Return a new polynomial over the same base ring but in a different variable.
EXAMPLES:
sage: x = polygen(QQ,'x') sage: f = -2/7*x^3 + (2/3)*x - 19/993; f -2/7*x^3 + 2/3*x - 19/993 sage: f.change_variable_name('theta') -2/7*theta^3 + 2/3*theta - 19/993
>>> from sage.all import * >>> x = polygen(QQ,'x') >>> f = -Integer(2)/Integer(7)*x**Integer(3) + (Integer(2)/Integer(3))*x - Integer(19)/Integer(993); f -2/7*x^3 + 2/3*x - 19/993 >>> f.change_variable_name('theta') -2/7*theta^3 + 2/3*theta - 19/993
x = polygen(QQ,'x') f = -2/7*x^3 + (2/3)*x - 19/993; f f.change_variable_name('theta')
- coefficients(sparse=True)[source]¶
Return the coefficients of the monomials appearing in
self
.If
sparse=True
(the default), it returns only the nonzero coefficients. Otherwise, it returns the same value asself.list()
. (In this case, it may be slightly faster to invokeself.list()
directly.) In either case, the coefficients are ordered by increasing degree.EXAMPLES:
sage: _.<x> = PolynomialRing(ZZ) sage: f = 3*x^4 + 2*x^2 + 1 sage: f.coefficients() [1, 2, 3] sage: f.coefficients(sparse=False) [1, 0, 2, 0, 3]
>>> from sage.all import * >>> _ = PolynomialRing(ZZ, names=('x',)); (x,) = _._first_ngens(1) >>> f = Integer(3)*x**Integer(4) + Integer(2)*x**Integer(2) + Integer(1) >>> f.coefficients() [1, 2, 3] >>> f.coefficients(sparse=False) [1, 0, 2, 0, 3]
_.<x> = PolynomialRing(ZZ) f = 3*x^4 + 2*x^2 + 1 f.coefficients() f.coefficients(sparse=False)
- complex_roots()[source]¶
Return the complex roots of this polynomial, without multiplicities.
Calls
self.roots(ring=CC)
, unless this is a polynomial with floating-point coefficients, in which case it is uses the appropriate precision from the input coefficients.EXAMPLES:
sage: # needs sage.libs.pari sage.rings.real_mpfr sage: x = polygen(ZZ) sage: (x^3 - 1).complex_roots() # note: low order bits slightly different on ppc. [1.00000000000000, -0.500000000000000 - 0.86602540378443...*I, -0.500000000000000 + 0.86602540378443...*I]
>>> from sage.all import * >>> # needs sage.libs.pari sage.rings.real_mpfr >>> x = polygen(ZZ) >>> (x**Integer(3) - Integer(1)).complex_roots() # note: low order bits slightly different on ppc. [1.00000000000000, -0.500000000000000 - 0.86602540378443...*I, -0.500000000000000 + 0.86602540378443...*I]
# needs sage.libs.pari sage.rings.real_mpfr x = polygen(ZZ) (x^3 - 1).complex_roots() # note: low order bits slightly different on ppc.
- compose_power(k, algorithm=None, monic=False)[source]¶
Return the \(k\)-th iterate of the composed product of this polynomial with itself.
INPUT:
k
– nonnegative integeralgorithm
–None
(default),'resultant'
, or'BFSS'
; seecomposed_op()
monic
– boolean (default:False
); seecomposed_op()
OUTPUT:
The polynomial of degree \(d^k\) where \(d\) is the degree, whose roots are all \(k\)-fold products of roots of this polynomial. That is, \(f*f*\dots*f\) where this is \(f\) and \(f*f=\)
f.composed_op(f, operator.mul)
.EXAMPLES:
sage: R.<a,b,c> = ZZ[] sage: x = polygen(R) sage: f = (x - a) * (x - b) * (x - c) sage: f.compose_power(2).factor() # needs sage.libs.singular sage.modules (x - c^2) * (x - b^2) * (x - a^2) * (x - b*c)^2 * (x - a*c)^2 * (x - a*b)^2 sage: # needs sage.libs.singular sage.modules sage: x = polygen(QQ) sage: f = x^2 - 2*x + 2 sage: f2 = f.compose_power(2); f2 x^4 - 4*x^3 + 8*x^2 - 16*x + 16 sage: f2 == f.composed_op(f, operator.mul) True sage: f3 = f.compose_power(3); f3 x^8 - 8*x^7 + 32*x^6 - 64*x^5 + 128*x^4 - 512*x^3 + 2048*x^2 - 4096*x + 4096 sage: f3 == f2.composed_op(f, operator.mul) True sage: f4 = f.compose_power(4) sage: f4 == f3.composed_op(f, operator.mul) True
>>> from sage.all import * >>> R = ZZ['a, b, c']; (a, b, c,) = R._first_ngens(3) >>> x = polygen(R) >>> f = (x - a) * (x - b) * (x - c) >>> f.compose_power(Integer(2)).factor() # needs sage.libs.singular sage.modules (x - c^2) * (x - b^2) * (x - a^2) * (x - b*c)^2 * (x - a*c)^2 * (x - a*b)^2 >>> # needs sage.libs.singular sage.modules >>> x = polygen(QQ) >>> f = x**Integer(2) - Integer(2)*x + Integer(2) >>> f2 = f.compose_power(Integer(2)); f2 x^4 - 4*x^3 + 8*x^2 - 16*x + 16 >>> f2 == f.composed_op(f, operator.mul) True >>> f3 = f.compose_power(Integer(3)); f3 x^8 - 8*x^7 + 32*x^6 - 64*x^5 + 128*x^4 - 512*x^3 + 2048*x^2 - 4096*x + 4096 >>> f3 == f2.composed_op(f, operator.mul) True >>> f4 = f.compose_power(Integer(4)) >>> f4 == f3.composed_op(f, operator.mul) True
R.<a,b,c> = ZZ[] x = polygen(R) f = (x - a) * (x - b) * (x - c) f.compose_power(2).factor() # needs sage.libs.singular sage.modules # needs sage.libs.singular sage.modules x = polygen(QQ) f = x^2 - 2*x + 2 f2 = f.compose_power(2); f2 f2 == f.composed_op(f, operator.mul) f3 = f.compose_power(3); f3 f3 == f2.composed_op(f, operator.mul) f4 = f.compose_power(4) f4 == f3.composed_op(f, operator.mul)
- compose_trunc(other, n)[source]¶
Return the composition of
self
andother
, truncated to \(O(x^n)\).This method currently works for some specific coefficient rings only.
EXAMPLES:
sage: Pol.<x> = CBF[] # needs sage.libs.flint sage: (1 + x + x^2/2 + x^3/6 + x^4/24 + x^5/120).compose_trunc(1 + x, 2) # needs sage.libs.flint ([2.708333333333333 +/- ...e-16])*x + [2.71666666666667 +/- ...e-15] sage: Pol.<x> = QQ['y'][] sage: (1 + x + x^2/2 + x^3/6 + x^4/24 + x^5/120).compose_trunc(1 + x, 2) Traceback (most recent call last): ... NotImplementedError: truncated composition is not implemented for this subclass of polynomials
>>> from sage.all import * >>> Pol = CBF['x']; (x,) = Pol._first_ngens(1)# needs sage.libs.flint >>> (Integer(1) + x + x**Integer(2)/Integer(2) + x**Integer(3)/Integer(6) + x**Integer(4)/Integer(24) + x**Integer(5)/Integer(120)).compose_trunc(Integer(1) + x, Integer(2)) # needs sage.libs.flint ([2.708333333333333 +/- ...e-16])*x + [2.71666666666667 +/- ...e-15] >>> Pol = QQ['y']['x']; (x,) = Pol._first_ngens(1) >>> (Integer(1) + x + x**Integer(2)/Integer(2) + x**Integer(3)/Integer(6) + x**Integer(4)/Integer(24) + x**Integer(5)/Integer(120)).compose_trunc(Integer(1) + x, Integer(2)) Traceback (most recent call last): ... NotImplementedError: truncated composition is not implemented for this subclass of polynomials
Pol.<x> = CBF[] # needs sage.libs.flint (1 + x + x^2/2 + x^3/6 + x^4/24 + x^5/120).compose_trunc(1 + x, 2) # needs sage.libs.flint Pol.<x> = QQ['y'][] (1 + x + x^2/2 + x^3/6 + x^4/24 + x^5/120).compose_trunc(1 + x, 2)
- composed_op(p1, p2, op, algorithm=None, monic=False)[source]¶
Return the composed sum, difference, product or quotient of this polynomial with another one.
In the case of two monic polynomials \(p_1\) and \(p_2\) over an integral domain, the composed sum, difference, etc. are given by
\[\prod_{p_1(a)=p_2(b)=0}(x - (a \ast b)), \qquad \ast ∈ \{ +, -, ×, / \}\]where the roots \(a\) and \(b\) are to be considered in the algebraic closure of the fraction field of the coefficients and counted with multiplicities. If the polynomials are not monic this quantity is multiplied by \(\alpha_1^{\deg(p_2)} \alpha_2^{\deg(p_1)}\) where \(\alpha_1\) and \(\alpha_2\) are the leading coefficients of \(p_1\) and \(p_2\) respectively.
INPUT:
p2
– univariate polynomial belonging to the same polynomial ring as this polynomialop
–operator.OP
whereOP=add
orsub
ormul
ortruediv
algorithm
– can be'resultant'
or'BFSS'
; by default the former is used when the polynomials have few nonzero coefficients and small degrees or if the base ring is not \(\ZZ\) or \(\QQ\). Otherwise the latter is used.monic
– whether to return a monic polynomial. IfTrue
the coefficients of the result belong to the fraction field of the coefficients.
ALGORITHM:
The computation is straightforward using resultants. Indeed for the composed sum it would be \(Res_y(p_1(x-y), p_2(y))\). However, the method from [BFSS2006] using series expansions is asymptotically much faster.
Note that the algorithm
BFSS
with polynomials with coefficients in \(\ZZ\) needs to perform operations over \(\QQ\).Todo
The [BFSS2006] algorithm has been implemented here only in the case of polynomials over rationals. For other rings of zero characteristic (or if the characteristic is larger than the product of the degrees), one needs to implement a generic method
_exp_series
. In the general case of nonzero characteristic there is an alternative algorithm in the same paper.The Newton series computation can be done much more efficiently! See [BFSS2006].
EXAMPLES:
sage: x = polygen(ZZ) sage: p1 = x^2 - 1 sage: p2 = x^4 - 1 sage: p1.composed_op(p2, operator.add) # needs sage.libs.singular x^8 - 4*x^6 + 4*x^4 - 16*x^2 sage: p1.composed_op(p2, operator.mul) # needs sage.libs.singular x^8 - 2*x^4 + 1 sage: p1.composed_op(p2, operator.truediv) # needs sage.libs.singular x^8 - 2*x^4 + 1
>>> from sage.all import * >>> x = polygen(ZZ) >>> p1 = x**Integer(2) - Integer(1) >>> p2 = x**Integer(4) - Integer(1) >>> p1.composed_op(p2, operator.add) # needs sage.libs.singular x^8 - 4*x^6 + 4*x^4 - 16*x^2 >>> p1.composed_op(p2, operator.mul) # needs sage.libs.singular x^8 - 2*x^4 + 1 >>> p1.composed_op(p2, operator.truediv) # needs sage.libs.singular x^8 - 2*x^4 + 1
x = polygen(ZZ) p1 = x^2 - 1 p2 = x^4 - 1 p1.composed_op(p2, operator.add) # needs sage.libs.singular p1.composed_op(p2, operator.mul) # needs sage.libs.singular p1.composed_op(p2, operator.truediv) # needs sage.libs.singular
This function works over any field. However for base rings other than \(\ZZ\) and \(\QQ\) only the resultant algorithm is available:
sage: # needs sage.rings.number_field sage: x = polygen(QQbar) sage: p1 = x**2 - AA(2).sqrt() sage: p2 = x**3 - AA(3).sqrt() sage: r1 = p1.roots(multiplicities=False) sage: r2 = p2.roots(multiplicities=False) sage: p = p1.composed_op(p2, operator.add); p x^6 - 4.242640687119285?*x^4 - 3.464101615137755?*x^3 + 6*x^2 - 14.69693845669907?*x + 0.1715728752538099? sage: all(p(x+y).is_zero() for x in r1 for y in r2) True sage: x = polygen(GF(2)) sage: p1 = x**2 + x - 1 sage: p2 = x**3 + x - 1 sage: p_add = p1.composed_op(p2, operator.add); p_add # needs sage.libs.singular x^6 + x^5 + x^3 + x^2 + 1 sage: p_mul = p1.composed_op(p2, operator.mul); p_mul # needs sage.libs.singular x^6 + x^4 + x^2 + x + 1 sage: p_div = p1.composed_op(p2, operator.truediv); p_div # needs sage.libs.singular x^6 + x^5 + x^4 + x^2 + 1 sage: # needs sage.rings.finite_rings sage: K = GF(2**6, 'a') sage: r1 = p1.roots(K, multiplicities=False) sage: r2 = p2.roots(K, multiplicities=False) sage: all(p_add(x1+x2).is_zero() for x1 in r1 for x2 in r2) # needs sage.libs.singular True sage: all(p_mul(x1*x2).is_zero() for x1 in r1 for x2 in r2) # needs sage.libs.singular True sage: all(p_div(x1/x2).is_zero() for x1 in r1 for x2 in r2) # needs sage.libs.singular True
>>> from sage.all import * >>> # needs sage.rings.number_field >>> x = polygen(QQbar) >>> p1 = x**Integer(2) - AA(Integer(2)).sqrt() >>> p2 = x**Integer(3) - AA(Integer(3)).sqrt() >>> r1 = p1.roots(multiplicities=False) >>> r2 = p2.roots(multiplicities=False) >>> p = p1.composed_op(p2, operator.add); p x^6 - 4.242640687119285?*x^4 - 3.464101615137755?*x^3 + 6*x^2 - 14.69693845669907?*x + 0.1715728752538099? >>> all(p(x+y).is_zero() for x in r1 for y in r2) True >>> x = polygen(GF(Integer(2))) >>> p1 = x**Integer(2) + x - Integer(1) >>> p2 = x**Integer(3) + x - Integer(1) >>> p_add = p1.composed_op(p2, operator.add); p_add # needs sage.libs.singular x^6 + x^5 + x^3 + x^2 + 1 >>> p_mul = p1.composed_op(p2, operator.mul); p_mul # needs sage.libs.singular x^6 + x^4 + x^2 + x + 1 >>> p_div = p1.composed_op(p2, operator.truediv); p_div # needs sage.libs.singular x^6 + x^5 + x^4 + x^2 + 1 >>> # needs sage.rings.finite_rings >>> K = GF(Integer(2)**Integer(6), 'a') >>> r1 = p1.roots(K, multiplicities=False) >>> r2 = p2.roots(K, multiplicities=False) >>> all(p_add(x1+x2).is_zero() for x1 in r1 for x2 in r2) # needs sage.libs.singular True >>> all(p_mul(x1*x2).is_zero() for x1 in r1 for x2 in r2) # needs sage.libs.singular True >>> all(p_div(x1/x2).is_zero() for x1 in r1 for x2 in r2) # needs sage.libs.singular True
# needs sage.rings.number_field x = polygen(QQbar) p1 = x**2 - AA(2).sqrt() p2 = x**3 - AA(3).sqrt() r1 = p1.roots(multiplicities=False) r2 = p2.roots(multiplicities=False) p = p1.composed_op(p2, operator.add); p all(p(x+y).is_zero() for x in r1 for y in r2) x = polygen(GF(2)) p1 = x**2 + x - 1 p2 = x**3 + x - 1 p_add = p1.composed_op(p2, operator.add); p_add # needs sage.libs.singular p_mul = p1.composed_op(p2, operator.mul); p_mul # needs sage.libs.singular p_div = p1.composed_op(p2, operator.truediv); p_div # needs sage.libs.singular # needs sage.rings.finite_rings K = GF(2**6, 'a') r1 = p1.roots(K, multiplicities=False) r2 = p2.roots(K, multiplicities=False) all(p_add(x1+x2).is_zero() for x1 in r1 for x2 in r2) # needs sage.libs.singular all(p_mul(x1*x2).is_zero() for x1 in r1 for x2 in r2) # needs sage.libs.singular all(p_div(x1/x2).is_zero() for x1 in r1 for x2 in r2) # needs sage.libs.singular
- constant_coefficient()[source]¶
Return the constant coefficient of this polynomial.
OUTPUT: element of base ring
EXAMPLES:
sage: R.<x> = QQ[] sage: f = -2*x^3 + 2*x - 1/3 sage: f.constant_coefficient() -1/3
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = -Integer(2)*x**Integer(3) + Integer(2)*x - Integer(1)/Integer(3) >>> f.constant_coefficient() -1/3
R.<x> = QQ[] f = -2*x^3 + 2*x - 1/3 f.constant_coefficient()
- content_ideal()[source]¶
Return the content ideal of this polynomial, defined as the ideal generated by its coefficients.
EXAMPLES:
sage: R.<x> = IntegerModRing(4)[] sage: f = x^4 + 3*x^2 + 2 sage: f.content_ideal() Ideal (2, 3, 1) of Ring of integers modulo 4
>>> from sage.all import * >>> R = IntegerModRing(Integer(4))['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(4) + Integer(3)*x**Integer(2) + Integer(2) >>> f.content_ideal() Ideal (2, 3, 1) of Ring of integers modulo 4
R.<x> = IntegerModRing(4)[] f = x^4 + 3*x^2 + 2 f.content_ideal()
When the base ring is a gcd ring, the content as a ring element is the generator of the content ideal:
sage: R.<x> = ZZ[] sage: f = 2*x^3 - 4*x^2 + 6*x - 10 sage: f.content_ideal().gen() 2
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = Integer(2)*x**Integer(3) - Integer(4)*x**Integer(2) + Integer(6)*x - Integer(10) >>> f.content_ideal().gen() 2
R.<x> = ZZ[] f = 2*x^3 - 4*x^2 + 6*x - 10 f.content_ideal().gen()
- cyclotomic_part()[source]¶
Return the product of the irreducible factors of this polynomial which are cyclotomic polynomials.
The algorithm assumes that the polynomial has rational coefficients.
EXAMPLES:
sage: P.<x> = PolynomialRing(Integers()) sage: pol = 2*(x^4 + 1) sage: pol.cyclotomic_part() x^4 + 1 sage: pol = x^4 + 2 sage: pol.cyclotomic_part() 1 sage: pol = (x^4 + 1)^2 * (x^4 + 2) sage: pol.cyclotomic_part() x^8 + 2*x^4 + 1 sage: P.<x> = PolynomialRing(QQ) sage: pol = (x^4 + 1)^2 * (x^4 + 2) sage: pol.cyclotomic_part() x^8 + 2*x^4 + 1 sage: pol = (x - 1) * x * (x + 2) sage: pol.cyclotomic_part() x - 1
>>> from sage.all import * >>> P = PolynomialRing(Integers(), names=('x',)); (x,) = P._first_ngens(1) >>> pol = Integer(2)*(x**Integer(4) + Integer(1)) >>> pol.cyclotomic_part() x^4 + 1 >>> pol = x**Integer(4) + Integer(2) >>> pol.cyclotomic_part() 1 >>> pol = (x**Integer(4) + Integer(1))**Integer(2) * (x**Integer(4) + Integer(2)) >>> pol.cyclotomic_part() x^8 + 2*x^4 + 1 >>> P = PolynomialRing(QQ, names=('x',)); (x,) = P._first_ngens(1) >>> pol = (x**Integer(4) + Integer(1))**Integer(2) * (x**Integer(4) + Integer(2)) >>> pol.cyclotomic_part() x^8 + 2*x^4 + 1 >>> pol = (x - Integer(1)) * x * (x + Integer(2)) >>> pol.cyclotomic_part() x - 1
P.<x> = PolynomialRing(Integers()) pol = 2*(x^4 + 1) pol.cyclotomic_part() pol = x^4 + 2 pol.cyclotomic_part() pol = (x^4 + 1)^2 * (x^4 + 2) pol.cyclotomic_part() P.<x> = PolynomialRing(QQ) pol = (x^4 + 1)^2 * (x^4 + 2) pol.cyclotomic_part() pol = (x - 1) * x * (x + 2) pol.cyclotomic_part()
- degree(gen=None)[source]¶
Return the degree of this polynomial. The zero polynomial has degree \(-1\).
EXAMPLES:
sage: x = ZZ['x'].0 sage: f = x^93 + 2*x + 1 sage: f.degree() 93 sage: x = PolynomialRing(QQ, 'x', sparse=True).0 sage: f = x^100000 sage: f.degree() 100000
>>> from sage.all import * >>> x = ZZ['x'].gen(0) >>> f = x**Integer(93) + Integer(2)*x + Integer(1) >>> f.degree() 93 >>> x = PolynomialRing(QQ, 'x', sparse=True).gen(0) >>> f = x**Integer(100000) >>> f.degree() 100000
x = ZZ['x'].0 f = x^93 + 2*x + 1 f.degree() x = PolynomialRing(QQ, 'x', sparse=True).0 f = x^100000 f.degree()
sage: x = QQ['x'].0 sage: f = 2006*x^2006 - x^2 + 3 sage: f.degree() 2006 sage: f = 0*x sage: f.degree() -1 sage: f = x + 33 sage: f.degree() 1
>>> from sage.all import * >>> x = QQ['x'].gen(0) >>> f = Integer(2006)*x**Integer(2006) - x**Integer(2) + Integer(3) >>> f.degree() 2006 >>> f = Integer(0)*x >>> f.degree() -1 >>> f = x + Integer(33) >>> f.degree() 1
x = QQ['x'].0 f = 2006*x^2006 - x^2 + 3 f.degree() f = 0*x f.degree() f = x + 33 f.degree()
>>> from sage.all import * >>> x = QQ['x'].gen(0) >>> f = Integer(2006)*x**Integer(2006) - x**Integer(2) + Integer(3) >>> f.degree() 2006 >>> f = Integer(0)*x >>> f.degree() -1 >>> f = x + Integer(33) >>> f.degree() 1
x = QQ['x'].0 f = 2006*x^2006 - x^2 + 3 f.degree() f = 0*x f.degree() f = x + 33 f.degree()
AUTHORS:
Naqi Jaffery (2006-01-24): examples
- denominator()[source]¶
Return a denominator of
self
.First, the lcm of the denominators of the entries of
self
is computed and returned. If this computation fails, the unit of the parent ofself
is returned.Note that some subclasses may implement their own
denominator()
method. For example, seesage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint
Warning
This is not the denominator of the rational function defined by
self
, which would always be 1 sinceself
is a polynomial.EXAMPLES:
First we compute the denominator of a polynomial with integer coefficients, which is of course 1.
sage: R.<x> = ZZ[] sage: f = x^3 + 17*x + 1 sage: f.denominator() 1
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + Integer(17)*x + Integer(1) >>> f.denominator() 1
R.<x> = ZZ[] f = x^3 + 17*x + 1 f.denominator()
Next we compute the denominator of a polynomial with rational coefficients.
sage: R.<x> = PolynomialRing(QQ) sage: f = (1/17)*x^19 - (2/3)*x + 1/3; f 1/17*x^19 - 2/3*x + 1/3 sage: f.denominator() 51
>>> from sage.all import * >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> f = (Integer(1)/Integer(17))*x**Integer(19) - (Integer(2)/Integer(3))*x + Integer(1)/Integer(3); f 1/17*x^19 - 2/3*x + 1/3 >>> f.denominator() 51
R.<x> = PolynomialRing(QQ) f = (1/17)*x^19 - (2/3)*x + 1/3; f f.denominator()
Finally, we try to compute the denominator of a polynomial with coefficients in the real numbers, which is a ring whose elements do not have a
denominator()
method.sage: # needs sage.rings.real_mpfr sage: R.<x> = RR[] sage: f = x + RR('0.3'); f x + 0.300000000000000 sage: f.denominator() 1.00000000000000
>>> from sage.all import * >>> # needs sage.rings.real_mpfr >>> R = RR['x']; (x,) = R._first_ngens(1) >>> f = x + RR('0.3'); f x + 0.300000000000000 >>> f.denominator() 1.00000000000000
# needs sage.rings.real_mpfr R.<x> = RR[] f = x + RR('0.3'); f f.denominator()
Check that the denominator is an element over the base whenever the base has no
denominator()
method. This closes Issue #9063.sage: R.<a> = GF(5)[] sage: x = R(0) sage: x.denominator() 1 sage: type(x.denominator()) <class 'sage.rings.finite_rings.integer_mod.IntegerMod_int'> sage: isinstance(x.numerator() / x.denominator(), Polynomial) True sage: isinstance(x.numerator() / R(1), Polynomial) False
>>> from sage.all import * >>> R = GF(Integer(5))['a']; (a,) = R._first_ngens(1) >>> x = R(Integer(0)) >>> x.denominator() 1 >>> type(x.denominator()) <class 'sage.rings.finite_rings.integer_mod.IntegerMod_int'> >>> isinstance(x.numerator() / x.denominator(), Polynomial) True >>> isinstance(x.numerator() / R(Integer(1)), Polynomial) False
R.<a> = GF(5)[] x = R(0) x.denominator() type(x.denominator()) isinstance(x.numerator() / x.denominator(), Polynomial) isinstance(x.numerator() / R(1), Polynomial)
- derivative(*args)[source]¶
The formal derivative of this polynomial, with respect to variables supplied in
args
.Multiple variables and iteration counts may be supplied; see documentation for the global
derivative()
function for more details.See also
_derivative()
EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: g = -x^4 + x^2/2 - x sage: g.derivative() -4*x^3 + x - 1 sage: g.derivative(x) -4*x^3 + x - 1 sage: g.derivative(x, x) -12*x^2 + 1 sage: g.derivative(x, 2) -12*x^2 + 1
>>> from sage.all import * >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> g = -x**Integer(4) + x**Integer(2)/Integer(2) - x >>> g.derivative() -4*x^3 + x - 1 >>> g.derivative(x) -4*x^3 + x - 1 >>> g.derivative(x, x) -12*x^2 + 1 >>> g.derivative(x, Integer(2)) -12*x^2 + 1
R.<x> = PolynomialRing(QQ) g = -x^4 + x^2/2 - x g.derivative() g.derivative(x) g.derivative(x, x) g.derivative(x, 2)
sage: R.<t> = PolynomialRing(ZZ) sage: S.<x> = PolynomialRing(R) sage: f = t^3*x^2 + t^4*x^3 sage: f.derivative() 3*t^4*x^2 + 2*t^3*x sage: f.derivative(x) 3*t^4*x^2 + 2*t^3*x sage: f.derivative(t) 4*t^3*x^3 + 3*t^2*x^2
>>> from sage.all import * >>> R = PolynomialRing(ZZ, names=('t',)); (t,) = R._first_ngens(1) >>> S = PolynomialRing(R, names=('x',)); (x,) = S._first_ngens(1) >>> f = t**Integer(3)*x**Integer(2) + t**Integer(4)*x**Integer(3) >>> f.derivative() 3*t^4*x^2 + 2*t^3*x >>> f.derivative(x) 3*t^4*x^2 + 2*t^3*x >>> f.derivative(t) 4*t^3*x^3 + 3*t^2*x^2
R.<t> = PolynomialRing(ZZ) S.<x> = PolynomialRing(R) f = t^3*x^2 + t^4*x^3 f.derivative() f.derivative(x) f.derivative(t)
>>> from sage.all import * >>> R = PolynomialRing(ZZ, names=('t',)); (t,) = R._first_ngens(1) >>> S = PolynomialRing(R, names=('x',)); (x,) = S._first_ngens(1) >>> f = t**Integer(3)*x**Integer(2) + t**Integer(4)*x**Integer(3) >>> f.derivative() 3*t^4*x^2 + 2*t^3*x >>> f.derivative(x) 3*t^4*x^2 + 2*t^3*x >>> f.derivative(t) 4*t^3*x^3 + 3*t^2*x^2
R.<t> = PolynomialRing(ZZ) S.<x> = PolynomialRing(R) f = t^3*x^2 + t^4*x^3 f.derivative() f.derivative(x) f.derivative(t)
- dict()[source]¶
Return a sparse dictionary representation of this univariate polynomial.
EXAMPLES:
sage: R.<x> = QQ[] sage: f = x^3 + -1/7*x + 13 sage: f.monomial_coefficients() {0: 13, 1: -1/7, 3: 1}
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + -Integer(1)/Integer(7)*x + Integer(13) >>> f.monomial_coefficients() {0: 13, 1: -1/7, 3: 1}
R.<x> = QQ[] f = x^3 + -1/7*x + 13 f.monomial_coefficients()
dict
is an alias:sage: f.dict() {0: 13, 1: -1/7, 3: 1}
>>> from sage.all import * >>> f.dict() {0: 13, 1: -1/7, 3: 1}
f.dict()
- diff(*args)[source]¶
The formal derivative of this polynomial, with respect to variables supplied in
args
.Multiple variables and iteration counts may be supplied; see documentation for the global
derivative()
function for more details.See also
_derivative()
EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: g = -x^4 + x^2/2 - x sage: g.derivative() -4*x^3 + x - 1 sage: g.derivative(x) -4*x^3 + x - 1 sage: g.derivative(x, x) -12*x^2 + 1 sage: g.derivative(x, 2) -12*x^2 + 1
>>> from sage.all import * >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> g = -x**Integer(4) + x**Integer(2)/Integer(2) - x >>> g.derivative() -4*x^3 + x - 1 >>> g.derivative(x) -4*x^3 + x - 1 >>> g.derivative(x, x) -12*x^2 + 1 >>> g.derivative(x, Integer(2)) -12*x^2 + 1
R.<x> = PolynomialRing(QQ) g = -x^4 + x^2/2 - x g.derivative() g.derivative(x) g.derivative(x, x) g.derivative(x, 2)
sage: R.<t> = PolynomialRing(ZZ) sage: S.<x> = PolynomialRing(R) sage: f = t^3*x^2 + t^4*x^3 sage: f.derivative() 3*t^4*x^2 + 2*t^3*x sage: f.derivative(x) 3*t^4*x^2 + 2*t^3*x sage: f.derivative(t) 4*t^3*x^3 + 3*t^2*x^2
>>> from sage.all import * >>> R = PolynomialRing(ZZ, names=('t',)); (t,) = R._first_ngens(1) >>> S = PolynomialRing(R, names=('x',)); (x,) = S._first_ngens(1) >>> f = t**Integer(3)*x**Integer(2) + t**Integer(4)*x**Integer(3) >>> f.derivative() 3*t^4*x^2 + 2*t^3*x >>> f.derivative(x) 3*t^4*x^2 + 2*t^3*x >>> f.derivative(t) 4*t^3*x^3 + 3*t^2*x^2
R.<t> = PolynomialRing(ZZ) S.<x> = PolynomialRing(R) f = t^3*x^2 + t^4*x^3 f.derivative() f.derivative(x) f.derivative(t)
>>> from sage.all import * >>> R = PolynomialRing(ZZ, names=('t',)); (t,) = R._first_ngens(1) >>> S = PolynomialRing(R, names=('x',)); (x,) = S._first_ngens(1) >>> f = t**Integer(3)*x**Integer(2) + t**Integer(4)*x**Integer(3) >>> f.derivative() 3*t^4*x^2 + 2*t^3*x >>> f.derivative(x) 3*t^4*x^2 + 2*t^3*x >>> f.derivative(t) 4*t^3*x^3 + 3*t^2*x^2
R.<t> = PolynomialRing(ZZ) S.<x> = PolynomialRing(R) f = t^3*x^2 + t^4*x^3 f.derivative() f.derivative(x) f.derivative(t)
- differentiate(*args)[source]¶
The formal derivative of this polynomial, with respect to variables supplied in
args
.Multiple variables and iteration counts may be supplied; see documentation for the global
derivative()
function for more details.See also
_derivative()
EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: g = -x^4 + x^2/2 - x sage: g.derivative() -4*x^3 + x - 1 sage: g.derivative(x) -4*x^3 + x - 1 sage: g.derivative(x, x) -12*x^2 + 1 sage: g.derivative(x, 2) -12*x^2 + 1
>>> from sage.all import * >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> g = -x**Integer(4) + x**Integer(2)/Integer(2) - x >>> g.derivative() -4*x^3 + x - 1 >>> g.derivative(x) -4*x^3 + x - 1 >>> g.derivative(x, x) -12*x^2 + 1 >>> g.derivative(x, Integer(2)) -12*x^2 + 1
R.<x> = PolynomialRing(QQ) g = -x^4 + x^2/2 - x g.derivative() g.derivative(x) g.derivative(x, x) g.derivative(x, 2)
sage: R.<t> = PolynomialRing(ZZ) sage: S.<x> = PolynomialRing(R) sage: f = t^3*x^2 + t^4*x^3 sage: f.derivative() 3*t^4*x^2 + 2*t^3*x sage: f.derivative(x) 3*t^4*x^2 + 2*t^3*x sage: f.derivative(t) 4*t^3*x^3 + 3*t^2*x^2
>>> from sage.all import * >>> R = PolynomialRing(ZZ, names=('t',)); (t,) = R._first_ngens(1) >>> S = PolynomialRing(R, names=('x',)); (x,) = S._first_ngens(1) >>> f = t**Integer(3)*x**Integer(2) + t**Integer(4)*x**Integer(3) >>> f.derivative() 3*t^4*x^2 + 2*t^3*x >>> f.derivative(x) 3*t^4*x^2 + 2*t^3*x >>> f.derivative(t) 4*t^3*x^3 + 3*t^2*x^2
R.<t> = PolynomialRing(ZZ) S.<x> = PolynomialRing(R) f = t^3*x^2 + t^4*x^3 f.derivative() f.derivative(x) f.derivative(t)
>>> from sage.all import * >>> R = PolynomialRing(ZZ, names=('t',)); (t,) = R._first_ngens(1) >>> S = PolynomialRing(R, names=('x',)); (x,) = S._first_ngens(1) >>> f = t**Integer(3)*x**Integer(2) + t**Integer(4)*x**Integer(3) >>> f.derivative() 3*t^4*x^2 + 2*t^3*x >>> f.derivative(x) 3*t^4*x^2 + 2*t^3*x >>> f.derivative(t) 4*t^3*x^3 + 3*t^2*x^2
R.<t> = PolynomialRing(ZZ) S.<x> = PolynomialRing(R) f = t^3*x^2 + t^4*x^3 f.derivative() f.derivative(x) f.derivative(t)
- discriminant()[source]¶
Return the discriminant of
self
.The discriminant is
\[R_n := a_n^{2 n-2} \prod_{1<i<j<n} (r_i-r_j)^2,\]where \(n\) is the degree of
self
, \(a_n\) is the leading coefficient ofself
, and the roots ofself
are \(r_1, \ldots, r_n\).OUTPUT: an element of the base ring of the polynomial ring
ALGORITHM:
Uses the identity \(R_n(f) := (-1)^{n (n-1)/2} R(f, f') a_n^{n-k-2}\), where \(n\) is the degree of
self
, \(a_n\) is the leading coefficient ofself
, \(f'\) is the derivative of \(f\), and \(k\) is the degree of \(f'\). Callsresultant()
.EXAMPLES:
In the case of elliptic curves in special form, the discriminant is easy to calculate:
sage: R.<x> = QQ[] sage: f = x^3 + x + 1 sage: d = f.discriminant(); d # needs sage.libs.pari -31 sage: d.parent() is QQ # needs sage.libs.pari True sage: EllipticCurve([1, 1]).discriminant()/16 # needs sage.libs.pari sage.schemes -31
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + x + Integer(1) >>> d = f.discriminant(); d # needs sage.libs.pari -31 >>> d.parent() is QQ # needs sage.libs.pari True >>> EllipticCurve([Integer(1), Integer(1)]).discriminant()/Integer(16) # needs sage.libs.pari sage.schemes -31
R.<x> = QQ[] f = x^3 + x + 1 d = f.discriminant(); d # needs sage.libs.pari d.parent() is QQ # needs sage.libs.pari EllipticCurve([1, 1]).discriminant()/16 # needs sage.libs.pari sage.schemes
sage: R.<x> = QQ[] sage: f = 2*x^3 + x + 1 sage: d = f.discriminant(); d # needs sage.libs.pari -116
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = Integer(2)*x**Integer(3) + x + Integer(1) >>> d = f.discriminant(); d # needs sage.libs.pari -116
R.<x> = QQ[] f = 2*x^3 + x + 1 d = f.discriminant(); d # needs sage.libs.pari
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = Integer(2)*x**Integer(3) + x + Integer(1) >>> d = f.discriminant(); d # needs sage.libs.pari -116
R.<x> = QQ[] f = 2*x^3 + x + 1 d = f.discriminant(); d # needs sage.libs.pari
We can compute discriminants over univariate and multivariate polynomial rings:
sage: R.<a> = QQ[] sage: S.<x> = R[] sage: f = a*x + x + a + 1 sage: d = f.discriminant(); d # needs sage.libs.pari 1 sage: d.parent() is R # needs sage.libs.pari True
>>> from sage.all import * >>> R = QQ['a']; (a,) = R._first_ngens(1) >>> S = R['x']; (x,) = S._first_ngens(1) >>> f = a*x + x + a + Integer(1) >>> d = f.discriminant(); d # needs sage.libs.pari 1 >>> d.parent() is R # needs sage.libs.pari True
R.<a> = QQ[] S.<x> = R[] f = a*x + x + a + 1 d = f.discriminant(); d # needs sage.libs.pari d.parent() is R # needs sage.libs.pari
sage: R.<a, b> = QQ[] sage: S.<x> = R[] sage: f = x^2 + a + b sage: d = f.discriminant(); d # needs sage.libs.pari -4*a - 4*b sage: d.parent() is R # needs sage.libs.pari True
>>> from sage.all import * >>> R = QQ['a, b']; (a, b,) = R._first_ngens(2) >>> S = R['x']; (x,) = S._first_ngens(1) >>> f = x**Integer(2) + a + b >>> d = f.discriminant(); d # needs sage.libs.pari -4*a - 4*b >>> d.parent() is R # needs sage.libs.pari True
R.<a, b> = QQ[] S.<x> = R[] f = x^2 + a + b d = f.discriminant(); d # needs sage.libs.pari d.parent() is R # needs sage.libs.pari
>>> from sage.all import * >>> R = QQ['a, b']; (a, b,) = R._first_ngens(2) >>> S = R['x']; (x,) = S._first_ngens(1) >>> f = x**Integer(2) + a + b >>> d = f.discriminant(); d # needs sage.libs.pari -4*a - 4*b >>> d.parent() is R # needs sage.libs.pari True
R.<a, b> = QQ[] S.<x> = R[] f = x^2 + a + b d = f.discriminant(); d # needs sage.libs.pari d.parent() is R # needs sage.libs.pari
- dispersion(other=None)[source]¶
Compute the dispersion of a pair of polynomials.
The dispersion of \(f\) and \(g\) is the largest nonnegative integer \(n\) such that \(f(x + n)\) and \(g(x)\) have a nonconstant common factor.
When
other
isNone
, compute the auto-dispersion ofself
, i.e., its dispersion with itself.See also
EXAMPLES:
sage: Pol.<x> = QQ[] sage: x.dispersion(x + 1) # needs sage.libs.pari 1 sage: (x + 1).dispersion(x) # needs sage.libs.pari -Infinity sage: # needs sage.libs.pari sage.rings.number_field sage.symbolic sage: Pol.<x> = QQbar[] sage: pol = Pol([sqrt(5), 1, 3/2]) sage: pol.dispersion() 0 sage: (pol*pol(x+3)).dispersion() 3
>>> from sage.all import * >>> Pol = QQ['x']; (x,) = Pol._first_ngens(1) >>> x.dispersion(x + Integer(1)) # needs sage.libs.pari 1 >>> (x + Integer(1)).dispersion(x) # needs sage.libs.pari -Infinity >>> # needs sage.libs.pari sage.rings.number_field sage.symbolic >>> Pol = QQbar['x']; (x,) = Pol._first_ngens(1) >>> pol = Pol([sqrt(Integer(5)), Integer(1), Integer(3)/Integer(2)]) >>> pol.dispersion() 0 >>> (pol*pol(x+Integer(3))).dispersion() 3
Pol.<x> = QQ[] x.dispersion(x + 1) # needs sage.libs.pari (x + 1).dispersion(x) # needs sage.libs.pari # needs sage.libs.pari sage.rings.number_field sage.symbolic Pol.<x> = QQbar[] pol = Pol([sqrt(5), 1, 3/2]) pol.dispersion() (pol*pol(x+3)).dispersion()
- dispersion_set(other=None)[source]¶
Compute the dispersion set of two polynomials.
The dispersion set of \(f\) and \(g\) is the set of nonnegative integers \(n\) such that \(f(x + n)\) and \(g(x)\) have a nonconstant common factor.
When
other
isNone
, compute the auto-dispersion set ofself
, i.e., its dispersion set with itself.ALGORITHM:
See Section 4 of Man & Wright [MW1994].
See also
EXAMPLES:
sage: Pol.<x> = QQ[] sage: x.dispersion_set(x + 1) # needs sage.libs.pari [1] sage: (x + 1).dispersion_set(x) # needs sage.libs.pari [] sage: pol = x^3 + x - 7 sage: (pol*pol(x+3)^2).dispersion_set() # needs sage.libs.pari [0, 3]
>>> from sage.all import * >>> Pol = QQ['x']; (x,) = Pol._first_ngens(1) >>> x.dispersion_set(x + Integer(1)) # needs sage.libs.pari [1] >>> (x + Integer(1)).dispersion_set(x) # needs sage.libs.pari [] >>> pol = x**Integer(3) + x - Integer(7) >>> (pol*pol(x+Integer(3))**Integer(2)).dispersion_set() # needs sage.libs.pari [0, 3]
Pol.<x> = QQ[] x.dispersion_set(x + 1) # needs sage.libs.pari (x + 1).dispersion_set(x) # needs sage.libs.pari pol = x^3 + x - 7 (pol*pol(x+3)^2).dispersion_set() # needs sage.libs.pari
- divides(p)[source]¶
Return
True
if this polynomial divides \(p\).This method is only implemented for polynomials over an integral domain.
EXAMPLES:
sage: R.<x> = ZZ[] sage: (2*x + 1).divides(4*x**2 - 1) True sage: (2*x + 1).divides(4*x**2 + 1) False sage: (2*x + 1).divides(R(0)) True sage: R(0).divides(2*x + 1) False sage: R(0).divides(R(0)) True sage: S.<y> = R[] sage: p = x * y**2 + (2*x + 1) * y + x + 1 sage: q = (x + 1) * y + (3*x + 2) sage: q.divides(p) False sage: q.divides(p * q) True sage: R.<x> = Zmod(6)[] sage: p = 4*x + 3 sage: q = 5*x**2 + x + 2 sage: q.divides(p) False sage: p.divides(q) False
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> (Integer(2)*x + Integer(1)).divides(Integer(4)*x**Integer(2) - Integer(1)) True >>> (Integer(2)*x + Integer(1)).divides(Integer(4)*x**Integer(2) + Integer(1)) False >>> (Integer(2)*x + Integer(1)).divides(R(Integer(0))) True >>> R(Integer(0)).divides(Integer(2)*x + Integer(1)) False >>> R(Integer(0)).divides(R(Integer(0))) True >>> S = R['y']; (y,) = S._first_ngens(1) >>> p = x * y**Integer(2) + (Integer(2)*x + Integer(1)) * y + x + Integer(1) >>> q = (x + Integer(1)) * y + (Integer(3)*x + Integer(2)) >>> q.divides(p) False >>> q.divides(p * q) True >>> R = Zmod(Integer(6))['x']; (x,) = R._first_ngens(1) >>> p = Integer(4)*x + Integer(3) >>> q = Integer(5)*x**Integer(2) + x + Integer(2) >>> q.divides(p) False >>> p.divides(q) False
R.<x> = ZZ[] (2*x + 1).divides(4*x**2 - 1) (2*x + 1).divides(4*x**2 + 1) (2*x + 1).divides(R(0)) R(0).divides(2*x + 1) R(0).divides(R(0)) S.<y> = R[] p = x * y**2 + (2*x + 1) * y + x + 1 q = (x + 1) * y + (3*x + 2) q.divides(p) q.divides(p * q) R.<x> = Zmod(6)[] p = 4*x + 3 q = 5*x**2 + x + 2 q.divides(p) p.divides(q)
- euclidean_degree()[source]¶
Return the degree of this element as an element of a Euclidean domain.
If this polynomial is defined over a field, this is simply its
degree()
.EXAMPLES:
sage: R.<x> = QQ[] sage: x.euclidean_degree() 1 sage: R.<x> = ZZ[] sage: x.euclidean_degree() Traceback (most recent call last): ... NotImplementedError
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> x.euclidean_degree() 1 >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> x.euclidean_degree() Traceback (most recent call last): ... NotImplementedError
R.<x> = QQ[] x.euclidean_degree() R.<x> = ZZ[] x.euclidean_degree()
- exponents()[source]¶
Return the exponents of the monomials appearing in
self
.EXAMPLES:
sage: _.<x> = PolynomialRing(ZZ) sage: f = x^4 + 2*x^2 + 1 sage: f.exponents() [0, 2, 4]
>>> from sage.all import * >>> _ = PolynomialRing(ZZ, names=('x',)); (x,) = _._first_ngens(1) >>> f = x**Integer(4) + Integer(2)*x**Integer(2) + Integer(1) >>> f.exponents() [0, 2, 4]
_.<x> = PolynomialRing(ZZ) f = x^4 + 2*x^2 + 1 f.exponents()
- factor(**kwargs)[source]¶
Return the factorization of
self
over its base ring.INPUT:
kwargs
– any keyword arguments are passed to the method_factor_univariate_polynomial()
of the base ring if it defines such a method.
OUTPUT:
A factorization of
self
over its parent into a unit and irreducible factors. If the parent is a polynomial ring over a field, these factors are monic.EXAMPLES:
Factorization is implemented over various rings. Over \(\QQ\):
sage: x = QQ['x'].0 sage: f = (x^3 - 1)^2 sage: f.factor() # needs sage.libs.pari (x - 1)^2 * (x^2 + x + 1)^2
>>> from sage.all import * >>> x = QQ['x'].gen(0) >>> f = (x**Integer(3) - Integer(1))**Integer(2) >>> f.factor() # needs sage.libs.pari (x - 1)^2 * (x^2 + x + 1)^2
x = QQ['x'].0 f = (x^3 - 1)^2 f.factor() # needs sage.libs.pari
Since \(\QQ\) is a field, the irreducible factors are monic:
sage: f = 10*x^5 - 1 sage: f.factor() # needs sage.libs.pari (10) * (x^5 - 1/10) sage: f = 10*x^5 - 10 sage: f.factor() # needs sage.libs.pari (10) * (x - 1) * (x^4 + x^3 + x^2 + x + 1)
>>> from sage.all import * >>> f = Integer(10)*x**Integer(5) - Integer(1) >>> f.factor() # needs sage.libs.pari (10) * (x^5 - 1/10) >>> f = Integer(10)*x**Integer(5) - Integer(10) >>> f.factor() # needs sage.libs.pari (10) * (x - 1) * (x^4 + x^3 + x^2 + x + 1)
f = 10*x^5 - 1 f.factor() # needs sage.libs.pari f = 10*x^5 - 10 f.factor() # needs sage.libs.pari
Over \(\ZZ\) the irreducible factors need not be monic:
sage: x = ZZ['x'].0 sage: f = 10*x^5 - 1 sage: f.factor() # needs sage.libs.pari 10*x^5 - 1
>>> from sage.all import * >>> x = ZZ['x'].gen(0) >>> f = Integer(10)*x**Integer(5) - Integer(1) >>> f.factor() # needs sage.libs.pari 10*x^5 - 1
x = ZZ['x'].0 f = 10*x^5 - 1 f.factor() # needs sage.libs.pari
We factor a non-monic polynomial over a finite field of 25 elements:
sage: # needs sage.rings.finite_rings sage: k.<a> = GF(25) sage: R.<x> = k[] sage: f = 2*x^10 + 2*x + 2*a sage: F = f.factor(); F (2) * (x + a + 2) * (x^2 + 3*x + 4*a + 4) * (x^2 + (a + 1)*x + a + 2) * (x^5 + (3*a + 4)*x^4 + (3*a + 3)*x^3 + 2*a*x^2 + (3*a + 1)*x + 3*a + 1)
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> k = GF(Integer(25), names=('a',)); (a,) = k._first_ngens(1) >>> R = k['x']; (x,) = R._first_ngens(1) >>> f = Integer(2)*x**Integer(10) + Integer(2)*x + Integer(2)*a >>> F = f.factor(); F (2) * (x + a + 2) * (x^2 + 3*x + 4*a + 4) * (x^2 + (a + 1)*x + a + 2) * (x^5 + (3*a + 4)*x^4 + (3*a + 3)*x^3 + 2*a*x^2 + (3*a + 1)*x + 3*a + 1)
# needs sage.rings.finite_rings k.<a> = GF(25) R.<x> = k[] f = 2*x^10 + 2*x + 2*a F = f.factor(); F
Notice that the unit factor is included when we multiply \(F\) back out:
sage: expand(F) # needs sage.rings.finite_rings sage.symbolic 2*x^10 + 2*x + 2*a
>>> from sage.all import * >>> expand(F) # needs sage.rings.finite_rings sage.symbolic 2*x^10 + 2*x + 2*a
expand(F) # needs sage.rings.finite_rings sage.symbolic
A new ring. In the example below, we set the special method
_factor_univariate_polynomial()
in the base ring which is called to factor univariate polynomials. This facility can be used to easily extend polynomial factorization to work over new rings you introduce:sage: # needs sage.libs.ntl sage: R.<x> = PolynomialRing(IntegerModRing(4), implementation="NTL") sage: (x^2).factor() Traceback (most recent call last): ... NotImplementedError: factorization of polynomials over rings with composite characteristic is not implemented sage: def my_factor(f): ....: return f.change_ring(ZZ).factor() sage: R.base_ring()._factor_univariate_polynomial = my_factor sage: (x^2).factor() # needs sage.libs.pari x^2 sage: del R.base_ring()._factor_univariate_polynomial # clean up
>>> from sage.all import * >>> # needs sage.libs.ntl >>> R = PolynomialRing(IntegerModRing(Integer(4)), implementation="NTL", names=('x',)); (x,) = R._first_ngens(1) >>> (x**Integer(2)).factor() Traceback (most recent call last): ... NotImplementedError: factorization of polynomials over rings with composite characteristic is not implemented >>> def my_factor(f): ... return f.change_ring(ZZ).factor() >>> R.base_ring()._factor_univariate_polynomial = my_factor >>> (x**Integer(2)).factor() # needs sage.libs.pari x^2 >>> del R.base_ring()._factor_univariate_polynomial # clean up
# needs sage.libs.ntl R.<x> = PolynomialRing(IntegerModRing(4), implementation="NTL") (x^2).factor() def my_factor(f): return f.change_ring(ZZ).factor() R.base_ring()._factor_univariate_polynomial = my_factor (x^2).factor() # needs sage.libs.pari del R.base_ring()._factor_univariate_polynomial # clean up
Arbitrary precision real and complex factorization:
sage: # needs sage.libs.pari sage.rings.real_mpfr sage: R.<x> = RealField(100)[] sage: F = factor(x^2 - 3); F (x - 1.7320508075688772935274463415) * (x + 1.7320508075688772935274463415) sage: expand(F) x^2 - 3.0000000000000000000000000000 sage: factor(x^2 + 1) x^2 + 1.0000000000000000000000000000 sage: # needs sage.libs.pari sage.rings.real_mpfr sage: R.<x> = ComplexField(100)[] sage: F = factor(x^2 + 3); F (x - 1.7320508075688772935274463415*I) * (x + 1.7320508075688772935274463415*I) sage: expand(F) x^2 + 3.0000000000000000000000000000 sage: factor(x^2 + 1) (x - I) * (x + I) sage: f = R(I) * (x^2 + 1) ; f I*x^2 + I sage: F = factor(f); F (1.0000000000000000000000000000*I) * (x - I) * (x + I) sage: expand(F) I*x^2 + I
>>> from sage.all import * >>> # needs sage.libs.pari sage.rings.real_mpfr >>> R = RealField(Integer(100))['x']; (x,) = R._first_ngens(1) >>> F = factor(x**Integer(2) - Integer(3)); F (x - 1.7320508075688772935274463415) * (x + 1.7320508075688772935274463415) >>> expand(F) x^2 - 3.0000000000000000000000000000 >>> factor(x**Integer(2) + Integer(1)) x^2 + 1.0000000000000000000000000000 >>> # needs sage.libs.pari sage.rings.real_mpfr >>> R = ComplexField(Integer(100))['x']; (x,) = R._first_ngens(1) >>> F = factor(x**Integer(2) + Integer(3)); F (x - 1.7320508075688772935274463415*I) * (x + 1.7320508075688772935274463415*I) >>> expand(F) x^2 + 3.0000000000000000000000000000 >>> factor(x**Integer(2) + Integer(1)) (x - I) * (x + I) >>> f = R(I) * (x**Integer(2) + Integer(1)) ; f I*x^2 + I >>> F = factor(f); F (1.0000000000000000000000000000*I) * (x - I) * (x + I) >>> expand(F) I*x^2 + I
# needs sage.libs.pari sage.rings.real_mpfr R.<x> = RealField(100)[] F = factor(x^2 - 3); F expand(F) factor(x^2 + 1) # needs sage.libs.pari sage.rings.real_mpfr R.<x> = ComplexField(100)[] F = factor(x^2 + 3); F expand(F) factor(x^2 + 1) f = R(I) * (x^2 + 1) ; f F = factor(f); F expand(F)
Over a number field:
sage: # needs sage.rings.number_field sage: K.<z> = CyclotomicField(15) sage: x = polygen(K) sage: ((x^3 + z*x + 1)^3 * (x - z)).factor() (x - z) * (x^3 + z*x + 1)^3 sage: cyclotomic_polynomial(12).change_ring(K).factor() (x^2 - z^5 - 1) * (x^2 + z^5) sage: ((x^3 + z*x + 1)^3 * (x/(z+2) - 1/3)).factor() (-1/331*z^7 + 3/331*z^6 - 6/331*z^5 + 11/331*z^4 - 21/331*z^3 + 41/331*z^2 - 82/331*z + 165/331) * (x - 1/3*z - 2/3) * (x^3 + z*x + 1)^3
>>> from sage.all import * >>> # needs sage.rings.number_field >>> K = CyclotomicField(Integer(15), names=('z',)); (z,) = K._first_ngens(1) >>> x = polygen(K) >>> ((x**Integer(3) + z*x + Integer(1))**Integer(3) * (x - z)).factor() (x - z) * (x^3 + z*x + 1)^3 >>> cyclotomic_polynomial(Integer(12)).change_ring(K).factor() (x^2 - z^5 - 1) * (x^2 + z^5) >>> ((x**Integer(3) + z*x + Integer(1))**Integer(3) * (x/(z+Integer(2)) - Integer(1)/Integer(3))).factor() (-1/331*z^7 + 3/331*z^6 - 6/331*z^5 + 11/331*z^4 - 21/331*z^3 + 41/331*z^2 - 82/331*z + 165/331) * (x - 1/3*z - 2/3) * (x^3 + z*x + 1)^3
# needs sage.rings.number_field K.<z> = CyclotomicField(15) x = polygen(K) ((x^3 + z*x + 1)^3 * (x - z)).factor() cyclotomic_polynomial(12).change_ring(K).factor() ((x^3 + z*x + 1)^3 * (x/(z+2) - 1/3)).factor()
Over a relative number field:
sage: # needs sage.rings.number_field sage: x = polygen(QQ) sage: K.<z> = CyclotomicField(3) sage: L.<a> = K.extension(x^3 - 2) sage: t = polygen(L, 't') sage: f = (t^3 + t + a) * (t^5 + t + z); f t^8 + t^6 + a*t^5 + t^4 + z*t^3 + t^2 + (a + z)*t + z*a sage: f.factor() (t^3 + t + a) * (t^5 + t + z)
>>> from sage.all import * >>> # needs sage.rings.number_field >>> x = polygen(QQ) >>> K = CyclotomicField(Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> L = K.extension(x**Integer(3) - Integer(2), names=('a',)); (a,) = L._first_ngens(1) >>> t = polygen(L, 't') >>> f = (t**Integer(3) + t + a) * (t**Integer(5) + t + z); f t^8 + t^6 + a*t^5 + t^4 + z*t^3 + t^2 + (a + z)*t + z*a >>> f.factor() (t^3 + t + a) * (t^5 + t + z)
# needs sage.rings.number_field x = polygen(QQ) K.<z> = CyclotomicField(3) L.<a> = K.extension(x^3 - 2) t = polygen(L, 't') f = (t^3 + t + a) * (t^5 + t + z); f f.factor()
Over the real double field:
sage: # needs numpy sage: R.<x> = RDF[] sage: (-2*x^2 - 1).factor() (-2.0) * (x^2 + 0.5000000000000001) sage: (-2*x^2 - 1).factor().expand() -2.0*x^2 - 1.0000000000000002 sage: f = (x - 1)^3 sage: f.factor() # abs tol 2e-5 (x - 1.0000065719436413) * (x^2 - 1.9999934280563585*x + 0.9999934280995487)
>>> from sage.all import * >>> # needs numpy >>> R = RDF['x']; (x,) = R._first_ngens(1) >>> (-Integer(2)*x**Integer(2) - Integer(1)).factor() (-2.0) * (x^2 + 0.5000000000000001) >>> (-Integer(2)*x**Integer(2) - Integer(1)).factor().expand() -2.0*x^2 - 1.0000000000000002 >>> f = (x - Integer(1))**Integer(3) >>> f.factor() # abs tol 2e-5 (x - 1.0000065719436413) * (x^2 - 1.9999934280563585*x + 0.9999934280995487)
# needs numpy R.<x> = RDF[] (-2*x^2 - 1).factor() (-2*x^2 - 1).factor().expand() f = (x - 1)^3 f.factor() # abs tol 2e-5
The above output is incorrect because it relies on the
roots()
method, which does not detect that all the roots are real:sage: f.roots() # abs tol 2e-5 # needs numpy [(1.0000065719436413, 1)]
>>> from sage.all import * >>> f.roots() # abs tol 2e-5 # needs numpy [(1.0000065719436413, 1)]
f.roots() # abs tol 2e-5 # needs numpy
Over the complex double field the factors are approximate and therefore occur with multiplicity 1:
sage: # needs numpy sage.rings.complex_double sage: R.<x> = CDF[] sage: f = (x^2 + 2*R(I))^3 sage: F = f.factor() sage: F # abs tol 3e-5 (x - 1.0000138879287663 + 1.0000013435286879*I) * (x - 0.9999942196864997 + 0.9999873009803959*I) * (x - 0.9999918923847313 + 1.0000113554909125*I) * (x + 0.9999908759550227 - 1.0000069659624138*I) * (x + 0.9999985293216753 - 0.9999886153831807*I) * (x + 1.0000105947233 - 1.0000044186544053*I) sage: [f(t[0][0]).abs() for t in F] # abs tol 1e-13 [1.979365054e-14, 1.97936298566e-14, 1.97936990747e-14, 3.6812407475e-14, 3.65211563729e-14, 3.65220890052e-14]
>>> from sage.all import * >>> # needs numpy sage.rings.complex_double >>> R = CDF['x']; (x,) = R._first_ngens(1) >>> f = (x**Integer(2) + Integer(2)*R(I))**Integer(3) >>> F = f.factor() >>> F # abs tol 3e-5 (x - 1.0000138879287663 + 1.0000013435286879*I) * (x - 0.9999942196864997 + 0.9999873009803959*I) * (x - 0.9999918923847313 + 1.0000113554909125*I) * (x + 0.9999908759550227 - 1.0000069659624138*I) * (x + 0.9999985293216753 - 0.9999886153831807*I) * (x + 1.0000105947233 - 1.0000044186544053*I) >>> [f(t[Integer(0)][Integer(0)]).abs() for t in F] # abs tol 1e-13 [1.979365054e-14, 1.97936298566e-14, 1.97936990747e-14, 3.6812407475e-14, 3.65211563729e-14, 3.65220890052e-14]
# needs numpy sage.rings.complex_double R.<x> = CDF[] f = (x^2 + 2*R(I))^3 F = f.factor() F # abs tol 3e-5 [f(t[0][0]).abs() for t in F] # abs tol 1e-13
Factoring polynomials over \(\ZZ/n\ZZ\) for composite \(n\) is not implemented:
sage: R.<x> = PolynomialRing(Integers(35)) sage: f = (x^2 + 2*x + 2) * (x^2 + 3*x + 9) sage: f.factor() Traceback (most recent call last): ... NotImplementedError: factorization of polynomials over rings with composite characteristic is not implemented
>>> from sage.all import * >>> R = PolynomialRing(Integers(Integer(35)), names=('x',)); (x,) = R._first_ngens(1) >>> f = (x**Integer(2) + Integer(2)*x + Integer(2)) * (x**Integer(2) + Integer(3)*x + Integer(9)) >>> f.factor() Traceback (most recent call last): ... NotImplementedError: factorization of polynomials over rings with composite characteristic is not implemented
R.<x> = PolynomialRing(Integers(35)) f = (x^2 + 2*x + 2) * (x^2 + 3*x + 9) f.factor()
Factoring polynomials over the algebraic numbers (see Issue #8544):
sage: R.<x> = QQbar[] # needs sage.rings.number_field sage: (x^8 - 1).factor() # needs sage.rings.number_field (x - 1) * (x - 0.7071067811865475? - 0.7071067811865475?*I) * (x - 0.7071067811865475? + 0.7071067811865475?*I) * (x - I) * (x + I) * (x + 0.7071067811865475? - 0.7071067811865475?*I) * (x + 0.7071067811865475? + 0.7071067811865475?*I) * (x + 1)
>>> from sage.all import * >>> R = QQbar['x']; (x,) = R._first_ngens(1)# needs sage.rings.number_field >>> (x**Integer(8) - Integer(1)).factor() # needs sage.rings.number_field (x - 1) * (x - 0.7071067811865475? - 0.7071067811865475?*I) * (x - 0.7071067811865475? + 0.7071067811865475?*I) * (x - I) * (x + I) * (x + 0.7071067811865475? - 0.7071067811865475?*I) * (x + 0.7071067811865475? + 0.7071067811865475?*I) * (x + 1)
R.<x> = QQbar[] # needs sage.rings.number_field (x^8 - 1).factor() # needs sage.rings.number_field
Factoring polynomials over the algebraic reals (see Issue #8544):
sage: R.<x> = AA[] # needs sage.rings.number_field sage: (x^8 + 1).factor() # needs sage.rings.number_field (x^2 - 1.847759065022574?*x + 1.000000000000000?) * (x^2 - 0.7653668647301795?*x + 1.000000000000000?) * (x^2 + 0.7653668647301795?*x + 1.000000000000000?) * (x^2 + 1.847759065022574?*x + 1.000000000000000?)
>>> from sage.all import * >>> R = AA['x']; (x,) = R._first_ngens(1)# needs sage.rings.number_field >>> (x**Integer(8) + Integer(1)).factor() # needs sage.rings.number_field (x^2 - 1.847759065022574?*x + 1.000000000000000?) * (x^2 - 0.7653668647301795?*x + 1.000000000000000?) * (x^2 + 0.7653668647301795?*x + 1.000000000000000?) * (x^2 + 1.847759065022574?*x + 1.000000000000000?)
R.<x> = AA[] # needs sage.rings.number_field (x^8 + 1).factor() # needs sage.rings.number_field
- gcd(other)[source]¶
Return a greatest common divisor of this polynomial and
other
.INPUT:
other
– a polynomial in the same ring as this polynomial
OUTPUT:
A greatest common divisor as a polynomial in the same ring as this polynomial. If the base ring is a field, the return value is a monic polynomial.
Note
The actual algorithm for computing greatest common divisors depends on the base ring underlying the polynomial ring. If the base ring defines a method
_gcd_univariate_polynomial()
, then this method will be called (see examples below).EXAMPLES:
sage: R.<x> = QQ[] sage: (2*x^2).gcd(2*x) x sage: R.zero().gcd(0) 0 sage: (2*x).gcd(0) x
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> (Integer(2)*x**Integer(2)).gcd(Integer(2)*x) x >>> R.zero().gcd(Integer(0)) 0 >>> (Integer(2)*x).gcd(Integer(0)) x
R.<x> = QQ[] (2*x^2).gcd(2*x) R.zero().gcd(0) (2*x).gcd(0)
One can easily add gcd functionality to new rings by providing a method
_gcd_univariate_polynomial
:sage: # needs sage.rings.number_field sage.symbolic sage: O = ZZ[-sqrt(5)] sage: R.<x> = O[] sage: a = O.1 sage: p = x + a sage: q = x^2 - 5 sage: p.gcd(q) Traceback (most recent call last): ... NotImplementedError: Order of conductor 2 generated by a in Number Field in a with defining polynomial x^2 - 5 with a = -2.236067977499790? does not provide a gcd implementation for univariate polynomials sage: S.<x> = O.number_field()[] sage: O._gcd_univariate_polynomial = lambda f, g: R(S(f).gcd(S(g))) sage: p.gcd(q) x + a sage: del O._gcd_univariate_polynomial
>>> from sage.all import * >>> # needs sage.rings.number_field sage.symbolic >>> O = ZZ[-sqrt(Integer(5))] >>> R = O['x']; (x,) = R._first_ngens(1) >>> a = O.gen(1) >>> p = x + a >>> q = x**Integer(2) - Integer(5) >>> p.gcd(q) Traceback (most recent call last): ... NotImplementedError: Order of conductor 2 generated by a in Number Field in a with defining polynomial x^2 - 5 with a = -2.236067977499790? does not provide a gcd implementation for univariate polynomials >>> S = O.number_field()['x']; (x,) = S._first_ngens(1) >>> O._gcd_univariate_polynomial = lambda f, g: R(S(f).gcd(S(g))) >>> p.gcd(q) x + a >>> del O._gcd_univariate_polynomial
# needs sage.rings.number_field sage.symbolic O = ZZ[-sqrt(5)] R.<x> = O[] a = O.1 p = x + a q = x^2 - 5 p.gcd(q) S.<x> = O.number_field()[] O._gcd_univariate_polynomial = lambda f, g: R(S(f).gcd(S(g))) p.gcd(q) del O._gcd_univariate_polynomial
Use multivariate implementation for polynomials over polynomials rings:
sage: R.<x> = ZZ[] sage: S.<y> = R[] sage: T.<z> = S[] sage: r = 2*x*y + z sage: p = r * (3*x*y*z - 1) sage: q = r * (x + y + z - 2) sage: p.gcd(q) # needs sage.libs.singular z + 2*x*y sage: R.<x> = QQ[] sage: S.<y> = R[] sage: r = 2*x*y + 1 sage: p = r * (x - 1/2 * y) sage: q = r * (x*y^2 - x + 1/3) sage: p.gcd(q) # needs sage.libs.singular 2*x*y + 1
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> S = R['y']; (y,) = S._first_ngens(1) >>> T = S['z']; (z,) = T._first_ngens(1) >>> r = Integer(2)*x*y + z >>> p = r * (Integer(3)*x*y*z - Integer(1)) >>> q = r * (x + y + z - Integer(2)) >>> p.gcd(q) # needs sage.libs.singular z + 2*x*y >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> S = R['y']; (y,) = S._first_ngens(1) >>> r = Integer(2)*x*y + Integer(1) >>> p = r * (x - Integer(1)/Integer(2) * y) >>> q = r * (x*y**Integer(2) - x + Integer(1)/Integer(3)) >>> p.gcd(q) # needs sage.libs.singular 2*x*y + 1
R.<x> = ZZ[] S.<y> = R[] T.<z> = S[] r = 2*x*y + z p = r * (3*x*y*z - 1) q = r * (x + y + z - 2) p.gcd(q) # needs sage.libs.singular R.<x> = QQ[] S.<y> = R[] r = 2*x*y + 1 p = r * (x - 1/2 * y) q = r * (x*y^2 - x + 1/3) p.gcd(q) # needs sage.libs.singular
- global_height(prec=None)[source]¶
Return the (projective) global height of the polynomial.
This returns the absolute logarithmic height of the coefficients thought of as a projective point.
INPUT:
prec
– desired floating point precision (default: defaultRealField
precision)
OUTPUT: a real number
EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: f = 3*x^3 + 2*x^2 + x sage: exp(f.global_height()) # needs sage.symbolic 3.00000000000000
>>> from sage.all import * >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> f = Integer(3)*x**Integer(3) + Integer(2)*x**Integer(2) + x >>> exp(f.global_height()) # needs sage.symbolic 3.00000000000000
R.<x> = PolynomialRing(QQ) f = 3*x^3 + 2*x^2 + x exp(f.global_height()) # needs sage.symbolic
Scaling should not change the result:
sage: R.<x> = PolynomialRing(QQ) sage: f = 1/25*x^2 + 25/3*x + 1 sage: f.global_height() # needs sage.symbolic 6.43775164973640 sage: g = 100 * f sage: g.global_height() # needs sage.symbolic 6.43775164973640
>>> from sage.all import * >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> f = Integer(1)/Integer(25)*x**Integer(2) + Integer(25)/Integer(3)*x + Integer(1) >>> f.global_height() # needs sage.symbolic 6.43775164973640 >>> g = Integer(100) * f >>> g.global_height() # needs sage.symbolic 6.43775164973640
R.<x> = PolynomialRing(QQ) f = 1/25*x^2 + 25/3*x + 1 f.global_height() # needs sage.symbolic g = 100 * f g.global_height() # needs sage.symbolic
sage: R.<x> = PolynomialRing(QQbar) # needs sage.rings.number_field sage: f = QQbar(i)*x^2 + 3*x # needs sage.rings.number_field sage: f.global_height() # needs sage.rings.number_field 1.09861228866811
>>> from sage.all import * >>> R = PolynomialRing(QQbar, names=('x',)); (x,) = R._first_ngens(1)# needs sage.rings.number_field >>> f = QQbar(i)*x**Integer(2) + Integer(3)*x # needs sage.rings.number_field >>> f.global_height() # needs sage.rings.number_field 1.09861228866811
R.<x> = PolynomialRing(QQbar) # needs sage.rings.number_field f = QQbar(i)*x^2 + 3*x # needs sage.rings.number_field f.global_height() # needs sage.rings.number_field
>>> from sage.all import * >>> R = PolynomialRing(QQbar, names=('x',)); (x,) = R._first_ngens(1)# needs sage.rings.number_field >>> f = QQbar(i)*x**Integer(2) + Integer(3)*x # needs sage.rings.number_field >>> f.global_height() # needs sage.rings.number_field 1.09861228866811
R.<x> = PolynomialRing(QQbar) # needs sage.rings.number_field f = QQbar(i)*x^2 + 3*x # needs sage.rings.number_field f.global_height() # needs sage.rings.number_field
sage: # needs sage.rings.number_field sage: R.<x> = PolynomialRing(QQ) sage: K.<k> = NumberField(x^2 + 5) sage: T.<t> = PolynomialRing(K) sage: f = 1/1331 * t^2 + 5 * t + 7 sage: f.global_height() 9.13959596745043
>>> from sage.all import * >>> # needs sage.rings.number_field >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> K = NumberField(x**Integer(2) + Integer(5), names=('k',)); (k,) = K._first_ngens(1) >>> T = PolynomialRing(K, names=('t',)); (t,) = T._first_ngens(1) >>> f = Integer(1)/Integer(1331) * t**Integer(2) + Integer(5) * t + Integer(7) >>> f.global_height() 9.13959596745043
# needs sage.rings.number_field R.<x> = PolynomialRing(QQ) K.<k> = NumberField(x^2 + 5) T.<t> = PolynomialRing(K) f = 1/1331 * t^2 + 5 * t + 7 f.global_height()
>>> from sage.all import * >>> # needs sage.rings.number_field >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> K = NumberField(x**Integer(2) + Integer(5), names=('k',)); (k,) = K._first_ngens(1) >>> T = PolynomialRing(K, names=('t',)); (t,) = T._first_ngens(1) >>> f = Integer(1)/Integer(1331) * t**Integer(2) + Integer(5) * t + Integer(7) >>> f.global_height() 9.13959596745043
# needs sage.rings.number_field R.<x> = PolynomialRing(QQ) K.<k> = NumberField(x^2 + 5) T.<t> = PolynomialRing(K) f = 1/1331 * t^2 + 5 * t + 7 f.global_height()
sage: R.<x> = QQ[] sage: f = 1/123*x^2 + 12 sage: f.global_height(prec=2) # needs sage.symbolic 8.0
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = Integer(1)/Integer(123)*x**Integer(2) + Integer(12) >>> f.global_height(prec=Integer(2)) # needs sage.symbolic 8.0
R.<x> = QQ[] f = 1/123*x^2 + 12 f.global_height(prec=2) # needs sage.symbolic
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = Integer(1)/Integer(123)*x**Integer(2) + Integer(12) >>> f.global_height(prec=Integer(2)) # needs sage.symbolic 8.0
R.<x> = QQ[] f = 1/123*x^2 + 12 f.global_height(prec=2) # needs sage.symbolic
sage: R.<x> = QQ[] sage: f = 0*x sage: f.global_height() # needs sage.rings.real_mpfr 0.000000000000000
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = Integer(0)*x >>> f.global_height() # needs sage.rings.real_mpfr 0.000000000000000
R.<x> = QQ[] f = 0*x f.global_height() # needs sage.rings.real_mpfr
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = Integer(0)*x >>> f.global_height() # needs sage.rings.real_mpfr 0.000000000000000
R.<x> = QQ[] f = 0*x f.global_height() # needs sage.rings.real_mpfr
- gradient()[source]¶
Return a list of the partial derivative of
self
with respect to the variable of this univariate polynomial.There is only one partial derivative.
EXAMPLES:
sage: P.<x> = QQ[] sage: f = x^2 + (2/3)*x + 1 sage: f.gradient() [2*x + 2/3] sage: f = P(1) sage: f.gradient() [0]
>>> from sage.all import * >>> P = QQ['x']; (x,) = P._first_ngens(1) >>> f = x**Integer(2) + (Integer(2)/Integer(3))*x + Integer(1) >>> f.gradient() [2*x + 2/3] >>> f = P(Integer(1)) >>> f.gradient() [0]
P.<x> = QQ[] f = x^2 + (2/3)*x + 1 f.gradient() f = P(1) f.gradient()
- hamming_weight()[source]¶
Return the number of nonzero coefficients of
self
.Also called weight, Hamming weight or sparsity.
EXAMPLES:
sage: R.<x> = ZZ[] sage: f = x^3 - x sage: f.number_of_terms() 2 sage: R(0).number_of_terms() 0 sage: f = (x + 1)^100 sage: f.number_of_terms() 101 sage: S = GF(5)['y'] sage: S(f).number_of_terms() 5 sage: cyclotomic_polynomial(105).number_of_terms() 33
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) - x >>> f.number_of_terms() 2 >>> R(Integer(0)).number_of_terms() 0 >>> f = (x + Integer(1))**Integer(100) >>> f.number_of_terms() 101 >>> S = GF(Integer(5))['y'] >>> S(f).number_of_terms() 5 >>> cyclotomic_polynomial(Integer(105)).number_of_terms() 33
R.<x> = ZZ[] f = x^3 - x f.number_of_terms() R(0).number_of_terms() f = (x + 1)^100 f.number_of_terms() S = GF(5)['y'] S(f).number_of_terms() cyclotomic_polynomial(105).number_of_terms()
The method
hamming_weight()
is an alias:sage: f.hamming_weight() 101
>>> from sage.all import * >>> f.hamming_weight() 101
f.hamming_weight()
- has_cyclotomic_factor()[source]¶
Return
True
if the given polynomial has a nontrivial cyclotomic factor.The algorithm assumes that the polynomial has rational coefficients.
If the polynomial is known to be irreducible, it may be slightly more efficient to call
is_cyclotomic()
instead.EXAMPLES:
sage: pol.<x> = PolynomialRing(Rationals()) sage: u = x^5 - 1; u.has_cyclotomic_factor() True sage: u = x^5 - 2; u.has_cyclotomic_factor() False sage: u = pol(cyclotomic_polynomial(7)) * pol.random_element() # random sage: u.has_cyclotomic_factor() # random True
>>> from sage.all import * >>> pol = PolynomialRing(Rationals(), names=('x',)); (x,) = pol._first_ngens(1) >>> u = x**Integer(5) - Integer(1); u.has_cyclotomic_factor() True >>> u = x**Integer(5) - Integer(2); u.has_cyclotomic_factor() False >>> u = pol(cyclotomic_polynomial(Integer(7))) * pol.random_element() # random >>> u.has_cyclotomic_factor() # random True
pol.<x> = PolynomialRing(Rationals()) u = x^5 - 1; u.has_cyclotomic_factor() u = x^5 - 2; u.has_cyclotomic_factor() u = pol(cyclotomic_polynomial(7)) * pol.random_element() # random u.has_cyclotomic_factor() # random
- homogenize(var='h')[source]¶
Return the homogenization of this polynomial.
The polynomial itself is returned if it is homogeneous already. Otherwise, its monomials are multiplied with the smallest powers of
var
such that they all have the same total degree.INPUT:
var
– a variable in the polynomial ring (as a string, an element of the ring, or0
) or a name for a new variable (default:'h'
)
OUTPUT:
If
var
specifies the variable in the polynomial ring, then a homogeneous element in that ring is returned. Otherwise, a homogeneous element is returned in a polynomial ring with an extra last variablevar
.EXAMPLES:
sage: R.<x> = QQ[] sage: f = x^2 + 1 sage: f.homogenize() x^2 + h^2
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) + Integer(1) >>> f.homogenize() x^2 + h^2
R.<x> = QQ[] f = x^2 + 1 f.homogenize()
The parameter
var
can be used to specify the name of the variable:sage: g = f.homogenize('z'); g x^2 + z^2 sage: g.parent() Multivariate Polynomial Ring in x, z over Rational Field
>>> from sage.all import * >>> g = f.homogenize('z'); g x^2 + z^2 >>> g.parent() Multivariate Polynomial Ring in x, z over Rational Field
g = f.homogenize('z'); g g.parent()
However, if the polynomial is homogeneous already, then that parameter is ignored and no extra variable is added to the polynomial ring:
sage: f = x^2 sage: g = f.homogenize('z'); g x^2 sage: g.parent() Univariate Polynomial Ring in x over Rational Field
>>> from sage.all import * >>> f = x**Integer(2) >>> g = f.homogenize('z'); g x^2 >>> g.parent() Univariate Polynomial Ring in x over Rational Field
f = x^2 g = f.homogenize('z'); g g.parent()
For compatibility with the multivariate case, if
var
specifies the variable of the polynomial ring, then the monomials are multiplied with the smallest powers ofvar
such that the result is homogeneous; in other words, we end up with a monomial whose leading coefficient is the sum of the coefficients of the polynomial:sage: f = x^2 + x + 1 sage: f.homogenize('x') 3*x^2
>>> from sage.all import * >>> f = x**Integer(2) + x + Integer(1) >>> f.homogenize('x') 3*x^2
f = x^2 + x + 1 f.homogenize('x')
In positive characteristic, the degree can drop in this case:
sage: R.<x> = GF(2)[] sage: f = x + 1 sage: f.homogenize(x) 0
>>> from sage.all import * >>> R = GF(Integer(2))['x']; (x,) = R._first_ngens(1) >>> f = x + Integer(1) >>> f.homogenize(x) 0
R.<x> = GF(2)[] f = x + 1 f.homogenize(x)
For compatibility with the multivariate case, the parameter
var
can also be 0 to specify the variable in the polynomial ring:sage: R.<x> = QQ[] sage: f = x^2 + x + 1 sage: f.homogenize(0) 3*x^2
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) + x + Integer(1) >>> f.homogenize(Integer(0)) 3*x^2
R.<x> = QQ[] f = x^2 + x + 1 f.homogenize(0)
- integral(var=None)[source]¶
Return the integral of this polynomial.
By default, the integration variable is the variable of the polynomial.
Otherwise, the integration variable is the optional parameter
var
Note
The integral is always chosen so that the constant term is 0.
EXAMPLES:
sage: R.<x> = ZZ[] sage: R(0).integral() 0 sage: f = R(2).integral(); f 2*x
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> R(Integer(0)).integral() 0 >>> f = R(Integer(2)).integral(); f 2*x
R.<x> = ZZ[] R(0).integral() f = R(2).integral(); f
Note that the integral lives over the fraction field of the scalar coefficients:
sage: f.parent() Univariate Polynomial Ring in x over Rational Field sage: R(0).integral().parent() Univariate Polynomial Ring in x over Rational Field sage: f = x^3 + x - 2 sage: g = f.integral(); g 1/4*x^4 + 1/2*x^2 - 2*x sage: g.parent() Univariate Polynomial Ring in x over Rational Field
>>> from sage.all import * >>> f.parent() Univariate Polynomial Ring in x over Rational Field >>> R(Integer(0)).integral().parent() Univariate Polynomial Ring in x over Rational Field >>> f = x**Integer(3) + x - Integer(2) >>> g = f.integral(); g 1/4*x^4 + 1/2*x^2 - 2*x >>> g.parent() Univariate Polynomial Ring in x over Rational Field
f.parent() R(0).integral().parent() f = x^3 + x - 2 g = f.integral(); g g.parent()
This shows that the issue at Issue #7711 is resolved:
sage: # needs sage.rings.finite_rings sage: P.<x,z> = PolynomialRing(GF(2147483647)) sage: Q.<y> = PolynomialRing(P) sage: p = x + y + z sage: p.integral() -1073741823*y^2 + (x + z)*y sage: # needs sage.rings.finite_rings sage: P.<x,z> = PolynomialRing(GF(next_prime(2147483647))) sage: Q.<y> = PolynomialRing(P) sage: p = x + y + z sage: p.integral() 1073741830*y^2 + (x + z)*y
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> P = PolynomialRing(GF(Integer(2147483647)), names=('x', 'z',)); (x, z,) = P._first_ngens(2) >>> Q = PolynomialRing(P, names=('y',)); (y,) = Q._first_ngens(1) >>> p = x + y + z >>> p.integral() -1073741823*y^2 + (x + z)*y >>> # needs sage.rings.finite_rings >>> P = PolynomialRing(GF(next_prime(Integer(2147483647))), names=('x', 'z',)); (x, z,) = P._first_ngens(2) >>> Q = PolynomialRing(P, names=('y',)); (y,) = Q._first_ngens(1) >>> p = x + y + z >>> p.integral() 1073741830*y^2 + (x + z)*y
# needs sage.rings.finite_rings P.<x,z> = PolynomialRing(GF(2147483647)) Q.<y> = PolynomialRing(P) p = x + y + z p.integral() # needs sage.rings.finite_rings P.<x,z> = PolynomialRing(GF(next_prime(2147483647))) Q.<y> = PolynomialRing(P) p = x + y + z p.integral()
A truly convoluted example:
sage: A.<a1, a2> = PolynomialRing(ZZ) sage: B.<b> = PolynomialRing(A) sage: C.<c> = PowerSeriesRing(B) sage: R.<x> = PolynomialRing(C) sage: f = a2*x^2 + c*x - a1*b sage: f.parent() Univariate Polynomial Ring in x over Power Series Ring in c over Univariate Polynomial Ring in b over Multivariate Polynomial Ring in a1, a2 over Integer Ring sage: f.integral() 1/3*a2*x^3 + 1/2*c*x^2 - a1*b*x sage: f.integral().parent() Univariate Polynomial Ring in x over Power Series Ring in c over Univariate Polynomial Ring in b over Multivariate Polynomial Ring in a1, a2 over Rational Field sage: g = 3*a2*x^2 + 2*c*x - a1*b sage: g.integral() a2*x^3 + c*x^2 - a1*b*x sage: g.integral().parent() Univariate Polynomial Ring in x over Power Series Ring in c over Univariate Polynomial Ring in b over Multivariate Polynomial Ring in a1, a2 over Rational Field
>>> from sage.all import * >>> A = PolynomialRing(ZZ, names=('a1', 'a2',)); (a1, a2,) = A._first_ngens(2) >>> B = PolynomialRing(A, names=('b',)); (b,) = B._first_ngens(1) >>> C = PowerSeriesRing(B, names=('c',)); (c,) = C._first_ngens(1) >>> R = PolynomialRing(C, names=('x',)); (x,) = R._first_ngens(1) >>> f = a2*x**Integer(2) + c*x - a1*b >>> f.parent() Univariate Polynomial Ring in x over Power Series Ring in c over Univariate Polynomial Ring in b over Multivariate Polynomial Ring in a1, a2 over Integer Ring >>> f.integral() 1/3*a2*x^3 + 1/2*c*x^2 - a1*b*x >>> f.integral().parent() Univariate Polynomial Ring in x over Power Series Ring in c over Univariate Polynomial Ring in b over Multivariate Polynomial Ring in a1, a2 over Rational Field >>> g = Integer(3)*a2*x**Integer(2) + Integer(2)*c*x - a1*b >>> g.integral() a2*x^3 + c*x^2 - a1*b*x >>> g.integral().parent() Univariate Polynomial Ring in x over Power Series Ring in c over Univariate Polynomial Ring in b over Multivariate Polynomial Ring in a1, a2 over Rational Field
A.<a1, a2> = PolynomialRing(ZZ) B.<b> = PolynomialRing(A) C.<c> = PowerSeriesRing(B) R.<x> = PolynomialRing(C) f = a2*x^2 + c*x - a1*b f.parent() f.integral() f.integral().parent() g = 3*a2*x^2 + 2*c*x - a1*b g.integral() g.integral().parent()
Integration with respect to a variable in the base ring:
sage: R.<x> = QQ[] sage: t = PolynomialRing(R,'t').gen() sage: f = x*t + 5*t^2 sage: f.integral(x) 5*x*t^2 + 1/2*x^2*t
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> t = PolynomialRing(R,'t').gen() >>> f = x*t + Integer(5)*t**Integer(2) >>> f.integral(x) 5*x*t^2 + 1/2*x^2*t
R.<x> = QQ[] t = PolynomialRing(R,'t').gen() f = x*t + 5*t^2 f.integral(x)
- inverse_mod(a, m)[source]¶
Invert the polynomial
a
with respect tom
, or raise aValueError
if no such inverse exists.The parameter
m
may be either a single polynomial or an ideal (for consistency withinverse_mod()
in other rings).See also
If you are only interested in the inverse modulo a monomial \(x^k\) then you might use the specialized method
inverse_series_trunc()
which is much faster.EXAMPLES:
sage: S.<t> = QQ[] sage: f = inverse_mod(t^2 + 1, t^3 + 1); f -1/2*t^2 - 1/2*t + 1/2 sage: f * (t^2 + 1) % (t^3 + 1) 1 sage: f = t.inverse_mod((t + 1)^7); f -t^6 - 7*t^5 - 21*t^4 - 35*t^3 - 35*t^2 - 21*t - 7 sage: (f * t) + (t + 1)^7 1 sage: t.inverse_mod(S.ideal((t + 1)^7)) == f True
>>> from sage.all import * >>> S = QQ['t']; (t,) = S._first_ngens(1) >>> f = inverse_mod(t**Integer(2) + Integer(1), t**Integer(3) + Integer(1)); f -1/2*t^2 - 1/2*t + 1/2 >>> f * (t**Integer(2) + Integer(1)) % (t**Integer(3) + Integer(1)) 1 >>> f = t.inverse_mod((t + Integer(1))**Integer(7)); f -t^6 - 7*t^5 - 21*t^4 - 35*t^3 - 35*t^2 - 21*t - 7 >>> (f * t) + (t + Integer(1))**Integer(7) 1 >>> t.inverse_mod(S.ideal((t + Integer(1))**Integer(7))) == f True
S.<t> = QQ[] f = inverse_mod(t^2 + 1, t^3 + 1); f f * (t^2 + 1) % (t^3 + 1) f = t.inverse_mod((t + 1)^7); f (f * t) + (t + 1)^7 t.inverse_mod(S.ideal((t + 1)^7)) == f
This also works over inexact rings, but note that due to rounding error the product may not always exactly equal the constant polynomial 1 and have extra terms with coefficients close to zero.
sage: # needs scipy sage.modules sage: R.<x> = RDF[] sage: epsilon = RDF(1).ulp()*50 # Allow an error of up to 50 ulp sage: f = inverse_mod(x^2 + 1, x^5 + x + 1); f # abs tol 1e-14 0.4*x^4 - 0.2*x^3 - 0.4*x^2 + 0.2*x + 0.8 sage: poly = f * (x^2 + 1) % (x^5 + x + 1) sage: # Remove noisy zero terms: sage: parent(poly)([0.0 if abs(c) <= epsilon else c ....: for c in poly.coefficients(sparse=False)]) 1.0 sage: f = inverse_mod(x^3 - x + 1, x - 2); f 0.14285714285714285 sage: f * (x^3 - x + 1) % (x - 2) 1.0 sage: g = 5*x^3 + x - 7; m = x^4 - 12*x + 13; f = inverse_mod(g, m); f -0.0319636125...*x^3 - 0.0383269759...*x^2 - 0.0463050900...*x + 0.346479687... sage: poly = f*g % m sage: # Remove noisy zero terms: sage: parent(poly)([0.0 if abs(c) <= epsilon else c # abs tol 1e-14 ....: for c in poly.coefficients(sparse=False)]) 1.0000000000000004
>>> from sage.all import * >>> # needs scipy sage.modules >>> R = RDF['x']; (x,) = R._first_ngens(1) >>> epsilon = RDF(Integer(1)).ulp()*Integer(50) # Allow an error of up to 50 ulp >>> f = inverse_mod(x**Integer(2) + Integer(1), x**Integer(5) + x + Integer(1)); f # abs tol 1e-14 0.4*x^4 - 0.2*x^3 - 0.4*x^2 + 0.2*x + 0.8 >>> poly = f * (x**Integer(2) + Integer(1)) % (x**Integer(5) + x + Integer(1)) >>> # Remove noisy zero terms: >>> parent(poly)([RealNumber('0.0') if abs(c) <= epsilon else c ... for c in poly.coefficients(sparse=False)]) 1.0 >>> f = inverse_mod(x**Integer(3) - x + Integer(1), x - Integer(2)); f 0.14285714285714285 >>> f * (x**Integer(3) - x + Integer(1)) % (x - Integer(2)) 1.0 >>> g = Integer(5)*x**Integer(3) + x - Integer(7); m = x**Integer(4) - Integer(12)*x + Integer(13); f = inverse_mod(g, m); f -0.0319636125...*x^3 - 0.0383269759...*x^2 - 0.0463050900...*x + 0.346479687... >>> poly = f*g % m >>> # Remove noisy zero terms: >>> parent(poly)([RealNumber('0.0') if abs(c) <= epsilon else c # abs tol 1e-14 ... for c in poly.coefficients(sparse=False)]) 1.0000000000000004
# needs scipy sage.modules R.<x> = RDF[] epsilon = RDF(1).ulp()*50 # Allow an error of up to 50 ulp f = inverse_mod(x^2 + 1, x^5 + x + 1); f # abs tol 1e-14 poly = f * (x^2 + 1) % (x^5 + x + 1) # Remove noisy zero terms: parent(poly)([0.0 if abs(c) <= epsilon else c for c in poly.coefficients(sparse=False)]) f = inverse_mod(x^3 - x + 1, x - 2); f f * (x^3 - x + 1) % (x - 2) g = 5*x^3 + x - 7; m = x^4 - 12*x + 13; f = inverse_mod(g, m); f poly = f*g % m # Remove noisy zero terms: parent(poly)([0.0 if abs(c) <= epsilon else c # abs tol 1e-14 for c in poly.coefficients(sparse=False)])
ALGORITHM: Solve the system \(as + mt = 1\), returning \(s\) as the inverse of \(a\) mod \(m\).
Uses the Euclidean algorithm for exact rings, and solves a linear system for the coefficients of \(s\) and \(t\) for inexact rings (as the Euclidean algorithm may not converge in that case).
AUTHORS:
Robert Bradshaw (2007-05-31)
- inverse_of_unit()[source]¶
EXAMPLES:
sage: R.<x> = QQ[] sage: f = x - 90283 sage: f.inverse_of_unit() Traceback (most recent call last): ... ArithmeticError: x - 90283 is not a unit in Univariate Polynomial Ring in x over Rational Field sage: f = R(-90283); g = f.inverse_of_unit(); g -1/90283 sage: parent(g) Univariate Polynomial Ring in x over Rational Field
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x - Integer(90283) >>> f.inverse_of_unit() Traceback (most recent call last): ... ArithmeticError: x - 90283 is not a unit in Univariate Polynomial Ring in x over Rational Field >>> f = R(-Integer(90283)); g = f.inverse_of_unit(); g -1/90283 >>> parent(g) Univariate Polynomial Ring in x over Rational Field
R.<x> = QQ[] f = x - 90283 f.inverse_of_unit() f = R(-90283); g = f.inverse_of_unit(); g parent(g)
- inverse_series_trunc(prec)[source]¶
Return a polynomial approximation of precision
prec
of the inverse series of this polynomial.See also
The method
inverse_mod()
allows more generally to invert this polynomial with respect to any ideal.EXAMPLES:
sage: x = polygen(ZZ) sage: s = (1 + x).inverse_series_trunc(5) sage: s x^4 - x^3 + x^2 - x + 1 sage: s * (1 + x) x^5 + 1
>>> from sage.all import * >>> x = polygen(ZZ) >>> s = (Integer(1) + x).inverse_series_trunc(Integer(5)) >>> s x^4 - x^3 + x^2 - x + 1 >>> s * (Integer(1) + x) x^5 + 1
x = polygen(ZZ) s = (1 + x).inverse_series_trunc(5) s s * (1 + x)
Note that the constant coefficient needs to be a unit:
sage: ZZx.<x> = ZZ[] sage: ZZxy.<y> = ZZx[] sage: (1+x + y**2).inverse_series_trunc(4) Traceback (most recent call last): ... ValueError: constant term x + 1 is not a unit sage: (1+x + y**2).change_ring(ZZx.fraction_field()).inverse_series_trunc(4) (-1/(x^2 + 2*x + 1))*y^2 + 1/(x + 1)
>>> from sage.all import * >>> ZZx = ZZ['x']; (x,) = ZZx._first_ngens(1) >>> ZZxy = ZZx['y']; (y,) = ZZxy._first_ngens(1) >>> (Integer(1)+x + y**Integer(2)).inverse_series_trunc(Integer(4)) Traceback (most recent call last): ... ValueError: constant term x + 1 is not a unit >>> (Integer(1)+x + y**Integer(2)).change_ring(ZZx.fraction_field()).inverse_series_trunc(Integer(4)) (-1/(x^2 + 2*x + 1))*y^2 + 1/(x + 1)
ZZx.<x> = ZZ[] ZZxy.<y> = ZZx[] (1+x + y**2).inverse_series_trunc(4) (1+x + y**2).change_ring(ZZx.fraction_field()).inverse_series_trunc(4)
The method works over any polynomial ring:
sage: R = Zmod(4) sage: Rx.<x> = R[] sage: Rxy.<y> = Rx[] sage: p = 1 + (1+2*x)*y + x**2*y**4 sage: q = p.inverse_series_trunc(10) sage: (p*q).truncate(11) (2*x^4 + 3*x^2 + 3)*y^10 + 1
>>> from sage.all import * >>> R = Zmod(Integer(4)) >>> Rx = R['x']; (x,) = Rx._first_ngens(1) >>> Rxy = Rx['y']; (y,) = Rxy._first_ngens(1) >>> p = Integer(1) + (Integer(1)+Integer(2)*x)*y + x**Integer(2)*y**Integer(4) >>> q = p.inverse_series_trunc(Integer(10)) >>> (p*q).truncate(Integer(11)) (2*x^4 + 3*x^2 + 3)*y^10 + 1
R = Zmod(4) Rx.<x> = R[] Rxy.<y> = Rx[] p = 1 + (1+2*x)*y + x**2*y**4 q = p.inverse_series_trunc(10) (p*q).truncate(11)
Even noncommutative ones:
sage: # needs sage.modules sage: M = MatrixSpace(ZZ, 2) sage: x = polygen(M) sage: p = M([1,2,3,4])*x^3 + M([-1,0,0,1])*x^2 + M([1,3,-1,0])*x + M.one() sage: q = p.inverse_series_trunc(5) sage: (p*q).truncate(5) == M.one() True sage: q = p.inverse_series_trunc(13) sage: (p*q).truncate(13) == M.one() True
>>> from sage.all import * >>> # needs sage.modules >>> M = MatrixSpace(ZZ, Integer(2)) >>> x = polygen(M) >>> p = M([Integer(1),Integer(2),Integer(3),Integer(4)])*x**Integer(3) + M([-Integer(1),Integer(0),Integer(0),Integer(1)])*x**Integer(2) + M([Integer(1),Integer(3),-Integer(1),Integer(0)])*x + M.one() >>> q = p.inverse_series_trunc(Integer(5)) >>> (p*q).truncate(Integer(5)) == M.one() True >>> q = p.inverse_series_trunc(Integer(13)) >>> (p*q).truncate(Integer(13)) == M.one() True
# needs sage.modules M = MatrixSpace(ZZ, 2) x = polygen(M) p = M([1,2,3,4])*x^3 + M([-1,0,0,1])*x^2 + M([1,3,-1,0])*x + M.one() q = p.inverse_series_trunc(5) (p*q).truncate(5) == M.one() q = p.inverse_series_trunc(13) (p*q).truncate(13) == M.one()
AUTHORS:
David Harvey (2006-09-09): Newton’s method implementation for power series
Vincent Delecroix (2014-2015): move the implementation directly in polynomial
- is_constant()[source]¶
Return
True
if this is a constant polynomial.OUTPUT: boolean;
True
if and only if this polynomial is constantEXAMPLES:
sage: R.<x> = ZZ[] sage: x.is_constant() False sage: R(2).is_constant() True sage: R(0).is_constant() True
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> x.is_constant() False >>> R(Integer(2)).is_constant() True >>> R(Integer(0)).is_constant() True
R.<x> = ZZ[] x.is_constant() R(2).is_constant() R(0).is_constant()
- is_cyclotomic(certificate=False, algorithm='pari')[source]¶
Test if this polynomial is a cyclotomic polynomial.
A cyclotomic polynomial is a monic, irreducible polynomial such that all roots are roots of unity.
By default the answer is a boolean. But if
certificate
isTrue
, the result is a nonnegative integer: it is0
ifself
is not cyclotomic, and a positive integern
ifself
is the \(n\)-th cyclotomic polynomial.INPUT:
certificate
– boolean (default:False
); only works withalgorithm
set to'pari'
algorithm
– either'pari'
(default) or'sage'
ALGORITHM:
The native algorithm implemented in Sage uses the first algorithm of [BD1989]. The algorithm in PARI (using pari:poliscyclo) is more subtle since it does compute the inverse of the Euler \(\phi\) function to determine the \(n\) such that the polynomial is the \(n\)-th cyclotomic polynomial.
EXAMPLES:
Quick tests:
sage: # needs sage.libs.pari sage: P.<x> = ZZ['x'] sage: (x - 1).is_cyclotomic() True sage: (x + 1).is_cyclotomic() True sage: (x^2 - 1).is_cyclotomic() False sage: (x^2 + x + 1).is_cyclotomic(certificate=True) 3 sage: (x^2 + 2*x + 1).is_cyclotomic(certificate=True) 0
>>> from sage.all import * >>> # needs sage.libs.pari >>> P = ZZ['x']; (x,) = P._first_ngens(1) >>> (x - Integer(1)).is_cyclotomic() True >>> (x + Integer(1)).is_cyclotomic() True >>> (x**Integer(2) - Integer(1)).is_cyclotomic() False >>> (x**Integer(2) + x + Integer(1)).is_cyclotomic(certificate=True) 3 >>> (x**Integer(2) + Integer(2)*x + Integer(1)).is_cyclotomic(certificate=True) 0
# needs sage.libs.pari P.<x> = ZZ['x'] (x - 1).is_cyclotomic() (x + 1).is_cyclotomic() (x^2 - 1).is_cyclotomic() (x^2 + x + 1).is_cyclotomic(certificate=True) (x^2 + 2*x + 1).is_cyclotomic(certificate=True)
Test first 100 cyclotomic polynomials:
sage: all(cyclotomic_polynomial(i).is_cyclotomic() for i in range(1, 101)) # needs sage.libs.pari True
>>> from sage.all import * >>> all(cyclotomic_polynomial(i).is_cyclotomic() for i in range(Integer(1), Integer(101))) # needs sage.libs.pari True
all(cyclotomic_polynomial(i).is_cyclotomic() for i in range(1, 101)) # needs sage.libs.pari
Some more tests:
sage: # needs sage.libs.pari sage: f = x^16 + x^14 - x^10 + x^8 - x^6 + x^2 + 1 sage: f.is_cyclotomic(algorithm='pari') False sage: f.is_cyclotomic(algorithm='sage') False sage: g = x^16 + x^14 - x^10 - x^8 - x^6 + x^2 + 1 sage: g.is_cyclotomic(algorithm='pari') True sage: g.is_cyclotomic(algorithm='sage') True sage: y = polygen(QQ) sage: (y/2 - 1/2).is_cyclotomic() False sage: (2*(y/2 - 1/2)).is_cyclotomic() # needs sage.libs.pari True
>>> from sage.all import * >>> # needs sage.libs.pari >>> f = x**Integer(16) + x**Integer(14) - x**Integer(10) + x**Integer(8) - x**Integer(6) + x**Integer(2) + Integer(1) >>> f.is_cyclotomic(algorithm='pari') False >>> f.is_cyclotomic(algorithm='sage') False >>> g = x**Integer(16) + x**Integer(14) - x**Integer(10) - x**Integer(8) - x**Integer(6) + x**Integer(2) + Integer(1) >>> g.is_cyclotomic(algorithm='pari') True >>> g.is_cyclotomic(algorithm='sage') True >>> y = polygen(QQ) >>> (y/Integer(2) - Integer(1)/Integer(2)).is_cyclotomic() False >>> (Integer(2)*(y/Integer(2) - Integer(1)/Integer(2))).is_cyclotomic() # needs sage.libs.pari True
# needs sage.libs.pari f = x^16 + x^14 - x^10 + x^8 - x^6 + x^2 + 1 f.is_cyclotomic(algorithm='pari') f.is_cyclotomic(algorithm='sage') g = x^16 + x^14 - x^10 - x^8 - x^6 + x^2 + 1 g.is_cyclotomic(algorithm='pari') g.is_cyclotomic(algorithm='sage') y = polygen(QQ) (y/2 - 1/2).is_cyclotomic() (2*(y/2 - 1/2)).is_cyclotomic() # needs sage.libs.pari
Invalid arguments:
sage: (x - 3).is_cyclotomic(algorithm='sage', certificate=True) # needs sage.libs.pari Traceback (most recent call last): ... ValueError: no implementation of the certificate within Sage
>>> from sage.all import * >>> (x - Integer(3)).is_cyclotomic(algorithm='sage', certificate=True) # needs sage.libs.pari Traceback (most recent call last): ... ValueError: no implementation of the certificate within Sage
(x - 3).is_cyclotomic(algorithm='sage', certificate=True) # needs sage.libs.pari
Test using other rings:
sage: z = polygen(GF(5)) sage: (z - 1).is_cyclotomic() Traceback (most recent call last): ... NotImplementedError: not implemented in nonzero characteristic
>>> from sage.all import * >>> z = polygen(GF(Integer(5))) >>> (z - Integer(1)).is_cyclotomic() Traceback (most recent call last): ... NotImplementedError: not implemented in nonzero characteristic
z = polygen(GF(5)) (z - 1).is_cyclotomic()
- is_cyclotomic_product()[source]¶
Test whether this polynomial is a product of cyclotomic polynomials.
This method simply calls the function pari:poliscycloprod from the Pari library.
EXAMPLES:
sage: x = polygen(ZZ) sage: (x^5 - 1).is_cyclotomic_product() # needs sage.libs.pari True sage: (x^5 + x^4 - x^2 + 1).is_cyclotomic_product() # needs sage.libs.pari False sage: p = prod(cyclotomic_polynomial(i) for i in [2, 5, 7, 12]) sage: p.is_cyclotomic_product() # needs sage.libs.pari True sage: (x^5 - 1/3).is_cyclotomic_product() False sage: x = polygen(Zmod(5)) sage: (x - 1).is_cyclotomic_product() Traceback (most recent call last): ... NotImplementedError: not implemented in nonzero characteristic
>>> from sage.all import * >>> x = polygen(ZZ) >>> (x**Integer(5) - Integer(1)).is_cyclotomic_product() # needs sage.libs.pari True >>> (x**Integer(5) + x**Integer(4) - x**Integer(2) + Integer(1)).is_cyclotomic_product() # needs sage.libs.pari False >>> p = prod(cyclotomic_polynomial(i) for i in [Integer(2), Integer(5), Integer(7), Integer(12)]) >>> p.is_cyclotomic_product() # needs sage.libs.pari True >>> (x**Integer(5) - Integer(1)/Integer(3)).is_cyclotomic_product() False >>> x = polygen(Zmod(Integer(5))) >>> (x - Integer(1)).is_cyclotomic_product() Traceback (most recent call last): ... NotImplementedError: not implemented in nonzero characteristic
x = polygen(ZZ) (x^5 - 1).is_cyclotomic_product() # needs sage.libs.pari (x^5 + x^4 - x^2 + 1).is_cyclotomic_product() # needs sage.libs.pari p = prod(cyclotomic_polynomial(i) for i in [2, 5, 7, 12]) p.is_cyclotomic_product() # needs sage.libs.pari (x^5 - 1/3).is_cyclotomic_product() x = polygen(Zmod(5)) (x - 1).is_cyclotomic_product()
- is_gen()[source]¶
Return
True
if this polynomial is the distinguished generator of the parent polynomial ring.EXAMPLES:
sage: R.<x> = QQ[] sage: R(1).is_gen() False sage: R(x).is_gen() True
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> R(Integer(1)).is_gen() False >>> R(x).is_gen() True
R.<x> = QQ[] R(1).is_gen() R(x).is_gen()
Important - this function doesn’t return
True
ifself
equals the generator; it returnsTrue
ifself
is the generator.sage: f = R([0,1]); f x sage: f.is_gen() False sage: f is x False sage: f == x True
>>> from sage.all import * >>> f = R([Integer(0),Integer(1)]); f x >>> f.is_gen() False >>> f is x False >>> f == x True
f = R([0,1]); f f.is_gen() f is x f == x
- is_homogeneous()[source]¶
Return
True
if this polynomial is homogeneous.EXAMPLES:
sage: P.<x> = PolynomialRing(QQ) sage: x.is_homogeneous() True sage: P(0).is_homogeneous() True sage: (x + 1).is_homogeneous() False
>>> from sage.all import * >>> P = PolynomialRing(QQ, names=('x',)); (x,) = P._first_ngens(1) >>> x.is_homogeneous() True >>> P(Integer(0)).is_homogeneous() True >>> (x + Integer(1)).is_homogeneous() False
P.<x> = PolynomialRing(QQ) x.is_homogeneous() P(0).is_homogeneous() (x + 1).is_homogeneous()
- is_irreducible()[source]¶
Return whether this polynomial is irreducible.
EXAMPLES:
sage: R.<x> = ZZ[] sage: (x^3 + 1).is_irreducible() # needs sage.libs.pari False sage: (x^2 - 1).is_irreducible() # needs sage.libs.pari False sage: (x^3 + 2).is_irreducible() # needs sage.libs.pari True sage: R(0).is_irreducible() False
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> (x**Integer(3) + Integer(1)).is_irreducible() # needs sage.libs.pari False >>> (x**Integer(2) - Integer(1)).is_irreducible() # needs sage.libs.pari False >>> (x**Integer(3) + Integer(2)).is_irreducible() # needs sage.libs.pari True >>> R(Integer(0)).is_irreducible() False
R.<x> = ZZ[] (x^3 + 1).is_irreducible() # needs sage.libs.pari (x^2 - 1).is_irreducible() # needs sage.libs.pari (x^3 + 2).is_irreducible() # needs sage.libs.pari R(0).is_irreducible()
The base ring does matter: for example, \(2x\) is irreducible as a polynomial in \(\QQ[x]\), but not in \(\ZZ[x]\):
sage: R.<x> = ZZ[] sage: R(2*x).is_irreducible() # needs sage.libs.pari False sage: R.<x> = QQ[] sage: R(2*x).is_irreducible() # needs sage.libs.pari True
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> R(Integer(2)*x).is_irreducible() # needs sage.libs.pari False >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> R(Integer(2)*x).is_irreducible() # needs sage.libs.pari True
R.<x> = ZZ[] R(2*x).is_irreducible() # needs sage.libs.pari R.<x> = QQ[] R(2*x).is_irreducible() # needs sage.libs.pari
- is_lorentzian(explain=False)[source]¶
Return
True
if this is a Lorentzian polynomial.A univariate real polynomial is Lorentzian if and only if it is a monomial with positive coefficient, or zero. The definition is more involved for multivariate real polynomials.
INPUT:
explain
– boolean (default:False
); ifTrue
return a tuple whose first element is the boolean result of the test, and the second element is a string describing the reason the test failed, orNone
if the test succeeded
EXAMPLES:
sage: P.<x> = QQ[] sage: p1 = x^2 sage: p1.is_lorentzian() True sage: p2 = 1 + x^2 sage: p2.is_lorentzian() False sage: p3 = P.zero() sage: p3.is_lorentzian() True sage: p4 = -2*x^3 sage: p4.is_lorentzian() False
>>> from sage.all import * >>> P = QQ['x']; (x,) = P._first_ngens(1) >>> p1 = x**Integer(2) >>> p1.is_lorentzian() True >>> p2 = Integer(1) + x**Integer(2) >>> p2.is_lorentzian() False >>> p3 = P.zero() >>> p3.is_lorentzian() True >>> p4 = -Integer(2)*x**Integer(3) >>> p4.is_lorentzian() False
P.<x> = QQ[] p1 = x^2 p1.is_lorentzian() p2 = 1 + x^2 p2.is_lorentzian() p3 = P.zero() p3.is_lorentzian() p4 = -2*x^3 p4.is_lorentzian()
It is an error to check if a polynomial is Lorentzian if its base ring is not a subring of the real numbers, as the notion is not defined in this case:
sage: # needs sage.rings.real_mpfr sage: Q.<y> = CC[] sage: q = y^2 sage: q.is_lorentzian() Traceback (most recent call last): ... NotImplementedError: is_lorentzian only implemented for real polynomials
>>> from sage.all import * >>> # needs sage.rings.real_mpfr >>> Q = CC['y']; (y,) = Q._first_ngens(1) >>> q = y**Integer(2) >>> q.is_lorentzian() Traceback (most recent call last): ... NotImplementedError: is_lorentzian only implemented for real polynomials
# needs sage.rings.real_mpfr Q.<y> = CC[] q = y^2 q.is_lorentzian()
The method can give a reason for a polynomial failing to be Lorentzian:
sage: p = x^2 + 2*x sage: p.is_lorentzian(explain=True) (False, 'inhomogeneous')
>>> from sage.all import * >>> p = x**Integer(2) + Integer(2)*x >>> p.is_lorentzian(explain=True) (False, 'inhomogeneous')
p = x^2 + 2*x p.is_lorentzian(explain=True)
REFERENCES:
For full definitions and related discussion, see [BrHu2019] and [HMMS2019].
- is_monic()[source]¶
Return
True
if this polynomial is monic. The zero polynomial is by definition not monic.EXAMPLES:
sage: x = QQ['x'].0 sage: f = x + 33 sage: f.is_monic() True sage: f = 0*x sage: f.is_monic() False sage: f = 3*x^3 + x^4 + x^2 sage: f.is_monic() True sage: f = 2*x^2 + x^3 + 56*x^5 sage: f.is_monic() False
>>> from sage.all import * >>> x = QQ['x'].gen(0) >>> f = x + Integer(33) >>> f.is_monic() True >>> f = Integer(0)*x >>> f.is_monic() False >>> f = Integer(3)*x**Integer(3) + x**Integer(4) + x**Integer(2) >>> f.is_monic() True >>> f = Integer(2)*x**Integer(2) + x**Integer(3) + Integer(56)*x**Integer(5) >>> f.is_monic() False
x = QQ['x'].0 f = x + 33 f.is_monic() f = 0*x f.is_monic() f = 3*x^3 + x^4 + x^2 f.is_monic() f = 2*x^2 + x^3 + 56*x^5 f.is_monic()
AUTHORS:
Naqi Jaffery (2006-01-24): examples
- is_monomial()[source]¶
Return
True
ifself
is a monomial, i.e., a power of the generator.EXAMPLES:
sage: R.<x> = QQ[] sage: x.is_monomial() True sage: (x + 1).is_monomial() False sage: (x^2).is_monomial() True sage: R(1).is_monomial() True
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> x.is_monomial() True >>> (x + Integer(1)).is_monomial() False >>> (x**Integer(2)).is_monomial() True >>> R(Integer(1)).is_monomial() True
R.<x> = QQ[] x.is_monomial() (x + 1).is_monomial() (x^2).is_monomial() R(1).is_monomial()
The coefficient must be 1:
sage: (2*x^5).is_monomial() False
>>> from sage.all import * >>> (Integer(2)*x**Integer(5)).is_monomial() False
(2*x^5).is_monomial()
To allow a non-1 leading coefficient, use
is_term()
:sage: (2*x^5).is_term() True
>>> from sage.all import * >>> (Integer(2)*x**Integer(5)).is_term() True
(2*x^5).is_term()
Warning
The definition of
is_monomial()
in Sage up to 4.7.1 was the same asis_term()
, i.e., it allowed a coefficient not equal to 1.
- is_nilpotent()[source]¶
Return
True
if this polynomial is nilpotent.EXAMPLES:
sage: R = Integers(12) sage: S.<x> = R[] sage: f = 5 + 6*x sage: f.is_nilpotent() False sage: f = 6 + 6*x^2 sage: f.is_nilpotent() True sage: f^2 0
>>> from sage.all import * >>> R = Integers(Integer(12)) >>> S = R['x']; (x,) = S._first_ngens(1) >>> f = Integer(5) + Integer(6)*x >>> f.is_nilpotent() False >>> f = Integer(6) + Integer(6)*x**Integer(2) >>> f.is_nilpotent() True >>> f**Integer(2) 0
R = Integers(12) S.<x> = R[] f = 5 + 6*x f.is_nilpotent() f = 6 + 6*x^2 f.is_nilpotent() f^2
EXERCISE (Atiyah-McDonald, Ch 1): Let \(A[x]\) be a polynomial ring in one variable. Then \(f=\sum a_i x^i \in A[x]\) is nilpotent if and only if every \(a_i\) is nilpotent.
- is_one()[source]¶
Test whether this polynomial is 1.
EXAMPLES:
sage: R.<x> = QQ[] sage: (x - 3).is_one() False sage: R(1).is_one() True sage: R2.<y> = R[] sage: R2(x).is_one() False sage: R2(1).is_one() True sage: R2(-1).is_one() False
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> (x - Integer(3)).is_one() False >>> R(Integer(1)).is_one() True >>> R2 = R['y']; (y,) = R2._first_ngens(1) >>> R2(x).is_one() False >>> R2(Integer(1)).is_one() True >>> R2(-Integer(1)).is_one() False
R.<x> = QQ[] (x - 3).is_one() R(1).is_one() R2.<y> = R[] R2(x).is_one() R2(1).is_one() R2(-1).is_one()
- is_primitive(n=None, n_prime_divs=None)[source]¶
Return
True
if the polynomial is primitive.The semantics of “primitive” depend on the polynomial coefficients.
(field theory) A polynomial of degree \(m\) over a finite field \(\GF{q}\) is primitive if it is irreducible and its root in \(\GF{q^m}\) generates the multiplicative group \(\GF{q^m}^*\).
(ring theory) A polynomial over a ring is primitive if its coefficients generate the unit ideal.
Calling
is_primitive()
on a polynomial over an infinite field will raise an error.The additional inputs to this function are to speed up computation for field semantics (see note).
INPUT:
n
– (default:None
) if provided, should equal \(q-1\) whereself.parent()
is the field with \(q\) elements; otherwise it will be computedn_prime_divs
– (default:None
) if provided, should be a list of the prime divisors of \(n\); otherwise it will be computed
Note
Computation of the prime divisors of \(n\) can dominate the running time of this method, so performing this computation externally (e.g.,
pdivs = n.prime_divisors()
) is a good idea for repeated calls tois_primitive()
for polynomials of the same degree.Results may be incorrect if the wrong \(n\) and/or factorization are provided.
EXAMPLES:
Field semantics examples.
sage: # needs sage.rings.finite_rings sage: R.<x> = GF(2)['x'] sage: f = x^4 + x^3 + x^2 + x + 1 sage: f.is_irreducible(), f.is_primitive() (True, False) sage: f = x^3 + x + 1 sage: f.is_irreducible(), f.is_primitive() (True, True) sage: R.<x> = GF(3)[] sage: f = x^3 - x + 1 sage: f.is_irreducible(), f.is_primitive() (True, True) sage: f = x^2 + 1 sage: f.is_irreducible(), f.is_primitive() (True, False) sage: R.<x> = GF(5)[] sage: f = x^2 + x + 1 sage: f.is_primitive() False sage: f = x^2 - x + 2 sage: f.is_primitive() True sage: x = polygen(QQ); f = x^2 + 1 sage: f.is_primitive() Traceback (most recent call last): ... NotImplementedError: is_primitive() not defined for polynomials over infinite fields.
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> R = GF(Integer(2))['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(4) + x**Integer(3) + x**Integer(2) + x + Integer(1) >>> f.is_irreducible(), f.is_primitive() (True, False) >>> f = x**Integer(3) + x + Integer(1) >>> f.is_irreducible(), f.is_primitive() (True, True) >>> R = GF(Integer(3))['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) - x + Integer(1) >>> f.is_irreducible(), f.is_primitive() (True, True) >>> f = x**Integer(2) + Integer(1) >>> f.is_irreducible(), f.is_primitive() (True, False) >>> R = GF(Integer(5))['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) + x + Integer(1) >>> f.is_primitive() False >>> f = x**Integer(2) - x + Integer(2) >>> f.is_primitive() True >>> x = polygen(QQ); f = x**Integer(2) + Integer(1) >>> f.is_primitive() Traceback (most recent call last): ... NotImplementedError: is_primitive() not defined for polynomials over infinite fields.
# needs sage.rings.finite_rings R.<x> = GF(2)['x'] f = x^4 + x^3 + x^2 + x + 1 f.is_irreducible(), f.is_primitive() f = x^3 + x + 1 f.is_irreducible(), f.is_primitive() R.<x> = GF(3)[] f = x^3 - x + 1 f.is_irreducible(), f.is_primitive() f = x^2 + 1 f.is_irreducible(), f.is_primitive() R.<x> = GF(5)[] f = x^2 + x + 1 f.is_primitive() f = x^2 - x + 2 f.is_primitive() x = polygen(QQ); f = x^2 + 1 f.is_primitive()
Ring semantics examples.
sage: x = polygen(ZZ) sage: f = 5*x^2 + 2 sage: f.is_primitive() True sage: f = 5*x^2 + 5 sage: f.is_primitive() False sage: # needs sage.rings.number_field sage: K = NumberField(x^2 + 5, 'a') sage: R = K.ring_of_integers() sage: a = R.gen(1) sage: a^2 -5 sage: f = a*x + 2 sage: f.is_primitive() True sage: f = (1+a)*x + 2 sage: f.is_primitive() False sage: x = polygen(Integers(10)) sage: f = 5*x^2 + 2 sage: #f.is_primitive() #BUG:: elsewhere in Sage, should return True sage: f = 4*x^2 + 2 sage: #f.is_primitive() #BUG:: elsewhere in Sage, should return False
>>> from sage.all import * >>> x = polygen(ZZ) >>> f = Integer(5)*x**Integer(2) + Integer(2) >>> f.is_primitive() True >>> f = Integer(5)*x**Integer(2) + Integer(5) >>> f.is_primitive() False >>> # needs sage.rings.number_field >>> K = NumberField(x**Integer(2) + Integer(5), 'a') >>> R = K.ring_of_integers() >>> a = R.gen(Integer(1)) >>> a**Integer(2) -5 >>> f = a*x + Integer(2) >>> f.is_primitive() True >>> f = (Integer(1)+a)*x + Integer(2) >>> f.is_primitive() False >>> x = polygen(Integers(Integer(10))) >>> f = Integer(5)*x**Integer(2) + Integer(2) >>> #f.is_primitive() #BUG:: elsewhere in Sage, should return True >>> f = Integer(4)*x**Integer(2) + Integer(2) >>> #f.is_primitive() #BUG:: elsewhere in Sage, should return False
x = polygen(ZZ) f = 5*x^2 + 2 f.is_primitive() f = 5*x^2 + 5 f.is_primitive() # needs sage.rings.number_field K = NumberField(x^2 + 5, 'a') R = K.ring_of_integers() a = R.gen(1) a^2 f = a*x + 2 f.is_primitive() f = (1+a)*x + 2 f.is_primitive() x = polygen(Integers(10)) f = 5*x^2 + 2 #f.is_primitive() #BUG:: elsewhere in Sage, should return True f = 4*x^2 + 2 #f.is_primitive() #BUG:: elsewhere in Sage, should return False
- is_real_rooted()[source]¶
Return
True
if the roots of this polynomial are all real.EXAMPLES:
sage: # needs sage.libs.pari sage: R.<x> = PolynomialRing(ZZ) sage: pol = chebyshev_T(5, x) sage: pol.is_real_rooted() True sage: pol = x^2 + 1 sage: pol.is_real_rooted() False
>>> from sage.all import * >>> # needs sage.libs.pari >>> R = PolynomialRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> pol = chebyshev_T(Integer(5), x) >>> pol.is_real_rooted() True >>> pol = x**Integer(2) + Integer(1) >>> pol.is_real_rooted() False
# needs sage.libs.pari R.<x> = PolynomialRing(ZZ) pol = chebyshev_T(5, x) pol.is_real_rooted() pol = x^2 + 1 pol.is_real_rooted()
- is_square(root=False)[source]¶
Return whether or not polynomial is square.
If the optional argument
root
is set toTrue
, then also returns the square root (orNone
, if the polynomial is not square).INPUT:
root
– whether or not to also return a square root (default:False
)
OUTPUT:
boolean; whether or not a square
(optional) an actual square root if found, and
None
otherwise
EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: (x^2 + 2*x + 1).is_square() True sage: (x^4 + 2*x^3 - x^2 - 2*x + 1).is_square(root=True) (True, x^2 + x - 1) sage: f = 12 * (x + 1)^2 * (x + 3)^2 sage: f.is_square() False sage: f.is_square(root=True) (False, None) sage: h = f/3; h 4*x^4 + 32*x^3 + 88*x^2 + 96*x + 36 sage: h.is_square(root=True) (True, 2*x^2 + 8*x + 6) sage: S.<y> = PolynomialRing(RR) sage: g = 12 * (y + 1)^2 * (y + 3)^2 sage: g.is_square() True
>>> from sage.all import * >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> (x**Integer(2) + Integer(2)*x + Integer(1)).is_square() True >>> (x**Integer(4) + Integer(2)*x**Integer(3) - x**Integer(2) - Integer(2)*x + Integer(1)).is_square(root=True) (True, x^2 + x - 1) >>> f = Integer(12) * (x + Integer(1))**Integer(2) * (x + Integer(3))**Integer(2) >>> f.is_square() False >>> f.is_square(root=True) (False, None) >>> h = f/Integer(3); h 4*x^4 + 32*x^3 + 88*x^2 + 96*x + 36 >>> h.is_square(root=True) (True, 2*x^2 + 8*x + 6) >>> S = PolynomialRing(RR, names=('y',)); (y,) = S._first_ngens(1) >>> g = Integer(12) * (y + Integer(1))**Integer(2) * (y + Integer(3))**Integer(2) >>> g.is_square() True
R.<x> = PolynomialRing(QQ) (x^2 + 2*x + 1).is_square() (x^4 + 2*x^3 - x^2 - 2*x + 1).is_square(root=True) f = 12 * (x + 1)^2 * (x + 3)^2 f.is_square() f.is_square(root=True) h = f/3; h h.is_square(root=True) S.<y> = PolynomialRing(RR) g = 12 * (y + 1)^2 * (y + 3)^2 g.is_square()
- is_squarefree()[source]¶
Return
False
if this polynomial is not square-free, i.e., if there is a non-unit \(g\) in the polynomial ring such that \(g^2\) dividesself
.Warning
This method is not consistent with
squarefree_decomposition()
since the latter does not factor the content of a polynomial. See the examples below.EXAMPLES:
sage: R.<x> = QQ[] sage: f = (x-1) * (x-2) * (x^2-5) * (x^17-3); f x^21 - 3*x^20 - 3*x^19 + 15*x^18 - 10*x^17 - 3*x^4 + 9*x^3 + 9*x^2 - 45*x + 30 sage: f.is_squarefree() True sage: (f * (x^2-5)).is_squarefree() False
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = (x-Integer(1)) * (x-Integer(2)) * (x**Integer(2)-Integer(5)) * (x**Integer(17)-Integer(3)); f x^21 - 3*x^20 - 3*x^19 + 15*x^18 - 10*x^17 - 3*x^4 + 9*x^3 + 9*x^2 - 45*x + 30 >>> f.is_squarefree() True >>> (f * (x**Integer(2)-Integer(5))).is_squarefree() False
R.<x> = QQ[] f = (x-1) * (x-2) * (x^2-5) * (x^17-3); f f.is_squarefree() (f * (x^2-5)).is_squarefree()
A generic implementation is available, which relies on gcd computations:
sage: # needs sage.libs.pari sage: R.<x> = ZZ[] sage: (2*x).is_squarefree() True sage: (4*x).is_squarefree() False sage: (2*x^2).is_squarefree() False sage: R(0).is_squarefree() False sage: S.<y> = QQ[] sage: R.<x> = S[] sage: (2*x*y).is_squarefree() True sage: (2*x*y^2).is_squarefree() False
>>> from sage.all import * >>> # needs sage.libs.pari >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> (Integer(2)*x).is_squarefree() True >>> (Integer(4)*x).is_squarefree() False >>> (Integer(2)*x**Integer(2)).is_squarefree() False >>> R(Integer(0)).is_squarefree() False >>> S = QQ['y']; (y,) = S._first_ngens(1) >>> R = S['x']; (x,) = R._first_ngens(1) >>> (Integer(2)*x*y).is_squarefree() True >>> (Integer(2)*x*y**Integer(2)).is_squarefree() False
# needs sage.libs.pari R.<x> = ZZ[] (2*x).is_squarefree() (4*x).is_squarefree() (2*x^2).is_squarefree() R(0).is_squarefree() S.<y> = QQ[] R.<x> = S[] (2*x*y).is_squarefree() (2*x*y^2).is_squarefree()
In positive characteristic, we compute the square-free decomposition or a full factorization, depending on which is available:
sage: K.<t> = FunctionField(GF(3)) sage: R.<x> = K[] sage: (x^3 - x).is_squarefree() True sage: (x^3 - 1).is_squarefree() # needs sage.libs.pari False sage: (x^3 + t).is_squarefree() # needs sage.libs.pari True sage: (x^3 + t^3).is_squarefree() # needs sage.libs.pari False
>>> from sage.all import * >>> K = FunctionField(GF(Integer(3)), names=('t',)); (t,) = K._first_ngens(1) >>> R = K['x']; (x,) = R._first_ngens(1) >>> (x**Integer(3) - x).is_squarefree() True >>> (x**Integer(3) - Integer(1)).is_squarefree() # needs sage.libs.pari False >>> (x**Integer(3) + t).is_squarefree() # needs sage.libs.pari True >>> (x**Integer(3) + t**Integer(3)).is_squarefree() # needs sage.libs.pari False
K.<t> = FunctionField(GF(3)) R.<x> = K[] (x^3 - x).is_squarefree() (x^3 - 1).is_squarefree() # needs sage.libs.pari (x^3 + t).is_squarefree() # needs sage.libs.pari (x^3 + t^3).is_squarefree() # needs sage.libs.pari
In the following example, \(t^2\) is a unit in the base field:
sage: R(t^2).is_squarefree() True
>>> from sage.all import * >>> R(t**Integer(2)).is_squarefree() True
R(t^2).is_squarefree()
This method is not consistent with
squarefree_decomposition()
:sage: R.<x> = ZZ[] sage: f = 4 * x sage: f.is_squarefree() # needs sage.libs.pari False sage: f.squarefree_decomposition() # needs sage.libs.pari (4) * x
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = Integer(4) * x >>> f.is_squarefree() # needs sage.libs.pari False >>> f.squarefree_decomposition() # needs sage.libs.pari (4) * x
R.<x> = ZZ[] f = 4 * x f.is_squarefree() # needs sage.libs.pari f.squarefree_decomposition() # needs sage.libs.pari
If you want this method equally not to consider the content, you can remove it as in the following example:
sage: c = f.content() sage: (f/c).is_squarefree() # needs sage.libs.pari True
>>> from sage.all import * >>> c = f.content() >>> (f/c).is_squarefree() # needs sage.libs.pari True
c = f.content() (f/c).is_squarefree() # needs sage.libs.pari
If the base ring is not an integral domain, the question is not mathematically well-defined:
sage: R.<x> = IntegerModRing(9)[] sage: pol = (x + 3) * (x + 6); pol x^2 sage: pol.is_squarefree() Traceback (most recent call last): ... TypeError: is_squarefree() is not defined for polynomials over Ring of integers modulo 9
>>> from sage.all import * >>> R = IntegerModRing(Integer(9))['x']; (x,) = R._first_ngens(1) >>> pol = (x + Integer(3)) * (x + Integer(6)); pol x^2 >>> pol.is_squarefree() Traceback (most recent call last): ... TypeError: is_squarefree() is not defined for polynomials over Ring of integers modulo 9
R.<x> = IntegerModRing(9)[] pol = (x + 3) * (x + 6); pol pol.is_squarefree()
- is_term()[source]¶
Return
True
if this polynomial is a nonzero element of the base ring times a power of the variable.EXAMPLES:
sage: R.<x> = QQ[] sage: x.is_term() True sage: R(0).is_term() False sage: R(1).is_term() True sage: (3*x^5).is_term() True sage: (1 + 3*x^5).is_term() False
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> x.is_term() True >>> R(Integer(0)).is_term() False >>> R(Integer(1)).is_term() True >>> (Integer(3)*x**Integer(5)).is_term() True >>> (Integer(1) + Integer(3)*x**Integer(5)).is_term() False
R.<x> = QQ[] x.is_term() R(0).is_term() R(1).is_term() (3*x^5).is_term() (1 + 3*x^5).is_term()
To require that the coefficient is 1, use
is_monomial()
instead:sage: (3*x^5).is_monomial() False
>>> from sage.all import * >>> (Integer(3)*x**Integer(5)).is_monomial() False
(3*x^5).is_monomial()
- is_unit()[source]¶
Return
True
if this polynomial is a unit.EXAMPLES:
sage: a = Integers(90384098234^3) sage: b = a(2*191*236607587) sage: b.is_nilpotent() True sage: # needs sage.libs.pari sage: R.<x> = a[] sage: f = 3 + b*x + b^2*x^2 sage: f.is_unit() True sage: f = 3 + b*x + b^2*x^2 + 17*x^3 sage: f.is_unit() False
>>> from sage.all import * >>> a = Integers(Integer(90384098234)**Integer(3)) >>> b = a(Integer(2)*Integer(191)*Integer(236607587)) >>> b.is_nilpotent() True >>> # needs sage.libs.pari >>> R = a['x']; (x,) = R._first_ngens(1) >>> f = Integer(3) + b*x + b**Integer(2)*x**Integer(2) >>> f.is_unit() True >>> f = Integer(3) + b*x + b**Integer(2)*x**Integer(2) + Integer(17)*x**Integer(3) >>> f.is_unit() False
a = Integers(90384098234^3) b = a(2*191*236607587) b.is_nilpotent() # needs sage.libs.pari R.<x> = a[] f = 3 + b*x + b^2*x^2 f.is_unit() f = 3 + b*x + b^2*x^2 + 17*x^3 f.is_unit()
EXERCISE (Atiyah-McDonald, Ch 1): Let \(A[x]\) be a polynomial ring in one variable. Then \(f=\sum a_i x^i \in A[x]\) is a unit if and only if \(a_0\) is a unit and \(a_1,\ldots, a_n\) are nilpotent.
- is_weil_polynomial(return_q=False)[source]¶
Return
True
if this is a Weil polynomial.This polynomial must have rational or integer coefficients.
INPUT:
self
– polynomial with rational or integer coefficientsreturn_q
– (default:False
) ifTrue
, return a second value \(q\) which is the prime power with respect to which this is \(q\)-Weil, or 0 if there is no such value
EXAMPLES:
sage: polRing.<x> = PolynomialRing(Rationals()) sage: P0 = x^4 + 5*x^3 + 15*x^2 + 25*x + 25 sage: P1 = x^4 + 25*x^3 + 15*x^2 + 5*x + 25 sage: P2 = x^4 + 5*x^3 + 25*x^2 + 25*x + 25 sage: P0.is_weil_polynomial(return_q=True) # needs sage.libs.pari (True, 5) sage: P0.is_weil_polynomial(return_q=False) # needs sage.libs.pari True sage: P1.is_weil_polynomial(return_q=True) (False, 0) sage: P1.is_weil_polynomial(return_q=False) False sage: P2.is_weil_polynomial() # needs sage.libs.pari False
>>> from sage.all import * >>> polRing = PolynomialRing(Rationals(), names=('x',)); (x,) = polRing._first_ngens(1) >>> P0 = x**Integer(4) + Integer(5)*x**Integer(3) + Integer(15)*x**Integer(2) + Integer(25)*x + Integer(25) >>> P1 = x**Integer(4) + Integer(25)*x**Integer(3) + Integer(15)*x**Integer(2) + Integer(5)*x + Integer(25) >>> P2 = x**Integer(4) + Integer(5)*x**Integer(3) + Integer(25)*x**Integer(2) + Integer(25)*x + Integer(25) >>> P0.is_weil_polynomial(return_q=True) # needs sage.libs.pari (True, 5) >>> P0.is_weil_polynomial(return_q=False) # needs sage.libs.pari True >>> P1.is_weil_polynomial(return_q=True) (False, 0) >>> P1.is_weil_polynomial(return_q=False) False >>> P2.is_weil_polynomial() # needs sage.libs.pari False
polRing.<x> = PolynomialRing(Rationals()) P0 = x^4 + 5*x^3 + 15*x^2 + 25*x + 25 P1 = x^4 + 25*x^3 + 15*x^2 + 5*x + 25 P2 = x^4 + 5*x^3 + 25*x^2 + 25*x + 25 P0.is_weil_polynomial(return_q=True) # needs sage.libs.pari P0.is_weil_polynomial(return_q=False) # needs sage.libs.pari P1.is_weil_polynomial(return_q=True) P1.is_weil_polynomial(return_q=False) P2.is_weil_polynomial() # needs sage.libs.pari
See also
Polynomial rings have a method
weil_polynomials()
to compute sets of Weil polynomials. This computation uses the iteratorsage.rings.polynomial.weil.weil_polynomials.WeilPolynomials
.AUTHORS:
David Zureick-Brown (2017-10-01)
- is_zero()[source]¶
Test whether this polynomial is zero.
EXAMPLES:
sage: R = GF(2)['x']['y'] sage: R([0,1]).is_zero() False sage: R([0]).is_zero() True sage: R([-1]).is_zero() False
>>> from sage.all import * >>> R = GF(Integer(2))['x']['y'] >>> R([Integer(0),Integer(1)]).is_zero() False >>> R([Integer(0)]).is_zero() True >>> R([-Integer(1)]).is_zero() False
R = GF(2)['x']['y'] R([0,1]).is_zero() R([0]).is_zero() R([-1]).is_zero()
- lc()[source]¶
Return the leading coefficient of this polynomial.
OUTPUT: element of the base ring
This method is the same as
leading_coefficient()
.EXAMPLES:
sage: R.<x> = QQ[] sage: f = (-2/5)*x^3 + 2*x - 1/3 sage: f.lc() -2/5
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = (-Integer(2)/Integer(5))*x**Integer(3) + Integer(2)*x - Integer(1)/Integer(3) >>> f.lc() -2/5
R.<x> = QQ[] f = (-2/5)*x^3 + 2*x - 1/3 f.lc()
- lcm(other)[source]¶
Let \(f\) and \(g\) be two polynomials. Then this function returns the monic least common multiple of \(f\) and \(g\).
- leading_coefficient()[source]¶
Return the leading coefficient of this polynomial.
OUTPUT: element of the base ring
EXAMPLES:
sage: R.<x> = QQ[] sage: f = (-2/5)*x^3 + 2*x - 1/3 sage: f.leading_coefficient() -2/5
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = (-Integer(2)/Integer(5))*x**Integer(3) + Integer(2)*x - Integer(1)/Integer(3) >>> f.leading_coefficient() -2/5
R.<x> = QQ[] f = (-2/5)*x^3 + 2*x - 1/3 f.leading_coefficient()
- list(copy=True)[source]¶
Return a new copy of the list of the underlying elements of
self
.EXAMPLES:
sage: R.<x> = QQ[] sage: f = (-2/5)*x^3 + 2*x - 1/3 sage: v = f.list(); v [-1/3, 2, 0, -2/5]
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = (-Integer(2)/Integer(5))*x**Integer(3) + Integer(2)*x - Integer(1)/Integer(3) >>> v = f.list(); v [-1/3, 2, 0, -2/5]
R.<x> = QQ[] f = (-2/5)*x^3 + 2*x - 1/3 v = f.list(); v
Note that
v
is a list, it is mutable, and each call to thelist()
method returns a new list:sage: type(v) <... 'list'> sage: v[0] = 5 sage: f.list() [-1/3, 2, 0, -2/5]
>>> from sage.all import * >>> type(v) <... 'list'> >>> v[Integer(0)] = Integer(5) >>> f.list() [-1/3, 2, 0, -2/5]
type(v) v[0] = 5 f.list()
Here is an example with a generic polynomial ring:
sage: R.<x> = QQ[] sage: S.<y> = R[] sage: f = y^3 + x*y - 3*x; f y^3 + x*y - 3*x sage: type(f) <class 'sage.rings.polynomial.polynomial_element.Polynomial_generic_dense'> sage: v = f.list(); v [-3*x, x, 0, 1] sage: v[0] = 10 sage: f.list() [-3*x, x, 0, 1]
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> S = R['y']; (y,) = S._first_ngens(1) >>> f = y**Integer(3) + x*y - Integer(3)*x; f y^3 + x*y - 3*x >>> type(f) <class 'sage.rings.polynomial.polynomial_element.Polynomial_generic_dense'> >>> v = f.list(); v [-3*x, x, 0, 1] >>> v[Integer(0)] = Integer(10) >>> f.list() [-3*x, x, 0, 1]
R.<x> = QQ[] S.<y> = R[] f = y^3 + x*y - 3*x; f type(f) v = f.list(); v v[0] = 10 f.list()
- lm()[source]¶
Return the leading monomial of this polynomial.
EXAMPLES:
sage: R.<x> = QQ[] sage: f = (-2/5)*x^3 + 2*x - 1/3 sage: f.lm() x^3 sage: R(5).lm() 1 sage: R(0).lm() 0 sage: R(0).lm().parent() is R True
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = (-Integer(2)/Integer(5))*x**Integer(3) + Integer(2)*x - Integer(1)/Integer(3) >>> f.lm() x^3 >>> R(Integer(5)).lm() 1 >>> R(Integer(0)).lm() 0 >>> R(Integer(0)).lm().parent() is R True
R.<x> = QQ[] f = (-2/5)*x^3 + 2*x - 1/3 f.lm() R(5).lm() R(0).lm() R(0).lm().parent() is R
- local_height(v, prec=None)[source]¶
Return the maximum of the local height of the coefficients of this polynomial.
INPUT:
v
– a prime or prime ideal of the base ringprec
– desired floating point precision (default: defaultRealField
precision)
OUTPUT: a real number
EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: f = 1/1331*x^2 + 1/4000*x sage: f.local_height(1331) # needs sage.rings.real_mpfr 7.19368581839511
>>> from sage.all import * >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> f = Integer(1)/Integer(1331)*x**Integer(2) + Integer(1)/Integer(4000)*x >>> f.local_height(Integer(1331)) # needs sage.rings.real_mpfr 7.19368581839511
R.<x> = PolynomialRing(QQ) f = 1/1331*x^2 + 1/4000*x f.local_height(1331) # needs sage.rings.real_mpfr
sage: # needs sage.rings.number_field sage: R.<x> = QQ[] sage: K.<k> = NumberField(x^2 - 5) sage: T.<t> = K[] sage: I = K.ideal(3) sage: f = 1/3*t^2 + 3 sage: f.local_height(I) 1.09861228866811
>>> from sage.all import * >>> # needs sage.rings.number_field >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> K = NumberField(x**Integer(2) - Integer(5), names=('k',)); (k,) = K._first_ngens(1) >>> T = K['t']; (t,) = T._first_ngens(1) >>> I = K.ideal(Integer(3)) >>> f = Integer(1)/Integer(3)*t**Integer(2) + Integer(3) >>> f.local_height(I) 1.09861228866811
# needs sage.rings.number_field R.<x> = QQ[] K.<k> = NumberField(x^2 - 5) T.<t> = K[] I = K.ideal(3) f = 1/3*t^2 + 3 f.local_height(I)
>>> from sage.all import * >>> # needs sage.rings.number_field >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> K = NumberField(x**Integer(2) - Integer(5), names=('k',)); (k,) = K._first_ngens(1) >>> T = K['t']; (t,) = T._first_ngens(1) >>> I = K.ideal(Integer(3)) >>> f = Integer(1)/Integer(3)*t**Integer(2) + Integer(3) >>> f.local_height(I) 1.09861228866811
# needs sage.rings.number_field R.<x> = QQ[] K.<k> = NumberField(x^2 - 5) T.<t> = K[] I = K.ideal(3) f = 1/3*t^2 + 3 f.local_height(I)
sage: R.<x> = QQ[] sage: f = 1/2*x^2 + 2 sage: f.local_height(2, prec=2) # needs sage.rings.real_mpfr 0.75
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = Integer(1)/Integer(2)*x**Integer(2) + Integer(2) >>> f.local_height(Integer(2), prec=Integer(2)) # needs sage.rings.real_mpfr 0.75
R.<x> = QQ[] f = 1/2*x^2 + 2 f.local_height(2, prec=2) # needs sage.rings.real_mpfr
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = Integer(1)/Integer(2)*x**Integer(2) + Integer(2) >>> f.local_height(Integer(2), prec=Integer(2)) # needs sage.rings.real_mpfr 0.75
R.<x> = QQ[] f = 1/2*x^2 + 2 f.local_height(2, prec=2) # needs sage.rings.real_mpfr
- local_height_arch(i, prec=None)[source]¶
Return the maximum of the local height at the
i
-th infinite place of the coefficients of this polynomial.INPUT:
i
– integerprec
– desired floating point precision (default: defaultRealField
precision)
OUTPUT: a real number
EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: f = 210*x^2 sage: f.local_height_arch(0) # needs sage.rings.real_mpfr 5.34710753071747
>>> from sage.all import * >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> f = Integer(210)*x**Integer(2) >>> f.local_height_arch(Integer(0)) # needs sage.rings.real_mpfr 5.34710753071747
R.<x> = PolynomialRing(QQ) f = 210*x^2 f.local_height_arch(0) # needs sage.rings.real_mpfr
sage: # needs sage.rings.number_field sage: R.<x> = QQ[] sage: K.<k> = NumberField(x^2 - 5) sage: T.<t> = K[] sage: f = 1/2*t^2 + 3 sage: f.local_height_arch(1, prec=52) 1.09861228866811
>>> from sage.all import * >>> # needs sage.rings.number_field >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> K = NumberField(x**Integer(2) - Integer(5), names=('k',)); (k,) = K._first_ngens(1) >>> T = K['t']; (t,) = T._first_ngens(1) >>> f = Integer(1)/Integer(2)*t**Integer(2) + Integer(3) >>> f.local_height_arch(Integer(1), prec=Integer(52)) 1.09861228866811
# needs sage.rings.number_field R.<x> = QQ[] K.<k> = NumberField(x^2 - 5) T.<t> = K[] f = 1/2*t^2 + 3 f.local_height_arch(1, prec=52)
>>> from sage.all import * >>> # needs sage.rings.number_field >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> K = NumberField(x**Integer(2) - Integer(5), names=('k',)); (k,) = K._first_ngens(1) >>> T = K['t']; (t,) = T._first_ngens(1) >>> f = Integer(1)/Integer(2)*t**Integer(2) + Integer(3) >>> f.local_height_arch(Integer(1), prec=Integer(52)) 1.09861228866811
# needs sage.rings.number_field R.<x> = QQ[] K.<k> = NumberField(x^2 - 5) T.<t> = K[] f = 1/2*t^2 + 3 f.local_height_arch(1, prec=52)
sage: R.<x> = QQ[] sage: f = 1/2*x^2 + 3 sage: f.local_height_arch(0, prec=2) # needs sage.rings.real_mpfr 1.0
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = Integer(1)/Integer(2)*x**Integer(2) + Integer(3) >>> f.local_height_arch(Integer(0), prec=Integer(2)) # needs sage.rings.real_mpfr 1.0
R.<x> = QQ[] f = 1/2*x^2 + 3 f.local_height_arch(0, prec=2) # needs sage.rings.real_mpfr
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = Integer(1)/Integer(2)*x**Integer(2) + Integer(3) >>> f.local_height_arch(Integer(0), prec=Integer(2)) # needs sage.rings.real_mpfr 1.0
R.<x> = QQ[] f = 1/2*x^2 + 3 f.local_height_arch(0, prec=2) # needs sage.rings.real_mpfr
- lt()[source]¶
Return the leading term of this polynomial.
EXAMPLES:
sage: R.<x> = QQ[] sage: f = (-2/5)*x^3 + 2*x - 1/3 sage: f.lt() -2/5*x^3 sage: R(5).lt() 5 sage: R(0).lt() 0 sage: R(0).lt().parent() is R True
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = (-Integer(2)/Integer(5))*x**Integer(3) + Integer(2)*x - Integer(1)/Integer(3) >>> f.lt() -2/5*x^3 >>> R(Integer(5)).lt() 5 >>> R(Integer(0)).lt() 0 >>> R(Integer(0)).lt().parent() is R True
R.<x> = QQ[] f = (-2/5)*x^3 + 2*x - 1/3 f.lt() R(5).lt() R(0).lt() R(0).lt().parent() is R
- map_coefficients(f, new_base_ring=None)[source]¶
Return the polynomial obtained by applying
f
to the nonzero coefficients ofself
.If
f
is asage.categories.map.Map
, then the resulting polynomial will be defined over the codomain off
. Otherwise, the resulting polynomial will be over the same ring asself
. Setnew_base_ring
to override this behaviour.INPUT:
f
– a callable that will be applied to the coefficients ofself
new_base_ring
– (optional) if given, the resulting polynomial will be defined over this ring
EXAMPLES:
sage: R.<x> = ZZ[] sage: f = x^2 + 2 sage: f.map_coefficients(lambda a: a + 42) 43*x^2 + 44 sage: R.<x> = PolynomialRing(ZZ, sparse=True) sage: f = x^(2^32) + 2 sage: f.map_coefficients(lambda a: a + 42) 43*x^4294967296 + 44 sage: # needs sage.symbolic sage: R.<x> = SR[] sage: f = (1+I)*x^2 + 3*x - I sage: f.map_coefficients(lambda z: z.conjugate()) (-I + 1)*x^2 + 3*x + I sage: R.<x> = PolynomialRing(SR, sparse=True) sage: f = (1+I)*x^(2^32) - I sage: f.map_coefficients(lambda z: z.conjugate()) (-I + 1)*x^4294967296 + I
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) + Integer(2) >>> f.map_coefficients(lambda a: a + Integer(42)) 43*x^2 + 44 >>> R = PolynomialRing(ZZ, sparse=True, names=('x',)); (x,) = R._first_ngens(1) >>> f = x**(Integer(2)**Integer(32)) + Integer(2) >>> f.map_coefficients(lambda a: a + Integer(42)) 43*x^4294967296 + 44 >>> # needs sage.symbolic >>> R = SR['x']; (x,) = R._first_ngens(1) >>> f = (Integer(1)+I)*x**Integer(2) + Integer(3)*x - I >>> f.map_coefficients(lambda z: z.conjugate()) (-I + 1)*x^2 + 3*x + I >>> R = PolynomialRing(SR, sparse=True, names=('x',)); (x,) = R._first_ngens(1) >>> f = (Integer(1)+I)*x**(Integer(2)**Integer(32)) - I >>> f.map_coefficients(lambda z: z.conjugate()) (-I + 1)*x^4294967296 + I
R.<x> = ZZ[] f = x^2 + 2 f.map_coefficients(lambda a: a + 42) R.<x> = PolynomialRing(ZZ, sparse=True) f = x^(2^32) + 2 f.map_coefficients(lambda a: a + 42) # needs sage.symbolic R.<x> = SR[] f = (1+I)*x^2 + 3*x - I f.map_coefficients(lambda z: z.conjugate()) R.<x> = PolynomialRing(SR, sparse=True) f = (1+I)*x^(2^32) - I f.map_coefficients(lambda z: z.conjugate())
Examples with different base ring:
sage: R.<x> = ZZ[] sage: k = GF(2) sage: residue = lambda x: k(x) sage: f = 4*x^2 + x + 3 sage: g = f.map_coefficients(residue); g x + 1 sage: g.parent() Univariate Polynomial Ring in x over Integer Ring sage: g = f.map_coefficients(residue, new_base_ring=k); g x + 1 sage: g.parent() # needs sage.libs.ntl Univariate Polynomial Ring in x over Finite Field of size 2 (using GF2X) sage: residue = k.coerce_map_from(ZZ) sage: g = f.map_coefficients(residue); g x + 1 sage: g.parent() # needs sage.libs.ntl Univariate Polynomial Ring in x over Finite Field of size 2 (using GF2X)
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> k = GF(Integer(2)) >>> residue = lambda x: k(x) >>> f = Integer(4)*x**Integer(2) + x + Integer(3) >>> g = f.map_coefficients(residue); g x + 1 >>> g.parent() Univariate Polynomial Ring in x over Integer Ring >>> g = f.map_coefficients(residue, new_base_ring=k); g x + 1 >>> g.parent() # needs sage.libs.ntl Univariate Polynomial Ring in x over Finite Field of size 2 (using GF2X) >>> residue = k.coerce_map_from(ZZ) >>> g = f.map_coefficients(residue); g x + 1 >>> g.parent() # needs sage.libs.ntl Univariate Polynomial Ring in x over Finite Field of size 2 (using GF2X)
R.<x> = ZZ[] k = GF(2) residue = lambda x: k(x) f = 4*x^2 + x + 3 g = f.map_coefficients(residue); g g.parent() g = f.map_coefficients(residue, new_base_ring=k); g g.parent() # needs sage.libs.ntl residue = k.coerce_map_from(ZZ) g = f.map_coefficients(residue); g g.parent() # needs sage.libs.ntl
- mod(other)[source]¶
Remainder of division of
self
byother
.EXAMPLES:
sage: R.<x> = ZZ[] sage: x % (x+1) -1 sage: (x^3 + x - 1) % (x^2 - 1) 2*x - 1
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> x % (x+Integer(1)) -1 >>> (x**Integer(3) + x - Integer(1)) % (x**Integer(2) - Integer(1)) 2*x - 1
R.<x> = ZZ[] x % (x+1) (x^3 + x - 1) % (x^2 - 1)
- monic()[source]¶
Return this polynomial divided by its leading coefficient. Does not change this polynomial.
EXAMPLES:
sage: x = QQ['x'].0 sage: f = 2*x^2 + x^3 + 56*x^5 sage: f.monic() x^5 + 1/56*x^3 + 1/28*x^2 sage: f = (1/4)*x^2 + 3*x + 1 sage: f.monic() x^2 + 12*x + 4
>>> from sage.all import * >>> x = QQ['x'].gen(0) >>> f = Integer(2)*x**Integer(2) + x**Integer(3) + Integer(56)*x**Integer(5) >>> f.monic() x^5 + 1/56*x^3 + 1/28*x^2 >>> f = (Integer(1)/Integer(4))*x**Integer(2) + Integer(3)*x + Integer(1) >>> f.monic() x^2 + 12*x + 4
x = QQ['x'].0 f = 2*x^2 + x^3 + 56*x^5 f.monic() f = (1/4)*x^2 + 3*x + 1 f.monic()
The following happens because \(f = 0\) cannot be made into a monic polynomial
sage: f = 0*x sage: f.monic() Traceback (most recent call last): ... ZeroDivisionError: rational division by zero
>>> from sage.all import * >>> f = Integer(0)*x >>> f.monic() Traceback (most recent call last): ... ZeroDivisionError: rational division by zero
f = 0*x f.monic()
Notice that the monic version of a polynomial over the integers is defined over the rationals.
sage: x = ZZ['x'].0 sage: f = 3*x^19 + x^2 - 37 sage: g = f.monic(); g x^19 + 1/3*x^2 - 37/3 sage: g.parent() Univariate Polynomial Ring in x over Rational Field
>>> from sage.all import * >>> x = ZZ['x'].gen(0) >>> f = Integer(3)*x**Integer(19) + x**Integer(2) - Integer(37) >>> g = f.monic(); g x^19 + 1/3*x^2 - 37/3 >>> g.parent() Univariate Polynomial Ring in x over Rational Field
x = ZZ['x'].0 f = 3*x^19 + x^2 - 37 g = f.monic(); g g.parent()
AUTHORS:
Naqi Jaffery (2006-01-24): examples
- monomial_coefficient(m)[source]¶
Return the coefficient in the base ring of the monomial
m
inself
, wherem
must have the same parent asself
.INPUT:
m
– a monomial
OUTPUT: coefficient in base ring
EXAMPLES:
sage: P.<x> = QQ[] sage: f = 2 * x sage: c = f.monomial_coefficient(x); c 2 sage: c.parent() Rational Field sage: f = x^9 - 1/2*x^2 + 7*x + 5/11 sage: f.monomial_coefficient(x^9) 1 sage: f.monomial_coefficient(x^2) -1/2 sage: f.monomial_coefficient(x) 7 sage: f.monomial_coefficient(x^0) 5/11 sage: f.monomial_coefficient(x^3) 0
>>> from sage.all import * >>> P = QQ['x']; (x,) = P._first_ngens(1) >>> f = Integer(2) * x >>> c = f.monomial_coefficient(x); c 2 >>> c.parent() Rational Field >>> f = x**Integer(9) - Integer(1)/Integer(2)*x**Integer(2) + Integer(7)*x + Integer(5)/Integer(11) >>> f.monomial_coefficient(x**Integer(9)) 1 >>> f.monomial_coefficient(x**Integer(2)) -1/2 >>> f.monomial_coefficient(x) 7 >>> f.monomial_coefficient(x**Integer(0)) 5/11 >>> f.monomial_coefficient(x**Integer(3)) 0
P.<x> = QQ[] f = 2 * x c = f.monomial_coefficient(x); c c.parent() f = x^9 - 1/2*x^2 + 7*x + 5/11 f.monomial_coefficient(x^9) f.monomial_coefficient(x^2) f.monomial_coefficient(x) f.monomial_coefficient(x^0) f.monomial_coefficient(x^3)
- monomial_coefficients()[source]¶
Return a sparse dictionary representation of this univariate polynomial.
EXAMPLES:
sage: R.<x> = QQ[] sage: f = x^3 + -1/7*x + 13 sage: f.monomial_coefficients() {0: 13, 1: -1/7, 3: 1}
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + -Integer(1)/Integer(7)*x + Integer(13) >>> f.monomial_coefficients() {0: 13, 1: -1/7, 3: 1}
R.<x> = QQ[] f = x^3 + -1/7*x + 13 f.monomial_coefficients()
dict
is an alias:sage: f.dict() {0: 13, 1: -1/7, 3: 1}
>>> from sage.all import * >>> f.dict() {0: 13, 1: -1/7, 3: 1}
f.dict()
- monomials()[source]¶
Return the list of the monomials in
self
in a decreasing order of their degrees.EXAMPLES:
sage: P.<x> = QQ[] sage: f = x^2 + (2/3)*x + 1 sage: f.monomials() [x^2, x, 1] sage: f = P(3/2) sage: f.monomials() [1] sage: f = P(0) sage: f.monomials() [] sage: f = x sage: f.monomials() [x] sage: f = - 1/2*x^2 + x^9 + 7*x + 5/11 sage: f.monomials() [x^9, x^2, x, 1] sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') sage: K.<rho> = NumberField(x**2 + 1) sage: R.<y> = QQ[] sage: p = rho * y sage: p.monomials() [y]
>>> from sage.all import * >>> P = QQ['x']; (x,) = P._first_ngens(1) >>> f = x**Integer(2) + (Integer(2)/Integer(3))*x + Integer(1) >>> f.monomials() [x^2, x, 1] >>> f = P(Integer(3)/Integer(2)) >>> f.monomials() [1] >>> f = P(Integer(0)) >>> f.monomials() [] >>> f = x >>> f.monomials() [x] >>> f = - Integer(1)/Integer(2)*x**Integer(2) + x**Integer(9) + Integer(7)*x + Integer(5)/Integer(11) >>> f.monomials() [x^9, x^2, x, 1] >>> # needs sage.rings.number_field >>> x = polygen(ZZ, 'x') >>> K = NumberField(x**Integer(2) + Integer(1), names=('rho',)); (rho,) = K._first_ngens(1) >>> R = QQ['y']; (y,) = R._first_ngens(1) >>> p = rho * y >>> p.monomials() [y]
P.<x> = QQ[] f = x^2 + (2/3)*x + 1 f.monomials() f = P(3/2) f.monomials() f = P(0) f.monomials() f = x f.monomials() f = - 1/2*x^2 + x^9 + 7*x + 5/11 f.monomials() # needs sage.rings.number_field x = polygen(ZZ, 'x') K.<rho> = NumberField(x**2 + 1) R.<y> = QQ[] p = rho * y p.monomials()
- multiplication_trunc(other, n)[source]¶
Truncated multiplication.
EXAMPLES:
sage: R.<x> = ZZ[] sage: (x^10 + 5*x^5 + x^2 - 3).multiplication_trunc(x^7 - 3*x^3 + 1, 11) x^10 + x^9 - 15*x^8 - 3*x^7 + 2*x^5 + 9*x^3 + x^2 - 3
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> (x**Integer(10) + Integer(5)*x**Integer(5) + x**Integer(2) - Integer(3)).multiplication_trunc(x**Integer(7) - Integer(3)*x**Integer(3) + Integer(1), Integer(11)) x^10 + x^9 - 15*x^8 - 3*x^7 + 2*x^5 + 9*x^3 + x^2 - 3
R.<x> = ZZ[] (x^10 + 5*x^5 + x^2 - 3).multiplication_trunc(x^7 - 3*x^3 + 1, 11)
Check that coercion is working:
sage: R2 = QQ['x'] sage: x2 = R2.gen() sage: p1 = (x^3 + 1).multiplication_trunc(x2^3 - 2, 5); p1 -x^3 - 2 sage: p2 = (x2^3 + 1).multiplication_trunc(x^3 - 2, 5); p2 -x^3 - 2 sage: parent(p1) == parent(p2) == R2 True
>>> from sage.all import * >>> R2 = QQ['x'] >>> x2 = R2.gen() >>> p1 = (x**Integer(3) + Integer(1)).multiplication_trunc(x2**Integer(3) - Integer(2), Integer(5)); p1 -x^3 - 2 >>> p2 = (x2**Integer(3) + Integer(1)).multiplication_trunc(x**Integer(3) - Integer(2), Integer(5)); p2 -x^3 - 2 >>> parent(p1) == parent(p2) == R2 True
R2 = QQ['x'] x2 = R2.gen() p1 = (x^3 + 1).multiplication_trunc(x2^3 - 2, 5); p1 p2 = (x2^3 + 1).multiplication_trunc(x^3 - 2, 5); p2 parent(p1) == parent(p2) == R2
- newton_raphson(n, x0)[source]¶
Return a list of n iterative approximations to a root of this polynomial, computed using the Newton-Raphson method.
The Newton-Raphson method is an iterative root-finding algorithm. For \(f(x)\) a polynomial, as is the case here, this is essentially the same as Horner’s method.
INPUT:
n
– integer; the number of iterationsx0
– an initial guess \(x_0\)
OUTPUT: list of numbers hopefully approximating a root of \(f(x)=0\)
If one of the iterates is a critical point of \(f\), a
ZeroDivisionError
exception is raised.EXAMPLES:
sage: x = PolynomialRing(RealField(), 'x').gen() # needs sage.rings.real_mpfr sage: f = x^2 - 2 # needs sage.rings.real_mpfr sage: f.newton_raphson(4, 1) # needs sage.rings.real_mpfr [1.50000000000000, 1.41666666666667, 1.41421568627451, 1.41421356237469]
>>> from sage.all import * >>> x = PolynomialRing(RealField(), 'x').gen() # needs sage.rings.real_mpfr >>> f = x**Integer(2) - Integer(2) # needs sage.rings.real_mpfr >>> f.newton_raphson(Integer(4), Integer(1)) # needs sage.rings.real_mpfr [1.50000000000000, 1.41666666666667, 1.41421568627451, 1.41421356237469]
x = PolynomialRing(RealField(), 'x').gen() # needs sage.rings.real_mpfr f = x^2 - 2 # needs sage.rings.real_mpfr f.newton_raphson(4, 1) # needs sage.rings.real_mpfr
AUTHORS:
David Joyner and William Stein (2005-11-28)
- newton_slopes(p, lengths=False)[source]¶
Return the \(p\)-adic slopes of the Newton polygon of
self
, when this makes sense.OUTPUT:
If
lengths
isFalse
, a list of rational numbers. Iflengths
isTrue
, a list of couples \((s,l)\) where \(s\) is the slope and \(l\) the length of the corresponding segment in the Newton polygon.EXAMPLES:
sage: x = QQ['x'].0 sage: f = x^3 + 2 sage: f.newton_slopes(2) # needs sage.libs.pari [1/3, 1/3, 1/3] sage: R.<x> = PolynomialRing(ZZ, sparse=True) sage: p = x^5 + 6*x^2 + 4 sage: p.newton_slopes(2) # needs sage.libs.pari [1/2, 1/2, 1/3, 1/3, 1/3] sage: p.newton_slopes(2, lengths=True) [(1/2, 2), (1/3, 3)] sage: (x^2^100 + 27).newton_slopes(3, lengths=True) [(3/1267650600228229401496703205376, 1267650600228229401496703205376)]
>>> from sage.all import * >>> x = QQ['x'].gen(0) >>> f = x**Integer(3) + Integer(2) >>> f.newton_slopes(Integer(2)) # needs sage.libs.pari [1/3, 1/3, 1/3] >>> R = PolynomialRing(ZZ, sparse=True, names=('x',)); (x,) = R._first_ngens(1) >>> p = x**Integer(5) + Integer(6)*x**Integer(2) + Integer(4) >>> p.newton_slopes(Integer(2)) # needs sage.libs.pari [1/2, 1/2, 1/3, 1/3, 1/3] >>> p.newton_slopes(Integer(2), lengths=True) [(1/2, 2), (1/3, 3)] >>> (x**Integer(2)**Integer(100) + Integer(27)).newton_slopes(Integer(3), lengths=True) [(3/1267650600228229401496703205376, 1267650600228229401496703205376)]
x = QQ['x'].0 f = x^3 + 2 f.newton_slopes(2) # needs sage.libs.pari R.<x> = PolynomialRing(ZZ, sparse=True) p = x^5 + 6*x^2 + 4 p.newton_slopes(2) # needs sage.libs.pari p.newton_slopes(2, lengths=True) (x^2^100 + 27).newton_slopes(3, lengths=True)
ALGORITHM: Uses PARI if
lengths
isFalse
.
- norm(p)[source]¶
Return the \(p\)-norm of this polynomial.
DEFINITION: For integer \(p\), the \(p\)-norm of a polynomial is the \(p\)th root of the sum of the \(p\)th powers of the absolute values of the coefficients of the polynomial.
INPUT:
p
– positive integer or +infinity; the degree of the norm
EXAMPLES:
sage: # needs sage.rings.real_mpfr sage: R.<x> = RR[] sage: f = x^6 + x^2 + -x^4 - 2*x^3 sage: f.norm(2) 2.64575131106459 sage: (sqrt(1^2 + 1^2 + (-1)^2 + (-2)^2)).n() # needs sage.symbolic 2.64575131106459
>>> from sage.all import * >>> # needs sage.rings.real_mpfr >>> R = RR['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(6) + x**Integer(2) + -x**Integer(4) - Integer(2)*x**Integer(3) >>> f.norm(Integer(2)) 2.64575131106459 >>> (sqrt(Integer(1)**Integer(2) + Integer(1)**Integer(2) + (-Integer(1))**Integer(2) + (-Integer(2))**Integer(2))).n() # needs sage.symbolic 2.64575131106459
# needs sage.rings.real_mpfr R.<x> = RR[] f = x^6 + x^2 + -x^4 - 2*x^3 f.norm(2) (sqrt(1^2 + 1^2 + (-1)^2 + (-2)^2)).n() # needs sage.symbolic
sage: f.norm(1) # needs sage.rings.real_mpfr 5.00000000000000 sage: f.norm(infinity) # needs sage.rings.real_mpfr 2.00000000000000
>>> from sage.all import * >>> f.norm(Integer(1)) # needs sage.rings.real_mpfr 5.00000000000000 >>> f.norm(infinity) # needs sage.rings.real_mpfr 2.00000000000000
f.norm(1) # needs sage.rings.real_mpfr f.norm(infinity) # needs sage.rings.real_mpfr
>>> from sage.all import * >>> f.norm(Integer(1)) # needs sage.rings.real_mpfr 5.00000000000000 >>> f.norm(infinity) # needs sage.rings.real_mpfr 2.00000000000000
f.norm(1) # needs sage.rings.real_mpfr f.norm(infinity) # needs sage.rings.real_mpfr
sage: f.norm(-1) # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: The degree of the norm must be positive
>>> from sage.all import * >>> f.norm(-Integer(1)) # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: The degree of the norm must be positive
f.norm(-1) # needs sage.rings.real_mpfr
>>> from sage.all import * >>> f.norm(-Integer(1)) # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: The degree of the norm must be positive
f.norm(-1) # needs sage.rings.real_mpfr
AUTHORS:
Didier Deshommes
William Stein: fix bugs, add definition, etc.
- nth_root(n)[source]¶
Return a \(n\)-th root of this polynomial.
This is computed using Newton method in the ring of power series. This method works only when the base ring is an integral domain. Moreover, for polynomial whose coefficient of lower degree is different from 1, the elements of the base ring should have a method
nth_root()
implemented.EXAMPLES:
sage: R.<x> = ZZ[] sage: a = 27 * (x+3)**6 * (x+5)**3 sage: a.nth_root(3) 3*x^3 + 33*x^2 + 117*x + 135 sage: b = 25 * (x^2 + x + 1) sage: b.nth_root(2) Traceback (most recent call last): ... ValueError: not a 2nd power sage: R(0).nth_root(3) 0 sage: R.<x> = QQ[] sage: a = 1/4 * (x/7 + 3/2)^2 * (x/2 + 5/3)^4 sage: a.nth_root(2) 1/56*x^3 + 103/336*x^2 + 365/252*x + 25/12 sage: # needs sage.rings.number_field sage: K.<sqrt2> = QuadraticField(2) sage: R.<x> = K[] sage: a = (x + sqrt2)^3 * ((1+sqrt2)*x - 1/sqrt2)^6 sage: b = a.nth_root(3); b (2*sqrt2 + 3)*x^3 + (2*sqrt2 + 2)*x^2 + (-2*sqrt2 - 3/2)*x + 1/2*sqrt2 sage: b^3 == a True sage: # needs sage.rings.number_field sage: R.<x> = QQbar[] sage: p = x**3 + QQbar(2).sqrt() * x - QQbar(3).sqrt() sage: r = (p**5).nth_root(5) sage: r * p[0] == p * r[0] True sage: p = (x+1)^20 + x^20 sage: p.nth_root(20) Traceback (most recent call last): ... ValueError: not a 20th power sage: # needs sage.rings.finite_rings sage: z = GF(4).gen() sage: R.<x> = GF(4)[] sage: p = z*x**4 + 2*x - 1 sage: r = (p**15).nth_root(15) sage: r * p[0] == p * r[0] True sage: ((x+1)**2).nth_root(2) x + 1 sage: ((x+1)**4).nth_root(4) x + 1 sage: ((x+1)**12).nth_root(12) x + 1 sage: (x^4 + x^3 + 1).nth_root(2) Traceback (most recent call last): ... ValueError: not a 2nd power sage: p = (x+1)^17 + x^17 sage: r = p.nth_root(17) Traceback (most recent call last): ... ValueError: not a 17th power sage: R1.<x> = QQ[] sage: R2.<y> = R1[] sage: R3.<z> = R2[] sage: (((y**2+x)*z^2 + x*y*z + 2*x)**3).nth_root(3) (y^2 + x)*z^2 + x*y*z + 2*x sage: ((x+y+z)**5).nth_root(5) z + y + x
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> a = Integer(27) * (x+Integer(3))**Integer(6) * (x+Integer(5))**Integer(3) >>> a.nth_root(Integer(3)) 3*x^3 + 33*x^2 + 117*x + 135 >>> b = Integer(25) * (x**Integer(2) + x + Integer(1)) >>> b.nth_root(Integer(2)) Traceback (most recent call last): ... ValueError: not a 2nd power >>> R(Integer(0)).nth_root(Integer(3)) 0 >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> a = Integer(1)/Integer(4) * (x/Integer(7) + Integer(3)/Integer(2))**Integer(2) * (x/Integer(2) + Integer(5)/Integer(3))**Integer(4) >>> a.nth_root(Integer(2)) 1/56*x^3 + 103/336*x^2 + 365/252*x + 25/12 >>> # needs sage.rings.number_field >>> K = QuadraticField(Integer(2), names=('sqrt2',)); (sqrt2,) = K._first_ngens(1) >>> R = K['x']; (x,) = R._first_ngens(1) >>> a = (x + sqrt2)**Integer(3) * ((Integer(1)+sqrt2)*x - Integer(1)/sqrt2)**Integer(6) >>> b = a.nth_root(Integer(3)); b (2*sqrt2 + 3)*x^3 + (2*sqrt2 + 2)*x^2 + (-2*sqrt2 - 3/2)*x + 1/2*sqrt2 >>> b**Integer(3) == a True >>> # needs sage.rings.number_field >>> R = QQbar['x']; (x,) = R._first_ngens(1) >>> p = x**Integer(3) + QQbar(Integer(2)).sqrt() * x - QQbar(Integer(3)).sqrt() >>> r = (p**Integer(5)).nth_root(Integer(5)) >>> r * p[Integer(0)] == p * r[Integer(0)] True >>> p = (x+Integer(1))**Integer(20) + x**Integer(20) >>> p.nth_root(Integer(20)) Traceback (most recent call last): ... ValueError: not a 20th power >>> # needs sage.rings.finite_rings >>> z = GF(Integer(4)).gen() >>> R = GF(Integer(4))['x']; (x,) = R._first_ngens(1) >>> p = z*x**Integer(4) + Integer(2)*x - Integer(1) >>> r = (p**Integer(15)).nth_root(Integer(15)) >>> r * p[Integer(0)] == p * r[Integer(0)] True >>> ((x+Integer(1))**Integer(2)).nth_root(Integer(2)) x + 1 >>> ((x+Integer(1))**Integer(4)).nth_root(Integer(4)) x + 1 >>> ((x+Integer(1))**Integer(12)).nth_root(Integer(12)) x + 1 >>> (x**Integer(4) + x**Integer(3) + Integer(1)).nth_root(Integer(2)) Traceback (most recent call last): ... ValueError: not a 2nd power >>> p = (x+Integer(1))**Integer(17) + x**Integer(17) >>> r = p.nth_root(Integer(17)) Traceback (most recent call last): ... ValueError: not a 17th power >>> R1 = QQ['x']; (x,) = R1._first_ngens(1) >>> R2 = R1['y']; (y,) = R2._first_ngens(1) >>> R3 = R2['z']; (z,) = R3._first_ngens(1) >>> (((y**Integer(2)+x)*z**Integer(2) + x*y*z + Integer(2)*x)**Integer(3)).nth_root(Integer(3)) (y^2 + x)*z^2 + x*y*z + 2*x >>> ((x+y+z)**Integer(5)).nth_root(Integer(5)) z + y + x
R.<x> = ZZ[] a = 27 * (x+3)**6 * (x+5)**3 a.nth_root(3) b = 25 * (x^2 + x + 1) b.nth_root(2) R(0).nth_root(3) R.<x> = QQ[] a = 1/4 * (x/7 + 3/2)^2 * (x/2 + 5/3)^4 a.nth_root(2) # needs sage.rings.number_field K.<sqrt2> = QuadraticField(2) R.<x> = K[] a = (x + sqrt2)^3 * ((1+sqrt2)*x - 1/sqrt2)^6 b = a.nth_root(3); b b^3 == a # needs sage.rings.number_field R.<x> = QQbar[] p = x**3 + QQbar(2).sqrt() * x - QQbar(3).sqrt() r = (p**5).nth_root(5) r * p[0] == p * r[0] p = (x+1)^20 + x^20 p.nth_root(20) # needs sage.rings.finite_rings z = GF(4).gen() R.<x> = GF(4)[] p = z*x**4 + 2*x - 1 r = (p**15).nth_root(15) r * p[0] == p * r[0] ((x+1)**2).nth_root(2) ((x+1)**4).nth_root(4) ((x+1)**12).nth_root(12) (x^4 + x^3 + 1).nth_root(2) p = (x+1)^17 + x^17 r = p.nth_root(17) R1.<x> = QQ[] R2.<y> = R1[] R3.<z> = R2[] (((y**2+x)*z^2 + x*y*z + 2*x)**3).nth_root(3) ((x+y+z)**5).nth_root(5)
Here we consider a base ring without
nth_root
method. The third example with a non-trivial coefficient of lowest degree raises an error:sage: # needs sage.libs.pari sage: R.<x> = QQ[] sage: R2 = R.quotient(x**2 + 1) sage: x = R2.gen() sage: R3.<y> = R2[] sage: (y**2 - 2*y + 1).nth_root(2) -y + 1 sage: (y**3).nth_root(3) y sage: (y**2 + x).nth_root(2) Traceback (most recent call last): ... AttributeError: ... has no attribute 'nth_root'...
>>> from sage.all import * >>> # needs sage.libs.pari >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> R2 = R.quotient(x**Integer(2) + Integer(1)) >>> x = R2.gen() >>> R3 = R2['y']; (y,) = R3._first_ngens(1) >>> (y**Integer(2) - Integer(2)*y + Integer(1)).nth_root(Integer(2)) -y + 1 >>> (y**Integer(3)).nth_root(Integer(3)) y >>> (y**Integer(2) + x).nth_root(Integer(2)) Traceback (most recent call last): ... AttributeError: ... has no attribute 'nth_root'...
# needs sage.libs.pari R.<x> = QQ[] R2 = R.quotient(x**2 + 1) x = R2.gen() R3.<y> = R2[] (y**2 - 2*y + 1).nth_root(2) (y**3).nth_root(3) (y**2 + x).nth_root(2)
- number_of_real_roots()[source]¶
Return the number of real roots of this polynomial, counted without multiplicity.
EXAMPLES:
sage: # needs sage.libs.pari sage: R.<x> = PolynomialRing(ZZ) sage: pol = (x - 1)^2 * (x - 2)^2 * (x - 3) sage: pol.number_of_real_roots() 3 sage: pol = (x - 1) * (x - 2) * (x - 3) sage: # needs sage.libs.pari sage.rings.real_mpfr sage: pol2 = pol.change_ring(CC) sage: pol2.number_of_real_roots() 3 sage: R.<x> = PolynomialRing(CC) sage: pol = (x - 1) * (x - CC(I)) sage: pol.number_of_real_roots() 1
>>> from sage.all import * >>> # needs sage.libs.pari >>> R = PolynomialRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> pol = (x - Integer(1))**Integer(2) * (x - Integer(2))**Integer(2) * (x - Integer(3)) >>> pol.number_of_real_roots() 3 >>> pol = (x - Integer(1)) * (x - Integer(2)) * (x - Integer(3)) >>> # needs sage.libs.pari sage.rings.real_mpfr >>> pol2 = pol.change_ring(CC) >>> pol2.number_of_real_roots() 3 >>> R = PolynomialRing(CC, names=('x',)); (x,) = R._first_ngens(1) >>> pol = (x - Integer(1)) * (x - CC(I)) >>> pol.number_of_real_roots() 1
# needs sage.libs.pari R.<x> = PolynomialRing(ZZ) pol = (x - 1)^2 * (x - 2)^2 * (x - 3) pol.number_of_real_roots() pol = (x - 1) * (x - 2) * (x - 3) # needs sage.libs.pari sage.rings.real_mpfr pol2 = pol.change_ring(CC) pol2.number_of_real_roots() R.<x> = PolynomialRing(CC) pol = (x - 1) * (x - CC(I)) pol.number_of_real_roots()
- number_of_roots_in_interval(a=None, b=None)[source]¶
Return the number of roots of this polynomial in the interval \([a,b]\), counted without multiplicity. The endpoints \(a\), \(b\) default to
-Infinity
,Infinity
(which are also valid input values).Calls the PARI routine pari:polsturm.
Note that as of version 2.8, PARI includes the left endpoint of the interval (and no longer uses Sturm’s algorithm on exact inputs). pari:polsturm requires a polynomial with real coefficients; in case PARI returns an error, we try again after taking the GCD of
self
with its complex conjugate.EXAMPLES:
sage: # needs sage.libs.pari sage: R.<x> = PolynomialRing(ZZ) sage: pol = (x - 1)^2 * (x - 2)^2 * (x - 3) sage: pol.number_of_roots_in_interval(1, 2) 2 sage: pol.number_of_roots_in_interval(1.01, 2) 1 sage: pol.number_of_roots_in_interval(None, 2) 2 sage: pol.number_of_roots_in_interval(1, Infinity) 3 sage: pol.number_of_roots_in_interval() 3 sage: pol = (x - 1) * (x - 2) * (x - 3) sage: # needs sage.libs.pari sage.rings.real_mpfr sage: pol2 = pol.change_ring(CC) sage: pol2.number_of_roots_in_interval() 3 sage: R.<x> = PolynomialRing(CC) sage: pol = (x - 1) * (x - CC(I)) sage: pol.number_of_roots_in_interval(0, 2) 1
>>> from sage.all import * >>> # needs sage.libs.pari >>> R = PolynomialRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> pol = (x - Integer(1))**Integer(2) * (x - Integer(2))**Integer(2) * (x - Integer(3)) >>> pol.number_of_roots_in_interval(Integer(1), Integer(2)) 2 >>> pol.number_of_roots_in_interval(RealNumber('1.01'), Integer(2)) 1 >>> pol.number_of_roots_in_interval(None, Integer(2)) 2 >>> pol.number_of_roots_in_interval(Integer(1), Infinity) 3 >>> pol.number_of_roots_in_interval() 3 >>> pol = (x - Integer(1)) * (x - Integer(2)) * (x - Integer(3)) >>> # needs sage.libs.pari sage.rings.real_mpfr >>> pol2 = pol.change_ring(CC) >>> pol2.number_of_roots_in_interval() 3 >>> R = PolynomialRing(CC, names=('x',)); (x,) = R._first_ngens(1) >>> pol = (x - Integer(1)) * (x - CC(I)) >>> pol.number_of_roots_in_interval(Integer(0), Integer(2)) 1
# needs sage.libs.pari R.<x> = PolynomialRing(ZZ) pol = (x - 1)^2 * (x - 2)^2 * (x - 3) pol.number_of_roots_in_interval(1, 2) pol.number_of_roots_in_interval(1.01, 2) pol.number_of_roots_in_interval(None, 2) pol.number_of_roots_in_interval(1, Infinity) pol.number_of_roots_in_interval() pol = (x - 1) * (x - 2) * (x - 3) # needs sage.libs.pari sage.rings.real_mpfr pol2 = pol.change_ring(CC) pol2.number_of_roots_in_interval() R.<x> = PolynomialRing(CC) pol = (x - 1) * (x - CC(I)) pol.number_of_roots_in_interval(0, 2)
- number_of_terms()[source]¶
Return the number of nonzero coefficients of
self
.Also called weight, Hamming weight or sparsity.
EXAMPLES:
sage: R.<x> = ZZ[] sage: f = x^3 - x sage: f.number_of_terms() 2 sage: R(0).number_of_terms() 0 sage: f = (x + 1)^100 sage: f.number_of_terms() 101 sage: S = GF(5)['y'] sage: S(f).number_of_terms() 5 sage: cyclotomic_polynomial(105).number_of_terms() 33
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) - x >>> f.number_of_terms() 2 >>> R(Integer(0)).number_of_terms() 0 >>> f = (x + Integer(1))**Integer(100) >>> f.number_of_terms() 101 >>> S = GF(Integer(5))['y'] >>> S(f).number_of_terms() 5 >>> cyclotomic_polynomial(Integer(105)).number_of_terms() 33
R.<x> = ZZ[] f = x^3 - x f.number_of_terms() R(0).number_of_terms() f = (x + 1)^100 f.number_of_terms() S = GF(5)['y'] S(f).number_of_terms() cyclotomic_polynomial(105).number_of_terms()
The method
hamming_weight()
is an alias:sage: f.hamming_weight() 101
>>> from sage.all import * >>> f.hamming_weight() 101
f.hamming_weight()
- numerator()[source]¶
Return a numerator of
self
, computed asself * self.denominator()
.Note that some subclasses may implement its own numerator function. For example, see
sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint
Warning
This is not the numerator of the rational function defined by
self
, which would always beself
sinceself
is a polynomial.EXAMPLES:
First we compute the numerator of a polynomial with integer coefficients, which is of course
self
.sage: R.<x> = ZZ[] sage: f = x^3 + 17*x + 1 sage: f.numerator() x^3 + 17*x + 1 sage: f == f.numerator() True
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + Integer(17)*x + Integer(1) >>> f.numerator() x^3 + 17*x + 1 >>> f == f.numerator() True
R.<x> = ZZ[] f = x^3 + 17*x + 1 f.numerator() f == f.numerator()
Next we compute the numerator of a polynomial with rational coefficients.
sage: R.<x> = PolynomialRing(QQ) sage: f = (1/17)*x^19 - (2/3)*x + 1/3; f 1/17*x^19 - 2/3*x + 1/3 sage: f.numerator() 3*x^19 - 34*x + 17 sage: f == f.numerator() False
>>> from sage.all import * >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> f = (Integer(1)/Integer(17))*x**Integer(19) - (Integer(2)/Integer(3))*x + Integer(1)/Integer(3); f 1/17*x^19 - 2/3*x + 1/3 >>> f.numerator() 3*x^19 - 34*x + 17 >>> f == f.numerator() False
R.<x> = PolynomialRing(QQ) f = (1/17)*x^19 - (2/3)*x + 1/3; f f.numerator() f == f.numerator()
We try to compute the denominator of a polynomial with coefficients in the real numbers, which is a ring whose elements do not have a denominator method.
sage: # needs sage.rings.real_mpfr sage: R.<x> = RR[] sage: f = x + RR('0.3'); f x + 0.300000000000000 sage: f.numerator() x + 0.300000000000000
>>> from sage.all import * >>> # needs sage.rings.real_mpfr >>> R = RR['x']; (x,) = R._first_ngens(1) >>> f = x + RR('0.3'); f x + 0.300000000000000 >>> f.numerator() x + 0.300000000000000
# needs sage.rings.real_mpfr R.<x> = RR[] f = x + RR('0.3'); f f.numerator()
We check that the computation of the numerator and denominator are valid.
sage: # needs sage.rings.number_field sage.symbolic sage: K = NumberField(symbolic_expression('x^3+2'), 'a')['s,t']['x'] sage: f = K.random_element() sage: f.numerator() / f.denominator() == f True sage: R = RR['x'] sage: f = R.random_element() sage: f.numerator() / f.denominator() == f True
>>> from sage.all import * >>> # needs sage.rings.number_field sage.symbolic >>> K = NumberField(symbolic_expression('x^3+2'), 'a')['s,t']['x'] >>> f = K.random_element() >>> f.numerator() / f.denominator() == f True >>> R = RR['x'] >>> f = R.random_element() >>> f.numerator() / f.denominator() == f True
# needs sage.rings.number_field sage.symbolic K = NumberField(symbolic_expression('x^3+2'), 'a')['s,t']['x'] f = K.random_element() f.numerator() / f.denominator() == f R = RR['x'] f = R.random_element() f.numerator() / f.denominator() == f
- ord(p=None)[source]¶
This is the same as the valuation of
self
at \(p\). See the documentation forvaluation()
.EXAMPLES:
sage: R.<x> = ZZ[] sage: (x^2 + x).ord(x + 1) 1
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> (x**Integer(2) + x).ord(x + Integer(1)) 1
R.<x> = ZZ[] (x^2 + x).ord(x + 1)
- padded_list(n=None)[source]¶
Return list of coefficients of
self
up to (but not including) \(q^n\).Includes 0s in the list on the right so that the list has length \(n\).
INPUT:
n
– (default:None
) if given, an integer that is at least 0
EXAMPLES:
sage: x = polygen(QQ) sage: f = 1 + x^3 + 23*x^5 sage: f.padded_list() [1, 0, 0, 1, 0, 23] sage: f.padded_list(10) [1, 0, 0, 1, 0, 23, 0, 0, 0, 0] sage: len(f.padded_list(10)) 10 sage: f.padded_list(3) [1, 0, 0] sage: f.padded_list(0) [] sage: f.padded_list(-1) Traceback (most recent call last): ... ValueError: n must be at least 0
>>> from sage.all import * >>> x = polygen(QQ) >>> f = Integer(1) + x**Integer(3) + Integer(23)*x**Integer(5) >>> f.padded_list() [1, 0, 0, 1, 0, 23] >>> f.padded_list(Integer(10)) [1, 0, 0, 1, 0, 23, 0, 0, 0, 0] >>> len(f.padded_list(Integer(10))) 10 >>> f.padded_list(Integer(3)) [1, 0, 0] >>> f.padded_list(Integer(0)) [] >>> f.padded_list(-Integer(1)) Traceback (most recent call last): ... ValueError: n must be at least 0
x = polygen(QQ) f = 1 + x^3 + 23*x^5 f.padded_list() f.padded_list(10) len(f.padded_list(10)) f.padded_list(3) f.padded_list(0) f.padded_list(-1)
- plot(xmin=None, xmax=None, *args, **kwds)[source]¶
Return a plot of this polynomial.
INPUT:
xmin
– floatxmax
– float*args, **kwds
– passed to either plot or point
OUTPUT: a graphic object
EXAMPLES:
sage: x = polygen(GF(389)) sage: plot(x^2 + 1, rgbcolor=(0,0,1)) # needs sage.plot Graphics object consisting of 1 graphics primitive sage: x = polygen(QQ) sage: plot(x^2 + 1, rgbcolor=(1,0,0)) # needs sage.plot Graphics object consisting of 1 graphics primitive
>>> from sage.all import * >>> x = polygen(GF(Integer(389))) >>> plot(x**Integer(2) + Integer(1), rgbcolor=(Integer(0),Integer(0),Integer(1))) # needs sage.plot Graphics object consisting of 1 graphics primitive >>> x = polygen(QQ) >>> plot(x**Integer(2) + Integer(1), rgbcolor=(Integer(1),Integer(0),Integer(0))) # needs sage.plot Graphics object consisting of 1 graphics primitive
x = polygen(GF(389)) plot(x^2 + 1, rgbcolor=(0,0,1)) # needs sage.plot x = polygen(QQ) plot(x^2 + 1, rgbcolor=(1,0,0)) # needs sage.plot
- polynomial(var)[source]¶
Let
var
be one of the variables of the parent ofself
. This returnsself
viewed as a univariate polynomial invar
over the polynomial ring generated by all the other variables of the parent.For univariate polynomials, if
var
is the generator of the parent ring, we return this polynomial, otherwise raise an error.EXAMPLES:
sage: R.<x> = QQ[] sage: (x + 1).polynomial(x) x + 1
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> (x + Integer(1)).polynomial(x) x + 1
R.<x> = QQ[] (x + 1).polynomial(x)
- power_trunc(n, prec)[source]¶
Truncated
n
-th power of this polynomial up to precisionprec
.INPUT:
n
– nonnegative integer; power to be takenprec
– integer; the precision
EXAMPLES:
sage: R.<x> = ZZ[] sage: (3*x^2 - 2*x + 1).power_trunc(5, 8) -1800*x^7 + 1590*x^6 - 1052*x^5 + 530*x^4 - 200*x^3 + 55*x^2 - 10*x + 1 sage: ((3*x^2 - 2*x + 1)^5).truncate(8) -1800*x^7 + 1590*x^6 - 1052*x^5 + 530*x^4 - 200*x^3 + 55*x^2 - 10*x + 1 sage: S.<y> = R[] sage: (x + y).power_trunc(5,5) 5*x*y^4 + 10*x^2*y^3 + 10*x^3*y^2 + 5*x^4*y + x^5 sage: ((x + y)^5).truncate(5) 5*x*y^4 + 10*x^2*y^3 + 10*x^3*y^2 + 5*x^4*y + x^5 sage: R.<x> = GF(3)[] sage: p = x^2 - x + 1 sage: q = p.power_trunc(80, 20); q x^19 + x^18 + ... + 2*x^4 + 2*x^3 + x + 1 sage: (p^80).truncate(20) == q True sage: R.<x> = GF(7)[] sage: p = (x^2 + x + 1).power_trunc(2^100, 100); p 2*x^99 + x^98 + x^95 + 2*x^94 + ... + 3*x^2 + 2*x + 1 sage: for i in range(100): ....: q1 = (x^2 + x + 1).power_trunc(2^100 + i, 100) ....: q2 = p * (x^2 + x + 1).power_trunc(i, 100) ....: q2 = q2.truncate(100) ....: assert q1 == q2, "i = {}".format(i)
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> (Integer(3)*x**Integer(2) - Integer(2)*x + Integer(1)).power_trunc(Integer(5), Integer(8)) -1800*x^7 + 1590*x^6 - 1052*x^5 + 530*x^4 - 200*x^3 + 55*x^2 - 10*x + 1 >>> ((Integer(3)*x**Integer(2) - Integer(2)*x + Integer(1))**Integer(5)).truncate(Integer(8)) -1800*x^7 + 1590*x^6 - 1052*x^5 + 530*x^4 - 200*x^3 + 55*x^2 - 10*x + 1 >>> S = R['y']; (y,) = S._first_ngens(1) >>> (x + y).power_trunc(Integer(5),Integer(5)) 5*x*y^4 + 10*x^2*y^3 + 10*x^3*y^2 + 5*x^4*y + x^5 >>> ((x + y)**Integer(5)).truncate(Integer(5)) 5*x*y^4 + 10*x^2*y^3 + 10*x^3*y^2 + 5*x^4*y + x^5 >>> R = GF(Integer(3))['x']; (x,) = R._first_ngens(1) >>> p = x**Integer(2) - x + Integer(1) >>> q = p.power_trunc(Integer(80), Integer(20)); q x^19 + x^18 + ... + 2*x^4 + 2*x^3 + x + 1 >>> (p**Integer(80)).truncate(Integer(20)) == q True >>> R = GF(Integer(7))['x']; (x,) = R._first_ngens(1) >>> p = (x**Integer(2) + x + Integer(1)).power_trunc(Integer(2)**Integer(100), Integer(100)); p 2*x^99 + x^98 + x^95 + 2*x^94 + ... + 3*x^2 + 2*x + 1 >>> for i in range(Integer(100)): ... q1 = (x**Integer(2) + x + Integer(1)).power_trunc(Integer(2)**Integer(100) + i, Integer(100)) ... q2 = p * (x**Integer(2) + x + Integer(1)).power_trunc(i, Integer(100)) ... q2 = q2.truncate(Integer(100)) ... assert q1 == q2, "i = {}".format(i)
R.<x> = ZZ[] (3*x^2 - 2*x + 1).power_trunc(5, 8) ((3*x^2 - 2*x + 1)^5).truncate(8) S.<y> = R[] (x + y).power_trunc(5,5) ((x + y)^5).truncate(5) R.<x> = GF(3)[] p = x^2 - x + 1 q = p.power_trunc(80, 20); q (p^80).truncate(20) == q R.<x> = GF(7)[] p = (x^2 + x + 1).power_trunc(2^100, 100); p for i in range(100): q1 = (x^2 + x + 1).power_trunc(2^100 + i, 100) q2 = p * (x^2 + x + 1).power_trunc(i, 100) q2 = q2.truncate(100) assert q1 == q2, "i = {}".format(i)
- prec()[source]¶
Return the precision of this polynomial. This is always infinity, since polynomials are of infinite precision by definition (there is no big-oh).
EXAMPLES:
sage: x = polygen(ZZ) sage: (x^5 + x + 1).prec() +Infinity sage: x.prec() +Infinity
>>> from sage.all import * >>> x = polygen(ZZ) >>> (x**Integer(5) + x + Integer(1)).prec() +Infinity >>> x.prec() +Infinity
x = polygen(ZZ) (x^5 + x + 1).prec() x.prec()
- pseudo_quo_rem(other)[source]¶
Compute the pseudo-division of two polynomials.
INPUT:
other
– a nonzero polynomial
OUTPUT:
\(Q\) and \(R\) such that \(l^{m-n+1} \mathrm{self} = Q \cdot\mathrm{other} + R\) where \(m\) is the degree of this polynomial, \(n\) is the degree of
other
, \(l\) is the leading coefficient ofother
. The result is such that \(\deg(R) < \deg(\mathrm{other})\).ALGORITHM:
Algorithm 3.1.2 in [Coh1993].
EXAMPLES:
sage: R.<x> = PolynomialRing(ZZ, sparse=True) sage: p = x^4 + 6*x^3 + x^2 - x + 2 sage: q = 2*x^2 - 3*x - 1 sage: quo, rem = p.pseudo_quo_rem(q); quo, rem (4*x^2 + 30*x + 51, 175*x + 67) sage: 2^(4-2+1)*p == quo*q + rem True sage: S.<T> = R[] sage: p = (-3*x^2 - x)*T^3 - 3*x*T^2 + (x^2 - x)*T + 2*x^2 + 3*x - 2 sage: q = (-x^2 - 4*x - 5)*T^2 + (6*x^2 + x + 1)*T + 2*x^2 - x sage: quo, rem = p.pseudo_quo_rem(q); quo, rem ((3*x^4 + 13*x^3 + 19*x^2 + 5*x)*T + 18*x^4 + 12*x^3 + 16*x^2 + 16*x, (-113*x^6 - 106*x^5 - 133*x^4 - 101*x^3 - 42*x^2 - 41*x)*T - 34*x^6 + 13*x^5 + 54*x^4 + 126*x^3 + 134*x^2 - 5*x - 50) sage: (-x^2 - 4*x - 5)^(3-2+1) * p == quo*q + rem True
>>> from sage.all import * >>> R = PolynomialRing(ZZ, sparse=True, names=('x',)); (x,) = R._first_ngens(1) >>> p = x**Integer(4) + Integer(6)*x**Integer(3) + x**Integer(2) - x + Integer(2) >>> q = Integer(2)*x**Integer(2) - Integer(3)*x - Integer(1) >>> quo, rem = p.pseudo_quo_rem(q); quo, rem (4*x^2 + 30*x + 51, 175*x + 67) >>> Integer(2)**(Integer(4)-Integer(2)+Integer(1))*p == quo*q + rem True >>> S = R['T']; (T,) = S._first_ngens(1) >>> p = (-Integer(3)*x**Integer(2) - x)*T**Integer(3) - Integer(3)*x*T**Integer(2) + (x**Integer(2) - x)*T + Integer(2)*x**Integer(2) + Integer(3)*x - Integer(2) >>> q = (-x**Integer(2) - Integer(4)*x - Integer(5))*T**Integer(2) + (Integer(6)*x**Integer(2) + x + Integer(1))*T + Integer(2)*x**Integer(2) - x >>> quo, rem = p.pseudo_quo_rem(q); quo, rem ((3*x^4 + 13*x^3 + 19*x^2 + 5*x)*T + 18*x^4 + 12*x^3 + 16*x^2 + 16*x, (-113*x^6 - 106*x^5 - 133*x^4 - 101*x^3 - 42*x^2 - 41*x)*T - 34*x^6 + 13*x^5 + 54*x^4 + 126*x^3 + 134*x^2 - 5*x - 50) >>> (-x**Integer(2) - Integer(4)*x - Integer(5))**(Integer(3)-Integer(2)+Integer(1)) * p == quo*q + rem True
R.<x> = PolynomialRing(ZZ, sparse=True) p = x^4 + 6*x^3 + x^2 - x + 2 q = 2*x^2 - 3*x - 1 quo, rem = p.pseudo_quo_rem(q); quo, rem 2^(4-2+1)*p == quo*q + rem S.<T> = R[] p = (-3*x^2 - x)*T^3 - 3*x*T^2 + (x^2 - x)*T + 2*x^2 + 3*x - 2 q = (-x^2 - 4*x - 5)*T^2 + (6*x^2 + x + 1)*T + 2*x^2 - x quo, rem = p.pseudo_quo_rem(q); quo, rem (-x^2 - 4*x - 5)^(3-2+1) * p == quo*q + rem
- radical()[source]¶
Return the radical of
self
.Over a field, this is the product of the distinct irreducible factors of
self
. (This is also sometimes called the “square-free part” ofself
, but that term is ambiguous; it is sometimes used to mean the quotient ofself
by its maximal square factor.)EXAMPLES:
sage: P.<x> = ZZ[] sage: t = (x^2-x+1)^3 * (3*x-1)^2 sage: t.radical() 3*x^3 - 4*x^2 + 4*x - 1 sage: radical(12 * x^5) 6*x
>>> from sage.all import * >>> P = ZZ['x']; (x,) = P._first_ngens(1) >>> t = (x**Integer(2)-x+Integer(1))**Integer(3) * (Integer(3)*x-Integer(1))**Integer(2) >>> t.radical() 3*x^3 - 4*x^2 + 4*x - 1 >>> radical(Integer(12) * x**Integer(5)) 6*x
P.<x> = ZZ[] t = (x^2-x+1)^3 * (3*x-1)^2 t.radical() radical(12 * x^5)
If
self
has a factor of multiplicity divisible by the characteristic (see Issue #8736):sage: P.<x> = GF(2)[] sage: (x^3 + x^2).radical() # needs sage.rings.finite_rings x^2 + x
>>> from sage.all import * >>> P = GF(Integer(2))['x']; (x,) = P._first_ngens(1) >>> (x**Integer(3) + x**Integer(2)).radical() # needs sage.rings.finite_rings x^2 + x
P.<x> = GF(2)[] (x^3 + x^2).radical() # needs sage.rings.finite_rings
- rational_reconstruct(*args, **kwds)[source]¶
Deprecated: Use
rational_reconstruction()
instead. See Issue #12696 for details.
- rational_reconstruction(m, n_deg=None, d_deg=None)[source]¶
Return a tuple of two polynomials
(n, d)
whereself * d
is congruent ton
modulom
andn.degree() <= n_deg
andd.degree() <= d_deg
.INPUT:
m
– a univariate polynomialn_deg
– (optional) an integer; the default is \(\lfloor (\deg(m) - 1)/2 \rfloor\)d_deg
– (optional) an integer; the default is \(\lfloor (\deg(m) - 1)/2 \rfloor\)
ALGORITHM:
The algorithm is based on the extended Euclidean algorithm for the polynomial greatest common divisor.
EXAMPLES:
Over \(\QQ[z]\):
sage: z = PolynomialRing(QQ, 'z').gen() sage: p = -z**16 - z**15 - z**14 + z**13 + z**12 + z**11 - z**5 - z**4 - z**3 + z**2 + z + 1 sage: m = z**21 sage: n, d = p.rational_reconstruction(m); n, d (z^4 + 2*z^3 + 3*z^2 + 2*z + 1, z^10 + z^9 + z^8 + z^7 + z^6 + z^5 + z^4 + z^3 + z^2 + z + 1) sage: ((p*d - n) % m).is_zero() True
>>> from sage.all import * >>> z = PolynomialRing(QQ, 'z').gen() >>> p = -z**Integer(16) - z**Integer(15) - z**Integer(14) + z**Integer(13) + z**Integer(12) + z**Integer(11) - z**Integer(5) - z**Integer(4) - z**Integer(3) + z**Integer(2) + z + Integer(1) >>> m = z**Integer(21) >>> n, d = p.rational_reconstruction(m); n, d (z^4 + 2*z^3 + 3*z^2 + 2*z + 1, z^10 + z^9 + z^8 + z^7 + z^6 + z^5 + z^4 + z^3 + z^2 + z + 1) >>> ((p*d - n) % m).is_zero() True
z = PolynomialRing(QQ, 'z').gen() p = -z**16 - z**15 - z**14 + z**13 + z**12 + z**11 - z**5 - z**4 - z**3 + z**2 + z + 1 m = z**21 n, d = p.rational_reconstruction(m); n, d ((p*d - n) % m).is_zero()
Over \(\ZZ[z]\):
sage: z = PolynomialRing(ZZ, 'z').gen() sage: p = -z**16 - z**15 - z**14 + z**13 + z**12 + z**11 - z**5 - z**4 - z**3 + z**2 + z + 1 sage: m = z**21 sage: n, d = p.rational_reconstruction(m); n, d (z^4 + 2*z^3 + 3*z^2 + 2*z + 1, z^10 + z^9 + z^8 + z^7 + z^6 + z^5 + z^4 + z^3 + z^2 + z + 1) sage: ((p*d - n) % m).is_zero() True
>>> from sage.all import * >>> z = PolynomialRing(ZZ, 'z').gen() >>> p = -z**Integer(16) - z**Integer(15) - z**Integer(14) + z**Integer(13) + z**Integer(12) + z**Integer(11) - z**Integer(5) - z**Integer(4) - z**Integer(3) + z**Integer(2) + z + Integer(1) >>> m = z**Integer(21) >>> n, d = p.rational_reconstruction(m); n, d (z^4 + 2*z^3 + 3*z^2 + 2*z + 1, z^10 + z^9 + z^8 + z^7 + z^6 + z^5 + z^4 + z^3 + z^2 + z + 1) >>> ((p*d - n) % m).is_zero() True
z = PolynomialRing(ZZ, 'z').gen() p = -z**16 - z**15 - z**14 + z**13 + z**12 + z**11 - z**5 - z**4 - z**3 + z**2 + z + 1 m = z**21 n, d = p.rational_reconstruction(m); n, d ((p*d - n) % m).is_zero()
Over an integral domain,
d
might not be monic:sage: P = PolynomialRing(ZZ, 'x') sage: x = P.gen() sage: p = 7*x^5 - 10*x^4 + 16*x^3 - 32*x^2 + 128*x + 256 sage: m = x^5 sage: n, d = p.rational_reconstruction(m, 3, 2); n, d (-32*x^3 + 384*x^2 + 2304*x + 2048, 5*x + 8) sage: ((p*d - n) % m).is_zero() True sage: n, d = p.rational_reconstruction(m, 4, 0); n, d (-10*x^4 + 16*x^3 - 32*x^2 + 128*x + 256, 1) sage: ((p*d - n) % m).is_zero() True
>>> from sage.all import * >>> P = PolynomialRing(ZZ, 'x') >>> x = P.gen() >>> p = Integer(7)*x**Integer(5) - Integer(10)*x**Integer(4) + Integer(16)*x**Integer(3) - Integer(32)*x**Integer(2) + Integer(128)*x + Integer(256) >>> m = x**Integer(5) >>> n, d = p.rational_reconstruction(m, Integer(3), Integer(2)); n, d (-32*x^3 + 384*x^2 + 2304*x + 2048, 5*x + 8) >>> ((p*d - n) % m).is_zero() True >>> n, d = p.rational_reconstruction(m, Integer(4), Integer(0)); n, d (-10*x^4 + 16*x^3 - 32*x^2 + 128*x + 256, 1) >>> ((p*d - n) % m).is_zero() True
P = PolynomialRing(ZZ, 'x') x = P.gen() p = 7*x^5 - 10*x^4 + 16*x^3 - 32*x^2 + 128*x + 256 m = x^5 n, d = p.rational_reconstruction(m, 3, 2); n, d ((p*d - n) % m).is_zero() n, d = p.rational_reconstruction(m, 4, 0); n, d ((p*d - n) % m).is_zero()
Over \(\QQ(t)[z]\):
sage: P = PolynomialRing(QQ, 't') sage: t = P.gen() sage: Pz = PolynomialRing(P.fraction_field(), 'z') sage: z = Pz.gen() sage: # p = (1 + t^2*z + z^4) / (1 - t*z) sage: p = (1 + t^2*z + z^4)*(1 - t*z).inverse_mod(z^9) sage: m = z^9 sage: n, d = p.rational_reconstruction(m); n, d (-1/t*z^4 - t*z - 1/t, z - 1/t) sage: ((p*d - n) % m).is_zero() True sage: w = PowerSeriesRing(P.fraction_field(), 'w').gen() sage: n = -10*t^2*z^4 + (-t^2 + t - 1)*z^3 + (-t - 8)*z^2 + z + 2*t^2 - t sage: d = z^4 + (2*t + 4)*z^3 + (-t + 5)*z^2 + (t^2 + 2)*z + t^2 + 2*t + 1 sage: prec = 9 sage: x = n.subs(z=w)/d.subs(z=w) + O(w^prec) sage: # needs sage.libs.flint (otherwise timeout) sage: nc, dc = Pz(x.list()).rational_reconstruction(z^prec) sage: (nc, dc) == (n, d) True
>>> from sage.all import * >>> P = PolynomialRing(QQ, 't') >>> t = P.gen() >>> Pz = PolynomialRing(P.fraction_field(), 'z') >>> z = Pz.gen() >>> # p = (1 + t^2*z + z^4) / (1 - t*z) >>> p = (Integer(1) + t**Integer(2)*z + z**Integer(4))*(Integer(1) - t*z).inverse_mod(z**Integer(9)) >>> m = z**Integer(9) >>> n, d = p.rational_reconstruction(m); n, d (-1/t*z^4 - t*z - 1/t, z - 1/t) >>> ((p*d - n) % m).is_zero() True >>> w = PowerSeriesRing(P.fraction_field(), 'w').gen() >>> n = -Integer(10)*t**Integer(2)*z**Integer(4) + (-t**Integer(2) + t - Integer(1))*z**Integer(3) + (-t - Integer(8))*z**Integer(2) + z + Integer(2)*t**Integer(2) - t >>> d = z**Integer(4) + (Integer(2)*t + Integer(4))*z**Integer(3) + (-t + Integer(5))*z**Integer(2) + (t**Integer(2) + Integer(2))*z + t**Integer(2) + Integer(2)*t + Integer(1) >>> prec = Integer(9) >>> x = n.subs(z=w)/d.subs(z=w) + O(w**prec) >>> # needs sage.libs.flint (otherwise timeout) >>> nc, dc = Pz(x.list()).rational_reconstruction(z**prec) >>> (nc, dc) == (n, d) True
P = PolynomialRing(QQ, 't') t = P.gen() Pz = PolynomialRing(P.fraction_field(), 'z') z = Pz.gen() # p = (1 + t^2*z + z^4) / (1 - t*z) p = (1 + t^2*z + z^4)*(1 - t*z).inverse_mod(z^9) m = z^9 n, d = p.rational_reconstruction(m); n, d ((p*d - n) % m).is_zero() w = PowerSeriesRing(P.fraction_field(), 'w').gen() n = -10*t^2*z^4 + (-t^2 + t - 1)*z^3 + (-t - 8)*z^2 + z + 2*t^2 - t d = z^4 + (2*t + 4)*z^3 + (-t + 5)*z^2 + (t^2 + 2)*z + t^2 + 2*t + 1 prec = 9 x = n.subs(z=w)/d.subs(z=w) + O(w^prec) # needs sage.libs.flint (otherwise timeout) nc, dc = Pz(x.list()).rational_reconstruction(z^prec) (nc, dc) == (n, d)
Over \(\QQ[t][z]\):
sage: P = PolynomialRing(QQ, 't') sage: t = P.gen() sage: z = PolynomialRing(P, 'z').gen() sage: # p = (1 + t^2*z + z^4) / (1 - t*z) mod z^9 sage: p = (1 + t^2*z + z^4) * sum((t*z)**i for i in range(9)) sage: m = z^9 sage: n, d = p.rational_reconstruction(m,); n, d (-z^4 - t^2*z - 1, t*z - 1) sage: ((p*d - n) % m).is_zero() True
>>> from sage.all import * >>> P = PolynomialRing(QQ, 't') >>> t = P.gen() >>> z = PolynomialRing(P, 'z').gen() >>> # p = (1 + t^2*z + z^4) / (1 - t*z) mod z^9 >>> p = (Integer(1) + t**Integer(2)*z + z**Integer(4)) * sum((t*z)**i for i in range(Integer(9))) >>> m = z**Integer(9) >>> n, d = p.rational_reconstruction(m,); n, d (-z^4 - t^2*z - 1, t*z - 1) >>> ((p*d - n) % m).is_zero() True
P = PolynomialRing(QQ, 't') t = P.gen() z = PolynomialRing(P, 'z').gen() # p = (1 + t^2*z + z^4) / (1 - t*z) mod z^9 p = (1 + t^2*z + z^4) * sum((t*z)**i for i in range(9)) m = z^9 n, d = p.rational_reconstruction(m,); n, d ((p*d - n) % m).is_zero()
Over \(\QQ_5\):
sage: # needs sage.rings.padics sage: x = PolynomialRing(Qp(5), 'x').gen() sage: p = 4*x^5 + 3*x^4 + 2*x^3 + 2*x^2 + 4*x + 2 sage: m = x^6 sage: n, d = p.rational_reconstruction(m, 3, 2) sage: ((p*d - n) % m).is_zero() True
>>> from sage.all import * >>> # needs sage.rings.padics >>> x = PolynomialRing(Qp(Integer(5)), 'x').gen() >>> p = Integer(4)*x**Integer(5) + Integer(3)*x**Integer(4) + Integer(2)*x**Integer(3) + Integer(2)*x**Integer(2) + Integer(4)*x + Integer(2) >>> m = x**Integer(6) >>> n, d = p.rational_reconstruction(m, Integer(3), Integer(2)) >>> ((p*d - n) % m).is_zero() True
# needs sage.rings.padics x = PolynomialRing(Qp(5), 'x').gen() p = 4*x^5 + 3*x^4 + 2*x^3 + 2*x^2 + 4*x + 2 m = x^6 n, d = p.rational_reconstruction(m, 3, 2) ((p*d - n) % m).is_zero()
Can also be used to obtain known Padé approximations:
sage: z = PowerSeriesRing(QQ, 'z').gen() sage: P = PolynomialRing(QQ, 'x') sage: x = P.gen() sage: p = P(z.exp().list()) sage: m = x^5 sage: n, d = p.rational_reconstruction(m, 4, 0); n, d (1/24*x^4 + 1/6*x^3 + 1/2*x^2 + x + 1, 1) sage: ((p*d - n) % m).is_zero() True sage: m = x^3 sage: n, d = p.rational_reconstruction(m, 1, 1); n, d (-x - 2, x - 2) sage: ((p*d - n) % m).is_zero() True sage: p = P(log(1-z).list()) sage: m = x^9 sage: n, d = p.rational_reconstruction(m, 4, 4); n, d (25/6*x^4 - 130/3*x^3 + 105*x^2 - 70*x, x^4 - 20*x^3 + 90*x^2 - 140*x + 70) sage: ((p*d - n) % m).is_zero() True sage: p = P(sqrt(1+z).list()) sage: m = x^6 sage: n, d = p.rational_reconstruction(m, 3, 2); n, d (1/6*x^3 + 3*x^2 + 8*x + 16/3, x^2 + 16/3*x + 16/3) sage: ((p*d - n) % m).is_zero() True sage: p = P((2*z).exp().list()) sage: m = x^7 sage: n, d = p.rational_reconstruction(m, 3, 3); n, d (-x^3 - 6*x^2 - 15*x - 15, x^3 - 6*x^2 + 15*x - 15) sage: ((p*d - n) % m).is_zero() True
>>> from sage.all import * >>> z = PowerSeriesRing(QQ, 'z').gen() >>> P = PolynomialRing(QQ, 'x') >>> x = P.gen() >>> p = P(z.exp().list()) >>> m = x**Integer(5) >>> n, d = p.rational_reconstruction(m, Integer(4), Integer(0)); n, d (1/24*x^4 + 1/6*x^3 + 1/2*x^2 + x + 1, 1) >>> ((p*d - n) % m).is_zero() True >>> m = x**Integer(3) >>> n, d = p.rational_reconstruction(m, Integer(1), Integer(1)); n, d (-x - 2, x - 2) >>> ((p*d - n) % m).is_zero() True >>> p = P(log(Integer(1)-z).list()) >>> m = x**Integer(9) >>> n, d = p.rational_reconstruction(m, Integer(4), Integer(4)); n, d (25/6*x^4 - 130/3*x^3 + 105*x^2 - 70*x, x^4 - 20*x^3 + 90*x^2 - 140*x + 70) >>> ((p*d - n) % m).is_zero() True >>> p = P(sqrt(Integer(1)+z).list()) >>> m = x**Integer(6) >>> n, d = p.rational_reconstruction(m, Integer(3), Integer(2)); n, d (1/6*x^3 + 3*x^2 + 8*x + 16/3, x^2 + 16/3*x + 16/3) >>> ((p*d - n) % m).is_zero() True >>> p = P((Integer(2)*z).exp().list()) >>> m = x**Integer(7) >>> n, d = p.rational_reconstruction(m, Integer(3), Integer(3)); n, d (-x^3 - 6*x^2 - 15*x - 15, x^3 - 6*x^2 + 15*x - 15) >>> ((p*d - n) % m).is_zero() True
z = PowerSeriesRing(QQ, 'z').gen() P = PolynomialRing(QQ, 'x') x = P.gen() p = P(z.exp().list()) m = x^5 n, d = p.rational_reconstruction(m, 4, 0); n, d ((p*d - n) % m).is_zero() m = x^3 n, d = p.rational_reconstruction(m, 1, 1); n, d ((p*d - n) % m).is_zero() p = P(log(1-z).list()) m = x^9 n, d = p.rational_reconstruction(m, 4, 4); n, d ((p*d - n) % m).is_zero() p = P(sqrt(1+z).list()) m = x^6 n, d = p.rational_reconstruction(m, 3, 2); n, d ((p*d - n) % m).is_zero() p = P((2*z).exp().list()) m = x^7 n, d = p.rational_reconstruction(m, 3, 3); n, d ((p*d - n) % m).is_zero()
Over \(\RR[z]\):
sage: # needs sage.rings.real_mpfr sage: z = PowerSeriesRing(RR, 'z').gen() sage: P = PolynomialRing(RR, 'x') sage: x = P.gen() sage: p = P((2*z).exp().list()) sage: m = x^7 sage: n, d = p.rational_reconstruction(m, 3, 3); n, d # absolute tolerance 1e-10 (-x^3 - 6.0*x^2 - 15.0*x - 15.0, x^3 - 6.0*x^2 + 15.0*x - 15.0)
>>> from sage.all import * >>> # needs sage.rings.real_mpfr >>> z = PowerSeriesRing(RR, 'z').gen() >>> P = PolynomialRing(RR, 'x') >>> x = P.gen() >>> p = P((Integer(2)*z).exp().list()) >>> m = x**Integer(7) >>> n, d = p.rational_reconstruction(m, Integer(3), Integer(3)); n, d # absolute tolerance 1e-10 (-x^3 - 6.0*x^2 - 15.0*x - 15.0, x^3 - 6.0*x^2 + 15.0*x - 15.0)
# needs sage.rings.real_mpfr z = PowerSeriesRing(RR, 'z').gen() P = PolynomialRing(RR, 'x') x = P.gen() p = P((2*z).exp().list()) m = x^7 n, d = p.rational_reconstruction(m, 3, 3); n, d # absolute tolerance 1e-10
- real_roots()[source]¶
Return the real roots of this polynomial, without multiplicities.
Calls
self.roots(ring=RR)
, unless this is a polynomial with floating-point real coefficients, in which case it callsself.roots()
.EXAMPLES:
sage: x = polygen(ZZ) sage: (x^2 - x - 1).real_roots() # needs sage.libs.pari sage.rings.real_mpfr [-0.618033988749895, 1.61803398874989]
>>> from sage.all import * >>> x = polygen(ZZ) >>> (x**Integer(2) - x - Integer(1)).real_roots() # needs sage.libs.pari sage.rings.real_mpfr [-0.618033988749895, 1.61803398874989]
x = polygen(ZZ) (x^2 - x - 1).real_roots() # needs sage.libs.pari sage.rings.real_mpfr
- reciprocal_transform(R=1, q=1)[source]¶
Transform a general polynomial into a self-reciprocal polynomial.
The input \(Q\) and output \(P\) satisfy the relation
\[P(x) = Q(x + q/x) x^{\deg(Q)} R(x).\]In this relation, \(Q\) has all roots in the real interval \([-2\sqrt{q}, 2\sqrt{q}]\) if and only if \(P\) has all roots on the circle \(|x| = \sqrt{q}\) and \(R\) divides \(x^2-q\).
See also
The inverse operation is
trace_polynomial()
.INPUT:
R
– polynomialq
– scalar (default: \(1\))
EXAMPLES:
sage: pol.<x> = PolynomialRing(Rationals()) sage: u = x^2 + x - 1 sage: u.reciprocal_transform() x^4 + x^3 + x^2 + x + 1 sage: u.reciprocal_transform(R=x-1) x^5 - 1 sage: u.reciprocal_transform(q=3) x^4 + x^3 + 5*x^2 + 3*x + 9
>>> from sage.all import * >>> pol = PolynomialRing(Rationals(), names=('x',)); (x,) = pol._first_ngens(1) >>> u = x**Integer(2) + x - Integer(1) >>> u.reciprocal_transform() x^4 + x^3 + x^2 + x + 1 >>> u.reciprocal_transform(R=x-Integer(1)) x^5 - 1 >>> u.reciprocal_transform(q=Integer(3)) x^4 + x^3 + 5*x^2 + 3*x + 9
pol.<x> = PolynomialRing(Rationals()) u = x^2 + x - 1 u.reciprocal_transform() u.reciprocal_transform(R=x-1) u.reciprocal_transform(q=3)
- resultant(other)[source]¶
Return the resultant of
self
andother
.INPUT:
other
– a polynomial
OUTPUT: an element of the base ring of the polynomial ring
ALGORITHM:
Uses PARI’s function pari:polresultant. For base rings that are not supported by PARI, the resultant is computed as the determinant of the Sylvester matrix.
EXAMPLES:
sage: R.<x> = QQ[] sage: f = x^3 + x + 1; g = x^3 - x - 1 sage: r = f.resultant(g); r # needs sage.libs.pari -8 sage: r.parent() is QQ # needs sage.libs.pari True
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + x + Integer(1); g = x**Integer(3) - x - Integer(1) >>> r = f.resultant(g); r # needs sage.libs.pari -8 >>> r.parent() is QQ # needs sage.libs.pari True
R.<x> = QQ[] f = x^3 + x + 1; g = x^3 - x - 1 r = f.resultant(g); r # needs sage.libs.pari r.parent() is QQ # needs sage.libs.pari
We can compute resultants over univariate and multivariate polynomial rings:
sage: R.<a> = QQ[] sage: S.<x> = R[] sage: f = x^2 + a; g = x^3 + a sage: r = f.resultant(g); r # needs sage.libs.pari a^3 + a^2 sage: r.parent() is R # needs sage.libs.pari True
>>> from sage.all import * >>> R = QQ['a']; (a,) = R._first_ngens(1) >>> S = R['x']; (x,) = S._first_ngens(1) >>> f = x**Integer(2) + a; g = x**Integer(3) + a >>> r = f.resultant(g); r # needs sage.libs.pari a^3 + a^2 >>> r.parent() is R # needs sage.libs.pari True
R.<a> = QQ[] S.<x> = R[] f = x^2 + a; g = x^3 + a r = f.resultant(g); r # needs sage.libs.pari r.parent() is R # needs sage.libs.pari
sage: R.<a, b> = QQ[] sage: S.<x> = R[] sage: f = x^2 + a; g = x^3 + b sage: r = f.resultant(g); r # needs sage.libs.pari a^3 + b^2 sage: r.parent() is R # needs sage.libs.pari True
>>> from sage.all import * >>> R = QQ['a, b']; (a, b,) = R._first_ngens(2) >>> S = R['x']; (x,) = S._first_ngens(1) >>> f = x**Integer(2) + a; g = x**Integer(3) + b >>> r = f.resultant(g); r # needs sage.libs.pari a^3 + b^2 >>> r.parent() is R # needs sage.libs.pari True
R.<a, b> = QQ[] S.<x> = R[] f = x^2 + a; g = x^3 + b r = f.resultant(g); r # needs sage.libs.pari r.parent() is R # needs sage.libs.pari
>>> from sage.all import * >>> R = QQ['a, b']; (a, b,) = R._first_ngens(2) >>> S = R['x']; (x,) = S._first_ngens(1) >>> f = x**Integer(2) + a; g = x**Integer(3) + b >>> r = f.resultant(g); r # needs sage.libs.pari a^3 + b^2 >>> r.parent() is R # needs sage.libs.pari True
R.<a, b> = QQ[] S.<x> = R[] f = x^2 + a; g = x^3 + b r = f.resultant(g); r # needs sage.libs.pari r.parent() is R # needs sage.libs.pari
- reverse(degree=None)[source]¶
Return polynomial but with the coefficients reversed.
If an optional
degree
argument is given, the coefficient list will be truncated or zero padded as necessary before reversing it. Assuming that the constant coefficient ofself
is nonzero, the reverse polynomial will have the specified degree.EXAMPLES:
sage: R.<x> = ZZ[]; S.<y> = R[] sage: f = y^3 + x*y - 3*x; f y^3 + x*y - 3*x sage: f.reverse() -3*x*y^3 + x*y^2 + 1 sage: f.reverse(degree=2) -3*x*y^2 + x*y sage: f.reverse(degree=5) -3*x*y^5 + x*y^4 + y^2
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1); S = R['y']; (y,) = S._first_ngens(1) >>> f = y**Integer(3) + x*y - Integer(3)*x; f y^3 + x*y - 3*x >>> f.reverse() -3*x*y^3 + x*y^2 + 1 >>> f.reverse(degree=Integer(2)) -3*x*y^2 + x*y >>> f.reverse(degree=Integer(5)) -3*x*y^5 + x*y^4 + y^2
R.<x> = ZZ[]; S.<y> = R[] f = y^3 + x*y - 3*x; f f.reverse() f.reverse(degree=2) f.reverse(degree=5)
- revert_series(n)[source]¶
Return a polynomial
f
such thatf(self(x)) = self(f(x)) = x mod x^n
.Currently, this is only implemented over some coefficient rings.
EXAMPLES:
sage: Pol.<x> = QQ[] sage: (x + x^3/6 + x^5/120).revert_series(6) 3/40*x^5 - 1/6*x^3 + x sage: Pol.<x> = CBF[] # needs sage.libs.flint sage: (x + x^3/6 + x^5/120).revert_series(6) # needs sage.libs.flint ([0.075000000000000 +/- ...e-17])*x^5 + ([-0.166666666666667 +/- ...e-16])*x^3 + x sage: # needs sage.symbolic sage: Pol.<x> = SR[] sage: x.revert_series(6) Traceback (most recent call last): ... NotImplementedError: only implemented for certain base rings
>>> from sage.all import * >>> Pol = QQ['x']; (x,) = Pol._first_ngens(1) >>> (x + x**Integer(3)/Integer(6) + x**Integer(5)/Integer(120)).revert_series(Integer(6)) 3/40*x^5 - 1/6*x^3 + x >>> Pol = CBF['x']; (x,) = Pol._first_ngens(1)# needs sage.libs.flint >>> (x + x**Integer(3)/Integer(6) + x**Integer(5)/Integer(120)).revert_series(Integer(6)) # needs sage.libs.flint ([0.075000000000000 +/- ...e-17])*x^5 + ([-0.166666666666667 +/- ...e-16])*x^3 + x >>> # needs sage.symbolic >>> Pol = SR['x']; (x,) = Pol._first_ngens(1) >>> x.revert_series(Integer(6)) Traceback (most recent call last): ... NotImplementedError: only implemented for certain base rings
Pol.<x> = QQ[] (x + x^3/6 + x^5/120).revert_series(6) Pol.<x> = CBF[] # needs sage.libs.flint (x + x^3/6 + x^5/120).revert_series(6) # needs sage.libs.flint # needs sage.symbolic Pol.<x> = SR[] x.revert_series(6)
- root_field(names, check_irreducible=True)[source]¶
Return the field generated by the roots of the irreducible polynomial
self
. The output is either a number field, relative number field, a quotient of a polynomial ring over a field, or the fraction field of the base ring.EXAMPLES:
sage: R.<x> = QQ['x'] sage: f = x^3 + x + 17 sage: f.root_field('a') # needs sage.rings.number_field Number Field in a with defining polynomial x^3 + x + 17
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + x + Integer(17) >>> f.root_field('a') # needs sage.rings.number_field Number Field in a with defining polynomial x^3 + x + 17
R.<x> = QQ['x'] f = x^3 + x + 17 f.root_field('a') # needs sage.rings.number_field
sage: R.<x> = QQ['x'] sage: f = x - 3 sage: f.root_field('b') # needs sage.rings.number_field Rational Field
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x - Integer(3) >>> f.root_field('b') # needs sage.rings.number_field Rational Field
R.<x> = QQ['x'] f = x - 3 f.root_field('b') # needs sage.rings.number_field
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x - Integer(3) >>> f.root_field('b') # needs sage.rings.number_field Rational Field
R.<x> = QQ['x'] f = x - 3 f.root_field('b') # needs sage.rings.number_field
sage: R.<x> = ZZ['x'] sage: f = x^3 + x + 17 sage: f.root_field('b') # needs sage.rings.number_field Number Field in b with defining polynomial x^3 + x + 17
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + x + Integer(17) >>> f.root_field('b') # needs sage.rings.number_field Number Field in b with defining polynomial x^3 + x + 17
R.<x> = ZZ['x'] f = x^3 + x + 17 f.root_field('b') # needs sage.rings.number_field
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + x + Integer(17) >>> f.root_field('b') # needs sage.rings.number_field Number Field in b with defining polynomial x^3 + x + 17
R.<x> = ZZ['x'] f = x^3 + x + 17 f.root_field('b') # needs sage.rings.number_field
sage: # needs sage.rings.number_field sage: y = QQ['x'].0 sage: L.<a> = NumberField(y^3 - 2) sage: R.<x> = L['x'] sage: f = x^3 + x + 17 sage: f.root_field('c') Number Field in c with defining polynomial x^3 + x + 17 over its base field
>>> from sage.all import * >>> # needs sage.rings.number_field >>> y = QQ['x'].gen(0) >>> L = NumberField(y**Integer(3) - Integer(2), names=('a',)); (a,) = L._first_ngens(1) >>> R = L['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + x + Integer(17) >>> f.root_field('c') Number Field in c with defining polynomial x^3 + x + 17 over its base field
# needs sage.rings.number_field y = QQ['x'].0 L.<a> = NumberField(y^3 - 2) R.<x> = L['x'] f = x^3 + x + 17 f.root_field('c')
>>> from sage.all import * >>> # needs sage.rings.number_field >>> y = QQ['x'].gen(0) >>> L = NumberField(y**Integer(3) - Integer(2), names=('a',)); (a,) = L._first_ngens(1) >>> R = L['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + x + Integer(17) >>> f.root_field('c') Number Field in c with defining polynomial x^3 + x + 17 over its base field
# needs sage.rings.number_field y = QQ['x'].0 L.<a> = NumberField(y^3 - 2) R.<x> = L['x'] f = x^3 + x + 17 f.root_field('c')
sage: # needs sage.rings.finite_rings sage: R.<x> = PolynomialRing(GF(9, 'a')) sage: f = x^3 + x^2 + 8 sage: K.<alpha> = f.root_field(); K Univariate Quotient Polynomial Ring in alpha over Finite Field in a of size 3^2 with modulus x^3 + x^2 + 2 sage: alpha^2 + 1 alpha^2 + 1 sage: alpha^3 + alpha^2 1
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> R = PolynomialRing(GF(Integer(9), 'a'), names=('x',)); (x,) = R._first_ngens(1) >>> f = x**Integer(3) + x**Integer(2) + Integer(8) >>> K = f.root_field(names=('alpha',)); (alpha,) = K._first_ngens(1); K Univariate Quotient Polynomial Ring in alpha over Finite Field in a of size 3^2 with modulus x^3 + x^2 + 2 >>> alpha**Integer(2) + Integer(1) alpha^2 + 1 >>> alpha**Integer(3) + alpha**Integer(2) 1
# needs sage.rings.finite_rings R.<x> = PolynomialRing(GF(9, 'a')) f = x^3 + x^2 + 8 K.<alpha> = f.root_field(); K alpha^2 + 1 alpha^3 + alpha^2
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> R = PolynomialRing(GF(Integer(9), 'a'), names=('x',)); (x,) = R._first_ngens(1) >>> f = x**Integer(3) + x**Integer(2) + Integer(8) >>> K = f.root_field(names=('alpha',)); (alpha,) = K._first_ngens(1); K Univariate Quotient Polynomial Ring in alpha over Finite Field in a of size 3^2 with modulus x^3 + x^2 + 2 >>> alpha**Integer(2) + Integer(1) alpha^2 + 1 >>> alpha**Integer(3) + alpha**Integer(2) 1
# needs sage.rings.finite_rings R.<x> = PolynomialRing(GF(9, 'a')) f = x^3 + x^2 + 8 K.<alpha> = f.root_field(); K alpha^2 + 1 alpha^3 + alpha^2
sage: R.<x> = QQ[] sage: f = x^2 sage: K.<alpha> = f.root_field() # needs sage.libs.pari Traceback (most recent call last): ... ValueError: polynomial must be irreducible
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) >>> K = f.root_field(names=('alpha',)); (alpha,) = K._first_ngens(1)# needs sage.libs.pari Traceback (most recent call last): ... ValueError: polynomial must be irreducible
R.<x> = QQ[] f = x^2 K.<alpha> = f.root_field() # needs sage.libs.pari
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) >>> K = f.root_field(names=('alpha',)); (alpha,) = K._first_ngens(1)# needs sage.libs.pari Traceback (most recent call last): ... ValueError: polynomial must be irreducible
R.<x> = QQ[] f = x^2 K.<alpha> = f.root_field() # needs sage.libs.pari
- roots(ring=None, multiplicities=True, algorithm=None, **kwds)[source]¶
Return the roots of this polynomial (by default, in the base ring of this polynomial).
INPUT:
ring
– the ring to find roots inmultiplicities
– boolean (default:True
); ifTrue
return list of pairs \((r, n)\), where \(r\) is the root and \(n\) is the multiplicity. IfFalse
, just return the unique roots, with no information about multiplicities.algorithm
– the root-finding algorithm to use. We attempt to select a reasonable algorithm by default, but this lets the caller override our choice.
By default, this finds all the roots that lie in the base ring of the polynomial. However, the ring parameter can be used to specify a ring to look for roots in.
If the polynomial and the output ring are both exact (integers, rationals, finite fields, etc.), then the output should always be correct (or raise an exception, if that case is not yet handled).
If the output ring is approximate (floating-point real or complex numbers), then the answer will be estimated numerically, using floating-point arithmetic of at least the precision of the output ring. If the polynomial is ill-conditioned, meaning that a small change in the coefficients of the polynomial will lead to a relatively large change in the location of the roots, this may give poor results. Distinct roots may be returned as multiple roots, multiple roots may be returned as distinct roots, real roots may be lost entirely (because the numerical estimate thinks they are complex roots). Note that polynomials with multiple roots are always ill-conditioned; there’s a footnote at the end of the docstring about this.
If the output ring is a
RealIntervalField
orComplexIntervalField
of a given precision, then the answer will always be correct (or an exception will be raised, if a case is not implemented). Each root will be contained in one of the returned intervals, and the intervals will be disjoint. (The returned intervals may be of higher precision than the specified output ring.)At the end of this docstring (after the examples) is a description of all the cases implemented in this function, and the algorithms used. That section also describes the possibilities for the
algorithm
keyword, for the cases where multiple algorithms exist.EXAMPLES:
sage: # needs sage.libs.pari sage: x = QQ['x'].0 sage: f = x^3 - 1 sage: f.roots() [(1, 1)] sage: f.roots(ring=CC) # ... - low order bits slightly different on ppc # needs sage.rings.real_mpfr [(1.00000000000000, 1), (-0.500000000000000 - 0.86602540378443...*I, 1), (-0.500000000000000 + 0.86602540378443...*I, 1)] sage: f = (x^3 - 1)^2 sage: f.roots() [(1, 2)] sage: f = -19*x + 884736 sage: f.roots() [(884736/19, 1)] sage: (f^20).roots() [(884736/19, 20)]
>>> from sage.all import * >>> # needs sage.libs.pari >>> x = QQ['x'].gen(0) >>> f = x**Integer(3) - Integer(1) >>> f.roots() [(1, 1)] >>> f.roots(ring=CC) # ... - low order bits slightly different on ppc # needs sage.rings.real_mpfr [(1.00000000000000, 1), (-0.500000000000000 - 0.86602540378443...*I, 1), (-0.500000000000000 + 0.86602540378443...*I, 1)] >>> f = (x**Integer(3) - Integer(1))**Integer(2) >>> f.roots() [(1, 2)] >>> f = -Integer(19)*x + Integer(884736) >>> f.roots() [(884736/19, 1)] >>> (f**Integer(20)).roots() [(884736/19, 20)]
# needs sage.libs.pari x = QQ['x'].0 f = x^3 - 1 f.roots() f.roots(ring=CC) # ... - low order bits slightly different on ppc # needs sage.rings.real_mpfr f = (x^3 - 1)^2 f.roots() f = -19*x + 884736 f.roots() (f^20).roots()
sage: # needs sage.rings.number_field sage: K.<z> = CyclotomicField(3) sage: f = K.defining_polynomial() sage: f.roots(ring=GF(7)) [(4, 1), (2, 1)] sage: g = f.change_ring(GF(7)) sage: g.roots() [(4, 1), (2, 1)] sage: g.roots(multiplicities=False) [4, 2]
>>> from sage.all import * >>> # needs sage.rings.number_field >>> K = CyclotomicField(Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> f = K.defining_polynomial() >>> f.roots(ring=GF(Integer(7))) [(4, 1), (2, 1)] >>> g = f.change_ring(GF(Integer(7))) >>> g.roots() [(4, 1), (2, 1)] >>> g.roots(multiplicities=False) [4, 2]
# needs sage.rings.number_field K.<z> = CyclotomicField(3) f = K.defining_polynomial() f.roots(ring=GF(7)) g = f.change_ring(GF(7)) g.roots() g.roots(multiplicities=False)
>>> from sage.all import * >>> # needs sage.rings.number_field >>> K = CyclotomicField(Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> f = K.defining_polynomial() >>> f.roots(ring=GF(Integer(7))) [(4, 1), (2, 1)] >>> g = f.change_ring(GF(Integer(7))) >>> g.roots() [(4, 1), (2, 1)] >>> g.roots(multiplicities=False) [4, 2]
# needs sage.rings.number_field K.<z> = CyclotomicField(3) f = K.defining_polynomial() f.roots(ring=GF(7)) g = f.change_ring(GF(7)) g.roots() g.roots(multiplicities=False)
A new ring. In the example below, we add the special method
_roots_univariate_polynomial()
to the base ring, and observe that this method is called instead to find roots of polynomials over this ring. This facility can be used to easily extend root finding to work over new rings you introduce:sage: R.<x> = QQ[] sage: (x^2 + 1).roots() # needs sage.libs.pari [] sage: def my_roots(f, *args, **kwds): ....: return f.change_ring(CDF).roots() sage: QQ._roots_univariate_polynomial = my_roots sage: (x^2 + 1).roots() # abs tol 1e-14 # needs numpy [(2.7755575615628914e-17 - 1.0*I, 1), (0.9999999999999997*I, 1)] sage: del QQ._roots_univariate_polynomial
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> (x**Integer(2) + Integer(1)).roots() # needs sage.libs.pari [] >>> def my_roots(f, *args, **kwds): ... return f.change_ring(CDF).roots() >>> QQ._roots_univariate_polynomial = my_roots >>> (x**Integer(2) + Integer(1)).roots() # abs tol 1e-14 # needs numpy [(2.7755575615628914e-17 - 1.0*I, 1), (0.9999999999999997*I, 1)] >>> del QQ._roots_univariate_polynomial
R.<x> = QQ[] (x^2 + 1).roots() # needs sage.libs.pari def my_roots(f, *args, **kwds): return f.change_ring(CDF).roots() QQ._roots_univariate_polynomial = my_roots (x^2 + 1).roots() # abs tol 1e-14 # needs numpy del QQ._roots_univariate_polynomial
An example over RR, which illustrates that only the roots in RR are returned:
sage: # needs numpy sage.rings.real_mpfr sage: x = RR['x'].0 sage: f = x^3 - 2 sage: f.roots() [(1.25992104989487, 1)] sage: f.factor() (x - 1.25992104989487) * (x^2 + 1.25992104989487*x + 1.58740105196820) sage: x = RealField(100)['x'].0 sage: f = x^3 - 2 sage: f.roots() [(1.2599210498948731647672106073, 1)]
>>> from sage.all import * >>> # needs numpy sage.rings.real_mpfr >>> x = RR['x'].gen(0) >>> f = x**Integer(3) - Integer(2) >>> f.roots() [(1.25992104989487, 1)] >>> f.factor() (x - 1.25992104989487) * (x^2 + 1.25992104989487*x + 1.58740105196820) >>> x = RealField(Integer(100))['x'].gen(0) >>> f = x**Integer(3) - Integer(2) >>> f.roots() [(1.2599210498948731647672106073, 1)]
# needs numpy sage.rings.real_mpfr x = RR['x'].0 f = x^3 - 2 f.roots() f.factor() x = RealField(100)['x'].0 f = x^3 - 2 f.roots()
sage: # needs sage.rings.real_mpfr sage: x = CC['x'].0 sage: f = x^3 - 2 sage: f.roots() # needs numpy [(1.25992104989487, 1), (-0.62996052494743... - 1.09112363597172*I, 1), (-0.62996052494743... + 1.09112363597172*I, 1)] sage: f.roots(algorithm='pari') # needs sage.libs.pari [(1.25992104989487, 1), (-0.629960524947437 - 1.09112363597172*I, 1), (-0.629960524947437 + 1.09112363597172*I, 1)]
>>> from sage.all import * >>> # needs sage.rings.real_mpfr >>> x = CC['x'].gen(0) >>> f = x**Integer(3) - Integer(2) >>> f.roots() # needs numpy [(1.25992104989487, 1), (-0.62996052494743... - 1.09112363597172*I, 1), (-0.62996052494743... + 1.09112363597172*I, 1)] >>> f.roots(algorithm='pari') # needs sage.libs.pari [(1.25992104989487, 1), (-0.629960524947437 - 1.09112363597172*I, 1), (-0.629960524947437 + 1.09112363597172*I, 1)]
# needs sage.rings.real_mpfr x = CC['x'].0 f = x^3 - 2 f.roots() # needs numpy f.roots(algorithm='pari') # needs sage.libs.pari
>>> from sage.all import * >>> # needs sage.rings.real_mpfr >>> x = CC['x'].gen(0) >>> f = x**Integer(3) - Integer(2) >>> f.roots() # needs numpy [(1.25992104989487, 1), (-0.62996052494743... - 1.09112363597172*I, 1), (-0.62996052494743... + 1.09112363597172*I, 1)] >>> f.roots(algorithm='pari') # needs sage.libs.pari [(1.25992104989487, 1), (-0.629960524947437 - 1.09112363597172*I, 1), (-0.629960524947437 + 1.09112363597172*I, 1)]
# needs sage.rings.real_mpfr x = CC['x'].0 f = x^3 - 2 f.roots() # needs numpy f.roots(algorithm='pari') # needs sage.libs.pari
Another example showing that only roots in the base ring are returned:
sage: x = polygen(ZZ) sage: f = (2*x - 3) * (x - 1) * (x + 1) sage: f.roots() # needs sage.libs.pari [(1, 1), (-1, 1)] sage: f.roots(ring=QQ) # needs sage.libs.pari [(3/2, 1), (1, 1), (-1, 1)]
>>> from sage.all import * >>> x = polygen(ZZ) >>> f = (Integer(2)*x - Integer(3)) * (x - Integer(1)) * (x + Integer(1)) >>> f.roots() # needs sage.libs.pari [(1, 1), (-1, 1)] >>> f.roots(ring=QQ) # needs sage.libs.pari [(3/2, 1), (1, 1), (-1, 1)]
x = polygen(ZZ) f = (2*x - 3) * (x - 1) * (x + 1) f.roots() # needs sage.libs.pari f.roots(ring=QQ) # needs sage.libs.pari
An example where we compute the roots lying in a subring of the base ring:
sage: Pols.<n> = QQ[] sage: pol = (n - 1/2)^2 * (n - 1)^2 * (n - 2) sage: pol.roots(ZZ) # needs sage.libs.pari [(2, 1), (1, 2)]
>>> from sage.all import * >>> Pols = QQ['n']; (n,) = Pols._first_ngens(1) >>> pol = (n - Integer(1)/Integer(2))**Integer(2) * (n - Integer(1))**Integer(2) * (n - Integer(2)) >>> pol.roots(ZZ) # needs sage.libs.pari [(2, 1), (1, 2)]
Pols.<n> = QQ[] pol = (n - 1/2)^2 * (n - 1)^2 * (n - 2) pol.roots(ZZ) # needs sage.libs.pari
An example involving large numbers:
sage: # needs numpy sage.rings.real_mpfr sage: x = RR['x'].0 sage: f = x^2 - 1e100 sage: f.roots() [(-1.00000000000000e50, 1), (1.00000000000000e50, 1)] sage: f = x^10 - 2 * (5*x - 1)^2 sage: f.roots(multiplicities=False) [-1.6772670339941..., 0.19995479628..., 0.20004530611..., 1.5763035161844...]
>>> from sage.all import * >>> # needs numpy sage.rings.real_mpfr >>> x = RR['x'].gen(0) >>> f = x**Integer(2) - RealNumber('1e100') >>> f.roots() [(-1.00000000000000e50, 1), (1.00000000000000e50, 1)] >>> f = x**Integer(10) - Integer(2) * (Integer(5)*x - Integer(1))**Integer(2) >>> f.roots(multiplicities=False) [-1.6772670339941..., 0.19995479628..., 0.20004530611..., 1.5763035161844...]
# needs numpy sage.rings.real_mpfr x = RR['x'].0 f = x^2 - 1e100 f.roots() f = x^10 - 2 * (5*x - 1)^2 f.roots(multiplicities=False)
sage: # needs numpy sage.rings.real_mpfr sage: x = CC['x'].0 sage: i = CC.0 sage: f = (x - 1) * (x - i) sage: f.roots(multiplicities=False) [1.00000000000000, 1.00000000000000*I] sage: g = (x - 1.33 + 1.33*i) * (x - 2.66 - 2.66*i) sage: g.roots(multiplicities=False) [1.33000000000000 - 1.33000000000000*I, 2.66000000000000 + 2.66000000000000*I]
>>> from sage.all import * >>> # needs numpy sage.rings.real_mpfr >>> x = CC['x'].gen(0) >>> i = CC.gen(0) >>> f = (x - Integer(1)) * (x - i) >>> f.roots(multiplicities=False) [1.00000000000000, 1.00000000000000*I] >>> g = (x - RealNumber('1.33') + RealNumber('1.33')*i) * (x - RealNumber('2.66') - RealNumber('2.66')*i) >>> g.roots(multiplicities=False) [1.33000000000000 - 1.33000000000000*I, 2.66000000000000 + 2.66000000000000*I]
# needs numpy sage.rings.real_mpfr x = CC['x'].0 i = CC.0 f = (x - 1) * (x - i) f.roots(multiplicities=False) g = (x - 1.33 + 1.33*i) * (x - 2.66 - 2.66*i) g.roots(multiplicities=False)
>>> from sage.all import * >>> # needs numpy sage.rings.real_mpfr >>> x = CC['x'].gen(0) >>> i = CC.gen(0) >>> f = (x - Integer(1)) * (x - i) >>> f.roots(multiplicities=False) [1.00000000000000, 1.00000000000000*I] >>> g = (x - RealNumber('1.33') + RealNumber('1.33')*i) * (x - RealNumber('2.66') - RealNumber('2.66')*i) >>> g.roots(multiplicities=False) [1.33000000000000 - 1.33000000000000*I, 2.66000000000000 + 2.66000000000000*I]
# needs numpy sage.rings.real_mpfr x = CC['x'].0 i = CC.0 f = (x - 1) * (x - i) f.roots(multiplicities=False) g = (x - 1.33 + 1.33*i) * (x - 2.66 - 2.66*i) g.roots(multiplicities=False)
Describing roots using radical expressions:
sage: x = QQ['x'].0 sage: f = x^2 + 2 sage: f.roots(SR) # needs sage.symbolic [(-I*sqrt(2), 1), (I*sqrt(2), 1)] sage: f.roots(SR, multiplicities=False) # needs sage.symbolic [-I*sqrt(2), I*sqrt(2)]
>>> from sage.all import * >>> x = QQ['x'].gen(0) >>> f = x**Integer(2) + Integer(2) >>> f.roots(SR) # needs sage.symbolic [(-I*sqrt(2), 1), (I*sqrt(2), 1)] >>> f.roots(SR, multiplicities=False) # needs sage.symbolic [-I*sqrt(2), I*sqrt(2)]
x = QQ['x'].0 f = x^2 + 2 f.roots(SR) # needs sage.symbolic f.roots(SR, multiplicities=False) # needs sage.symbolic
The roots of some polynomials cannot be described using radical expressions:
sage: (x^5 - x + 1).roots(SR) # needs sage.symbolic []
>>> from sage.all import * >>> (x**Integer(5) - x + Integer(1)).roots(SR) # needs sage.symbolic []
(x^5 - x + 1).roots(SR) # needs sage.symbolic
For some other polynomials, no roots can be found at the moment due to the way roots are computed. Issue #17516 addresses these defects. Until that gets implemented, one such example is the following:
sage: f = x^6 - 300*x^5 + 30361*x^4 - 1061610*x^3 + 1141893*x^2 - 915320*x + 101724 sage: f.roots() # needs sage.libs.pari []
>>> from sage.all import * >>> f = x**Integer(6) - Integer(300)*x**Integer(5) + Integer(30361)*x**Integer(4) - Integer(1061610)*x**Integer(3) + Integer(1141893)*x**Integer(2) - Integer(915320)*x + Integer(101724) >>> f.roots() # needs sage.libs.pari []
f = x^6 - 300*x^5 + 30361*x^4 - 1061610*x^3 + 1141893*x^2 - 915320*x + 101724 f.roots() # needs sage.libs.pari
A purely symbolic roots example:
sage: # needs sage.symbolic sage: X = var('X') sage: f = expand((X - 1) * (X - I)^3 * (X^2 - sqrt(2))); f X^6 - (3*I + 1)*X^5 - sqrt(2)*X^4 + (3*I - 3)*X^4 + (3*I + 1)*sqrt(2)*X^3 + (I + 3)*X^3 - (3*I - 3)*sqrt(2)*X^2 - I*X^2 - (I + 3)*sqrt(2)*X + I*sqrt(2) sage: f.roots() [(I, 3), (-2^(1/4), 1), (2^(1/4), 1), (1, 1)]
>>> from sage.all import * >>> # needs sage.symbolic >>> X = var('X') >>> f = expand((X - Integer(1)) * (X - I)**Integer(3) * (X**Integer(2) - sqrt(Integer(2)))); f X^6 - (3*I + 1)*X^5 - sqrt(2)*X^4 + (3*I - 3)*X^4 + (3*I + 1)*sqrt(2)*X^3 + (I + 3)*X^3 - (3*I - 3)*sqrt(2)*X^2 - I*X^2 - (I + 3)*sqrt(2)*X + I*sqrt(2) >>> f.roots() [(I, 3), (-2^(1/4), 1), (2^(1/4), 1), (1, 1)]
# needs sage.symbolic X = var('X') f = expand((X - 1) * (X - I)^3 * (X^2 - sqrt(2))); f f.roots()
The same operation, performed over a polynomial ring with symbolic coefficients:
sage: # needs sage.symbolic sage: X = SR['X'].0 sage: f = (X - 1) * (X - I)^3 * (X^2 - sqrt(2)); f X^6 + (-3*I - 1)*X^5 + (-sqrt(2) + 3*I - 3)*X^4 + ((3*I + 1)*sqrt(2) + I + 3)*X^3 + (-(3*I - 3)*sqrt(2) - I)*X^2 + (-(I + 3)*sqrt(2))*X + I*sqrt(2) sage: f.roots() [(I, 3), (-2^(1/4), 1), (2^(1/4), 1), (1, 1)] sage: f.roots(multiplicities=False) [I, -2^(1/4), 2^(1/4), 1]
>>> from sage.all import * >>> # needs sage.symbolic >>> X = SR['X'].gen(0) >>> f = (X - Integer(1)) * (X - I)**Integer(3) * (X**Integer(2) - sqrt(Integer(2))); f X^6 + (-3*I - 1)*X^5 + (-sqrt(2) + 3*I - 3)*X^4 + ((3*I + 1)*sqrt(2) + I + 3)*X^3 + (-(3*I - 3)*sqrt(2) - I)*X^2 + (-(I + 3)*sqrt(2))*X + I*sqrt(2) >>> f.roots() [(I, 3), (-2^(1/4), 1), (2^(1/4), 1), (1, 1)] >>> f.roots(multiplicities=False) [I, -2^(1/4), 2^(1/4), 1]
# needs sage.symbolic X = SR['X'].0 f = (X - 1) * (X - I)^3 * (X^2 - sqrt(2)); f f.roots() f.roots(multiplicities=False)
A couple of examples where the base ring does not have a factorization algorithm (yet). Note that this is currently done via a rather naive enumeration, so could be very slow:
sage: R = Integers(6) sage: S.<x> = R['x'] sage: p = x^2 - 1 sage: p.roots() Traceback (most recent call last): ... NotImplementedError: root finding with multiplicities for this polynomial not implemented (try the multiplicities=False option) sage: p.roots(multiplicities=False) # needs sage.libs.pari [5, 1] sage: R = Integers(9) sage: A = PolynomialRing(R, 'y') sage: y = A.gen() sage: f = 10*y^2 - y^3 - 9 sage: f.roots(multiplicities=False) # needs sage.libs.pari [1, 0, 3, 6]
>>> from sage.all import * >>> R = Integers(Integer(6)) >>> S = R['x']; (x,) = S._first_ngens(1) >>> p = x**Integer(2) - Integer(1) >>> p.roots() Traceback (most recent call last): ... NotImplementedError: root finding with multiplicities for this polynomial not implemented (try the multiplicities=False option) >>> p.roots(multiplicities=False) # needs sage.libs.pari [5, 1] >>> R = Integers(Integer(9)) >>> A = PolynomialRing(R, 'y') >>> y = A.gen() >>> f = Integer(10)*y**Integer(2) - y**Integer(3) - Integer(9) >>> f.roots(multiplicities=False) # needs sage.libs.pari [1, 0, 3, 6]
R = Integers(6) S.<x> = R['x'] p = x^2 - 1 p.roots() p.roots(multiplicities=False) # needs sage.libs.pari R = Integers(9) A = PolynomialRing(R, 'y') y = A.gen() f = 10*y^2 - y^3 - 9 f.roots(multiplicities=False) # needs sage.libs.pari
An example over the complex double field (where root finding is fast, thanks to NumPy):
sage: # needs numpy sage.rings.complex_double sage: R.<x> = CDF[] sage: f = R.cyclotomic_polynomial(5); f x^4 + x^3 + x^2 + x + 1.0 sage: f.roots(multiplicities=False) # abs tol 1e-9 [-0.8090169943749469 - 0.5877852522924724*I, -0.8090169943749473 + 0.5877852522924724*I, 0.30901699437494773 - 0.951056516295154*I, 0.30901699437494756 + 0.9510565162951525*I] sage: [z^5 for z in f.roots(multiplicities=False)] # abs tol 2e-14 [0.9999999999999957 - 1.2864981197413038e-15*I, 0.9999999999999976 + 3.062854959141552e-15*I, 1.0000000000000024 + 1.1331077795295987e-15*I, 0.9999999999999953 - 2.0212861992297117e-15*I] sage: f = CDF['x']([1,2,3,4]); f 4.0*x^3 + 3.0*x^2 + 2.0*x + 1.0 sage: r = f.roots(multiplicities=False) sage: [f(a).abs() for a in r] # abs tol 1e-14 [2.574630599127759e-15, 1.457101633618084e-15, 1.1443916996305594e-15]
>>> from sage.all import * >>> # needs numpy sage.rings.complex_double >>> R = CDF['x']; (x,) = R._first_ngens(1) >>> f = R.cyclotomic_polynomial(Integer(5)); f x^4 + x^3 + x^2 + x + 1.0 >>> f.roots(multiplicities=False) # abs tol 1e-9 [-0.8090169943749469 - 0.5877852522924724*I, -0.8090169943749473 + 0.5877852522924724*I, 0.30901699437494773 - 0.951056516295154*I, 0.30901699437494756 + 0.9510565162951525*I] >>> [z**Integer(5) for z in f.roots(multiplicities=False)] # abs tol 2e-14 [0.9999999999999957 - 1.2864981197413038e-15*I, 0.9999999999999976 + 3.062854959141552e-15*I, 1.0000000000000024 + 1.1331077795295987e-15*I, 0.9999999999999953 - 2.0212861992297117e-15*I] >>> f = CDF['x']([Integer(1),Integer(2),Integer(3),Integer(4)]); f 4.0*x^3 + 3.0*x^2 + 2.0*x + 1.0 >>> r = f.roots(multiplicities=False) >>> [f(a).abs() for a in r] # abs tol 1e-14 [2.574630599127759e-15, 1.457101633618084e-15, 1.1443916996305594e-15]
# needs numpy sage.rings.complex_double R.<x> = CDF[] f = R.cyclotomic_polynomial(5); f f.roots(multiplicities=False) # abs tol 1e-9 [z^5 for z in f.roots(multiplicities=False)] # abs tol 2e-14 f = CDF['x']([1,2,3,4]); f r = f.roots(multiplicities=False) [f(a).abs() for a in r] # abs tol 1e-14
Another example over RDF:
sage: x = RDF['x'].0 sage: ((x^3 - 1)).roots() # abs tol 4e-16 # needs numpy [(1.0000000000000002, 1)] sage: ((x^3 - 1)).roots(multiplicities=False) # abs tol 4e-16 # needs numpy [1.0000000000000002]
>>> from sage.all import * >>> x = RDF['x'].gen(0) >>> ((x**Integer(3) - Integer(1))).roots() # abs tol 4e-16 # needs numpy [(1.0000000000000002, 1)] >>> ((x**Integer(3) - Integer(1))).roots(multiplicities=False) # abs tol 4e-16 # needs numpy [1.0000000000000002]
x = RDF['x'].0 ((x^3 - 1)).roots() # abs tol 4e-16 # needs numpy ((x^3 - 1)).roots(multiplicities=False) # abs tol 4e-16 # needs numpy
More examples involving the complex double field:
sage: # needs numpy sage.rings.complex_double sage.rings.real_mpfr sage: x = CDF['x'].0 sage: i = CDF.0 sage: f = x^3 + 2*i; f x^3 + 2.0*I sage: f.roots() [(-1.09112363597172... - 0.62996052494743...*I, 1), (...1.25992104989487...*I, 1), (1.09112363597172... - 0.62996052494743...*I, 1)] sage: f.roots(multiplicities=False) [-1.09112363597172... - 0.62996052494743...*I, ...1.25992104989487...*I, 1.09112363597172... - 0.62996052494743...*I] sage: [abs(f(z)) for z in f.roots(multiplicities=False)] # abs tol 1e-14 [8.95090418262362e-16, 8.728374398092689e-16, 1.0235750533041806e-15] sage: f = i*x^3 + 2; f I*x^3 + 2.0 sage: f.roots() [(-1.09112363597172... + 0.62996052494743...*I, 1), (...1.25992104989487...*I, 1), (1.09112363597172... + 0.62996052494743...*I, 1)] sage: abs(f(f.roots()[0][0])) # abs tol 1e-13 1.1102230246251565e-16
>>> from sage.all import * >>> # needs numpy sage.rings.complex_double sage.rings.real_mpfr >>> x = CDF['x'].gen(0) >>> i = CDF.gen(0) >>> f = x**Integer(3) + Integer(2)*i; f x^3 + 2.0*I >>> f.roots() [(-1.09112363597172... - 0.62996052494743...*I, 1), (...1.25992104989487...*I, 1), (1.09112363597172... - 0.62996052494743...*I, 1)] >>> f.roots(multiplicities=False) [-1.09112363597172... - 0.62996052494743...*I, ...1.25992104989487...*I, 1.09112363597172... - 0.62996052494743...*I] >>> [abs(f(z)) for z in f.roots(multiplicities=False)] # abs tol 1e-14 [8.95090418262362e-16, 8.728374398092689e-16, 1.0235750533041806e-15] >>> f = i*x**Integer(3) + Integer(2); f I*x^3 + 2.0 >>> f.roots() [(-1.09112363597172... + 0.62996052494743...*I, 1), (...1.25992104989487...*I, 1), (1.09112363597172... + 0.62996052494743...*I, 1)] >>> abs(f(f.roots()[Integer(0)][Integer(0)])) # abs tol 1e-13 1.1102230246251565e-16
# needs numpy sage.rings.complex_double sage.rings.real_mpfr x = CDF['x'].0 i = CDF.0 f = x^3 + 2*i; f f.roots() f.roots(multiplicities=False) [abs(f(z)) for z in f.roots(multiplicities=False)] # abs tol 1e-14 f = i*x^3 + 2; f f.roots() abs(f(f.roots()[0][0])) # abs tol 1e-13
Examples using real root isolation:
sage: x = polygen(ZZ) sage: f = x^2 - x - 1 sage: f.roots() # needs sage.libs.pari [] sage: f.roots(ring=AA) # needs sage.rings.number_field [(-0.618033988749895?, 1), (1.618033988749895?, 1)] sage: # needs sage.rings.real_interval_field sage: f.roots(ring=RIF) [(-0.6180339887498948482045868343657?, 1), (1.6180339887498948482045868343657?, 1)] sage: f.roots(ring=RIF, multiplicities=False) [-0.6180339887498948482045868343657?, 1.6180339887498948482045868343657?] sage: f.roots(ring=RealIntervalField(150)) [(-0.6180339887498948482045868343656381177203091798057628621354486227?, 1), (1.618033988749894848204586834365638117720309179805762862135448623?, 1)] sage: f = f^2 * (x - 1) sage: f.roots(ring=RIF) [(-0.6180339887498948482045868343657?, 2), (1.0000000000000000000000000000000?, 1), (1.6180339887498948482045868343657?, 2)] sage: f.roots(ring=RIF, multiplicities=False) [-0.6180339887498948482045868343657?, 1.0000000000000000000000000000000?, 1.6180339887498948482045868343657?]
>>> from sage.all import * >>> x = polygen(ZZ) >>> f = x**Integer(2) - x - Integer(1) >>> f.roots() # needs sage.libs.pari [] >>> f.roots(ring=AA) # needs sage.rings.number_field [(-0.618033988749895?, 1), (1.618033988749895?, 1)] >>> # needs sage.rings.real_interval_field >>> f.roots(ring=RIF) [(-0.6180339887498948482045868343657?, 1), (1.6180339887498948482045868343657?, 1)] >>> f.roots(ring=RIF, multiplicities=False) [-0.6180339887498948482045868343657?, 1.6180339887498948482045868343657?] >>> f.roots(ring=RealIntervalField(Integer(150))) [(-0.6180339887498948482045868343656381177203091798057628621354486227?, 1), (1.618033988749894848204586834365638117720309179805762862135448623?, 1)] >>> f = f**Integer(2) * (x - Integer(1)) >>> f.roots(ring=RIF) [(-0.6180339887498948482045868343657?, 2), (1.0000000000000000000000000000000?, 1), (1.6180339887498948482045868343657?, 2)] >>> f.roots(ring=RIF, multiplicities=False) [-0.6180339887498948482045868343657?, 1.0000000000000000000000000000000?, 1.6180339887498948482045868343657?]
x = polygen(ZZ) f = x^2 - x - 1 f.roots() # needs sage.libs.pari f.roots(ring=AA) # needs sage.rings.number_field # needs sage.rings.real_interval_field f.roots(ring=RIF) f.roots(ring=RIF, multiplicities=False) f.roots(ring=RealIntervalField(150)) f = f^2 * (x - 1) f.roots(ring=RIF) f.roots(ring=RIF, multiplicities=False)
Examples using complex root isolation:
sage: x = polygen(ZZ) sage: p = x^5 - x - 1 sage: p.roots() # needs sage.libs.pari [] sage: p.roots(ring=CIF) # needs sage.rings.complex_interval_field [(1.167303978261419?, 1), (-0.764884433600585? - 0.352471546031727?*I, 1), (-0.764884433600585? + 0.352471546031727?*I, 1), (0.181232444469876? - 1.083954101317711?*I, 1), (0.181232444469876? + 1.083954101317711?*I, 1)] sage: p.roots(ring=ComplexIntervalField(200)) # needs sage.rings.complex_interval_field [(1.167303978261418684256045899854842180720560371525489039140082?, 1), (-0.76488443360058472602982318770854173032899665194736756700778? - 0.35247154603172624931794709140258105439420648082424733283770?*I, 1), (-0.76488443360058472602982318770854173032899665194736756700778? + 0.35247154603172624931794709140258105439420648082424733283770?*I, 1), (0.18123244446987538390180023778112063996871646618462304743774? - 1.08395410131771066843034449298076657427364024315511565430114?*I, 1), (0.18123244446987538390180023778112063996871646618462304743774? + 1.08395410131771066843034449298076657427364024315511565430114?*I, 1)] sage: rts = p.roots(ring=QQbar); rts # needs sage.rings.number_field [(1.167303978261419?, 1), (-0.7648844336005847? - 0.3524715460317263?*I, 1), (-0.7648844336005847? + 0.3524715460317263?*I, 1), (0.1812324444698754? - 1.083954101317711?*I, 1), (0.1812324444698754? + 1.083954101317711?*I, 1)] sage: p.roots(ring=AA) # needs sage.rings.number_field [(1.167303978261419?, 1)] sage: p = (x - rts[4][0])^2 * (3*x^2 + x + 1) # needs sage.rings.number_field sage: p.roots(ring=QQbar) # needs sage.rings.number_field [(-0.1666666666666667? - 0.552770798392567?*I, 1), (-0.1666666666666667? + 0.552770798392567?*I, 1), (0.1812324444698754? + 1.083954101317711?*I, 2)] sage: p.roots(ring=CIF) # needs sage.rings.complex_interval_field [(-0.1666666666666667? - 0.552770798392567?*I, 1), (-0.1666666666666667? + 0.552770798392567?*I, 1), (0.1812324444698754? + 1.083954101317711?*I, 2)]
>>> from sage.all import * >>> x = polygen(ZZ) >>> p = x**Integer(5) - x - Integer(1) >>> p.roots() # needs sage.libs.pari [] >>> p.roots(ring=CIF) # needs sage.rings.complex_interval_field [(1.167303978261419?, 1), (-0.764884433600585? - 0.352471546031727?*I, 1), (-0.764884433600585? + 0.352471546031727?*I, 1), (0.181232444469876? - 1.083954101317711?*I, 1), (0.181232444469876? + 1.083954101317711?*I, 1)] >>> p.roots(ring=ComplexIntervalField(Integer(200))) # needs sage.rings.complex_interval_field [(1.167303978261418684256045899854842180720560371525489039140082?, 1), (-0.76488443360058472602982318770854173032899665194736756700778? - 0.35247154603172624931794709140258105439420648082424733283770?*I, 1), (-0.76488443360058472602982318770854173032899665194736756700778? + 0.35247154603172624931794709140258105439420648082424733283770?*I, 1), (0.18123244446987538390180023778112063996871646618462304743774? - 1.08395410131771066843034449298076657427364024315511565430114?*I, 1), (0.18123244446987538390180023778112063996871646618462304743774? + 1.08395410131771066843034449298076657427364024315511565430114?*I, 1)] >>> rts = p.roots(ring=QQbar); rts # needs sage.rings.number_field [(1.167303978261419?, 1), (-0.7648844336005847? - 0.3524715460317263?*I, 1), (-0.7648844336005847? + 0.3524715460317263?*I, 1), (0.1812324444698754? - 1.083954101317711?*I, 1), (0.1812324444698754? + 1.083954101317711?*I, 1)] >>> p.roots(ring=AA) # needs sage.rings.number_field [(1.167303978261419?, 1)] >>> p = (x - rts[Integer(4)][Integer(0)])**Integer(2) * (Integer(3)*x**Integer(2) + x + Integer(1)) # needs sage.rings.number_field >>> p.roots(ring=QQbar) # needs sage.rings.number_field [(-0.1666666666666667? - 0.552770798392567?*I, 1), (-0.1666666666666667? + 0.552770798392567?*I, 1), (0.1812324444698754? + 1.083954101317711?*I, 2)] >>> p.roots(ring=CIF) # needs sage.rings.complex_interval_field [(-0.1666666666666667? - 0.552770798392567?*I, 1), (-0.1666666666666667? + 0.552770798392567?*I, 1), (0.1812324444698754? + 1.083954101317711?*I, 2)]
x = polygen(ZZ) p = x^5 - x - 1 p.roots() # needs sage.libs.pari p.roots(ring=CIF) # needs sage.rings.complex_interval_field p.roots(ring=ComplexIntervalField(200)) # needs sage.rings.complex_interval_field rts = p.roots(ring=QQbar); rts # needs sage.rings.number_field p.roots(ring=AA) # needs sage.rings.number_field p = (x - rts[4][0])^2 * (3*x^2 + x + 1) # needs sage.rings.number_field p.roots(ring=QQbar) # needs sage.rings.number_field p.roots(ring=CIF) # needs sage.rings.complex_interval_field
In some cases, it is possible to isolate the roots of polynomials over complex ball fields:
sage: # needs sage.libs.flint sage: Pol.<x> = CBF[] sage: (x^2 + 2).roots(multiplicities=False) [[+/- ...e-19] + [-1.414213562373095 +/- ...e-17]*I, [+/- ...e-19] + [1.414213562373095 +/- ...e-17]*I] sage: (x^3 - 1/2).roots(RBF, multiplicities=False) [[0.7937005259840997 +/- ...e-17]] sage: ((x - 1)^2).roots(multiplicities=False, proof=False) doctest:... UserWarning: roots may have been lost... [[1.00000000000 +/- ...e-12] + [+/- ...e-11]*I, [1.0000000000 +/- ...e-12] + [+/- ...e-12]*I] sage: ((x - 1)^2).roots(multiplicities=False, proof=False, warn=False) [[1.00000000000 +/- ...e-12] + [+/- ...e-11]*I, [1.0000000000 +/- ...e-12] + [+/- ...e-12]*I]
>>> from sage.all import * >>> # needs sage.libs.flint >>> Pol = CBF['x']; (x,) = Pol._first_ngens(1) >>> (x**Integer(2) + Integer(2)).roots(multiplicities=False) [[+/- ...e-19] + [-1.414213562373095 +/- ...e-17]*I, [+/- ...e-19] + [1.414213562373095 +/- ...e-17]*I] >>> (x**Integer(3) - Integer(1)/Integer(2)).roots(RBF, multiplicities=False) [[0.7937005259840997 +/- ...e-17]] >>> ((x - Integer(1))**Integer(2)).roots(multiplicities=False, proof=False) doctest:... UserWarning: roots may have been lost... [[1.00000000000 +/- ...e-12] + [+/- ...e-11]*I, [1.0000000000 +/- ...e-12] + [+/- ...e-12]*I] >>> ((x - Integer(1))**Integer(2)).roots(multiplicities=False, proof=False, warn=False) [[1.00000000000 +/- ...e-12] + [+/- ...e-11]*I, [1.0000000000 +/- ...e-12] + [+/- ...e-12]*I]
# needs sage.libs.flint Pol.<x> = CBF[] (x^2 + 2).roots(multiplicities=False) (x^3 - 1/2).roots(RBF, multiplicities=False) ((x - 1)^2).roots(multiplicities=False, proof=False) ((x - 1)^2).roots(multiplicities=False, proof=False, warn=False)
Note that coefficients in a number field with defining polynomial \(x^2 + 1\) are considered to be Gaussian rationals (with the generator mapping to \(+I\)), if you ask for complex roots.
sage: # needs sage.rings.number_field sage: K.<im> = QuadraticField(-1) sage: y = polygen(K) sage: p = y^4 - 2 - im sage: p.roots(ring=CC) [(-1.2146389322441... - 0.14142505258239...*I, 1), (-0.14142505258239... + 1.2146389322441...*I, 1), (0.14142505258239... - 1.2146389322441...*I, 1), (1.2146389322441... + 0.14142505258239...*I, 1)] sage: p = p^2 * (y^2 - 2) sage: p.roots(ring=CIF) [(-1.414213562373095?, 1), (1.414213562373095?, 1), (-1.214638932244183? - 0.141425052582394?*I, 2), (-0.141425052582394? + 1.214638932244183?*I, 2), (0.141425052582394? - 1.214638932244183?*I, 2), (1.214638932244183? + 0.141425052582394?*I, 2)]
>>> from sage.all import * >>> # needs sage.rings.number_field >>> K = QuadraticField(-Integer(1), names=('im',)); (im,) = K._first_ngens(1) >>> y = polygen(K) >>> p = y**Integer(4) - Integer(2) - im >>> p.roots(ring=CC) [(-1.2146389322441... - 0.14142505258239...*I, 1), (-0.14142505258239... + 1.2146389322441...*I, 1), (0.14142505258239... - 1.2146389322441...*I, 1), (1.2146389322441... + 0.14142505258239...*I, 1)] >>> p = p**Integer(2) * (y**Integer(2) - Integer(2)) >>> p.roots(ring=CIF) [(-1.414213562373095?, 1), (1.414213562373095?, 1), (-1.214638932244183? - 0.141425052582394?*I, 2), (-0.141425052582394? + 1.214638932244183?*I, 2), (0.141425052582394? - 1.214638932244183?*I, 2), (1.214638932244183? + 0.141425052582394?*I, 2)]
# needs sage.rings.number_field K.<im> = QuadraticField(-1) y = polygen(K) p = y^4 - 2 - im p.roots(ring=CC) p = p^2 * (y^2 - 2) p.roots(ring=CIF)
Note that one should not use NumPy when wanting high precision output as it does not support any of the high precision types:
sage: # needs numpy sage.rings.real_mpfr sage.symbolic sage: R.<x> = RealField(200)[] sage: f = x^2 - R(pi) sage: f.roots() [(-1.7724538509055160272981674833411451827975494561223871282138, 1), (1.7724538509055160272981674833411451827975494561223871282138, 1)] sage: f.roots(algorithm='numpy') doctest... UserWarning: NumPy does not support arbitrary precision arithmetic. The roots found will likely have less precision than you expect. [(-1.77245385090551..., 1), (1.77245385090551..., 1)]
>>> from sage.all import * >>> # needs numpy sage.rings.real_mpfr sage.symbolic >>> R = RealField(Integer(200))['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) - R(pi) >>> f.roots() [(-1.7724538509055160272981674833411451827975494561223871282138, 1), (1.7724538509055160272981674833411451827975494561223871282138, 1)] >>> f.roots(algorithm='numpy') doctest... UserWarning: NumPy does not support arbitrary precision arithmetic. The roots found will likely have less precision than you expect. [(-1.77245385090551..., 1), (1.77245385090551..., 1)]
# needs numpy sage.rings.real_mpfr sage.symbolic R.<x> = RealField(200)[] f = x^2 - R(pi) f.roots() f.roots(algorithm='numpy')
We can also find roots over number fields:
sage: K.<z> = CyclotomicField(15) # needs sage.rings.number_field sage: R.<x> = PolynomialRing(K) # needs sage.rings.number_field sage: (x^2 + x + 1).roots() # needs sage.rings.number_field [(z^5, 1), (-z^5 - 1, 1)]
>>> from sage.all import * >>> K = CyclotomicField(Integer(15), names=('z',)); (z,) = K._first_ngens(1)# needs sage.rings.number_field >>> R = PolynomialRing(K, names=('x',)); (x,) = R._first_ngens(1)# needs sage.rings.number_field >>> (x**Integer(2) + x + Integer(1)).roots() # needs sage.rings.number_field [(z^5, 1), (-z^5 - 1, 1)]
K.<z> = CyclotomicField(15) # needs sage.rings.number_field R.<x> = PolynomialRing(K) # needs sage.rings.number_field (x^2 + x + 1).roots() # needs sage.rings.number_field
There are many combinations of floating-point input and output types that work. (Note that some of them are quite pointless like using
algorithm='numpy'
with high-precision types.)sage: # needs numpy sage.rings.complex_double sage.rings.real_mpfr sage: rflds = (RR, RDF, RealField(100)) sage: cflds = (CC, CDF, ComplexField(100)) sage: def cross(a, b): ....: return list(cartesian_product_iterator([a, b])) sage: flds = cross(rflds, rflds) + cross(rflds, cflds) + cross(cflds, cflds) sage: for (fld_in, fld_out) in flds: ....: x = polygen(fld_in) ....: f = x^3 - fld_in(2) ....: x2 = polygen(fld_out) ....: f2 = x2^3 - fld_out(2) ....: for algo in (None, 'pari', 'numpy'): ....: rts = f.roots(ring=fld_out, multiplicities=False) ....: rts = sorted(rts, key=lambda x: x.imag()) ....: if fld_in == fld_out and algo is None: ....: print("{} {}".format(fld_in, rts)) ....: for rt in rts: ....: assert(abs(f2(rt)) <= 1e-10) ....: assert(rt.parent() == fld_out) Real Field with 53 bits of precision [1.25992104989487] Real Double Field [1.25992104989...] Real Field with 100 bits of precision [1.2599210498948731647672106073] Complex Field with 53 bits of precision [-0.62996052494743... - 1.09112363597172*I, 1.25992104989487, -0.62996052494743... + 1.09112363597172*I] Complex Double Field [-0.629960524947... - 1.0911236359717...*I, 1.25992104989487..., -0.629960524947... + 1.0911236359717...*I] Complex Field with 100 bits of precision [-0.62996052494743658238360530364 - 1.0911236359717214035600726142*I, 1.2599210498948731647672106073, -0.62996052494743658238360530364 + 1.0911236359717214035600726142*I]
>>> from sage.all import * >>> # needs numpy sage.rings.complex_double sage.rings.real_mpfr >>> rflds = (RR, RDF, RealField(Integer(100))) >>> cflds = (CC, CDF, ComplexField(Integer(100))) >>> def cross(a, b): ... return list(cartesian_product_iterator([a, b])) >>> flds = cross(rflds, rflds) + cross(rflds, cflds) + cross(cflds, cflds) >>> for (fld_in, fld_out) in flds: ... x = polygen(fld_in) ... f = x**Integer(3) - fld_in(Integer(2)) ... x2 = polygen(fld_out) ... f2 = x2**Integer(3) - fld_out(Integer(2)) ... for algo in (None, 'pari', 'numpy'): ... rts = f.roots(ring=fld_out, multiplicities=False) ... rts = sorted(rts, key=lambda x: x.imag()) ... if fld_in == fld_out and algo is None: ... print("{} {}".format(fld_in, rts)) ... for rt in rts: ... assert(abs(f2(rt)) <= RealNumber('1e-10')) ... assert(rt.parent() == fld_out) Real Field with 53 bits of precision [1.25992104989487] Real Double Field [1.25992104989...] Real Field with 100 bits of precision [1.2599210498948731647672106073] Complex Field with 53 bits of precision [-0.62996052494743... - 1.09112363597172*I, 1.25992104989487, -0.62996052494743... + 1.09112363597172*I] Complex Double Field [-0.629960524947... - 1.0911236359717...*I, 1.25992104989487..., -0.629960524947... + 1.0911236359717...*I] Complex Field with 100 bits of precision [-0.62996052494743658238360530364 - 1.0911236359717214035600726142*I, 1.2599210498948731647672106073, -0.62996052494743658238360530364 + 1.0911236359717214035600726142*I]
# needs numpy sage.rings.complex_double sage.rings.real_mpfr rflds = (RR, RDF, RealField(100)) cflds = (CC, CDF, ComplexField(100)) def cross(a, b): return list(cartesian_product_iterator([a, b])) flds = cross(rflds, rflds) + cross(rflds, cflds) + cross(cflds, cflds) for (fld_in, fld_out) in flds: x = polygen(fld_in) f = x^3 - fld_in(2) x2 = polygen(fld_out) f2 = x2^3 - fld_out(2) for algo in (None, 'pari', 'numpy'): rts = f.roots(ring=fld_out, multiplicities=False) rts = sorted(rts, key=lambda x: x.imag()) if fld_in == fld_out and algo is None: print("{} {}".format(fld_in, rts)) for rt in rts: assert(abs(f2(rt)) <= 1e-10) assert(rt.parent() == fld_out)
Note that we can find the roots of a polynomial with algebraic coefficients:
sage: # needs sage.rings.number_field sage: rt2 = sqrt(AA(2)) sage: rt3 = sqrt(AA(3)) sage: x = polygen(AA) sage: f = (x - rt2) * (x - rt3); f x^2 - 3.146264369941973?*x + 2.449489742783178? sage: rts = f.roots(); rts [(1.414213562373095?, 1), (1.732050807568878?, 1)] sage: rts[0][0] == rt2 True sage: f.roots(ring=RealIntervalField(150)) [(1.414213562373095048801688724209698078569671875376948073176679738?, 1), (1.732050807568877293527446341505872366942805253810380628055806980?, 1)]
>>> from sage.all import * >>> # needs sage.rings.number_field >>> rt2 = sqrt(AA(Integer(2))) >>> rt3 = sqrt(AA(Integer(3))) >>> x = polygen(AA) >>> f = (x - rt2) * (x - rt3); f x^2 - 3.146264369941973?*x + 2.449489742783178? >>> rts = f.roots(); rts [(1.414213562373095?, 1), (1.732050807568878?, 1)] >>> rts[Integer(0)][Integer(0)] == rt2 True >>> f.roots(ring=RealIntervalField(Integer(150))) [(1.414213562373095048801688724209698078569671875376948073176679738?, 1), (1.732050807568877293527446341505872366942805253810380628055806980?, 1)]
# needs sage.rings.number_field rt2 = sqrt(AA(2)) rt3 = sqrt(AA(3)) x = polygen(AA) f = (x - rt2) * (x - rt3); f rts = f.roots(); rts rts[0][0] == rt2 f.roots(ring=RealIntervalField(150))
We can handle polynomials with huge coefficients.
This number doesn’t even fit in an IEEE double-precision float, but
RR
andCC
allow a much larger range of floating-point numbers:sage: bigc = 2^1500 sage: CDF(bigc) # needs sage.rings.complex_double +infinity sage: CC(bigc) # needs sage.rings.real_mpfr 3.50746621104340e451
>>> from sage.all import * >>> bigc = Integer(2)**Integer(1500) >>> CDF(bigc) # needs sage.rings.complex_double +infinity >>> CC(bigc) # needs sage.rings.real_mpfr 3.50746621104340e451
bigc = 2^1500 CDF(bigc) # needs sage.rings.complex_double CC(bigc) # needs sage.rings.real_mpfr
Polynomials using such large coefficients can’t be handled by numpy, but pari can deal with them:
sage: x = polygen(QQ) sage: p = x + bigc sage: p.roots(ring=RR, algorithm='numpy') # needs numpy sage.rings.real_mpfr Traceback (most recent call last): ... LinAlgError: Array must not contain infs or NaNs sage: p.roots(ring=RR, algorithm='pari') # needs sage.libs.pari sage.rings.real_mpfr [(-3.50746621104340e451, 1)] sage: p.roots(ring=AA) # needs sage.rings.number_field [(-3.5074662110434039?e451, 1)] sage: p.roots(ring=QQbar) # needs sage.rings.number_field [(-3.5074662110434039?e451, 1)] sage: p = bigc*x + 1 sage: p.roots(ring=RR) # needs numpy [(-2.85106096489671e-452, 1)] sage: p.roots(ring=AA) # needs sage.rings.number_field [(-2.8510609648967059?e-452, 1)] sage: p.roots(ring=QQbar) # needs sage.rings.number_field [(-2.8510609648967059?e-452, 1)] sage: p = x^2 - bigc sage: p.roots(ring=RR) # needs numpy [(-5.92238652153286e225, 1), (5.92238652153286e225, 1)] sage: p.roots(ring=QQbar) # needs sage.rings.number_field [(-5.9223865215328558?e225, 1), (5.9223865215328558?e225, 1)]
>>> from sage.all import * >>> x = polygen(QQ) >>> p = x + bigc >>> p.roots(ring=RR, algorithm='numpy') # needs numpy sage.rings.real_mpfr Traceback (most recent call last): ... LinAlgError: Array must not contain infs or NaNs >>> p.roots(ring=RR, algorithm='pari') # needs sage.libs.pari sage.rings.real_mpfr [(-3.50746621104340e451, 1)] >>> p.roots(ring=AA) # needs sage.rings.number_field [(-3.5074662110434039?e451, 1)] >>> p.roots(ring=QQbar) # needs sage.rings.number_field [(-3.5074662110434039?e451, 1)] >>> p = bigc*x + Integer(1) >>> p.roots(ring=RR) # needs numpy [(-2.85106096489671e-452, 1)] >>> p.roots(ring=AA) # needs sage.rings.number_field [(-2.8510609648967059?e-452, 1)] >>> p.roots(ring=QQbar) # needs sage.rings.number_field [(-2.8510609648967059?e-452, 1)] >>> p = x**Integer(2) - bigc >>> p.roots(ring=RR) # needs numpy [(-5.92238652153286e225, 1), (5.92238652153286e225, 1)] >>> p.roots(ring=QQbar) # needs sage.rings.number_field [(-5.9223865215328558?e225, 1), (5.9223865215328558?e225, 1)]
x = polygen(QQ) p = x + bigc p.roots(ring=RR, algorithm='numpy') # needs numpy sage.rings.real_mpfr p.roots(ring=RR, algorithm='pari') # needs sage.libs.pari sage.rings.real_mpfr p.roots(ring=AA) # needs sage.rings.number_field p.roots(ring=QQbar) # needs sage.rings.number_field p = bigc*x + 1 p.roots(ring=RR) # needs numpy p.roots(ring=AA) # needs sage.rings.number_field p.roots(ring=QQbar) # needs sage.rings.number_field p = x^2 - bigc p.roots(ring=RR) # needs numpy p.roots(ring=QQbar) # needs sage.rings.number_field
Check that Issue #30522 is fixed:
sage: PolynomialRing(SR, names="x")("x^2").roots() # needs sage.symbolic [(0, 2)]
>>> from sage.all import * >>> PolynomialRing(SR, names="x")("x^2").roots() # needs sage.symbolic [(0, 2)]
PolynomialRing(SR, names="x")("x^2").roots() # needs sage.symbolic
Check that Issue #30523 is fixed:
sage: PolynomialRing(SR, names="x")("x^2 + q").roots() # needs sage.symbolic [(-sqrt(-q), 1), (sqrt(-q), 1)]
>>> from sage.all import * >>> PolynomialRing(SR, names="x")("x^2 + q").roots() # needs sage.symbolic [(-sqrt(-q), 1), (sqrt(-q), 1)]
PolynomialRing(SR, names="x")("x^2 + q").roots() # needs sage.symbolic
ALGORITHM:
For brevity, we will use
RR
to mean anyRealField
of any precision; similarly forRIF
,CC
, andCIF
. Since Sage has no specific implementation of Gaussian rationals (or of number fields with embedding, at all), when we refer to Gaussian rationals below we will accept any number field with defining polynomial \(x^2+1\), mapping the field generator to +I.We call the base ring of the polynomial \(K\), and the ring given by the
ring
argument \(L\). (Ifring
is not specified, then \(L\) is the same as \(K\).)If \(K\) and \(L\) are floating-point (
RDF
,CDF
,RR
, orCC
), then a floating-point root-finder is used. If \(L\) isRDF
orCDF
, then we default to using NumPy’sroots()
; otherwise, we use PARI’s function pari:polroots. This choice can be overridden withalgorithm='pari'
oralgorithm='numpy'
. If the algorithm is unspecified and NumPy’sroots()
algorithm fails, then we fall back to PARI (NumPy will fail if some coefficient is infinite, for instance).If \(L\) is
SR
(or one of its subrings), then the roots will be radical expressions, computed as the solutions of a symbolic polynomial expression. At the moment this delegates tosage.symbolic.expression.Expression.solve()
which in turn uses Maxima to find radical solutions. Some solutions may be lost in this approach. Once Issue #17516 gets implemented, all possible radical solutions should become available.If \(L\) is
AA
orRIF
, and \(K\) isZZ
,QQ
, orAA
, then the root isolation algorithmsage.rings.polynomial.real_roots.real_roots()
is used. (You can callreal_roots()
directly to get more control than this method gives.)If \(L\) is
QQbar
orCIF
, and \(K\) isZZ
,QQ
,AA
,QQbar
, or the Gaussian rationals, then the root isolation algorithmsage.rings.polynomial.complex_roots.complex_roots()
is used. (You can callcomplex_roots()
directly to get more control than this method gives.)If \(L\) is
AA
and \(K\) isQQbar
or the Gaussian rationals, thencomplex_roots()
is used (as above) to find roots inQQbar
, then these roots are filtered to select only the real roots.If \(L\) is floating-point and \(K\) is not, then we attempt to change the polynomial ring to \(L\) (using
change_ring()
) (or, if \(L\) is complex and \(K\) is not, to the corresponding real field). Then we use either PARI or NumPy as specified above.For all other cases where \(K\) is different from \(L\), we attempt to use
.change_ring(L)
. When that fails but \(L\) is a subring of \(K\), we also attempt to compute the roots over \(K\) and filter the ones belonging to \(L\).The next method, which is used if \(K\) is an integral domain, is to attempt to factor the polynomial. If this succeeds, then for every degree-one factor \(ax+b\), we add \(-b/a\) as a root (as long as this quotient is actually in the desired ring).
If factoring over \(K\) is not implemented (or \(K\) is not an integral domain), and \(K\) is finite, then we find the roots by enumerating all elements of \(K\) and checking whether the polynomial evaluates to zero at that value.
Note
We mentioned above that polynomials with multiple roots are always ill-conditioned; if your input is given to \(n\) bits of precision, you should not expect more than \(n/k\) good bits for a \(k\)-fold root. (You can get solutions that make the polynomial evaluate to a number very close to zero; basically the problem is that with a multiple root, there are many such numbers, and it’s difficult to choose between them.)
To see why this is true, consider the naive floating-point error analysis model where you just pretend that all floating-point numbers are somewhat imprecise - a little ‘fuzzy’, if you will. Then the graph of a floating-point polynomial will be a fuzzy line. Consider the graph of \((x-1)^3\); this will be a fuzzy line with a horizontal tangent at \(x=1\), \(y=0\). If the fuzziness extends up and down by about j, then it will extend left and right by about cube_root(j).
- shift(n)[source]¶
Return this polynomial multiplied by the power \(x^n\). If \(n\) is negative, terms below \(x^n\) will be discarded. Does not change this polynomial (since polynomials are immutable).
EXAMPLES:
sage: R.<x> = QQ[] sage: p = x^2 + 2*x + 4 sage: p.shift(0) x^2 + 2*x + 4 sage: p.shift(-1) x + 2 sage: p.shift(-5) 0 sage: p.shift(2) x^4 + 2*x^3 + 4*x^2
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> p = x**Integer(2) + Integer(2)*x + Integer(4) >>> p.shift(Integer(0)) x^2 + 2*x + 4 >>> p.shift(-Integer(1)) x + 2 >>> p.shift(-Integer(5)) 0 >>> p.shift(Integer(2)) x^4 + 2*x^3 + 4*x^2
R.<x> = QQ[] p = x^2 + 2*x + 4 p.shift(0) p.shift(-1) p.shift(-5) p.shift(2)
One can also use the infix shift operator:
sage: f = x^3 + x sage: f >> 2 x sage: f << 2 x^5 + x^3
>>> from sage.all import * >>> f = x**Integer(3) + x >>> f >> Integer(2) x >>> f << Integer(2) x^5 + x^3
f = x^3 + x f >> 2 f << 2
AUTHORS:
David Harvey (2006-08-06)
Robert Bradshaw (2007-04-18): Added support for infix operator.
- specialization(D=None, phi=None)[source]¶
Specialization of this polynomial.
Given a family of polynomials defined over a polynomial ring. A specialization is a particular member of that family. The specialization can be specified either by a dictionary or a
SpecializationMorphism
.INPUT:
D
– dictionary (optional)phi
–SpecializationMorphism
(optional)
OUTPUT: a new polynomial
EXAMPLES:
sage: R.<c> = PolynomialRing(ZZ) sage: S.<z> = PolynomialRing(R) sage: F = c*z^2 + c^2 sage: F.specialization({c:2}) 2*z^2 + 4
>>> from sage.all import * >>> R = PolynomialRing(ZZ, names=('c',)); (c,) = R._first_ngens(1) >>> S = PolynomialRing(R, names=('z',)); (z,) = S._first_ngens(1) >>> F = c*z**Integer(2) + c**Integer(2) >>> F.specialization({c:Integer(2)}) 2*z^2 + 4
R.<c> = PolynomialRing(ZZ) S.<z> = PolynomialRing(R) F = c*z^2 + c^2 F.specialization({c:2})
sage: A.<c> = QQ[] sage: R.<x> = Frac(A)[] sage: X = (1 + x/c).specialization({c:20}) sage: X 1/20*x + 1 sage: X.parent() Univariate Polynomial Ring in x over Rational Field
>>> from sage.all import * >>> A = QQ['c']; (c,) = A._first_ngens(1) >>> R = Frac(A)['x']; (x,) = R._first_ngens(1) >>> X = (Integer(1) + x/c).specialization({c:Integer(20)}) >>> X 1/20*x + 1 >>> X.parent() Univariate Polynomial Ring in x over Rational Field
A.<c> = QQ[] R.<x> = Frac(A)[] X = (1 + x/c).specialization({c:20}) X X.parent()
>>> from sage.all import * >>> A = QQ['c']; (c,) = A._first_ngens(1) >>> R = Frac(A)['x']; (x,) = R._first_ngens(1) >>> X = (Integer(1) + x/c).specialization({c:Integer(20)}) >>> X 1/20*x + 1 >>> X.parent() Univariate Polynomial Ring in x over Rational Field
A.<c> = QQ[] R.<x> = Frac(A)[] X = (1 + x/c).specialization({c:20}) X X.parent()
- splitting_field(names=None, map=False, **kwds)[source]¶
Compute the absolute splitting field of a given polynomial.
INPUT:
names
– (default:None
) a variable name for the splitting fieldmap
– boolean (default:False
); also return an embedding ofself
into the resulting fieldkwds
– additional keywords depending on the type. Currently, only number fields are implemented. Seesage.rings.number_field.splitting_field.splitting_field()
for the documentation of these keywords.
OUTPUT:
If
map
isFalse
, the splitting field as an absolute field. Ifmap
isTrue
, a tuple(K, phi)
wherephi
is an embedding of the base field ofself
inK
.EXAMPLES:
sage: R.<x> = PolynomialRing(ZZ) sage: K.<a> = (x^3 + 2).splitting_field(); K # needs sage.rings.number_field Number Field in a with defining polynomial x^6 + 3*x^5 + 6*x^4 + 11*x^3 + 12*x^2 - 3*x + 1 sage: K.<a> = (x^3 - 3*x + 1).splitting_field(); K # needs sage.rings.number_field Number Field in a with defining polynomial x^3 - 3*x + 1
>>> from sage.all import * >>> R = PolynomialRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> K = (x**Integer(3) + Integer(2)).splitting_field(names=('a',)); (a,) = K._first_ngens(1); K # needs sage.rings.number_field Number Field in a with defining polynomial x^6 + 3*x^5 + 6*x^4 + 11*x^3 + 12*x^2 - 3*x + 1 >>> K = (x**Integer(3) - Integer(3)*x + Integer(1)).splitting_field(names=('a',)); (a,) = K._first_ngens(1); K # needs sage.rings.number_field Number Field in a with defining polynomial x^3 - 3*x + 1
R.<x> = PolynomialRing(ZZ) K.<a> = (x^3 + 2).splitting_field(); K # needs sage.rings.number_field K.<a> = (x^3 - 3*x + 1).splitting_field(); K # needs sage.rings.number_field
Relative situation:
sage: # needs sage.rings.number_field sage: R.<x> = PolynomialRing(QQ) sage: K.<a> = NumberField(x^3 + 2) sage: S.<t> = PolynomialRing(K) sage: L.<b> = (t^2 - a).splitting_field() sage: L Number Field in b with defining polynomial t^6 + 2
>>> from sage.all import * >>> # needs sage.rings.number_field >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> K = NumberField(x**Integer(3) + Integer(2), names=('a',)); (a,) = K._first_ngens(1) >>> S = PolynomialRing(K, names=('t',)); (t,) = S._first_ngens(1) >>> L = (t**Integer(2) - a).splitting_field(names=('b',)); (b,) = L._first_ngens(1) >>> L Number Field in b with defining polynomial t^6 + 2
# needs sage.rings.number_field R.<x> = PolynomialRing(QQ) K.<a> = NumberField(x^3 + 2) S.<t> = PolynomialRing(K) L.<b> = (t^2 - a).splitting_field() L
With
map=True
, we also get the embedding of the base field into the splitting field:sage: L.<b>, phi = (t^2 - a).splitting_field(map=True) # needs sage.rings.number_field sage: phi # needs sage.rings.number_field Ring morphism: From: Number Field in a with defining polynomial x^3 + 2 To: Number Field in b with defining polynomial t^6 + 2 Defn: a |--> b^2
>>> from sage.all import * >>> L, phi = (t**Integer(2) - a).splitting_field(map=True, names=('b',)); (b,) = L._first_ngens(1)# needs sage.rings.number_field >>> phi # needs sage.rings.number_field Ring morphism: From: Number Field in a with defining polynomial x^3 + 2 To: Number Field in b with defining polynomial t^6 + 2 Defn: a |--> b^2
L.<b>, phi = (t^2 - a).splitting_field(map=True) # needs sage.rings.number_field phi # needs sage.rings.number_field
An example over a finite field:
sage: P.<x> = PolynomialRing(GF(7)) sage: t = x^2 + 1 sage: t.splitting_field('b') # needs sage.rings.finite_rings Finite Field in b of size 7^2 sage: P.<x> = PolynomialRing(GF(7^3, 'a')) # needs sage.rings.finite_rings sage: t = x^2 + 1 sage: t.splitting_field('b', map=True) # needs sage.rings.finite_rings (Finite Field in b of size 7^6, Ring morphism: From: Finite Field in a of size 7^3 To: Finite Field in b of size 7^6 Defn: a |--> 2*b^4 + 6*b^3 + 2*b^2 + 3*b + 2)
>>> from sage.all import * >>> P = PolynomialRing(GF(Integer(7)), names=('x',)); (x,) = P._first_ngens(1) >>> t = x**Integer(2) + Integer(1) >>> t.splitting_field('b') # needs sage.rings.finite_rings Finite Field in b of size 7^2 >>> P = PolynomialRing(GF(Integer(7)**Integer(3), 'a'), names=('x',)); (x,) = P._first_ngens(1)# needs sage.rings.finite_rings >>> t = x**Integer(2) + Integer(1) >>> t.splitting_field('b', map=True) # needs sage.rings.finite_rings (Finite Field in b of size 7^6, Ring morphism: From: Finite Field in a of size 7^3 To: Finite Field in b of size 7^6 Defn: a |--> 2*b^4 + 6*b^3 + 2*b^2 + 3*b + 2)
P.<x> = PolynomialRing(GF(7)) t = x^2 + 1 t.splitting_field('b') # needs sage.rings.finite_rings P.<x> = PolynomialRing(GF(7^3, 'a')) # needs sage.rings.finite_rings t = x^2 + 1 t.splitting_field('b', map=True) # needs sage.rings.finite_rings
If the extension is trivial and the generators have the same name, the map will be the identity:
sage: t = 24*x^13 + 2*x^12 + 14 sage: t.splitting_field('a', map=True) # needs sage.rings.finite_rings (Finite Field in a of size 7^3, Identity endomorphism of Finite Field in a of size 7^3) sage: t = x^56 - 14*x^3 sage: t.splitting_field('b', map=True) # needs sage.rings.finite_rings (Finite Field in b of size 7^3, Ring morphism: From: Finite Field in a of size 7^3 To: Finite Field in b of size 7^3 Defn: a |--> b)
>>> from sage.all import * >>> t = Integer(24)*x**Integer(13) + Integer(2)*x**Integer(12) + Integer(14) >>> t.splitting_field('a', map=True) # needs sage.rings.finite_rings (Finite Field in a of size 7^3, Identity endomorphism of Finite Field in a of size 7^3) >>> t = x**Integer(56) - Integer(14)*x**Integer(3) >>> t.splitting_field('b', map=True) # needs sage.rings.finite_rings (Finite Field in b of size 7^3, Ring morphism: From: Finite Field in a of size 7^3 To: Finite Field in b of size 7^3 Defn: a |--> b)
t = 24*x^13 + 2*x^12 + 14 t.splitting_field('a', map=True) # needs sage.rings.finite_rings t = x^56 - 14*x^3 t.splitting_field('b', map=True) # needs sage.rings.finite_rings
See also
sage.rings.number_field.splitting_field.splitting_field()
for more examples over number fields
- square()[source]¶
Return the square of this polynomial.
Todo
This is just a placeholder; for now it just uses ordinary multiplication. But generally speaking, squaring is faster than ordinary multiplication, and it’s frequently used, so subclasses may choose to provide a specialised squaring routine.
Perhaps this even belongs at a lower level? RingElement or something?
AUTHORS:
David Harvey (2006-09-09)
EXAMPLES:
sage: R.<x> = QQ[] sage: f = x^3 + 1 sage: f.square() x^6 + 2*x^3 + 1 sage: f*f x^6 + 2*x^3 + 1
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + Integer(1) >>> f.square() x^6 + 2*x^3 + 1 >>> f*f x^6 + 2*x^3 + 1
R.<x> = QQ[] f = x^3 + 1 f.square() f*f
- squarefree_decomposition()[source]¶
Return the square-free decomposition of this polynomial. This is a partial factorization into square-free, coprime polynomials.
EXAMPLES:
sage: x = polygen(QQ) sage: p = 37 * (x - 1)^3 * (x - 2)^3 * (x - 1/3)^7 * (x - 3/7) sage: p.squarefree_decomposition() (37*x - 111/7) * (x^2 - 3*x + 2)^3 * (x - 1/3)^7 sage: p = 37 * (x - 2/3)^2 sage: p.squarefree_decomposition() (37) * (x - 2/3)^2 sage: x = polygen(GF(3)) sage: x.squarefree_decomposition() x sage: f = QQbar['x'](1) # needs sage.rings.number_field sage: f.squarefree_decomposition() # needs sage.rings.number_field 1
>>> from sage.all import * >>> x = polygen(QQ) >>> p = Integer(37) * (x - Integer(1))**Integer(3) * (x - Integer(2))**Integer(3) * (x - Integer(1)/Integer(3))**Integer(7) * (x - Integer(3)/Integer(7)) >>> p.squarefree_decomposition() (37*x - 111/7) * (x^2 - 3*x + 2)^3 * (x - 1/3)^7 >>> p = Integer(37) * (x - Integer(2)/Integer(3))**Integer(2) >>> p.squarefree_decomposition() (37) * (x - 2/3)^2 >>> x = polygen(GF(Integer(3))) >>> x.squarefree_decomposition() x >>> f = QQbar['x'](Integer(1)) # needs sage.rings.number_field >>> f.squarefree_decomposition() # needs sage.rings.number_field 1
x = polygen(QQ) p = 37 * (x - 1)^3 * (x - 2)^3 * (x - 1/3)^7 * (x - 3/7) p.squarefree_decomposition() p = 37 * (x - 2/3)^2 p.squarefree_decomposition() x = polygen(GF(3)) x.squarefree_decomposition() f = QQbar['x'](1) # needs sage.rings.number_field f.squarefree_decomposition() # needs sage.rings.number_field
- subresultants(other)[source]¶
Return the nonzero subresultant polynomials of
self
andother
.INPUT:
other
– a polynomial
OUTPUT: list of polynomials in the same ring as
self
EXAMPLES:
sage: R.<x> = ZZ[] sage: f = x^8 + x^6 - 3*x^4 - 3*x^3 + 8*x^2 + 2*x - 5 sage: g = 3*x^6 + 5*x^4 - 4*x^2 - 9*x + 21 sage: f.subresultants(g) [260708, 9326*x - 12300, 169*x^2 + 325*x - 637, 65*x^2 + 125*x - 245, 25*x^4 - 5*x^2 + 15, 15*x^4 - 3*x^2 + 9]
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(8) + x**Integer(6) - Integer(3)*x**Integer(4) - Integer(3)*x**Integer(3) + Integer(8)*x**Integer(2) + Integer(2)*x - Integer(5) >>> g = Integer(3)*x**Integer(6) + Integer(5)*x**Integer(4) - Integer(4)*x**Integer(2) - Integer(9)*x + Integer(21) >>> f.subresultants(g) [260708, 9326*x - 12300, 169*x^2 + 325*x - 637, 65*x^2 + 125*x - 245, 25*x^4 - 5*x^2 + 15, 15*x^4 - 3*x^2 + 9]
R.<x> = ZZ[] f = x^8 + x^6 - 3*x^4 - 3*x^3 + 8*x^2 + 2*x - 5 g = 3*x^6 + 5*x^4 - 4*x^2 - 9*x + 21 f.subresultants(g)
ALGORITHM:
We use the schoolbook algorithm with Lazard’s optimization described in [Duc1998]
REFERENCES:
Wikipedia article Polynomial_greatest_common_divisor#Subresultants
- subs(in_dict=None, *args, **kwds)[source]¶
Substitute the variable in
self
.EXAMPLES:
sage: R.<x> = QQ[] sage: f = x^3 + x - 3 sage: f.subs(x=5) 127 sage: f.subs(5) 127 sage: f.subs({x:2}) 7 sage: f.subs({}) x^3 + x - 3 sage: f.subs({'x':2}) Traceback (most recent call last): ... TypeError: keys do not match self's parent
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + x - Integer(3) >>> f.subs(x=Integer(5)) 127 >>> f.subs(Integer(5)) 127 >>> f.subs({x:Integer(2)}) 7 >>> f.subs({}) x^3 + x - 3 >>> f.subs({'x':Integer(2)}) Traceback (most recent call last): ... TypeError: keys do not match self's parent
R.<x> = QQ[] f = x^3 + x - 3 f.subs(x=5) f.subs(5) f.subs({x:2}) f.subs({}) f.subs({'x':2})
- sylvester_matrix(right, variable=None)[source]¶
Return the Sylvester matrix of
self
andright
.Note that the Sylvester matrix is not defined if one of the polynomials is zero.
INPUT:
right
– a polynomial in the same ring asself
variable
– (optional) included for compatibility with the multivariate case only; the variable of the polynomials
EXAMPLES:
sage: R.<x> = PolynomialRing(ZZ) sage: f = (6*x + 47) * (7*x^2 - 2*x + 38) sage: g = (6*x + 47) * (3*x^3 + 2*x + 1) sage: M = f.sylvester_matrix(g); M # needs sage.modules [ 42 317 134 1786 0 0 0] [ 0 42 317 134 1786 0 0] [ 0 0 42 317 134 1786 0] [ 0 0 0 42 317 134 1786] [ 18 141 12 100 47 0 0] [ 0 18 141 12 100 47 0] [ 0 0 18 141 12 100 47]
>>> from sage.all import * >>> R = PolynomialRing(ZZ, names=('x',)); (x,) = R._first_ngens(1) >>> f = (Integer(6)*x + Integer(47)) * (Integer(7)*x**Integer(2) - Integer(2)*x + Integer(38)) >>> g = (Integer(6)*x + Integer(47)) * (Integer(3)*x**Integer(3) + Integer(2)*x + Integer(1)) >>> M = f.sylvester_matrix(g); M # needs sage.modules [ 42 317 134 1786 0 0 0] [ 0 42 317 134 1786 0 0] [ 0 0 42 317 134 1786 0] [ 0 0 0 42 317 134 1786] [ 18 141 12 100 47 0 0] [ 0 18 141 12 100 47 0] [ 0 0 18 141 12 100 47]
R.<x> = PolynomialRing(ZZ) f = (6*x + 47) * (7*x^2 - 2*x + 38) g = (6*x + 47) * (3*x^3 + 2*x + 1) M = f.sylvester_matrix(g); M # needs sage.modules
If the polynomials share a non-constant common factor then the determinant of the Sylvester matrix will be zero:
sage: M.determinant() # needs sage.modules 0
>>> from sage.all import * >>> M.determinant() # needs sage.modules 0
M.determinant() # needs sage.modules
If
self
andright
are polynomials of positive degree, the determinant of the Sylvester matrix is the resultant of the polynomials.:sage: h1 = R._random_nonzero_element() sage: h2 = R._random_nonzero_element() sage: M1 = h1.sylvester_matrix(h2) # needs sage.modules sage: M1.determinant() == h1.resultant(h2) # needs sage.libs.pari sage.modules True
>>> from sage.all import * >>> h1 = R._random_nonzero_element() >>> h2 = R._random_nonzero_element() >>> M1 = h1.sylvester_matrix(h2) # needs sage.modules >>> M1.determinant() == h1.resultant(h2) # needs sage.libs.pari sage.modules True
h1 = R._random_nonzero_element() h2 = R._random_nonzero_element() M1 = h1.sylvester_matrix(h2) # needs sage.modules M1.determinant() == h1.resultant(h2) # needs sage.libs.pari sage.modules
The rank of the Sylvester matrix is related to the degree of the gcd of
self
andright
:sage: f.gcd(g).degree() == f.degree() + g.degree() - M.rank() # needs sage.modules True sage: h1.gcd(h2).degree() == h1.degree() + h2.degree() - M1.rank() # needs sage.modules True
>>> from sage.all import * >>> f.gcd(g).degree() == f.degree() + g.degree() - M.rank() # needs sage.modules True >>> h1.gcd(h2).degree() == h1.degree() + h2.degree() - M1.rank() # needs sage.modules True
f.gcd(g).degree() == f.degree() + g.degree() - M.rank() # needs sage.modules h1.gcd(h2).degree() == h1.degree() + h2.degree() - M1.rank() # needs sage.modules
- symmetric_power(k, monic=False)[source]¶
Return the polynomial whose roots are products of \(k\)-th distinct roots of this.
EXAMPLES:
sage: x = polygen(QQ) sage: f = x^4 - x + 2 sage: [f.symmetric_power(k) for k in range(5)] # needs sage.libs.singular [x - 1, x^4 - x + 2, x^6 - 2*x^4 - x^3 - 4*x^2 + 8, x^4 - x^3 + 8, x - 2] sage: f = x^5 - 2*x + 2 sage: [f.symmetric_power(k) for k in range(6)] # needs sage.libs.singular [x - 1, x^5 - 2*x + 2, x^10 + 2*x^8 - 4*x^6 - 8*x^5 - 8*x^4 - 8*x^3 + 16, x^10 + 4*x^7 - 8*x^6 + 16*x^5 - 16*x^4 + 32*x^2 + 64, x^5 + 2*x^4 - 16, x + 2] sage: R.<a,b,c,d> = ZZ[] sage: x = polygen(R) sage: f = (x - a) * (x - b) * (x - c) * (x - d) sage: [f.symmetric_power(k).factor() for k in range(5)] # needs sage.libs.singular [x - 1, (-x + d) * (-x + c) * (-x + b) * (-x + a), (x - c*d) * (x - b*d) * (x - a*d) * (x - b*c) * (x - a*c) * (x - a*b), (x - b*c*d) * (x - a*c*d) * (x - a*b*d) * (x - a*b*c), x - a*b*c*d]
>>> from sage.all import * >>> x = polygen(QQ) >>> f = x**Integer(4) - x + Integer(2) >>> [f.symmetric_power(k) for k in range(Integer(5))] # needs sage.libs.singular [x - 1, x^4 - x + 2, x^6 - 2*x^4 - x^3 - 4*x^2 + 8, x^4 - x^3 + 8, x - 2] >>> f = x**Integer(5) - Integer(2)*x + Integer(2) >>> [f.symmetric_power(k) for k in range(Integer(6))] # needs sage.libs.singular [x - 1, x^5 - 2*x + 2, x^10 + 2*x^8 - 4*x^6 - 8*x^5 - 8*x^4 - 8*x^3 + 16, x^10 + 4*x^7 - 8*x^6 + 16*x^5 - 16*x^4 + 32*x^2 + 64, x^5 + 2*x^4 - 16, x + 2] >>> R = ZZ['a, b, c, d']; (a, b, c, d,) = R._first_ngens(4) >>> x = polygen(R) >>> f = (x - a) * (x - b) * (x - c) * (x - d) >>> [f.symmetric_power(k).factor() for k in range(Integer(5))] # needs sage.libs.singular [x - 1, (-x + d) * (-x + c) * (-x + b) * (-x + a), (x - c*d) * (x - b*d) * (x - a*d) * (x - b*c) * (x - a*c) * (x - a*b), (x - b*c*d) * (x - a*c*d) * (x - a*b*d) * (x - a*b*c), x - a*b*c*d]
x = polygen(QQ) f = x^4 - x + 2 [f.symmetric_power(k) for k in range(5)] # needs sage.libs.singular f = x^5 - 2*x + 2 [f.symmetric_power(k) for k in range(6)] # needs sage.libs.singular R.<a,b,c,d> = ZZ[] x = polygen(R) f = (x - a) * (x - b) * (x - c) * (x - d) [f.symmetric_power(k).factor() for k in range(5)] # needs sage.libs.singular
- trace_polynomial()[source]¶
Compute the trace polynomial and cofactor.
The input \(P\) and output \(Q\) satisfy the relation
\[P(x) = Q(x + q/x) x^{\deg(Q)} R(x).\]In this relation, \(Q\) has all roots in the real interval \([-2\sqrt{q}, 2\sqrt{q}]\) if and only if \(P\) has all roots on the circle \(|x| = \sqrt{q}\) and \(R\) divides \(x^2-q\). We thus require that the base ring of this polynomial have a coercion to the real numbers.
See also
The inverse operation is
reciprocal_transform()
.OUTPUT:
Q
– trace polynomialR
– cofactorq
– scaling factor
EXAMPLES:
sage: pol.<x> = PolynomialRing(Rationals()) sage: u = x^5 - 1; u.trace_polynomial() (x^2 + x - 1, x - 1, 1) sage: u = x^4 + x^3 + 5*x^2 + 3*x + 9 sage: u.trace_polynomial() (x^2 + x - 1, 1, 3)
>>> from sage.all import * >>> pol = PolynomialRing(Rationals(), names=('x',)); (x,) = pol._first_ngens(1) >>> u = x**Integer(5) - Integer(1); u.trace_polynomial() (x^2 + x - 1, x - 1, 1) >>> u = x**Integer(4) + x**Integer(3) + Integer(5)*x**Integer(2) + Integer(3)*x + Integer(9) >>> u.trace_polynomial() (x^2 + x - 1, 1, 3)
pol.<x> = PolynomialRing(Rationals()) u = x^5 - 1; u.trace_polynomial() u = x^4 + x^3 + 5*x^2 + 3*x + 9 u.trace_polynomial()
We check that this function works for rings that have a coercion to the reals:
sage: # needs sage.rings.number_field sage: K.<a> = NumberField(x^2 - 2, embedding=1.4) sage: u = x^4 + a*x^3 + 3*x^2 + 2*a*x + 4 sage: u.trace_polynomial() (x^2 + a*x - 1, 1, 2) sage: (u*(x^2-2)).trace_polynomial() (x^2 + a*x - 1, x^2 - 2, 2) sage: (u*(x^2-2)^2).trace_polynomial() (x^4 + a*x^3 - 9*x^2 - 8*a*x + 8, 1, 2) sage: (u*(x^2-2)^3).trace_polynomial() (x^4 + a*x^3 - 9*x^2 - 8*a*x + 8, x^2 - 2, 2) sage: u = x^4 + a*x^3 + 3*x^2 + 4*a*x + 16 sage: u.trace_polynomial() (x^2 + a*x - 5, 1, 4) sage: (u*(x-2)).trace_polynomial() (x^2 + a*x - 5, x - 2, 4) sage: (u*(x+2)).trace_polynomial() (x^2 + a*x - 5, x + 2, 4)
>>> from sage.all import * >>> # needs sage.rings.number_field >>> K = NumberField(x**Integer(2) - Integer(2), embedding=RealNumber('1.4'), names=('a',)); (a,) = K._first_ngens(1) >>> u = x**Integer(4) + a*x**Integer(3) + Integer(3)*x**Integer(2) + Integer(2)*a*x + Integer(4) >>> u.trace_polynomial() (x^2 + a*x - 1, 1, 2) >>> (u*(x**Integer(2)-Integer(2))).trace_polynomial() (x^2 + a*x - 1, x^2 - 2, 2) >>> (u*(x**Integer(2)-Integer(2))**Integer(2)).trace_polynomial() (x^4 + a*x^3 - 9*x^2 - 8*a*x + 8, 1, 2) >>> (u*(x**Integer(2)-Integer(2))**Integer(3)).trace_polynomial() (x^4 + a*x^3 - 9*x^2 - 8*a*x + 8, x^2 - 2, 2) >>> u = x**Integer(4) + a*x**Integer(3) + Integer(3)*x**Integer(2) + Integer(4)*a*x + Integer(16) >>> u.trace_polynomial() (x^2 + a*x - 5, 1, 4) >>> (u*(x-Integer(2))).trace_polynomial() (x^2 + a*x - 5, x - 2, 4) >>> (u*(x+Integer(2))).trace_polynomial() (x^2 + a*x - 5, x + 2, 4)
# needs sage.rings.number_field K.<a> = NumberField(x^2 - 2, embedding=1.4) u = x^4 + a*x^3 + 3*x^2 + 2*a*x + 4 u.trace_polynomial() (u*(x^2-2)).trace_polynomial() (u*(x^2-2)^2).trace_polynomial() (u*(x^2-2)^3).trace_polynomial() u = x^4 + a*x^3 + 3*x^2 + 4*a*x + 16 u.trace_polynomial() (u*(x-2)).trace_polynomial() (u*(x+2)).trace_polynomial()
- truncate(n)[source]¶
Return the polynomial of degree \(< n\) which is equivalent to
self
modulo \(x^n\).EXAMPLES:
sage: R.<x> = ZZ[]; S.<y> = PolynomialRing(R, sparse=True) sage: f = y^3 + x*y - 3*x; f y^3 + x*y - 3*x sage: f.truncate(2) x*y - 3*x sage: f.truncate(1) -3*x sage: f.truncate(0) 0
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1); S = PolynomialRing(R, sparse=True, names=('y',)); (y,) = S._first_ngens(1) >>> f = y**Integer(3) + x*y - Integer(3)*x; f y^3 + x*y - 3*x >>> f.truncate(Integer(2)) x*y - 3*x >>> f.truncate(Integer(1)) -3*x >>> f.truncate(Integer(0)) 0
R.<x> = ZZ[]; S.<y> = PolynomialRing(R, sparse=True) f = y^3 + x*y - 3*x; f f.truncate(2) f.truncate(1) f.truncate(0)
- valuation(p=None)[source]¶
If \(f = a_r x^r + a_{r+1}x^{r+1} + \cdots\), with \(a_r\) nonzero, then the valuation of \(f\) is \(r\). The valuation of the zero polynomial is \(\infty\).
If a prime (or non-prime) \(p\) is given, then the valuation is the largest power of \(p\) which divides
self
.The valuation at \(\infty\) is
-self.degree()
.EXAMPLES:
sage: P.<x> = ZZ[] sage: (x^2 + x).valuation() 1 sage: (x^2 + x).valuation(x + 1) 1 sage: (x^2 + 1).valuation() 0 sage: (x^3 + 1).valuation(infinity) -3 sage: P(0).valuation() +Infinity
>>> from sage.all import * >>> P = ZZ['x']; (x,) = P._first_ngens(1) >>> (x**Integer(2) + x).valuation() 1 >>> (x**Integer(2) + x).valuation(x + Integer(1)) 1 >>> (x**Integer(2) + Integer(1)).valuation() 0 >>> (x**Integer(3) + Integer(1)).valuation(infinity) -3 >>> P(Integer(0)).valuation() +Infinity
P.<x> = ZZ[] (x^2 + x).valuation() (x^2 + x).valuation(x + 1) (x^2 + 1).valuation() (x^3 + 1).valuation(infinity) P(0).valuation()
- variable_name()[source]¶
Return name of variable used in this polynomial as a string.
OUTPUT: string
EXAMPLES:
sage: R.<t> = QQ[] sage: f = t^3 + 3/2*t + 5 sage: f.variable_name() 't'
>>> from sage.all import * >>> R = QQ['t']; (t,) = R._first_ngens(1) >>> f = t**Integer(3) + Integer(3)/Integer(2)*t + Integer(5) >>> f.variable_name() 't'
R.<t> = QQ[] f = t^3 + 3/2*t + 5 f.variable_name()
- variables()[source]¶
Return the tuple of variables occurring in this polynomial.
EXAMPLES:
sage: R.<x> = QQ[] sage: x.variables() (x,)
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> x.variables() (x,)
R.<x> = QQ[] x.variables()
A constant polynomial has no variables.
sage: R(2).variables() ()
>>> from sage.all import * >>> R(Integer(2)).variables() ()
R(2).variables()
- xgcd(other)[source]¶
Return an extended gcd of this polynomial and
other
.INPUT:
other
– a polynomial in the same ring as this polynomial
OUTPUT:
A tuple
(r, s, t)
wherer
is a greatest common divisor of this polynomial andother
, ands
andt
are such thatr = s*self + t*other
holds.Note
The actual algorithm for computing the extended gcd depends on the base ring underlying the polynomial ring. If the base ring defines a method
_xgcd_univariate_polynomial()
, then this method will be called (see examples below).EXAMPLES:
sage: # needs sage.rings.number_field sage: R.<x> = QQbar[] sage: (2*x^2).gcd(2*x) x sage: R.zero().gcd(0) 0 sage: (2*x).gcd(0) x
>>> from sage.all import * >>> # needs sage.rings.number_field >>> R = QQbar['x']; (x,) = R._first_ngens(1) >>> (Integer(2)*x**Integer(2)).gcd(Integer(2)*x) x >>> R.zero().gcd(Integer(0)) 0 >>> (Integer(2)*x).gcd(Integer(0)) x
# needs sage.rings.number_field R.<x> = QQbar[] (2*x^2).gcd(2*x) R.zero().gcd(0) (2*x).gcd(0)
One can easily add xgcd functionality to new rings by providing a method
_xgcd_univariate_polynomial()
:sage: R.<x> = QQ[] sage: S.<y> = R[] sage: h1 = y*x sage: h2 = y^2*x^2 sage: h1.xgcd(h2) Traceback (most recent call last): ... NotImplementedError: Univariate Polynomial Ring in x over Rational Field does not provide an xgcd implementation for univariate polynomials sage: T.<x,y> = QQ[] sage: def poor_xgcd(f, g): ....: ret = S(T(f).gcd(g)) ....: if ret == f: return ret, S.one(), S.zero() ....: if ret == g: return ret, S.zero(), S.one() ....: raise NotImplementedError sage: R._xgcd_univariate_polynomial = poor_xgcd sage: h1.xgcd(h2) (x*y, 1, 0) sage: del R._xgcd_univariate_polynomial
>>> from sage.all import * >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> S = R['y']; (y,) = S._first_ngens(1) >>> h1 = y*x >>> h2 = y**Integer(2)*x**Integer(2) >>> h1.xgcd(h2) Traceback (most recent call last): ... NotImplementedError: Univariate Polynomial Ring in x over Rational Field does not provide an xgcd implementation for univariate polynomials >>> T = QQ['x, y']; (x, y,) = T._first_ngens(2) >>> def poor_xgcd(f, g): ... ret = S(T(f).gcd(g)) ... if ret == f: return ret, S.one(), S.zero() ... if ret == g: return ret, S.zero(), S.one() ... raise NotImplementedError >>> R._xgcd_univariate_polynomial = poor_xgcd >>> h1.xgcd(h2) (x*y, 1, 0) >>> del R._xgcd_univariate_polynomial
R.<x> = QQ[] S.<y> = R[] h1 = y*x h2 = y^2*x^2 h1.xgcd(h2) T.<x,y> = QQ[] def poor_xgcd(f, g): ret = S(T(f).gcd(g)) if ret == f: return ret, S.one(), S.zero() if ret == g: return ret, S.zero(), S.one() raise NotImplementedError R._xgcd_univariate_polynomial = poor_xgcd h1.xgcd(h2) del R._xgcd_univariate_polynomial
- class sage.rings.polynomial.polynomial_element.PolynomialBaseringInjection[source]¶
Bases:
Morphism
This class is used for conversion from a ring to a polynomial over that ring.
It calls the
_new_constant_poly()
method on the generator, which should be optimized for a particular polynomial type.Technically, it should be a method of the polynomial ring, but few polynomial rings are Cython classes, and so, as a method of a Cython polynomial class, it is faster.
EXAMPLES:
We demonstrate that most polynomial ring classes use polynomial base injection maps for coercion. They are supposed to be the fastest maps for that purpose. See Issue #9944.
sage: # needs sage.rings.padics sage: R.<x> = Qp(3)[] sage: R.coerce_map_from(R.base_ring()) Polynomial base injection morphism: From: 3-adic Field with capped relative precision 20 To: Univariate Polynomial Ring in x over 3-adic Field with capped relative precision 20 sage: R.<x,y> = Qp(3)[] sage: R.coerce_map_from(R.base_ring()) Polynomial base injection morphism: From: 3-adic Field with capped relative precision 20 To: Multivariate Polynomial Ring in x, y over 3-adic Field with capped relative precision 20 sage: R.<x,y> = QQ[] sage: R.coerce_map_from(R.base_ring()) Polynomial base injection morphism: From: Rational Field To: Multivariate Polynomial Ring in x, y over Rational Field sage: R.<x> = QQ[] sage: R.coerce_map_from(R.base_ring()) Polynomial base injection morphism: From: Rational Field To: Univariate Polynomial Ring in x over Rational Field
>>> from sage.all import * >>> # needs sage.rings.padics >>> R = Qp(Integer(3))['x']; (x,) = R._first_ngens(1) >>> R.coerce_map_from(R.base_ring()) Polynomial base injection morphism: From: 3-adic Field with capped relative precision 20 To: Univariate Polynomial Ring in x over 3-adic Field with capped relative precision 20 >>> R = Qp(Integer(3))['x, y']; (x, y,) = R._first_ngens(2) >>> R.coerce_map_from(R.base_ring()) Polynomial base injection morphism: From: 3-adic Field with capped relative precision 20 To: Multivariate Polynomial Ring in x, y over 3-adic Field with capped relative precision 20 >>> R = QQ['x, y']; (x, y,) = R._first_ngens(2) >>> R.coerce_map_from(R.base_ring()) Polynomial base injection morphism: From: Rational Field To: Multivariate Polynomial Ring in x, y over Rational Field >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> R.coerce_map_from(R.base_ring()) Polynomial base injection morphism: From: Rational Field To: Univariate Polynomial Ring in x over Rational Field
# needs sage.rings.padics R.<x> = Qp(3)[] R.coerce_map_from(R.base_ring()) R.<x,y> = Qp(3)[] R.coerce_map_from(R.base_ring()) R.<x,y> = QQ[] R.coerce_map_from(R.base_ring()) R.<x> = QQ[] R.coerce_map_from(R.base_ring())
By Issue #9944, there are now only very few exceptions:
sage: PolynomialRing(QQ,names=[]).coerce_map_from(QQ) Call morphism: From: Rational Field To: Multivariate Polynomial Ring in no variables over Rational Field
>>> from sage.all import * >>> PolynomialRing(QQ,names=[]).coerce_map_from(QQ) Call morphism: From: Rational Field To: Multivariate Polynomial Ring in no variables over Rational Field
PolynomialRing(QQ,names=[]).coerce_map_from(QQ)
- is_injective()[source]¶
Return whether this morphism is injective.
EXAMPLES:
sage: R.<x> = ZZ[] sage: S.<y> = R[] sage: S.coerce_map_from(R).is_injective() True
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> S = R['y']; (y,) = S._first_ngens(1) >>> S.coerce_map_from(R).is_injective() True
R.<x> = ZZ[] S.<y> = R[] S.coerce_map_from(R).is_injective()
Check that Issue #23203 has been resolved:
sage: R.is_subring(S) # indirect doctest True
>>> from sage.all import * >>> R.is_subring(S) # indirect doctest True
R.is_subring(S) # indirect doctest
- is_surjective()[source]¶
Return whether this morphism is surjective.
EXAMPLES:
sage: R.<x> = ZZ[] sage: R.coerce_map_from(ZZ).is_surjective() False
>>> from sage.all import * >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> R.coerce_map_from(ZZ).is_surjective() False
R.<x> = ZZ[] R.coerce_map_from(ZZ).is_surjective()
- class sage.rings.polynomial.polynomial_element.Polynomial_generic_dense[source]¶
Bases:
Polynomial
A generic dense polynomial.
EXAMPLES:
sage: f = QQ['x']['y'].random_element() sage: loads(f.dumps()) == f True
>>> from sage.all import * >>> f = QQ['x']['y'].random_element() >>> loads(f.dumps()) == f True
f = QQ['x']['y'].random_element() loads(f.dumps()) == f
- constant_coefficient()[source]¶
Return the constant coefficient of this polynomial.
OUTPUT: element of base ring
EXAMPLES:
sage: R.<t> = QQ[] sage: S.<x> = R[] sage: f = x*t + x + t sage: f.constant_coefficient() t
>>> from sage.all import * >>> R = QQ['t']; (t,) = R._first_ngens(1) >>> S = R['x']; (x,) = S._first_ngens(1) >>> f = x*t + x + t >>> f.constant_coefficient() t
R.<t> = QQ[] S.<x> = R[] f = x*t + x + t f.constant_coefficient()
- degree(gen=None)[source]¶
EXAMPLES:
sage: R.<x> = RDF[] sage: f = (1+2*x^7)^5 sage: f.degree() 35
>>> from sage.all import * >>> R = RDF['x']; (x,) = R._first_ngens(1) >>> f = (Integer(1)+Integer(2)*x**Integer(7))**Integer(5) >>> f.degree() 35
R.<x> = RDF[] f = (1+2*x^7)^5 f.degree()
- is_term()[source]¶
Return
True
if this polynomial is a nonzero element of the base ring times a power of the variable.EXAMPLES:
sage: # needs sage.symbolic sage: R.<x> = SR[] sage: R(0).is_term() False sage: R(1).is_term() True sage: (3*x^5).is_term() True sage: (1 + 3*x^5).is_term() False
>>> from sage.all import * >>> # needs sage.symbolic >>> R = SR['x']; (x,) = R._first_ngens(1) >>> R(Integer(0)).is_term() False >>> R(Integer(1)).is_term() True >>> (Integer(3)*x**Integer(5)).is_term() True >>> (Integer(1) + Integer(3)*x**Integer(5)).is_term() False
# needs sage.symbolic R.<x> = SR[] R(0).is_term() R(1).is_term() (3*x^5).is_term() (1 + 3*x^5).is_term()
- list(copy=True)[source]¶
Return a new copy of the list of the underlying elements of
self
.EXAMPLES:
sage: R.<x> = GF(17)[] sage: f = (1+2*x)^3 + 3*x; f 8*x^3 + 12*x^2 + 9*x + 1 sage: f.list() [1, 9, 12, 8]
>>> from sage.all import * >>> R = GF(Integer(17))['x']; (x,) = R._first_ngens(1) >>> f = (Integer(1)+Integer(2)*x)**Integer(3) + Integer(3)*x; f 8*x^3 + 12*x^2 + 9*x + 1 >>> f.list() [1, 9, 12, 8]
R.<x> = GF(17)[] f = (1+2*x)^3 + 3*x; f f.list()
- quo_rem(other)[source]¶
Return the quotient and remainder of the Euclidean division of
self
andother
.Raises a
ZeroDivisionError
ifother
is zero. Raises anArithmeticError
if the division is not exact.EXAMPLES:
sage: P.<x> = QQ[] sage: R.<y> = P[] sage: f = y^10 + R.random_element(9) sage: g = y^5 + R.random_element(4) sage: q, r = f.quo_rem(g) sage: f == q*g + r True sage: g = x*y^5 sage: f.quo_rem(g) Traceback (most recent call last): ... ArithmeticError: division non exact (consider coercing to polynomials over the fraction field) sage: g = 0 sage: f.quo_rem(g) Traceback (most recent call last): ... ZeroDivisionError: division by zero polynomial
>>> from sage.all import * >>> P = QQ['x']; (x,) = P._first_ngens(1) >>> R = P['y']; (y,) = R._first_ngens(1) >>> f = y**Integer(10) + R.random_element(Integer(9)) >>> g = y**Integer(5) + R.random_element(Integer(4)) >>> q, r = f.quo_rem(g) >>> f == q*g + r True >>> g = x*y**Integer(5) >>> f.quo_rem(g) Traceback (most recent call last): ... ArithmeticError: division non exact (consider coercing to polynomials over the fraction field) >>> g = Integer(0) >>> f.quo_rem(g) Traceback (most recent call last): ... ZeroDivisionError: division by zero polynomial
P.<x> = QQ[] R.<y> = P[] f = y^10 + R.random_element(9) g = y^5 + R.random_element(4) q, r = f.quo_rem(g) f == q*g + r g = x*y^5 f.quo_rem(g) g = 0 f.quo_rem(g)
Polynomials over noncommutative rings are also allowed (after Issue #34733):
sage: # needs sage.combinat sage.modules sage: HH = QuaternionAlgebra(QQ, -1, -1) sage: P.<x> = HH[] sage: f = P.random_element(5) sage: g = P.random_element((0, 5)) sage: q, r = f.quo_rem(g) sage: f == q*g + r True
>>> from sage.all import * >>> # needs sage.combinat sage.modules >>> HH = QuaternionAlgebra(QQ, -Integer(1), -Integer(1)) >>> P = HH['x']; (x,) = P._first_ngens(1) >>> f = P.random_element(Integer(5)) >>> g = P.random_element((Integer(0), Integer(5))) >>> q, r = f.quo_rem(g) >>> f == q*g + r True
# needs sage.combinat sage.modules HH = QuaternionAlgebra(QQ, -1, -1) P.<x> = HH[] f = P.random_element(5) g = P.random_element((0, 5)) q, r = f.quo_rem(g) f == q*g + r
- shift(n)[source]¶
Return this polynomial multiplied by the power \(x^n\).
If \(n\) is negative, terms below \(x^n\) will be discarded. Does not change this polynomial.
EXAMPLES:
sage: R.<x> = PolynomialRing(PolynomialRing(QQ,'y'), 'x') sage: p = x^2 + 2*x + 4 sage: type(p) <class 'sage.rings.polynomial.polynomial_element.Polynomial_generic_dense'> sage: p.shift(0) x^2 + 2*x + 4 sage: p.shift(-1) x + 2 sage: p.shift(2) x^4 + 2*x^3 + 4*x^2
>>> from sage.all import * >>> R = PolynomialRing(PolynomialRing(QQ,'y'), 'x', names=('x',)); (x,) = R._first_ngens(1) >>> p = x**Integer(2) + Integer(2)*x + Integer(4) >>> type(p) <class 'sage.rings.polynomial.polynomial_element.Polynomial_generic_dense'> >>> p.shift(Integer(0)) x^2 + 2*x + 4 >>> p.shift(-Integer(1)) x + 2 >>> p.shift(Integer(2)) x^4 + 2*x^3 + 4*x^2
R.<x> = PolynomialRing(PolynomialRing(QQ,'y'), 'x') p = x^2 + 2*x + 4 type(p) p.shift(0) p.shift(-1) p.shift(2)
AUTHORS:
David Harvey (2006-08-06)
- truncate(n)[source]¶
Return the polynomial of degree \(< n\) which is equivalent to
self
modulo \(x^n\).EXAMPLES:
sage: S.<q> = QQ['t']['q'] sage: f = (1 + q^10 + q^11 + q^12).truncate(11); f q^10 + 1 sage: f = (1 + q^10 + q^100).truncate(50); f q^10 + 1 sage: f.degree() 10 sage: f = (1 + q^10 + q^100).truncate(500); f q^100 + q^10 + 1
>>> from sage.all import * >>> S = QQ['t']['q']; (q,) = S._first_ngens(1) >>> f = (Integer(1) + q**Integer(10) + q**Integer(11) + q**Integer(12)).truncate(Integer(11)); f q^10 + 1 >>> f = (Integer(1) + q**Integer(10) + q**Integer(100)).truncate(Integer(50)); f q^10 + 1 >>> f.degree() 10 >>> f = (Integer(1) + q**Integer(10) + q**Integer(100)).truncate(Integer(500)); f q^100 + q^10 + 1
S.<q> = QQ['t']['q'] f = (1 + q^10 + q^11 + q^12).truncate(11); f f = (1 + q^10 + q^100).truncate(50); f f.degree() f = (1 + q^10 + q^100).truncate(500); f
- class sage.rings.polynomial.polynomial_element.Polynomial_generic_dense_inexact[source]¶
Bases:
Polynomial_generic_dense
A dense polynomial over an inexact ring.
AUTHOR:
Xavier Caruso (2013-03)
- degree(secure=False)[source]¶
INPUT:
secure
– boolean (default:False
)
OUTPUT: the degree of
self
If
secure
isTrue
and the degree of this polynomial is not determined (because the leading coefficient is indistinguishable from 0), an error is raisedIf
secure
isFalse
, the returned value is the largest \(n\) so that the coefficient of \(x^n\) does not compare equal to \(0\).EXAMPLES:
sage: # needs sage.rings.padics sage: K = Qp(3, 10) sage: R.<T> = K[] sage: f = T + 2; f (1 + O(3^10))*T + 2 + O(3^10) sage: f.degree() 1 sage: (f - T).degree() 0 sage: (f - T).degree(secure=True) Traceback (most recent call last): ... PrecisionError: the leading coefficient is indistinguishable from 0 sage: # needs sage.rings.padics sage: x = O(3^5) sage: li = [3^i * x for i in range(0,5)]; li [O(3^5), O(3^6), O(3^7), O(3^8), O(3^9)] sage: f = R(li); f O(3^9)*T^4 + O(3^8)*T^3 + O(3^7)*T^2 + O(3^6)*T + O(3^5) sage: f.degree() -1 sage: f.degree(secure=True) Traceback (most recent call last): ... PrecisionError: the leading coefficient is indistinguishable from 0
>>> from sage.all import * >>> # needs sage.rings.padics >>> K = Qp(Integer(3), Integer(10)) >>> R = K['T']; (T,) = R._first_ngens(1) >>> f = T + Integer(2); f (1 + O(3^10))*T + 2 + O(3^10) >>> f.degree() 1 >>> (f - T).degree() 0 >>> (f - T).degree(secure=True) Traceback (most recent call last): ... PrecisionError: the leading coefficient is indistinguishable from 0 >>> # needs sage.rings.padics >>> x = O(Integer(3)**Integer(5)) >>> li = [Integer(3)**i * x for i in range(Integer(0),Integer(5))]; li [O(3^5), O(3^6), O(3^7), O(3^8), O(3^9)] >>> f = R(li); f O(3^9)*T^4 + O(3^8)*T^3 + O(3^7)*T^2 + O(3^6)*T + O(3^5) >>> f.degree() -1 >>> f.degree(secure=True) Traceback (most recent call last): ... PrecisionError: the leading coefficient is indistinguishable from 0
# needs sage.rings.padics K = Qp(3, 10) R.<T> = K[] f = T + 2; f f.degree() (f - T).degree() (f - T).degree(secure=True) # needs sage.rings.padics x = O(3^5) li = [3^i * x for i in range(0,5)]; li f = R(li); f f.degree() f.degree(secure=True)
AUTHOR:
Xavier Caruso (2013-03)
- prec_degree()[source]¶
Return the largest \(n\) so that precision information is stored about the coefficient of \(x^n\).
Always greater than or equal to degree.
EXAMPLES:
sage: # needs sage.rings.padics sage: K = Qp(3, 10) sage: R.<T> = K[] sage: f = T + 2; f (1 + O(3^10))*T + 2 + O(3^10) sage: f.degree() 1 sage: f.prec_degree() 1 sage: g = f - T; g # needs sage.rings.padics O(3^10)*T + 2 + O(3^10) sage: g.degree() # needs sage.rings.padics 0 sage: g.prec_degree() # needs sage.rings.padics 1
>>> from sage.all import * >>> # needs sage.rings.padics >>> K = Qp(Integer(3), Integer(10)) >>> R = K['T']; (T,) = R._first_ngens(1) >>> f = T + Integer(2); f (1 + O(3^10))*T + 2 + O(3^10) >>> f.degree() 1 >>> f.prec_degree() 1 >>> g = f - T; g # needs sage.rings.padics O(3^10)*T + 2 + O(3^10) >>> g.degree() # needs sage.rings.padics 0 >>> g.prec_degree() # needs sage.rings.padics 1
# needs sage.rings.padics K = Qp(3, 10) R.<T> = K[] f = T + 2; f f.degree() f.prec_degree() g = f - T; g # needs sage.rings.padics g.degree() # needs sage.rings.padics g.prec_degree() # needs sage.rings.padics
AUTHOR:
Xavier Caruso (2013-03)
- sage.rings.polynomial.polynomial_element.generic_power_trunc(p, n, prec)[source]¶
Generic truncated power algorithm.
INPUT:
p
– a polynomialn
– integer (of typesage.rings.integer.Integer
)prec
– a precision (should fit into a Clong
)
- sage.rings.polynomial.polynomial_element.is_Polynomial(f)[source]¶
Return
True
iff
is of type univariate polynomial.This function is deprecated.
INPUT:
f
– an object
EXAMPLES:
sage: from sage.rings.polynomial.polynomial_element import is_Polynomial sage: R.<x> = ZZ[] sage: is_Polynomial(x^3 + x + 1) doctest:...: DeprecationWarning: the function is_Polynomial is deprecated; use isinstance(x, sage.rings.polynomial.polynomial_element.Polynomial) instead See https://github.com/sagemath/sage/issues/32709 for details. True sage: S.<y> = R[] sage: f = y^3 + x*y - 3*x; f y^3 + x*y - 3*x sage: is_Polynomial(f) True
>>> from sage.all import * >>> from sage.rings.polynomial.polynomial_element import is_Polynomial >>> R = ZZ['x']; (x,) = R._first_ngens(1) >>> is_Polynomial(x**Integer(3) + x + Integer(1)) doctest:...: DeprecationWarning: the function is_Polynomial is deprecated; use isinstance(x, sage.rings.polynomial.polynomial_element.Polynomial) instead See https://github.com/sagemath/sage/issues/32709 for details. True >>> S = R['y']; (y,) = S._first_ngens(1) >>> f = y**Integer(3) + x*y - Integer(3)*x; f y^3 + x*y - 3*x >>> is_Polynomial(f) True
from sage.rings.polynomial.polynomial_element import is_Polynomial R.<x> = ZZ[] is_Polynomial(x^3 + x + 1) S.<y> = R[] f = y^3 + x*y - 3*x; f is_Polynomial(f)
However this function does not return
True
for genuine multivariate polynomial type objects or symbolic polynomials, since those are not of the same data type as univariate polynomials:sage: R.<x,y> = QQ[] sage: f = y^3 + x*y - 3*x; f y^3 + x*y - 3*x sage: is_Polynomial(f) False sage: # needs sage.symbolic sage: var('x,y') (x, y) sage: f = y^3 + x*y - 3*x; f y^3 + x*y - 3*x sage: is_Polynomial(f) False
>>> from sage.all import * >>> R = QQ['x, y']; (x, y,) = R._first_ngens(2) >>> f = y**Integer(3) + x*y - Integer(3)*x; f y^3 + x*y - 3*x >>> is_Polynomial(f) False >>> # needs sage.symbolic >>> var('x,y') (x, y) >>> f = y**Integer(3) + x*y - Integer(3)*x; f y^3 + x*y - 3*x >>> is_Polynomial(f) False
R.<x,y> = QQ[] f = y^3 + x*y - 3*x; f is_Polynomial(f) # needs sage.symbolic var('x,y') f = y^3 + x*y - 3*x; f is_Polynomial(f)
- sage.rings.polynomial.polynomial_element.polynomial_is_variable(x)[source]¶
Test whether the given polynomial is a variable of its parent ring.
Implemented for instances of
Polynomial
andMPolynomial
.See also
EXAMPLES:
sage: from sage.rings.polynomial.polynomial_element import polynomial_is_variable sage: R.<x> = QQ[] sage: polynomial_is_variable(x) True sage: polynomial_is_variable(R([0,1])) True sage: polynomial_is_variable(x^2) False sage: polynomial_is_variable(R(42)) False
>>> from sage.all import * >>> from sage.rings.polynomial.polynomial_element import polynomial_is_variable >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> polynomial_is_variable(x) True >>> polynomial_is_variable(R([Integer(0),Integer(1)])) True >>> polynomial_is_variable(x**Integer(2)) False >>> polynomial_is_variable(R(Integer(42))) False
from sage.rings.polynomial.polynomial_element import polynomial_is_variable R.<x> = QQ[] polynomial_is_variable(x) polynomial_is_variable(R([0,1])) polynomial_is_variable(x^2) polynomial_is_variable(R(42))
sage: R.<y,z> = QQ[] sage: polynomial_is_variable(y) True sage: polynomial_is_variable(z) True sage: polynomial_is_variable(y^2) False sage: polynomial_is_variable(y+z) False sage: polynomial_is_variable(R(42)) False
>>> from sage.all import * >>> R = QQ['y, z']; (y, z,) = R._first_ngens(2) >>> polynomial_is_variable(y) True >>> polynomial_is_variable(z) True >>> polynomial_is_variable(y**Integer(2)) False >>> polynomial_is_variable(y+z) False >>> polynomial_is_variable(R(Integer(42))) False
R.<y,z> = QQ[] polynomial_is_variable(y) polynomial_is_variable(z) polynomial_is_variable(y^2) polynomial_is_variable(y+z) polynomial_is_variable(R(42))
>>> from sage.all import * >>> R = QQ['y, z']; (y, z,) = R._first_ngens(2) >>> polynomial_is_variable(y) True >>> polynomial_is_variable(z) True >>> polynomial_is_variable(y**Integer(2)) False >>> polynomial_is_variable(y+z) False >>> polynomial_is_variable(R(Integer(42))) False
R.<y,z> = QQ[] polynomial_is_variable(y) polynomial_is_variable(z) polynomial_is_variable(y^2) polynomial_is_variable(y+z) polynomial_is_variable(R(42))
sage: polynomial_is_variable(42) False
>>> from sage.all import * >>> polynomial_is_variable(Integer(42)) False
polynomial_is_variable(42)
>>> from sage.all import * >>> polynomial_is_variable(Integer(42)) False
polynomial_is_variable(42)
- sage.rings.polynomial.polynomial_element.universal_discriminant()[source]¶
Return the discriminant of the ‘universal’ univariate polynomial \(a_n x^n + \cdots + a_1 x + a_0\) in \(\ZZ[a_0, \ldots, a_n][x]\).
INPUT:
n
– degree of the polynomial
OUTPUT:
The discriminant as a polynomial in \(n + 1\) variables over \(\ZZ\). The result will be cached, so subsequent computations of discriminants of the same degree will be faster.
EXAMPLES:
sage: # needs sage.libs.pari sage: from sage.rings.polynomial.polynomial_element import universal_discriminant sage: universal_discriminant(1) 1 sage: universal_discriminant(2) a1^2 - 4*a0*a2 sage: universal_discriminant(3) a1^2*a2^2 - 4*a0*a2^3 - 4*a1^3*a3 + 18*a0*a1*a2*a3 - 27*a0^2*a3^2 sage: universal_discriminant(4).degrees() (3, 4, 4, 4, 3)
>>> from sage.all import * >>> # needs sage.libs.pari >>> from sage.rings.polynomial.polynomial_element import universal_discriminant >>> universal_discriminant(Integer(1)) 1 >>> universal_discriminant(Integer(2)) a1^2 - 4*a0*a2 >>> universal_discriminant(Integer(3)) a1^2*a2^2 - 4*a0*a2^3 - 4*a1^3*a3 + 18*a0*a1*a2*a3 - 27*a0^2*a3^2 >>> universal_discriminant(Integer(4)).degrees() (3, 4, 4, 4, 3)
# needs sage.libs.pari from sage.rings.polynomial.polynomial_element import universal_discriminant universal_discriminant(1) universal_discriminant(2) universal_discriminant(3) universal_discriminant(4).degrees()
See also