Fraction field elements of Ore polynomial rings

AUTHOR:

  • Xavier Caruso (2020-05)

class sage.rings.polynomial.ore_function_element.ConstantOreFunctionSection[source]

Bases: Map

Representation of the canonical homomorphism from the constants of a Ore function field to the base field.

This class is needed by the coercion system.

EXAMPLES:

sage: # needs sage.rings.finite_rings
sage: from sage.rings.polynomial.ore_polynomial_element import ConstantOrePolynomialSection
sage: k.<a> = GF(5^3)
sage: Frob = k.frobenius_endomorphism()
sage: S.<x> = k['x', Frob]
sage: K = S.fraction_field()
sage: iota = K.coerce_map_from(k)
sage: sigma = iota.section(); sigma
Generic map:
  From: Ore Function Field in x over Finite Field in a of size 5^3
        twisted by a |--> a^5
  To:   Finite Field in a of size 5^3
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> from sage.rings.polynomial.ore_polynomial_element import ConstantOrePolynomialSection
>>> 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()
>>> iota = K.coerce_map_from(k)
>>> sigma = iota.section(); sigma
Generic map:
  From: Ore Function Field in x over Finite Field in a of size 5^3
        twisted by a |--> a^5
  To:   Finite Field in a of size 5^3
# needs sage.rings.finite_rings
from sage.rings.polynomial.ore_polynomial_element import ConstantOrePolynomialSection
k.<a> = GF(5^3)
Frob = k.frobenius_endomorphism()
S.<x> = k['x', Frob]
K = S.fraction_field()
iota = K.coerce_map_from(k)
sigma = iota.section(); sigma
class sage.rings.polynomial.ore_function_element.OreFunction(parent, numerator, denominator=None, simplify=True)[source]

Bases: AlgebraElement

An element in a Ore function field.

hilbert_shift(s, var=None)[source]

Return this Ore function with variable shifted by \(s\), i.e. if this Ore function is \(f(x)\), return \(f(x+s)\).

INPUT:

  • s – an element in the base ring

  • var – string; the variable name

EXAMPLES:

sage: R.<t> = GF(7)[]
sage: der = R.derivation()
sage: A.<d> = R['d', der]
sage: K = A.fraction_field()

sage: f = 1 / (d-t)
sage: f.hilbert_shift(t)
d^(-1)
>>> from sage.all import *
>>> R = GF(Integer(7))['t']; (t,) = R._first_ngens(1)
>>> der = R.derivation()
>>> A = R['d', der]; (d,) = A._first_ngens(1)
>>> K = A.fraction_field()

>>> f = Integer(1) / (d-t)
>>> f.hilbert_shift(t)
d^(-1)
R.<t> = GF(7)[]
der = R.derivation()
A.<d> = R['d', der]
K = A.fraction_field()
f = 1 / (d-t)
f.hilbert_shift(t)

One can specify another variable name:

sage: f.hilbert_shift(t, var='x')
x^(-1)
>>> from sage.all import *
>>> f.hilbert_shift(t, var='x')
x^(-1)
f.hilbert_shift(t, var='x')

When the twisting morphism is not trivial, the output lies in a different Ore polynomial ring:

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()
sage: f = (x-a)^(-2)
sage: g = f.hilbert_shift(a); g
x^(-2)
sage: g.parent()
Ore Function Field in x over Finite Field in a of size 5^3
 twisted by a |--> a^5 and a*([a |--> a^5] - id)
sage: g.parent() is S
False
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> 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()
>>> f = (x-a)**(-Integer(2))
>>> g = f.hilbert_shift(a); g
x^(-2)
>>> g.parent()
Ore Function Field in x over Finite Field in a of size 5^3
 twisted by a |--> a^5 and a*([a |--> a^5] - id)
>>> g.parent() is S
False
# needs sage.rings.finite_rings
k.<a> = GF(5^3)
Frob = k.frobenius_endomorphism()
S.<x> = k['x', Frob]
K = S.fraction_field()
f = (x-a)^(-2)
g = f.hilbert_shift(a); g
g.parent()
g.parent() is S

This behavior ensures that the Hilbert shift by a fixed element defines a homomorphism of fields:

sage: # needs sage.rings.finite_rings
sage: U = K.random_element(degree=5)
sage: V = K.random_element(degree=5)
sage: s = k.random_element()
sage: (U+V).hilbert_shift(s) == U.hilbert_shift(s) + V.hilbert_shift(s)
True
sage: (U*V).hilbert_shift(s) == U.hilbert_shift(s) * V.hilbert_shift(s)
True
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> U = K.random_element(degree=Integer(5))
>>> V = K.random_element(degree=Integer(5))
>>> s = k.random_element()
>>> (U+V).hilbert_shift(s) == U.hilbert_shift(s) + V.hilbert_shift(s)
True
>>> (U*V).hilbert_shift(s) == U.hilbert_shift(s) * V.hilbert_shift(s)
True
# needs sage.rings.finite_rings
U = K.random_element(degree=5)
V = K.random_element(degree=5)
s = k.random_element()
(U+V).hilbert_shift(s) == U.hilbert_shift(s) + V.hilbert_shift(s)
(U*V).hilbert_shift(s) == U.hilbert_shift(s) * V.hilbert_shift(s)
is_zero()[source]

Return True if this element is equal to zero.

EXAMPLES:

sage: R.<t> = GF(3)[]
sage: der = R.derivation()
sage: A.<d> = R['x', der]
sage: f = t/d
sage: f.is_zero()
False
sage: (f-f).is_zero()
True
>>> from sage.all import *
>>> R = GF(Integer(3))['t']; (t,) = R._first_ngens(1)
>>> der = R.derivation()
>>> A = R['x', der]; (d,) = A._first_ngens(1)
>>> f = t/d
>>> f.is_zero()
False
>>> (f-f).is_zero()
True
R.<t> = GF(3)[]
der = R.derivation()
A.<d> = R['x', der]
f = t/d
f.is_zero()
(f-f).is_zero()
left_denominator()[source]

Return \(s\) if this element reads \(s^{-1} t\).

WARNING:

When the twisting morphism is bijective, there is a unique irreducible fraction of the form \(s^{-1} t\) representing this element. Here irreducible means that \(s\) and \(t\) have no nontrivial common left divisor. Under this additional assumption, this method always returns this distinguished denominator \(s\).

On the contrary, when the twisting morphism is not bijective, this method returns the denominator of some fraction representing the input element. However, the software guarantees that the method right_numerator() outputs the numerator of the same fraction.

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 = x + a
sage: t = x^2 + a*x + a^2
sage: f = s^(-1) * t
sage: f.left_denominator()
x + a
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> 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 = x + a
>>> t = x**Integer(2) + a*x + a**Integer(2)
>>> f = s**(-Integer(1)) * t
>>> f.left_denominator()
x + a
# needs sage.rings.finite_rings
k.<a> = GF(5^3)
Frob = k.frobenius_endomorphism()
S.<x> = k['x', Frob]
s = x + a
t = x^2 + a*x + a^2
f = s^(-1) * t
f.left_denominator()

In the example below, a simplification occurs:

sage: # needs sage.rings.finite_rings
sage: u = S.random_element(degree=2)
sage: g = (u*s)^(-1) * (u*t)
sage: g.left_denominator()
x + a
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> u = S.random_element(degree=Integer(2))
>>> g = (u*s)**(-Integer(1)) * (u*t)
>>> g.left_denominator()
x + a
# needs sage.rings.finite_rings
u = S.random_element(degree=2)
g = (u*s)^(-1) * (u*t)
g.left_denominator()

When the twisting morphism is not invertible, simplifications do not occur in general:

sage: R.<z> = GF(11)[]
sage: sigma = R.hom([z^2])
sage: S.<x> = R['x', sigma]
sage: s = (x + z)^2
sage: t = (x + z) * (x^2 + z^2)
sage: f = s^(-1) * t                                                        # needs sage.rings.function_field
sage: f.left_denominator()                                                  # needs sage.rings.function_field
x^2 + (z^2 + z)*x + z^2
>>> from sage.all import *
>>> R = GF(Integer(11))['z']; (z,) = R._first_ngens(1)
>>> sigma = R.hom([z**Integer(2)])
>>> S = R['x', sigma]; (x,) = S._first_ngens(1)
>>> s = (x + z)**Integer(2)
>>> t = (x + z) * (x**Integer(2) + z**Integer(2))
>>> f = s**(-Integer(1)) * t                                                        # needs sage.rings.function_field
>>> f.left_denominator()                                                  # needs sage.rings.function_field
x^2 + (z^2 + z)*x + z^2
R.<z> = GF(11)[]
sigma = R.hom([z^2])
S.<x> = R['x', sigma]
s = (x + z)^2
t = (x + z) * (x^2 + z^2)
f = s^(-1) * t                                                        # needs sage.rings.function_field
f.left_denominator()                                                  # needs sage.rings.function_field

However, the following always holds true:

sage: f == f.left_denominator()^(-1) * f.right_numerator()                  # needs sage.rings.function_field
True
>>> from sage.all import *
>>> f == f.left_denominator()**(-Integer(1)) * f.right_numerator()                  # needs sage.rings.function_field
True
f == f.left_denominator()^(-1) * f.right_numerator()                  # needs sage.rings.function_field
left_numerator()[source]

Return \(t\) if this element reads \(t s^{-1}\).

WARNING:

When the twisting morphism is bijective, there is a unique irreducible fraction of the form \(t s^{-1}\) representing this element. Here irreducible means that \(s\) and \(t\) have no nontrivial common right divisor. Under this additional assumption, this method always returns this distinguished numerator \(t\).

On the contrary, when the twisting morphism is not bijective, the existence of the writing \(t s^{-1}\) is not guaranteed in general. In this case, this method raises an error.

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 = x + a
sage: t = x^2 + a*x + a^2
sage: f = t/s
sage: f.left_numerator()
x^2 + a*x + a^2
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> 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 = x + a
>>> t = x**Integer(2) + a*x + a**Integer(2)
>>> f = t/s
>>> f.left_numerator()
x^2 + a*x + a^2
# needs sage.rings.finite_rings
k.<a> = GF(5^3)
Frob = k.frobenius_endomorphism()
S.<x> = k['x', Frob]
s = x + a
t = x^2 + a*x + a^2
f = t/s
f.left_numerator()

In the example below, a simplification occurs:

sage: # needs sage.rings.finite_rings
sage: u = S.random_element(degree=2)
sage: g = (t*u) / (s*u)
sage: g.left_numerator()
x^2 + a*x + a^2
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> u = S.random_element(degree=Integer(2))
>>> g = (t*u) / (s*u)
>>> g.left_numerator()
x^2 + a*x + a^2
# needs sage.rings.finite_rings
u = S.random_element(degree=2)
g = (t*u) / (s*u)
g.left_numerator()
right_denominator()[source]

Return \(s\) if this element reads \(t s^{-1}\).

WARNING:

When the twisting morphism is bijective, there is a unique irreducible fraction of the form \(t s^{-1}\) representing this element. Here irreducible means that \(s\) and \(t\) have no nontrivial common right divisor. Under this additional assumption, this method always returns this distinguished denominator \(s\).

On the contrary, when the twisting morphism is not bijective, the existence of the writing \(t s^{-1}\) is not guaranteed in general. In this case, this method raises an error.

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 = x + a
sage: t = x^2 + a*x + a^2
sage: f = t/s
sage: f.right_denominator()
x + a
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> 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 = x + a
>>> t = x**Integer(2) + a*x + a**Integer(2)
>>> f = t/s
>>> f.right_denominator()
x + a
# needs sage.rings.finite_rings
k.<a> = GF(5^3)
Frob = k.frobenius_endomorphism()
S.<x> = k['x', Frob]
s = x + a
t = x^2 + a*x + a^2
f = t/s
f.right_denominator()

In the example below, a simplification occurs:

sage: # needs sage.rings.finite_rings
sage: u = S.random_element(degree=2)
sage: g = (t*u) / (s*u)
sage: g.right_denominator()
x + a
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> u = S.random_element(degree=Integer(2))
>>> g = (t*u) / (s*u)
>>> g.right_denominator()
x + a
# needs sage.rings.finite_rings
u = S.random_element(degree=2)
g = (t*u) / (s*u)
g.right_denominator()
right_numerator()[source]

Return \(t\) if this element reads \(s^{-1} t\).

WARNING:

When the twisting morphism is bijective, there is a unique irreducible fraction of the form \(s^{-1} t\) representing this element. Here irreducible means that \(s\) and \(t\) have no nontrivial common left divisor. Under this additional assumption, this method always returns this distinguished numerator \(t\).

On the contrary, when the twisting morphism is not bijective, this method returns the numerator of some fraction representing the input element. However, the software guarantees that the method left_denominator() outputs the numerator of the same fraction.

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 = x + a
sage: t = x^2 + a*x + a^2
sage: f = s^(-1) * t
sage: f.right_numerator()
x^2 + a*x + a^2
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> 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 = x + a
>>> t = x**Integer(2) + a*x + a**Integer(2)
>>> f = s**(-Integer(1)) * t
>>> f.right_numerator()
x^2 + a*x + a^2
# needs sage.rings.finite_rings
k.<a> = GF(5^3)
Frob = k.frobenius_endomorphism()
S.<x> = k['x', Frob]
s = x + a
t = x^2 + a*x + a^2
f = s^(-1) * t
f.right_numerator()

In the example below, a simplification occurs:

sage: # needs sage.rings.finite_rings
sage: u = S.random_element(degree=2)
sage: g = (u*s)^(-1) * (u*t)
sage: g.right_numerator()
x^2 + a*x + a^2
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> u = S.random_element(degree=Integer(2))
>>> g = (u*s)**(-Integer(1)) * (u*t)
>>> g.right_numerator()
x^2 + a*x + a^2
# needs sage.rings.finite_rings
u = S.random_element(degree=2)
g = (u*s)^(-1) * (u*t)
g.right_numerator()
class sage.rings.polynomial.ore_function_element.OreFunctionBaseringInjection(domain, codomain)[source]

Bases: Morphism

Representation of the canonical homomorphism from a field \(k\) into a Ore function field over \(k\).

This class is needed by the coercion system.

an_element()[source]

Return an element of the codomain of the ring homomorphism.

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: K = S.fraction_field()
sage: m = K.coerce_map_from(k)
sage: m.an_element()
x
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> 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)
>>> K = S.fraction_field()
>>> m = K.coerce_map_from(k)
>>> m.an_element()
x
# needs sage.rings.finite_rings
k.<t> = GF(5^3)
Frob = k.frobenius_endomorphism()
S.<x> = k['x',Frob]
K = S.fraction_field()
m = K.coerce_map_from(k)
m.an_element()
section()[source]

Return the canonical homomorphism from the constants of a Ore function filed to its base field.

class sage.rings.polynomial.ore_function_element.OreFunction_with_large_center(parent, numerator, denominator=None, simplify=True)[source]

Bases: OreFunction

A special class for elements of Ore function fields whose center has finite index.

reduced_norm(var=None)[source]

Return the reduced norm of this Ore function.

INPUT:

  • var – string or None (default: None); the name of the central variable

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: K = S.fraction_field()
sage: a = (x + t) / (x^2 + t^2)
sage: N = a.reduced_norm(); N
(z + 2)/(z^2 + 4)
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> 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)
>>> K = S.fraction_field()
>>> a = (x + t) / (x**Integer(2) + t**Integer(2))
>>> N = a.reduced_norm(); N
(z + 2)/(z^2 + 4)
# needs sage.rings.finite_rings
k.<t> = GF(5^3)
Frob = k.frobenius_endomorphism()
S.<x> = k['x', Frob]
K = S.fraction_field()
a = (x + t) / (x^2 + t^2)
N = a.reduced_norm(); N

The reduced norm lies in the center of \(S\), which is the fraction field of a univariate polynomial ring in the variable \(z = x^3\) over \(GF(5)\).

sage: # needs sage.rings.finite_rings
sage: N.parent()
Fraction Field of Univariate Polynomial Ring in z over Finite Field of size 5
sage: N.parent() is K.center()
True
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> N.parent()
Fraction Field of Univariate Polynomial Ring in z over Finite Field of size 5
>>> N.parent() is K.center()
True
# needs sage.rings.finite_rings
N.parent()
N.parent() is K.center()

We can use explicit conversion to view N as a skew polynomial:

sage: K(N)                                                                  # needs sage.rings.finite_rings
(x^6 + 4)^(-1) * (x^3 + 2)
>>> from sage.all import *
>>> K(N)                                                                  # needs sage.rings.finite_rings
(x^6 + 4)^(-1) * (x^3 + 2)
K(N)                                                                  # needs sage.rings.finite_rings

By default, the name of the central variable is usually z (see sage.rings.polynomial.skew_polynomial_ring.SkewPolynomiaRing_finite_order.center() for more details about this). However, the user can specify a different variable name if desired:

sage: a.reduced_norm(var='u')                                               # needs sage.rings.finite_rings
(u + 2)/(u^2 + 4)
>>> from sage.all import *
>>> a.reduced_norm(var='u')                                               # needs sage.rings.finite_rings
(u + 2)/(u^2 + 4)
a.reduced_norm(var='u')                                               # needs sage.rings.finite_rings
reduced_trace(var=None)[source]

Return the reduced trace of this element.

INPUT:

  • var – string or None (default: None); the name of the central variable

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: K = S.fraction_field()
sage: a = 1 / (x^2 + t)
sage: tr = a.reduced_trace(); tr
3/(z^2 + 2)
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> 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)
>>> K = S.fraction_field()
>>> a = Integer(1) / (x**Integer(2) + t)
>>> tr = a.reduced_trace(); tr
3/(z^2 + 2)
# needs sage.rings.finite_rings
k.<t> = GF(5^3)
Frob = k.frobenius_endomorphism()
S.<x> = k['x', Frob]
K = S.fraction_field()
a = 1 / (x^2 + t)
tr = a.reduced_trace(); tr

The reduced trace lies in the center of \(S\), which is the fraction field of a univariate polynomial ring in the variable \(z = x^3\) over \(GF(5)\):

sage: # needs sage.rings.finite_rings
sage: tr.parent()
Fraction Field of Univariate Polynomial Ring in z over Finite Field of size 5
sage: tr.parent() is K.center()
True
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> tr.parent()
Fraction Field of Univariate Polynomial Ring in z over Finite Field of size 5
>>> tr.parent() is K.center()
True
# needs sage.rings.finite_rings
tr.parent()
tr.parent() is K.center()

We can use explicit conversion to view tr as a Ore function:

sage: K(tr)                                                                 # needs sage.rings.finite_rings
(x^6 + 2)^(-1) * 3
>>> from sage.all import *
>>> K(tr)                                                                 # needs sage.rings.finite_rings
(x^6 + 2)^(-1) * 3
K(tr)                                                                 # needs sage.rings.finite_rings

By default, the name of the central variable is usually z (see sage.rings.polynomial.skew_polynomial_ring.OreFunctionField_with_large_center.center() for more details about this). However, the user can specify a different variable name if desired:

sage: a.reduced_trace(var='u')                                              # needs sage.rings.finite_rings
3/(u^2 + 2)
>>> from sage.all import *
>>> a.reduced_trace(var='u')                                              # needs sage.rings.finite_rings
3/(u^2 + 2)
a.reduced_trace(var='u')                                              # needs sage.rings.finite_rings