Pseudomorphisms of free modules¶
AUTHORS:
Xavier Caruso, Yossef Musleh (2024-09): initial version
- class sage.modules.free_module_pseudomorphism.FreeModulePseudoMorphism(parent, f, side)[source]¶
Bases:
Morphism
Let
be modules over a ring , a ring homomorphism, and a -derivation, which is a map such that:A pseudomorphism
is an additive map such thatThe map
(resp. ) is referred to as the twisting endomorphism (resp. the twisting derivation) of .Note
The implementation currently requires that
and are free modules.We represent pseudomorphisms by matrices with coefficient in the base ring
. The matrix representing is such that its lines (resp. columns ifside
is"right"
) are the coordinates of the images of the distinguished basis of the domain (see also methodmatrix()
). More concretely, let (resp. ) be the dimension of (resp. ), let be a basis of . For any , we haveWhen
side
is"right"
, the formula isThis class is not supposed to be instantiated directly; the user should use instead the method
sage.rings.module.free_module.FreeModule_generic.pseudohom()
to create a pseudomorphism.- matrix()[source]¶
Return the underlying matrix of this pseudomorphism.
It is defined as the matrix
whose lines (resp. columns ifside
is"right"
) are the coordinates of the images of the distinguished basis of the domain.EXAMPLES:
sage: Fq.<z> = GF(7^3) sage: Frob = Fq.frobenius_endomorphism() sage: M = Fq^3 sage: f = M.pseudohom([[1, z, 3], [0, 1, z^2], [z+1, 1, 1]], Frob) sage: f.matrix() [ 1 z 3] [ 0 1 z^2] [z + 1 1 1]
>>> from sage.all import * >>> Fq = GF(Integer(7)**Integer(3), names=('z',)); (z,) = Fq._first_ngens(1) >>> Frob = Fq.frobenius_endomorphism() >>> M = Fq**Integer(3) >>> f = M.pseudohom([[Integer(1), z, Integer(3)], [Integer(0), Integer(1), z**Integer(2)], [z+Integer(1), Integer(1), Integer(1)]], Frob) >>> f.matrix() [ 1 z 3] [ 0 1 z^2] [z + 1 1 1]
Fq.<z> = GF(7^3) Frob = Fq.frobenius_endomorphism() M = Fq^3 f = M.pseudohom([[1, z, 3], [0, 1, z^2], [z+1, 1, 1]], Frob) f.matrix()
sage: e1, e2, e3 = M.basis() sage: f(e1) (1, z, 3) sage: f(e2) (0, 1, z^2) sage: f(e3) (z + 1, 1, 1)
>>> from sage.all import * >>> e1, e2, e3 = M.basis() >>> f(e1) (1, z, 3) >>> f(e2) (0, 1, z^2) >>> f(e3) (z + 1, 1, 1)
e1, e2, e3 = M.basis() f(e1) f(e2) f(e3)
- ore_module(names=None)[source]¶
Return the Ore module over which the Ore variable acts through this pseudomorphism.
INPUT:
names
– a string, a list of strings orNone
, the names of the vector of the canonical basis of the Ore module; ifNone
, elements are represented as vectors in (where is the base ring)
EXAMPLES:
sage: Fq.<z> = GF(7^3) sage: Frob = Fq.frobenius_endomorphism() sage: V = Fq^2 sage: mat = matrix(2, [1, z, z^2, z^3]) sage: f = V.pseudohom(mat, Frob) sage: M = f.ore_module() sage: M Ore module of rank 2 over Finite Field in z of size 7^3 twisted by z |--> z^7
>>> from sage.all import * >>> Fq = GF(Integer(7)**Integer(3), names=('z',)); (z,) = Fq._first_ngens(1) >>> Frob = Fq.frobenius_endomorphism() >>> V = Fq**Integer(2) >>> mat = matrix(Integer(2), [Integer(1), z, z**Integer(2), z**Integer(3)]) >>> f = V.pseudohom(mat, Frob) >>> M = f.ore_module() >>> M Ore module of rank 2 over Finite Field in z of size 7^3 twisted by z |--> z^7
Fq.<z> = GF(7^3) Frob = Fq.frobenius_endomorphism() V = Fq^2 mat = matrix(2, [1, z, z^2, z^3]) f = V.pseudohom(mat, Frob) M = f.ore_module() M
Here
is a module over the Ore ring and the variable acts on through :sage: S.<X> = M.ore_ring() sage: S Ore Polynomial Ring in X over Finite Field in z of size 7^3 twisted by z |--> z^7 sage: v = M((1,0)) sage: X*v (1, z)
>>> from sage.all import * >>> S = M.ore_ring(names=('X',)); (X,) = S._first_ngens(1) >>> S Ore Polynomial Ring in X over Finite Field in z of size 7^3 twisted by z |--> z^7 >>> v = M((Integer(1),Integer(0))) >>> X*v (1, z)
S.<X> = M.ore_ring() S v = M((1,0)) X*v
The argument
names
can be used to give chosen names to the vectors in the canonical basis:sage: M = f.ore_module(names=('v', 'w')) sage: M.basis() [v, w]
>>> from sage.all import * >>> M = f.ore_module(names=('v', 'w')) >>> M.basis() [v, w]
M = f.ore_module(names=('v', 'w')) M.basis()
or even:
sage: M = f.ore_module(names='e') sage: M.basis() [e0, e1]
>>> from sage.all import * >>> M = f.ore_module(names='e') >>> M.basis() [e0, e1]
M = f.ore_module(names='e') M.basis()
Note that the bracket construction also works:
sage: M.<v,w> = f.ore_module() sage: M.basis() [v, w] sage: v + w v + w
>>> from sage.all import * >>> M = f.ore_module(names=('v', 'w',)); (v, w,) = M._first_ngens(2) >>> M.basis() [v, w] >>> v + w v + w
M.<v,w> = f.ore_module() M.basis() v + w
We refer to
sage.modules.ore_module
for a tutorial on Ore modules in SageMath.See also
- side()[source]¶
Return the side of vectors acted on, relative to the matrix.
EXAMPLES:
sage: Fq.<z> = GF(7^3) sage: Frob = Fq.frobenius_endomorphism() sage: V = Fq^2 sage: m = matrix(2, [1, z, z^2, z^3]) sage: h1 = V.pseudohom(m, Frob) sage: h1.side() 'left' sage: h1([1, 0]) (1, z) sage: h2 = V.pseudohom(m, Frob, side="right") sage: h2.side() 'right' sage: h2([1, 0]) (1, z^2)
>>> from sage.all import * >>> Fq = GF(Integer(7)**Integer(3), names=('z',)); (z,) = Fq._first_ngens(1) >>> Frob = Fq.frobenius_endomorphism() >>> V = Fq**Integer(2) >>> m = matrix(Integer(2), [Integer(1), z, z**Integer(2), z**Integer(3)]) >>> h1 = V.pseudohom(m, Frob) >>> h1.side() 'left' >>> h1([Integer(1), Integer(0)]) (1, z) >>> h2 = V.pseudohom(m, Frob, side="right") >>> h2.side() 'right' >>> h2([Integer(1), Integer(0)]) (1, z^2)
Fq.<z> = GF(7^3) Frob = Fq.frobenius_endomorphism() V = Fq^2 m = matrix(2, [1, z, z^2, z^3]) h1 = V.pseudohom(m, Frob) h1.side() h1([1, 0]) h2 = V.pseudohom(m, Frob, side="right") h2.side() h2([1, 0])
- side_switch()[source]¶
Return the same morphism, acting on vectors on the opposite side.
EXAMPLES:
sage: Fq.<z> = GF(7^3) sage: Frob = Fq.frobenius_endomorphism() sage: V = Fq^2 sage: m = matrix(2, [1, z, z^2, z^3]) sage: h1 = V.pseudohom(m, Frob) sage: h1 Free module pseudomorphism (twisted by z |--> z^7) defined by the matrix [ 1 z] [ z^2 z^2 + 3] Domain: Vector space of dimension 2 over Finite Field in z of size 7^3 Codomain: Vector space of dimension 2 over Finite Field in z of size 7^3 sage: h2 = h1.side_switch() sage: h2 Free module pseudomorphism (twisted by z |--> z^7) defined as left-multiplication by the matrix [ 1 z^2] [ z z^2 + 3] Domain: Vector space of dimension 2 over Finite Field in z of size 7^3 Codomain: Vector space of dimension 2 over Finite Field in z of size 7^3
>>> from sage.all import * >>> Fq = GF(Integer(7)**Integer(3), names=('z',)); (z,) = Fq._first_ngens(1) >>> Frob = Fq.frobenius_endomorphism() >>> V = Fq**Integer(2) >>> m = matrix(Integer(2), [Integer(1), z, z**Integer(2), z**Integer(3)]) >>> h1 = V.pseudohom(m, Frob) >>> h1 Free module pseudomorphism (twisted by z |--> z^7) defined by the matrix [ 1 z] [ z^2 z^2 + 3] Domain: Vector space of dimension 2 over Finite Field in z of size 7^3 Codomain: Vector space of dimension 2 over Finite Field in z of size 7^3 >>> h2 = h1.side_switch() >>> h2 Free module pseudomorphism (twisted by z |--> z^7) defined as left-multiplication by the matrix [ 1 z^2] [ z z^2 + 3] Domain: Vector space of dimension 2 over Finite Field in z of size 7^3 Codomain: Vector space of dimension 2 over Finite Field in z of size 7^3
Fq.<z> = GF(7^3) Frob = Fq.frobenius_endomorphism() V = Fq^2 m = matrix(2, [1, z, z^2, z^3]) h1 = V.pseudohom(m, Frob) h1 h2 = h1.side_switch() h2
We check that
h1
andh2
are the same:sage: v = V.random_element() sage: h1(v) == h2(v) True
>>> from sage.all import * >>> v = V.random_element() >>> h1(v) == h2(v) True
v = V.random_element() h1(v) == h2(v)
- twisting_derivation()[source]¶
Return the twisting derivation of the pseudomorphism (or
None
if the twisting derivation is zero).EXAMPLES:
sage: P.<x> = ZZ[] sage: d = P.derivation() sage: M = P^2 sage: f = M.pseudohom([[1, 2*x], [x, 1]], d) sage: f.twisting_derivation() d/dx
>>> from sage.all import * >>> P = ZZ['x']; (x,) = P._first_ngens(1) >>> d = P.derivation() >>> M = P**Integer(2) >>> f = M.pseudohom([[Integer(1), Integer(2)*x], [x, Integer(1)]], d) >>> f.twisting_derivation() d/dx
P.<x> = ZZ[] d = P.derivation() M = P^2 f = M.pseudohom([[1, 2*x], [x, 1]], d) f.twisting_derivation()
sage: Fq.<z> = GF(7^3) sage: Frob = Fq.frobenius_endomorphism() sage: V = Fq^2 sage: f = V.pseudohom([[1, z], [0, z^2]], Frob) sage: f.twisting_derivation()
>>> from sage.all import * >>> Fq = GF(Integer(7)**Integer(3), names=('z',)); (z,) = Fq._first_ngens(1) >>> Frob = Fq.frobenius_endomorphism() >>> V = Fq**Integer(2) >>> f = V.pseudohom([[Integer(1), z], [Integer(0), z**Integer(2)]], Frob) >>> f.twisting_derivation()
Fq.<z> = GF(7^3) Frob = Fq.frobenius_endomorphism() V = Fq^2 f = V.pseudohom([[1, z], [0, z^2]], Frob) f.twisting_derivation()
- twisting_morphism()[source]¶
Return the twisting morphism of the pseudomorphism (or
None
if the twisting morphism is the identity).EXAMPLES:
sage: Fq.<z> = GF(7^3) sage: Frob = Fq.frobenius_endomorphism() sage: V = Fq^2 sage: f = V.pseudohom([[1, z], [0, z^2]], Frob) sage: f.twisting_morphism() Frobenius endomorphism z |--> z^7 on Finite Field in z of size 7^3
>>> from sage.all import * >>> Fq = GF(Integer(7)**Integer(3), names=('z',)); (z,) = Fq._first_ngens(1) >>> Frob = Fq.frobenius_endomorphism() >>> V = Fq**Integer(2) >>> f = V.pseudohom([[Integer(1), z], [Integer(0), z**Integer(2)]], Frob) >>> f.twisting_morphism() Frobenius endomorphism z |--> z^7 on Finite Field in z of size 7^3
Fq.<z> = GF(7^3) Frob = Fq.frobenius_endomorphism() V = Fq^2 f = V.pseudohom([[1, z], [0, z^2]], Frob) f.twisting_morphism()
sage: P.<x> = ZZ[] sage: d = P.derivation() sage: M = P^2 sage: f = M.pseudohom([[1, 2*x], [x, 1]], d) sage: f.twisting_morphism()
>>> from sage.all import * >>> P = ZZ['x']; (x,) = P._first_ngens(1) >>> d = P.derivation() >>> M = P**Integer(2) >>> f = M.pseudohom([[Integer(1), Integer(2)*x], [x, Integer(1)]], d) >>> f.twisting_morphism()
P.<x> = ZZ[] d = P.derivation() M = P^2 f = M.pseudohom([[1, 2*x], [x, 1]], d) f.twisting_morphism()