passagemath-objects 10.6.47__cp311-cp311-macosx_13_0_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_objects/.dylibs/libgmp.10.dylib +0 -0
- passagemath_objects/__init__.py +3 -0
- passagemath_objects-10.6.47.dist-info/METADATA +115 -0
- passagemath_objects-10.6.47.dist-info/RECORD +280 -0
- passagemath_objects-10.6.47.dist-info/WHEEL +6 -0
- passagemath_objects-10.6.47.dist-info/top_level.txt +3 -0
- sage/all__sagemath_objects.py +37 -0
- sage/arith/all__sagemath_objects.py +5 -0
- sage/arith/long.pxd +411 -0
- sage/arith/numerical_approx.cpython-311-darwin.so +0 -0
- sage/arith/numerical_approx.pxd +35 -0
- sage/arith/numerical_approx.pyx +75 -0
- sage/arith/power.cpython-311-darwin.so +0 -0
- sage/arith/power.pxd +31 -0
- sage/arith/power.pyx +127 -0
- sage/categories/action.cpython-311-darwin.so +0 -0
- sage/categories/action.pxd +29 -0
- sage/categories/action.pyx +641 -0
- sage/categories/algebra_functor.py +745 -0
- sage/categories/all__sagemath_objects.py +33 -0
- sage/categories/basic.py +62 -0
- sage/categories/cartesian_product.py +295 -0
- sage/categories/category.py +3401 -0
- sage/categories/category_cy_helper.cpython-311-darwin.so +0 -0
- sage/categories/category_cy_helper.pxd +8 -0
- sage/categories/category_cy_helper.pyx +322 -0
- sage/categories/category_singleton.cpython-311-darwin.so +0 -0
- sage/categories/category_singleton.pxd +3 -0
- sage/categories/category_singleton.pyx +342 -0
- sage/categories/category_types.py +637 -0
- sage/categories/category_with_axiom.py +2876 -0
- sage/categories/covariant_functorial_construction.py +703 -0
- sage/categories/facade_sets.py +228 -0
- sage/categories/functor.cpython-311-darwin.so +0 -0
- sage/categories/functor.pxd +7 -0
- sage/categories/functor.pyx +691 -0
- sage/categories/homset.py +1338 -0
- sage/categories/homsets.py +364 -0
- sage/categories/isomorphic_objects.py +73 -0
- sage/categories/map.cpython-311-darwin.so +0 -0
- sage/categories/map.pxd +34 -0
- sage/categories/map.pyx +2106 -0
- sage/categories/morphism.cpython-311-darwin.so +0 -0
- sage/categories/morphism.pxd +14 -0
- sage/categories/morphism.pyx +895 -0
- sage/categories/objects.py +167 -0
- sage/categories/primer.py +1696 -0
- sage/categories/pushout.py +4834 -0
- sage/categories/quotients.py +64 -0
- sage/categories/realizations.py +200 -0
- sage/categories/sets_cat.py +3290 -0
- sage/categories/sets_with_partial_maps.py +52 -0
- sage/categories/subobjects.py +64 -0
- sage/categories/subquotients.py +21 -0
- sage/categories/with_realizations.py +311 -0
- sage/cpython/__init__.py +19 -0
- sage/cpython/_py2_random.py +619 -0
- sage/cpython/all.py +3 -0
- sage/cpython/atexit.cpython-311-darwin.so +0 -0
- sage/cpython/atexit.pyx +269 -0
- sage/cpython/builtin_types.cpython-311-darwin.so +0 -0
- sage/cpython/builtin_types.pyx +7 -0
- sage/cpython/cython_metaclass.cpython-311-darwin.so +0 -0
- sage/cpython/cython_metaclass.h +117 -0
- sage/cpython/cython_metaclass.pxd +3 -0
- sage/cpython/cython_metaclass.pyx +130 -0
- sage/cpython/debug.cpython-311-darwin.so +0 -0
- sage/cpython/debug.pyx +302 -0
- sage/cpython/dict_del_by_value.cpython-311-darwin.so +0 -0
- sage/cpython/dict_del_by_value.pxd +9 -0
- sage/cpython/dict_del_by_value.pyx +191 -0
- sage/cpython/dict_internal.h +245 -0
- sage/cpython/getattr.cpython-311-darwin.so +0 -0
- sage/cpython/getattr.pxd +9 -0
- sage/cpython/getattr.pyx +439 -0
- sage/cpython/pycore_long.h +97 -0
- sage/cpython/pycore_long.pxd +10 -0
- sage/cpython/python_debug.h +44 -0
- sage/cpython/python_debug.pxd +47 -0
- sage/cpython/pyx_visit.h +13 -0
- sage/cpython/string.cpython-311-darwin.so +0 -0
- sage/cpython/string.pxd +76 -0
- sage/cpython/string.pyx +34 -0
- sage/cpython/string_impl.h +60 -0
- sage/cpython/type.cpython-311-darwin.so +0 -0
- sage/cpython/type.pxd +2 -0
- sage/cpython/type.pyx +40 -0
- sage/cpython/wrapperdescr.pxd +67 -0
- sage/ext/all__sagemath_objects.py +3 -0
- sage/ext/ccobject.h +64 -0
- sage/ext/cplusplus.pxd +17 -0
- sage/ext/mod_int.h +30 -0
- sage/ext/mod_int.pxd +24 -0
- sage/ext/stdsage.pxd +39 -0
- sage/groups/all__sagemath_objects.py +1 -0
- sage/groups/group.cpython-311-darwin.so +0 -0
- sage/groups/group.pxd +14 -0
- sage/groups/group.pyx +322 -0
- sage/groups/old.cpython-311-darwin.so +0 -0
- sage/groups/old.pxd +14 -0
- sage/groups/old.pyx +219 -0
- sage/libs/all__sagemath_objects.py +3 -0
- sage/libs/gmp/__init__.py +1 -0
- sage/libs/gmp/all.pxd +6 -0
- sage/libs/gmp/binop.pxd +23 -0
- sage/libs/gmp/misc.pxd +8 -0
- sage/libs/gmp/mpf.pxd +88 -0
- sage/libs/gmp/mpn.pxd +57 -0
- sage/libs/gmp/mpq.pxd +57 -0
- sage/libs/gmp/mpz.pxd +202 -0
- sage/libs/gmp/pylong.cpython-311-darwin.so +0 -0
- sage/libs/gmp/pylong.pxd +12 -0
- sage/libs/gmp/pylong.pyx +150 -0
- sage/libs/gmp/random.pxd +25 -0
- sage/libs/gmp/randomize.pxd +59 -0
- sage/libs/gmp/types.pxd +53 -0
- sage/libs/gmpxx.pxd +19 -0
- sage/misc/abstract_method.py +276 -0
- sage/misc/all__sagemath_objects.py +43 -0
- sage/misc/bindable_class.py +253 -0
- sage/misc/c3_controlled.cpython-311-darwin.so +0 -0
- sage/misc/c3_controlled.pxd +2 -0
- sage/misc/c3_controlled.pyx +1402 -0
- sage/misc/cachefunc.cpython-311-darwin.so +0 -0
- sage/misc/cachefunc.pxd +43 -0
- sage/misc/cachefunc.pyx +3781 -0
- sage/misc/call.py +188 -0
- sage/misc/classcall_metaclass.cpython-311-darwin.so +0 -0
- sage/misc/classcall_metaclass.pxd +14 -0
- sage/misc/classcall_metaclass.pyx +599 -0
- sage/misc/constant_function.cpython-311-darwin.so +0 -0
- sage/misc/constant_function.pyx +130 -0
- sage/misc/decorators.py +747 -0
- sage/misc/fast_methods.cpython-311-darwin.so +0 -0
- sage/misc/fast_methods.pxd +20 -0
- sage/misc/fast_methods.pyx +351 -0
- sage/misc/flatten.py +90 -0
- sage/misc/fpickle.cpython-311-darwin.so +0 -0
- sage/misc/fpickle.pyx +177 -0
- sage/misc/function_mangling.cpython-311-darwin.so +0 -0
- sage/misc/function_mangling.pxd +11 -0
- sage/misc/function_mangling.pyx +308 -0
- sage/misc/inherit_comparison.cpython-311-darwin.so +0 -0
- sage/misc/inherit_comparison.pxd +5 -0
- sage/misc/inherit_comparison.pyx +105 -0
- sage/misc/instancedoc.cpython-311-darwin.so +0 -0
- sage/misc/instancedoc.pyx +331 -0
- sage/misc/lazy_attribute.cpython-311-darwin.so +0 -0
- sage/misc/lazy_attribute.pyx +607 -0
- sage/misc/lazy_format.py +135 -0
- sage/misc/lazy_import.cpython-311-darwin.so +0 -0
- sage/misc/lazy_import.pyx +1299 -0
- sage/misc/lazy_import_cache.py +36 -0
- sage/misc/lazy_list.cpython-311-darwin.so +0 -0
- sage/misc/lazy_list.pxd +19 -0
- sage/misc/lazy_list.pyx +1187 -0
- sage/misc/lazy_string.cpython-311-darwin.so +0 -0
- sage/misc/lazy_string.pxd +7 -0
- sage/misc/lazy_string.pyx +546 -0
- sage/misc/misc.py +1066 -0
- sage/misc/misc_c.cpython-311-darwin.so +0 -0
- sage/misc/misc_c.pxd +3 -0
- sage/misc/misc_c.pyx +766 -0
- sage/misc/namespace_package.py +37 -0
- sage/misc/nested_class.cpython-311-darwin.so +0 -0
- sage/misc/nested_class.pxd +3 -0
- sage/misc/nested_class.pyx +394 -0
- sage/misc/persist.cpython-311-darwin.so +0 -0
- sage/misc/persist.pyx +1251 -0
- sage/misc/prandom.py +418 -0
- sage/misc/randstate.cpython-311-darwin.so +0 -0
- sage/misc/randstate.pxd +30 -0
- sage/misc/randstate.pyx +1059 -0
- sage/misc/repr.py +203 -0
- sage/misc/reset.cpython-311-darwin.so +0 -0
- sage/misc/reset.pyx +196 -0
- sage/misc/sage_ostools.cpython-311-darwin.so +0 -0
- sage/misc/sage_ostools.pyx +323 -0
- sage/misc/sage_timeit.py +275 -0
- sage/misc/sage_timeit_class.cpython-311-darwin.so +0 -0
- sage/misc/sage_timeit_class.pyx +120 -0
- sage/misc/sage_unittest.py +637 -0
- sage/misc/sageinspect.py +2768 -0
- sage/misc/session.cpython-311-darwin.so +0 -0
- sage/misc/session.pyx +392 -0
- sage/misc/superseded.py +557 -0
- sage/misc/test_nested_class.py +228 -0
- sage/misc/timing.py +264 -0
- sage/misc/unknown.py +222 -0
- sage/misc/verbose.py +253 -0
- sage/misc/weak_dict.cpython-311-darwin.so +0 -0
- sage/misc/weak_dict.pxd +15 -0
- sage/misc/weak_dict.pyx +1231 -0
- sage/modules/all__sagemath_objects.py +1 -0
- sage/modules/module.cpython-311-darwin.so +0 -0
- sage/modules/module.pxd +5 -0
- sage/modules/module.pyx +329 -0
- sage/rings/all__sagemath_objects.py +3 -0
- sage/rings/integer_fake.h +22 -0
- sage/rings/integer_fake.pxd +55 -0
- sage/sets/all__sagemath_objects.py +3 -0
- sage/sets/pythonclass.cpython-311-darwin.so +0 -0
- sage/sets/pythonclass.pxd +9 -0
- sage/sets/pythonclass.pyx +247 -0
- sage/structure/__init__.py +4 -0
- sage/structure/all.py +30 -0
- sage/structure/category_object.cpython-311-darwin.so +0 -0
- sage/structure/category_object.pxd +28 -0
- sage/structure/category_object.pyx +1087 -0
- sage/structure/coerce.cpython-311-darwin.so +0 -0
- sage/structure/coerce.pxd +44 -0
- sage/structure/coerce.pyx +2107 -0
- sage/structure/coerce_actions.cpython-311-darwin.so +0 -0
- sage/structure/coerce_actions.pxd +27 -0
- sage/structure/coerce_actions.pyx +988 -0
- sage/structure/coerce_dict.cpython-311-darwin.so +0 -0
- sage/structure/coerce_dict.pxd +51 -0
- sage/structure/coerce_dict.pyx +1557 -0
- sage/structure/coerce_exceptions.py +23 -0
- sage/structure/coerce_maps.cpython-311-darwin.so +0 -0
- sage/structure/coerce_maps.pxd +28 -0
- sage/structure/coerce_maps.pyx +718 -0
- sage/structure/debug_options.cpython-311-darwin.so +0 -0
- sage/structure/debug_options.pxd +6 -0
- sage/structure/debug_options.pyx +54 -0
- sage/structure/dynamic_class.py +541 -0
- sage/structure/element.cpython-311-darwin.so +0 -0
- sage/structure/element.pxd +272 -0
- sage/structure/element.pyx +4772 -0
- sage/structure/element_wrapper.cpython-311-darwin.so +0 -0
- sage/structure/element_wrapper.pxd +12 -0
- sage/structure/element_wrapper.pyx +582 -0
- sage/structure/factorization.py +1422 -0
- sage/structure/factorization_integer.py +105 -0
- sage/structure/factory.cpython-311-darwin.so +0 -0
- sage/structure/factory.pyx +786 -0
- sage/structure/formal_sum.py +489 -0
- sage/structure/gens_py.py +73 -0
- sage/structure/global_options.py +1743 -0
- sage/structure/indexed_generators.py +863 -0
- sage/structure/list_clone.cpython-311-darwin.so +0 -0
- sage/structure/list_clone.pxd +65 -0
- sage/structure/list_clone.pyx +1867 -0
- sage/structure/list_clone_demo.cpython-311-darwin.so +0 -0
- sage/structure/list_clone_demo.pyx +248 -0
- sage/structure/list_clone_timings.py +179 -0
- sage/structure/list_clone_timings_cy.cpython-311-darwin.so +0 -0
- sage/structure/list_clone_timings_cy.pyx +86 -0
- sage/structure/mutability.cpython-311-darwin.so +0 -0
- sage/structure/mutability.pxd +21 -0
- sage/structure/mutability.pyx +348 -0
- sage/structure/nonexact.py +69 -0
- sage/structure/parent.cpython-311-darwin.so +0 -0
- sage/structure/parent.pxd +112 -0
- sage/structure/parent.pyx +3093 -0
- sage/structure/parent_base.cpython-311-darwin.so +0 -0
- sage/structure/parent_base.pxd +13 -0
- sage/structure/parent_base.pyx +44 -0
- sage/structure/parent_gens.cpython-311-darwin.so +0 -0
- sage/structure/parent_gens.pxd +22 -0
- sage/structure/parent_gens.pyx +377 -0
- sage/structure/parent_old.cpython-311-darwin.so +0 -0
- sage/structure/parent_old.pxd +25 -0
- sage/structure/parent_old.pyx +294 -0
- sage/structure/proof/__init__.py +1 -0
- sage/structure/proof/all.py +243 -0
- sage/structure/proof/proof.py +300 -0
- sage/structure/richcmp.cpython-311-darwin.so +0 -0
- sage/structure/richcmp.pxd +213 -0
- sage/structure/richcmp.pyx +495 -0
- sage/structure/sage_object.cpython-311-darwin.so +0 -0
- sage/structure/sage_object.pxd +3 -0
- sage/structure/sage_object.pyx +988 -0
- sage/structure/sage_object_test.py +19 -0
- sage/structure/sequence.py +937 -0
- sage/structure/set_factories.py +1178 -0
- sage/structure/set_factories_example.py +527 -0
- sage/structure/support_view.py +179 -0
- sage/structure/test_factory.py +56 -0
- sage/structure/unique_representation.py +1359 -0
|
@@ -0,0 +1,895 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
"""
|
|
3
|
+
Morphisms
|
|
4
|
+
|
|
5
|
+
This module defines the base classes of morphisms between objects of a given
|
|
6
|
+
category.
|
|
7
|
+
|
|
8
|
+
EXAMPLES:
|
|
9
|
+
|
|
10
|
+
Typically, a morphism is defined by the images of the generators of the domain. ::
|
|
11
|
+
|
|
12
|
+
sage: X.<a, b> = ZZ[]
|
|
13
|
+
sage: Y.<c> = ZZ[]
|
|
14
|
+
sage: X.hom([c, c^2])
|
|
15
|
+
Ring morphism:
|
|
16
|
+
From: Multivariate Polynomial Ring in a, b over Integer Ring
|
|
17
|
+
To: Univariate Polynomial Ring in c over Integer Ring
|
|
18
|
+
Defn: a |--> c
|
|
19
|
+
b |--> c^2
|
|
20
|
+
|
|
21
|
+
AUTHORS:
|
|
22
|
+
|
|
23
|
+
- William Stein (2005): initial version
|
|
24
|
+
|
|
25
|
+
- David Joyner (2005-12-17): added examples
|
|
26
|
+
|
|
27
|
+
- Robert Bradshaw (2007-06-25): Pyrexification
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
# ****************************************************************************
|
|
31
|
+
# Copyright (C) 2005 William Stein <wstein@gmail.com>
|
|
32
|
+
#
|
|
33
|
+
# This program is free software: you can redistribute it and/or modify
|
|
34
|
+
# it under the terms of the GNU General Public License as published by
|
|
35
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
36
|
+
# (at your option) any later version.
|
|
37
|
+
# https://www.gnu.org/licenses/
|
|
38
|
+
# ****************************************************************************
|
|
39
|
+
|
|
40
|
+
from cpython.object cimport *
|
|
41
|
+
|
|
42
|
+
from sage.misc.constant_function import ConstantFunction
|
|
43
|
+
|
|
44
|
+
from sage.structure.element cimport Element, ModuleElement
|
|
45
|
+
from sage.structure.richcmp cimport richcmp_not_equal, rich_to_bool
|
|
46
|
+
from sage.structure.parent cimport Parent
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def is_Morphism(x):
|
|
50
|
+
from sage.misc.superseded import deprecation_cython
|
|
51
|
+
deprecation_cython(38103, "The function is_Morphism is deprecated; use 'isinstance(..., Morphism)' instead.")
|
|
52
|
+
return isinstance(x, Morphism)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
cdef class Morphism(Map):
|
|
56
|
+
|
|
57
|
+
def _repr_(self):
|
|
58
|
+
"""
|
|
59
|
+
Return the string representation of ``self``.
|
|
60
|
+
|
|
61
|
+
.. NOTE::
|
|
62
|
+
|
|
63
|
+
It uses :meth:`_repr_type` and :meth:`_repr_defn`.
|
|
64
|
+
|
|
65
|
+
A morphism that has been subject to
|
|
66
|
+
:meth:`~sage.categories.map.Map._make_weak_references` has probably
|
|
67
|
+
been used internally in the coercion system. Hence, it may become
|
|
68
|
+
defunct by garbage collection of the domain. In this case, a warning
|
|
69
|
+
is printed accordingly.
|
|
70
|
+
|
|
71
|
+
EXAMPLES::
|
|
72
|
+
|
|
73
|
+
sage: R.<t> = ZZ[]
|
|
74
|
+
sage: f = R.hom([t + 1])
|
|
75
|
+
sage: f # indirect doctest
|
|
76
|
+
Ring endomorphism of Univariate Polynomial Ring in t over Integer Ring
|
|
77
|
+
Defn: t |--> t + 1
|
|
78
|
+
|
|
79
|
+
TESTS::
|
|
80
|
+
|
|
81
|
+
sage: # needs sage.rings.number_field
|
|
82
|
+
sage: K = CyclotomicField(12)
|
|
83
|
+
sage: L = CyclotomicField(132)
|
|
84
|
+
sage: phi = L._internal_coerce_map_from(K); phi
|
|
85
|
+
(map internal to coercion system -- copy before use)
|
|
86
|
+
Generic morphism:
|
|
87
|
+
From: Cyclotomic Field of order 12 and degree 4
|
|
88
|
+
To: Cyclotomic Field of order 132 and degree 40
|
|
89
|
+
sage: del K
|
|
90
|
+
sage: import gc
|
|
91
|
+
sage: _ = gc.collect()
|
|
92
|
+
sage: phi
|
|
93
|
+
Defunct morphism
|
|
94
|
+
"""
|
|
95
|
+
D = self.domain()
|
|
96
|
+
if D is None:
|
|
97
|
+
return "Defunct morphism"
|
|
98
|
+
if self.is_endomorphism():
|
|
99
|
+
s = "{} endomorphism of {}".format(self._repr_type(), self.domain())
|
|
100
|
+
else:
|
|
101
|
+
s = "{} morphism:".format(self._repr_type())
|
|
102
|
+
s += "\n From: {}".format(self.domain())
|
|
103
|
+
s += "\n To: {}".format(self._codomain)
|
|
104
|
+
if isinstance(self.domain, ConstantFunction):
|
|
105
|
+
d = self._repr_defn()
|
|
106
|
+
if d != '':
|
|
107
|
+
s += "\n Defn: " + '\n '.join(d.split('\n'))
|
|
108
|
+
else:
|
|
109
|
+
d = "(map internal to coercion system -- copy before use)"
|
|
110
|
+
s = d + "\n" + s
|
|
111
|
+
return s
|
|
112
|
+
|
|
113
|
+
def _default_repr_(self):
|
|
114
|
+
"""
|
|
115
|
+
Return a string representation of this morphism.
|
|
116
|
+
|
|
117
|
+
EXAMPLES::
|
|
118
|
+
|
|
119
|
+
sage: R.<t> = ZZ[]
|
|
120
|
+
sage: f = R.hom([t+1])
|
|
121
|
+
sage: f._default_repr_()
|
|
122
|
+
'Ring endomorphism of Univariate Polynomial Ring in t over Integer Ring\n Defn: t |--> t + 1'
|
|
123
|
+
"""
|
|
124
|
+
D = self.domain()
|
|
125
|
+
if D is None:
|
|
126
|
+
return "Defunct morphism"
|
|
127
|
+
if self.is_endomorphism():
|
|
128
|
+
s = "{} endomorphism of {}".format(self._repr_type(), self.domain())
|
|
129
|
+
else:
|
|
130
|
+
s = "{} morphism:".format(self._repr_type())
|
|
131
|
+
s += "\n From: {}".format(self.domain())
|
|
132
|
+
s += "\n To: {}".format(self._codomain)
|
|
133
|
+
d = self._repr_defn()
|
|
134
|
+
if d != '':
|
|
135
|
+
s += "\n Defn: " + '\n '.join(d.split('\n'))
|
|
136
|
+
return s
|
|
137
|
+
|
|
138
|
+
def _repr_short(self):
|
|
139
|
+
"""
|
|
140
|
+
Return a short string representation of this morphism.
|
|
141
|
+
|
|
142
|
+
EXAMPLES::
|
|
143
|
+
|
|
144
|
+
sage: R.<t> = ZZ[]
|
|
145
|
+
sage: f = R.hom([t+1])
|
|
146
|
+
sage: f
|
|
147
|
+
Ring endomorphism of Univariate Polynomial Ring in t over Integer Ring
|
|
148
|
+
Defn: t |--> t + 1
|
|
149
|
+
sage: f._repr_short()
|
|
150
|
+
't |--> t + 1'
|
|
151
|
+
sage: print(f._repr_short())
|
|
152
|
+
t |--> t + 1
|
|
153
|
+
|
|
154
|
+
sage: R.<u,v> = ZZ[]
|
|
155
|
+
sage: f = R.hom([v,u+v])
|
|
156
|
+
sage: f
|
|
157
|
+
Ring endomorphism of Multivariate Polynomial Ring in u, v over Integer Ring
|
|
158
|
+
Defn: u |--> v
|
|
159
|
+
v |--> u + v
|
|
160
|
+
sage: print(f._repr_short())
|
|
161
|
+
u |--> v, v |--> u + v
|
|
162
|
+
|
|
163
|
+
AUTHOR:
|
|
164
|
+
|
|
165
|
+
- Xavier Caruso (2012-06-29)
|
|
166
|
+
"""
|
|
167
|
+
d = self._repr_defn()
|
|
168
|
+
if d == "":
|
|
169
|
+
return self._repr_()
|
|
170
|
+
else:
|
|
171
|
+
return ", ".join(d.split("\n"))
|
|
172
|
+
|
|
173
|
+
def category(self):
|
|
174
|
+
"""
|
|
175
|
+
Return the category of the parent of this morphism.
|
|
176
|
+
|
|
177
|
+
EXAMPLES::
|
|
178
|
+
|
|
179
|
+
sage: R.<t> = ZZ[]
|
|
180
|
+
sage: f = R.hom([t**2])
|
|
181
|
+
sage: f.category()
|
|
182
|
+
Category of endsets of unital magmas and right modules over
|
|
183
|
+
(Dedekind domains and euclidean domains
|
|
184
|
+
and noetherian rings
|
|
185
|
+
and infinite enumerated sets and metric spaces)
|
|
186
|
+
and left modules over
|
|
187
|
+
(Dedekind domains and euclidean domains
|
|
188
|
+
and noetherian rings
|
|
189
|
+
and infinite enumerated sets and metric spaces)
|
|
190
|
+
|
|
191
|
+
sage: # needs sage.rings.number_field
|
|
192
|
+
sage: K = CyclotomicField(12)
|
|
193
|
+
sage: L = CyclotomicField(132)
|
|
194
|
+
sage: phi = L._internal_coerce_map_from(K)
|
|
195
|
+
sage: phi.category()
|
|
196
|
+
Category of homsets of number fields
|
|
197
|
+
"""
|
|
198
|
+
# Should it be Category of elements of ...?
|
|
199
|
+
return self.parent().category()
|
|
200
|
+
|
|
201
|
+
def is_endomorphism(self):
|
|
202
|
+
"""
|
|
203
|
+
Return ``True`` if this morphism is an endomorphism.
|
|
204
|
+
|
|
205
|
+
EXAMPLES::
|
|
206
|
+
|
|
207
|
+
sage: R.<t> = ZZ[]
|
|
208
|
+
sage: f = R.hom([t])
|
|
209
|
+
sage: f.is_endomorphism()
|
|
210
|
+
True
|
|
211
|
+
|
|
212
|
+
sage: # needs sage.rings.number_field
|
|
213
|
+
sage: K = CyclotomicField(12)
|
|
214
|
+
sage: L = CyclotomicField(132)
|
|
215
|
+
sage: phi = L._internal_coerce_map_from(K)
|
|
216
|
+
sage: phi.is_endomorphism()
|
|
217
|
+
False
|
|
218
|
+
"""
|
|
219
|
+
return self.parent().is_endomorphism_set()
|
|
220
|
+
|
|
221
|
+
def is_identity(self):
|
|
222
|
+
"""
|
|
223
|
+
Return ``True`` if this morphism is the identity morphism.
|
|
224
|
+
|
|
225
|
+
.. NOTE::
|
|
226
|
+
|
|
227
|
+
Implemented only when the domain has a method gens()
|
|
228
|
+
|
|
229
|
+
EXAMPLES::
|
|
230
|
+
|
|
231
|
+
sage: R.<t> = ZZ[]
|
|
232
|
+
sage: f = R.hom([t])
|
|
233
|
+
sage: f.is_identity()
|
|
234
|
+
True
|
|
235
|
+
sage: g = R.hom([t + 1])
|
|
236
|
+
sage: g.is_identity()
|
|
237
|
+
False
|
|
238
|
+
|
|
239
|
+
A morphism between two different spaces cannot be the identity::
|
|
240
|
+
|
|
241
|
+
sage: R2.<t2> = QQ[]
|
|
242
|
+
sage: h = R.hom([t2])
|
|
243
|
+
sage: h.is_identity()
|
|
244
|
+
False
|
|
245
|
+
"""
|
|
246
|
+
try:
|
|
247
|
+
i = self._parent.identity()
|
|
248
|
+
except TypeError:
|
|
249
|
+
# If there is no identity morphism,
|
|
250
|
+
# then self cannot be equal to it.
|
|
251
|
+
return False
|
|
252
|
+
return self._richcmp_(i, Py_EQ)
|
|
253
|
+
|
|
254
|
+
def pushforward(self, I):
|
|
255
|
+
raise NotImplementedError
|
|
256
|
+
|
|
257
|
+
def register_as_coercion(self):
|
|
258
|
+
r"""
|
|
259
|
+
Register this morphism as a coercion to Sage's coercion model
|
|
260
|
+
(see :mod:`sage.structure.coerce`).
|
|
261
|
+
|
|
262
|
+
EXAMPLES:
|
|
263
|
+
|
|
264
|
+
By default, adding polynomials over different variables triggers an error::
|
|
265
|
+
|
|
266
|
+
sage: X.<x> = ZZ[]
|
|
267
|
+
sage: Y.<y> = ZZ[]
|
|
268
|
+
sage: x^2 + y
|
|
269
|
+
Traceback (most recent call last):
|
|
270
|
+
...
|
|
271
|
+
TypeError: unsupported operand parent(s) for +:
|
|
272
|
+
'Univariate Polynomial Ring in x over Integer Ring' and
|
|
273
|
+
'Univariate Polynomial Ring in y over Integer Ring'
|
|
274
|
+
|
|
275
|
+
Let us declare a coercion from `\ZZ[x]` to `\ZZ[z]`::
|
|
276
|
+
|
|
277
|
+
sage: Z.<z> = ZZ[]
|
|
278
|
+
sage: phi = Hom(X, Z)(z)
|
|
279
|
+
sage: phi(x^2+1)
|
|
280
|
+
z^2 + 1
|
|
281
|
+
sage: phi.register_as_coercion()
|
|
282
|
+
|
|
283
|
+
Now we can add elements from `\ZZ[x]` and `\ZZ[z]`, because
|
|
284
|
+
the elements of the former are allowed to be implicitly
|
|
285
|
+
coerced into the later::
|
|
286
|
+
|
|
287
|
+
sage: x^2 + z
|
|
288
|
+
z^2 + z
|
|
289
|
+
|
|
290
|
+
Caveat: the registration of the coercion must be done before any
|
|
291
|
+
other coercion is registered or discovered::
|
|
292
|
+
|
|
293
|
+
sage: phi = Hom(X, Z)(z^2)
|
|
294
|
+
sage: phi.register_as_coercion()
|
|
295
|
+
Traceback (most recent call last):
|
|
296
|
+
...
|
|
297
|
+
AssertionError: coercion from Univariate Polynomial Ring in x over Integer Ring
|
|
298
|
+
to Univariate Polynomial Ring in z over Integer Ring
|
|
299
|
+
already registered or discovered
|
|
300
|
+
"""
|
|
301
|
+
self._codomain.register_coercion(self)
|
|
302
|
+
|
|
303
|
+
def register_as_conversion(self):
|
|
304
|
+
r"""
|
|
305
|
+
Register this morphism as a conversion to Sage's coercion model.
|
|
306
|
+
|
|
307
|
+
(see :mod:`sage.structure.coerce`).
|
|
308
|
+
|
|
309
|
+
EXAMPLES:
|
|
310
|
+
|
|
311
|
+
Let us declare a conversion from the symmetric group to `\ZZ`
|
|
312
|
+
through the sign map::
|
|
313
|
+
|
|
314
|
+
sage: # needs sage.groups
|
|
315
|
+
sage: S = SymmetricGroup(4)
|
|
316
|
+
sage: phi = Hom(S, ZZ)(lambda x: ZZ(x.sign()))
|
|
317
|
+
sage: x = S.an_element(); x
|
|
318
|
+
(2,3,4)
|
|
319
|
+
sage: phi(x)
|
|
320
|
+
1
|
|
321
|
+
sage: phi.register_as_conversion()
|
|
322
|
+
sage: ZZ(x)
|
|
323
|
+
1
|
|
324
|
+
"""
|
|
325
|
+
self._codomain.register_conversion(self)
|
|
326
|
+
|
|
327
|
+
def __hash__(self):
|
|
328
|
+
"""
|
|
329
|
+
Return a hash of this morphism.
|
|
330
|
+
|
|
331
|
+
It is the hash of the triple (domain, codomain, definition)
|
|
332
|
+
where ``definition`` is:
|
|
333
|
+
|
|
334
|
+
- a tuple consisting of the images of the generators
|
|
335
|
+
of the domain if domain has generators
|
|
336
|
+
|
|
337
|
+
- the string representation of this morphism otherwise
|
|
338
|
+
|
|
339
|
+
AUTHOR:
|
|
340
|
+
|
|
341
|
+
- Xavier Caruso (2012-07-09)
|
|
342
|
+
"""
|
|
343
|
+
domain = self.domain()
|
|
344
|
+
codomain = self.codomain()
|
|
345
|
+
try:
|
|
346
|
+
gens = domain.gens()
|
|
347
|
+
definition = tuple([self(x) for x in gens])
|
|
348
|
+
except (AttributeError, NotImplementedError):
|
|
349
|
+
definition = repr(self)
|
|
350
|
+
return hash((domain, codomain, definition))
|
|
351
|
+
|
|
352
|
+
cpdef _richcmp_(self, other, int op):
|
|
353
|
+
"""
|
|
354
|
+
Generic comparison function for morphisms.
|
|
355
|
+
|
|
356
|
+
We check the images of the generators of the domain under both
|
|
357
|
+
maps. We then iteratively check the base.
|
|
358
|
+
|
|
359
|
+
TESTS::
|
|
360
|
+
|
|
361
|
+
sage: # needs sage.combinat
|
|
362
|
+
sage: from sage.categories.morphism import SetMorphism
|
|
363
|
+
sage: E = End(Partitions(5))
|
|
364
|
+
sage: f = E.identity()
|
|
365
|
+
sage: g = SetMorphism(E, lambda x: x)
|
|
366
|
+
sage: f == g
|
|
367
|
+
Traceback (most recent call last):
|
|
368
|
+
...
|
|
369
|
+
NotImplementedError: unable to compare morphisms of type <... 'sage.categories.morphism.IdentityMorphism'>
|
|
370
|
+
and <... 'sage.categories.morphism.SetMorphism'> with domain Partitions of the integer 5
|
|
371
|
+
|
|
372
|
+
We check that :issue:`28617` is fixed::
|
|
373
|
+
|
|
374
|
+
sage: FF = GF(2^20) # needs sage.rings.finite_rings
|
|
375
|
+
sage: f = FF.frobenius_endomorphism() # needs sage.rings.finite_rings
|
|
376
|
+
sage: f == FF.frobenius_endomorphism() # needs sage.rings.finite_rings
|
|
377
|
+
True
|
|
378
|
+
|
|
379
|
+
and that :issue:`29632` is fixed::
|
|
380
|
+
|
|
381
|
+
sage: R.<x,y> = QuadraticField(-1)[] # needs sage.rings.number_field
|
|
382
|
+
sage: f = R.hom(R.gens(), R) # needs sage.rings.number_field
|
|
383
|
+
sage: f.is_identity() # needs sage.rings.number_field
|
|
384
|
+
True
|
|
385
|
+
"""
|
|
386
|
+
if self is other:
|
|
387
|
+
return rich_to_bool(op, 0)
|
|
388
|
+
|
|
389
|
+
# Important note: because of the coercion model, we know that
|
|
390
|
+
# self and other have identical parents. This means that self
|
|
391
|
+
# and other have the same domain and codomain.
|
|
392
|
+
|
|
393
|
+
cdef Parent domain = <Parent?>self.domain()
|
|
394
|
+
e = None
|
|
395
|
+
while True:
|
|
396
|
+
try:
|
|
397
|
+
m = domain.gens
|
|
398
|
+
except AttributeError:
|
|
399
|
+
raise NotImplementedError(f"unable to compare morphisms of type {type(self)} and {type(other)} with domain {domain}")
|
|
400
|
+
gens = m()
|
|
401
|
+
# If e is a ModuleElement, then this is not the first
|
|
402
|
+
# iteration and we are really in the base structure.
|
|
403
|
+
#
|
|
404
|
+
# If so, we see the base as a ring of scalars and create new
|
|
405
|
+
# gens by picking an element of the initial domain (e) and
|
|
406
|
+
# multiplying it with the gens of the scalar ring.
|
|
407
|
+
#
|
|
408
|
+
# It is known that this way of comparing morphisms may give
|
|
409
|
+
# a mathematically wrong answer. See Issue #28617 and #31783.
|
|
410
|
+
if e is not None and isinstance(e, ModuleElement):
|
|
411
|
+
B = (<ModuleElement>e)._parent._base
|
|
412
|
+
gens = [e * B.coerce(x) for x in gens]
|
|
413
|
+
for g in gens:
|
|
414
|
+
x = self(g)
|
|
415
|
+
y = other(g)
|
|
416
|
+
if x != y:
|
|
417
|
+
return richcmp_not_equal(x, y, op)
|
|
418
|
+
if e is None and g:
|
|
419
|
+
e = g
|
|
420
|
+
# Check base
|
|
421
|
+
base = domain._base
|
|
422
|
+
if base is None or base is domain:
|
|
423
|
+
break
|
|
424
|
+
domain = <Parent?>base
|
|
425
|
+
return rich_to_bool(op, 0)
|
|
426
|
+
|
|
427
|
+
def __bool__(self):
|
|
428
|
+
r"""
|
|
429
|
+
Return whether this morphism is not a zero morphism.
|
|
430
|
+
|
|
431
|
+
.. NOTE::
|
|
432
|
+
|
|
433
|
+
Be careful when overriding this method. Often morphisms are used
|
|
434
|
+
(incorrectly) in constructs such as ``if f: # do something`` where
|
|
435
|
+
the author meant to write ``if f is not None: # do something``.
|
|
436
|
+
Having morphisms return ``False`` here can therefore lead to subtle
|
|
437
|
+
bugs.
|
|
438
|
+
|
|
439
|
+
EXAMPLES::
|
|
440
|
+
|
|
441
|
+
sage: f = Hom(ZZ,Zmod(1)).an_element()
|
|
442
|
+
sage: bool(f) # indirect doctest
|
|
443
|
+
False
|
|
444
|
+
"""
|
|
445
|
+
try:
|
|
446
|
+
return self._is_nonzero()
|
|
447
|
+
except Exception:
|
|
448
|
+
return super().__bool__()
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
cdef class FormalCoercionMorphism(Morphism):
|
|
452
|
+
def __init__(self, parent):
|
|
453
|
+
Morphism.__init__(self, parent)
|
|
454
|
+
if not self._codomain.has_coerce_map_from(self.domain()):
|
|
455
|
+
raise TypeError("Natural coercion morphism from {} to {} not defined.".format(self.domain(), self._codomain))
|
|
456
|
+
|
|
457
|
+
def _repr_type(self):
|
|
458
|
+
return "Coercion"
|
|
459
|
+
|
|
460
|
+
cpdef Element _call_(self, x):
|
|
461
|
+
return self._codomain.coerce(x)
|
|
462
|
+
|
|
463
|
+
cdef class CallMorphism(Morphism):
|
|
464
|
+
|
|
465
|
+
def _repr_type(self):
|
|
466
|
+
return "Call"
|
|
467
|
+
|
|
468
|
+
cpdef Element _call_(self, x):
|
|
469
|
+
return self._codomain(x)
|
|
470
|
+
|
|
471
|
+
cdef class IdentityMorphism(Morphism):
|
|
472
|
+
|
|
473
|
+
def __init__(self, parent):
|
|
474
|
+
from sage.categories.homset import Homset, Hom
|
|
475
|
+
if not isinstance(parent, Homset):
|
|
476
|
+
parent = Hom(parent, parent)
|
|
477
|
+
Morphism.__init__(self, parent)
|
|
478
|
+
|
|
479
|
+
def _repr_type(self):
|
|
480
|
+
return "Identity"
|
|
481
|
+
|
|
482
|
+
cpdef Element _call_(self, x):
|
|
483
|
+
return x
|
|
484
|
+
|
|
485
|
+
cpdef Element _call_with_args(self, x, args=(), kwds={}):
|
|
486
|
+
if not args and not kwds:
|
|
487
|
+
return x
|
|
488
|
+
cdef Parent C = self._codomain
|
|
489
|
+
return C._element_constructor(x, *args, **kwds)
|
|
490
|
+
|
|
491
|
+
def __mul__(left, right):
|
|
492
|
+
if not isinstance(right, Map):
|
|
493
|
+
raise TypeError(f"right (={right}) must be a map "
|
|
494
|
+
f"to multiply it by {left}")
|
|
495
|
+
if not isinstance(left, Map):
|
|
496
|
+
raise TypeError(f"left (={left}) must be a map "
|
|
497
|
+
f"to multiply it by {right}")
|
|
498
|
+
if right.codomain() != left.domain():
|
|
499
|
+
raise TypeError(f"self (={left}) domain must equal "
|
|
500
|
+
f"right (={right}) codomain")
|
|
501
|
+
if isinstance(left, IdentityMorphism):
|
|
502
|
+
return right
|
|
503
|
+
else:
|
|
504
|
+
return left
|
|
505
|
+
|
|
506
|
+
cpdef _pow_int(self, n):
|
|
507
|
+
return self
|
|
508
|
+
|
|
509
|
+
def __invert__(self):
|
|
510
|
+
return self
|
|
511
|
+
|
|
512
|
+
def is_identity(self):
|
|
513
|
+
"""
|
|
514
|
+
Return ``True`` if this morphism is the identity morphism.
|
|
515
|
+
|
|
516
|
+
EXAMPLES::
|
|
517
|
+
|
|
518
|
+
sage: E = End(Partitions(5))
|
|
519
|
+
sage: E.identity().is_identity()
|
|
520
|
+
True
|
|
521
|
+
|
|
522
|
+
Check that :issue:`15478` is fixed::
|
|
523
|
+
|
|
524
|
+
sage: # needs sage.rings.finite_rings
|
|
525
|
+
sage: K.<z> = GF(4)
|
|
526
|
+
sage: phi = End(K)([z^2])
|
|
527
|
+
sage: R.<t> = K[]
|
|
528
|
+
sage: psi = End(R)(phi)
|
|
529
|
+
sage: psi.is_identity()
|
|
530
|
+
False
|
|
531
|
+
"""
|
|
532
|
+
return True
|
|
533
|
+
|
|
534
|
+
def section(self):
|
|
535
|
+
"""
|
|
536
|
+
Return a section of this morphism.
|
|
537
|
+
|
|
538
|
+
EXAMPLES::
|
|
539
|
+
|
|
540
|
+
sage: T = Hom(ZZ, ZZ).identity()
|
|
541
|
+
sage: T.section() is T
|
|
542
|
+
True
|
|
543
|
+
"""
|
|
544
|
+
return self
|
|
545
|
+
|
|
546
|
+
def is_surjective(self):
|
|
547
|
+
r"""
|
|
548
|
+
Return whether this morphism is surjective.
|
|
549
|
+
|
|
550
|
+
EXAMPLES::
|
|
551
|
+
|
|
552
|
+
sage: Hom(ZZ, ZZ).identity().is_surjective()
|
|
553
|
+
True
|
|
554
|
+
"""
|
|
555
|
+
return True
|
|
556
|
+
|
|
557
|
+
def is_injective(self):
|
|
558
|
+
r"""
|
|
559
|
+
Return whether this morphism is injective.
|
|
560
|
+
|
|
561
|
+
EXAMPLES::
|
|
562
|
+
|
|
563
|
+
sage: Hom(ZZ, ZZ).identity().is_injective()
|
|
564
|
+
True
|
|
565
|
+
"""
|
|
566
|
+
return True
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
cdef class SetMorphism(Morphism):
|
|
570
|
+
def __init__(self, parent, function):
|
|
571
|
+
"""
|
|
572
|
+
INPUT:
|
|
573
|
+
|
|
574
|
+
- ``parent`` -- a Homset
|
|
575
|
+
- ``function`` -- a Python function that takes elements
|
|
576
|
+
of the domain as input and returns elements of the codomain
|
|
577
|
+
|
|
578
|
+
EXAMPLES::
|
|
579
|
+
|
|
580
|
+
sage: from sage.categories.morphism import SetMorphism
|
|
581
|
+
sage: f = SetMorphism(Hom(QQ, ZZ, Sets()), numerator)
|
|
582
|
+
sage: f.parent()
|
|
583
|
+
Set of Morphisms from Rational Field to Integer Ring in Category of sets
|
|
584
|
+
sage: f.domain()
|
|
585
|
+
Rational Field
|
|
586
|
+
sage: f.codomain()
|
|
587
|
+
Integer Ring
|
|
588
|
+
sage: TestSuite(f).run()
|
|
589
|
+
"""
|
|
590
|
+
Morphism.__init__(self, parent)
|
|
591
|
+
self._function = function
|
|
592
|
+
|
|
593
|
+
cpdef Element _call_(self, x):
|
|
594
|
+
"""
|
|
595
|
+
INPUT:
|
|
596
|
+
|
|
597
|
+
- ``x`` -- an element of ``self.domain()``
|
|
598
|
+
|
|
599
|
+
Returns the result of ``self`` applied on ``x``.
|
|
600
|
+
|
|
601
|
+
EXAMPLES::
|
|
602
|
+
|
|
603
|
+
sage: from sage.categories.morphism import SetMorphism
|
|
604
|
+
sage: f = SetMorphism(Hom(QQ, ZZ, Sets()), numerator) # could use Monoids() once the categories will be in
|
|
605
|
+
sage: f(2/3)
|
|
606
|
+
2
|
|
607
|
+
sage: f(5/4)
|
|
608
|
+
5
|
|
609
|
+
sage: f(3) # todo: this should complain that 3 is not in QQ
|
|
610
|
+
3
|
|
611
|
+
"""
|
|
612
|
+
return self._function(x)
|
|
613
|
+
|
|
614
|
+
cpdef Element _call_with_args(self, x, args=(), kwds={}):
|
|
615
|
+
"""
|
|
616
|
+
Extra arguments are passed to the defining function.
|
|
617
|
+
|
|
618
|
+
TESTS::
|
|
619
|
+
|
|
620
|
+
sage: from sage.categories.morphism import SetMorphism
|
|
621
|
+
sage: R.<x> = QQ[]
|
|
622
|
+
sage: def foo(x, *args, **kwds):
|
|
623
|
+
....: print('foo called with {} {}'.format(args, kwds))
|
|
624
|
+
....: return x
|
|
625
|
+
sage: f = SetMorphism(Hom(R,R,Rings()), foo)
|
|
626
|
+
sage: f(2,'hello world',test=1) # indirect doctest
|
|
627
|
+
foo called with ('hello world',) {'test': 1}
|
|
628
|
+
2
|
|
629
|
+
"""
|
|
630
|
+
try:
|
|
631
|
+
return self._function(x, *args, **kwds)
|
|
632
|
+
except Exception:
|
|
633
|
+
raise TypeError("Underlying map %s does not accept additional arguments" % type(self._function))
|
|
634
|
+
|
|
635
|
+
cdef dict _extra_slots(self):
|
|
636
|
+
"""
|
|
637
|
+
Extend the dictionary with extra slots for this class.
|
|
638
|
+
|
|
639
|
+
INPUT:
|
|
640
|
+
|
|
641
|
+
- ``_slots`` -- dictionary
|
|
642
|
+
|
|
643
|
+
EXAMPLES::
|
|
644
|
+
|
|
645
|
+
sage: f = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__abs__)
|
|
646
|
+
sage: f._extra_slots_test()
|
|
647
|
+
{'_codomain': Integer Ring,
|
|
648
|
+
'_domain': Integer Ring,
|
|
649
|
+
'_function': <built-in function ...abs...>,
|
|
650
|
+
'_is_coercion': False,
|
|
651
|
+
'_repr_type_str': None}
|
|
652
|
+
"""
|
|
653
|
+
slots = Map._extra_slots(self)
|
|
654
|
+
slots['_function'] = self._function
|
|
655
|
+
return slots
|
|
656
|
+
|
|
657
|
+
cdef _update_slots(self, dict _slots):
|
|
658
|
+
"""
|
|
659
|
+
INPUT:
|
|
660
|
+
|
|
661
|
+
- ``_slots`` -- dictionary
|
|
662
|
+
|
|
663
|
+
Updates the slots of ``self`` from the data in the dictionary
|
|
664
|
+
|
|
665
|
+
EXAMPLES::
|
|
666
|
+
|
|
667
|
+
sage: f = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__abs__)
|
|
668
|
+
sage: f(3)
|
|
669
|
+
3
|
|
670
|
+
sage: f._update_slots_test({'_function' : operator.__neg__,
|
|
671
|
+
....: '_domain' : QQ,
|
|
672
|
+
....: '_codomain' : QQ,
|
|
673
|
+
....: '_repr_type_str' : 'bla'})
|
|
674
|
+
sage: f(3)
|
|
675
|
+
-3
|
|
676
|
+
sage: f._repr_type()
|
|
677
|
+
'bla'
|
|
678
|
+
sage: f.domain()
|
|
679
|
+
Rational Field
|
|
680
|
+
sage: f.codomain()
|
|
681
|
+
Rational Field
|
|
682
|
+
"""
|
|
683
|
+
self._function = _slots['_function']
|
|
684
|
+
Map._update_slots(self, _slots)
|
|
685
|
+
|
|
686
|
+
cpdef bint _eq_c_impl(self, Element other) noexcept:
|
|
687
|
+
"""
|
|
688
|
+
Equality test.
|
|
689
|
+
|
|
690
|
+
EXAMPLES::
|
|
691
|
+
|
|
692
|
+
sage: f = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__abs__)
|
|
693
|
+
sage: g = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__abs__)
|
|
694
|
+
sage: h = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Rings()), operator.__abs__) # todo: replace by the more correct Monoids
|
|
695
|
+
sage: i = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__neg__)
|
|
696
|
+
sage: f._eq_c_impl(g)
|
|
697
|
+
True
|
|
698
|
+
sage: f._eq_c_impl(h)
|
|
699
|
+
False
|
|
700
|
+
sage: f._eq_c_impl(i)
|
|
701
|
+
False
|
|
702
|
+
sage: f._eq_c_impl(1)
|
|
703
|
+
False
|
|
704
|
+
"""
|
|
705
|
+
return isinstance(other, SetMorphism) and self.parent() == other.parent() and self._function == (<SetMorphism>other)._function
|
|
706
|
+
|
|
707
|
+
def __richcmp__(self, right, int op):
|
|
708
|
+
"""
|
|
709
|
+
INPUT:
|
|
710
|
+
|
|
711
|
+
- ``self`` -- SetMorphism
|
|
712
|
+
- ``right`` -- any object
|
|
713
|
+
- ``op`` -- integer
|
|
714
|
+
|
|
715
|
+
EXAMPLES::
|
|
716
|
+
|
|
717
|
+
sage: f = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__abs__)
|
|
718
|
+
sage: g = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__abs__)
|
|
719
|
+
sage: h = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Rings()), operator.__abs__) # todo: replace by the more correct Monoids
|
|
720
|
+
sage: i = sage.categories.morphism.SetMorphism(Hom(ZZ,ZZ, Sets()), operator.__neg__)
|
|
721
|
+
sage: f == f, f != f, f < f, f > f, f <= f, f >= f
|
|
722
|
+
(True, False, False, False, True, True)
|
|
723
|
+
sage: f == g, f != g, f < g, f > g, f <= g, f >= g
|
|
724
|
+
(True, False, False, False, True, True)
|
|
725
|
+
sage: f == h, f != h, f < h, f > h, f <= h, f >= h
|
|
726
|
+
(False, True, False, False, False, False)
|
|
727
|
+
sage: f == i, f != i, f < i, f > i, f <= i, f >= i
|
|
728
|
+
(False, True, False, False, False, False)
|
|
729
|
+
sage: f == 0, f == int(0), f is None
|
|
730
|
+
(False, False, False)
|
|
731
|
+
sage: f != 0, f != int(0), f is not None
|
|
732
|
+
(True, True, True)
|
|
733
|
+
"""
|
|
734
|
+
if op == Py_EQ or op == Py_LE or op == Py_GE:
|
|
735
|
+
return isinstance(right, Element) and self._eq_c_impl(right)
|
|
736
|
+
elif op == Py_NE:
|
|
737
|
+
return not (isinstance(right, Element) and self._eq_c_impl(right))
|
|
738
|
+
else:
|
|
739
|
+
return False
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
cdef class SetIsomorphism(SetMorphism):
|
|
743
|
+
r"""
|
|
744
|
+
An isomorphism of sets.
|
|
745
|
+
|
|
746
|
+
INPUT:
|
|
747
|
+
|
|
748
|
+
- ``parent`` -- a Homset
|
|
749
|
+
- ``function`` -- a Python function that takes elements
|
|
750
|
+
of the domain as input and returns elements of the codomain
|
|
751
|
+
|
|
752
|
+
EXAMPLES::
|
|
753
|
+
|
|
754
|
+
sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
|
|
755
|
+
....: operator.__neg__); f
|
|
756
|
+
Generic endomorphism of Integer Ring
|
|
757
|
+
sage: f._set_inverse(f)
|
|
758
|
+
sage: ~f is f
|
|
759
|
+
True
|
|
760
|
+
"""
|
|
761
|
+
def _set_inverse(self, inverse):
|
|
762
|
+
r"""
|
|
763
|
+
Set the inverse morphism of ``self`` to be ``inverse``.
|
|
764
|
+
|
|
765
|
+
INPUT:
|
|
766
|
+
|
|
767
|
+
- ``inverse`` -- a :class:`SetIsomorphism`
|
|
768
|
+
|
|
769
|
+
EXAMPLES::
|
|
770
|
+
|
|
771
|
+
sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
|
|
772
|
+
....: operator.__neg__)
|
|
773
|
+
sage: f._set_inverse(f)
|
|
774
|
+
sage: ~f is f
|
|
775
|
+
True
|
|
776
|
+
"""
|
|
777
|
+
self._inverse = inverse
|
|
778
|
+
|
|
779
|
+
def __invert__(self):
|
|
780
|
+
r"""
|
|
781
|
+
Return the inverse morphism of ``self``.
|
|
782
|
+
|
|
783
|
+
If :meth:`_set_inverse` has not been called yet, an error is raised.
|
|
784
|
+
|
|
785
|
+
EXAMPLES::
|
|
786
|
+
|
|
787
|
+
sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
|
|
788
|
+
....: operator.__neg__)
|
|
789
|
+
sage: ~f
|
|
790
|
+
Traceback (most recent call last):
|
|
791
|
+
...
|
|
792
|
+
RuntimeError: inverse morphism has not been set
|
|
793
|
+
sage: f._set_inverse(f)
|
|
794
|
+
sage: ~f
|
|
795
|
+
Generic endomorphism of Integer Ring
|
|
796
|
+
"""
|
|
797
|
+
if not self._inverse:
|
|
798
|
+
raise RuntimeError('inverse morphism has not been set')
|
|
799
|
+
return self._inverse
|
|
800
|
+
|
|
801
|
+
cdef dict _extra_slots(self):
|
|
802
|
+
"""
|
|
803
|
+
Extend the dictionary with extra slots for this class.
|
|
804
|
+
|
|
805
|
+
INPUT:
|
|
806
|
+
|
|
807
|
+
- ``_slots`` -- dictionary
|
|
808
|
+
|
|
809
|
+
EXAMPLES::
|
|
810
|
+
|
|
811
|
+
sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
|
|
812
|
+
....: operator.__neg__)
|
|
813
|
+
sage: f._set_inverse(f)
|
|
814
|
+
sage: f._extra_slots_test()
|
|
815
|
+
{'_codomain': Integer Ring,
|
|
816
|
+
'_domain': Integer Ring,
|
|
817
|
+
'_function': <built-in function neg>,
|
|
818
|
+
'_inverse': Generic endomorphism of Integer Ring,
|
|
819
|
+
'_is_coercion': False,
|
|
820
|
+
'_repr_type_str': None}
|
|
821
|
+
"""
|
|
822
|
+
slots = SetMorphism._extra_slots(self)
|
|
823
|
+
slots['_inverse'] = self._inverse
|
|
824
|
+
return slots
|
|
825
|
+
|
|
826
|
+
cdef _update_slots(self, dict _slots):
|
|
827
|
+
"""
|
|
828
|
+
Update the slots of ``self`` from the data in the dictionary.
|
|
829
|
+
|
|
830
|
+
INPUT:
|
|
831
|
+
|
|
832
|
+
- ``_slots`` -- dictionary
|
|
833
|
+
|
|
834
|
+
EXAMPLES::
|
|
835
|
+
|
|
836
|
+
sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
|
|
837
|
+
....: operator.__neg__)
|
|
838
|
+
sage: f._update_slots_test({'_function': operator.__neg__,
|
|
839
|
+
....: '_inverse': f,
|
|
840
|
+
....: '_domain': QQ,
|
|
841
|
+
....: '_codomain': QQ,
|
|
842
|
+
....: '_repr_type_str': 'bla'})
|
|
843
|
+
sage: f(3)
|
|
844
|
+
-3
|
|
845
|
+
sage: f._repr_type()
|
|
846
|
+
'bla'
|
|
847
|
+
sage: f.domain()
|
|
848
|
+
Rational Field
|
|
849
|
+
sage: f.codomain()
|
|
850
|
+
Rational Field
|
|
851
|
+
sage: f.inverse() == f
|
|
852
|
+
True
|
|
853
|
+
"""
|
|
854
|
+
self._inverse = _slots['_inverse']
|
|
855
|
+
SetMorphism._update_slots(self, _slots)
|
|
856
|
+
|
|
857
|
+
def section(self):
|
|
858
|
+
"""
|
|
859
|
+
Return a section of this morphism.
|
|
860
|
+
|
|
861
|
+
EXAMPLES::
|
|
862
|
+
|
|
863
|
+
sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
|
|
864
|
+
....: operator.__neg__)
|
|
865
|
+
sage: f._set_inverse(f)
|
|
866
|
+
sage: f.section() is f
|
|
867
|
+
True
|
|
868
|
+
"""
|
|
869
|
+
return self.__invert__()
|
|
870
|
+
|
|
871
|
+
def is_surjective(self):
|
|
872
|
+
r"""
|
|
873
|
+
Return whether this morphism is surjective.
|
|
874
|
+
|
|
875
|
+
EXAMPLES::
|
|
876
|
+
|
|
877
|
+
sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
|
|
878
|
+
....: operator.__neg__)
|
|
879
|
+
sage: f.is_surjective()
|
|
880
|
+
True
|
|
881
|
+
"""
|
|
882
|
+
return True
|
|
883
|
+
|
|
884
|
+
def is_injective(self):
|
|
885
|
+
r"""
|
|
886
|
+
Return whether this morphism is injective.
|
|
887
|
+
|
|
888
|
+
EXAMPLES::
|
|
889
|
+
|
|
890
|
+
sage: f = sage.categories.morphism.SetIsomorphism(Hom(ZZ, ZZ, Sets()),
|
|
891
|
+
....: operator.__neg__)
|
|
892
|
+
sage: f.is_injective()
|
|
893
|
+
True
|
|
894
|
+
"""
|
|
895
|
+
return True
|