passagemath-objects 10.6.41__cp314-cp314t-macosx_13_0_arm64.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.
Potentially problematic release.
This version of passagemath-objects might be problematic. Click here for more details.
- passagemath_objects/.dylibs/libgmp.10.dylib +0 -0
- passagemath_objects/__init__.py +3 -0
- passagemath_objects-10.6.41.dist-info/METADATA +115 -0
- passagemath_objects-10.6.41.dist-info/RECORD +280 -0
- passagemath_objects-10.6.41.dist-info/WHEEL +6 -0
- passagemath_objects-10.6.41.dist-info/top_level.txt +3 -0
- sage/all__sagemath_objects.py +37 -0
- sage/arith/all__sagemath_objects.py +5 -0
- sage/arith/long.pxd +411 -0
- sage/arith/numerical_approx.cpython-314t-darwin.so +0 -0
- sage/arith/numerical_approx.pxd +35 -0
- sage/arith/numerical_approx.pyx +75 -0
- sage/arith/power.cpython-314t-darwin.so +0 -0
- sage/arith/power.pxd +31 -0
- sage/arith/power.pyx +127 -0
- sage/categories/action.cpython-314t-darwin.so +0 -0
- sage/categories/action.pxd +29 -0
- sage/categories/action.pyx +641 -0
- sage/categories/algebra_functor.py +745 -0
- sage/categories/all__sagemath_objects.py +33 -0
- sage/categories/basic.py +62 -0
- sage/categories/cartesian_product.py +295 -0
- sage/categories/category.py +3401 -0
- sage/categories/category_cy_helper.cpython-314t-darwin.so +0 -0
- sage/categories/category_cy_helper.pxd +8 -0
- sage/categories/category_cy_helper.pyx +322 -0
- sage/categories/category_singleton.cpython-314t-darwin.so +0 -0
- sage/categories/category_singleton.pxd +3 -0
- sage/categories/category_singleton.pyx +342 -0
- sage/categories/category_types.py +637 -0
- sage/categories/category_with_axiom.py +2876 -0
- sage/categories/covariant_functorial_construction.py +703 -0
- sage/categories/facade_sets.py +228 -0
- sage/categories/functor.cpython-314t-darwin.so +0 -0
- sage/categories/functor.pxd +7 -0
- sage/categories/functor.pyx +691 -0
- sage/categories/homset.py +1338 -0
- sage/categories/homsets.py +364 -0
- sage/categories/isomorphic_objects.py +73 -0
- sage/categories/map.cpython-314t-darwin.so +0 -0
- sage/categories/map.pxd +34 -0
- sage/categories/map.pyx +2112 -0
- sage/categories/morphism.cpython-314t-darwin.so +0 -0
- sage/categories/morphism.pxd +14 -0
- sage/categories/morphism.pyx +895 -0
- sage/categories/objects.py +167 -0
- sage/categories/primer.py +1696 -0
- sage/categories/pushout.py +4834 -0
- sage/categories/quotients.py +64 -0
- sage/categories/realizations.py +200 -0
- sage/categories/sets_cat.py +3228 -0
- sage/categories/sets_with_partial_maps.py +52 -0
- sage/categories/subobjects.py +64 -0
- sage/categories/subquotients.py +21 -0
- sage/categories/with_realizations.py +311 -0
- sage/cpython/__init__.py +19 -0
- sage/cpython/_py2_random.py +619 -0
- sage/cpython/all.py +3 -0
- sage/cpython/atexit.cpython-314t-darwin.so +0 -0
- sage/cpython/atexit.pyx +269 -0
- sage/cpython/builtin_types.cpython-314t-darwin.so +0 -0
- sage/cpython/builtin_types.pyx +7 -0
- sage/cpython/cython_metaclass.cpython-314t-darwin.so +0 -0
- sage/cpython/cython_metaclass.h +117 -0
- sage/cpython/cython_metaclass.pxd +3 -0
- sage/cpython/cython_metaclass.pyx +130 -0
- sage/cpython/debug.cpython-314t-darwin.so +0 -0
- sage/cpython/debug.pyx +302 -0
- sage/cpython/dict_del_by_value.cpython-314t-darwin.so +0 -0
- sage/cpython/dict_del_by_value.pxd +9 -0
- sage/cpython/dict_del_by_value.pyx +191 -0
- sage/cpython/dict_internal.h +245 -0
- sage/cpython/getattr.cpython-314t-darwin.so +0 -0
- sage/cpython/getattr.pxd +9 -0
- sage/cpython/getattr.pyx +439 -0
- sage/cpython/pycore_long.h +97 -0
- sage/cpython/pycore_long.pxd +10 -0
- sage/cpython/python_debug.h +44 -0
- sage/cpython/python_debug.pxd +47 -0
- sage/cpython/pyx_visit.h +13 -0
- sage/cpython/string.cpython-314t-darwin.so +0 -0
- sage/cpython/string.pxd +76 -0
- sage/cpython/string.pyx +34 -0
- sage/cpython/string_impl.h +60 -0
- sage/cpython/type.cpython-314t-darwin.so +0 -0
- sage/cpython/type.pxd +2 -0
- sage/cpython/type.pyx +40 -0
- sage/cpython/wrapperdescr.pxd +67 -0
- sage/ext/all__sagemath_objects.py +3 -0
- sage/ext/ccobject.h +64 -0
- sage/ext/cplusplus.pxd +17 -0
- sage/ext/mod_int.h +30 -0
- sage/ext/mod_int.pxd +24 -0
- sage/ext/stdsage.pxd +39 -0
- sage/groups/all__sagemath_objects.py +1 -0
- sage/groups/group.cpython-314t-darwin.so +0 -0
- sage/groups/group.pxd +14 -0
- sage/groups/group.pyx +322 -0
- sage/groups/old.cpython-314t-darwin.so +0 -0
- sage/groups/old.pxd +14 -0
- sage/groups/old.pyx +219 -0
- sage/libs/all__sagemath_objects.py +3 -0
- sage/libs/gmp/__init__.py +1 -0
- sage/libs/gmp/all.pxd +6 -0
- sage/libs/gmp/binop.pxd +23 -0
- sage/libs/gmp/misc.pxd +8 -0
- sage/libs/gmp/mpf.pxd +88 -0
- sage/libs/gmp/mpn.pxd +57 -0
- sage/libs/gmp/mpq.pxd +57 -0
- sage/libs/gmp/mpz.pxd +202 -0
- sage/libs/gmp/pylong.cpython-314t-darwin.so +0 -0
- sage/libs/gmp/pylong.pxd +12 -0
- sage/libs/gmp/pylong.pyx +150 -0
- sage/libs/gmp/random.pxd +25 -0
- sage/libs/gmp/randomize.pxd +59 -0
- sage/libs/gmp/types.pxd +53 -0
- sage/libs/gmpxx.pxd +19 -0
- sage/misc/abstract_method.py +276 -0
- sage/misc/all__sagemath_objects.py +43 -0
- sage/misc/bindable_class.py +253 -0
- sage/misc/c3_controlled.cpython-314t-darwin.so +0 -0
- sage/misc/c3_controlled.pxd +2 -0
- sage/misc/c3_controlled.pyx +1402 -0
- sage/misc/cachefunc.cpython-314t-darwin.so +0 -0
- sage/misc/cachefunc.pxd +43 -0
- sage/misc/cachefunc.pyx +3781 -0
- sage/misc/call.py +188 -0
- sage/misc/classcall_metaclass.cpython-314t-darwin.so +0 -0
- sage/misc/classcall_metaclass.pxd +14 -0
- sage/misc/classcall_metaclass.pyx +599 -0
- sage/misc/constant_function.cpython-314t-darwin.so +0 -0
- sage/misc/constant_function.pyx +130 -0
- sage/misc/decorators.py +747 -0
- sage/misc/fast_methods.cpython-314t-darwin.so +0 -0
- sage/misc/fast_methods.pxd +20 -0
- sage/misc/fast_methods.pyx +351 -0
- sage/misc/flatten.py +90 -0
- sage/misc/fpickle.cpython-314t-darwin.so +0 -0
- sage/misc/fpickle.pyx +177 -0
- sage/misc/function_mangling.cpython-314t-darwin.so +0 -0
- sage/misc/function_mangling.pxd +11 -0
- sage/misc/function_mangling.pyx +308 -0
- sage/misc/inherit_comparison.cpython-314t-darwin.so +0 -0
- sage/misc/inherit_comparison.pxd +5 -0
- sage/misc/inherit_comparison.pyx +105 -0
- sage/misc/instancedoc.cpython-314t-darwin.so +0 -0
- sage/misc/instancedoc.pyx +331 -0
- sage/misc/lazy_attribute.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_attribute.pyx +607 -0
- sage/misc/lazy_format.py +135 -0
- sage/misc/lazy_import.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_import.pyx +1299 -0
- sage/misc/lazy_import_cache.py +36 -0
- sage/misc/lazy_list.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_list.pxd +19 -0
- sage/misc/lazy_list.pyx +1187 -0
- sage/misc/lazy_string.cpython-314t-darwin.so +0 -0
- sage/misc/lazy_string.pxd +7 -0
- sage/misc/lazy_string.pyx +546 -0
- sage/misc/misc.py +1066 -0
- sage/misc/misc_c.cpython-314t-darwin.so +0 -0
- sage/misc/misc_c.pxd +3 -0
- sage/misc/misc_c.pyx +766 -0
- sage/misc/namespace_package.py +37 -0
- sage/misc/nested_class.cpython-314t-darwin.so +0 -0
- sage/misc/nested_class.pxd +3 -0
- sage/misc/nested_class.pyx +394 -0
- sage/misc/persist.cpython-314t-darwin.so +0 -0
- sage/misc/persist.pyx +1251 -0
- sage/misc/prandom.py +418 -0
- sage/misc/randstate.cpython-314t-darwin.so +0 -0
- sage/misc/randstate.pxd +30 -0
- sage/misc/randstate.pyx +1059 -0
- sage/misc/repr.py +203 -0
- sage/misc/reset.cpython-314t-darwin.so +0 -0
- sage/misc/reset.pyx +196 -0
- sage/misc/sage_ostools.cpython-314t-darwin.so +0 -0
- sage/misc/sage_ostools.pyx +323 -0
- sage/misc/sage_timeit.py +276 -0
- sage/misc/sage_timeit_class.cpython-314t-darwin.so +0 -0
- sage/misc/sage_timeit_class.pyx +120 -0
- sage/misc/sage_unittest.py +637 -0
- sage/misc/sageinspect.py +2768 -0
- sage/misc/session.cpython-314t-darwin.so +0 -0
- sage/misc/session.pyx +392 -0
- sage/misc/superseded.py +557 -0
- sage/misc/test_nested_class.py +228 -0
- sage/misc/timing.py +264 -0
- sage/misc/unknown.py +222 -0
- sage/misc/verbose.py +253 -0
- sage/misc/weak_dict.cpython-314t-darwin.so +0 -0
- sage/misc/weak_dict.pxd +15 -0
- sage/misc/weak_dict.pyx +1231 -0
- sage/modules/all__sagemath_objects.py +1 -0
- sage/modules/module.cpython-314t-darwin.so +0 -0
- sage/modules/module.pxd +5 -0
- sage/modules/module.pyx +329 -0
- sage/rings/all__sagemath_objects.py +3 -0
- sage/rings/integer_fake.h +22 -0
- sage/rings/integer_fake.pxd +55 -0
- sage/sets/all__sagemath_objects.py +3 -0
- sage/sets/pythonclass.cpython-314t-darwin.so +0 -0
- sage/sets/pythonclass.pxd +9 -0
- sage/sets/pythonclass.pyx +247 -0
- sage/structure/__init__.py +4 -0
- sage/structure/all.py +30 -0
- sage/structure/category_object.cpython-314t-darwin.so +0 -0
- sage/structure/category_object.pxd +28 -0
- sage/structure/category_object.pyx +1087 -0
- sage/structure/coerce.cpython-314t-darwin.so +0 -0
- sage/structure/coerce.pxd +44 -0
- sage/structure/coerce.pyx +2107 -0
- sage/structure/coerce_actions.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_actions.pxd +27 -0
- sage/structure/coerce_actions.pyx +988 -0
- sage/structure/coerce_dict.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_dict.pxd +51 -0
- sage/structure/coerce_dict.pyx +1557 -0
- sage/structure/coerce_exceptions.py +23 -0
- sage/structure/coerce_maps.cpython-314t-darwin.so +0 -0
- sage/structure/coerce_maps.pxd +28 -0
- sage/structure/coerce_maps.pyx +718 -0
- sage/structure/debug_options.cpython-314t-darwin.so +0 -0
- sage/structure/debug_options.pxd +6 -0
- sage/structure/debug_options.pyx +54 -0
- sage/structure/dynamic_class.py +541 -0
- sage/structure/element.cpython-314t-darwin.so +0 -0
- sage/structure/element.pxd +272 -0
- sage/structure/element.pyx +4772 -0
- sage/structure/element_wrapper.cpython-314t-darwin.so +0 -0
- sage/structure/element_wrapper.pxd +12 -0
- sage/structure/element_wrapper.pyx +582 -0
- sage/structure/factorization.py +1422 -0
- sage/structure/factorization_integer.py +105 -0
- sage/structure/factory.cpython-314t-darwin.so +0 -0
- sage/structure/factory.pyx +786 -0
- sage/structure/formal_sum.py +489 -0
- sage/structure/gens_py.py +73 -0
- sage/structure/global_options.py +1743 -0
- sage/structure/indexed_generators.py +863 -0
- sage/structure/list_clone.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone.pxd +65 -0
- sage/structure/list_clone.pyx +1867 -0
- sage/structure/list_clone_demo.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone_demo.pyx +248 -0
- sage/structure/list_clone_timings.py +179 -0
- sage/structure/list_clone_timings_cy.cpython-314t-darwin.so +0 -0
- sage/structure/list_clone_timings_cy.pyx +86 -0
- sage/structure/mutability.cpython-314t-darwin.so +0 -0
- sage/structure/mutability.pxd +21 -0
- sage/structure/mutability.pyx +348 -0
- sage/structure/nonexact.py +69 -0
- sage/structure/parent.cpython-314t-darwin.so +0 -0
- sage/structure/parent.pxd +112 -0
- sage/structure/parent.pyx +3093 -0
- sage/structure/parent_base.cpython-314t-darwin.so +0 -0
- sage/structure/parent_base.pxd +13 -0
- sage/structure/parent_base.pyx +44 -0
- sage/structure/parent_gens.cpython-314t-darwin.so +0 -0
- sage/structure/parent_gens.pxd +22 -0
- sage/structure/parent_gens.pyx +377 -0
- sage/structure/parent_old.cpython-314t-darwin.so +0 -0
- sage/structure/parent_old.pxd +25 -0
- sage/structure/parent_old.pyx +294 -0
- sage/structure/proof/__init__.py +1 -0
- sage/structure/proof/all.py +243 -0
- sage/structure/proof/proof.py +300 -0
- sage/structure/richcmp.cpython-314t-darwin.so +0 -0
- sage/structure/richcmp.pxd +213 -0
- sage/structure/richcmp.pyx +495 -0
- sage/structure/sage_object.cpython-314t-darwin.so +0 -0
- sage/structure/sage_object.pxd +3 -0
- sage/structure/sage_object.pyx +988 -0
- sage/structure/sage_object_test.py +19 -0
- sage/structure/sequence.py +937 -0
- sage/structure/set_factories.py +1178 -0
- sage/structure/set_factories_example.py +527 -0
- sage/structure/support_view.py +179 -0
- sage/structure/test_factory.py +56 -0
- 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
|