Morphisms between Ore modules¶
Let
By definition, a Ore module is a module over sage.modules.ore_module
for more details.
A morphism of Ore modules is a
Construction of morphisms
There are several ways for creating Ore modules morphisms in SageMath.
First of all, one can use the method sage.modules.ore_module.OreModule.hom()
,
passing to it the matrix (in the canonical bases) of the morphism
we want to build:
sage: K.<z> = GF(5^3)
sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism())
sage: M.<e0,e1> = S.quotient_module(X^2 + X + z)
sage: mat = matrix(2, 2, [z, 3*z^2 + z + 2,
....: z + 1, 4*z + 4])
sage: f = M.hom(mat)
sage: f
Ore module endomorphism of Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5
>>> from sage.all import *
>>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1)
>>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1)
>>> M = S.quotient_module(X**Integer(2) + X + z, names=('e0', 'e1',)); (e0, e1,) = M._first_ngens(2)
>>> mat = matrix(Integer(2), Integer(2), [z, Integer(3)*z**Integer(2) + z + Integer(2),
... z + Integer(1), Integer(4)*z + Integer(4)])
>>> f = M.hom(mat)
>>> f
Ore module endomorphism of Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) M.<e0,e1> = S.quotient_module(X^2 + X + z) mat = matrix(2, 2, [z, 3*z^2 + z + 2, z + 1, 4*z + 4]) f = M.hom(mat) f
Clearly, this method is not optimal: typing all the entries of the defining matrix is long and a potential source of errors.
Instead, one can use a dictionary encoding the values taken by the
morphism on a set of generators; the morphism is then automatically
prolonged by
sage: g = M.hom({e0: X^3*e0})
sage: g
Ore module endomorphism of Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5
>>> from sage.all import *
>>> g = M.hom({e0: X**Integer(3)*e0})
>>> g
Ore module endomorphism of Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5
g = M.hom({e0: X^3*e0}) g
One can then recover the matrix by using the method
sage.modules.ore_module_morphism.OreModuleMorphism.matrix()
:
sage: g.matrix()
[ z 3*z^2 + z + 2]
[ z + 1 4*z + 4]
>>> from sage.all import *
>>> g.matrix()
[ z 3*z^2 + z + 2]
[ z + 1 4*z + 4]
g.matrix()
Alternatively, one can use the method
sage.modules.ore_module.OreModule.multiplication_map()
:
sage: h = M.multiplication_map(X^3)
sage: h
Ore module endomorphism of Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5
sage: g == h
True
>>> from sage.all import *
>>> h = M.multiplication_map(X**Integer(3))
>>> h
Ore module endomorphism of Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5
>>> g == h
True
h = M.multiplication_map(X^3) h g == h
Of course, this method also accepts values in the base ring:
sage: h = M.multiplication_map(2)
sage: h
Ore module endomorphism of Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5
sage: h.matrix()
[2 0]
[0 2]
>>> from sage.all import *
>>> h = M.multiplication_map(Integer(2))
>>> h
Ore module endomorphism of Ore module <e0, e1> over Finite Field in z of size 5^3 twisted by z |--> z^5
>>> h.matrix()
[2 0]
[0 2]
h = M.multiplication_map(2) h h.matrix()
Be careful that scalar multiplications do not always properly define a morphism of Ore modules:
sage: M.multiplication_map(z)
Traceback (most recent call last):
...
ValueError: does not define a morphism of Ore modules
>>> from sage.all import *
>>> M.multiplication_map(z)
Traceback (most recent call last):
...
ValueError: does not define a morphism of Ore modules
M.multiplication_map(z)
SageMath provides methods to compute kernels, cokernels, images and coimages. In order to illustrate this, we will build the sequence
and check that it is exact. We first build the Ore modules:
sage: P = X^2 + z*X + 1
sage: Q = X^3 + z^2*X^2 + X + z
sage: U = S.quotient_module(P, names='u')
sage: U.inject_variables()
Defining u0, u1
sage: V = S.quotient_module(P*Q, names='v')
sage: V.inject_variables()
Defining v0, v1, v2, v3, v4
sage: W = S.quotient_module(Q, names='w')
sage: W.inject_variables()
Defining w0, w1, w2
>>> from sage.all import *
>>> P = X**Integer(2) + z*X + Integer(1)
>>> Q = X**Integer(3) + z**Integer(2)*X**Integer(2) + X + z
>>> U = S.quotient_module(P, names='u')
>>> U.inject_variables()
Defining u0, u1
>>> V = S.quotient_module(P*Q, names='v')
>>> V.inject_variables()
Defining v0, v1, v2, v3, v4
>>> W = S.quotient_module(Q, names='w')
>>> W.inject_variables()
Defining w0, w1, w2
P = X^2 + z*X + 1 Q = X^3 + z^2*X^2 + X + z U = S.quotient_module(P, names='u') U.inject_variables() V = S.quotient_module(P*Q, names='v') V.inject_variables() W = S.quotient_module(Q, names='w') W.inject_variables()
Next, we build the morphisms:
sage: f = U.hom({u0: Q*v0})
sage: g = V.hom({v0: w0})
>>> from sage.all import *
>>> f = U.hom({u0: Q*v0})
>>> g = V.hom({v0: w0})
f = U.hom({u0: Q*v0}) g = V.hom({v0: w0})
We can now check that
sage: f.kernel()
Ore module of rank 0 over Finite Field in z of size 5^3 twisted by z |--> z^5
>>> from sage.all import *
>>> f.kernel()
Ore module of rank 0 over Finite Field in z of size 5^3 twisted by z |--> z^5
f.kernel()
We see on the output that it has dimension sage.modules.ore_module.OreModule.is_zero()
:
sage: f.kernel().is_zero()
True
>>> from sage.all import *
>>> f.kernel().is_zero()
True
f.kernel().is_zero()
Actually, in our use case, one can, more simply, use the method
sage.modules.ore_module_morphism.OreModuleMorphism.is_injective()
:
sage: f.is_injective()
True
>>> from sage.all import *
>>> f.is_injective()
True
f.is_injective()
Similarly, one checks that
sage: g.is_surjective()
True
>>> from sage.all import *
>>> g.is_surjective()
True
g.is_surjective()
or equivalently:
sage: g.cokernel().is_zero()
True
>>> from sage.all import *
>>> g.cokernel().is_zero()
True
g.cokernel().is_zero()
Now, we need to check that the kernel of
sage: ker = g.kernel()
sage: im = f.image()
sage: ker == im
True
>>> from sage.all import *
>>> ker = g.kernel()
>>> im = f.image()
>>> ker == im
True
ker = g.kernel() im = f.image() ker == im
As a sanity check, one can also verity that the composite
sage: h = g * f
sage: h
Ore module morphism:
From: Ore module <u0, u1> over Finite Field in z of size 5^3 twisted by z |--> z^5
To: Ore module <w0, w1, w2> over Finite Field in z of size 5^3 twisted by z |--> z^5
sage: h.is_zero()
True
>>> from sage.all import *
>>> h = g * f
>>> h
Ore module morphism:
From: Ore module <u0, u1> over Finite Field in z of size 5^3 twisted by z |--> z^5
To: Ore module <w0, w1, w2> over Finite Field in z of size 5^3 twisted by z |--> z^5
>>> h.is_zero()
True
h = g * f h h.is_zero()
Let us now consider another morphism
sage: A = X + z
sage: B = X + z + 1
sage: P = X^2 + X + z
sage: U = S.quotient_module(B*P, names='u')
sage: U.inject_variables()
Defining u0, u1, u2
sage: V = S.quotient_module(P*A, names='v')
sage: V.inject_variables()
Defining v0, v1, v2
sage: f = U.hom({u0: A*v0})
sage: f
Ore module morphism:
From: Ore module <u0, u1, u2> over Finite Field in z of size 5^3 twisted by z |--> z^5
To: Ore module <v0, v1, v2> over Finite Field in z of size 5^3 twisted by z |--> z^5
>>> from sage.all import *
>>> A = X + z
>>> B = X + z + Integer(1)
>>> P = X**Integer(2) + X + z
>>> U = S.quotient_module(B*P, names='u')
>>> U.inject_variables()
Defining u0, u1, u2
>>> V = S.quotient_module(P*A, names='v')
>>> V.inject_variables()
Defining v0, v1, v2
>>> f = U.hom({u0: A*v0})
>>> f
Ore module morphism:
From: Ore module <u0, u1, u2> over Finite Field in z of size 5^3 twisted by z |--> z^5
To: Ore module <v0, v1, v2> over Finite Field in z of size 5^3 twisted by z |--> z^5
A = X + z B = X + z + 1 P = X^2 + X + z U = S.quotient_module(B*P, names='u') U.inject_variables() V = S.quotient_module(P*A, names='v') V.inject_variables() f = U.hom({u0: A*v0}) f
Now we compute the image and the coimage:
sage: I = f.image(names='im')
sage: I
Ore module <im0, im1> over Finite Field in z of size 5^3 twisted by z |--> z^5
sage: C = f.coimage(names='co')
sage: C
Ore module <co0, co1> over Finite Field in z of size 5^3 twisted by z |--> z^5
>>> from sage.all import *
>>> I = f.image(names='im')
>>> I
Ore module <im0, im1> over Finite Field in z of size 5^3 twisted by z |--> z^5
>>> C = f.coimage(names='co')
>>> C
Ore module <co0, co1> over Finite Field in z of size 5^3 twisted by z |--> z^5
I = f.image(names='im') I C = f.coimage(names='co') C
We can already check that the image and the coimage have the
same rank. We now want to construct the isomorphism between
them. For this, we first need to corestrict sage.modules.ore_module.OreSubmodule.morphism_corestriction()
of the Ore module:
sage: g = I.morphism_corestriction(f)
sage: g
Ore module morphism:
From: Ore module <u0, u1, u2> over Finite Field in z of size 5^3 twisted by z |--> z^5
To: Ore module <im0, im1> over Finite Field in z of size 5^3 twisted by z |--> z^5
>>> from sage.all import *
>>> g = I.morphism_corestriction(f)
>>> g
Ore module morphism:
From: Ore module <u0, u1, u2> over Finite Field in z of size 5^3 twisted by z |--> z^5
To: Ore module <im0, im1> over Finite Field in z of size 5^3 twisted by z |--> z^5
g = I.morphism_corestriction(f) g
Next, we want to factor
sage: h = C.morphism_quotient(g)
sage: h
Ore module morphism:
From: Ore module <co0, co1> over Finite Field in z of size 5^3 twisted by z |--> z^5
To: Ore module <im0, im1> over Finite Field in z of size 5^3 twisted by z |--> z^5
>>> from sage.all import *
>>> h = C.morphism_quotient(g)
>>> h
Ore module morphism:
From: Ore module <co0, co1> over Finite Field in z of size 5^3 twisted by z |--> z^5
To: Ore module <im0, im1> over Finite Field in z of size 5^3 twisted by z |--> z^5
h = C.morphism_quotient(g) h
We have found the morphism we were looking for: it is
sage: h.is_isomorphism()
True
>>> from sage.all import *
>>> h.is_isomorphism()
True
h.is_isomorphism()
As a shortcut, we can use explicit conversions as follows:
sage: H = Hom(C, I) # the hom space
sage: h2 = H(f)
sage: h2
Ore module morphism:
From: Ore module <co0, co1> over Finite Field in z of size 5^3 twisted by z |--> z^5
To: Ore module <im0, im1> over Finite Field in z of size 5^3 twisted by z |--> z^5
sage: h == h2
True
>>> from sage.all import *
>>> H = Hom(C, I) # the hom space
>>> h2 = H(f)
>>> h2
Ore module morphism:
From: Ore module <co0, co1> over Finite Field in z of size 5^3 twisted by z |--> z^5
To: Ore module <im0, im1> over Finite Field in z of size 5^3 twisted by z |--> z^5
>>> h == h2
True
H = Hom(C, I) # the hom space h2 = H(f) h2 h == h2
For endomorphisms, one can compute classical invariants as
determinants and characteristic polynomials.
To illustrate this, we check on an example that the characteristic
polynomial of the multiplication by
sage: P = X^5 + z*X^4 + z^2*X^2 + z + 1
sage: M = S.quotient_module(P)
sage: f = M.multiplication_map(X^3)
sage: f.charpoly()
x^5 + x^4 + x^3 + x^2 + 1
sage: P.reduced_norm('x')
x^5 + x^4 + x^3 + x^2 + 1
>>> from sage.all import *
>>> P = X**Integer(5) + z*X**Integer(4) + z**Integer(2)*X**Integer(2) + z + Integer(1)
>>> M = S.quotient_module(P)
>>> f = M.multiplication_map(X**Integer(3))
>>> f.charpoly()
x^5 + x^4 + x^3 + x^2 + 1
>>> P.reduced_norm('x')
x^5 + x^4 + x^3 + x^2 + 1
P = X^5 + z*X^4 + z^2*X^2 + z + 1 M = S.quotient_module(P) f = M.multiplication_map(X^3) f.charpoly() P.reduced_norm('x')
AUTHOR:
Xavier Caruso (2024-10)
- class sage.modules.ore_module_morphism.OreModuleMorphism(parent, im_gens, check=True)[source]¶
Bases:
Morphism
Generic class for morphism between Ore modules.
- characteristic_polynomial(var='x')[source]¶
Return the determinant of this endomorphism.
EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: P = X^3 + z*X^2 + (z^2 + 3)*X + z^5 sage: M = S.quotient_module(P) sage: f = M.multiplication_map(X^3) sage: f.characteristic_polynomial() x^3 + x^2 + 2*x + 2
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> P = X**Integer(3) + z*X**Integer(2) + (z**Integer(2) + Integer(3))*X + z**Integer(5) >>> M = S.quotient_module(P) >>> f = M.multiplication_map(X**Integer(3)) >>> f.characteristic_polynomial() x^3 + x^2 + 2*x + 2
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) P = X^3 + z*X^2 + (z^2 + 3)*X + z^5 M = S.quotient_module(P) f = M.multiplication_map(X^3) f.characteristic_polynomial()
We check that the latter is equal to the reduced norm of
:sage: P.reduced_norm('x') x^3 + x^2 + 2*x + 2
>>> from sage.all import * >>> P.reduced_norm('x') x^3 + x^2 + 2*x + 2
P.reduced_norm('x')
- charpoly(var='x')[source]¶
Return the determinant of this endomorphism.
EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: P = X^3 + z*X^2 + (z^2 + 3)*X + z^5 sage: M = S.quotient_module(P) sage: f = M.multiplication_map(X^3) sage: f.characteristic_polynomial() x^3 + x^2 + 2*x + 2
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> P = X**Integer(3) + z*X**Integer(2) + (z**Integer(2) + Integer(3))*X + z**Integer(5) >>> M = S.quotient_module(P) >>> f = M.multiplication_map(X**Integer(3)) >>> f.characteristic_polynomial() x^3 + x^2 + 2*x + 2
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) P = X^3 + z*X^2 + (z^2 + 3)*X + z^5 M = S.quotient_module(P) f = M.multiplication_map(X^3) f.characteristic_polynomial()
We check that the latter is equal to the reduced norm of
:sage: P.reduced_norm('x') x^3 + x^2 + 2*x + 2
>>> from sage.all import * >>> P.reduced_norm('x') x^3 + x^2 + 2*x + 2
P.reduced_norm('x')
- coimage(names=None)[source]¶
Return
True
if this morphism is injective.EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: P = X^3 + z*X^2 + z^2 sage: M = S.quotient_module(P^2, names='m') sage: M.inject_variables() Defining m0, m1, m2, m3, m4, m5 sage: N = S.quotient_module(P, names='n') sage: N.inject_variables() Defining n0, n1, n2 sage: f = M.hom({m0: n0}) sage: coim = f.coimage() sage: coim Ore module of rank 3 over Finite Field in z of size 5^3 twisted by z |--> z^5 sage: coim.basis() [m3, m4, m5]
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> P = X**Integer(3) + z*X**Integer(2) + z**Integer(2) >>> M = S.quotient_module(P**Integer(2), names='m') >>> M.inject_variables() Defining m0, m1, m2, m3, m4, m5 >>> N = S.quotient_module(P, names='n') >>> N.inject_variables() Defining n0, n1, n2 >>> f = M.hom({m0: n0}) >>> coim = f.coimage() >>> coim Ore module of rank 3 over Finite Field in z of size 5^3 twisted by z |--> z^5 >>> coim.basis() [m3, m4, m5]
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) P = X^3 + z*X^2 + z^2 M = S.quotient_module(P^2, names='m') M.inject_variables() N = S.quotient_module(P, names='n') N.inject_variables() f = M.hom({m0: n0}) coim = f.coimage() coim coim.basis()
- cokernel(names=None)[source]¶
Return
True
if this morphism is injective.EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: P = X^3 + z*X^2 + z^2 sage: M = S.quotient_module(P^2, names='m') sage: M.inject_variables() Defining m0, m1, m2, m3, m4, m5 sage: N = S.quotient_module(P, names='n') sage: N.inject_variables() Defining n0, n1, n2 sage: f = N.hom({n0: P*m0}) sage: coker = f.cokernel() sage: coker Ore module of rank 3 over Finite Field in z of size 5^3 twisted by z |--> z^5 sage: coker.basis() [m3, m4, m5]
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> P = X**Integer(3) + z*X**Integer(2) + z**Integer(2) >>> M = S.quotient_module(P**Integer(2), names='m') >>> M.inject_variables() Defining m0, m1, m2, m3, m4, m5 >>> N = S.quotient_module(P, names='n') >>> N.inject_variables() Defining n0, n1, n2 >>> f = N.hom({n0: P*m0}) >>> coker = f.cokernel() >>> coker Ore module of rank 3 over Finite Field in z of size 5^3 twisted by z |--> z^5 >>> coker.basis() [m3, m4, m5]
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) P = X^3 + z*X^2 + z^2 M = S.quotient_module(P^2, names='m') M.inject_variables() N = S.quotient_module(P, names='n') N.inject_variables() f = N.hom({n0: P*m0}) coker = f.cokernel() coker coker.basis()
- det()[source]¶
Return the determinant of this endomorphism.
EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: M.<m0,m1> = S.quotient_module(X^2 + z) sage: f = M.multiplication_map(X^3) sage: f.determinant() 2
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> M = S.quotient_module(X**Integer(2) + z, names=('m0', 'm1',)); (m0, m1,) = M._first_ngens(2) >>> f = M.multiplication_map(X**Integer(3)) >>> f.determinant() 2
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) M.<m0,m1> = S.quotient_module(X^2 + z) f = M.multiplication_map(X^3) f.determinant()
If the domain differs from the codomain (even if they have the same rank), an error is raised:
sage: N.<n0,n1> = S.quotient_module(X^2 + z^25) sage: g = M.hom({z*m0: n0}) sage: g.determinant() Traceback (most recent call last): ... ValueError: determinants are only defined for endomorphisms
>>> from sage.all import * >>> N = S.quotient_module(X**Integer(2) + z**Integer(25), names=('n0', 'n1',)); (n0, n1,) = N._first_ngens(2) >>> g = M.hom({z*m0: n0}) >>> g.determinant() Traceback (most recent call last): ... ValueError: determinants are only defined for endomorphisms
N.<n0,n1> = S.quotient_module(X^2 + z^25) g = M.hom({z*m0: n0}) g.determinant()
- determinant()[source]¶
Return the determinant of this endomorphism.
EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: M.<m0,m1> = S.quotient_module(X^2 + z) sage: f = M.multiplication_map(X^3) sage: f.determinant() 2
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> M = S.quotient_module(X**Integer(2) + z, names=('m0', 'm1',)); (m0, m1,) = M._first_ngens(2) >>> f = M.multiplication_map(X**Integer(3)) >>> f.determinant() 2
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) M.<m0,m1> = S.quotient_module(X^2 + z) f = M.multiplication_map(X^3) f.determinant()
If the domain differs from the codomain (even if they have the same rank), an error is raised:
sage: N.<n0,n1> = S.quotient_module(X^2 + z^25) sage: g = M.hom({z*m0: n0}) sage: g.determinant() Traceback (most recent call last): ... ValueError: determinants are only defined for endomorphisms
>>> from sage.all import * >>> N = S.quotient_module(X**Integer(2) + z**Integer(25), names=('n0', 'n1',)); (n0, n1,) = N._first_ngens(2) >>> g = M.hom({z*m0: n0}) >>> g.determinant() Traceback (most recent call last): ... ValueError: determinants are only defined for endomorphisms
N.<n0,n1> = S.quotient_module(X^2 + z^25) g = M.hom({z*m0: n0}) g.determinant()
- image(names=None)[source]¶
Return
True
if this morphism is injective.EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: P = X^3 + z*X^2 + z^2 sage: M = S.quotient_module(P^2, names='m') sage: M.inject_variables() Defining m0, m1, m2, m3, m4, m5 sage: N = S.quotient_module(P, names='n') sage: N.inject_variables() Defining n0, n1, n2 sage: f = N.hom({n0: P*m0}) sage: im = f.image() sage: im Ore module of rank 3 over Finite Field in z of size 5^3 twisted by z |--> z^5 sage: im.basis() [m0 + (2*z^2+3*z+1)*m3 + (4*z^2+3*z+3)*m4 + (2*z^2+3*z)*m5, m1 + (z+3)*m3 + (z^2+z+4)*m4, m2 + (2*z^2+4*z+2)*m4 + (2*z^2+z+1)*m5]
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> P = X**Integer(3) + z*X**Integer(2) + z**Integer(2) >>> M = S.quotient_module(P**Integer(2), names='m') >>> M.inject_variables() Defining m0, m1, m2, m3, m4, m5 >>> N = S.quotient_module(P, names='n') >>> N.inject_variables() Defining n0, n1, n2 >>> f = N.hom({n0: P*m0}) >>> im = f.image() >>> im Ore module of rank 3 over Finite Field in z of size 5^3 twisted by z |--> z^5 >>> im.basis() [m0 + (2*z^2+3*z+1)*m3 + (4*z^2+3*z+3)*m4 + (2*z^2+3*z)*m5, m1 + (z+3)*m3 + (z^2+z+4)*m4, m2 + (2*z^2+4*z+2)*m4 + (2*z^2+z+1)*m5]
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) P = X^3 + z*X^2 + z^2 M = S.quotient_module(P^2, names='m') M.inject_variables() N = S.quotient_module(P, names='n') N.inject_variables() f = N.hom({n0: P*m0}) im = f.image() im im.basis()
- inverse()[source]¶
Return the inverse of this morphism.
EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: P = X^2 + z sage: M.<e0,e1,e2,e3> = S.quotient_module(P^2) sage: f = M.multiplication_map(X^3) sage: g = f.inverse() sage: (f*g).is_identity() True sage: (g*f).is_identity() True
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> P = X**Integer(2) + z >>> M = S.quotient_module(P**Integer(2), names=('e0', 'e1', 'e2', 'e3',)); (e0, e1, e2, e3,) = M._first_ngens(4) >>> f = M.multiplication_map(X**Integer(3)) >>> g = f.inverse() >>> (f*g).is_identity() True >>> (g*f).is_identity() True
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) P = X^2 + z M.<e0,e1,e2,e3> = S.quotient_module(P^2) f = M.multiplication_map(X^3) g = f.inverse() (f*g).is_identity() (g*f).is_identity()
If the morphism is not invertible, an error is raised:
sage: h = M.hom({e0: P*e0}) sage: h.inverse() Traceback (most recent call last): ... ValueError: this morphism is not invertible
>>> from sage.all import * >>> h = M.hom({e0: P*e0}) >>> h.inverse() Traceback (most recent call last): ... ValueError: this morphism is not invertible
h = M.hom({e0: P*e0}) h.inverse()
- is_bijective()[source]¶
Return
True
if this morphism is bijective.EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: M = S.quotient_module(X^2 + z) sage: f = M.multiplication_map(X^3) sage: f.is_bijective() True sage: N = S.quotient_module(X^2) sage: g = N.multiplication_map(X^3) sage: g.is_bijective() False
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> M = S.quotient_module(X**Integer(2) + z) >>> f = M.multiplication_map(X**Integer(3)) >>> f.is_bijective() True >>> N = S.quotient_module(X**Integer(2)) >>> g = N.multiplication_map(X**Integer(3)) >>> g.is_bijective() False
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) M = S.quotient_module(X^2 + z) f = M.multiplication_map(X^3) f.is_bijective() N = S.quotient_module(X^2) g = N.multiplication_map(X^3) g.is_bijective()
- is_identity()[source]¶
Return
True
if this morphism is the identity.EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: M.<v,w> = S.quotient_module(X^2 + z) sage: f = M.hom({v: v}) sage: f.is_identity() True sage: f = M.hom({v: 2*v}) sage: f.is_identity() False
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> M = S.quotient_module(X**Integer(2) + z, names=('v', 'w',)); (v, w,) = M._first_ngens(2) >>> f = M.hom({v: v}) >>> f.is_identity() True >>> f = M.hom({v: Integer(2)*v}) >>> f.is_identity() False
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) M.<v,w> = S.quotient_module(X^2 + z) f = M.hom({v: v}) f.is_identity() f = M.hom({v: 2*v}) f.is_identity()
- is_injective()[source]¶
Return
True
if this morphism is injective.EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: P = X^3 + z*X^2 + z^2 sage: M = S.quotient_module(P^2, names='m') sage: M.inject_variables() Defining m0, m1, m2, m3, m4, m5 sage: N = S.quotient_module(P, names='n') sage: N.inject_variables() Defining n0, n1, n2 sage: f = N.hom({n0: P*m0}) sage: f.is_injective() True sage: g = M.hom({m0: n0}) sage: g.is_injective() False
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> P = X**Integer(3) + z*X**Integer(2) + z**Integer(2) >>> M = S.quotient_module(P**Integer(2), names='m') >>> M.inject_variables() Defining m0, m1, m2, m3, m4, m5 >>> N = S.quotient_module(P, names='n') >>> N.inject_variables() Defining n0, n1, n2 >>> f = N.hom({n0: P*m0}) >>> f.is_injective() True >>> g = M.hom({m0: n0}) >>> g.is_injective() False
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) P = X^3 + z*X^2 + z^2 M = S.quotient_module(P^2, names='m') M.inject_variables() N = S.quotient_module(P, names='n') N.inject_variables() f = N.hom({n0: P*m0}) f.is_injective() g = M.hom({m0: n0}) g.is_injective()
- is_isomorphism()[source]¶
Return
True
if this morphism is an isomorphism.EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: M = S.quotient_module(X^2 + z) sage: f = M.multiplication_map(X^3) sage: f.is_isomorphism() True sage: N = S.quotient_module(X^2) sage: g = N.multiplication_map(X^3) sage: g.is_isomorphism() False
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> M = S.quotient_module(X**Integer(2) + z) >>> f = M.multiplication_map(X**Integer(3)) >>> f.is_isomorphism() True >>> N = S.quotient_module(X**Integer(2)) >>> g = N.multiplication_map(X**Integer(3)) >>> g.is_isomorphism() False
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) M = S.quotient_module(X^2 + z) f = M.multiplication_map(X^3) f.is_isomorphism() N = S.quotient_module(X^2) g = N.multiplication_map(X^3) g.is_isomorphism()
- is_surjective()[source]¶
Return
True
if this morphism is surjective.EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: P = X^3 + z*X^2 + z^2 sage: M = S.quotient_module(P^2, names='m') sage: M.inject_variables() Defining m0, m1, m2, m3, m4, m5 sage: N = S.quotient_module(P, names='n') sage: N.inject_variables() Defining n0, n1, n2 sage: f = N.hom({n0: P*m0}) sage: f.is_surjective() False sage: g = M.hom({m0: n0}) sage: g.is_surjective() True
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> P = X**Integer(3) + z*X**Integer(2) + z**Integer(2) >>> M = S.quotient_module(P**Integer(2), names='m') >>> M.inject_variables() Defining m0, m1, m2, m3, m4, m5 >>> N = S.quotient_module(P, names='n') >>> N.inject_variables() Defining n0, n1, n2 >>> f = N.hom({n0: P*m0}) >>> f.is_surjective() False >>> g = M.hom({m0: n0}) >>> g.is_surjective() True
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) P = X^3 + z*X^2 + z^2 M = S.quotient_module(P^2, names='m') M.inject_variables() N = S.quotient_module(P, names='n') N.inject_variables() f = N.hom({n0: P*m0}) f.is_surjective() g = M.hom({m0: n0}) g.is_surjective()
- is_zero()[source]¶
Return
True
if this morphism is zero.EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: P = X^3 + z*X^2 + z^2 + 1 sage: M = S.quotient_module(P^2, names='e') sage: M.inject_variables() Defining e0, e1, e2, e3, e4, e5 sage: f = M.hom({e0: P*e0}) sage: f.is_zero() False sage: (f*f).is_zero() True
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> P = X**Integer(3) + z*X**Integer(2) + z**Integer(2) + Integer(1) >>> M = S.quotient_module(P**Integer(2), names='e') >>> M.inject_variables() Defining e0, e1, e2, e3, e4, e5 >>> f = M.hom({e0: P*e0}) >>> f.is_zero() False >>> (f*f).is_zero() True
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) P = X^3 + z*X^2 + z^2 + 1 M = S.quotient_module(P^2, names='e') M.inject_variables() f = M.hom({e0: P*e0}) f.is_zero() (f*f).is_zero()
- kernel(names=None)[source]¶
Return
True
if this morphism is injective.EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: P = X^3 + z*X^2 + z^2 sage: M = S.quotient_module(P^2, names='m') sage: M.inject_variables() Defining m0, m1, m2, m3, m4, m5 sage: N = S.quotient_module(P, names='n') sage: N.inject_variables() Defining n0, n1, n2 sage: f = M.hom({m0: n0}) sage: ker = f.kernel() sage: ker Ore module of rank 3 over Finite Field in z of size 5^3 twisted by z |--> z^5 sage: ker.basis() [m0 + (2*z^2+3*z+1)*m3 + (4*z^2+3*z+3)*m4 + (2*z^2+3*z)*m5, m1 + (z+3)*m3 + (z^2+z+4)*m4, m2 + (2*z^2+4*z+2)*m4 + (2*z^2+z+1)*m5]
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> P = X**Integer(3) + z*X**Integer(2) + z**Integer(2) >>> M = S.quotient_module(P**Integer(2), names='m') >>> M.inject_variables() Defining m0, m1, m2, m3, m4, m5 >>> N = S.quotient_module(P, names='n') >>> N.inject_variables() Defining n0, n1, n2 >>> f = M.hom({m0: n0}) >>> ker = f.kernel() >>> ker Ore module of rank 3 over Finite Field in z of size 5^3 twisted by z |--> z^5 >>> ker.basis() [m0 + (2*z^2+3*z+1)*m3 + (4*z^2+3*z+3)*m4 + (2*z^2+3*z)*m5, m1 + (z+3)*m3 + (z^2+z+4)*m4, m2 + (2*z^2+4*z+2)*m4 + (2*z^2+z+1)*m5]
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) P = X^3 + z*X^2 + z^2 M = S.quotient_module(P^2, names='m') M.inject_variables() N = S.quotient_module(P, names='n') N.inject_variables() f = M.hom({m0: n0}) ker = f.kernel() ker ker.basis()
- matrix()[source]¶
Return the matrix defining this morphism.
EXAMPLES:
sage: K.<z> = GF(5^3) sage: S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) sage: M = S.quotient_module(X^2 + z) sage: f = M.multiplication_map(2) sage: f.matrix() [2 0] [0 2] sage: g = M.multiplication_map(X^3) sage: g.matrix() [ 0 3*z^2 + z + 1] [ 2*z + 1 0]
>>> from sage.all import * >>> K = GF(Integer(5)**Integer(3), names=('z',)); (z,) = K._first_ngens(1) >>> S = OrePolynomialRing(K, K.frobenius_endomorphism(), names=('X',)); (X,) = S._first_ngens(1) >>> M = S.quotient_module(X**Integer(2) + z) >>> f = M.multiplication_map(Integer(2)) >>> f.matrix() [2 0] [0 2] >>> g = M.multiplication_map(X**Integer(3)) >>> g.matrix() [ 0 3*z^2 + z + 1] [ 2*z + 1 0]
K.<z> = GF(5^3) S.<X> = OrePolynomialRing(K, K.frobenius_endomorphism()) M = S.quotient_module(X^2 + z) f = M.multiplication_map(2) f.matrix() g = M.multiplication_map(X^3) g.matrix()