|
43 | 43 |
|
44 | 44 | import sage.modules.free_module as free_module
|
45 | 45 | from . import matrix_morphism
|
| 46 | +from sage.categories.morphism import Morphism |
46 | 47 | from sage.structure.sequence import Sequence
|
| 48 | +from sage.structure.richcmp import richcmp, rich_to_bool |
47 | 49 |
|
48 | 50 | from . import free_module_homspace
|
49 | 51 |
|
@@ -612,3 +614,178 @@ def minimal_polynomial(self,var='x'):
|
612 | 614 | raise TypeError("not an endomorphism")
|
613 | 615 |
|
614 | 616 | minpoly = minimal_polynomial
|
| 617 | + |
| 618 | +class BaseIsomorphism1D(Morphism): |
| 619 | + """ |
| 620 | + An isomorphism between a ring and a free rank-1 module over the ring. |
| 621 | +
|
| 622 | + EXAMPLES:: |
| 623 | +
|
| 624 | + sage: R.<x,y> = QQ[] |
| 625 | + sage: V, from_V, to_V = R.free_module(R) |
| 626 | + sage: from_V |
| 627 | + Isomorphism morphism: |
| 628 | + From: Ambient free module of rank 1 over the integral domain Multivariate Polynomial Ring in x, y over Rational Field |
| 629 | + To: Multivariate Polynomial Ring in x, y over Rational Field |
| 630 | + """ |
| 631 | + def _repr_type(self): |
| 632 | + r""" |
| 633 | + EXAMPLES:: |
| 634 | +
|
| 635 | + sage: R.<x,y> = QQ[] |
| 636 | + sage: V, from_V, to_V = R.free_module(R) |
| 637 | + sage: from_V._repr_type() |
| 638 | + 'Isomorphism' |
| 639 | + """ |
| 640 | + return "Isomorphism" |
| 641 | + |
| 642 | + def is_injective(self): |
| 643 | + r""" |
| 644 | + EXAMPLES:: |
| 645 | +
|
| 646 | + sage: R.<x,y> = QQ[] |
| 647 | + sage: V, from_V, to_V = R.free_module(R) |
| 648 | + sage: from_V.is_injective() |
| 649 | + True |
| 650 | + """ |
| 651 | + return True |
| 652 | + |
| 653 | + def is_surjective(self): |
| 654 | + r""" |
| 655 | + EXAMPLES:: |
| 656 | +
|
| 657 | + sage: R.<x,y> = QQ[] |
| 658 | + sage: V, from_V, to_V = R.free_module(R) |
| 659 | + sage: from_V.is_surjective() |
| 660 | + True |
| 661 | + """ |
| 662 | + return True |
| 663 | + |
| 664 | + def _richcmp_(self, other, op): |
| 665 | + r""" |
| 666 | + EXAMPLES:: |
| 667 | +
|
| 668 | + sage: R.<x,y> = QQ[] |
| 669 | + sage: V, fr, to = R.free_module(R) |
| 670 | + sage: fr == loads(dumps(fr)) |
| 671 | + True |
| 672 | + """ |
| 673 | + if isinstance(other, BaseIsomorphism1D): |
| 674 | + return richcmp(self._basis, other._basis, op) |
| 675 | + else: |
| 676 | + return rich_to_bool(op, 1) |
| 677 | + |
| 678 | +class BaseIsomorphism1D_to_FM(BaseIsomorphism1D): |
| 679 | + """ |
| 680 | + An isomorphism from a ring to its 1-dimensional free module |
| 681 | +
|
| 682 | + INPUT: |
| 683 | +
|
| 684 | + - ``parent`` -- the homset |
| 685 | + - ``basis`` -- (default 1) an invertible element of the ring |
| 686 | +
|
| 687 | + EXAMPLES:: |
| 688 | +
|
| 689 | + sage: R = Zmod(8) |
| 690 | + sage: V, from_V, to_V = R.free_module(R) |
| 691 | + sage: v = to_V(2); v |
| 692 | + (2) |
| 693 | + sage: from_V(v) |
| 694 | + 2 |
| 695 | + sage: W, from_W, to_W = R.free_module(R, basis=3) |
| 696 | + sage: W is V |
| 697 | + True |
| 698 | + sage: w = to_W(2); w |
| 699 | + (6) |
| 700 | + sage: from_W(w) |
| 701 | + 2 |
| 702 | +
|
| 703 | + The basis vector has to be a unit so that the map is an isomorphism:: |
| 704 | +
|
| 705 | + sage: W, from_W, to_W = R.free_module(R, basis=4) |
| 706 | + Traceback (most recent call last): |
| 707 | + ... |
| 708 | + ValueError: Basis element must be a unit |
| 709 | + """ |
| 710 | + def __init__(self, parent, basis=None): |
| 711 | + """ |
| 712 | + TESTS:: |
| 713 | +
|
| 714 | + sage: R = Zmod(8) |
| 715 | + sage: W, from_W, to_W = R.free_module(R, basis=3) |
| 716 | + sage: TestSuite(to_W).run() |
| 717 | + """ |
| 718 | + Morphism.__init__(self, parent) |
| 719 | + self._basis = basis |
| 720 | + |
| 721 | + def _call_(self, x): |
| 722 | + """ |
| 723 | + TESTS:: |
| 724 | +
|
| 725 | + sage: R = Zmod(8) |
| 726 | + sage: W, from_W, to_W = R.free_module(R, basis=3) |
| 727 | + sage: to_W(6) # indirect doctest |
| 728 | + (2) |
| 729 | + """ |
| 730 | + if self._basis is not None: |
| 731 | + x *= self._basis |
| 732 | + return self.codomain()([x]) |
| 733 | + |
| 734 | +class BaseIsomorphism1D_from_FM(BaseIsomorphism1D): |
| 735 | + """ |
| 736 | + An isomorphism to a ring from its 1-dimensional free module |
| 737 | +
|
| 738 | + INPUT: |
| 739 | +
|
| 740 | + - ``parent`` -- the homset |
| 741 | + - ``basis`` -- (default 1) an invertible element of the ring |
| 742 | +
|
| 743 | + EXAMPLES:: |
| 744 | +
|
| 745 | + sage: R.<x> = QQ[[]] |
| 746 | + sage: V, from_V, to_V = R.free_module(R) |
| 747 | + sage: v = to_V(1+x); v |
| 748 | + (1 + x) |
| 749 | + sage: from_V(v) |
| 750 | + 1 + x |
| 751 | + sage: W, from_W, to_W = R.free_module(R, basis=(1-x)) |
| 752 | + sage: W is V |
| 753 | + True |
| 754 | + sage: w = to_W(1+x); w |
| 755 | + (1 - x^2) |
| 756 | + sage: from_W(w) |
| 757 | + 1 + x + O(x^20) |
| 758 | +
|
| 759 | + The basis vector has to be a unit so that the map is an isomorphism:: |
| 760 | +
|
| 761 | + sage: W, from_W, to_W = R.free_module(R, basis=x) |
| 762 | + Traceback (most recent call last): |
| 763 | + ... |
| 764 | + ValueError: Basis element must be a unit |
| 765 | + """ |
| 766 | + def __init__(self, parent, basis=None): |
| 767 | + """ |
| 768 | + TESTS:: |
| 769 | +
|
| 770 | + sage: R.<x> = QQ[[]] |
| 771 | + sage: W, from_W, to_W = R.free_module(R, basis=(1-x)) |
| 772 | + sage: TestSuite(from_W).run(skip='_test_nonzero_equal') |
| 773 | + """ |
| 774 | + Morphism.__init__(self, parent) |
| 775 | + self._basis = basis |
| 776 | + |
| 777 | + def _call_(self, x): |
| 778 | + """ |
| 779 | + TESTS:: |
| 780 | +
|
| 781 | + sage: R.<x> = QQ[[]] |
| 782 | + sage: W, from_W, to_W = R.free_module(R, basis=(1-x)) |
| 783 | + sage: w = to_W(1+x); w |
| 784 | + (1 - x^2) |
| 785 | + sage: from_W(w) |
| 786 | + 1 + x + O(x^20) |
| 787 | + """ |
| 788 | + if self._basis is None: |
| 789 | + return x[0] |
| 790 | + else: |
| 791 | + return self.codomain()(x[0] / self._basis) |
0 commit comments