passagemath-objects 10.6.45__cp313-cp313-musllinux_1_2_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.
Potentially problematic release.
This version of passagemath-objects might be problematic. Click here for more details.
- passagemath_objects/__init__.py +3 -0
- passagemath_objects-10.6.45.dist-info/METADATA +115 -0
- passagemath_objects-10.6.45.dist-info/RECORD +280 -0
- passagemath_objects-10.6.45.dist-info/WHEEL +5 -0
- passagemath_objects-10.6.45.dist-info/top_level.txt +3 -0
- passagemath_objects.libs/libgmp-0e7fc84e.so.10.5.0 +0 -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-313-x86_64-linux-musl.so +0 -0
- sage/arith/numerical_approx.pxd +35 -0
- sage/arith/numerical_approx.pyx +75 -0
- sage/arith/power.cpython-313-x86_64-linux-musl.so +0 -0
- sage/arith/power.pxd +31 -0
- sage/arith/power.pyx +127 -0
- sage/categories/action.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/categories/category_cy_helper.pxd +8 -0
- sage/categories/category_cy_helper.pyx +322 -0
- sage/categories/category_singleton.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/categories/map.pxd +34 -0
- sage/categories/map.pyx +2106 -0
- sage/categories/morphism.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/cpython/atexit.pyx +269 -0
- sage/cpython/builtin_types.cpython-313-x86_64-linux-musl.so +0 -0
- sage/cpython/builtin_types.pyx +7 -0
- sage/cpython/cython_metaclass.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/cpython/debug.pyx +302 -0
- sage/cpython/dict_del_by_value.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.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-313-x86_64-linux-musl.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-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/groups/group.pxd +14 -0
- sage/groups/group.pyx +322 -0
- sage/groups/old.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/misc/c3_controlled.pxd +2 -0
- sage/misc/c3_controlled.pyx +1402 -0
- sage/misc/cachefunc.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/misc/classcall_metaclass.pxd +14 -0
- sage/misc/classcall_metaclass.pyx +599 -0
- sage/misc/constant_function.cpython-313-x86_64-linux-musl.so +0 -0
- sage/misc/constant_function.pyx +130 -0
- sage/misc/decorators.py +747 -0
- sage/misc/fast_methods.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/misc/fpickle.pyx +177 -0
- sage/misc/function_mangling.cpython-313-x86_64-linux-musl.so +0 -0
- sage/misc/function_mangling.pxd +11 -0
- sage/misc/function_mangling.pyx +308 -0
- sage/misc/inherit_comparison.cpython-313-x86_64-linux-musl.so +0 -0
- sage/misc/inherit_comparison.pxd +5 -0
- sage/misc/inherit_comparison.pyx +105 -0
- sage/misc/instancedoc.cpython-313-x86_64-linux-musl.so +0 -0
- sage/misc/instancedoc.pyx +331 -0
- sage/misc/lazy_attribute.cpython-313-x86_64-linux-musl.so +0 -0
- sage/misc/lazy_attribute.pyx +607 -0
- sage/misc/lazy_format.py +135 -0
- sage/misc/lazy_import.cpython-313-x86_64-linux-musl.so +0 -0
- sage/misc/lazy_import.pyx +1299 -0
- sage/misc/lazy_import_cache.py +36 -0
- sage/misc/lazy_list.cpython-313-x86_64-linux-musl.so +0 -0
- sage/misc/lazy_list.pxd +19 -0
- sage/misc/lazy_list.pyx +1187 -0
- sage/misc/lazy_string.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/misc/nested_class.pxd +3 -0
- sage/misc/nested_class.pyx +394 -0
- sage/misc/persist.cpython-313-x86_64-linux-musl.so +0 -0
- sage/misc/persist.pyx +1251 -0
- sage/misc/prandom.py +418 -0
- sage/misc/randstate.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/misc/reset.pyx +196 -0
- sage/misc/sage_ostools.cpython-313-x86_64-linux-musl.so +0 -0
- sage/misc/sage_ostools.pyx +323 -0
- sage/misc/sage_timeit.py +275 -0
- sage/misc/sage_timeit_class.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.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-313-x86_64-linux-musl.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-313-x86_64-linux-musl.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-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/structure/category_object.pxd +28 -0
- sage/structure/category_object.pyx +1087 -0
- sage/structure/coerce.cpython-313-x86_64-linux-musl.so +0 -0
- sage/structure/coerce.pxd +44 -0
- sage/structure/coerce.pyx +2107 -0
- sage/structure/coerce_actions.cpython-313-x86_64-linux-musl.so +0 -0
- sage/structure/coerce_actions.pxd +27 -0
- sage/structure/coerce_actions.pyx +988 -0
- sage/structure/coerce_dict.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/structure/coerce_maps.pxd +28 -0
- sage/structure/coerce_maps.pyx +718 -0
- sage/structure/debug_options.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/structure/element.pxd +272 -0
- sage/structure/element.pyx +4772 -0
- sage/structure/element_wrapper.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/structure/list_clone.pxd +65 -0
- sage/structure/list_clone.pyx +1867 -0
- sage/structure/list_clone_demo.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/structure/list_clone_timings_cy.pyx +86 -0
- sage/structure/mutability.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/structure/parent.pxd +112 -0
- sage/structure/parent.pyx +3093 -0
- sage/structure/parent_base.cpython-313-x86_64-linux-musl.so +0 -0
- sage/structure/parent_base.pxd +13 -0
- sage/structure/parent_base.pyx +44 -0
- sage/structure/parent_gens.cpython-313-x86_64-linux-musl.so +0 -0
- sage/structure/parent_gens.pxd +22 -0
- sage/structure/parent_gens.pyx +377 -0
- sage/structure/parent_old.cpython-313-x86_64-linux-musl.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-313-x86_64-linux-musl.so +0 -0
- sage/structure/richcmp.pxd +213 -0
- sage/structure/richcmp.pyx +495 -0
- sage/structure/sage_object.cpython-313-x86_64-linux-musl.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,1087 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-objects
|
|
2
|
+
# cython: old_style_globals=True
|
|
3
|
+
r"""
|
|
4
|
+
Base class for objects of a category
|
|
5
|
+
|
|
6
|
+
CLASS HIERARCHY:
|
|
7
|
+
|
|
8
|
+
- :class:`~sage.structure.sage_object.SageObject`
|
|
9
|
+
|
|
10
|
+
- **CategoryObject**
|
|
11
|
+
|
|
12
|
+
- :class:`~sage.structure.parent.Parent`
|
|
13
|
+
|
|
14
|
+
Many category objects in Sage are equipped with generators, which are
|
|
15
|
+
usually special elements of the object. For example, the polynomial ring
|
|
16
|
+
`\ZZ[x,y,z]` is generated by `x`, `y`, and `z`. In Sage the ``i`` th
|
|
17
|
+
generator of an object ``X`` is obtained using the notation
|
|
18
|
+
``X.gen(i)``. From the Sage interactive prompt, the shorthand
|
|
19
|
+
notation ``X.i`` is also allowed.
|
|
20
|
+
|
|
21
|
+
The following examples illustrate these functions in the context of
|
|
22
|
+
multivariate polynomial rings and free modules.
|
|
23
|
+
|
|
24
|
+
EXAMPLES::
|
|
25
|
+
|
|
26
|
+
sage: R = PolynomialRing(ZZ, 3, 'x')
|
|
27
|
+
sage: R.ngens()
|
|
28
|
+
3
|
|
29
|
+
sage: R.gen(0)
|
|
30
|
+
x0
|
|
31
|
+
sage: R.gens()
|
|
32
|
+
(x0, x1, x2)
|
|
33
|
+
sage: R.variable_names()
|
|
34
|
+
('x0', 'x1', 'x2')
|
|
35
|
+
|
|
36
|
+
This example illustrates generators for a free module over `\ZZ`.
|
|
37
|
+
|
|
38
|
+
::
|
|
39
|
+
|
|
40
|
+
sage: # needs sage.modules
|
|
41
|
+
sage: M = FreeModule(ZZ, 4)
|
|
42
|
+
sage: M
|
|
43
|
+
Ambient free module of rank 4 over the principal ideal domain Integer Ring
|
|
44
|
+
sage: M.ngens()
|
|
45
|
+
4
|
|
46
|
+
sage: M.gen(0)
|
|
47
|
+
(1, 0, 0, 0)
|
|
48
|
+
sage: M.gens()
|
|
49
|
+
((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1))
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
# ****************************************************************************
|
|
53
|
+
# This program is free software: you can redistribute it and/or modify
|
|
54
|
+
# it under the terms of the GNU General Public License as published by
|
|
55
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
56
|
+
# (at your option) any later version.
|
|
57
|
+
# https://www.gnu.org/licenses/
|
|
58
|
+
# ****************************************************************************
|
|
59
|
+
|
|
60
|
+
from sage.cpython.getattr import dir_with_other_class
|
|
61
|
+
from sage.cpython.getattr cimport getattr_from_other_class
|
|
62
|
+
from sage.categories.category import Category
|
|
63
|
+
from sage.misc.cachefunc import cached_method
|
|
64
|
+
from sage.structure.dynamic_class import DynamicMetaclass
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
cpdef inline check_default_category(default_category, category):
|
|
68
|
+
"""
|
|
69
|
+
The resulting category is guaranteed to be
|
|
70
|
+
a sub-category of the default.
|
|
71
|
+
"""
|
|
72
|
+
if category is None:
|
|
73
|
+
return default_category
|
|
74
|
+
return default_category.join([default_category, category])
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
cdef class CategoryObject(SageObject):
|
|
78
|
+
"""
|
|
79
|
+
An object in some category.
|
|
80
|
+
"""
|
|
81
|
+
def __init__(self, category=None, base=None):
|
|
82
|
+
"""
|
|
83
|
+
Initialize an object in a category.
|
|
84
|
+
|
|
85
|
+
INPUT:
|
|
86
|
+
|
|
87
|
+
- ``category`` -- the category this object belongs to; if this object
|
|
88
|
+
belongs to multiple categories, those can be passed as a tuple
|
|
89
|
+
- ``base`` -- if this object has another object that should be
|
|
90
|
+
considered a base in its primary category, you can include that base
|
|
91
|
+
here
|
|
92
|
+
|
|
93
|
+
EXAMPLES::
|
|
94
|
+
|
|
95
|
+
sage: from sage.structure.category_object import CategoryObject
|
|
96
|
+
sage: A = CategoryObject()
|
|
97
|
+
sage: A.category()
|
|
98
|
+
Category of objects
|
|
99
|
+
sage: A.base()
|
|
100
|
+
|
|
101
|
+
sage: A = CategoryObject(category = Rings(), base = QQ)
|
|
102
|
+
sage: A.category()
|
|
103
|
+
Category of rings
|
|
104
|
+
sage: A.base()
|
|
105
|
+
Rational Field
|
|
106
|
+
|
|
107
|
+
sage: A = CategoryObject(category = (Semigroups(), CommutativeAdditiveSemigroups()))
|
|
108
|
+
sage: A.category()
|
|
109
|
+
Join of Category of semigroups and Category of commutative additive semigroups
|
|
110
|
+
|
|
111
|
+
FIXME: the base and generators attributes have nothing to do with categories, do they?
|
|
112
|
+
"""
|
|
113
|
+
if base is not None:
|
|
114
|
+
self._base = base
|
|
115
|
+
if category is not None:
|
|
116
|
+
self._init_category_(category)
|
|
117
|
+
|
|
118
|
+
def __cinit__(self):
|
|
119
|
+
self._cached_methods = {}
|
|
120
|
+
self._hash_value = -1
|
|
121
|
+
|
|
122
|
+
def _init_category_(self, category):
|
|
123
|
+
"""
|
|
124
|
+
Set the category or categories of this object.
|
|
125
|
+
|
|
126
|
+
INPUT:
|
|
127
|
+
|
|
128
|
+
- ``category`` -- a category, or list or tuple thereof
|
|
129
|
+
|
|
130
|
+
EXAMPLES::
|
|
131
|
+
|
|
132
|
+
sage: A = sage.structure.category_object.CategoryObject()
|
|
133
|
+
sage: A._init_category_(Rings())
|
|
134
|
+
sage: A.category()
|
|
135
|
+
Category of rings
|
|
136
|
+
sage: A._init_category_((Semigroups(), CommutativeAdditiveSemigroups()))
|
|
137
|
+
sage: A.category()
|
|
138
|
+
Join of Category of semigroups and Category of commutative additive semigroups
|
|
139
|
+
sage: P = Parent(category=None)
|
|
140
|
+
sage: P.category()
|
|
141
|
+
Category of sets
|
|
142
|
+
|
|
143
|
+
TESTS::
|
|
144
|
+
|
|
145
|
+
sage: A = sage.structure.category_object.CategoryObject()
|
|
146
|
+
sage: A._init_category_(None)
|
|
147
|
+
Traceback (most recent call last):
|
|
148
|
+
...
|
|
149
|
+
TypeError: CategoryObject of type CategoryObject requires a Category, list or tuple, not NoneType
|
|
150
|
+
"""
|
|
151
|
+
if isinstance(category, Category):
|
|
152
|
+
self._category = category
|
|
153
|
+
elif isinstance(category, (list, tuple)):
|
|
154
|
+
self._category = Category.join(category)
|
|
155
|
+
else:
|
|
156
|
+
raise TypeError(f"CategoryObject of type {type(self).__name__} requires a Category, list or tuple, not {type(category).__name__}")
|
|
157
|
+
|
|
158
|
+
def _refine_category_(self, category):
|
|
159
|
+
"""
|
|
160
|
+
Change the category of ``self`` into a subcategory.
|
|
161
|
+
|
|
162
|
+
INPUT:
|
|
163
|
+
|
|
164
|
+
- ``category`` -- a category or list or tuple thereof
|
|
165
|
+
|
|
166
|
+
The new category is obtained by adjoining ``category`` to the
|
|
167
|
+
current one.
|
|
168
|
+
|
|
169
|
+
.. SEEALSO:: :function:`Category.join`
|
|
170
|
+
|
|
171
|
+
EXAMPLES::
|
|
172
|
+
|
|
173
|
+
sage: P = Parent()
|
|
174
|
+
sage: P.category()
|
|
175
|
+
Category of sets
|
|
176
|
+
sage: P._refine_category_(Magmas())
|
|
177
|
+
sage: P.category()
|
|
178
|
+
Category of magmas
|
|
179
|
+
sage: P._refine_category_(Magmas())
|
|
180
|
+
sage: P.category()
|
|
181
|
+
Category of magmas
|
|
182
|
+
sage: P._refine_category_(EnumeratedSets())
|
|
183
|
+
sage: P.category()
|
|
184
|
+
Category of enumerated magmas
|
|
185
|
+
sage: P._refine_category_([Semigroups(), CommutativeAdditiveSemigroups()])
|
|
186
|
+
sage: P.category()
|
|
187
|
+
Join of Category of semigroups and Category of commutative additive semigroups and Category of enumerated sets
|
|
188
|
+
sage: P._refine_category_((CommutativeAdditiveMonoids(), Monoids()))
|
|
189
|
+
sage: P.category()
|
|
190
|
+
Join of Category of monoids and Category of commutative additive monoids and Category of enumerated sets
|
|
191
|
+
"""
|
|
192
|
+
if self._category is None:
|
|
193
|
+
self._init_category_(category)
|
|
194
|
+
return
|
|
195
|
+
if not isinstance(category, (tuple, list)):
|
|
196
|
+
category = [category]
|
|
197
|
+
self._category = self._category.join([self._category]+list(category))
|
|
198
|
+
|
|
199
|
+
def _is_category_initialized(self):
|
|
200
|
+
return self._category is not None
|
|
201
|
+
|
|
202
|
+
def category(self):
|
|
203
|
+
if self._category is None:
|
|
204
|
+
# COERCE TODO: we shouldn't need this
|
|
205
|
+
from sage.categories.objects import Objects
|
|
206
|
+
self._category = Objects()
|
|
207
|
+
return self._category
|
|
208
|
+
|
|
209
|
+
def categories(self):
|
|
210
|
+
"""
|
|
211
|
+
Return the categories of ``self``.
|
|
212
|
+
|
|
213
|
+
EXAMPLES::
|
|
214
|
+
|
|
215
|
+
sage: ZZ.categories()
|
|
216
|
+
[Join of Category of Dedekind domains
|
|
217
|
+
and Category of euclidean domains
|
|
218
|
+
and Category of noetherian rings
|
|
219
|
+
and Category of infinite enumerated sets
|
|
220
|
+
and Category of metric spaces,
|
|
221
|
+
Category of Dedekind domains,
|
|
222
|
+
Category of euclidean domains,
|
|
223
|
+
Category of principal ideal domains,
|
|
224
|
+
Category of unique factorization domains,
|
|
225
|
+
Category of gcd domains,
|
|
226
|
+
Category of integral domains,
|
|
227
|
+
Category of domains, ...
|
|
228
|
+
Category of commutative rings, ...
|
|
229
|
+
Category of monoids, ...,
|
|
230
|
+
Category of commutative additive groups, ...,
|
|
231
|
+
Category of sets, ...,
|
|
232
|
+
Category of objects]
|
|
233
|
+
"""
|
|
234
|
+
return self.category().all_super_categories()
|
|
235
|
+
|
|
236
|
+
def _underlying_class(self):
|
|
237
|
+
r"""
|
|
238
|
+
Return the underlying class (class without the attached
|
|
239
|
+
categories) of the given object.
|
|
240
|
+
|
|
241
|
+
OUTPUT: a class
|
|
242
|
+
|
|
243
|
+
EXAMPLES::
|
|
244
|
+
|
|
245
|
+
sage: type(QQ)
|
|
246
|
+
<class 'sage.rings.rational_field.RationalField_with_category'>
|
|
247
|
+
sage: QQ._underlying_class()
|
|
248
|
+
<class 'sage.rings.rational_field.RationalField'>
|
|
249
|
+
sage: type(ZZ)
|
|
250
|
+
<... 'sage.rings.integer_ring.IntegerRing_class'>
|
|
251
|
+
sage: ZZ._underlying_class()
|
|
252
|
+
<... 'sage.rings.integer_ring.IntegerRing_class'>
|
|
253
|
+
"""
|
|
254
|
+
cls = type(self)
|
|
255
|
+
if isinstance(cls, DynamicMetaclass):
|
|
256
|
+
return cls.__bases__[0]
|
|
257
|
+
else:
|
|
258
|
+
return cls
|
|
259
|
+
|
|
260
|
+
##############################################################################
|
|
261
|
+
# Generators
|
|
262
|
+
##############################################################################
|
|
263
|
+
|
|
264
|
+
@cached_method
|
|
265
|
+
def __gens_dict(self):
|
|
266
|
+
cdef dict v = {}
|
|
267
|
+
for x in self._defining_names():
|
|
268
|
+
v[str(x)] = x
|
|
269
|
+
return v
|
|
270
|
+
|
|
271
|
+
def gens_dict(self, *, copy=True):
|
|
272
|
+
r"""
|
|
273
|
+
Return a dictionary whose entries are ``{name:variable,...}``,
|
|
274
|
+
where ``name`` stands for the variable names of this
|
|
275
|
+
object (as strings) and ``variable`` stands for the
|
|
276
|
+
corresponding defining generators (as elements of this object).
|
|
277
|
+
|
|
278
|
+
EXAMPLES::
|
|
279
|
+
|
|
280
|
+
sage: B.<a,b,c,d> = BooleanPolynomialRing() # needs sage.rings.polynomial.pbori
|
|
281
|
+
sage: B.gens_dict() # needs sage.rings.polynomial.pbori
|
|
282
|
+
{'a': a, 'b': b, 'c': c, 'd': d}
|
|
283
|
+
|
|
284
|
+
TESTS::
|
|
285
|
+
|
|
286
|
+
sage: B.<a,b,c,d> = PolynomialRing(QQ)
|
|
287
|
+
sage: B.gens_dict(copy=False) is B.gens_dict(copy=False)
|
|
288
|
+
True
|
|
289
|
+
sage: B.gens_dict(copy=False) is B.gens_dict()
|
|
290
|
+
False
|
|
291
|
+
"""
|
|
292
|
+
if copy:
|
|
293
|
+
return dict(self.__gens_dict())
|
|
294
|
+
else:
|
|
295
|
+
return self.__gens_dict()
|
|
296
|
+
|
|
297
|
+
def gens_dict_recursive(self):
|
|
298
|
+
r"""
|
|
299
|
+
Return the dictionary of generators of ``self`` and its base rings.
|
|
300
|
+
|
|
301
|
+
OUTPUT:
|
|
302
|
+
|
|
303
|
+
- a dictionary with string names of generators as keys and
|
|
304
|
+
generators of ``self`` and its base rings as values.
|
|
305
|
+
|
|
306
|
+
EXAMPLES::
|
|
307
|
+
|
|
308
|
+
sage: R = QQ['x,y']['z,w']
|
|
309
|
+
sage: sorted(R.gens_dict_recursive().items())
|
|
310
|
+
[('w', w), ('x', x), ('y', y), ('z', z)]
|
|
311
|
+
"""
|
|
312
|
+
B = self.base_ring()
|
|
313
|
+
if B is self:
|
|
314
|
+
return {}
|
|
315
|
+
GDR = B.gens_dict_recursive()
|
|
316
|
+
GDR.update(self.gens_dict())
|
|
317
|
+
return GDR
|
|
318
|
+
|
|
319
|
+
def objgens(self):
|
|
320
|
+
"""
|
|
321
|
+
Return the tuple ``(self, self.gens())``.
|
|
322
|
+
|
|
323
|
+
EXAMPLES::
|
|
324
|
+
|
|
325
|
+
sage: R = PolynomialRing(QQ, 3, 'x'); R
|
|
326
|
+
Multivariate Polynomial Ring in x0, x1, x2 over Rational Field
|
|
327
|
+
sage: R.objgens()
|
|
328
|
+
(Multivariate Polynomial Ring in x0, x1, x2 over Rational Field, (x0, x1, x2))
|
|
329
|
+
"""
|
|
330
|
+
return self, self.gens()
|
|
331
|
+
|
|
332
|
+
def objgen(self):
|
|
333
|
+
"""
|
|
334
|
+
Return the tuple ``(self, self.gen())``.
|
|
335
|
+
|
|
336
|
+
EXAMPLES::
|
|
337
|
+
|
|
338
|
+
sage: R, x = PolynomialRing(QQ,'x').objgen()
|
|
339
|
+
sage: R
|
|
340
|
+
Univariate Polynomial Ring in x over Rational Field
|
|
341
|
+
sage: x
|
|
342
|
+
x
|
|
343
|
+
"""
|
|
344
|
+
return self, self.gen()
|
|
345
|
+
|
|
346
|
+
def _first_ngens(self, n):
|
|
347
|
+
"""
|
|
348
|
+
Used by the preparser for ``R.<x> = ...``.
|
|
349
|
+
|
|
350
|
+
EXAMPLES::
|
|
351
|
+
|
|
352
|
+
sage: R.<x> = PolynomialRing(QQ)
|
|
353
|
+
sage: x
|
|
354
|
+
x
|
|
355
|
+
sage: parent(x)
|
|
356
|
+
Univariate Polynomial Ring in x over Rational Field
|
|
357
|
+
|
|
358
|
+
For orders, we correctly use the ring generator, see
|
|
359
|
+
:issue:`15348`::
|
|
360
|
+
|
|
361
|
+
sage: A.<i> = ZZ.extension(x^2 + 1) # needs sage.rings.number_field
|
|
362
|
+
sage: i # needs sage.rings.number_field
|
|
363
|
+
i
|
|
364
|
+
sage: parent(i) # needs sage.rings.number_field
|
|
365
|
+
Gaussian Integers generated by i
|
|
366
|
+
in Number Field in i with defining polynomial x^2 + 1
|
|
367
|
+
|
|
368
|
+
::
|
|
369
|
+
|
|
370
|
+
sage: B.<z> = EquationOrder(x^2 + 3) # needs sage.rings.number_field
|
|
371
|
+
sage: z.minpoly() # needs sage.rings.number_field
|
|
372
|
+
x^2 + 3
|
|
373
|
+
"""
|
|
374
|
+
names = self._defining_names()
|
|
375
|
+
if isinstance(names, (list, tuple)):
|
|
376
|
+
return names[:n]
|
|
377
|
+
# case of Family
|
|
378
|
+
it = iter(names)
|
|
379
|
+
return tuple(next(it) for i in range(n))
|
|
380
|
+
|
|
381
|
+
@cached_method
|
|
382
|
+
def _defining_names(self):
|
|
383
|
+
"""
|
|
384
|
+
The elements used to "define" this object.
|
|
385
|
+
|
|
386
|
+
What this means depends on the type of object: for rings, it
|
|
387
|
+
usually means generators as a ring. The result of this function
|
|
388
|
+
is not required to generate the object, but it should contain
|
|
389
|
+
all named elements if the object was constructed using a
|
|
390
|
+
``names'' argument.
|
|
391
|
+
|
|
392
|
+
This function is used by the preparser to implement
|
|
393
|
+
``R.<x> = ...`` and it is also used by :meth:`gens_dict`.
|
|
394
|
+
|
|
395
|
+
EXAMPLES::
|
|
396
|
+
|
|
397
|
+
sage: R.<x> = PolynomialRing(QQ)
|
|
398
|
+
sage: R._defining_names()
|
|
399
|
+
(x,)
|
|
400
|
+
|
|
401
|
+
For orders, we correctly use the ring generator, see
|
|
402
|
+
:issue:`15348`::
|
|
403
|
+
|
|
404
|
+
sage: B.<z> = EquationOrder(x^2 + 3) # needs sage.rings.number_field
|
|
405
|
+
sage: B._defining_names() # needs sage.rings.number_field
|
|
406
|
+
(z,)
|
|
407
|
+
|
|
408
|
+
For vector spaces and free modules, we get a basis (which can
|
|
409
|
+
be different from the given generators)::
|
|
410
|
+
|
|
411
|
+
sage: # needs sage.modules
|
|
412
|
+
sage: V = ZZ^3
|
|
413
|
+
sage: V._defining_names()
|
|
414
|
+
((1, 0, 0), (0, 1, 0), (0, 0, 1))
|
|
415
|
+
sage: W = V.span([(0, 1, 0), (1/2, 1, 0)])
|
|
416
|
+
sage: W._defining_names()
|
|
417
|
+
((1/2, 0, 0), (0, 1, 0))
|
|
418
|
+
"""
|
|
419
|
+
return self.gens()
|
|
420
|
+
|
|
421
|
+
#################################################################################################
|
|
422
|
+
# Names and Printers
|
|
423
|
+
#################################################################################################
|
|
424
|
+
|
|
425
|
+
def _assign_names(self, names=None, normalize=True, ngens=None):
|
|
426
|
+
"""
|
|
427
|
+
Set the names of the generator of this object.
|
|
428
|
+
|
|
429
|
+
This can only be done once because objects with generators
|
|
430
|
+
are immutable, and is typically done during creation of the object.
|
|
431
|
+
|
|
432
|
+
EXAMPLES:
|
|
433
|
+
When we create this polynomial ring, self._assign_names is called by the constructor::
|
|
434
|
+
|
|
435
|
+
sage: R = QQ['x,y,abc']; R
|
|
436
|
+
Multivariate Polynomial Ring in x, y, abc over Rational Field
|
|
437
|
+
sage: R.2
|
|
438
|
+
abc
|
|
439
|
+
|
|
440
|
+
We can't rename the variables::
|
|
441
|
+
|
|
442
|
+
sage: R._assign_names(['a','b','c'])
|
|
443
|
+
Traceback (most recent call last):
|
|
444
|
+
...
|
|
445
|
+
ValueError: variable names cannot be changed after object creation.
|
|
446
|
+
"""
|
|
447
|
+
# this will eventually all be handled by the printer
|
|
448
|
+
if names is None: return
|
|
449
|
+
if normalize:
|
|
450
|
+
if ngens is None:
|
|
451
|
+
ngens = -1 # unknown
|
|
452
|
+
names = normalize_names(ngens, names)
|
|
453
|
+
if self._names is not None and names != self._names:
|
|
454
|
+
raise ValueError('variable names cannot be changed after object creation.')
|
|
455
|
+
if isinstance(names, str):
|
|
456
|
+
names = (names, ) # make it a tuple
|
|
457
|
+
elif isinstance(names, list):
|
|
458
|
+
names = tuple(names)
|
|
459
|
+
elif not isinstance(names, tuple):
|
|
460
|
+
raise TypeError("names must be a tuple of strings")
|
|
461
|
+
self._names = names
|
|
462
|
+
|
|
463
|
+
def variable_names(self):
|
|
464
|
+
"""
|
|
465
|
+
Return the list of variable names corresponding to the generators.
|
|
466
|
+
|
|
467
|
+
OUTPUT: a tuple of strings
|
|
468
|
+
|
|
469
|
+
EXAMPLES::
|
|
470
|
+
|
|
471
|
+
sage: R.<z,y,a42> = QQ[]
|
|
472
|
+
sage: R.variable_names()
|
|
473
|
+
('z', 'y', 'a42')
|
|
474
|
+
sage: S = R.quotient_ring(z+y)
|
|
475
|
+
sage: S.variable_names()
|
|
476
|
+
('zbar', 'ybar', 'a42bar')
|
|
477
|
+
|
|
478
|
+
::
|
|
479
|
+
|
|
480
|
+
sage: T.<x> = InfinitePolynomialRing(ZZ)
|
|
481
|
+
sage: T.variable_names()
|
|
482
|
+
('x',)
|
|
483
|
+
"""
|
|
484
|
+
if self._names is not None:
|
|
485
|
+
return self._names
|
|
486
|
+
raise ValueError("variable names have not yet been set using self._assign_names(...)")
|
|
487
|
+
|
|
488
|
+
def variable_name(self):
|
|
489
|
+
"""
|
|
490
|
+
Return the first variable name.
|
|
491
|
+
|
|
492
|
+
OUTPUT: string
|
|
493
|
+
|
|
494
|
+
EXAMPLES::
|
|
495
|
+
|
|
496
|
+
sage: R.<z,y,a42> = ZZ[]
|
|
497
|
+
sage: R.variable_name()
|
|
498
|
+
'z'
|
|
499
|
+
sage: R.<x> = InfinitePolynomialRing(ZZ)
|
|
500
|
+
sage: R.variable_name()
|
|
501
|
+
'x'
|
|
502
|
+
"""
|
|
503
|
+
return self.variable_names()[0]
|
|
504
|
+
|
|
505
|
+
def _temporarily_change_names(self, names, latex_names):
|
|
506
|
+
"""
|
|
507
|
+
This is used by the variable names context manager.
|
|
508
|
+
|
|
509
|
+
TESTS:
|
|
510
|
+
|
|
511
|
+
In an old version, it was impossible to temporarily change
|
|
512
|
+
the names if no names were previously assigned. But if one
|
|
513
|
+
wants to print elements of the quotient of such an "unnamed"
|
|
514
|
+
ring, an error resulted. That was fixed in :issue:`11068`::
|
|
515
|
+
|
|
516
|
+
sage: # needs sage.modules
|
|
517
|
+
sage: MS = MatrixSpace(GF(5), 2, 2)
|
|
518
|
+
sage: I = MS * [MS.0*MS.1, MS.2 + MS.3] * MS
|
|
519
|
+
sage: Q.<a,b,c,d> = MS.quo(I)
|
|
520
|
+
sage: a #indirect doctest
|
|
521
|
+
[1 0]
|
|
522
|
+
[0 0]
|
|
523
|
+
"""
|
|
524
|
+
# old = self._names, self._latex_names
|
|
525
|
+
# We cannot assume that self *has* _latex_variable_names.
|
|
526
|
+
# But there is a method that returns them and sets
|
|
527
|
+
# the attribute at the same time, if needed.
|
|
528
|
+
# Simon King: It is not necessarily the case that variable
|
|
529
|
+
# names are assigned. In that case, self._names is None,
|
|
530
|
+
# and self.variable_names() raises a ValueError
|
|
531
|
+
try:
|
|
532
|
+
old = self.variable_names(), self.latex_variable_names()
|
|
533
|
+
except ValueError:
|
|
534
|
+
old = None, None
|
|
535
|
+
self._names, self._latex_names = names, latex_names
|
|
536
|
+
return old
|
|
537
|
+
|
|
538
|
+
def inject_variables(self, scope=None, verbose=True):
|
|
539
|
+
"""
|
|
540
|
+
Inject the generators of ``self`` with their names into the
|
|
541
|
+
namespace of the Python code from which this function is
|
|
542
|
+
called.
|
|
543
|
+
|
|
544
|
+
Thus, e.g., if the generators of ``self`` are labeled
|
|
545
|
+
'a', 'b', and 'c', then after calling this method the
|
|
546
|
+
variables a, b, and c in the current scope will be set
|
|
547
|
+
equal to the generators of ``self``.
|
|
548
|
+
|
|
549
|
+
NOTE: If Foo is a constructor for a Sage object with generators, and
|
|
550
|
+
Foo is defined in Cython, then it would typically call
|
|
551
|
+
``inject_variables()`` on the object it creates. E.g.,
|
|
552
|
+
``PolynomialRing(QQ, 'y')`` does this so that the variable y is the
|
|
553
|
+
generator of the polynomial ring.
|
|
554
|
+
"""
|
|
555
|
+
vs = self.variable_names()
|
|
556
|
+
gs = self.gens()
|
|
557
|
+
if scope is None:
|
|
558
|
+
scope = globals()
|
|
559
|
+
if verbose:
|
|
560
|
+
print("Defining %s" % (', '.join(vs)))
|
|
561
|
+
for v, g in zip(vs, gs):
|
|
562
|
+
scope[v] = g
|
|
563
|
+
|
|
564
|
+
#################################################################################################
|
|
565
|
+
# Bases
|
|
566
|
+
#################################################################################################
|
|
567
|
+
|
|
568
|
+
def base_ring(self):
|
|
569
|
+
"""
|
|
570
|
+
Return the base ring of ``self``.
|
|
571
|
+
|
|
572
|
+
INPUT:
|
|
573
|
+
|
|
574
|
+
- ``self`` -- an object over a base ring; typically a module
|
|
575
|
+
|
|
576
|
+
EXAMPLES::
|
|
577
|
+
|
|
578
|
+
sage: from sage.modules.module import Module
|
|
579
|
+
sage: Module(ZZ).base_ring()
|
|
580
|
+
Integer Ring
|
|
581
|
+
|
|
582
|
+
sage: F = FreeModule(ZZ, 3) # needs sage.modules
|
|
583
|
+
sage: F.base_ring() # needs sage.modules
|
|
584
|
+
Integer Ring
|
|
585
|
+
sage: F.__class__.base_ring # needs sage.modules
|
|
586
|
+
<method 'base_ring' of 'sage.structure.category_object.CategoryObject' objects>
|
|
587
|
+
|
|
588
|
+
Note that the coordinates of the elements of a module can lie
|
|
589
|
+
in a bigger ring, the ``coordinate_ring``::
|
|
590
|
+
|
|
591
|
+
sage: # needs sage.modules
|
|
592
|
+
sage: M = (ZZ^2) * (1/2)
|
|
593
|
+
sage: v = M([1/2, 0])
|
|
594
|
+
sage: v.base_ring()
|
|
595
|
+
Integer Ring
|
|
596
|
+
sage: parent(v[0])
|
|
597
|
+
Rational Field
|
|
598
|
+
sage: v.coordinate_ring()
|
|
599
|
+
Rational Field
|
|
600
|
+
|
|
601
|
+
More examples::
|
|
602
|
+
|
|
603
|
+
sage: F = FreeAlgebra(QQ, 'x') # needs sage.combinat sage.modules
|
|
604
|
+
sage: F.base_ring() # needs sage.combinat sage.modules
|
|
605
|
+
Rational Field
|
|
606
|
+
sage: F.__class__.base_ring # needs sage.combinat sage.modules
|
|
607
|
+
<method 'base_ring' of 'sage.structure.category_object.CategoryObject' objects>
|
|
608
|
+
|
|
609
|
+
sage: # needs sage.modules
|
|
610
|
+
sage: E = CombinatorialFreeModule(ZZ, [1,2,3])
|
|
611
|
+
sage: F = CombinatorialFreeModule(ZZ, [2,3,4])
|
|
612
|
+
sage: H = Hom(E, F)
|
|
613
|
+
sage: H.base_ring()
|
|
614
|
+
Integer Ring
|
|
615
|
+
sage: H.__class__.base_ring
|
|
616
|
+
<method 'base_ring' of 'sage.structure.category_object.CategoryObject' objects>
|
|
617
|
+
|
|
618
|
+
.. TODO::
|
|
619
|
+
|
|
620
|
+
Move this method elsewhere (typically in the Modules
|
|
621
|
+
category) so as not to pollute the namespace of all
|
|
622
|
+
category objects.
|
|
623
|
+
"""
|
|
624
|
+
return self._base
|
|
625
|
+
|
|
626
|
+
def base(self):
|
|
627
|
+
return self._base
|
|
628
|
+
|
|
629
|
+
############################################################################
|
|
630
|
+
# Homomorphism --
|
|
631
|
+
############################################################################
|
|
632
|
+
def Hom(self, codomain, cat=None):
|
|
633
|
+
r"""
|
|
634
|
+
Return the homspace ``Hom(self, codomain, cat)`` of all
|
|
635
|
+
homomorphisms from ``self`` to ``codomain`` in the category ``cat``.
|
|
636
|
+
|
|
637
|
+
The default category is determined by ``self.category()`` and
|
|
638
|
+
``codomain.category()``.
|
|
639
|
+
|
|
640
|
+
EXAMPLES::
|
|
641
|
+
|
|
642
|
+
sage: R.<x,y> = PolynomialRing(QQ, 2)
|
|
643
|
+
sage: R.Hom(QQ)
|
|
644
|
+
Set of Homomorphisms
|
|
645
|
+
from Multivariate Polynomial Ring in x, y over Rational Field
|
|
646
|
+
to Rational Field
|
|
647
|
+
|
|
648
|
+
Homspaces are defined for very general Sage objects, even elements of familiar rings.
|
|
649
|
+
|
|
650
|
+
::
|
|
651
|
+
|
|
652
|
+
sage: n = 5; Hom(n,7)
|
|
653
|
+
Set of Morphisms from 5 to 7 in Category of elements of Integer Ring
|
|
654
|
+
sage: z = 2/3; Hom(z, 8/1)
|
|
655
|
+
Set of Morphisms from 2/3 to 8 in Category of elements of Rational Field
|
|
656
|
+
|
|
657
|
+
This example illustrates the optional third argument::
|
|
658
|
+
|
|
659
|
+
sage: QQ.Hom(ZZ, Sets())
|
|
660
|
+
Set of Morphisms from Rational Field to Integer Ring in Category of sets
|
|
661
|
+
"""
|
|
662
|
+
try:
|
|
663
|
+
return self._Hom_(codomain, cat)
|
|
664
|
+
except (AttributeError, TypeError):
|
|
665
|
+
pass
|
|
666
|
+
from sage.categories.homset import Hom
|
|
667
|
+
return Hom(self, codomain, cat)
|
|
668
|
+
|
|
669
|
+
def latex_variable_names(self):
|
|
670
|
+
"""
|
|
671
|
+
Return the list of variable names suitable for latex output.
|
|
672
|
+
|
|
673
|
+
All ``_SOMETHING`` substrings are replaced by ``_{SOMETHING}``
|
|
674
|
+
recursively so that subscripts of subscripts work.
|
|
675
|
+
|
|
676
|
+
EXAMPLES::
|
|
677
|
+
|
|
678
|
+
sage: R, x = PolynomialRing(QQ, 'x', 12).objgens()
|
|
679
|
+
sage: x
|
|
680
|
+
(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)
|
|
681
|
+
sage: R.latex_variable_names ()
|
|
682
|
+
['x_{0}', 'x_{1}', 'x_{2}', 'x_{3}', 'x_{4}', 'x_{5}', 'x_{6}',
|
|
683
|
+
'x_{7}', 'x_{8}', 'x_{9}', 'x_{10}', 'x_{11}']
|
|
684
|
+
sage: f = x[0]^3 + 15/3 * x[1]^10
|
|
685
|
+
sage: print(latex(f))
|
|
686
|
+
5 x_{1}^{10} + x_{0}^{3}
|
|
687
|
+
"""
|
|
688
|
+
from sage.misc.latex import latex_variable_name
|
|
689
|
+
try:
|
|
690
|
+
names = self._latex_names
|
|
691
|
+
if names is not None:
|
|
692
|
+
return names
|
|
693
|
+
except AttributeError:
|
|
694
|
+
pass
|
|
695
|
+
# Compute the latex versions of the variable names.
|
|
696
|
+
self._latex_names = [latex_variable_name(x)
|
|
697
|
+
for x in self.variable_names()]
|
|
698
|
+
return self._latex_names
|
|
699
|
+
|
|
700
|
+
def latex_name(self):
|
|
701
|
+
return self.latex_variable_names()[0]
|
|
702
|
+
|
|
703
|
+
#################################################################################
|
|
704
|
+
# Give all objects with generators a dictionary, so that attribute setting
|
|
705
|
+
# works. It would be nice if this functionality were standard in Cython,
|
|
706
|
+
# i.e., just define __dict__ as an attribute and all this code gets generated.
|
|
707
|
+
#################################################################################
|
|
708
|
+
def __getstate__(self):
|
|
709
|
+
try:
|
|
710
|
+
d = self.__dict__.copy() # so we can add elements
|
|
711
|
+
except AttributeError:
|
|
712
|
+
d = {}
|
|
713
|
+
d['_category'] = self._category
|
|
714
|
+
d['_base'] = self._base
|
|
715
|
+
d['_names'] = self._names
|
|
716
|
+
###########
|
|
717
|
+
# The _pickle_version ensures that the unpickling for objects created
|
|
718
|
+
# in different versions of sage works across versions.
|
|
719
|
+
# Update this integer if you change any of these attributes
|
|
720
|
+
###########
|
|
721
|
+
d['_pickle_version'] = 1
|
|
722
|
+
|
|
723
|
+
return d
|
|
724
|
+
|
|
725
|
+
def __setstate__(self, d):
|
|
726
|
+
try:
|
|
727
|
+
version = d['_pickle_version']
|
|
728
|
+
except KeyError:
|
|
729
|
+
version = 0
|
|
730
|
+
try:
|
|
731
|
+
if version == 1:
|
|
732
|
+
if d['_category'] is not None:
|
|
733
|
+
# We must not erase the category information of
|
|
734
|
+
# self. Otherwise, pickles break (e.g., QQ should
|
|
735
|
+
# be a commutative ring, but when QQ._category is
|
|
736
|
+
# None then it only knows that it is a ring!
|
|
737
|
+
if self._category is None:
|
|
738
|
+
self._category = d['_category']
|
|
739
|
+
else:
|
|
740
|
+
self._category = self._category.join([self._category,d['_category']])
|
|
741
|
+
self._base = d['_base']
|
|
742
|
+
self._names = d['_names']
|
|
743
|
+
elif version == 0:
|
|
744
|
+
# In the old code, this functionality was in parent_gens,
|
|
745
|
+
# but there were parents that didn't inherit from parent_gens.
|
|
746
|
+
# If we have such, then we only need to deal with the dictionary.
|
|
747
|
+
try:
|
|
748
|
+
self._base = d['_base']
|
|
749
|
+
self._names = d['_names']
|
|
750
|
+
# We throw away d['_latex_names'] and d['_list']
|
|
751
|
+
except (AttributeError, KeyError):
|
|
752
|
+
pass
|
|
753
|
+
try:
|
|
754
|
+
self.__dict__ = d
|
|
755
|
+
except AttributeError:
|
|
756
|
+
pass
|
|
757
|
+
except (AttributeError, KeyError):
|
|
758
|
+
raise
|
|
759
|
+
# raise RuntimeError("If you change the pickling code in parent or category_object, you need to update the _pickle_version field")
|
|
760
|
+
|
|
761
|
+
def __hash__(self):
|
|
762
|
+
"""
|
|
763
|
+
A default hash based on the string representation of ``self``.
|
|
764
|
+
|
|
765
|
+
It is cached to remain consistent throughout a session, even
|
|
766
|
+
if the representation changes.
|
|
767
|
+
|
|
768
|
+
EXAMPLES::
|
|
769
|
+
|
|
770
|
+
sage: bla = PolynomialRing(ZZ,"x")
|
|
771
|
+
sage: h1 = hash(bla)
|
|
772
|
+
sage: h1 # random
|
|
773
|
+
-5279516879544852222
|
|
774
|
+
sage: bla.rename('toto')
|
|
775
|
+
sage: h2 = hash(bla)
|
|
776
|
+
sage: h2 # random
|
|
777
|
+
-5279516879544852222
|
|
778
|
+
sage: h1 == h2
|
|
779
|
+
True
|
|
780
|
+
"""
|
|
781
|
+
if self._hash_value == -1:
|
|
782
|
+
self._hash_value = hash(repr(self))
|
|
783
|
+
return self._hash_value
|
|
784
|
+
|
|
785
|
+
##############################################################################
|
|
786
|
+
# Getting attributes from the category
|
|
787
|
+
##############################################################################
|
|
788
|
+
|
|
789
|
+
def __getattr__(self, name):
|
|
790
|
+
"""
|
|
791
|
+
Let cat be the category of ``self``. This method emulates
|
|
792
|
+
``self`` being an instance of both ``CategoryObject`` and
|
|
793
|
+
``cat.parent_class``, in that order, for attribute lookup.
|
|
794
|
+
|
|
795
|
+
This attribute lookup is cached for speed.
|
|
796
|
+
|
|
797
|
+
EXAMPLES:
|
|
798
|
+
|
|
799
|
+
We test that ZZ (an extension type) inherits the methods from
|
|
800
|
+
its categories, that is from ``EuclideanDomains().parent_class``::
|
|
801
|
+
|
|
802
|
+
sage: ZZ._test_associativity
|
|
803
|
+
<bound method Semigroups.ParentMethods._test_associativity of Integer Ring>
|
|
804
|
+
sage: ZZ._test_associativity(verbose = True)
|
|
805
|
+
sage: TestSuite(ZZ).run(verbose = True)
|
|
806
|
+
running ._test_additive_associativity() . . . pass
|
|
807
|
+
running ._test_an_element() . . . pass
|
|
808
|
+
running ._test_associativity() . . . pass
|
|
809
|
+
running ._test_cardinality() . . . pass
|
|
810
|
+
running ._test_category() . . . pass
|
|
811
|
+
running ._test_characteristic() . . . pass
|
|
812
|
+
running ._test_construction() . . . pass
|
|
813
|
+
running ._test_distributivity() . . . pass
|
|
814
|
+
running ._test_divides() . . . pass
|
|
815
|
+
running ._test_elements() . . .
|
|
816
|
+
Running the test suite of self.an_element()
|
|
817
|
+
running ._test_category() . . . pass
|
|
818
|
+
running ._test_eq() . . . pass
|
|
819
|
+
running ._test_new() . . . pass
|
|
820
|
+
running ._test_nonzero_equal() . . . pass
|
|
821
|
+
running ._test_not_implemented_methods() . . . pass
|
|
822
|
+
running ._test_pickling() . . . pass
|
|
823
|
+
pass
|
|
824
|
+
running ._test_elements_eq_reflexive() . . . pass
|
|
825
|
+
running ._test_elements_eq_symmetric() . . . pass
|
|
826
|
+
running ._test_elements_eq_transitive() . . . pass
|
|
827
|
+
running ._test_elements_neq() . . . pass
|
|
828
|
+
running ._test_enumerated_set_contains() . . . pass
|
|
829
|
+
running ._test_enumerated_set_iter_cardinality() . . . pass
|
|
830
|
+
running ._test_enumerated_set_iter_list() . . . pass
|
|
831
|
+
running ._test_eq() . . . pass
|
|
832
|
+
running ._test_euclidean_degree() . . . pass
|
|
833
|
+
running ._test_fraction_field() . . . pass
|
|
834
|
+
running ._test_gcd_vs_xgcd() . . . pass
|
|
835
|
+
running ._test_metric_function() . . . pass
|
|
836
|
+
running ._test_new() . . . pass
|
|
837
|
+
running ._test_not_implemented_methods() . . . pass
|
|
838
|
+
running ._test_one() . . . pass
|
|
839
|
+
running ._test_pickling() . . . pass
|
|
840
|
+
running ._test_prod() . . . pass
|
|
841
|
+
running ._test_quo_rem() . . . pass
|
|
842
|
+
running ._test_some_elements() . . . pass
|
|
843
|
+
running ._test_zero() . . . pass
|
|
844
|
+
running ._test_zero_divisors() . . . pass
|
|
845
|
+
|
|
846
|
+
sage: Sets().example().sadfasdf
|
|
847
|
+
Traceback (most recent call last):
|
|
848
|
+
...
|
|
849
|
+
AttributeError: 'PrimeNumbers_with_category' object has no attribute 'sadfasdf'...
|
|
850
|
+
"""
|
|
851
|
+
return self.getattr_from_category(name)
|
|
852
|
+
|
|
853
|
+
cdef getattr_from_category(self, name):
|
|
854
|
+
# Lookup a method or attribute from the category abstract classes.
|
|
855
|
+
# See __getattr__ above for documentation.
|
|
856
|
+
try:
|
|
857
|
+
return self._cached_methods[name]
|
|
858
|
+
except KeyError:
|
|
859
|
+
if self._category is None:
|
|
860
|
+
# Usually, this will just raise AttributeError in
|
|
861
|
+
# getattr_from_other_class().
|
|
862
|
+
cls = type
|
|
863
|
+
else:
|
|
864
|
+
cls = self._category.parent_class
|
|
865
|
+
|
|
866
|
+
attr = getattr_from_other_class(self, cls, name)
|
|
867
|
+
self._cached_methods[name] = attr
|
|
868
|
+
return attr
|
|
869
|
+
|
|
870
|
+
def __dir__(self):
|
|
871
|
+
"""
|
|
872
|
+
Let cat be the category of ``self``. This method emulates
|
|
873
|
+
``self`` being an instance of both ``CategoryObject`` and
|
|
874
|
+
``cat.parent_class``, in that order, for attribute directory.
|
|
875
|
+
|
|
876
|
+
EXAMPLES::
|
|
877
|
+
|
|
878
|
+
sage: for s in dir(ZZ):
|
|
879
|
+
....: if s[:6] == "_test_": print(s)
|
|
880
|
+
_test_additive_associativity
|
|
881
|
+
_test_an_element
|
|
882
|
+
_test_associativity
|
|
883
|
+
_test_cardinality
|
|
884
|
+
_test_category
|
|
885
|
+
_test_characteristic
|
|
886
|
+
_test_construction
|
|
887
|
+
_test_distributivity
|
|
888
|
+
_test_divides
|
|
889
|
+
_test_elements
|
|
890
|
+
_test_elements_eq_reflexive
|
|
891
|
+
_test_elements_eq_symmetric
|
|
892
|
+
_test_elements_eq_transitive
|
|
893
|
+
_test_elements_neq
|
|
894
|
+
_test_enumerated_set_contains
|
|
895
|
+
_test_enumerated_set_iter_cardinality
|
|
896
|
+
_test_enumerated_set_iter_list
|
|
897
|
+
_test_eq
|
|
898
|
+
_test_euclidean_degree
|
|
899
|
+
_test_fraction_field
|
|
900
|
+
_test_gcd_vs_xgcd
|
|
901
|
+
_test_metric_function
|
|
902
|
+
_test_new
|
|
903
|
+
_test_not_implemented_methods
|
|
904
|
+
_test_one
|
|
905
|
+
_test_pickling
|
|
906
|
+
_test_prod
|
|
907
|
+
_test_quo_rem
|
|
908
|
+
_test_some_elements
|
|
909
|
+
_test_zero
|
|
910
|
+
_test_zero_divisors
|
|
911
|
+
sage: F = GF(9,'a') # needs sage.rings.finite_rings
|
|
912
|
+
sage: dir(F) # needs sage.rings.finite_rings
|
|
913
|
+
[..., '__class__', ..., '_test_pickling', ..., 'extension', ...]
|
|
914
|
+
"""
|
|
915
|
+
return dir_with_other_class(self, self.category().parent_class)
|
|
916
|
+
|
|
917
|
+
cpdef normalize_names(Py_ssize_t ngens, names):
|
|
918
|
+
r"""
|
|
919
|
+
Return a tuple of strings of variable names of length ngens given
|
|
920
|
+
the input names.
|
|
921
|
+
|
|
922
|
+
INPUT:
|
|
923
|
+
|
|
924
|
+
- ``ngens`` -- integer; number of generators. The value ``ngens=-1``
|
|
925
|
+
means that the number of generators is unknown a priori.
|
|
926
|
+
|
|
927
|
+
- ``names`` -- any of the following:
|
|
928
|
+
|
|
929
|
+
- a tuple or list of strings, such as ``('x', 'y')``
|
|
930
|
+
|
|
931
|
+
- a comma-separated string, such as ``x,y``
|
|
932
|
+
|
|
933
|
+
- a string prefix, such as 'alpha'
|
|
934
|
+
|
|
935
|
+
- a string of single character names, such as 'xyz'
|
|
936
|
+
|
|
937
|
+
OUTPUT: a tuple of ``ngens`` strings to be used as variable names
|
|
938
|
+
|
|
939
|
+
EXAMPLES::
|
|
940
|
+
|
|
941
|
+
sage: from sage.structure.category_object import normalize_names as nn
|
|
942
|
+
sage: nn(0, "")
|
|
943
|
+
()
|
|
944
|
+
sage: nn(0, [])
|
|
945
|
+
()
|
|
946
|
+
sage: nn(0, None)
|
|
947
|
+
()
|
|
948
|
+
sage: nn(1, 'a')
|
|
949
|
+
('a',)
|
|
950
|
+
sage: nn(2, 'z_z')
|
|
951
|
+
('z_z0', 'z_z1')
|
|
952
|
+
sage: nn(3, 'x, y, z')
|
|
953
|
+
('x', 'y', 'z')
|
|
954
|
+
sage: nn(2, 'ab')
|
|
955
|
+
('a', 'b')
|
|
956
|
+
sage: nn(2, 'x0')
|
|
957
|
+
('x00', 'x01')
|
|
958
|
+
sage: nn(3, (' a ', ' bb ', ' ccc '))
|
|
959
|
+
('a', 'bb', 'ccc')
|
|
960
|
+
sage: nn(4, ['a1', 'a2', 'b1', 'b11'])
|
|
961
|
+
('a1', 'a2', 'b1', 'b11')
|
|
962
|
+
|
|
963
|
+
Arguments are converted to strings::
|
|
964
|
+
|
|
965
|
+
sage: nn(1, u'a')
|
|
966
|
+
('a',)
|
|
967
|
+
sage: var('alpha') # needs sage.symbolic
|
|
968
|
+
alpha
|
|
969
|
+
sage: nn(2, alpha) # needs sage.symbolic
|
|
970
|
+
('alpha0', 'alpha1')
|
|
971
|
+
sage: nn(1, [alpha]) # needs sage.symbolic
|
|
972
|
+
('alpha',)
|
|
973
|
+
|
|
974
|
+
With an unknown number of generators::
|
|
975
|
+
|
|
976
|
+
sage: nn(-1, 'a')
|
|
977
|
+
('a',)
|
|
978
|
+
sage: nn(-1, 'x, y, z')
|
|
979
|
+
('x', 'y', 'z')
|
|
980
|
+
|
|
981
|
+
Test errors::
|
|
982
|
+
|
|
983
|
+
sage: nn(3, ["x", "y"])
|
|
984
|
+
Traceback (most recent call last):
|
|
985
|
+
...
|
|
986
|
+
IndexError: the number of names must equal the number of generators
|
|
987
|
+
sage: nn(None, "a")
|
|
988
|
+
Traceback (most recent call last):
|
|
989
|
+
...
|
|
990
|
+
TypeError: 'NoneType' object cannot be interpreted as an integer
|
|
991
|
+
sage: nn(1, "")
|
|
992
|
+
Traceback (most recent call last):
|
|
993
|
+
...
|
|
994
|
+
ValueError: variable name must be nonempty
|
|
995
|
+
sage: nn(1, "foo@")
|
|
996
|
+
Traceback (most recent call last):
|
|
997
|
+
...
|
|
998
|
+
ValueError: variable name 'foo@' is not alphanumeric
|
|
999
|
+
sage: nn(2, "_foo")
|
|
1000
|
+
Traceback (most recent call last):
|
|
1001
|
+
...
|
|
1002
|
+
ValueError: variable name '_foo0' does not start with a letter
|
|
1003
|
+
sage: nn(1, 3/2)
|
|
1004
|
+
Traceback (most recent call last):
|
|
1005
|
+
...
|
|
1006
|
+
ValueError: variable name '3/2' is not alphanumeric
|
|
1007
|
+
"""
|
|
1008
|
+
if isinstance(names, (tuple, list)):
|
|
1009
|
+
# Convert names to strings and strip whitespace
|
|
1010
|
+
names = [str(x).strip() for x in names]
|
|
1011
|
+
else:
|
|
1012
|
+
# Interpret names as string and convert to tuple of strings
|
|
1013
|
+
names = str(names)
|
|
1014
|
+
|
|
1015
|
+
if ',' in names:
|
|
1016
|
+
names = [x.strip() for x in names.split(',')]
|
|
1017
|
+
elif ngens > 1 and len(names) == ngens:
|
|
1018
|
+
# Split a name like "xyz" into ("x", "y", "z")
|
|
1019
|
+
try:
|
|
1020
|
+
certify_names(names)
|
|
1021
|
+
names = tuple(names)
|
|
1022
|
+
except ValueError:
|
|
1023
|
+
pass
|
|
1024
|
+
if isinstance(names, str):
|
|
1025
|
+
if ngens < 0:
|
|
1026
|
+
names = [names]
|
|
1027
|
+
else:
|
|
1028
|
+
import sage.misc.defaults
|
|
1029
|
+
names = sage.misc.defaults.variable_names(ngens, names)
|
|
1030
|
+
|
|
1031
|
+
certify_names(names)
|
|
1032
|
+
if ngens >= 0 and len(names) != ngens:
|
|
1033
|
+
raise IndexError("the number of names must equal the number of generators")
|
|
1034
|
+
return tuple(names)
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
cpdef bint certify_names(names) except -1:
|
|
1038
|
+
"""
|
|
1039
|
+
Check that ``names`` are valid variable names.
|
|
1040
|
+
|
|
1041
|
+
INPUT:
|
|
1042
|
+
|
|
1043
|
+
- ``names`` -- an iterable with strings representing variable names
|
|
1044
|
+
|
|
1045
|
+
OUTPUT: ``True`` (for efficiency of the Cython call)
|
|
1046
|
+
|
|
1047
|
+
EXAMPLES::
|
|
1048
|
+
|
|
1049
|
+
sage: from sage.structure.category_object import certify_names as cn
|
|
1050
|
+
sage: cn(["a", "b", "c"])
|
|
1051
|
+
1
|
|
1052
|
+
sage: cn("abc")
|
|
1053
|
+
1
|
|
1054
|
+
sage: cn([])
|
|
1055
|
+
1
|
|
1056
|
+
sage: cn([""])
|
|
1057
|
+
Traceback (most recent call last):
|
|
1058
|
+
...
|
|
1059
|
+
ValueError: variable name must be nonempty
|
|
1060
|
+
sage: cn(["_foo"])
|
|
1061
|
+
Traceback (most recent call last):
|
|
1062
|
+
...
|
|
1063
|
+
ValueError: variable name '_foo' does not start with a letter
|
|
1064
|
+
sage: cn(["x'"])
|
|
1065
|
+
Traceback (most recent call last):
|
|
1066
|
+
...
|
|
1067
|
+
ValueError: variable name "x'" is not alphanumeric
|
|
1068
|
+
sage: cn(["a", "b", "b"])
|
|
1069
|
+
Traceback (most recent call last):
|
|
1070
|
+
...
|
|
1071
|
+
ValueError: variable name 'b' appears more than once
|
|
1072
|
+
"""
|
|
1073
|
+
cdef set s = set()
|
|
1074
|
+
for N in names:
|
|
1075
|
+
if not isinstance(N, str):
|
|
1076
|
+
raise TypeError("variable name {!r} must be a string, not {}".format(N, type(N)))
|
|
1077
|
+
if not N:
|
|
1078
|
+
raise ValueError("variable name must be nonempty")
|
|
1079
|
+
if not N.replace("_", "").isalnum():
|
|
1080
|
+
# We must be alphanumeric, but we make an exception for non-leading '_' characters.
|
|
1081
|
+
raise ValueError("variable name {!r} is not alphanumeric".format(N))
|
|
1082
|
+
if not N[0].isalpha():
|
|
1083
|
+
raise ValueError("variable name {!r} does not start with a letter".format(N))
|
|
1084
|
+
if N in s:
|
|
1085
|
+
raise ValueError("variable name {!r} appears more than once".format(N))
|
|
1086
|
+
s.add(N)
|
|
1087
|
+
return True
|