From 9fcf32ea544d7e841a41deda364c179205108e9b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 8 Jun 2021 17:06:15 -0700 Subject: [PATCH 1/2] Sets.CartesianProducts.ParentMethods, FreeModule_ambient, IntegerRing_class, InternalRealInterval, RealSet, NonNegativeIntegers, IntegerRing_class, PositiveIntegers, RationalField: Add _sympy_ methods --- src/sage/categories/sets_cat.py | 15 ++++++ src/sage/modules/free_module.py | 14 ++++++ src/sage/rings/integer_ring.pyx | 12 +++++ src/sage/rings/rational_field.py | 12 +++++ src/sage/sets/non_negative_integers.py | 13 ++++++ src/sage/sets/positive_integers.py | 12 +++++ src/sage/sets/real_set.py | 63 ++++++++++++++++++++++++++ 7 files changed, 141 insertions(+) diff --git a/src/sage/categories/sets_cat.py b/src/sage/categories/sets_cat.py index 68ba29bfa7c..6b2f57e18cf 100644 --- a/src/sage/categories/sets_cat.py +++ b/src/sage/categories/sets_cat.py @@ -2438,6 +2438,21 @@ def _cartesian_product_of_elements(self, elements): (42, 47, 42) """ + def _sympy_(self): + """ + Return a SymPy ``ProductSet`` corresponding to ``self``. + + EXAMPLES:: + + sage: ZZ3 = cartesian_product([ZZ, ZZ, ZZ]) + sage: sZZ3 = ZZ3._sympy_(); sZZ3 + ProductSet(Integers, Integers, Integers) + sage: (1, 2, 3) in sZZ3 + True + """ + from sympy import ProductSet + return ProductSet(*self.cartesian_factors()) + class ElementMethods: def cartesian_projection(self, i): diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index b4ce5196e48..36f668d99fe 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -5306,6 +5306,20 @@ def gen(self, i=0): v.set_immutable() return v + def _sympy_(self): + """ + Return a SymPy ``ProductSet`` corresponding to ``self``. + + EXAMPLES:: + + sage: sZZ3 = (ZZ^3)._sympy_(); sZZ3 + ProductSet(Integers, Integers, Integers) + sage: (1, 2, 3) in sZZ3 + True + """ + from sympy import ProductSet + return ProductSet(*([self.coordinate_ring()] * self.rank())) + ############################################################################### # diff --git a/src/sage/rings/integer_ring.pyx b/src/sage/rings/integer_ring.pyx index ae0b0f41327..737dda9ecb3 100644 --- a/src/sage/rings/integer_ring.pyx +++ b/src/sage/rings/integer_ring.pyx @@ -1467,6 +1467,18 @@ cdef class IntegerRing_class(PrincipalIdealDomain): """ return '"Integer"' + def _sympy_(self): + r""" + Return the SymPy set ``Integers``. + + EXAMPLES:: + + sage: ZZ._sympy_() + Integers + """ + from sympy import Integers + return Integers + def _sage_input_(self, sib, coerced): r""" Produce an expression which will reproduce this value when diff --git a/src/sage/rings/rational_field.py b/src/sage/rings/rational_field.py index e7959e21a01..2a4237f0dfc 100644 --- a/src/sage/rings/rational_field.py +++ b/src/sage/rings/rational_field.py @@ -1576,6 +1576,18 @@ def _polymake_init_(self): """ return '"Rational"' + def _sympy_(self): + r""" + Return the SymPy set ``Rationals``. + + EXAMPLES:: + + sage: QQ._sympy_() + Rationals + """ + from sympy import Rationals + return Rationals + def _sage_input_(self, sib, coerced): r""" Produce an expression which will reproduce this value when evaluated. diff --git a/src/sage/sets/non_negative_integers.py b/src/sage/sets/non_negative_integers.py index 9d3579a5f46..adabc89a987 100644 --- a/src/sage/sets/non_negative_integers.py +++ b/src/sage/sets/non_negative_integers.py @@ -221,3 +221,16 @@ def unrank(self, rnk): 100 """ return self.from_integer(rnk) + + def _sympy_(self): + r""" + Return the SymPy set ``Naturals0``. + + EXAMPLES:: + + sage: NN = NonNegativeIntegers() + sage: NN._sympy_() + Naturals0 + """ + from sympy import Naturals0 + return Naturals0 diff --git a/src/sage/sets/positive_integers.py b/src/sage/sets/positive_integers.py index c800d201e95..693ca04706c 100644 --- a/src/sage/sets/positive_integers.py +++ b/src/sage/sets/positive_integers.py @@ -75,3 +75,15 @@ def an_element(self): 42 """ return Integer(42) + + def _sympy_(self): + r""" + Return the SymPy set ``Naturals``. + + EXAMPLES:: + + sage: PositiveIntegers()._sympy_() + Naturals + """ + from sympy import Naturals + return Naturals diff --git a/src/sage/sets/real_set.py b/src/sage/sets/real_set.py index a4621569133..f2eb7d97202 100644 --- a/src/sage/sets/real_set.py +++ b/src/sage/sets/real_set.py @@ -415,6 +415,28 @@ def _sympy_condition_(self, variable): upper_condition = true return lower_condition & upper_condition + def _sympy_(self): + r""" + Return the SymPy set corresponding to ``self``. + + EXAMPLES:: + + sage: RealSet.open_closed(0, 1)[0]._sympy_() + Interval.Lopen(0, 1) + sage: RealSet.point(0)[0]._sympy_() + FiniteSet(0) + sage: RealSet.open(0,1)[0]._sympy_() + Interval.open(0, 1) + sage: RealSet.open(-oo,1)[0]._sympy_() + Interval.open(-oo, 1) + sage: RealSet.open(0, oo)[0]._sympy_() + Interval.open(0, oo) + """ + from sympy import Interval + return Interval(self.lower(), self.upper(), + left_open=not self._lower_closed, + right_open=not self._upper_closed) + def closure(self): """ Return the closure @@ -986,6 +1008,17 @@ def is_empty(self): """ return len(self._intervals) == 0 + def is_universe(self): + """ + Return whether the set is the ambient space (the real line). + + EXAMPLES:: + + sage: RealSet().ambient().is_universe() + True + """ + return self == self.ambient() + def get_interval(self, i): """ Return the ``i``-th connected component. @@ -1811,3 +1844,33 @@ def __rmul__(self, other): [0, 1/2*pi] + [2*pi, +oo) """ return self * other + + def _sympy_(self): + r""" + Return the SymPy set corresponding to ``self``. + + EXAMPLES:: + + sage: RealSet()._sympy_() + EmptySet + sage: RealSet.point(5)._sympy_() + FiniteSet(5) + sage: (RealSet.point(1).union(RealSet.point(2)))._sympy_() + FiniteSet(1, 2) + sage: (RealSet(1, 2).union(RealSet.closed(3, 4)))._sympy_() + Union(Interval.open(1, 2), Interval(3, 4)) + sage: RealSet(-oo, oo)._sympy_() + Reals + + Infinities are not elements:: + + sage: import sympy + sage: RealSet(-oo, oo)._sympy_().contains(sympy.oo) + False + """ + from sympy import Reals, Union + if self.is_universe(): + return Reals + else: + return Union(*[interval._sympy_() + for interval in self._intervals]) From 93fbb2be5b07dfa18b4b1aec6d30c3c2895c54ab Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 9 Jun 2021 13:52:18 -0700 Subject: [PATCH 2/2] Call sympy_init in all added _sympy_ methods --- src/sage/categories/sets_cat.py | 2 ++ src/sage/modules/free_module.py | 2 ++ src/sage/rings/integer_ring.pyx | 2 ++ src/sage/rings/rational_field.py | 2 ++ src/sage/sets/non_negative_integers.py | 2 ++ src/sage/sets/positive_integers.py | 2 ++ src/sage/sets/real_set.py | 4 ++++ 7 files changed, 16 insertions(+) diff --git a/src/sage/categories/sets_cat.py b/src/sage/categories/sets_cat.py index 6b2f57e18cf..4b17b8f23d2 100644 --- a/src/sage/categories/sets_cat.py +++ b/src/sage/categories/sets_cat.py @@ -2451,6 +2451,8 @@ def _sympy_(self): True """ from sympy import ProductSet + from sage.interfaces.sympy import sympy_init + sympy_init() return ProductSet(*self.cartesian_factors()) class ElementMethods: diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 36f668d99fe..c8617d1885b 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -5318,6 +5318,8 @@ def _sympy_(self): True """ from sympy import ProductSet + from sage.interfaces.sympy import sympy_init + sympy_init() return ProductSet(*([self.coordinate_ring()] * self.rank())) diff --git a/src/sage/rings/integer_ring.pyx b/src/sage/rings/integer_ring.pyx index 737dda9ecb3..2d4aa4eb8af 100644 --- a/src/sage/rings/integer_ring.pyx +++ b/src/sage/rings/integer_ring.pyx @@ -1477,6 +1477,8 @@ cdef class IntegerRing_class(PrincipalIdealDomain): Integers """ from sympy import Integers + from sage.interfaces.sympy import sympy_init + sympy_init() return Integers def _sage_input_(self, sib, coerced): diff --git a/src/sage/rings/rational_field.py b/src/sage/rings/rational_field.py index 2a4237f0dfc..c79d2655535 100644 --- a/src/sage/rings/rational_field.py +++ b/src/sage/rings/rational_field.py @@ -1586,6 +1586,8 @@ def _sympy_(self): Rationals """ from sympy import Rationals + from sage.interfaces.sympy import sympy_init + sympy_init() return Rationals def _sage_input_(self, sib, coerced): diff --git a/src/sage/sets/non_negative_integers.py b/src/sage/sets/non_negative_integers.py index adabc89a987..9b01ad6f3d4 100644 --- a/src/sage/sets/non_negative_integers.py +++ b/src/sage/sets/non_negative_integers.py @@ -233,4 +233,6 @@ def _sympy_(self): Naturals0 """ from sympy import Naturals0 + from sage.interfaces.sympy import sympy_init + sympy_init() return Naturals0 diff --git a/src/sage/sets/positive_integers.py b/src/sage/sets/positive_integers.py index 693ca04706c..7ed7d9657e9 100644 --- a/src/sage/sets/positive_integers.py +++ b/src/sage/sets/positive_integers.py @@ -86,4 +86,6 @@ def _sympy_(self): Naturals """ from sympy import Naturals + from sage.interfaces.sympy import sympy_init + sympy_init() return Naturals diff --git a/src/sage/sets/real_set.py b/src/sage/sets/real_set.py index f2eb7d97202..1f594c59752 100644 --- a/src/sage/sets/real_set.py +++ b/src/sage/sets/real_set.py @@ -433,6 +433,8 @@ def _sympy_(self): Interval.open(0, oo) """ from sympy import Interval + from sage.interfaces.sympy import sympy_init + sympy_init() return Interval(self.lower(), self.upper(), left_open=not self._lower_closed, right_open=not self._upper_closed) @@ -1869,6 +1871,8 @@ def _sympy_(self): False """ from sympy import Reals, Union + from sage.interfaces.sympy import sympy_init + sympy_init() if self.is_universe(): return Reals else: