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:
sage.structure.unique_representation.UniqueRepresentation
,sage.rings.ring.Algebra
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: k.<a> = GF(5^3) sage: Frob = k.frobenius_endomorphism() sage: S = OrePolynomialRing(k, Frob, 'x') sage: 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: T.<x> = k['x', Frob] sage: 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] 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 True
We are now ready to carry on computations in the Ore ring:
sage: x*a (2*a^2 + 4*a + 4)*x sage: Frob(a)*x (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: R.<t> = QQ[] sage: der = R.derivation(); der d/dt sage: A = OrePolynomialRing(R, der, 'd') sage: 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] sage: A is B True
and computations can be carried out:
sage: d*t 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: 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] sage: 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] 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: 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] False
Similarly, varying the twisting morphisms yields to different Ore rings (expect when the morphism coincide):
sage: S is k['x', Frob^2] False sage: S is k['x', Frob^3] False sage: S is k['x', Frob^4] True
Todo
Sparse Ore Polynomial Ring
Multivariate Ore Polynomial Ring
- 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: 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: 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: 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: y is x True sage: S.gen(0) x
This is also known as the parameter:
sage: S.parameter() is S.gen() True
- 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, i.e. if the twisting morphism is the identity and the twisting derivation vanishes.EXAMPLES:
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: 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: 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: 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, which 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: y is x True sage: S.gen(0) x
This is also known as the parameter:
sage: S.parameter() is S.gen() True
- random_element(degree=2, monic=False, *args, **kwds)¶
Return a random Ore polynomial in this ring.
INPUT:
degree
– (default: 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: 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: p = S.random_element(degree=5) # random (t^2 + 3*t)*x^4 + (4*t + 4)*x^3 + (4*t^2 + 4*t)*x^2 + (2*t^2 + 1)*x + 3 sage: p.degree() <= 5 True
When
monic
isFalse
, the returned Ore polynomial may have a degree less thandegree
(it happens when the random leading coefficient is zero). However, ifmonic
isTrue
, this cannot happen:sage: p = S.random_element(degree=4, monic=True) sage: p.leading_coefficient() == S.base_ring().one() True sage: p.degree() == 4 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 (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
If the first tuple element is greater than the second, a
ValueError
is raised:sage: S.random_element(degree=(5,4)) Traceback (most recent call last): ... ValueError: first degree argument must be less or equal to the second
- 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: k.<t> = GF(5^3) sage: Frob = k.frobenius_endomorphism() sage: S.<x> = k['x',Frob] sage: A = S.random_irreducible(); A x^2 + (4*t^2 + 3*t + 4)*x + 4*t^2 + t sage: A.is_irreducible() True sage: B = S.random_irreducible(degree=3,monic=False); B # random (4*t + 1)*x^3 + (t^2 + 3*t + 3)*x^2 + (3*t^2 + 2*t + 2)*x + 3*t^2 + 3*t + 1 sage: B.is_irreducible() True
- twist_map(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.This method is deprecated. Use
twisting_morphism()
instead.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.twist_map() ... DeprecationWarning: The method twist_map is deprecated; use twisting_morphism (same semantic) instead See https://trac.sagemath.org/29629 for details. Ring endomorphism of Univariate Polynomial Ring in t over Rational Field Defn: t |--> t + 1
- 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: 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: 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: 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