|
21 | 21 | # http://www.gnu.org/licenses/
|
22 | 22 | # ****************************************************************************
|
23 | 23 |
|
| 24 | +from sage.categories.map import FormalCompositeMap |
24 | 25 | from sage.categories.morphism import Morphism
|
25 | 26 | from sage.structure.richcmp import richcmp
|
26 | 27 | from sage.modules.free_module_morphism import FreeModuleMorphism
|
@@ -507,6 +508,83 @@ def _richcmp_(self, other, op):
|
507 | 508 | """
|
508 | 509 | return richcmp(self._matrix, other._matrix, op)
|
509 | 510 |
|
| 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 | + |
510 | 588 | def ore_module(self, names=None):
|
511 | 589 | r"""
|
512 | 590 | Return the Ore module over which the Ore variable acts
|
|
0 commit comments