Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/categories/algebras.py
4099 views
1
r"""
2
Algebras
3
4
AUTHORS:
5
6
- David Kohel & William Stein (2005): initial revision
7
- Nicolas M. Thiery (2008): rewrote for new category framework
8
"""
9
#*****************************************************************************
10
# Copyright (C) 2005 David Kohel <[email protected]>
11
# William Stein <[email protected]>
12
# 2008 Teresa Gomez-Diaz (CNRS) <[email protected]>
13
# 2008-2009 Nicolas M. Thiery <nthiery at users.sf.net>
14
#
15
# Distributed under the terms of the GNU General Public License (GPL)
16
# http://www.gnu.org/licenses/
17
#******************************************************************************
18
19
from category_types import Category_over_base_ring
20
from sage.categories.homset import Hom
21
from sage.categories.cartesian_product import CartesianProductsCategory, cartesian_product
22
from sage.categories.dual import DualObjectsCategory
23
from sage.categories.tensor import TensorProductsCategory, tensor
24
from sage.categories.morphism import SetMorphism
25
from sage.categories.modules import Modules
26
from sage.categories.rings import Rings
27
from sage.misc.cachefunc import cached_method
28
from sage.structure.sage_object import have_same_parent
29
30
class Algebras(Category_over_base_ring):
31
"""
32
The category of algebras over a given base ring.
33
34
An algebra over a ring `R` is a module over `R` which is itself a ring.
35
36
TODO: should `R` be a commutative ring?
37
38
EXAMPLES::
39
40
sage: Algebras(ZZ)
41
Category of algebras over Integer Ring
42
sage: Algebras(ZZ).super_categories()
43
[Category of rings, Category of modules over Integer Ring]
44
45
TESTS::
46
47
sage: TestSuite(Algebras(ZZ)).run()
48
"""
49
50
# For backward compatibility?
51
def __contains__(self, x):
52
"""
53
Membership testing
54
55
EXAMPLES::
56
57
sage: QQ[x] in Algebras(QQ)
58
True
59
60
sage: QQ^3 in Algebras(QQ)
61
False
62
sage: QQ[x] in Algebras(CDF)
63
False
64
"""
65
if super(Algebras, self).__contains__(x):
66
return True
67
from sage.rings.ring import Algebra
68
return isinstance(x, Algebra) and x.base_ring() == self.base_ring()
69
70
def super_categories(self):
71
"""
72
EXAMPLES::
73
74
sage: Algebras(ZZ).super_categories()
75
[Category of rings, Category of modules over Integer Ring]
76
"""
77
R = self.base_ring()
78
return [Rings(), Modules(R)]
79
80
class ParentMethods: # (Algebra): # Eventually, the content of Algebra should be moved here
81
def from_base_ring(self, r):
82
"""
83
Canonical embedding from base ring
84
85
INPUT:
86
87
- ``r`` -- an element of ``self.base_ring()``
88
89
Returns the canonical embedding of `r` into self.
90
91
EXAMPLES::
92
93
sage: A = AlgebrasWithBasis(QQ).example(); A
94
An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field
95
sage: A.from_base_ring(1)
96
B[word: ]
97
"""
98
return self.one()._lmul_(r)
99
100
def __init_extra__(self):
101
"""
102
Declares the canonical coercion from ``self.base_ring()`` to ``self``,
103
if there has been none before.
104
105
EXAMPLES::
106
107
sage: A = AlgebrasWithBasis(QQ).example(); A
108
An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field
109
sage: coercion_model = sage.structure.element.get_coercion_model()
110
sage: coercion_model.discover_coercion(QQ, A)
111
(Generic morphism:
112
From: Rational Field
113
To: An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field, None)
114
sage: A(1) # indirect doctest
115
B[word: ]
116
117
"""
118
# If self has an attribute _no_generic_basering_coercion
119
# set to True, then this declaration is skipped.
120
# This trick, introduced in #11900, is used in
121
# sage.matrix.matrix_space.py and
122
# sage.rings.polynomial.polynomial_ring.
123
# It will hopefully be refactored into something more
124
# conceptual later on.
125
if getattr(self,'_no_generic_basering_coercion',False):
126
return
127
128
base_ring = self.base_ring()
129
if base_ring is self:
130
# There are rings that are their own base rings. No need to register that.
131
return
132
if self.is_coercion_cached(base_ring):
133
# We will not use any generic stuff, since a (presumably) better conversion
134
# has already been registered.
135
return
136
mor = None
137
# This could be a morphism of Algebras(self.base_ring()); however, e.g., QQ is not in Algebras(QQ)
138
H = Hom(base_ring, self, Rings())
139
140
# Idea: There is a generic method "from_base_ring", that just does multiplication with
141
# the multiplicative unit. However, the unit is constructed repeatedly, which is slow.
142
# Hence, if the unit is available *now*, then we store it.
143
#
144
# However, if there is a specialised from_base_ring method, then it should be used!
145
try:
146
has_custom_conversion = self.category().parent_class.from_base_ring.__func__ is not self.from_base_ring.__func__
147
except AttributeError:
148
# Sometimes from_base_ring is a lazy attribute
149
has_custom_conversion = True
150
if has_custom_conversion:
151
mor = SetMorphism(function = self.from_base_ring, parent = H)
152
try:
153
self.register_coercion(mor)
154
except AssertionError:
155
pass
156
return
157
158
try:
159
one = self.one()
160
except (NotImplementedError, AttributeError, TypeError):
161
# The unit is not available, yet. But there are cases
162
# in which it will be available later. Hence:
163
mor = SetMorphism(function = self.from_base_ring, parent = H)
164
# try sanity of one._lmul_
165
if mor is None:
166
try:
167
if one._lmul_(base_ring.an_element()) is None:
168
# There are cases in which lmul returns None, believe it or not.
169
# One example: Hecke algebras.
170
# In that case, the generic implementation of from_base_ring would
171
# fail as well. Hence, unless it is overruled, we will not use it.
172
#mor = SetMorphism(function = self.from_base_ring, parent = H)
173
return
174
except (NotImplementedError, AttributeError, TypeError):
175
# it is possible that an_element or lmul are not implemented.
176
return
177
#mor = SetMorphism(function = self.from_base_ring, parent = H)
178
mor = SetMorphism(function = one._lmul_, parent = H)
179
try:
180
self.register_coercion(mor)
181
except AssertionError:
182
pass
183
184
class ElementMethods:
185
# TODO: move the content of AlgebraElement here
186
187
# Workaround: this sets back Semigroups.Element.__mul__, which is currently overriden by Modules.Element.__mul__
188
# What does this mean in terms of inheritance order?
189
# Could we do a variant like __mul__ = Semigroups.Element.__mul__
190
def __mul__(self, right):
191
"""
192
EXAMPLES::
193
194
sage: s = SFASchur(QQ)
195
sage: a = s([2])
196
sage: a._mul_(a) #indirect doctest
197
s[2, 2] + s[3, 1] + s[4]
198
199
Todo: use AlgebrasWithBasis(QQ).example()
200
"""
201
if have_same_parent(self, right) and hasattr(self, "_mul_"):
202
return self._mul_(right)
203
from sage.structure.element import get_coercion_model
204
import operator
205
return get_coercion_model().bin_op(self, right, operator.mul)
206
207
# __imul__ = __mul__
208
209
# Parents in this category should implement _lmul_ and _rmul_
210
211
def _div_(self, y):
212
"""
213
Division by invertible elements
214
215
# TODO: move in Monoids
216
217
EXAMPLES::
218
219
sage: C = AlgebrasWithBasis(QQ).example()
220
sage: x = C(2); x
221
2*B[word: ]
222
sage: y = C.algebra_generators().first(); y
223
B[word: a]
224
225
sage: y._div_(x)
226
1/2*B[word: a]
227
sage: x._div_(y)
228
Traceback (most recent call last):
229
...
230
ValueError: cannot invert self (= B[word: a])
231
"""
232
return self.parent().product(self, ~y)
233
234
class CartesianProducts(CartesianProductsCategory):
235
"""
236
The category of algebras constructed as cartesian products of algebras
237
238
This construction gives the direct product of algebras. See
239
discussion on:
240
241
- http://groups.google.fr/group/sage-devel/browse_thread/thread/35a72b1d0a2fc77a/348f42ae77a66d16#348f42ae77a66d16
242
- http://en.wikipedia.org/wiki/Direct_product
243
"""
244
def extra_super_categories(self):
245
"""
246
A cartesian product of algebras is endowed with a natural
247
algebra structure.
248
249
EXAMPLES::
250
251
sage: Algebras(QQ).CartesianProducts().extra_super_categories()
252
[Category of algebras over Rational Field]
253
sage: Algebras(QQ).CartesianProducts().super_categories()
254
[Category of algebras over Rational Field, Category of Cartesian products of monoids]
255
"""
256
return [self.base_category()]
257
258
259
class TensorProducts(TensorProductsCategory):
260
@cached_method
261
def extra_super_categories(self):
262
"""
263
EXAMPLES::
264
265
sage: Algebras(QQ).TensorProducts().extra_super_categories()
266
[Category of algebras over Rational Field]
267
sage: Algebras(QQ).TensorProducts().super_categories()
268
[Category of algebras over Rational Field]
269
270
Meaning: a tensor product of algebras is an algebra
271
"""
272
return [self.base_category()]
273
274
class ParentMethods:
275
#def coproduct(self):
276
# tensor products of morphisms are not yet implemented
277
# return tensor(module.coproduct for module in self.modules)
278
pass
279
280
class ElementMethods:
281
pass
282
283
class DualObjects(DualObjectsCategory):
284
285
def extra_super_categories(self):
286
r"""
287
Returns the dual category
288
289
EXAMPLES:
290
291
The category of algebras over the Rational Field is dual
292
to the category of coalgebras over the same field::
293
294
sage: C = Algebras(QQ)
295
sage: C.dual()
296
Category of duals of algebras over Rational Field
297
sage: C.dual().extra_super_categories()
298
[Category of coalgebras over Rational Field]
299
"""
300
from sage.categories.coalgebras import Coalgebras
301
return [Coalgebras(self.base_category().base_ring())]
302
303