Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/structure/generators.pyx
4045 views
1
"""
2
This module implements Generators, a type of object that represents (algebraic) generators of a Sage object.
3
4
5
"""
6
7
include "../ext/stdsage.pxi"
8
from sage.structure.sage_object cimport SageObject
9
10
class GenIter(SageObject):
11
"""
12
An iterator over a set of generators.
13
"""
14
def __init__(self, Generators gens):
15
if gens._index_set is None:
16
self._index_iter = iter(xrange(gens.count()))
17
else:
18
self._index_iter = iter(gens._index_set)
19
self._gens = gens
20
21
def next(self):
22
return self._gens.get_from_index(self._index_iter.next())
23
24
def __iter__(self):
25
return self
26
27
cdef class Generators(SageObject):
28
"""
29
This class implements generators that can be attached to CategoryObjects.
30
"""
31
def __init__(self, obj, index_set, category):
32
self._obj = obj
33
self._index_set = index_set
34
self._category = category
35
36
cpdef get_from_index(self, i):
37
return self._obj._gen_(i)
38
39
def __contains__(self, x):
40
for a in self:
41
if x == a:
42
return True
43
return False
44
45
def __call__(self, i):
46
return self.get_from_index(i)
47
48
def __getitem__(self, i):
49
if isinstance(i, slice):
50
return self.list()[i]
51
return self.get_from_index(i)
52
53
def __iter__(self):
54
return GenIter(self)
55
56
def __len__(self):
57
return self.count()
58
59
cpdef index_set(self):
60
if self._index_set is None:
61
return range(self.count())
62
else:
63
return self._index_set
64
65
cpdef category(self):
66
return self._category
67
68
cpdef obj(self):
69
return self._obj
70
71
cpdef count(self):
72
return len(self._index_set)
73
74
cpdef list(self):
75
try:
76
if not self._index_set.is_finite():
77
raise ValueError, "index set must be finite to compute list"
78
except AttributeError:
79
pass
80
return [self.get_from_index(i) for i in self.index_set()]
81
82
def _repr_(self):
83
if not PY_TYPE_CHECK(self._obj, Generators):
84
return "Set of generators of %s"%(self.obj())
85
else:
86
raise RuntimeError, "Set of generators of a generators object"
87
88
cdef class Generators_finite(Generators):
89
def __init__(self, obj, n, index_set, category):
90
"""
91
Creates a generator object representing finitely many generators.
92
"""
93
self._n = n
94
Generators.__init__(self, obj, index_set, category)
95
96
cpdef count(self):
97
return self._n
98
99
def __cmp__(self, other_unty):
100
cdef Generators_finite other = other_unty
101
return cmp((self._obj, self._n, self._index_set, self._category),
102
(other._obj, other._n, other._index_set, other._category))
103
104
105
def _repr_(self):
106
return "(" + ", ".join([repr(self[i]) for i in self.index_set()]) + ")"
107
108
def __reduce__(self):
109
return make_finite_gens, (self._obj, self._n, self._index_set, self._category)
110
111
def make_finite_gens(obj, n, index_set, category):
112
return Generators_finite(obj, n, index_set, category)
113
114
115
cdef class Generators_list(Generators_finite):
116
"""
117
This class represents a set of generators as a tuple of elements, indexed
118
by the integers 0 to len(self)-1.
119
120
It is the easiest to use of all the generator classes, and gets constructed
121
implicitly when a list is passed into \code{_populate_generators_}.
122
"""
123
def __init__(self, obj, L, category):
124
"""
125
EXAMPLES:
126
sage: from sage.structure.generators import Generators_list
127
sage: gens = Generators_list(ZZ, [2,3], Rings)
128
sage: gens.count()
129
2
130
sage: gens(1)
131
3
132
sage: list(gens)
133
[2, 3]
134
"""
135
self._List = tuple(L)
136
Generators_finite.__init__(self, obj, len(self._List), None, category)
137
138
cpdef get_from_index(self, i):
139
"""
140
EXAMPLES:
141
sage: from sage.structure.generators import Generators_list
142
sage: gens = Generators_list(ZZ, [5,9], Rings)
143
sage: gens.get_from_index(0)
144
5
145
"""
146
try:
147
return self._List[i]
148
except IndexError:
149
raise IndexError, "No such generator: %s must be less than %s" % (i, len(self._List))
150
151
def __iter__(self):
152
"""
153
EXAMPLES:
154
sage: from sage.structure.generators import Generators_list
155
sage: gens = Generators_list(ZZ, [3,4,5], Rings)
156
sage: [x^2 for x in gens]
157
[9, 16, 25]
158
"""
159
return iter(self._List)
160
161
cpdef list(self):
162
"""
163
Actually returns a tuple, which is immutable.
164
165
EXAMPLES:
166
sage: from sage.structure.generators import Generators_list
167
sage: gens = Generators_list(ZZ, (1,2,3), Rings)
168
sage: gens.list()
169
(1, 2, 3)
170
"""
171
return self._List
172
173
def __reduce__(self):
174
return make_list_gens, (self._obj, self._List, self._category)
175
176
def __cmp__(left, _right):
177
cdef Generators_list right
178
try:
179
right = _right
180
return cmp(left._n, right._n) or \
181
cmp(left._List, right._List) or \
182
cmp(left._category, right._category)
183
except TypeError:
184
return cmp(type(left), type(right))
185
186
def _repr_(self):
187
return repr(self._List)
188
189
def make_list_gens(*args):
190
"""
191
TEST:
192
sage: from sage.structure.generators import Generators_list
193
sage: gens = Generators_list(QQ, [-3,17], Fields())
194
sage: loads(dumps(gens)) == gens
195
True
196
"""
197
return Generators_list(*args)
198
199
cdef class Generators_naturals(Generators):
200
def __init__(self, obj, category):
201
import sage.rings.natural_parents
202
Generators.__init__(self, obj, sage.rings.natural_parents.NaturalSemiring, category)
203
204
cpdef count(self):
205
import sage.rings.infinity
206
return sage.rings.infinity.infinity
207
208
def __getitem__(self, i):
209
if isinstance(i, slice):
210
raise NotImplementedError
211
return self.get_from_index(i)
212
213
cdef class Generators_none(Generators):
214
def __init__(self, obj, category = None):
215
Generators.__init__(self, obj, None, category)
216
217
cpdef get_from_index(self, i):
218
if self._category is None:
219
raise ValueError, "this object does not have generators"
220
else:
221
raise ValueError, "this object does not have generators in that category"
222
223
def __contains__(self, x):
224
if self._category is None:
225
raise ValueError, "this object does not have generators"
226
else:
227
raise ValueError, "this object does not have generators in that category"
228
229
def __iter__(self):
230
if self._category is None:
231
raise ValueError, "this object does not have generators"
232
else:
233
raise ValueError, "this object does not have generators in that category"
234
235
cpdef index_set(self):
236
if self._category is None:
237
raise ValueError, "this object does not have generators"
238
else:
239
raise ValueError, "this object does not have generators in that category"
240
241
cpdef count(self):
242
if self._category is None:
243
raise ValueError, "this object does not have generators"
244
else:
245
raise ValueError, "this object does not have generators in that category"
246
247
cpdef list(self):
248
if self._category is None:
249
raise ValueError, "this object does not have generators"
250
else:
251
raise ValueError, "this object does not have generators in that category"
252
253
254
255
cdef class Generators_lazy_all(Generators):
256
"""
257
Use this generators class if there is a finite list of generators that is expensive to compute but which is computed all at once.
258
"""
259
def __init__(self, G, index_set, category, computing_function):
260
self._f = computing_function
261
Generators.__init__(self, G, index_set, category)
262
263
cdef int _compute_gens(self) except -1:
264
self._gens = self._f()
265
266
cpdef get_from_index(self, i):
267
try:
268
return self._gens[i]
269
except AttributeError:
270
self._compute_gens()
271
return self._gens[i]
272
273
cpdef count(self):
274
try:
275
return len(self._gens)
276
except AttributeError:
277
self._compute_gens()
278
return len(self._gens)
279
280
cpdef list(self):
281
try:
282
return list(self._gens)
283
except AttributeError:
284
self._compute_gens()
285
return list(self._gens)
286
287
def _repr_(self):
288
try:
289
return repr(self._gens)
290
except AttributeError:
291
self._compute_gens()
292
return repr(self._gens)
293
294
295