Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ConditionSet object not iterable #21258

Open
amine-aboufirass opened this issue Apr 7, 2021 · 7 comments
Open

ConditionSet object not iterable #21258

amine-aboufirass opened this issue Apr 7, 2021 · 7 comments
Labels

Comments

@amine-aboufirass
Copy link

I would like to generate a simple set based on a condition to mimic set builder notation, and then enumerate its contents. I tried the following based on an example in the docs:

from sympy import Symbol, S, ConditionSet
from sympy.abc import x

new_set = ConditionSet(x, x<7, S.Naturals)
iterable = iter(new_set)
print("done")

When I run this I get an error:

Traceback (most recent call last):
  File "test.py", line 5, in <module>
    iterable = iter(new_set)
TypeError: 'ConditionSet' object is not iterable

Why is it that I cannot enumerate the ConditionSet object? It has finite contents so I would assume this should be possible?

Thanks

@akshanshbhatt
Copy link
Member

ConditionSet can represent your set in set builder form. It is useful only when you have to check whether a particular element is present in your set. These sets are not stored in their roster form. Although this is one specific case in which the set is countably finite. I would suggest you use iterable sets such as FiniteSet for such purposes.

@amine-aboufirass
Copy link
Author

amine-aboufirass commented Apr 7, 2021

But you cannot construct FiniteSet objects based on conditionals... Ultimately I would like to construct a set like A = {1, 4, 7, 10, 13...} and check whether it is closed under operations like addition and multiplication, or perhaps user-defined operations like x+y+x*y. Perhaps I am going about this the wrong way?

@oscarbenjamin
Copy link
Contributor

It would be possible to add an __iter__ method to ConditionSet but in a case like this the iteration would never terminate. You can do it yourself like:

def iter_cs(cs):
    for x in cs.base_set:
        if cs.contains(x):
            yield x

Ideally there would be a way to simplify this ConditionSet into a FiniteSet.

@amine-aboufirass
Copy link
Author

I see. That is a slick workaround but I could see it totally break down for cases where the call to .contains is expensive. It also appears to not know when to raise a StopIteration...

I tried simplify but still get another ConditionSet on the other end... Any idea why it is not simplifying to FiniteSet in the current version of sympy?

@oscarbenjamin
Copy link
Contributor

That's not a slick workaround. That's what __iter__ for a ConditionSet would have to be if it was defined. The fact that contains is expensive is only part of the problem. It is sometimes impossible to know whether an element of the base set does or does not satisfy the condition e.g.:

In [11]: ConditionSet(x, x<y, {1, 2, 3})
Out[11]: {xx ∊ {1, 2, 3} ∧ (x < y)}

There are not many functions for simplifying sets yet.

@smichr
Copy link
Member

smichr commented Apr 7, 2021

I posted this comment at SO:

ConditionSet does not try hard to resolve its expression with an infinite base set. For linear or quadratic univariate inequalities, it wouldn't be hard to do so at instantiation, however. But for now you have to do so on your own:

>>> c = ConditionSet(x, x < 7, S.Naturals)
>>> solveset(c.args[1], c.args[0], domain=S.Reals).intersection(c.args[-1])
Range(1, 7, 1)
>>> next(iter(_))
1

In theory you should be able to set domain=c.args[-1] but the solver does not handle such sets well, yet.

@smichr
Copy link
Member

smichr commented Apr 8, 2021

does not handle such sets well, yet.

This is fixed in the most up to date master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants