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 ringtwisting_map
– either an endomorphism of the base ring, or a (twisted) derivation of itnames
– a string or a list of stringssparse
– a 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: # needs sage.rings.finite_rings 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
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: # needs sage.rings.finite_rings 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
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: 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
Note moreover that, similarly to the classical case, using the brackets notation also sets the variable:
sage: x.parent() is S # needs sage.rings.finite_rings True
We are now ready to carry on computations in the Ore ring:
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
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: # needs sage.rings.finite_rings 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
Again, the brackets notation is available:
sage: B.<d> = R['d', der] # needs sage.rings.finite_rings sage: A is B # needs sage.rings.finite_rings True
and computations can be carried out:
sage: 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: # needs sage.rings.padics 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)
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: 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: 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
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: 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
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: # needs sage.rings.finite_rings 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
Rings with different variables names are different:
sage: 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: 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
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 asself
.INPUT:
var
– a string representing the name of the new variable
EXAMPLES:
sage: # needs sage.rings.finite_rings 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
- characteristic()#
Return the characteristic of the base ring of
self
.EXAMPLES:
sage: R.<t> = QQ[] sage: sigma = R.hom([t+1]) sage: R['x',sigma].characteristic() 0 sage: # needs sage.rings.finite_rings sage: k.<u> = GF(5^3) sage: Frob = k.frobenius_endomorphism() sage: k['y',Frob].characteristic() 5
- fraction_field()#
Return the fraction field of this skew ring.
EXAMPLES:
sage: # needs sage.rings.finite_rings 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
Below is another example with differentiel operators:
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
- 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: 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
This is also known as the parameter:
sage: S.parameter() is S.gen() True
- gens()#
Return the tuple of generators of
self
.EXAMPLES:
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,)
- gens_dict()#
Return a {name: variable} dictionary of the generators of this Ore polynomial ring.
EXAMPLES:
sage: R.<t> = ZZ[] sage: sigma = R.hom([t+1]) sage: S.<x> = SkewPolynomialRing(R,sigma) sage: S.gens_dict() {'x': x}
- is_commutative()#
Return
True
if this Ore polynomial ring is commutative.This holds if the twisting morphism is the identity and the twisting derivation vanishes.
EXAMPLES:
sage: # needs sage.rings.finite_rings sage: k.<a> = GF(5^3) sage: Frob = k.frobenius_endomorphism() sage: S.<x> = k['x', Frob] sage: S.is_commutative() False sage: T.<y> = k['y', Frob^3] sage: T.is_commutative() True sage: R.<t> = GF(5)[] sage: der = R.derivation() sage: A.<d> = R['d', der] sage: A.is_commutative() False sage: B.<b> = R['b', 5*der] sage: B.is_commutative() True
- 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: # needs sage.rings.finite_rings 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
- is_field(proof=False)#
Return always
False
since Ore polynomial rings are never fields.EXAMPLES:
sage: # needs sage.rings.finite_rings sage: k.<a> = GF(5^3) sage: Frob = k.frobenius_endomorphism() sage: S.<x> = k['x', Frob] sage: S.is_field() False
- is_finite()#
Return
False
since Ore polynomial rings are not finite (unless the base ring is \(0\)).EXAMPLES:
sage: # needs sage.rings.finite_rings 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
- 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: R.<t> = RR[] sage: sigma = R.hom([t+1]) sage: S.<x> = R['x',sigma] sage: S.is_sparse() False
- ngens()#
Return the number of generators of this Ore polynomial ring.
This is \(1\).
EXAMPLES:
sage: R.<t> = RR[] sage: sigma = R.hom([t+1]) sage: S.<x> = R['x',sigma] sage: S.ngens() 1
- parameter(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: 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
This is also known as the parameter:
sage: S.parameter() is S.gen() True
- 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 degreesmonic
– (default:False
) ifTrue
, return a monic Ore polynomial*args, **kwds
– passed on to therandom_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: # needs sage.rings.finite_rings 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
Use
degree
to obtain polynomials of higher degree:sage: # needs sage.rings.finite_rings 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
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: 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
- 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 degreesmonic
- ifTrue
, returns a monic Ore polynomial (default:True
)*args, **kwds
- passed in to therandom_element
method for the base ring
EXAMPLES:
sage: # needs sage.rings.finite_rings 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
- 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: R.<t> = QQ[] sage: der = R.derivation(); der d/dt sage: A.<d> = R['d', der] sage: A.twisting_derivation() d/dt sage: # needs sage.rings.finite_rings sage: k.<a> = GF(5^3) sage: Frob = k.frobenius_endomorphism() sage: S.<x> = k['x', Frob] sage: S.twisting_derivation()
See also
- twisting_morphism(n=1)#
Return the twisting endomorphism defining this Ore polynomial ring iterated
n
times orNone
if this Ore polynomial ring is not twisted by an endomorphism.INPUT:
n
- an integer (default: 1)
EXAMPLES:
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
If
n
in negative, Sage tries to compute the inverse of the twisting morphism:sage: # needs sage.rings.finite_rings 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
Sometimes it fails, even if the twisting morphism is actually invertible:
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
When the Ore polynomial ring is only twisted by a derivation, this method returns nothing:
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()
Here is an example where the twisting morphism is automatically inferred from the derivation:
sage: # needs sage.rings.finite_rings 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
See also