1 | 20,21c20,21 |
---|
2 | < from sage.combinat.finite_class import FiniteCombinatorialClass_l |
---|
3 | < from sage.rings.all import ZZ |
---|
4 | --- |
---|
5 | > from sage.combinat.finite_class import FiniteCombinatorialClass |
---|
6 | > from sage.rings.integer import Integer |
---|
7 | 37,39c37,39 |
---|
8 | < In its simplest form, a list l by itself is considered as the |
---|
9 | < family `(l[i]_{i \in I})` where `I` is the range |
---|
10 | < `0\dots,len(l)`. So Family(l) just returns it. |
---|
11 | --- |
---|
12 | > In its simplest form, a list l or a tuple by itself is considered as the |
---|
13 | > family `(l[i]_{i \in I})` where `I` is the range `0\dots,len(l)`. So |
---|
14 | > Family(l) returns the corresponding family. |
---|
15 | 45c45,48 |
---|
16 | < [1, 2, 3] |
---|
17 | --- |
---|
18 | > Family (1, 2, 3) |
---|
19 | > sage: f = Family((1,2,3)) |
---|
20 | > sage: f |
---|
21 | > Family (1, 2, 3) |
---|
22 | 87,91c90,99 |
---|
23 | < By default, if the index set is a list, all images are computed |
---|
24 | < right away, and stored in an internal dictionary. Note that this |
---|
25 | < requires all the elements of the list to be hashable. One can ask |
---|
26 | < instead for the images `f(i)` to be computed lazily, when |
---|
27 | < needed:: |
---|
28 | --- |
---|
29 | > By default, if the index set is a list or a tuple, all images are |
---|
30 | > computed right away, and stored in an internal dictionary:: |
---|
31 | > |
---|
32 | > sage: f = Family((3,4,7), lambda i: 2*i) |
---|
33 | > sage: f |
---|
34 | > Finite family {3: 6, 4: 8, 7: 14} |
---|
35 | > |
---|
36 | > Note that this requires all the elements of the list to be |
---|
37 | > hashable. One can ask instead for the images `f(i)` to be computed |
---|
38 | > lazily, when needed:: |
---|
39 | 121c129 |
---|
40 | < sage: f = LazyFamily(Permutations(3), lambda i: (i.to_lehmer_code())) |
---|
41 | --- |
---|
42 | > sage: f = LazyFamily(Permutations(3), attrcall("to_lehmer_code")) |
---|
43 | 130,131c138,153 |
---|
44 | < unpickle. |
---|
45 | < |
---|
46 | --- |
---|
47 | > unpickle. The following two work:: |
---|
48 | > |
---|
49 | > sage: loads(dumps(LazyFamily(Permutations(3), lambda p: p.to_lehmer_code()))) |
---|
50 | > Lazy family (f(i))_{i in Standard permutations of 3} |
---|
51 | > |
---|
52 | > sage: loads(dumps(LazyFamily(Permutations(3), attrcall("to_lehmer_code")))) |
---|
53 | > Lazy family (f(i))_{i in Standard permutations of 3} |
---|
54 | > |
---|
55 | > But this one dont:: |
---|
56 | > |
---|
57 | > sage: def plus_n(n): return lambda x: x+n |
---|
58 | > sage: loads(dumps(LazyFamily([1,2,3], plus_n(3)))) |
---|
59 | > Traceback (most recent call last): |
---|
60 | > ... |
---|
61 | > ValueError: Cannot pickle code objects from closures |
---|
62 | > |
---|
63 | 249a272,293 |
---|
64 | > |
---|
65 | > The factory ``Family`` is supposed to be idempotent. We test this feature here:: |
---|
66 | > |
---|
67 | > sage: f = FiniteFamily({3: 'a', 4: 'b', 7: 'd'}) |
---|
68 | > sage: g = Family(f) |
---|
69 | > sage: f == g |
---|
70 | > True |
---|
71 | > |
---|
72 | > sage: f = Family([3,4,7], lambda i: 2r*i, hidden_keys=[2]) |
---|
73 | > sage: g = Family(f) |
---|
74 | > sage: f == g |
---|
75 | > True |
---|
76 | > |
---|
77 | > sage: f = LazyFamily([3,4,7], lambda i: 2r*i) |
---|
78 | > sage: g = Family(f) |
---|
79 | > sage: f == g |
---|
80 | > True |
---|
81 | > |
---|
82 | > sage: f = TrivialFamily([3,4,7]) |
---|
83 | > sage: g = Family(f) |
---|
84 | > sage: f == g |
---|
85 | > True |
---|
86 | 252,255c296,297 |
---|
87 | < if function == None and hidden_keys == []: |
---|
88 | < if type(indices) == list or isinstance(indices, FiniteCombinatorialClass_l) or isinstance(indices, FiniteFamily) or isinstance(indices, LazyFamily): |
---|
89 | < return indices |
---|
90 | < if type(indices) == dict: |
---|
91 | --- |
---|
92 | > if function is None and hidden_keys == []: |
---|
93 | > if isinstance(indices, dict): |
---|
94 | 256a299,303 |
---|
95 | > if isinstance(indices, (list, tuple) ): |
---|
96 | > return TrivialFamily(indices) |
---|
97 | > if isinstance(indices, (FiniteCombinatorialClass, |
---|
98 | > FiniteFamily, LazyFamily, TrivialFamily) ): |
---|
99 | > return indices |
---|
100 | 258c305 |
---|
101 | < if type(indices) == list or isinstance(indices, FiniteCombinatorialClass_l): |
---|
102 | --- |
---|
103 | > if isinstance(indices, (list, tuple, FiniteCombinatorialClass) ): |
---|
104 | 270a318,322 |
---|
105 | > """ |
---|
106 | > The abstract class for family |
---|
107 | > |
---|
108 | > Any family belongs to a class which inherits from ``AbstractFamily``. |
---|
109 | > """ |
---|
110 | 360c412,420 |
---|
111 | < """ |
---|
112 | --- |
---|
113 | > |
---|
114 | > Check for bug #5538:: |
---|
115 | > |
---|
116 | > sage: d = {1:"a", 3:"b", 4:"c"} |
---|
117 | > sage: f = Family(d) |
---|
118 | > sage: d[2] = 'DD' |
---|
119 | > sage: f |
---|
120 | > Finite family {1: 'a', 3: 'b', 4: 'c'} |
---|
121 | > """ |
---|
122 | 362c422 |
---|
123 | < self.dictionary = dictionary |
---|
124 | --- |
---|
125 | > self.dictionary = dict(dictionary) |
---|
126 | 409c469 |
---|
127 | < return ZZ(len(self.dictionary)) |
---|
128 | --- |
---|
129 | > return Integer(len(self.dictionary)) |
---|
130 | 450c510 |
---|
131 | < EXAMPLES:: |
---|
132 | --- |
---|
133 | > TESTS:: |
---|
134 | 524c584 |
---|
135 | < EXAMPLES:: |
---|
136 | --- |
---|
137 | > TESTS:: |
---|
138 | 540c600 |
---|
139 | < EXAMPLES:: |
---|
140 | --- |
---|
141 | > TESTS:: |
---|
142 | 549a610,617 |
---|
143 | > |
---|
144 | > sage: f = LazyFamily(Permutations(3), lambda p: p.to_lehmer_code()) |
---|
145 | > sage: f == loads(dumps(f)) |
---|
146 | > True |
---|
147 | > |
---|
148 | > sage: f = LazyFamily(Permutations(3), attrcall("to_lehmer_code")) |
---|
149 | > sage: f == loads(dumps(f)) |
---|
150 | > True |
---|
151 | 551,552c619,623 |
---|
152 | < from sage.misc.fpickle import unpickle_function |
---|
153 | < hidden_function = unpickle_function(d['hidden_function']) |
---|
154 | --- |
---|
155 | > hidden_function = d['hidden_function'] |
---|
156 | > if isinstance(hidden_function, str): |
---|
157 | > # Let's assume that hidden_function is an unpicled function. |
---|
158 | > from sage.misc.fpickle import unpickle_function |
---|
159 | > hidden_function = unpickle_function(hidden_function) |
---|
160 | 567c638 |
---|
161 | < EXAMPLES:: |
---|
162 | --- |
---|
163 | > TESTS:: |
---|
164 | 572a644,652 |
---|
165 | > |
---|
166 | > Check for bug #5538:: |
---|
167 | > |
---|
168 | > sage: l = [3,4,7] |
---|
169 | > sage: f = LazyFamily(l, lambda i: 2r*i); |
---|
170 | > sage: l[1] = 18 |
---|
171 | > sage: f |
---|
172 | > Lazy family (f(i))_{i in [3, 4, 7]} |
---|
173 | > |
---|
174 | 574c654,655 |
---|
175 | < self.set = set |
---|
176 | --- |
---|
177 | > from copy import copy |
---|
178 | > self.set = copy(set) |
---|
179 | 610c691 |
---|
180 | < return ZZ(len(self.set)) |
---|
181 | --- |
---|
182 | > return Integer(len(self.set)) |
---|
183 | 649,650c730,736 |
---|
184 | < from sage.misc.fpickle import pickle_function |
---|
185 | < f = pickle_function(self.function) |
---|
186 | --- |
---|
187 | > f = self.function |
---|
188 | > # This should be done once for all by registering |
---|
189 | > # sage.misc.fpickle.pickle_function to copy_reg |
---|
190 | > if type(f) is type(Family): # TODO: where is the python `function` type? |
---|
191 | > from sage.misc.fpickle import pickle_function |
---|
192 | > f = pickle_function(f) |
---|
193 | > |
---|
194 | 668,669c754,759 |
---|
195 | < from sage.misc.fpickle import unpickle_function |
---|
196 | < function = unpickle_function(d['function']) |
---|
197 | --- |
---|
198 | > function = d['function'] |
---|
199 | > if isinstance(function, str): |
---|
200 | > # Let's assume that function is an unpicled function. |
---|
201 | > from sage.misc.fpickle import unpickle_function |
---|
202 | > function = unpickle_function(function) |
---|
203 | > |
---|
204 | 670a761,858 |
---|
205 | > |
---|
206 | > |
---|
207 | > class TrivialFamily(AbstractFamily): |
---|
208 | > r""" |
---|
209 | > ``TrivialFamily(c)`` turn the container c into a family indexed by |
---|
210 | > the set `{0,\dots, len(c)}`. The container `c` can be either a list or a |
---|
211 | > tuple. |
---|
212 | > |
---|
213 | > Instances should be created via the Family factory, which see for |
---|
214 | > examples and tests. |
---|
215 | > """ |
---|
216 | > def __init__(self, set): |
---|
217 | > """ |
---|
218 | > EXAMPLES:: |
---|
219 | > |
---|
220 | > sage: f = TrivialFamily((3,4,7)); f |
---|
221 | > Family (3, 4, 7) |
---|
222 | > sage: f = TrivialFamily([3,4,7]); f |
---|
223 | > Family (3, 4, 7) |
---|
224 | > sage: f == loads(dumps(f)) |
---|
225 | > True |
---|
226 | > """ |
---|
227 | > self.set = tuple(set) |
---|
228 | > |
---|
229 | > def __repr__(self): |
---|
230 | > """ |
---|
231 | > EXAMPLES:: |
---|
232 | > |
---|
233 | > sage: f = TrivialFamily([3,4,7]); f |
---|
234 | > Family (3, 4, 7) |
---|
235 | > """ |
---|
236 | > return "Family %s"%((self.set),) |
---|
237 | > |
---|
238 | > def keys(self): |
---|
239 | > """ |
---|
240 | > Returns self's keys. |
---|
241 | > |
---|
242 | > EXAMPLES:: |
---|
243 | > |
---|
244 | > sage: f = TrivialFamily([3,4,7]) |
---|
245 | > sage: f.keys() |
---|
246 | > [0, 1, 2] |
---|
247 | > """ |
---|
248 | > return range(len(self.set)) |
---|
249 | > |
---|
250 | > def cardinality(self): |
---|
251 | > """ |
---|
252 | > Return the number of elements in self. |
---|
253 | > |
---|
254 | > EXAMPLES:: |
---|
255 | > |
---|
256 | > sage: f = TrivialFamily([3,4,7]) |
---|
257 | > sage: f.cardinality() |
---|
258 | > 3 |
---|
259 | > """ |
---|
260 | > return Integer(len(self.set)) |
---|
261 | > |
---|
262 | > def __iter__(self): |
---|
263 | > """ |
---|
264 | > EXAMPLES:: |
---|
265 | > |
---|
266 | > sage: f = TrivialFamily([3,4,7]) |
---|
267 | > sage: [i for i in f] |
---|
268 | > [3, 4, 7] |
---|
269 | > """ |
---|
270 | > for i in self.set: |
---|
271 | > yield i |
---|
272 | > |
---|
273 | > def __getitem__(self, i): |
---|
274 | > """ |
---|
275 | > EXAMPLES:: |
---|
276 | > |
---|
277 | > sage: f = TrivialFamily([3,4,7]) |
---|
278 | > sage: f[1] |
---|
279 | > 4 |
---|
280 | > """ |
---|
281 | > return self.set[i] |
---|
282 | > |
---|
283 | > def __getstate__(self): |
---|
284 | > """ |
---|
285 | > TESTS:: |
---|
286 | > |
---|
287 | > sage: f = TrivialFamily([3,4,7]) |
---|
288 | > sage: f.__getstate__() |
---|
289 | > {'set': (3, 4, 7)} |
---|
290 | > """ |
---|
291 | > return {'set': self.set} |
---|
292 | > |
---|
293 | > def __setstate__(self, state): |
---|
294 | > """ |
---|
295 | > TESTS:: |
---|
296 | > |
---|
297 | > sage: f = TrivialFamily([3,4,7]) |
---|
298 | > sage: f.__setstate__({'set': (2, 4, 8)}) |
---|
299 | > sage: f |
---|
300 | > Family (2, 4, 8) |
---|
301 | > """ |
---|
302 | > self.__init__(state['set']) |
---|