Polynomials - Tutorial

Skip to content
Back to top
View this page
Edit this page

# Polynomials

In this section we illustrate how to create and use polynomials in Sage.

## Univariate Polynomials

There are three ways to create polynomial rings.

Sage

    sage: R = PolynomialRing(QQ, 't')
    sage: R
    Univariate Polynomial Ring in t over Rational Field

Python

    >>> from sage.all import *
    >>> R = PolynomialRing(QQ, 't')
    >>> R
    Univariate Polynomial Ring in t over Rational Field

This creates a polynomial ring and tells Sage to use (the string) ‘t’ as the indeterminate when printing to the screen. However, this does not define the symbol `t` for use in Sage, so you cannot use it to enter a polynomial (such as \(t^2+1\)) belonging to `R`.

An alternate way is

Sage

    sage: S = QQ['t']
    sage: S == R
    True

[Python]

    >>> from sage.all import *
    >>> S = QQ['t']
    >>> S == R
    True

This has the same issue regarding `t`.

A third very convenient way is

Sage

    sage: R.<t> = PolynomialRing(QQ)

Python

    >>> from sage.all import *
    >>> R = PolynomialRing(QQ, names=('t',)); (t,) = R._first_ngens(1)

or

Sage

    sage: R.<t> = QQ['t']

[Python]

    >>> from sage.all import *
    >>> R = QQ['t']; (t,) = R._first_ngens(1)

or even

Sage

    sage: R.<t> = QQ[]

Python

    >>> from sage.all import *
    >>> R = QQ['t']; (t,) = R._first_ngens(1)

This has the additional side effect that it defines the variable `t` to be the indeterminate of the polynomial ring, so you can easily construct elements of `R`, as follows. (Note that the third way is very similar to the constructor notation in Magma, and just as in Magma it can be used for a wide range of objects.)

Sage

    sage: poly = (t+1) * (t+2); poly
    t^2 + 3*t + 2
    sage: poly in R
    True

[Python]

    >>> from sage.all import *
    >>> poly = (t+Integer(1)) * (t+Integer(2)); poly
    t^2 + 3*t + 2
    >>> poly in R
    True

Whatever method you use to define a polynomial ring, you can recover the indeterminate as the \(0^{th}\) generator:

Sage

    sage: R = PolynomialRing(QQ, 't')
    sage: t = R.0
    sage: t in R
    True

Python

    >>> from sage.all import *
    >>> R = PolynomialRing(QQ, 't')
    >>> t = R.gen(0)
    >>> t in R
    True

Note that a similar construction works with the complex numbers: the complex numbers can be viewed as being generated over the real numbers by the symbol `i`; thus we have the following:

Sage

    sage: CC
    Complex Field with 53 bits of precision
    sage: CC.0  # 0th generator of CC
    1.00000000000000*I

[Python]

    >>> from sage.all import *
    >>> CC
    Complex Field with 53 bits of precision
    >>> CC.gen(0)  # 0th generator of CC
    1.00000000000000*I

For polynomial rings, you can obtain both the ring and its generator, or just the generator, during ring creation as follows:

Sage

    sage: R, t = QQ['t'].objgen()
    sage: t    = QQ['t'].gen()
    sage: R, t = objgen(QQ['t'])
    sage: t    = gen(QQ['t'])

Python

    >>> from sage.all import *
    >>> R, t = QQ['t'].objgen()
    >>> t    = QQ['t'].gen()
    >>> R, t = objgen(QQ['t'])
    >>> t    = gen(QQ['t'])

Finally we do some arithmetic in \(\QQ[t]\).

Sage

    sage: R, t = QQ['t'].objgen()
    sage: f = 2*t^7 + 3*t^2 - 15/19
    sage: f^2
    4*t^14 + 12*t^9 - 60/19*t^7 + 9*t^4 - 90/19*t^2 + 225/361
    sage: cyclo = R.cyclotomic_polynomial(7); cyclo
    t^6 + t^5 + t^4 + t^3 + t^2 + t + 1
    sage: g = 7 * cyclo * t^5 * (t^5 + 10*t + 2)
    sage: g
    7*t^16 + 7*t^15 + 7*t^14 + 7*t^13 + 77*t^12 + 91*t^11 + 91*t^10 + 84*t^9
           + 84*t^8 + 84*t^7 + 84*t^6 + 14*t^5
    sage: F = factor(g); F
    (7) * t^5 * (t^5 + 10*t + 2) * (t^6 + t^5 + t^4 + t^3 + t^2 + t + 1)
    sage: F.unit()
    7
    sage: list(F)
    [(t, 5), (t^5 + 10*t + 2, 1), (t^6 + t^5 + t^4 + t^3 + t^2 + t + 1, 1)]

[Python]

    >>> from sage.all import *
    >>> R, t = QQ['t'].objgen()
    >>> f = Integer(2)*t**Integer(7) + Integer(3)*t**Integer(2) - Integer(15)/Integer(19)
    >>> f**Integer(2)
    4*t^14 + 12*t^9 - 60/19*t^7 + 9*t^4 - 90/19*t^2 + 225/361
    >>> cyclo = R.cyclotomic_polynomial(Integer(7)); cyclo
    t^6 + t^5 + t^4 + t^3 + t^2 + t + 1
    >>> g = Integer(7) * cyclo * t**Integer(5) * (t**Integer(5) + Integer(10)*t + Integer(2))
    >>> g
    7*t^16 + 7*t^15 + 7*t^14 + 7*t^13 + 77*t^12 + 91*t^11 + 91*t^10 + 84*t^9
           + 84*t^8 + 84*t^7 + 84*t^6 + 14*t^5
    >>> F = factor(g); F
    (7) * t^5 * (t^5 + 10*t + 2) * (t^6 + t^5 + t^4 + t^3 + t^2 + t + 1)
    >>> F.unit()
    7
    >>> list(F)
    [(t, 5), (t^5 + 10*t + 2, 1), (t^6 + t^5 + t^4 + t^3 + t^2 + t + 1, 1)]

Notice that the factorization correctly takes into account and records the unit part.

If you were to use, e.g., the `R.cyclotomic_polynomial` function a lot for some research project, in addition to citing Sage you should make an attempt to find out what component of Sage is being used to actually compute the cyclotomic polynomial and cite that as well. In this case, if you type `R.cyclotomic_polynomial??` to see the source code, you’ll quickly see a line `f = pari.polcyclo(n)` which means that PARI is being used for computation of the cyclotomic polynomial. Cite PARI in your work as well.

Dividing two polynomials constructs an element of the fraction field (which Sage creates automatically).

Sage

    sage: x = QQ['x'].0
    sage: f = x^3 + 1; g = x^2 - 17
    sage: h = f/g;  h
    (x^3 + 1)/(x^2 - 17)
    sage: h.parent()
    Fraction Field of Univariate Polynomial Ring in x over Rational Field

Python

    >>> from sage.all import *
    >>> x = QQ['x'].gen(0)
    >>> f = x**Integer(3) + Integer(1); g = x**Integer(2) - Integer(17)
    >>> h = f/g;  h
    (x^3 + 1)/(x^2 - 17)
    >>> h.parent()
    Fraction Field of Univariate Polynomial Ring in x over Rational Field

Using Laurent series, one can compute series expansions in the fraction field of `QQ[x]`:

Sage

    sage: R.<x> = LaurentSeriesRing(QQ); R
    Laurent Series Ring in x over Rational Field
    sage: 1/(1-x) + O(x^10)
    1 + x + x^2 + x^3 + x^4 + x^5 + x^6 + x^7 + x^8 + x^9 + O(x^10)

[Python]

    >>> from sage.all import *
    >>> R = LaurentSeriesRing(QQ, names=('x',)); (x,) = R._first_ngens(1); R
    Laurent Series Ring in x over Rational Field
    >>> Integer(1)/(Integer(1)-x) + O(x**Integer(10))
    1 + x + x^2 + x^3 + x^4 + x^5 + x^6 + x^7 + x^8 + x^9 + O(x^10)

If we name the variable differently, we obtain a different univariate polynomial ring.

Sage

    sage: R.<x> = PolynomialRing(QQ)
    sage: S.<y> = PolynomialRing(QQ)
    sage: x == y
    False
    sage: R == S
    False
    sage: R(y)
    x
    sage: R(y^2 - 17)
    x^2 - 17

Python

    >>> from sage.all import *
    >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1)
    >>> S = PolynomialRing(QQ, names=('y',)); (y,) = S._first_ngens(1)
    >>> x == y
    False
    >>> R == S
    False
    >>> R(y)
    x
    >>> R(y**Integer(2) - Integer(17))
    x^2 - 17

The ring is determined by the variable. Note that making another ring with variable called `x` does not return a different ring.

Sage

    sage: R = PolynomialRing(QQ, "x")
    sage: T = PolynomialRing(QQ, "x")
    sage: R == T
    True
    sage: R is T
    True
    sage: R.0 == T.0
    True

[Python]

    >>> from sage.all import *
    >>> R = PolynomialRing(QQ, "x")
    >>> T = PolynomialRing(QQ, "x")
    >>> R == T
    True
    >>> R is T
    True
    >>> R.gen(0) == T.gen(0)
    True

Sage also has support for power series and Laurent series rings over any base ring. In the following example, we create an element of \(\GF{7}[[T]]\) and divide to create an element of \(\GF{7}((T))\).

Sage

    sage: R.<T> = PowerSeriesRing(GF(7)); R
    Power Series Ring in T over Finite Field of size 7
    sage: f = T  + 3*T^2 + T^3 + O(T^4)
    sage: f^3
    T^3 + 2*T^4 + 2*T^5 + O(T^6)
    sage: 1/f
    T^-1 + 4 + T + O(T^2)
    sage: parent(1/f)
    Laurent Series Ring in T over Finite Field of size 7

Python

    >>> from sage.all import *
    >>> R = PowerSeriesRing(GF(Integer(7)), names=('T',)); (T,) = R._first_ngens(1); R
    Power Series Ring in T over Finite Field of size 7
    >>> f = T  + Integer(3)*T**Integer(2) + T**Integer(3) + O(T**Integer(4))
    >>> f**Integer(3)
    T^3 + 2*T^4 + 2*T^5 + O(T^6)
    >>> Integer(1)/f
    T^-1 + 4 + T + O(T^2)
    >>> parent(Integer(1)/f)
    Laurent Series Ring in T over Finite Field of size 7

You can also create power series rings using a double-brackets shorthand:

Sage

    sage: GF(7)[['T']]
    Power Series Ring in T over Finite Field of size 7

[Python]

    >>> from sage.all import *
    >>> GF(Integer(7))[['T']]
    Power Series Ring in T over Finite Field of size 7

## Multivariate Polynomials

To work with polynomials of several variables, we declare the polynomial ring and variables first.

Sage

    sage: R = PolynomialRing(GF(5),3,"z") # here, 3 = number of variables
    sage: R
    Multivariate Polynomial Ring in z0, z1, z2 over Finite Field of size 5

Python

    >>> from sage.all import *
    >>> R = PolynomialRing(GF(Integer(5)),Integer(3),"z") # here, 3 = number of variables
    >>> R
    Multivariate Polynomial Ring in z0, z1, z2 over Finite Field of size 5

Just as for defining univariate polynomial rings, there are alternative ways:

Sage

    sage: GF(5)['z0, z1, z2']
    Multivariate Polynomial Ring in z0, z1, z2 over Finite Field of size 5
    sage: R.<z0,z1,z2> = GF(5)[]; R
    Multivariate Polynomial Ring in z0, z1, z2 over Finite Field of size 5

[Python]

    >>> from sage.all import *
    >>> GF(Integer(5))['z0, z1, z2']
    Multivariate Polynomial Ring in z0, z1, z2 over Finite Field of size 5
    >>> R = GF(Integer(5))['z0, z1, z2']; (z0, z1, z2,) = R._first_ngens(3); R
    Multivariate Polynomial Ring in z0, z1, z2 over Finite Field of size 5

Also, if you want the variable names to be single letters then you can use the following shorthand:

Sage

    sage: PolynomialRing(GF(5), 3, 'xyz')
    Multivariate Polynomial Ring in x, y, z over Finite Field of size 5

Python

    >>> from sage.all import *
    >>> PolynomialRing(GF(Integer(5)), Integer(3), 'xyz')
    Multivariate Polynomial Ring in x, y, z over Finite Field of size 5

Next let’s do some arithmetic.

Sage

    sage: z = GF(5)['z0, z1, z2'].gens()
    sage: z
    (z0, z1, z2)
    sage: (z[0]+z[1]+z[2])^2
    z0^2 + 2*z0*z1 + z1^2 + 2*z0*z2 + 2*z1*z2 + z2^2

[Python]

    >>> from sage.all import *
    >>> z = GF(Integer(5))['z0, z1, z2'].gens()
    >>> z
    (z0, z1, z2)
    >>> (z[Integer(0)]+z[Integer(1)]+z[Integer(2)])**Integer(2)
    z0^2 + 2*z0*z1 + z1^2 + 2*z0*z2 + 2*z1*z2 + z2^2

You can also use more mathematical notation to construct a polynomial ring.

Sage

    sage: R = GF(5)['x,y,z']
    sage: x,y,z = R.gens()
    sage: QQ['x']
    Univariate Polynomial Ring in x over Rational Field
    sage: QQ['x,y'].gens()
    (x, y)
    sage: QQ['x'].objgens()
    (Univariate Polynomial Ring in x over Rational Field, (x,))

Python

    >>> from sage.all import *
    >>> R = GF(Integer(5))['x,y,z']
    >>> x,y,z = R.gens()
    >>> QQ['x']
    Univariate Polynomial Ring in x over Rational Field
    >>> QQ['x,y'].gens()
    (x, y)
    >>> QQ['x'].objgens()
    (Univariate Polynomial Ring in x over Rational Field, (x,))

Multivariate polynomials are implemented in Sage using Python dictionaries and the “distributive representation” of a polynomial. Sage makes some use of Singular [Si], e.g., for computation of gcd’s and Gröbner basis of ideals.

Sage

    sage: R, (x, y) = PolynomialRing(RationalField(), 2, 'xy').objgens()
    sage: f = (x^3 + 2*y^2*x)^2
    sage: g = x^2*y^2
    sage: f.gcd(g)
    x^2

[Python]

    >>> from sage.all import *
    >>> R, (x, y) = PolynomialRing(RationalField(), Integer(2), 'xy').objgens()
    >>> f = (x**Integer(3) + Integer(2)*y**Integer(2)*x)**Integer(2)
    >>> g = x**Integer(2)*y**Integer(2)
    >>> f.gcd(g)
    x^2

Next we create the ideal \((f,g)\) generated by \(f\) and \(g\), by simply multiplying `(f,g)` by `R` (we could also write `ideal([f,g])` or `ideal(f,g)`).

Sage

    sage: I = (f, g)*R; I
    Ideal (x^6 + 4*x^4*y^2 + 4*x^2*y^4, x^2*y^2) of Multivariate Polynomial
    Ring in x, y over Rational Field
    sage: B = I.groebner_basis(); B
    [x^6, x^2*y^2]
    sage: x^2 in I
    False

Python

    >>> from sage.all import *
    >>> I = (f, g)*R; I
    Ideal (x^6 + 4*x^4*y^2 + 4*x^2*y^4, x^2*y^2) of Multivariate Polynomial
    Ring in x, y over Rational Field
    >>> B = I.groebner_basis(); B
    [x^6, x^2*y^2]
    >>> x**Integer(2) in I
    False

Incidentally, the Gröbner basis above is not a list but an immutable sequence. This means that it has a universe, parent, and cannot be changed (which is good because changing the basis would break other routines that use the Gröbner basis).

Sage

    sage: B.universe()
    Multivariate Polynomial Ring in x, y over Rational Field
    sage: B[1] = x
    Traceback (most recent call last):
    ...
    ValueError: object is immutable; please change a copy instead.

[Python]

    >>> from sage.all import *
    >>> B.universe()
    Multivariate Polynomial Ring in x, y over Rational Field
    >>> B[Integer(1)] = x
    Traceback (most recent call last):
    ...
    ValueError: object is immutable; please change a copy instead.

Some (read: not as much as we would like) commutative algebra is available in Sage, implemented via Singular. For example, we can compute the primary decomposition and associated primes of \(I\):

Sage

    sage: I.primary_decomposition()
    [Ideal (x^2) of Multivariate Polynomial Ring in x, y over Rational Field,
     Ideal (y^2, x^6) of Multivariate Polynomial Ring in x, y over Rational Field]
    sage: I.associated_primes()
    [Ideal (x) of Multivariate Polynomial Ring in x, y over Rational Field,
     Ideal (y, x) of Multivariate Polynomial Ring in x, y over Rational Field]

Python

    >>> from sage.all import *
    >>> I.primary_decomposition()
    [Ideal (x^2) of Multivariate Polynomial Ring in x, y over Rational Field,
     Ideal (y^2, x^6) of Multivariate Polynomial Ring in x, y over Rational Field]
    >>> I.associated_primes()
    [Ideal (x) of Multivariate Polynomial Ring in x, y over Rational Field,
     Ideal (y, x) of Multivariate Polynomial Ring in x, y over Rational Field]