Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/categories/additive_magmas.py
4096 views
1
r"""
2
Additive Magmas
3
"""
4
#*****************************************************************************
5
# Copyright (C) 2010 Nicolas M. Thiery <nthiery at users.sf.net>
6
#
7
# Distributed under the terms of the GNU General Public License (GPL)
8
# http://www.gnu.org/licenses/
9
#******************************************************************************
10
11
from sage.misc.abstract_method import abstract_method
12
from sage.misc.cachefunc import cached_method
13
from sage.categories.category_singleton import Category_singleton
14
from sage.categories.sets_cat import Sets
15
from sage.structure.sage_object import have_same_parent
16
17
class AdditiveMagmas(Category_singleton):
18
"""
19
The category of additive magmas, i.e. sets with an binary
20
operation ``+``.
21
22
EXAMPLES::
23
24
sage: AdditiveMagmas()
25
Category of additive magmas
26
sage: AdditiveMagmas().super_categories()
27
[Category of sets]
28
sage: AdditiveMagmas().all_super_categories()
29
[Category of additive magmas, Category of sets, Category of sets with partial maps, Category of objects]
30
31
TESTS::
32
33
sage: C = AdditiveMagmas()
34
sage: TestSuite(C).run()
35
36
"""
37
38
def super_categories(self):
39
"""
40
EXAMPLES::
41
42
sage: AdditiveMagmas().super_categories()
43
[Category of sets]
44
"""
45
return [Sets()]
46
47
class ParentMethods:
48
49
def summation(self, x, y):
50
"""
51
The binary addition operator of the semigroup
52
53
INPUT:
54
55
- ``x``, ``y`` -- elements of this additive semigroup
56
57
Returns the sum of ``x`` and ``y``
58
59
EXAMPLES::
60
61
sage: S = CommutativeAdditiveSemigroups().example()
62
sage: (a,b,c,d) = S.additive_semigroup_generators()
63
sage: S.summation(a, b)
64
a + b
65
66
A parent in ``AdditiveMagmas()`` must
67
either implement :meth:`.summation` in the parent class or
68
``_add_`` in the element class. By default, the addition
69
method on elements ``x._add_(y)`` calls
70
``S.summation(x,y)``, and reciprocally.
71
72
73
As a bonus effect, ``S.summation`` by itself models the
74
binary function from ``S`` to ``S``::
75
76
sage: bin = S.summation
77
sage: bin(a,b)
78
a + b
79
80
Here, ``S.summation`` is just a bound method. Whenever
81
possible, it is recommended to enrich ``S.summation`` with
82
extra mathematical structure. Lazy attributes can come
83
handy for this.
84
85
Todo: add an example.
86
"""
87
return x._add_(y)
88
89
summation_from_element_class_add = summation
90
91
def __init_extra__(self):
92
"""
93
TESTS::
94
95
sage: S = CommutativeAdditiveSemigroups().example()
96
sage: (a,b,c,d) = S.additive_semigroup_generators()
97
sage: a + b # indirect doctest
98
a + b
99
sage: a.__class__._add_ == a.__class__._add_parent
100
True
101
"""
102
# This should instead register the summation to the coercion model
103
# But this is not yet implemented in the coercion model
104
if (self.summation != self.summation_from_element_class_add) and hasattr(self, "element_class") and hasattr(self.element_class, "_add_parent"):
105
self.element_class._add_ = self.element_class._add_parent
106
107
108
def addition_table(self, names='letters', elements=None):
109
r"""
110
Returns a table describing the addition operation.
111
112
.. note:: The order of the elements in the row and column
113
headings is equal to the order given by the table's
114
:meth:`~sage.matrix.operation_table.OperationTable.list`
115
method. The association can also be retrieved with the
116
:meth:`~sage.matrix.operation_table.OperationTable.dict`
117
method.
118
119
INPUTS:
120
121
- ``names`` - the type of names used
122
123
* ``letters`` - lowercase ASCII letters are used
124
for a base 26 representation of the elements'
125
positions in the list given by
126
:meth:`~sage.matrix.operation_table.OperationTable.column_keys`,
127
padded to a common width with leading 'a's.
128
* ``digits`` - base 10 representation of the
129
elements' positions in the list given by
130
:meth:`~sage.matrix.operation_table.OperationTable.column_keys`,
131
padded to a common width with leading zeros.
132
* ``elements`` - the string representations
133
of the elements themselves.
134
* a list - a list of strings, where the length
135
of the list equals the number of elements.
136
- ``elements`` - default = ``None``. A list of
137
elements of the set. This may be used to impose an
138
alternate ordering on the elements, perhaps
139
when this is used in the context of a particular structure.
140
The default is to use whatever ordering the
141
``S.list``
142
method returns. Or the ``elements`` can be a subset
143
which is closed under the operation. In particular,
144
this can be used when the base set is infinite.
145
146
OUTPUT:
147
The addition table as an object of the class
148
:class:`~sage.matrix.operation_table.OperationTable`
149
which defines several methods for manipulating and
150
displaying the table. See the documentation there
151
for full details to supplement the documentation
152
here.
153
154
EXAMPLES:
155
156
All that is required is that an algebraic structure
157
has an addition defined.The default is to represent
158
elements as lowercase ASCII letters. ::
159
160
sage: R=IntegerModRing(5)
161
sage: R.addition_table()
162
+ a b c d e
163
+----------
164
a| a b c d e
165
b| b c d e a
166
c| c d e a b
167
d| d e a b c
168
e| e a b c d
169
170
The ``names`` argument allows displaying the elements in different ways. Requesting ``elements`` will use the representation of the elements of the set. Requesting ``digits`` will include leading zeros as padding. ::
171
172
sage: R=IntegerModRing(11)
173
sage: P=R.addition_table(names='elements')
174
sage: P
175
+ 0 1 2 3 4 5 6 7 8 9 10
176
+---------------------------------
177
0| 0 1 2 3 4 5 6 7 8 9 10
178
1| 1 2 3 4 5 6 7 8 9 10 0
179
2| 2 3 4 5 6 7 8 9 10 0 1
180
3| 3 4 5 6 7 8 9 10 0 1 2
181
4| 4 5 6 7 8 9 10 0 1 2 3
182
5| 5 6 7 8 9 10 0 1 2 3 4
183
6| 6 7 8 9 10 0 1 2 3 4 5
184
7| 7 8 9 10 0 1 2 3 4 5 6
185
8| 8 9 10 0 1 2 3 4 5 6 7
186
9| 9 10 0 1 2 3 4 5 6 7 8
187
10| 10 0 1 2 3 4 5 6 7 8 9
188
189
sage: T=R.addition_table(names='digits')
190
sage: T
191
+ 00 01 02 03 04 05 06 07 08 09 10
192
+---------------------------------
193
00| 00 01 02 03 04 05 06 07 08 09 10
194
01| 01 02 03 04 05 06 07 08 09 10 00
195
02| 02 03 04 05 06 07 08 09 10 00 01
196
03| 03 04 05 06 07 08 09 10 00 01 02
197
04| 04 05 06 07 08 09 10 00 01 02 03
198
05| 05 06 07 08 09 10 00 01 02 03 04
199
06| 06 07 08 09 10 00 01 02 03 04 05
200
07| 07 08 09 10 00 01 02 03 04 05 06
201
08| 08 09 10 00 01 02 03 04 05 06 07
202
09| 09 10 00 01 02 03 04 05 06 07 08
203
10| 10 00 01 02 03 04 05 06 07 08 09
204
205
Specifying the elements in an alternative order can provide
206
more insight into how the operation behaves. ::
207
208
sage: S=IntegerModRing(7)
209
sage: elts = [0, 3, 6, 2, 5, 1, 4]
210
sage: S.addition_table(elements=elts)
211
+ a b c d e f g
212
+--------------
213
a| a b c d e f g
214
b| b c d e f g a
215
c| c d e f g a b
216
d| d e f g a b c
217
e| e f g a b c d
218
f| f g a b c d e
219
g| g a b c d e f
220
221
The ``elements`` argument can be used to provide
222
a subset of the elements of the structure. The subset
223
must be closed under the operation. Elements need only
224
be in a form that can be coerced into the set. The
225
``names`` argument can also be used to request that
226
the elements be represented with their usual string
227
representation. ::
228
229
sage: T=IntegerModRing(12)
230
sage: elts=[0, 3, 6, 9]
231
sage: T.addition_table(names='elements', elements=elts)
232
+ 0 3 6 9
233
+--------
234
0| 0 3 6 9
235
3| 3 6 9 0
236
6| 6 9 0 3
237
9| 9 0 3 6
238
239
The table returned can be manipulated in various ways. See
240
the documentation for
241
:class:`~sage.matrix.operation_table.OperationTable` for more
242
comprehensive documentation. ::
243
244
sage: R=IntegerModRing(3)
245
sage: T=R.addition_table()
246
sage: T.column_keys()
247
(0, 1, 2)
248
sage: sorted(T.translation().items())
249
[('a', 0), ('b', 1), ('c', 2)]
250
sage: T.change_names(['x', 'y', 'z'])
251
sage: sorted(T.translation().items())
252
[('x', 0), ('y', 1), ('z', 2)]
253
sage: T
254
+ x y z
255
+------
256
x| x y z
257
y| y z x
258
z| z x y
259
"""
260
from sage.matrix.operation_table import OperationTable
261
import operator
262
return OperationTable(self, operation=operator.add, names=names, elements=elements)
263
264
class ElementMethods:
265
266
# This could eventually be moved to SageObject
267
def __add__(self, right):
268
r"""
269
Sum of two elements
270
271
This calls the `_add_` method of ``self``, if it is
272
available and the two elements have the same parent.
273
274
Otherwise, the job is delegated to the coercion model.
275
276
Do not override; instead implement an ``_add_`` method in the
277
element class or a ``summation`` method in the parent class.
278
279
EXAMPLES::
280
281
sage: F = CommutativeAdditiveSemigroups().example()
282
sage: (a,b,c,d) = F.additive_semigroup_generators()
283
sage: a + b
284
a + b
285
"""
286
if have_same_parent(self, right) and hasattr(self, "_add_"):
287
return self._add_(right)
288
from sage.structure.element import get_coercion_model
289
import operator
290
return get_coercion_model().bin_op(self, right, operator.add)
291
292
def __radd__(self, left):
293
r"""
294
Handles the sum of two elements, when the left hand side
295
needs to be coerced first.
296
297
EXAMPLES::
298
299
sage: F = CommutativeAdditiveSemigroups().example()
300
sage: (a,b,c,d) = F.additive_semigroup_generators()
301
sage: a.__radd__(b)
302
a + b
303
"""
304
if have_same_parent(left, self) and hasattr(left, "_add_"):
305
return left._add_(self)
306
from sage.structure.element import get_coercion_model
307
import operator
308
return get_coercion_model().bin_op(left, self, operator.add)
309
310
@abstract_method(optional = True)
311
def _add_(self, right):
312
"""
313
Sum of two elements
314
315
INPUT:
316
317
- ``self``, ``right`` -- two elements with the same parent
318
319
OUTPUT:
320
321
- an element of the same parent
322
323
EXAMPLES::
324
325
sage: F = CommutativeAdditiveSemigroups().example()
326
sage: (a,b,c,d) = F.additive_semigroup_generators()
327
sage: a._add_(b)
328
a + b
329
"""
330
331
def _add_parent(self, other):
332
r"""
333
Returns the sum of the two elements, calculated using
334
the ``summation`` method of the parent.
335
336
This is the default implementation of _add_ if
337
``summation`` is implemented in the parent.
338
339
INPUT:
340
341
- ``other`` -- an element of the parent of ``self``
342
343
OUTPUT:
344
345
an element of the parent of ``self``
346
347
EXAMPLES::
348
349
sage: S = CommutativeAdditiveSemigroups().example()
350
sage: (a,b,c,d) = S.additive_semigroup_generators()
351
sage: a._add_parent(b)
352
a + b
353
"""
354
return self.parent().summation(self, other)
355
356