passagemath-objects 10.6.47__cp311-cp311-macosx_13_0_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.
Files changed (280) hide show
  1. passagemath_objects/.dylibs/libgmp.10.dylib +0 -0
  2. passagemath_objects/__init__.py +3 -0
  3. passagemath_objects-10.6.47.dist-info/METADATA +115 -0
  4. passagemath_objects-10.6.47.dist-info/RECORD +280 -0
  5. passagemath_objects-10.6.47.dist-info/WHEEL +6 -0
  6. passagemath_objects-10.6.47.dist-info/top_level.txt +3 -0
  7. sage/all__sagemath_objects.py +37 -0
  8. sage/arith/all__sagemath_objects.py +5 -0
  9. sage/arith/long.pxd +411 -0
  10. sage/arith/numerical_approx.cpython-311-darwin.so +0 -0
  11. sage/arith/numerical_approx.pxd +35 -0
  12. sage/arith/numerical_approx.pyx +75 -0
  13. sage/arith/power.cpython-311-darwin.so +0 -0
  14. sage/arith/power.pxd +31 -0
  15. sage/arith/power.pyx +127 -0
  16. sage/categories/action.cpython-311-darwin.so +0 -0
  17. sage/categories/action.pxd +29 -0
  18. sage/categories/action.pyx +641 -0
  19. sage/categories/algebra_functor.py +745 -0
  20. sage/categories/all__sagemath_objects.py +33 -0
  21. sage/categories/basic.py +62 -0
  22. sage/categories/cartesian_product.py +295 -0
  23. sage/categories/category.py +3401 -0
  24. sage/categories/category_cy_helper.cpython-311-darwin.so +0 -0
  25. sage/categories/category_cy_helper.pxd +8 -0
  26. sage/categories/category_cy_helper.pyx +322 -0
  27. sage/categories/category_singleton.cpython-311-darwin.so +0 -0
  28. sage/categories/category_singleton.pxd +3 -0
  29. sage/categories/category_singleton.pyx +342 -0
  30. sage/categories/category_types.py +637 -0
  31. sage/categories/category_with_axiom.py +2876 -0
  32. sage/categories/covariant_functorial_construction.py +703 -0
  33. sage/categories/facade_sets.py +228 -0
  34. sage/categories/functor.cpython-311-darwin.so +0 -0
  35. sage/categories/functor.pxd +7 -0
  36. sage/categories/functor.pyx +691 -0
  37. sage/categories/homset.py +1338 -0
  38. sage/categories/homsets.py +364 -0
  39. sage/categories/isomorphic_objects.py +73 -0
  40. sage/categories/map.cpython-311-darwin.so +0 -0
  41. sage/categories/map.pxd +34 -0
  42. sage/categories/map.pyx +2106 -0
  43. sage/categories/morphism.cpython-311-darwin.so +0 -0
  44. sage/categories/morphism.pxd +14 -0
  45. sage/categories/morphism.pyx +895 -0
  46. sage/categories/objects.py +167 -0
  47. sage/categories/primer.py +1696 -0
  48. sage/categories/pushout.py +4834 -0
  49. sage/categories/quotients.py +64 -0
  50. sage/categories/realizations.py +200 -0
  51. sage/categories/sets_cat.py +3290 -0
  52. sage/categories/sets_with_partial_maps.py +52 -0
  53. sage/categories/subobjects.py +64 -0
  54. sage/categories/subquotients.py +21 -0
  55. sage/categories/with_realizations.py +311 -0
  56. sage/cpython/__init__.py +19 -0
  57. sage/cpython/_py2_random.py +619 -0
  58. sage/cpython/all.py +3 -0
  59. sage/cpython/atexit.cpython-311-darwin.so +0 -0
  60. sage/cpython/atexit.pyx +269 -0
  61. sage/cpython/builtin_types.cpython-311-darwin.so +0 -0
  62. sage/cpython/builtin_types.pyx +7 -0
  63. sage/cpython/cython_metaclass.cpython-311-darwin.so +0 -0
  64. sage/cpython/cython_metaclass.h +117 -0
  65. sage/cpython/cython_metaclass.pxd +3 -0
  66. sage/cpython/cython_metaclass.pyx +130 -0
  67. sage/cpython/debug.cpython-311-darwin.so +0 -0
  68. sage/cpython/debug.pyx +302 -0
  69. sage/cpython/dict_del_by_value.cpython-311-darwin.so +0 -0
  70. sage/cpython/dict_del_by_value.pxd +9 -0
  71. sage/cpython/dict_del_by_value.pyx +191 -0
  72. sage/cpython/dict_internal.h +245 -0
  73. sage/cpython/getattr.cpython-311-darwin.so +0 -0
  74. sage/cpython/getattr.pxd +9 -0
  75. sage/cpython/getattr.pyx +439 -0
  76. sage/cpython/pycore_long.h +97 -0
  77. sage/cpython/pycore_long.pxd +10 -0
  78. sage/cpython/python_debug.h +44 -0
  79. sage/cpython/python_debug.pxd +47 -0
  80. sage/cpython/pyx_visit.h +13 -0
  81. sage/cpython/string.cpython-311-darwin.so +0 -0
  82. sage/cpython/string.pxd +76 -0
  83. sage/cpython/string.pyx +34 -0
  84. sage/cpython/string_impl.h +60 -0
  85. sage/cpython/type.cpython-311-darwin.so +0 -0
  86. sage/cpython/type.pxd +2 -0
  87. sage/cpython/type.pyx +40 -0
  88. sage/cpython/wrapperdescr.pxd +67 -0
  89. sage/ext/all__sagemath_objects.py +3 -0
  90. sage/ext/ccobject.h +64 -0
  91. sage/ext/cplusplus.pxd +17 -0
  92. sage/ext/mod_int.h +30 -0
  93. sage/ext/mod_int.pxd +24 -0
  94. sage/ext/stdsage.pxd +39 -0
  95. sage/groups/all__sagemath_objects.py +1 -0
  96. sage/groups/group.cpython-311-darwin.so +0 -0
  97. sage/groups/group.pxd +14 -0
  98. sage/groups/group.pyx +322 -0
  99. sage/groups/old.cpython-311-darwin.so +0 -0
  100. sage/groups/old.pxd +14 -0
  101. sage/groups/old.pyx +219 -0
  102. sage/libs/all__sagemath_objects.py +3 -0
  103. sage/libs/gmp/__init__.py +1 -0
  104. sage/libs/gmp/all.pxd +6 -0
  105. sage/libs/gmp/binop.pxd +23 -0
  106. sage/libs/gmp/misc.pxd +8 -0
  107. sage/libs/gmp/mpf.pxd +88 -0
  108. sage/libs/gmp/mpn.pxd +57 -0
  109. sage/libs/gmp/mpq.pxd +57 -0
  110. sage/libs/gmp/mpz.pxd +202 -0
  111. sage/libs/gmp/pylong.cpython-311-darwin.so +0 -0
  112. sage/libs/gmp/pylong.pxd +12 -0
  113. sage/libs/gmp/pylong.pyx +150 -0
  114. sage/libs/gmp/random.pxd +25 -0
  115. sage/libs/gmp/randomize.pxd +59 -0
  116. sage/libs/gmp/types.pxd +53 -0
  117. sage/libs/gmpxx.pxd +19 -0
  118. sage/misc/abstract_method.py +276 -0
  119. sage/misc/all__sagemath_objects.py +43 -0
  120. sage/misc/bindable_class.py +253 -0
  121. sage/misc/c3_controlled.cpython-311-darwin.so +0 -0
  122. sage/misc/c3_controlled.pxd +2 -0
  123. sage/misc/c3_controlled.pyx +1402 -0
  124. sage/misc/cachefunc.cpython-311-darwin.so +0 -0
  125. sage/misc/cachefunc.pxd +43 -0
  126. sage/misc/cachefunc.pyx +3781 -0
  127. sage/misc/call.py +188 -0
  128. sage/misc/classcall_metaclass.cpython-311-darwin.so +0 -0
  129. sage/misc/classcall_metaclass.pxd +14 -0
  130. sage/misc/classcall_metaclass.pyx +599 -0
  131. sage/misc/constant_function.cpython-311-darwin.so +0 -0
  132. sage/misc/constant_function.pyx +130 -0
  133. sage/misc/decorators.py +747 -0
  134. sage/misc/fast_methods.cpython-311-darwin.so +0 -0
  135. sage/misc/fast_methods.pxd +20 -0
  136. sage/misc/fast_methods.pyx +351 -0
  137. sage/misc/flatten.py +90 -0
  138. sage/misc/fpickle.cpython-311-darwin.so +0 -0
  139. sage/misc/fpickle.pyx +177 -0
  140. sage/misc/function_mangling.cpython-311-darwin.so +0 -0
  141. sage/misc/function_mangling.pxd +11 -0
  142. sage/misc/function_mangling.pyx +308 -0
  143. sage/misc/inherit_comparison.cpython-311-darwin.so +0 -0
  144. sage/misc/inherit_comparison.pxd +5 -0
  145. sage/misc/inherit_comparison.pyx +105 -0
  146. sage/misc/instancedoc.cpython-311-darwin.so +0 -0
  147. sage/misc/instancedoc.pyx +331 -0
  148. sage/misc/lazy_attribute.cpython-311-darwin.so +0 -0
  149. sage/misc/lazy_attribute.pyx +607 -0
  150. sage/misc/lazy_format.py +135 -0
  151. sage/misc/lazy_import.cpython-311-darwin.so +0 -0
  152. sage/misc/lazy_import.pyx +1299 -0
  153. sage/misc/lazy_import_cache.py +36 -0
  154. sage/misc/lazy_list.cpython-311-darwin.so +0 -0
  155. sage/misc/lazy_list.pxd +19 -0
  156. sage/misc/lazy_list.pyx +1187 -0
  157. sage/misc/lazy_string.cpython-311-darwin.so +0 -0
  158. sage/misc/lazy_string.pxd +7 -0
  159. sage/misc/lazy_string.pyx +546 -0
  160. sage/misc/misc.py +1066 -0
  161. sage/misc/misc_c.cpython-311-darwin.so +0 -0
  162. sage/misc/misc_c.pxd +3 -0
  163. sage/misc/misc_c.pyx +766 -0
  164. sage/misc/namespace_package.py +37 -0
  165. sage/misc/nested_class.cpython-311-darwin.so +0 -0
  166. sage/misc/nested_class.pxd +3 -0
  167. sage/misc/nested_class.pyx +394 -0
  168. sage/misc/persist.cpython-311-darwin.so +0 -0
  169. sage/misc/persist.pyx +1251 -0
  170. sage/misc/prandom.py +418 -0
  171. sage/misc/randstate.cpython-311-darwin.so +0 -0
  172. sage/misc/randstate.pxd +30 -0
  173. sage/misc/randstate.pyx +1059 -0
  174. sage/misc/repr.py +203 -0
  175. sage/misc/reset.cpython-311-darwin.so +0 -0
  176. sage/misc/reset.pyx +196 -0
  177. sage/misc/sage_ostools.cpython-311-darwin.so +0 -0
  178. sage/misc/sage_ostools.pyx +323 -0
  179. sage/misc/sage_timeit.py +275 -0
  180. sage/misc/sage_timeit_class.cpython-311-darwin.so +0 -0
  181. sage/misc/sage_timeit_class.pyx +120 -0
  182. sage/misc/sage_unittest.py +637 -0
  183. sage/misc/sageinspect.py +2768 -0
  184. sage/misc/session.cpython-311-darwin.so +0 -0
  185. sage/misc/session.pyx +392 -0
  186. sage/misc/superseded.py +557 -0
  187. sage/misc/test_nested_class.py +228 -0
  188. sage/misc/timing.py +264 -0
  189. sage/misc/unknown.py +222 -0
  190. sage/misc/verbose.py +253 -0
  191. sage/misc/weak_dict.cpython-311-darwin.so +0 -0
  192. sage/misc/weak_dict.pxd +15 -0
  193. sage/misc/weak_dict.pyx +1231 -0
  194. sage/modules/all__sagemath_objects.py +1 -0
  195. sage/modules/module.cpython-311-darwin.so +0 -0
  196. sage/modules/module.pxd +5 -0
  197. sage/modules/module.pyx +329 -0
  198. sage/rings/all__sagemath_objects.py +3 -0
  199. sage/rings/integer_fake.h +22 -0
  200. sage/rings/integer_fake.pxd +55 -0
  201. sage/sets/all__sagemath_objects.py +3 -0
  202. sage/sets/pythonclass.cpython-311-darwin.so +0 -0
  203. sage/sets/pythonclass.pxd +9 -0
  204. sage/sets/pythonclass.pyx +247 -0
  205. sage/structure/__init__.py +4 -0
  206. sage/structure/all.py +30 -0
  207. sage/structure/category_object.cpython-311-darwin.so +0 -0
  208. sage/structure/category_object.pxd +28 -0
  209. sage/structure/category_object.pyx +1087 -0
  210. sage/structure/coerce.cpython-311-darwin.so +0 -0
  211. sage/structure/coerce.pxd +44 -0
  212. sage/structure/coerce.pyx +2107 -0
  213. sage/structure/coerce_actions.cpython-311-darwin.so +0 -0
  214. sage/structure/coerce_actions.pxd +27 -0
  215. sage/structure/coerce_actions.pyx +988 -0
  216. sage/structure/coerce_dict.cpython-311-darwin.so +0 -0
  217. sage/structure/coerce_dict.pxd +51 -0
  218. sage/structure/coerce_dict.pyx +1557 -0
  219. sage/structure/coerce_exceptions.py +23 -0
  220. sage/structure/coerce_maps.cpython-311-darwin.so +0 -0
  221. sage/structure/coerce_maps.pxd +28 -0
  222. sage/structure/coerce_maps.pyx +718 -0
  223. sage/structure/debug_options.cpython-311-darwin.so +0 -0
  224. sage/structure/debug_options.pxd +6 -0
  225. sage/structure/debug_options.pyx +54 -0
  226. sage/structure/dynamic_class.py +541 -0
  227. sage/structure/element.cpython-311-darwin.so +0 -0
  228. sage/structure/element.pxd +272 -0
  229. sage/structure/element.pyx +4772 -0
  230. sage/structure/element_wrapper.cpython-311-darwin.so +0 -0
  231. sage/structure/element_wrapper.pxd +12 -0
  232. sage/structure/element_wrapper.pyx +582 -0
  233. sage/structure/factorization.py +1422 -0
  234. sage/structure/factorization_integer.py +105 -0
  235. sage/structure/factory.cpython-311-darwin.so +0 -0
  236. sage/structure/factory.pyx +786 -0
  237. sage/structure/formal_sum.py +489 -0
  238. sage/structure/gens_py.py +73 -0
  239. sage/structure/global_options.py +1743 -0
  240. sage/structure/indexed_generators.py +863 -0
  241. sage/structure/list_clone.cpython-311-darwin.so +0 -0
  242. sage/structure/list_clone.pxd +65 -0
  243. sage/structure/list_clone.pyx +1867 -0
  244. sage/structure/list_clone_demo.cpython-311-darwin.so +0 -0
  245. sage/structure/list_clone_demo.pyx +248 -0
  246. sage/structure/list_clone_timings.py +179 -0
  247. sage/structure/list_clone_timings_cy.cpython-311-darwin.so +0 -0
  248. sage/structure/list_clone_timings_cy.pyx +86 -0
  249. sage/structure/mutability.cpython-311-darwin.so +0 -0
  250. sage/structure/mutability.pxd +21 -0
  251. sage/structure/mutability.pyx +348 -0
  252. sage/structure/nonexact.py +69 -0
  253. sage/structure/parent.cpython-311-darwin.so +0 -0
  254. sage/structure/parent.pxd +112 -0
  255. sage/structure/parent.pyx +3093 -0
  256. sage/structure/parent_base.cpython-311-darwin.so +0 -0
  257. sage/structure/parent_base.pxd +13 -0
  258. sage/structure/parent_base.pyx +44 -0
  259. sage/structure/parent_gens.cpython-311-darwin.so +0 -0
  260. sage/structure/parent_gens.pxd +22 -0
  261. sage/structure/parent_gens.pyx +377 -0
  262. sage/structure/parent_old.cpython-311-darwin.so +0 -0
  263. sage/structure/parent_old.pxd +25 -0
  264. sage/structure/parent_old.pyx +294 -0
  265. sage/structure/proof/__init__.py +1 -0
  266. sage/structure/proof/all.py +243 -0
  267. sage/structure/proof/proof.py +300 -0
  268. sage/structure/richcmp.cpython-311-darwin.so +0 -0
  269. sage/structure/richcmp.pxd +213 -0
  270. sage/structure/richcmp.pyx +495 -0
  271. sage/structure/sage_object.cpython-311-darwin.so +0 -0
  272. sage/structure/sage_object.pxd +3 -0
  273. sage/structure/sage_object.pyx +988 -0
  274. sage/structure/sage_object_test.py +19 -0
  275. sage/structure/sequence.py +937 -0
  276. sage/structure/set_factories.py +1178 -0
  277. sage/structure/set_factories_example.py +527 -0
  278. sage/structure/support_view.py +179 -0
  279. sage/structure/test_factory.py +56 -0
  280. sage/structure/unique_representation.py +1359 -0
@@ -0,0 +1,1178 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ r"""
3
+ Set factories
4
+ =============
5
+
6
+
7
+ A *set factory* `F` is a device for constructing some :class:`Parent`
8
+ `P` that models subsets of a big set `S`. Typically, each such parent
9
+ is constructed as the subset of `S` of all elements satisfying a
10
+ certain collection of constraints `cons`. In such a hierarchy of
11
+ subsets, one needs an easy and flexible control on how elements are
12
+ constructed. For example, one may want to construct the elements of
13
+ `P` in some subclass of the class of the elements of `S`. On other
14
+ occasions, one also often needs `P` to be a facade parent, whose
15
+ elements are represented as elements of `S` (see
16
+ :class:`~sage.categories.facade_sets.FacadeSets`).
17
+
18
+ The role of a set factory is twofold:
19
+
20
+ - *Manage a database* of constructors for the different parents `P = F(cons)`
21
+ depending on the various kinds of constraints `cons`. Note: currently there
22
+ is no real support for that. We are gathering use cases before fixing the
23
+ interface.
24
+
25
+ - Ensure that the elements `e = P(...)` created by the different parents
26
+ follows a consistent policy concerning their *class and parent*.
27
+
28
+ .. RUBRIC:: Basic usage: constructing parents through a factory
29
+
30
+ The file :mod:`sage.structure.set_factories_example` shows an example of a
31
+ :class:`SetFactory` together with typical implementation. Note that the
32
+ written code is intentionally kept minimal, many things and in particular
33
+ several iterators could be written in a more efficient way.
34
+
35
+ Consider the set `S` of couples `(x,y)` with `x` and `y` in `I:=\{0,1,2,3,4\}`.
36
+ We represent an element of `S` as a 2-elements tuple, wrapped in a class
37
+ :class:`~.set_factories_example.XYPair` deriving from :class:`ElementWrapper`.
38
+ You can create a :class:`~.set_factories_example.XYPair` with any
39
+ :class:`Parent`::
40
+
41
+ sage: from sage.structure.set_factories import *
42
+ sage: from sage.structure.set_factories_example import *
43
+ sage: p = XYPair(Parent(), (0,1)); p
44
+ (0, 1)
45
+
46
+ Now, given `(a, b)\in S` we want to consider the following subsets of
47
+ `S`
48
+
49
+ .. MATH::
50
+
51
+ S_a := \{(x,y) \in S \mid x = a\},
52
+
53
+ S^b := \{(x,y) \in S \mid y = b\},
54
+
55
+ S_a^b := \{(x,y) \in S \mid x = a, y = b\}.
56
+
57
+ The constraints considered here are admittedly trivial. In a realistic
58
+ example, there would be much more of them. And for some sets of constraints
59
+ no good enumeration algorithms would be known.
60
+
61
+ In Sage, those sets are constructed by passing the constraints to the
62
+ factory. We first create the set with no constraints at all::
63
+
64
+ sage: XYPairs
65
+ Factory for XY pairs
66
+ sage: S = XYPairs(); S.list()
67
+ [(0, 0), (1, 0), ..., (4, 0), (0, 1), (1, 1), ..., (3, 4), (4, 4)]
68
+ sage: S.cardinality()
69
+ 25
70
+
71
+ Let us construct `S_2`, `S^3` and `S_2^3`::
72
+
73
+ sage: Sx2 = XYPairs(x=2); Sx2.list()
74
+ [(2, 0), (2, 1), (2, 2), (2, 3), (2, 4)]
75
+ sage: Sy3 = XYPairs(y=3); Sy3.list()
76
+ [(0, 3), (1, 3), (2, 3), (3, 3), (4, 3)]
77
+ sage: S23 = XYPairs(x=2, y=3); S23.list()
78
+ [(2, 3)]
79
+
80
+ Set factories provide an alternative way to build subsets of an
81
+ already constructed set: each set constructed by a factory has a
82
+ method :meth:`~ParentWithSetFactory.subset` which accept new
83
+ constraints. Sets constructed by the factory or the
84
+ :meth:`~ParentWithSetFactory.subset` methods are identical::
85
+
86
+ sage: Sx2s = S.subset(x=2); Sx2 is Sx2s
87
+ True
88
+ sage: Sx2.subset(y=3) is S23
89
+ True
90
+
91
+ It is not possible to change an already given constraint::
92
+
93
+ sage: S23.subset(y=5)
94
+ Traceback (most recent call last):
95
+ ...
96
+ ValueError: Duplicate value for constraints 'y': was 3 now 5
97
+
98
+ .. RUBRIC:: Constructing custom elements: policies
99
+
100
+ We now come to the point of factories: constructing custom elements. The
101
+ writer of :func:`~.set_factories_example.XYPairs` decided that, by default,
102
+ the parents ``Sx2``, ``Sy3`` and ``S23`` are facade for parent ``S``. This
103
+ means that each element constructed by those subsets behaves as if they where
104
+ directly constructed by ``S`` itself::
105
+
106
+ sage: Sx2.an_element().parent()
107
+ AllPairs
108
+ sage: el = Sx2.an_element()
109
+ sage: el.parent() is S
110
+ True
111
+ sage: type(el) is S.element_class
112
+ True
113
+
114
+ This is not always desirable. The device which decides how to construct an
115
+ element is called a *policy* (see :class:`SetFactoryPolicy`). Each factory
116
+ should have a default policy. Here is the policy of
117
+ :func:`~.set_factories_example.XYPairs`::
118
+
119
+ sage: XYPairs._default_policy
120
+ Set factory policy for <class 'sage.structure.set_factories_example.XYPair'> with parent AllPairs[=Factory for XY pairs(())]
121
+
122
+ This means that with the current policy, the parent builds elements with class
123
+ ``XYPair`` and parent ``AllPairs`` which is itself constructed by calling the
124
+ factory :func:`~.set_factories_example.XYPairs` with constraints ``()``. There
125
+ is a lot of flexibility to change that. We now illustrate how to make a few
126
+ different choices.
127
+
128
+ 1 - In a first use case, we want to add some methods to the constructed
129
+ elements. As illustration, we add here a new method ``sum`` which returns
130
+ `x+y`. We therefore create a new class for the elements which inherits from
131
+ :class:`~.set_factories_example.XYPair`::
132
+
133
+ sage: class NewXYPair(XYPair):
134
+ ....: def sum(self):
135
+ ....: return sum(self.value)
136
+
137
+ Here is an instance of this class (with a dummy parent)::
138
+
139
+ sage: el = NewXYPair(Parent(), (2,3))
140
+ sage: el.sum()
141
+ 5
142
+
143
+ We now want to have subsets generating those new elements while still having a
144
+ single real parent (the one with no constraint) for each element. The
145
+ corresponding policy is called :class:`TopMostParentPolicy`. It takes three
146
+ parameters:
147
+
148
+ - the factory;
149
+ - the parameters for void constraint;
150
+ - the class used for elements.
151
+
152
+ Calling the factory with this policy returns a new set which builds its
153
+ elements with the new policy::
154
+
155
+ sage: new_policy = TopMostParentPolicy(XYPairs, (), NewXYPair)
156
+ sage: NewS = XYPairs(policy=new_policy)
157
+ sage: el = NewS.an_element(); el
158
+ (0, 0)
159
+ sage: el.sum()
160
+ 0
161
+ sage: el.parent() is NewS
162
+ True
163
+ sage: isinstance(el, NewXYPair)
164
+ True
165
+
166
+ Newly constructed subsets inherit the policy::
167
+
168
+ sage: NewS2 = NewS.subset(x=2)
169
+ sage: el2 = NewS2.an_element(); el2
170
+ (2, 0)
171
+ sage: el2.sum()
172
+ 2
173
+ sage: el2.parent() is NewS
174
+ True
175
+
176
+ 2 - In a second use case, we want the elements to remember which
177
+ parent created them. The corresponding policy is called
178
+ :class:`SelfParentPolicy`. It takes only two parameters:
179
+
180
+ - the factory;
181
+ - the class used for elements.
182
+
183
+ Here is an example::
184
+
185
+ sage: selfpolicy = SelfParentPolicy(XYPairs, NewXYPair)
186
+ sage: SelfS = XYPairs(policy=selfpolicy)
187
+ sage: el = SelfS.an_element()
188
+ sage: el.parent() is SelfS
189
+ True
190
+
191
+ Now all subsets are the parent of the elements that they create::
192
+
193
+ sage: SelfS2 = SelfS.subset(x=2)
194
+ sage: el2 = SelfS2.an_element()
195
+ sage: el2.parent() is NewS
196
+ False
197
+ sage: el2.parent() is SelfS2
198
+ True
199
+
200
+ 3 - Finally, a common use case is to construct simple python object which are
201
+ not Sage :class:`sage.structure.Element`. As an example, we show how to build
202
+ a parent ``TupleS`` which construct pairs as tuple. The corresponding policy
203
+ is called :class:`BareFunctionPolicy`. It takes two parameters:
204
+
205
+ - the factory;
206
+ - the function called to construct the elements.
207
+
208
+ Here is how to do it::
209
+
210
+ sage: cons = lambda t, check: tuple(t) # ignore the check parameter
211
+ sage: tuplepolicy = BareFunctionPolicy(XYPairs, cons)
212
+ sage: P = XYPairs(x=2, policy=tuplepolicy)
213
+ sage: P.list()
214
+ [(2, 0), (2, 1), (2, 2), (2, 3), (2, 4)]
215
+ sage: el = P.an_element()
216
+ sage: type(el)
217
+ <... 'tuple'>
218
+
219
+ Here are the currently implemented policies:
220
+
221
+ - :class:`FacadeParentPolicy`: reuse an existing parent together with
222
+ its element_class
223
+
224
+ - :class:`TopMostParentPolicy`: use a parent created by the factory
225
+ itself and provide a class ``Element`` for it. In this case, we need
226
+ to specify the set of constraints which build this parent taking the
227
+ ownership of all elements and the class which will be used for the
228
+ ``Element``.
229
+
230
+ - :class:`SelfParentPolicy`: provide systematically ``Element`` and
231
+ element_class and ensure that the parent is ``self``.
232
+
233
+ - :class:`BareFunctionPolicy`: instead of calling a class constructor element
234
+ are passed to a function provided to the policy.
235
+
236
+ .. TODO::
237
+
238
+ Generalize :class:`TopMostParentPolicy` to be able to have several
239
+ topmost parents.
240
+
241
+ .. RUBRIC:: Technicalities: how policies inform parents
242
+
243
+ Parents built from factories should inherit from
244
+ :class:`ParentWithSetFactory`. This class provide a few methods
245
+ related to factories and policies. The ``__init__`` method of
246
+ :class:`ParentWithSetFactory` must be provided with the set of
247
+ constraints and the policy. A parent built from a factory must create
248
+ elements through a call to the method ``_element_constructor_``. The
249
+ current way in which policies inform parents how to builds their elements is
250
+ set by a few attributes. So the class must accept attribute
251
+ adding. The precise details of which attributes are set may be subject
252
+ to change in the future.
253
+
254
+ .. RUBRIC:: How to write a set factory
255
+
256
+ .. SEEALSO:: :mod:`.set_factories_example` for an example of a factory.
257
+
258
+ Here are the specifications:
259
+
260
+ A parent built from a factory should
261
+
262
+ - *inherit* from :class:`ParentWithSetFactory`. It should accept a
263
+ ``policy`` argument and pass it verbatim to the ``__init__`` method
264
+ of :class:`ParentWithSetFactory` together with the set of
265
+ constraints;
266
+
267
+ - *create its elements* through calls to the method
268
+ ``_element_constructor_``;
269
+
270
+ - *define a method* :class:`ParentWithSetFactory.check_element` which
271
+ checks if a built element indeed belongs to it. The method should
272
+ accept an extra keyword parameter called ``check`` specifying which
273
+ level of check should be performed. It will only be called when
274
+ ``bool(check)`` evaluates to ``True``.
275
+
276
+ The constructor of the elements of a parent from a factory should:
277
+
278
+ - receive the parent as first mandatory argument;
279
+
280
+ - accept an extra optional keyword parameter called ``check`` which is meant
281
+ to tell if the input must be checked or not. The precise meaning of
282
+ ``check`` is intentionally left vague. The only intent is that if
283
+ ``bool(check)`` evaluates to ``False``, no check is performed at all.
284
+
285
+ A factory should
286
+
287
+ - *define a method* ``__call__`` which is responsible for calling the
288
+ appropriate parent constructor given the constraints;
289
+
290
+ - *define a method* overloading :meth:`SetFactory.add_constraints` which is
291
+ responsible of computing the union of two sets of constraints;
292
+
293
+ - *optionally* define a method or an attribute ``_default_policy`` passed to
294
+ the :class:`ParentWithSetFactory` if no policy is given to the factory.
295
+
296
+
297
+ .. TODO::
298
+
299
+ There is currently no support for dealing with sets of
300
+ constraints. The set factory and the parents must cooperate to
301
+ consistently handle them. More support, together with a generic mechanism
302
+ to select the appropriate parent class from the constraints, will be added
303
+ as soon as we have gathered sufficiently enough use-cases.
304
+
305
+ AUTHORS:
306
+
307
+ - Florent Hivert (2011-2012): initial revision
308
+ """
309
+ # ****************************************************************************
310
+ # Copyright (C) 2012 Florent Hivert <florent.hivert at lri.fr>
311
+ #
312
+ # Distributed under the terms of the GNU General Public License (GPL)
313
+ # https://www.gnu.org/licenses/
314
+ # ****************************************************************************
315
+
316
+
317
+ from sage.structure.sage_object import SageObject
318
+ from sage.structure.parent import Parent
319
+ from sage.structure.unique_representation import UniqueRepresentation
320
+ from sage.misc.abstract_method import abstract_method
321
+
322
+ ####################################################
323
+ # Factories #
324
+ ####################################################
325
+
326
+
327
+ class SetFactory(UniqueRepresentation, SageObject):
328
+ r"""
329
+ This class is currently just a stub that we will be using to add
330
+ more structures on factories.
331
+
332
+ TESTS::
333
+
334
+ sage: from sage.structure.set_factories import SetFactory
335
+ sage: S = SetFactory()
336
+ sage: S.__call__("foo")
337
+ Traceback (most recent call last):
338
+ ...
339
+ NotImplementedError: <abstract method __call__ at ...>
340
+ sage: S.add_constraints("foo")
341
+ Traceback (most recent call last):
342
+ ...
343
+ NotImplementedError: <abstract method add_constraints at ...>
344
+ """
345
+ @abstract_method
346
+ def __call__(self, *constraints, **consdict):
347
+ r"""
348
+ Construct the parent associated with the constraints in
349
+ argument. This should return a :class:`Parent`.
350
+
351
+ .. NOTE::
352
+
353
+ Currently there is no specification on how constraints are
354
+ passed as arguments.
355
+
356
+ EXAMPLES::
357
+
358
+ sage: from sage.structure.set_factories_example import XYPairs
359
+ sage: XYPairs()
360
+ AllPairs
361
+ sage: XYPairs(3)
362
+ {(3, b) | b in range(5)}
363
+
364
+ sage: XYPairs(x=3)
365
+ {(3, b) | b in range(5)}
366
+
367
+ sage: XYPairs(y=2)
368
+ {(a, 2) | a in range(5)}
369
+
370
+ TESTS::
371
+
372
+ sage: from sage.structure.set_factories import SetFactory
373
+ sage: F = SetFactory()
374
+ sage: F()
375
+ Traceback (most recent call last):
376
+ ...
377
+ NotImplementedError: <abstract method __call__ at 0x...>
378
+ """
379
+
380
+ @abstract_method
381
+ def add_constraints(self, cons, *args, **opts):
382
+ r"""
383
+ Add constraints to the set of constraints `cons`.
384
+
385
+ Should return a set of constraints.
386
+
387
+ .. NOTE::
388
+
389
+ Currently there is no specification on how constraints are
390
+ passed as arguments.
391
+
392
+ EXAMPLES::
393
+
394
+ sage: from sage.structure.set_factories_example import XYPairs
395
+ sage: XYPairs.add_constraints((3,),((None, 2), {}))
396
+ (3, 2)
397
+
398
+ sage: XYPairs.add_constraints((3,),((None, None), {'y': 2}))
399
+ (3, 2)
400
+
401
+ TESTS::
402
+
403
+ sage: from sage.structure.set_factories import SetFactory
404
+ sage: F = SetFactory()
405
+ sage: F.add_constraints(())
406
+ Traceback (most recent call last):
407
+ ...
408
+ NotImplementedError: <abstract method add_constraints at 0x...>
409
+ """
410
+
411
+ # TODO : default policy ?
412
+
413
+ ####################################################
414
+ # Policies #
415
+ ####################################################
416
+
417
+
418
+ class SetFactoryPolicy(UniqueRepresentation, SageObject):
419
+ r"""
420
+ Abstract base class for policies.
421
+
422
+ A policy is a device which is passed to a parent inheriting from
423
+ :class:`ParentWithSetFactory` in order to set-up the element
424
+ construction framework.
425
+
426
+ INPUT:
427
+
428
+ - ``factory`` -- a :class:`SetFactory`
429
+
430
+ .. WARNING::
431
+
432
+ This class is a base class for policies, one should not try
433
+ to create instances.
434
+ """
435
+ def __init__(self, factory):
436
+ r"""
437
+ TESTS::
438
+
439
+ sage: from sage.structure.set_factories import SetFactoryPolicy
440
+ sage: from sage.structure.set_factories_example import XYPairs
441
+ sage: S = SetFactoryPolicy(XYPairs); S
442
+ <sage.structure.set_factories.SetFactoryPolicy object at ...>
443
+ """
444
+ assert isinstance(factory, SetFactory)
445
+ self._factory = factory
446
+
447
+ def factory(self):
448
+ r"""
449
+ Return the factory for ``self``.
450
+
451
+ EXAMPLES::
452
+
453
+ sage: from sage.structure.set_factories import SetFactoryPolicy, SelfParentPolicy
454
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
455
+ sage: XYPairs._default_policy.factory()
456
+ Factory for XY pairs
457
+ sage: XYPairs._default_policy.factory() is XYPairs
458
+ True
459
+
460
+ TESTS::
461
+
462
+ sage: policy = SetFactoryPolicy(XYPairs)
463
+ sage: policy.factory()
464
+ Factory for XY pairs
465
+ sage: SelfParentPolicy(XYPairs, XYPair).factory()
466
+ Factory for XY pairs
467
+ """
468
+ return self._factory
469
+
470
+ def self_element_constructor_attributes(self, Element):
471
+ r"""
472
+ Element Constructor Attributes for non facade parent.
473
+
474
+ The list of attributes which must be set during the init of a
475
+ non facade parent with factory.
476
+
477
+ INPUT:
478
+
479
+ - ``Element`` -- the class used for the elements
480
+
481
+ EXAMPLES::
482
+
483
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
484
+ sage: pol = XYPairs._default_policy
485
+ sage: pol.self_element_constructor_attributes(XYPair)
486
+ {'Element': <class 'sage.structure.set_factories_example.XYPair'>,
487
+ '_parent_for': 'self'}
488
+ """
489
+ return {'_parent_for': "self", 'Element': Element}
490
+
491
+ def facade_element_constructor_attributes(self, parent):
492
+ r"""
493
+ Element Constructor Attributes for facade parent.
494
+
495
+ The list of attributes which must be set during the init of a
496
+ facade parent with factory.
497
+
498
+ INPUT:
499
+
500
+ - ``parent`` -- the actual parent for the elements
501
+
502
+ EXAMPLES::
503
+
504
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
505
+ sage: pol = XYPairs._default_policy
506
+ sage: pol.facade_element_constructor_attributes(XYPairs())
507
+ {'_facade_for': AllPairs,
508
+ '_parent_for': AllPairs,
509
+ 'element_class': <class 'sage.structure.set_factories_example.AllPairs_with_category.element_class'>}
510
+ """
511
+ return {'_parent_for': parent,
512
+ '_facade_for': parent,
513
+ 'element_class': parent.element_class}
514
+
515
+ @abstract_method
516
+ def element_constructor_attributes(self, constraints):
517
+ r"""
518
+ Element constructor attributes.
519
+
520
+ INPUT:
521
+
522
+ - ``constraints`` -- a bunch of constraints
523
+
524
+ Should return the attributes that are prerequisite for element
525
+ construction. This is coordinated with
526
+ :meth:`ParentWithSetFactory._element_constructor_`. Currently two standard
527
+ attributes are provided in
528
+ :meth:`facade_element_constructor_attributes` and
529
+ :meth:`self_element_constructor_attributes`. You should return the
530
+ one needed depending on the given constraints.
531
+
532
+ EXAMPLES::
533
+
534
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
535
+ sage: pol = XYPairs._default_policy
536
+ sage: pol.element_constructor_attributes(())
537
+ {'Element': <class 'sage.structure.set_factories_example.XYPair'>,
538
+ '_parent_for': 'self'}
539
+ sage: pol.element_constructor_attributes((1))
540
+ {'_facade_for': AllPairs,
541
+ '_parent_for': AllPairs,
542
+ 'element_class': <class 'sage.structure.set_factories_example.AllPairs_with_category.element_class'>}
543
+ """
544
+
545
+
546
+ class SelfParentPolicy(SetFactoryPolicy):
547
+ r"""
548
+ Policy where each parent is a standard parent.
549
+
550
+ INPUT:
551
+
552
+ - ``factory`` -- an instance of :class:`SetFactory`
553
+ - ``Element`` -- a subclass of :class:`~.element.Element`
554
+
555
+ Given a factory ``F`` and a class ``E``, returns a policy for
556
+ parent ``P`` creating elements in class ``E`` and parent ``P``
557
+ itself.
558
+
559
+ EXAMPLES::
560
+
561
+ sage: from sage.structure.set_factories import SelfParentPolicy
562
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair, Pairs_Y
563
+ sage: pol = SelfParentPolicy(XYPairs, XYPair)
564
+ sage: S = Pairs_Y(3, pol)
565
+ sage: el = S.an_element()
566
+ sage: el.parent() is S
567
+ True
568
+
569
+ sage: class Foo(XYPair): pass
570
+ sage: pol = SelfParentPolicy(XYPairs, Foo)
571
+ sage: S = Pairs_Y(3, pol)
572
+ sage: el = S.an_element()
573
+ sage: isinstance(el, Foo)
574
+ True
575
+ """
576
+ def __init__(self, factory, Element):
577
+ r"""
578
+ TESTS::
579
+
580
+ sage: from sage.structure.set_factories import SelfParentPolicy
581
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
582
+ sage: S = SelfParentPolicy(XYPairs, XYPair); S
583
+ Set factory policy for <class 'sage.structure.set_factories_example.XYPair'> with parent ``self``
584
+ sage: TestSuite(S).run(skip='_test_category')
585
+ """
586
+ self._Element = Element
587
+ SetFactoryPolicy.__init__(self, factory)
588
+
589
+ def element_constructor_attributes(self, constraints):
590
+ r"""
591
+ Return the element constructor attributes as per
592
+ :meth:`SetFactoryPolicy.element_constructor_attributes`
593
+
594
+ INPUT:
595
+
596
+ - ``constraints`` -- a bunch of constraints
597
+
598
+ TESTS::
599
+
600
+ sage: from sage.structure.set_factories import SelfParentPolicy
601
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
602
+ sage: pol = SelfParentPolicy(XYPairs, XYPair)
603
+ sage: pol.element_constructor_attributes(())
604
+ {'Element': <class 'sage.structure.set_factories_example.XYPair'>,
605
+ '_parent_for': 'self'}
606
+ """
607
+ return self.self_element_constructor_attributes(self._Element)
608
+
609
+ def _repr_(self):
610
+ r"""
611
+ TESTS::
612
+
613
+ sage: from sage.structure.set_factories import SelfParentPolicy
614
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
615
+ sage: SelfParentPolicy(XYPairs, XYPair) # indirect doctest
616
+ Set factory policy for <class 'sage.structure.set_factories_example.XYPair'> with parent ``self``
617
+ """
618
+ return "Set factory policy for {} with parent ``self``".format(self._Element)
619
+
620
+
621
+ class TopMostParentPolicy(SetFactoryPolicy):
622
+ r"""
623
+ Policy where the parent of the elements is the topmost parent.
624
+
625
+ INPUT:
626
+
627
+ - ``factory`` -- an instance of :class:`SetFactory`
628
+ - ``top_constraints`` -- the empty set of constraints
629
+ - ``Element`` -- a subclass of :class:`~.element.Element`
630
+
631
+ Given a factory ``F`` and a class ``E``, returns a policy for
632
+ parent ``P`` creating element in class ``E`` and parent
633
+ ``factory(*top_constraints, policy)``.
634
+
635
+ EXAMPLES::
636
+
637
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
638
+ sage: P = XYPairs(); P.policy()
639
+ Set factory policy for <class 'sage.structure.set_factories_example.XYPair'> with parent AllPairs[=Factory for XY pairs(())]
640
+ """
641
+ def __init__(self, factory, top_constraints, Element):
642
+ """
643
+ TESTS::
644
+
645
+ sage: from sage.structure.set_factories import TopMostParentPolicy
646
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
647
+ sage: T = TopMostParentPolicy(XYPairs, (), XYPair); T
648
+ Set factory policy for <class 'sage.structure.set_factories_example.XYPair'> with parent AllPairs[=Factory for XY pairs(())]
649
+ sage: TestSuite(T).run(skip='_test_category')
650
+ """
651
+ # assert(isinstance(top_constraints, tuple))
652
+ self._top_constraints = top_constraints
653
+ self._Element = Element
654
+ SetFactoryPolicy.__init__(self, factory)
655
+
656
+ def element_constructor_attributes(self, constraints):
657
+ r"""
658
+ Return the element constructor attributes as per
659
+ :meth:`SetFactoryPolicy.element_constructor_attributes`.
660
+
661
+ INPUT:
662
+
663
+ - ``constraints`` -- a bunch of constraints
664
+
665
+ TESTS::
666
+
667
+ sage: from sage.structure.set_factories import TopMostParentPolicy
668
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
669
+ sage: pol = TopMostParentPolicy(XYPairs, (), XYPair)
670
+ sage: pol.element_constructor_attributes(())
671
+ {'Element': <class 'sage.structure.set_factories_example.XYPair'>,
672
+ '_parent_for': 'self'}
673
+ sage: pol.element_constructor_attributes((1))
674
+ {'_facade_for': AllPairs,
675
+ '_parent_for': AllPairs,
676
+ 'element_class': <class 'sage.structure.set_factories_example.AllPairs_with_category.element_class'>}
677
+ """
678
+ factory = self._factory
679
+ if constraints == self._top_constraints:
680
+ return self.self_element_constructor_attributes(self._Element)
681
+ else:
682
+ return self.facade_element_constructor_attributes(
683
+ factory(*self._top_constraints, policy=self))
684
+
685
+ def _repr_(self):
686
+ r"""
687
+ TESTS::
688
+
689
+ sage: from sage.structure.set_factories import TopMostParentPolicy
690
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
691
+ sage: TopMostParentPolicy(XYPairs, (), XYPair) # indirect doctest
692
+ Set factory policy for <class 'sage.structure.set_factories_example.XYPair'> with parent AllPairs[=Factory for XY pairs(())]
693
+ """
694
+ return "Set factory policy for {} with parent {}[={}({})]".format(
695
+ self._Element, self._factory(*self._top_constraints, policy=self),
696
+ self._factory, self._top_constraints)
697
+
698
+
699
+ class FacadeParentPolicy(SetFactoryPolicy):
700
+ r"""
701
+ Policy for facade parent.
702
+
703
+ INPUT:
704
+
705
+ - ``factory`` -- an instance of :class:`SetFactory`
706
+ - ``parent`` -- an instance of :class:`Parent`
707
+
708
+ Given a factory ``F`` and a class ``E``, returns a policy for
709
+ parent ``P`` creating elements as if they were created by
710
+ ``parent``.
711
+
712
+ EXAMPLES::
713
+
714
+ sage: from sage.structure.set_factories import SelfParentPolicy, FacadeParentPolicy
715
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
716
+
717
+ We create a custom standard parent ``P``::
718
+
719
+ sage: selfpolicy = SelfParentPolicy(XYPairs, XYPair)
720
+ sage: P = XYPairs(x=2, policy=selfpolicy)
721
+ sage: pol = FacadeParentPolicy(XYPairs, P)
722
+ sage: P2 = XYPairs(x=2, y=3, policy=pol)
723
+ sage: el = P2.an_element()
724
+ sage: el.parent() is P
725
+ True
726
+ sage: type(el) is P.element_class
727
+ True
728
+
729
+ If ``parent`` is itself a facade parent, then transitivity is
730
+ correctly applied::
731
+
732
+ sage: P = XYPairs()
733
+ sage: P2 = XYPairs(x=2)
734
+ sage: P2.category()
735
+ Category of facade finite enumerated sets
736
+ sage: pol = FacadeParentPolicy(XYPairs, P)
737
+ sage: P23 = XYPairs(x=2, y=3, policy=pol)
738
+ sage: el = P2.an_element()
739
+ sage: el.parent() is P
740
+ True
741
+ sage: type(el) is P.element_class
742
+ True
743
+ """
744
+ def __init__(self, factory, parent):
745
+ r"""
746
+ TESTS::
747
+
748
+ sage: from sage.structure.set_factories import FacadeParentPolicy
749
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
750
+ sage: F = FacadeParentPolicy(XYPairs, XYPairs()); F
751
+ Set factory policy for facade parent AllPairs
752
+ sage: TestSuite(F).run(skip='_test_category')
753
+ """
754
+ self._parent_for = parent
755
+ SetFactoryPolicy.__init__(self, factory)
756
+
757
+ def element_constructor_attributes(self, constraints):
758
+ r"""
759
+ Return the element constructor attributes as per
760
+ :meth:`SetFactoryPolicy.element_constructor_attributes`.
761
+
762
+ INPUT:
763
+
764
+ - ``constraints`` -- a bunch of constraints
765
+
766
+ TESTS::
767
+
768
+ sage: from sage.structure.set_factories import FacadeParentPolicy
769
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
770
+ sage: pol = FacadeParentPolicy(XYPairs, XYPairs())
771
+ sage: pol.element_constructor_attributes(())
772
+ {'_facade_for': AllPairs,
773
+ '_parent_for': AllPairs,
774
+ 'element_class': <class 'sage.structure.set_factories_example.AllPairs_with_category.element_class'>}
775
+ sage: pol.element_constructor_attributes((1))
776
+ {'_facade_for': AllPairs,
777
+ '_parent_for': AllPairs,
778
+ 'element_class': <class 'sage.structure.set_factories_example.AllPairs_with_category.element_class'>}
779
+ """
780
+ return self.facade_element_constructor_attributes(
781
+ self._parent_for._parent_for)
782
+
783
+ def _repr_(self):
784
+ r"""
785
+ TESTS::
786
+
787
+ sage: from sage.structure.set_factories import FacadeParentPolicy
788
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
789
+ sage: FacadeParentPolicy(XYPairs, XYPairs()) # indirect doctest
790
+ Set factory policy for facade parent AllPairs
791
+ """
792
+ return "Set factory policy for facade parent {}".format(
793
+ self._parent_for)
794
+
795
+
796
+ class BareFunctionPolicy(SetFactoryPolicy):
797
+ r"""
798
+ Policy where element are constructed using a bare function.
799
+
800
+ INPUT:
801
+
802
+ - ``factory`` -- an instance of :class:`SetFactory`
803
+ - ``constructor`` -- a function
804
+
805
+ Given a factory ``F`` and a function ``c``, returns a policy for
806
+ parent ``P`` creating element using the function ``f``.
807
+
808
+ EXAMPLES::
809
+
810
+ sage: from sage.structure.set_factories import BareFunctionPolicy
811
+ sage: from sage.structure.set_factories_example import XYPairs
812
+ sage: cons = lambda t, check: tuple(t) # ignore the check parameter
813
+ sage: tuplepolicy = BareFunctionPolicy(XYPairs, cons)
814
+ sage: P = XYPairs(x=2, policy=tuplepolicy)
815
+ sage: el = P.an_element()
816
+ sage: type(el)
817
+ <... 'tuple'>
818
+ """
819
+ def __init__(self, factory, constructor):
820
+ """
821
+ TESTS::
822
+
823
+ sage: from sage.structure.set_factories import BareFunctionPolicy
824
+ sage: from sage.structure.set_factories_example import XYPairs
825
+ sage: pol = BareFunctionPolicy(XYPairs, tuple)
826
+ sage: TestSuite(pol).run(skip='_test_category')
827
+ """
828
+ # assert(isinstance(top_constraints, tuple))
829
+ self._constructor = constructor
830
+ SetFactoryPolicy.__init__(self, factory)
831
+
832
+ def element_constructor_attributes(self, constraints):
833
+ r"""
834
+ Return the element constructor attributes as per
835
+ :meth:`SetFactoryPolicy.element_constructor_attributes`.
836
+
837
+ INPUT:
838
+
839
+ - ``constraints`` -- a bunch of constraints
840
+
841
+ TESTS::
842
+
843
+ sage: from sage.structure.set_factories import BareFunctionPolicy
844
+ sage: from sage.structure.set_factories_example import XYPairs
845
+ sage: pol = BareFunctionPolicy(XYPairs, tuple)
846
+ sage: pol.element_constructor_attributes(())
847
+ {'_element_constructor_': <... 'tuple'>, '_parent_for': None}
848
+ """
849
+ return {'_element_constructor_': self._constructor,
850
+ '_parent_for': None}
851
+
852
+ def _repr_(self):
853
+ r"""
854
+ TESTS::
855
+
856
+ sage: from sage.structure.set_factories import BareFunctionPolicy
857
+ sage: from sage.structure.set_factories_example import XYPairs
858
+ sage: BareFunctionPolicy(XYPairs, tuple)
859
+ Set factory policy for bare function <... 'tuple'>
860
+ """
861
+ return "Set factory policy for bare function {}".format(self._constructor)
862
+
863
+
864
+ ####################################################
865
+ # Parent #
866
+ ####################################################
867
+
868
+
869
+ class ParentWithSetFactory(Parent):
870
+ r"""
871
+ Abstract class for parent belonging to a set factory.
872
+
873
+ INPUT:
874
+
875
+ - ``constraints`` -- set of constraints
876
+ - ``policy`` -- the policy for element construction
877
+ - ``category`` -- the category of the parent (default: ``None``)
878
+
879
+ Depending on the constraints and the policy, initialize the parent
880
+ in a proper category to set up element construction.
881
+
882
+ EXAMPLES::
883
+
884
+ sage: from sage.structure.set_factories_example import XYPairs, PairsX_
885
+ sage: P = PairsX_(3, XYPairs._default_policy)
886
+ sage: P is XYPairs(3)
887
+ True
888
+ sage: P.category()
889
+ Category of facade finite enumerated sets
890
+ """
891
+ def __init__(self, constraints, policy, category=None):
892
+ r"""
893
+ TESTS::
894
+
895
+ sage: from sage.structure.set_factories import ParentWithSetFactory
896
+ sage: from sage.structure.set_factories_example import XYPairs
897
+ sage: isinstance(XYPairs(3), ParentWithSetFactory) # indirect doctest
898
+ True
899
+ """
900
+ self._constraints = constraints
901
+ assert isinstance(policy, SetFactoryPolicy)
902
+ self._policy = policy
903
+ policy_attributes = policy.element_constructor_attributes(constraints)
904
+ for attrname, attr in policy_attributes.items():
905
+ if attr == "self":
906
+ setattr(self, attrname, self)
907
+ else:
908
+ setattr(self, attrname, attr)
909
+ assert self._parent_for is None or isinstance(self._parent_for, Parent)
910
+ Parent.__init__(self,
911
+ category=category,
912
+ facade=policy_attributes.get('_facade_for', None))
913
+
914
+ def constraints(self):
915
+ r"""
916
+ Return the constraints defining ``self``.
917
+
918
+ .. NOTE::
919
+
920
+ Currently there is no specification on how constraints are
921
+ passed as arguments.
922
+
923
+ EXAMPLES::
924
+
925
+ sage: from sage.structure.set_factories_example import XYPairs
926
+ sage: XYPairs().constraints()
927
+ ()
928
+ sage: XYPairs(x=3).constraints()
929
+ (3, None)
930
+ sage: XYPairs(y=2).constraints()
931
+ (None, 2)
932
+ """
933
+ return self._constraints
934
+
935
+ def policy(self):
936
+ r"""
937
+ Return the policy used when ``self`` was created.
938
+
939
+ EXAMPLES::
940
+
941
+ sage: from sage.structure.set_factories_example import XYPairs
942
+ sage: XYPairs().policy()
943
+ Set factory policy for <class 'sage.structure.set_factories_example.XYPair'> with parent AllPairs[=Factory for XY pairs(())]
944
+ sage: XYPairs(x=3).policy()
945
+ Set factory policy for <class 'sage.structure.set_factories_example.XYPair'> with parent AllPairs[=Factory for XY pairs(())]
946
+ """
947
+ return self._policy
948
+
949
+ def facade_policy(self):
950
+ r"""
951
+ Return the policy for parent facade for ``self``.
952
+
953
+ EXAMPLES::
954
+
955
+ sage: from sage.structure.set_factories import SelfParentPolicy
956
+ sage: from sage.structure.set_factories_example import XYPairs, XYPair
957
+
958
+ We create a custom standard parent ``P``::
959
+
960
+ sage: selfpolicy = SelfParentPolicy(XYPairs, XYPair)
961
+ sage: P = XYPairs(x=2, policy=selfpolicy)
962
+ sage: P.facade_policy()
963
+ Set factory policy for facade parent {(2, b) | b in range(5)}
964
+
965
+ Now passing ``P.facade_policy()`` creates parent which are facade for
966
+ ``P``::
967
+
968
+ sage: P3 = XYPairs(x=2, y=3, policy=P.facade_policy())
969
+ sage: P3.facade_for() == (P,)
970
+ True
971
+ sage: el = P3.an_element()
972
+ sage: el.parent() is P
973
+ True
974
+ """
975
+ return FacadeParentPolicy(self.factory(), self)
976
+
977
+ def factory(self):
978
+ r"""
979
+ Return the factory which built ``self``.
980
+
981
+ EXAMPLES::
982
+
983
+ sage: from sage.structure.set_factories_example import XYPairs
984
+ sage: XYPairs().factory() is XYPairs
985
+ True
986
+ sage: XYPairs(x=3).factory() is XYPairs
987
+ True
988
+ """
989
+ return self._policy.factory()
990
+
991
+ def subset(self, *args, **options):
992
+ r"""
993
+ Return a subset of ``self`` by adding more constraints.
994
+
995
+ .. NOTE::
996
+
997
+ Currently there is no specification on how constraints are
998
+ passed as arguments.
999
+
1000
+ EXAMPLES::
1001
+
1002
+ sage: from sage.structure.set_factories_example import XYPairs
1003
+ sage: S = XYPairs()
1004
+ sage: S3 = S.subset(x=3)
1005
+ sage: S3.list()
1006
+ [(3, 0), (3, 1), (3, 2), (3, 3), (3, 4)]
1007
+
1008
+ TESTS::
1009
+
1010
+ sage: S3 is XYPairs(3)
1011
+ True
1012
+ sage: S3 is XYPairs(x=3)
1013
+ True
1014
+ """
1015
+ factory = self.factory()
1016
+ constr = factory.add_constraints(self._constraints,
1017
+ (args, options))
1018
+ return factory(*constr, policy=self._policy)
1019
+
1020
+ def _test_subset(self, **options):
1021
+ r"""
1022
+ Test that subsets with no extra parameters returns ``self``.
1023
+
1024
+ Currently, only the test that one gets the same parent when no
1025
+ more constraints are given, is performed.
1026
+
1027
+ .. TODO::
1028
+
1029
+ Straighten the test when handling of constraints will be
1030
+ specified.
1031
+
1032
+ EXAMPLES::
1033
+
1034
+ sage: from sage.structure.set_factories_example import XYPairs
1035
+ sage: S = XYPairs()
1036
+ sage: S._test_subset()
1037
+ """
1038
+ tester = self._tester(**options)
1039
+ tester.assertIs(self.subset(), self)
1040
+
1041
+ @abstract_method
1042
+ def check_element(self, x, check):
1043
+ r"""
1044
+ Check that ``x`` verifies the constraints of ``self``.
1045
+
1046
+ INPUT:
1047
+
1048
+ - ``x`` -- an instance of ``self.element_class``
1049
+
1050
+ - ``check`` -- the level of checking to be performed (usually a
1051
+ boolean)
1052
+
1053
+ This method may assume that ``x`` was properly constructed by
1054
+ ``self`` or a possible super-set of ``self`` for which
1055
+ ``self`` is a facade. It should return nothing if ``x``
1056
+ verifies the constraints and raise a
1057
+ :exc:`~exceptions.ValueError` explaining which constraints
1058
+ ``x`` fails otherwise.
1059
+
1060
+ The method should accept an extra parameter check specifying
1061
+ which level of check should be performed. It will only be
1062
+ called when ``bool(check)`` evaluates to ``True``.
1063
+
1064
+ .. TODO::
1065
+
1066
+ Should we always call check element and let it decide
1067
+ which check has to be performed ?
1068
+
1069
+ EXAMPLES::
1070
+
1071
+ sage: from sage.structure.set_factories_example import XYPairs
1072
+ sage: S = XYPairs()
1073
+ sage: el = S((2,3))
1074
+ sage: S.check_element(el, True)
1075
+ sage: XYPairs(x=2).check_element(el, True)
1076
+ sage: XYPairs(x=3).check_element(el, True)
1077
+ Traceback (most recent call last):
1078
+ ...
1079
+ ValueError: Wrong first coordinate
1080
+ sage: XYPairs(y=4).check_element(el, True)
1081
+ Traceback (most recent call last):
1082
+ ...
1083
+ ValueError: Wrong second coordinate
1084
+ """
1085
+
1086
+ def __contains__(self, x):
1087
+ r"""
1088
+ Default implementation for ``__contains__``.
1089
+
1090
+ INPUT:
1091
+
1092
+ - ``x`` -- any object
1093
+
1094
+ Check for class, parent and calls ``self.check_element(x)``.
1095
+
1096
+ TESTS::
1097
+
1098
+ sage: from sage.structure.set_factories_example import XYPairs
1099
+ sage: S = XYPairs()
1100
+ sage: el = S((2,3))
1101
+ sage: el in S
1102
+ True
1103
+ sage: el in XYPairs(x=2)
1104
+ True
1105
+ sage: el in XYPairs(x=3)
1106
+ False
1107
+ sage: el in XYPairs(y=4)
1108
+ False
1109
+ """
1110
+ if (isinstance(x, self.element_class) and
1111
+ x.parent() == self._parent_for): # TODO: is_parent_of ???
1112
+ try:
1113
+ self.check_element(x, True)
1114
+ except ValueError:
1115
+ return False
1116
+ else:
1117
+ return True
1118
+ return False
1119
+
1120
+ def __call__(self, *args, **keywords):
1121
+ r"""
1122
+ TESTS::
1123
+
1124
+ sage: from sage.structure.set_factories_example import XYPairs
1125
+ sage: S = XYPairs()
1126
+ sage: el = S((2,3)); el
1127
+ (2, 3)
1128
+ sage: S(el) is el
1129
+ True
1130
+
1131
+ sage: XYPairs(x=3)((2,3))
1132
+ Traceback (most recent call last):
1133
+ ...
1134
+ ValueError: Wrong first coordinate
1135
+
1136
+ sage: XYPairs(x=3)(el)
1137
+ Traceback (most recent call last):
1138
+ ...
1139
+ ValueError: Wrong first coordinate
1140
+ """
1141
+ # Ensure idempotence of element construction
1142
+ if (len(args) == 1 and
1143
+ isinstance(args[0], self.element_class) and
1144
+ args[0].parent() == self._parent_for):
1145
+ check = keywords.get("check", True)
1146
+ if check:
1147
+ self.check_element(args[0], check)
1148
+ return args[0]
1149
+ else:
1150
+ return Parent.__call__(self, *args, **keywords)
1151
+
1152
+ # QUESTION: Should we call:
1153
+ # self._parent_for._element_constructor_
1154
+ # currently we do not call it directly because:
1155
+ # - it may do some extra check we dont want to perform ?
1156
+ # - calling directly element_class should be faster
1157
+ def _element_constructor_(self, *args, **keywords):
1158
+ r"""
1159
+ TESTS::
1160
+
1161
+ sage: from sage.structure.set_factories_example import XYPairs
1162
+ sage: XYPairs()((2,3)) # indirect doctest
1163
+ (2, 3)
1164
+ sage: XYPairs(x=3)((3,3)) # indirect doctest
1165
+ (3, 3)
1166
+ sage: XYPairs(x=3)((2,3)) # indirect doctest
1167
+ Traceback (most recent call last):
1168
+ ...
1169
+ ValueError: Wrong first coordinate
1170
+
1171
+ sage: XYPairs(x=3)((2,3), check=False) # Don't do this at home, kids
1172
+ (2, 3)
1173
+ """
1174
+ check = keywords.get("check", True)
1175
+ res = self.element_class(self._parent_for, *args, **keywords)
1176
+ if check:
1177
+ self.check_element(res, check)
1178
+ return res