Skip to content

Commit

Permalink
gh-36272: sage.sets: Update # needs
Browse files Browse the repository at this point in the history
    
<!-- ^^^^^
Please provide a concise, informative and self-explanatory title.
Don't put issue numbers in there, do this in the PR body below.
For example, instead of "Fixes #1234" use "Introduce new method to
calculate 1+1"
-->
<!-- Describe your changes here in detail -->

<!-- Why is this change required? What problem does it solve? -->
<!-- If this PR resolves an open issue, please link to it here. For
example "Fixes #12345". -->
- Part of: #29705
- Cherry-picked from: #35095
<!-- If your change requires a documentation PR, please link it
appropriately. -->

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->
<!-- If your change requires a documentation PR, please link it
appropriately -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
<!-- Feel free to remove irrelevant items. -->

- [x] The title is concise, informative, and self-explanatory.
- [ ] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [ ] I have created tests covering the changes.
- [ ] I have updated the documentation accordingly.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on
- #12345: short description why this is a dependency
- #34567: ...
-->

<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
    
URL: #36272
Reported by: Matthias Köppe
Reviewer(s): David Coudert
  • Loading branch information
Release Manager committed Oct 4, 2023
2 parents 8ebaeff + 34e4139 commit 7c62ef8
Show file tree
Hide file tree
Showing 15 changed files with 388 additions and 303 deletions.
8 changes: 4 additions & 4 deletions src/sage/sets/cartesian_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,9 @@ def __len__(self):
EXAMPLES::
sage: C = cartesian_product([ZZ, QQ, CC])
sage: e = C.random_element()
sage: len(e)
sage: C = cartesian_product([ZZ, QQ, CC]) # needs sage.rings.real_mpfr
sage: e = C.random_element() # needs sage.rings.real_mpfr
sage: len(e) # needs sage.rings.real_mpfr
3
"""
return len(self.value)
Expand All @@ -368,7 +368,7 @@ def cartesian_factors(self):
EXAMPLES::
sage: A = cartesian_product([ZZ, RR])
sage: A((1, 1.23)).cartesian_factors()
sage: A((1, 1.23)).cartesian_factors() # needs sage.rings.real_mpfr
(1, 1.23000000000000)
sage: type(_)
<... 'tuple'>
Expand Down
78 changes: 47 additions & 31 deletions src/sage/sets/condition_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,28 +62,30 @@ class ConditionSet(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_ope
sage: 7/2 in EvensAndOdds
False
sage: var('y')
sage: var('y') # needs sage.symbolic
y
sage: SmallOdds = ConditionSet(ZZ, is_odd, abs(y) <= 11, vars=[y]); SmallOdds
sage: SmallOdds = ConditionSet(ZZ, is_odd, abs(y) <= 11, vars=[y]); SmallOdds # needs sage.symbolic
{ y ∈ Integer Ring : abs(y) <= 11, <function is_odd at 0x...>(y) }
sage: # needs sage.geometry.polyhedron
sage: P = polytopes.cube(); P
A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices
sage: P.rename("P")
sage: P_inter_B = ConditionSet(P, lambda x: x.norm() < 1.2); P_inter_B
{ x ∈ P : <function <lambda> at 0x...>(x) }
sage: vector([1, 0, 0]) in P_inter_B
True
sage: vector([1, 1, 1]) in P_inter_B
sage: vector([1, 1, 1]) in P_inter_B # needs sage.symbolic
False
sage: # needs sage.symbolic
sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 1.2; predicate
(x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 1.20000000000000
sage: P_inter_B_again = ConditionSet(P, predicate); P_inter_B_again
sage: P_inter_B_again = ConditionSet(P, predicate); P_inter_B_again # needs sage.geometry.polyhedron
{ (x, y, z) ∈ P : sqrt(x^2 + y^2 + z^2) < 1.20000000000000 }
sage: vector([1, 0, 0]) in P_inter_B_again
sage: vector([1, 0, 0]) in P_inter_B_again # needs sage.geometry.polyhedron
True
sage: vector([1, 1, 1]) in P_inter_B_again
sage: vector([1, 1, 1]) in P_inter_B_again # needs sage.geometry.polyhedron
False
Iterating over subsets determined by predicates::
Expand All @@ -104,24 +106,25 @@ class ConditionSet(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_ope
Using ``ConditionSet`` without predicates provides a way of attaching variable names
to a set::
sage: Z3 = ConditionSet(ZZ^3, vars=['x', 'y', 'z']); Z3
{ (x, y, z) ∈ Ambient free module of rank 3 over the principal ideal domain Integer Ring }
sage: Z3.variable_names()
sage: Z3 = ConditionSet(ZZ^3, vars=['x', 'y', 'z']); Z3 # needs sage.modules
{ (x, y, z) ∈ Ambient free module of rank 3
over the principal ideal domain Integer Ring }
sage: Z3.variable_names() # needs sage.modules
('x', 'y', 'z')
sage: Z3.arguments()
sage: Z3.arguments() # needs sage.modules sage.symbolic
(x, y, z)
sage: Q4.<a, b, c, d> = ConditionSet(QQ^4); Q4
sage: Q4.<a, b, c, d> = ConditionSet(QQ^4); Q4 # needs sage.modules sage.symbolic
{ (a, b, c, d) ∈ Vector space of dimension 4 over Rational Field }
sage: Q4.variable_names()
sage: Q4.variable_names() # needs sage.modules sage.symbolic
('a', 'b', 'c', 'd')
sage: Q4.arguments()
sage: Q4.arguments() # needs sage.modules sage.symbolic
(a, b, c, d)
TESTS::
sage: TestSuite(P_inter_B).run(skip='_test_pickling') # cannot pickle lambdas
sage: TestSuite(P_inter_B_again).run()
sage: TestSuite(P_inter_B).run(skip='_test_pickling') # cannot pickle lambdas # needs sage.geometry.polyhedron
sage: TestSuite(P_inter_B_again).run() # needs sage.geometry.polyhedron sage.symbolic
"""
@staticmethod
def __classcall_private__(cls, universe, *predicates, vars=None, names=None, category=None):
Expand All @@ -130,9 +133,9 @@ def __classcall_private__(cls, universe, *predicates, vars=None, names=None, cat
TESTS::
sage: ConditionSet(ZZ, names=["x"]) is ConditionSet(ZZ, names=x)
sage: ConditionSet(ZZ, names=["x"]) is ConditionSet(ZZ, names=x) # needs sage.symbolic
True
sage: ConditionSet(RR, x > 0, names=x) is ConditionSet(RR, (x > 0).function(x))
sage: ConditionSet(RR, x > 0, names=x) is ConditionSet(RR, (x > 0).function(x)) # needs sage.symbolic
True
"""
if category is None:
Expand Down Expand Up @@ -224,10 +227,10 @@ def _repr_(self):
EXAMPLES::
sage: var('t') # parameter
sage: var('t') # parameter # needs sage.symbolic
t
sage: ZeroDimButNotNullary = ConditionSet(ZZ^0, t > 0, vars=("q"))
sage: ZeroDimButNotNullary._repr_()
sage: ZeroDimButNotNullary = ConditionSet(ZZ^0, t > 0, vars=("q")) # needs sage.symbolic
sage: ZeroDimButNotNullary._repr_() # needs sage.symbolic
'{ q ∈ Ambient free module of rank 0
over the principal ideal domain Integer Ring : t > 0 }'
"""
Expand Down Expand Up @@ -257,10 +260,12 @@ def _repr_condition(self, predicate):
sage: Evens = ConditionSet(ZZ, is_even)
sage: Evens._repr_condition(is_even)
'<function is_even at 0x...>(x)'
sage: # needs sage.symbolic
sage: BigSin = ConditionSet(RR, sin(x) > 0.9, vars=[x])
sage: BigSin._repr_condition(BigSin._predicates[0])
'sin(x) > 0.900000000000000'
sage: var('t') # parameter
sage: var('t') # parameter
t
sage: ZeroDimButNotNullary = ConditionSet(ZZ^0, t > 0, vars=("q"))
sage: ZeroDimButNotNullary._repr_condition(ZeroDimButNotNullary._predicates[0])
Expand All @@ -285,9 +290,9 @@ def arguments(self):
sage: Odds = ConditionSet(ZZ, is_odd); Odds
{ x ∈ Integer Ring : <function is_odd at 0x...>(x) }
sage: args = Odds.arguments(); args
sage: args = Odds.arguments(); args # needs sage.symbolic
(x,)
sage: args[0].parent()
sage: args[0].parent() # needs sage.symbolic
Symbolic Ring
"""
from sage.symbolic.ring import SR
Expand Down Expand Up @@ -339,6 +344,7 @@ def _call_predicate(self, predicate, element):
TESTS::
sage: # needs sage.modules sage.symbolic
sage: TripleDigits = ZZ^3
sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate
(x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 12
Expand All @@ -350,6 +356,7 @@ def _call_predicate(self, predicate, element):
sage: SmallTriples._call_predicate(predicate, element)
sqrt(14) < 12
sage: # needs sage.modules sage.symbolic
sage: var('t')
t
sage: TinyUniverse = ZZ^0
Expand All @@ -372,6 +379,7 @@ def _an_element_(self):
TESTS::
sage: # needs sage.modules sage.symbolic
sage: TripleDigits = ZZ^3
sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate
(x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 12
Expand Down Expand Up @@ -406,6 +414,7 @@ def _sympy_(self):
EXAMPLES::
sage: # needs sympy sage.modules sage.symbolic
sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate
(x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 12
sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples
Expand All @@ -418,17 +427,17 @@ def _sympy_(self):
True
sage: (5, 7, 9) in ST
False
sage: Interval = ConditionSet(RR, x >= -7, x <= 4, vars=[x]); Interval
{ x ∈ Real Field with 53 bits of precision : x >= -7, x <= 4 }
sage: Interval._sympy_()
ConditionSet(x, (x >= -7) & (x <= 4), SageSet(Real Field with 53 bits of precision))
ConditionSet(x, (x >= -7) & (x <= 4),
SageSet(Real Field with 53 bits of precision))
If a predicate is not symbolic, we fall back to creating a wrapper::
sage: Evens = ConditionSet(ZZ, is_even); Evens
{ x ∈ Integer Ring : <function is_even at 0x...>(x) }
sage: Evens._sympy_()
sage: Evens._sympy_() # needs sympy sage.symbolic
SageSet({ x ∈ Integer Ring : <function is_even at 0x...>(x) })
"""
from sage.interfaces.sympy import sympy_init
Expand Down Expand Up @@ -463,10 +472,12 @@ def intersection(self, X):
EXAMPLES::
sage: # needs sage.modules sage.symbolic
sage: in_small_oblong(x, y) = x^2 + 3 * y^2 <= 42
sage: SmallOblongUniverse = ConditionSet(QQ^2, in_small_oblong)
sage: SmallOblongUniverse
{ (x, y) ∈ Vector space of dimension 2 over Rational Field : x^2 + 3*y^2 <= 42 }
{ (x, y) ∈ Vector space of dimension 2
over Rational Field : x^2 + 3*y^2 <= 42 }
sage: parity_check(x, y) = abs(sin(pi/2*(x + y))) < 1/1000
sage: EvenUniverse = ConditionSet(ZZ^2, parity_check); EvenUniverse
{ (x, y) ∈ Ambient free module of rank 2 over the principal ideal
Expand All @@ -480,13 +491,18 @@ def intersection(self, X):
Combining two ``ConditionSet``s with different formal variables works correctly.
The formal variables of the intersection are taken from ``self``::
sage: SmallMirrorUniverse = ConditionSet(QQ^2, in_small_oblong, vars=(y, x))
sage: # needs sage.modules sage.symbolic
sage: SmallMirrorUniverse = ConditionSet(QQ^2, in_small_oblong,
....: vars=(y, x))
sage: SmallMirrorUniverse
{ (y, x) ∈ Vector space of dimension 2 over Rational Field : 3*x^2 + y^2 <= 42 }
{ (y, x) ∈ Vector space of dimension 2
over Rational Field : 3*x^2 + y^2 <= 42 }
sage: SmallOblongUniverse & SmallMirrorUniverse
{ (x, y) ∈ Vector space of dimension 2 over Rational Field : x^2 + 3*y^2 <= 42 }
{ (x, y) ∈ Vector space of dimension 2
over Rational Field : x^2 + 3*y^2 <= 42 }
sage: SmallMirrorUniverse & SmallOblongUniverse
{ (y, x) ∈ Vector space of dimension 2 over Rational Field : 3*x^2 + y^2 <= 42 }
{ (y, x) ∈ Vector space of dimension 2
over Rational Field : 3*x^2 + y^2 <= 42 }
"""
if isinstance(X, ConditionSet):
return ConditionSet(self.ambient().intersection(X.ambient()),
Expand Down
18 changes: 9 additions & 9 deletions src/sage/sets/disjoint_set.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def DisjointSet(arg):
or an iterable::
sage: DisjointSet(4.3)
sage: DisjointSet(4.3) # needs sage.rings.real_mpfr
Traceback (most recent call last):
...
TypeError: 'sage.rings.real_mpfr.RealLiteral' object is not iterable
Expand Down Expand Up @@ -561,7 +561,7 @@ cdef class DisjointSet_of_integers(DisjointSet_class):
sage: d.union(4,1)
sage: e = d.element_to_root_dict(); e
{0: 0, 1: 4, 2: 2, 3: 2, 4: 4}
sage: WordMorphism(e)
sage: WordMorphism(e) # needs sage.combinat
WordMorphism: 0->0, 1->4, 2->2, 3->2, 4->4
"""
d = {}
Expand All @@ -583,9 +583,9 @@ cdef class DisjointSet_of_integers(DisjointSet_class):
sage: d.union(3,4)
sage: d
{{0}, {1, 2, 3, 4}}
sage: g = d.to_digraph(); g
sage: g = d.to_digraph(); g # needs sage.graphs
Looped digraph on 5 vertices
sage: g.edges(sort=True)
sage: g.edges(sort=True) # needs sage.graphs
[(0, 0, None), (1, 2, None), (2, 2, None), (3, 2, None), (4, 2, None)]
The result depends on the ordering of the union::
Expand All @@ -596,7 +596,7 @@ cdef class DisjointSet_of_integers(DisjointSet_class):
sage: d.union(1,4)
sage: d
{{0}, {1, 2, 3, 4}}
sage: d.to_digraph().edges(sort=True)
sage: d.to_digraph().edges(sort=True) # needs sage.graphs
[(0, 0, None), (1, 1, None), (2, 1, None), (3, 1, None), (4, 1, None)]
"""
d = {i: [self._nodes.parent[i]] for i in range(self.cardinality())}
Expand Down Expand Up @@ -849,7 +849,7 @@ cdef class DisjointSet_of_hashables(DisjointSet_class):
sage: e = d.element_to_root_dict()
sage: sorted(e.items())
[(0, 0), (1, 4), (2, 2), (3, 2), (4, 4)]
sage: WordMorphism(e)
sage: WordMorphism(e) # needs sage.combinat
WordMorphism: 0->0, 1->4, 2->2, 3->2, 4->4
"""
d = {}
Expand All @@ -870,9 +870,9 @@ cdef class DisjointSet_of_hashables(DisjointSet_class):
sage: d.union(3,4)
sage: d
{{0}, {1, 2, 3, 4}}
sage: g = d.to_digraph(); g
sage: g = d.to_digraph(); g # needs sage.graphs
Looped digraph on 5 vertices
sage: g.edges(sort=True)
sage: g.edges(sort=True) # needs sage.graphs
[(0, 0, None), (1, 2, None), (2, 2, None), (3, 2, None), (4, 2, None)]
The result depends on the ordering of the union::
Expand All @@ -883,7 +883,7 @@ cdef class DisjointSet_of_hashables(DisjointSet_class):
sage: d.union(1,4)
sage: d
{{0}, {1, 2, 3, 4}}
sage: d.to_digraph().edges(sort=True)
sage: d.to_digraph().edges(sort=True) # needs sage.graphs
[(0, 0, None), (1, 1, None), (2, 1, None), (3, 1, None), (4, 1, None)]
"""
d = {}
Expand Down
Loading

0 comments on commit 7c62ef8

Please sign in to comment.