Skip to content

Commit ec65a08

Browse files
author
Xavier Caruso
committed
implement composition of pseudomorphisms
1 parent 94fe540 commit ec65a08

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

src/sage/modules/free_module_pseudomorphism.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
# http://www.gnu.org/licenses/
2222
# ****************************************************************************
2323

24+
from sage.categories.map import FormalCompositeMap
2425
from sage.categories.morphism import Morphism
2526
from sage.structure.richcmp import richcmp
2627
from sage.modules.free_module_morphism import FreeModuleMorphism
@@ -507,6 +508,83 @@ def _richcmp_(self, other, op):
507508
"""
508509
return richcmp(self._matrix, other._matrix, op)
509510

511+
def _composition_(self, right, homset):
512+
r"""
513+
Return the composition of ``self`` and ``right``.
514+
515+
EXAMPLES:
516+
517+
When there is no twisting derivation, the composite is still
518+
a pseudomorphism and it is computed as such::
519+
520+
sage: Fq.<z> = GF(7^3)
521+
sage: Frob = Fq.frobenius_endomorphism()
522+
sage: V = Fq^2
523+
sage: mat = matrix(2, [1, z, z^2, z^3])
524+
sage: f = V.pseudohom(mat, Frob)
525+
sage: f * f
526+
Free module pseudomorphism (twisted by z |--> z^(7^2)) defined by the matrix
527+
[ z^2 + 2*z + 4 3*z^2 + 4*z + 3]
528+
[2*z^2 + 2*z + 5 4*z^2 + 5*z + 6]
529+
Domain: Vector space of dimension 2 over Finite Field in z of size 7^3
530+
Codomain: Vector space of dimension 2 over Finite Field in z of size 7^3
531+
532+
We note that the side is preserved::
533+
534+
sage: fr = f.side_switch()
535+
sage: fr
536+
Free module pseudomorphism (twisted by z |--> z^7) defined as left-multiplication by the matrix
537+
[ 1 z^2]
538+
[ z z^2 + 3]
539+
Domain: Vector space of dimension 2 over Finite Field in z of size 7^3
540+
Codomain: Vector space of dimension 2 over Finite Field in z of size 7^3
541+
sage: fr * fr
542+
Free module pseudomorphism (twisted by z |--> z^(7^2)) defined as left-multiplication by the matrix
543+
[ z^2 + 2*z + 4 2*z^2 + 2*z + 5]
544+
[3*z^2 + 4*z + 3 4*z^2 + 5*z + 6]
545+
Domain: Vector space of dimension 2 over Finite Field in z of size 7^3
546+
Codomain: Vector space of dimension 2 over Finite Field in z of size 7^3
547+
548+
For general pseudomorphisms, a formal composed map is returned::
549+
550+
sage: P.<x> = ZZ[]
551+
sage: d = P.derivation()
552+
sage: M = P^2
553+
sage: f = M.pseudohom([[1, 2*x], [x, 1]], d)
554+
sage: f * f
555+
Composite map:
556+
From: Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in x over Integer Ring
557+
To: Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in x over Integer Ring
558+
Defn: Free module pseudomorphism (twisted by d/dx) defined by the matrix
559+
[ 1 2*x]
560+
[ x 1]
561+
Domain: Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in x over Integer Ring
562+
Codomain: Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in x over Integer Ring
563+
then
564+
Free module pseudomorphism (twisted by d/dx) defined by the matrix
565+
[ 1 2*x]
566+
[ x 1]
567+
Domain: Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in x over Integer Ring
568+
Codomain: Ambient free module of rank 2 over the integral domain Univariate Polynomial Ring in x over Integer Ring
569+
"""
570+
if (isinstance(right, FreeModulePseudoMorphism)
571+
and self._derivation is None and right._derivation is None):
572+
if self._morphism is None:
573+
morphism = right._morphism
574+
mat = right._matrix * self._matrix
575+
else:
576+
if right._morphism is None:
577+
morphism = self._morphism
578+
else:
579+
morphism = self._morphism * right._morphism
580+
mat = right._matrix.map_coefficients(self._morphism) * self._matrix
581+
parent = right.domain().pseudoHom(morphism, codomain=self.codomain())
582+
f = FreeModulePseudoMorphism(parent, mat, "left")
583+
if self.side() == 'right' and right.side() == 'right':
584+
f._side = "right"
585+
return f
586+
return FormalCompositeMap(homset, right, self)
587+
510588
def ore_module(self, names=None):
511589
r"""
512590
Return the Ore module over which the Ore variable acts

0 commit comments

Comments
 (0)