Univariate Ore polynomial rings - Noncommutative Polynomials

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

# Univariate Ore polynomial rings

This module provides the `OrePolynomialRing`, which constructs a general dense univariate Ore polynomial ring over a commutative base with equipped with an endomorphism and/or a derivation.

AUTHOR:

- Xavier Caruso (2020-04)

class sage.rings.polynomial.ore_polynomial_ring.OrePolynomialRing(base_ring, morphism, derivation, name, sparse, category=None)

  Bases: `UniqueRepresentation`, `Parent`

  Construct and return the globally unique Ore polynomial ring with the given properties and variable names.

  Given a ring \(R\) and a ring automorphism \(\sigma\) of \(R\) and a \(\sigma\)-derivation \(\partial\), the ring of Ore polynomials \(R[X; \sigma, \partial]\) is the usual abelian group polynomial \(R[X]\) equipped with the modification multiplication deduced from the rule \(X a = \sigma(a) X + \partial(a)\). We refer to [Ore1933] for more material on Ore polynomials.

  INPUT:

  - `base_ring` – a commutative ring

  - `twisting_map` – either an endomorphism of the base ring, or a (twisted) derivation of it

  - `names` – string or list of strings

  - `sparse` – boolean (default: `False`); currently not supported

  EXAMPLES:

  The case of a twisting endomorphism

  We create the Ore ring \(\GF{5^3}[x, \text{Frob}]\) where Frob is the Frobenius endomorphism:

  Sage

      sage: k.<a> = GF(5^3)
      sage: Frob = k.frobenius_endomorphism()
      sage: S = OrePolynomialRing(k, Frob, 'x'); S
      Ore Polynomial Ring in x over Finite Field in a of size 5^3 twisted by a |--> a^5

  Python

      >>> from sage.all import *
      >>> k = GF(Integer(5)**Integer(3), names=('a',)); (a,) = k._first_ngens(1)
      >>> Frob = k.frobenius_endomorphism()
      >>> S = OrePolynomialRing(k, Frob, 'x'); S
      Ore Polynomial Ring in x over Finite Field in a of size 5^3 twisted by a |--> a^5

  In particular, observe that it is not needed to create and pass in the twisting derivation (which is \(0\) in our example).

  As a shortcut, we can use the square brackets notation as follow:

  Sage

      sage: T.<x> = k['x', Frob]; T
      Ore Polynomial Ring in x over Finite Field in a of size 5^3 twisted by a |--> a^5
      sage: T is S
      True

  [Python]

      >>> from sage.all import *
      >>> T = k['x', Frob]; (x,) = T._first_ngens(1); T
      Ore Polynomial Ring in x over Finite Field in a of size 5^3 twisted by a |--> a^5
      >>> T is S
      True

  We emphasize that it is necessary to repeat the name of the variable in the right hand side. Indeed, the following fails (it is interpreted by Sage as a classical polynomial ring with variable name `Frob`):

  Sage

      sage: T.<x> = k[Frob]                                                           # needs sage.rings.finite_rings
      Traceback (most recent call last):
      ...
      ValueError: variable name 'Frobenius endomorphism a |--> a^5 on
      Finite Field in a of size 5^3' is not alphanumeric

  Python

      >>> from sage.all import *
      >>> T = k[Frob]; (x,) = T._first_ngens(1)# needs sage.rings.finite_rings
      Traceback (most recent call last):
      ...
      ValueError: variable name 'Frobenius endomorphism a |--> a^5 on
      Finite Field in a of size 5^3' is not alphanumeric

  Note moreover that, similarly to the classical case, using the brackets notation also sets the variable:

  Sage

      sage: x.parent() is S                                                           # needs sage.rings.finite_rings
      True

  [Python]

      >>> from sage.all import *
      >>> x.parent() is S                                                           # needs sage.rings.finite_rings
      True

  We are now ready to carry on computations in the Ore ring:

  Sage

      sage: x*a                                                                       # needs sage.rings.finite_rings
      (2*a^2 + 4*a + 4)*x
      sage: Frob(a)*x                                                                 # needs sage.rings.finite_rings
      (2*a^2 + 4*a + 4)*x

  Python

      >>> from sage.all import *
      >>> x*a                                                                       # needs sage.rings.finite_rings
      (2*a^2 + 4*a + 4)*x
      >>> Frob(a)*x                                                                 # needs sage.rings.finite_rings
      (2*a^2 + 4*a + 4)*x

  The case of a twisting derivation

  We can similarly create the Ore ring of differential operators over \(\QQ[t]\), namely \(\QQ[t][d, \frac{d}{dt}]\):

  Sage

      sage: R.<t> = QQ[]
      sage: der = R.derivation(); der
      d/dt
      sage: A = OrePolynomialRing(R, der, 'd'); A
      Ore Polynomial Ring in d over Univariate Polynomial Ring in t
       over Rational Field twisted by d/dt

  [Python]

      >>> from sage.all import *
      >>> R = QQ['t']; (t,) = R._first_ngens(1)
      >>> der = R.derivation(); der
      d/dt
      >>> A = OrePolynomialRing(R, der, 'd'); A
      Ore Polynomial Ring in d over Univariate Polynomial Ring in t
       over Rational Field twisted by d/dt

  Again, the brackets notation is available:

  Sage

      sage: B.<d> = R['d', der]                                                       # needs sage.rings.finite_rings
      sage: A is B                                                                    # needs sage.rings.finite_rings
      True

  Python

      >>> from sage.all import *
      >>> B = R['d', der]; (d,) = B._first_ngens(1)# needs sage.rings.finite_rings
      >>> A is B                                                                    # needs sage.rings.finite_rings
      True

  and computations can be carried out:

  Sage

      sage: d*t                                                                       # needs sage.rings.finite_rings
      t*d + 1

  [Python]

      >>> from sage.all import *
      >>> d*t                                                                       # needs sage.rings.finite_rings
      t*d + 1

  The combined case

  Ore polynomial rings involving at the same time a twisting morphism \(\sigma\) and a twisting \(\sigma\)-derivation can be created as well as follows:

  Sage

      sage: F.<u> = Qq(3^2)
      sage: sigma = F.frobenius_endomorphism(); sigma
      Frobenius endomorphism on 3-adic Unramified Extension Field in u
       defined by x^2 + 2*x + 2 lifting u |--> u^3 on the residue field
      sage: der = F.derivation(3, twist=sigma); der
      (3 + O(3^21))*([Frob] - id)
      sage: M.<X> = F['X', der]; M
      Ore Polynomial Ring in X over 3-adic Unramified Extension Field in u
       defined by x^2 + 2*x + 2 twisted by Frob and (3 + O(3^21))*([Frob] - id)

  Python

      >>> from sage.all import *
      >>> F = Qq(Integer(3)**Integer(2), names=('u',)); (u,) = F._first_ngens(1)
      >>> sigma = F.frobenius_endomorphism(); sigma
      Frobenius endomorphism on 3-adic Unramified Extension Field in u
       defined by x^2 + 2*x + 2 lifting u |--> u^3 on the residue field
      >>> der = F.derivation(Integer(3), twist=sigma); der
      (3 + O(3^21))*([Frob] - id)
      >>> M = F['X', der]; (X,) = M._first_ngens(1); M
      Ore Polynomial Ring in X over 3-adic Unramified Extension Field in u
       defined by x^2 + 2*x + 2 twisted by Frob and (3 + O(3^21))*([Frob] - id)

  We emphasize that we only need to pass in the twisted derivation as it already contains in it the datum of the twisting endomorphism. Actually, passing in both twisting maps results in an error:

  Sage

      sage: F['X', sigma, der]                                                        # needs sage.rings.padics
      Traceback (most recent call last):
      ...
      ValueError: variable name 'Frobenius endomorphism ...' is not alphanumeric

  [Python]

      >>> from sage.all import *
      >>> F['X', sigma, der]                                                        # needs sage.rings.padics
      Traceback (most recent call last):
      ...
      ValueError: variable name 'Frobenius endomorphism ...' is not alphanumeric

  Examples of variable name context

  Consider the following:

  Sage

      sage: R.<t> = ZZ[]
      sage: sigma = R.hom([t+1])
      sage: S.<x> = SkewPolynomialRing(R, sigma); S
      Ore Polynomial Ring in x over Univariate Polynomial Ring in t over Integer Ring
       twisted by t |--> t + 1

  Python

      >>> from sage.all import *
      >>> R = ZZ['t']; (t,) = R._first_ngens(1)
      >>> sigma = R.hom([t+Integer(1)])
      >>> S = SkewPolynomialRing(R, sigma, names=('x',)); (x,) = S._first_ngens(1); S
      Ore Polynomial Ring in x over Univariate Polynomial Ring in t over Integer Ring
       twisted by t |--> t + 1

  The names of the variables defined above cannot be arbitrarily modified because each Ore polynomial ring is unique in Sage and other objects in Sage could have pointers to that Ore polynomial ring.

  However, the variable can be changed within the scope of a `with` block using the localvars context:

  Sage

      sage: R.<t> = ZZ[]
      sage: sigma = R.hom([t+1])
      sage: S.<x> = SkewPolynomialRing(R, sigma); S
      Ore Polynomial Ring in x over Univariate Polynomial Ring in t over Integer Ring
       twisted by t |--> t + 1

      sage: with localvars(S, ['y']):
      ....:     print(S)
      Ore Polynomial Ring in y over Univariate Polynomial Ring in t over Integer Ring
       twisted by t |--> t + 1

  [Python]

      >>> from sage.all import *
      >>> R = ZZ['t']; (t,) = R._first_ngens(1)
      >>> sigma = R.hom([t+Integer(1)])
      >>> S = SkewPolynomialRing(R, sigma, names=('x',)); (x,) = S._first_ngens(1); S
      Ore Polynomial Ring in x over Univariate Polynomial Ring in t over Integer Ring
       twisted by t |--> t + 1

      >>> with localvars(S, ['y']):
      ...     print(S)
      Ore Polynomial Ring in y over Univariate Polynomial Ring in t over Integer Ring
       twisted by t |--> t + 1

  Uniqueness and immutability

  In Sage, there is exactly one Ore polynomial ring for each quadruple (base ring, twisting morphism, twisting derivation, name of the variable):

  Sage

      sage: k.<a> = GF(7^3)
      sage: Frob = k.frobenius_endomorphism()
      sage: S = k['x', Frob]
      sage: T = k['x', Frob]
      sage: S is T
      True

  Python

      >>> from sage.all import *
      >>> k = GF(Integer(7)**Integer(3), names=('a',)); (a,) = k._first_ngens(1)
      >>> Frob = k.frobenius_endomorphism()
      >>> S = k['x', Frob]
      >>> T = k['x', Frob]
      >>> S is T
      True

  Rings with different variables names are different:

  Sage

      sage: S is k['y', Frob]                                                         # needs sage.rings.finite_rings
      False

  [Python]

      >>> from sage.all import *
      >>> S is k['y', Frob]                                                         # needs sage.rings.finite_rings
      False

  Similarly, varying the twisting morphisms yields to different Ore rings (expect when the morphism coincide):

  Sage

      sage: S is k['x', Frob^2]                                                       # needs sage.rings.finite_rings
      False
      sage: S is k['x', Frob^3]                                                       # needs sage.rings.finite_rings
      False
      sage: S is k['x', Frob^4]                                                       # needs sage.rings.finite_rings
      True

  Python

      >>> from sage.all import *
      >>> S is k['x', Frob**Integer(2)]                                                       # needs sage.rings.finite_rings
      False
      >>> S is k['x', Frob**Integer(3)]                                                       # needs sage.rings.finite_rings
      False
      >>> S is k['x', Frob**Integer(4)]                                                       # needs sage.rings.finite_rings
      True

  Todo

  - Sparse Ore Polynomial Ring

  - Multivariate Ore Polynomial Ring

  Element = None
  change_var(var)

    Return the Ore polynomial ring in variable `var` with the same base ring, twisting morphism and twisting derivation as `self`.

    INPUT:

    - `var` – string representing the name of the new variable

    EXAMPLES:

    Sage

        sage: k.<t> = GF(5^3)
        sage: Frob = k.frobenius_endomorphism()
        sage: R.<x> = OrePolynomialRing(k,Frob); R
        Ore Polynomial Ring in x over Finite Field in t of size 5^3 twisted by t |--> t^5
        sage: Ry = R.change_var('y'); Ry
        Ore Polynomial Ring in y over Finite Field in t of size 5^3 twisted by t |--> t^5
        sage: Ry is R.change_var('y')
        True

    Python

        >>> from sage.all import *
        >>> k = GF(Integer(5)**Integer(3), names=('t',)); (t,) = k._first_ngens(1)
        >>> Frob = k.frobenius_endomorphism()
        >>> R = OrePolynomialRing(k,Frob, names=('x',)); (x,) = R._first_ngens(1); R
        Ore Polynomial Ring in x over Finite Field in t of size 5^3 twisted by t |--> t^5
        >>> Ry = R.change_var('y'); Ry
        Ore Polynomial Ring in y over Finite Field in t of size 5^3 twisted by t |--> t^5
        >>> Ry is R.change_var('y')
        True

  characteristic()

    Return the characteristic of the base ring of `self`.

    EXAMPLES:

    Sage

        sage: R.<t> = QQ[]
        sage: sigma = R.hom([t+1])
        sage: R['x',sigma].characteristic()
        0

        sage: k.<u> = GF(5^3)
        sage: Frob = k.frobenius_endomorphism()
        sage: k['y',Frob].characteristic()
        5

    Python

        >>> from sage.all import *
        >>> R = QQ['t']; (t,) = R._first_ngens(1)
        >>> sigma = R.hom([t+Integer(1)])
        >>> R['x',sigma].characteristic()
        0

        >>> k = GF(Integer(5)**Integer(3), names=('u',)); (u,) = k._first_ngens(1)
        >>> Frob = k.frobenius_endomorphism()
        >>> k['y',Frob].characteristic()
        5

  fraction_field()

    Return the fraction field of this skew ring.

    EXAMPLES:

    Sage

        sage: k.<a> = GF(5^3)
        sage: Frob = k.frobenius_endomorphism()
        sage: S.<x> = k['x', Frob]
        sage: K = S.fraction_field(); K
        Ore Function Field in x over Finite Field in a of size 5^3 twisted by a |--> a^5
        sage: f = 1/(x + a); f
        (x + a)^(-1)
        sage: f.parent() is K
        True

    Python

        >>> from sage.all import *
        >>> k = GF(Integer(5)**Integer(3), names=('a',)); (a,) = k._first_ngens(1)
        >>> Frob = k.frobenius_endomorphism()
        >>> S = k['x', Frob]; (x,) = S._first_ngens(1)
        >>> K = S.fraction_field(); K
        Ore Function Field in x over Finite Field in a of size 5^3 twisted by a |--> a^5
        >>> f = Integer(1)/(x + a); f
        (x + a)^(-1)
        >>> f.parent() is K
        True

    Below is another example with differentiel operators:

    Sage

        sage: R.<t> = QQ[]
        sage: der = R.derivation()
        sage: A.<d> = R['d', der]
        sage: A.fraction_field()
        Ore Function Field in d over Fraction Field of Univariate Polynomial Ring in t
         over Rational Field twisted by d/dt
        sage: f = t/d; f
        (d - 1/t)^(-1) * t
        sage: f*d
        t

    [Python]

        >>> from sage.all import *
        >>> R = QQ['t']; (t,) = R._first_ngens(1)
        >>> der = R.derivation()
        >>> A = R['d', der]; (d,) = A._first_ngens(1)
        >>> A.fraction_field()
        Ore Function Field in d over Fraction Field of Univariate Polynomial Ring in t
         over Rational Field twisted by d/dt
        >>> f = t/d; f
        (d - 1/t)^(-1) * t
        >>> f*d
        t

    See also

    `sage.rings.polynomial.ore_function_field`

  gen(n=0)

    Return the indeterminate generator of this Ore polynomial ring.

    INPUT:

    - `n` – index of generator to return (default: 0); exists for compatibility with other polynomial rings

    EXAMPLES:

    Sage

        sage: R.<t> = QQ[]
        sage: sigma = R.hom([t+1])
        sage: S.<x> = R['x',sigma]; S
        Ore Polynomial Ring in x over Univariate Polynomial Ring in t
         over Rational Field twisted by t |--> t + 1
        sage: y = S.gen(); y
        x
        sage: y == x
        True
        sage: S.gen(0)
        x

    Python

        >>> from sage.all import *
        >>> R = QQ['t']; (t,) = R._first_ngens(1)
        >>> sigma = R.hom([t+Integer(1)])
        >>> S = R['x',sigma]; (x,) = S._first_ngens(1); S
        Ore Polynomial Ring in x over Univariate Polynomial Ring in t
         over Rational Field twisted by t |--> t + 1
        >>> y = S.gen(); y
        x
        >>> y == x
        True
        >>> S.gen(Integer(0))
        x

    This is also known as the parameter:

    Sage

        sage: S.parameter() is S.gen()
        True

    [Python]

        >>> from sage.all import *
        >>> S.parameter() is S.gen()
        True

  gens()

    Return the tuple of generators of `self`.

    EXAMPLES:

    Sage

        sage: R.<t> = QQ[]
        sage: sigma = R.hom([t+1])
        sage: S.<x> = R['x',sigma]; S
        Ore Polynomial Ring in x over Univariate Polynomial Ring in t
         over Rational Field twisted by t |--> t + 1
        sage: S.gens()
        (x,)

    Python

        >>> from sage.all import *
        >>> R = QQ['t']; (t,) = R._first_ngens(1)
        >>> sigma = R.hom([t+Integer(1)])
        >>> S = R['x',sigma]; (x,) = S._first_ngens(1); S
        Ore Polynomial Ring in x over Univariate Polynomial Ring in t
         over Rational Field twisted by t |--> t + 1
        >>> S.gens()
        (x,)

  gens_dict()

    Return a {name: variable} dictionary of the generators of this Ore polynomial ring.

    EXAMPLES:

    Sage

        sage: R.<t> = ZZ[]
        sage: sigma = R.hom([t+1])
        sage: S.<x> = SkewPolynomialRing(R,sigma)
        sage: S.gens_dict()
        {'x': x}

    Python

        >>> from sage.all import *
        >>> R = ZZ['t']; (t,) = R._first_ngens(1)
        >>> sigma = R.hom([t+Integer(1)])
        >>> S = SkewPolynomialRing(R,sigma, names=('x',)); (x,) = S._first_ngens(1)
        >>> S.gens_dict()
        {'x': x}

  is_exact()

    Return `True` if elements of this Ore polynomial ring are exact.

    This happens if and only if elements of the base ring are exact.

    EXAMPLES:

    Sage

        sage: k.<t> = GF(5^3)
        sage: Frob = k.frobenius_endomorphism()
        sage: S.<x> = k['x', Frob]
        sage: S.is_exact()
        True
        sage: S.base_ring().is_exact()
        True
        sage: R.<u> = k[[]]
        sage: sigma = R.hom([u + u^2])
        sage: T.<y> = R['y', sigma]
        sage: T.is_exact()
        False
        sage: T.base_ring().is_exact()
        False

    Python

        >>> from sage.all import *
        >>> k = GF(Integer(5)**Integer(3), names=('t',)); (t,) = k._first_ngens(1)
        >>> Frob = k.frobenius_endomorphism()
        >>> S = k['x', Frob]; (x,) = S._first_ngens(1)
        >>> S.is_exact()
        True
        >>> S.base_ring().is_exact()
        True
        >>> R = k[['u']]; (u,) = R._first_ngens(1)
        >>> sigma = R.hom([u + u**Integer(2)])
        >>> T = R['y', sigma]; (y,) = T._first_ngens(1)
        >>> T.is_exact()
        False
        >>> T.base_ring().is_exact()
        False

  is_field(proof=False)

    Return always `False` since Ore polynomial rings are never fields.

    EXAMPLES:

    Sage

        sage: k.<a> = GF(5^3)
        sage: Frob = k.frobenius_endomorphism()
        sage: S.<x> = k['x', Frob]
        sage: S.is_field()
        False

    Python

        >>> from sage.all import *
        >>> k = GF(Integer(5)**Integer(3), names=('a',)); (a,) = k._first_ngens(1)
        >>> Frob = k.frobenius_endomorphism()
        >>> S = k['x', Frob]; (x,) = S._first_ngens(1)
        >>> S.is_field()
        False

  is_finite()

    Return `False` since Ore polynomial rings are not finite (unless the base ring is \(0\)).

    EXAMPLES:

    Sage

        sage: k.<t> = GF(5^3)
        sage: k.is_finite()
        True
        sage: Frob = k.frobenius_endomorphism()
        sage: S.<x> = k['x',Frob]
        sage: S.is_finite()
        False

    Python

        >>> from sage.all import *
        >>> k = GF(Integer(5)**Integer(3), names=('t',)); (t,) = k._first_ngens(1)
        >>> k.is_finite()
        True
        >>> Frob = k.frobenius_endomorphism()
        >>> S = k['x',Frob]; (x,) = S._first_ngens(1)
        >>> S.is_finite()
        False

  is_sparse()

    Return `True` if the elements of this Ore polynomial ring are sparsely represented.

    Warning

    Since sparse Ore polynomials are not yet implemented, this function always returns `False`.

    EXAMPLES:

    Sage

        sage: R.<t> = RR[]
        sage: sigma = R.hom([t+1])
        sage: S.<x> = R['x',sigma]
        sage: S.is_sparse()
        False

    Python

        >>> from sage.all import *
        >>> R = RR['t']; (t,) = R._first_ngens(1)
        >>> sigma = R.hom([t+Integer(1)])
        >>> S = R['x',sigma]; (x,) = S._first_ngens(1)
        >>> S.is_sparse()
        False

  ngens()

    Return the number of generators of this Ore polynomial ring.

    This is \(1\).

    EXAMPLES:

    Sage

        sage: R.<t> = RR[]
        sage: sigma = R.hom([t+1])
        sage: S.<x> = R['x',sigma]
        sage: S.ngens()
        1

    Python

        >>> from sage.all import *
        >>> R = RR['t']; (t,) = R._first_ngens(1)
        >>> sigma = R.hom([t+Integer(1)])
        >>> S = R['x',sigma]; (x,) = S._first_ngens(1)
        >>> S.ngens()
        1

  parameter(n=0)

    alias of `gen()`.

  quotient_module(P, names=None)

    Return the quotient ring \(A/AP\) as a module over \(A\) where \(A\) is this Ore polynomial ring.

    INPUT:

    - `names` (default: `None`) – a string or a list of string, the names of the vector of the canonical basis

    EXAMPLES:

    Sage

        sage: k.<a> = GF(5^3)
        sage: S.<x> = k['a', k.frobenius_endomorphism()]
        sage: P = x^3 + a*x^2 + a^2 + 1
        sage: M = S.quotient_module(P)
        sage: M
        Ore module of rank 3 over Finite Field in a of size 5^3 twisted by a |--> a^5

    Python

        >>> from sage.all import *
        >>> k = GF(Integer(5)**Integer(3), names=('a',)); (a,) = k._first_ngens(1)
        >>> S = k['a', k.frobenius_endomorphism()]; (x,) = S._first_ngens(1)
        >>> P = x**Integer(3) + a*x**Integer(2) + a**Integer(2) + Integer(1)
        >>> M = S.quotient_module(P)
        >>> M
        Ore module of rank 3 over Finite Field in a of size 5^3 twisted by a |--> a^5

    The argument `names` can be used to give chosen names to the vectors in the canonical basis:

    Sage

        sage: M = S.quotient_module(P, names=('u', 'v', 'w'))
        sage: M.basis()
        [u, v, w]

    [Python]

        >>> from sage.all import *
        >>> M = S.quotient_module(P, names=('u', 'v', 'w'))
        >>> M.basis()
        [u, v, w]

    or even:

    Sage

        sage: M = S.quotient_module(P, names='e')
        sage: M.basis()
        [e0, e1, e2]

    Python

        >>> from sage.all import *
        >>> M = S.quotient_module(P, names='e')
        >>> M.basis()
        [e0, e1, e2]

    Note that the bracket construction also works:

    Sage

        sage: M.<u,v,w> = S.quotient_module(P)
        sage: M.basis()
        [u, v, w]

    [Python]

        >>> from sage.all import *
        >>> M = S.quotient_module(P, names=('u', 'v', 'w',)); (u, v, w,) = M._first_ngens(3)
        >>> M.basis()
        [u, v, w]

    With this construction, the vectors \(u\), \(v\) and \(w\) are directly available in the namespace:

    Sage

        sage: x*u + v
        2*v

    Python

        >>> from sage.all import *
        >>> x*u + v
        2*v

    We refer to `sage.modules.ore_module` for a tutorial on Ore modules in SageMath.

    See also

    `sage.modules.ore_module`

  random_element(degree=(-1, 2), monic=False, *args, **kwds)

    Return a random Ore polynomial in this ring.

    INPUT:

    - `degree` – (default: `(-1,2)`) integer with degree or a tuple of integers with minimum and maximum degrees

    - `monic` – boolean (default: `False`); if `True`, return a monic Ore polynomial

    - `*args`, `**kwds` – passed on to the `random_element` method for the base ring

    OUTPUT:

    Ore polynomial such that the coefficients of \(x^i\), for \(i\) up to `degree`, are random elements from the base ring, randomized subject to the arguments `*args` and `**kwds`.

    EXAMPLES:

    Sage

        sage: k.<t> = GF(5^3)
        sage: Frob = k.frobenius_endomorphism()
        sage: S.<x> = k['x', Frob]
        sage: S.random_element()  # random
        (2*t^2 + 3)*x^2 + (4*t^2 + t + 4)*x + 2*t^2 + 2
        sage: S.random_element(monic=True)  # random
        x^2 + (2*t^2 + t + 1)*x + 3*t^2 + 3*t + 2

    Python

        >>> from sage.all import *
        >>> k = GF(Integer(5)**Integer(3), names=('t',)); (t,) = k._first_ngens(1)
        >>> Frob = k.frobenius_endomorphism()
        >>> S = k['x', Frob]; (x,) = S._first_ngens(1)
        >>> S.random_element()  # random
        (2*t^2 + 3)*x^2 + (4*t^2 + t + 4)*x + 2*t^2 + 2
        >>> S.random_element(monic=True)  # random
        x^2 + (2*t^2 + t + 1)*x + 3*t^2 + 3*t + 2

    Use `degree` to obtain polynomials of higher degree:

    Sage

        sage: p = S.random_element(degree=5)   # random
        (t^2 + 3*t)*x^5 + (4*t + 4)*x^3 + (4*t^2 + 4*t)*x^2 + (2*t^2 + 1)*x + 3
        sage: p.degree() == 5
        True

    [Python]

        >>> from sage.all import *
        >>> p = S.random_element(degree=Integer(5))   # random
        (t^2 + 3*t)*x^5 + (4*t + 4)*x^3 + (4*t^2 + 4*t)*x^2 + (2*t^2 + 1)*x + 3
        >>> p.degree() == Integer(5)
        True

    If a tuple of two integers is given for the degree argument, a random integer will be chosen between the first and second element of the tuple as the degree, both inclusive:

    Sage

        sage: S.random_element(degree=(2,7))  # random                              # needs sage.rings.finite_rings
        (3*t^2 + 1)*x^4 + (4*t + 2)*x^3 + (4*t + 1)*x^2
         + (t^2 + 3*t + 3)*x + 3*t^2 + 2*t + 2

    Python

        >>> from sage.all import *
        >>> S.random_element(degree=(Integer(2),Integer(7)))  # random                              # needs sage.rings.finite_rings
        (3*t^2 + 1)*x^4 + (4*t + 2)*x^3 + (4*t + 1)*x^2
         + (t^2 + 3*t + 3)*x + 3*t^2 + 2*t + 2

  random_irreducible(degree=2, monic=True, *args, **kwds)

    Return a random irreducible Ore polynomial.

    Warning

    Elements of this Ore polynomial ring need to have a method is_irreducible(). Currently, this method is implemented only when the base ring is a finite field.

    INPUT:

    - `degree` – integer with degree (default: 2) or a tuple of integers with minimum and maximum degrees

    - `monic` – if `True`, returns a monic Ore polynomial (default: `True`)

    - `*args`, `**kwds` – passed in to the `random_element` method for the base ring

    EXAMPLES:

    Sage

        sage: k.<t> = GF(5^3)
        sage: Frob = k.frobenius_endomorphism()
        sage: S.<x> = k['x',Frob]
        sage: A = S.random_irreducible()
        sage: A.is_irreducible()
        True
        sage: B = S.random_irreducible(degree=3, monic=False)
        sage: B.is_irreducible()
        True

    Python

        >>> from sage.all import *
        >>> k = GF(Integer(5)**Integer(3), names=('t',)); (t,) = k._first_ngens(1)
        >>> Frob = k.frobenius_endomorphism()
        >>> S = k['x',Frob]; (x,) = S._first_ngens(1)
        >>> A = S.random_irreducible()
        >>> A.is_irreducible()
        True
        >>> B = S.random_irreducible(degree=Integer(3), monic=False)
        >>> B.is_irreducible()
        True

  twisting_derivation()

    Return the twisting derivation defining this Ore polynomial ring or `None` if this Ore polynomial ring is not twisted by a derivation.

    EXAMPLES:

    Sage

        sage: R.<t> = QQ[]
        sage: der = R.derivation(); der
        d/dt
        sage: A.<d> = R['d', der]
        sage: A.twisting_derivation()
        d/dt

        sage: k.<a> = GF(5^3)
        sage: Frob = k.frobenius_endomorphism()
        sage: S.<x> = k['x', Frob]
        sage: S.twisting_derivation()

    Python

        >>> from sage.all import *
        >>> R = QQ['t']; (t,) = R._first_ngens(1)
        >>> der = R.derivation(); der
        d/dt
        >>> A = R['d', der]; (d,) = A._first_ngens(1)
        >>> A.twisting_derivation()
        d/dt

        >>> k = GF(Integer(5)**Integer(3), names=('a',)); (a,) = k._first_ngens(1)
        >>> Frob = k.frobenius_endomorphism()
        >>> S = k['x', Frob]; (x,) = S._first_ngens(1)
        >>> S.twisting_derivation()

    See also

    `twisting_morphism()`

  twisting_morphism(n=1)

    Return the twisting endomorphism defining this Ore polynomial ring iterated `n` times or `None` if this Ore polynomial ring is not twisted by an endomorphism.

    INPUT:

    - `n` – integer (default: 1)

    EXAMPLES:

    Sage

        sage: R.<t> = QQ[]
        sage: sigma = R.hom([t+1])
        sage: S.<x> = R['x', sigma]
        sage: S.twisting_morphism()
        Ring endomorphism of Univariate Polynomial Ring in t over Rational Field
          Defn: t |--> t + 1
        sage: S.twisting_morphism() == sigma
        True
        sage: S.twisting_morphism(10)
        Ring endomorphism of Univariate Polynomial Ring in t over Rational Field
          Defn: t |--> t + 10

    Python

        >>> from sage.all import *
        >>> R = QQ['t']; (t,) = R._first_ngens(1)
        >>> sigma = R.hom([t+Integer(1)])
        >>> S = R['x', sigma]; (x,) = S._first_ngens(1)
        >>> S.twisting_morphism()
        Ring endomorphism of Univariate Polynomial Ring in t over Rational Field
          Defn: t |--> t + 1
        >>> S.twisting_morphism() == sigma
        True
        >>> S.twisting_morphism(Integer(10))
        Ring endomorphism of Univariate Polynomial Ring in t over Rational Field
          Defn: t |--> t + 10

    If `n` in negative, Sage tries to compute the inverse of the twisting morphism:

    Sage

        sage: k.<a> = GF(5^3)
        sage: Frob = k.frobenius_endomorphism()
        sage: T.<y> = k['y',Frob]
        sage: T.twisting_morphism(-1)
        Frobenius endomorphism a |--> a^(5^2) on Finite Field in a of size 5^3

    [Python]

        >>> from sage.all import *
        >>> k = GF(Integer(5)**Integer(3), names=('a',)); (a,) = k._first_ngens(1)
        >>> Frob = k.frobenius_endomorphism()
        >>> T = k['y',Frob]; (y,) = T._first_ngens(1)
        >>> T.twisting_morphism(-Integer(1))
        Frobenius endomorphism a |--> a^(5^2) on Finite Field in a of size 5^3

    Sometimes it fails, even if the twisting morphism is actually invertible:

    Sage

        sage: K = R.fraction_field()
        sage: phi = K.hom([(t+1)/(t-1)])
        sage: T.<y> = K['y', phi]
        sage: T.twisting_morphism(-1)
        Traceback (most recent call last):
        ...
        NotImplementedError: inverse not implemented for morphisms of
        Fraction Field of Univariate Polynomial Ring in t over Rational Field

    Python

        >>> from sage.all import *
        >>> K = R.fraction_field()
        >>> phi = K.hom([(t+Integer(1))/(t-Integer(1))])
        >>> T = K['y', phi]; (y,) = T._first_ngens(1)
        >>> T.twisting_morphism(-Integer(1))
        Traceback (most recent call last):
        ...
        NotImplementedError: inverse not implemented for morphisms of
        Fraction Field of Univariate Polynomial Ring in t over Rational Field

    When the Ore polynomial ring is only twisted by a derivation, this method returns nothing:

    Sage

        sage: der = R.derivation()
        sage: A.<d> = R['x', der]
        sage: A
        Ore Polynomial Ring in x over Univariate Polynomial Ring in t
         over Rational Field twisted by d/dt
        sage: A.twisting_morphism()

    [Python]

        >>> from sage.all import *
        >>> der = R.derivation()
        >>> A = R['x', der]; (d,) = A._first_ngens(1)
        >>> A
        Ore Polynomial Ring in x over Univariate Polynomial Ring in t
         over Rational Field twisted by d/dt
        >>> A.twisting_morphism()

    Here is an example where the twisting morphism is automatically inferred from the derivation:

    Sage

        sage: k.<a> = GF(5^3)
        sage: Frob = k.frobenius_endomorphism()
        sage: der = k.derivation(1, twist=Frob)
        sage: der
        [a |--> a^5] - id
        sage: S.<x> = k['x', der]
        sage: S.twisting_morphism()
        Frobenius endomorphism a |--> a^5 on Finite Field in a of size 5^3

    Python

        >>> from sage.all import *
        >>> k = GF(Integer(5)**Integer(3), names=('a',)); (a,) = k._first_ngens(1)
        >>> Frob = k.frobenius_endomorphism()
        >>> der = k.derivation(Integer(1), twist=Frob)
        >>> der
        [a |--> a^5] - id
        >>> S = k['x', der]; (x,) = S._first_ngens(1)
        >>> S.twisting_morphism()
        Frobenius endomorphism a |--> a^5 on Finite Field in a of size 5^3

    See also

    `twisting_derivation()`