-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Point(1) in Interval(0, 2) == False ? - Fails in 1 dim #11683
Comments
It seems that the reason for this behaviour is that def _contains(self, other):
if not isinstance(other, Expr) or (
other is S.Infinity or
other is S.NegativeInfinity or
other is S.NaN or
other is S.ComplexInfinity) or other.is_real is False:
return false On the contrary, when def _contains(self, element):
"""
"""
try:
if len(element) != len(self.args):
return false
except TypeError: # maybe element isn't an iterable
return false
return And(*
[set.contains(item) for set, item in zip(self.sets, element)]) A possible fix is to add this line to while isinstance(other, collections.Iterable) and len(other) == 1:
other = other[0] I can add this fix and send a pull request. I'm new to open-source contribution. I don't know if I should now wait for a confirmation by someone, or should I just proceed to applying the suggested fix |
What you propose sounds fine to me. |
So I will work on this issue |
In commit 29268d3 a condition is added which requires the if len(coords) < 2:
raise ValueError(filldedent('''
Point requires 2 or more coordinates or
keyword `dim` > 1.''')) Does it mean that we can close this issue? |
mm, i think its not solved, in some way yes, but the origin of this not, of the first place, why dim 1 is disabled? al leas to me don't have to much sense... |
I tried to remove the condition that disallows one-dimensional points. However, several tests (which I think were added in commit b2aae57) failed. To me this indicates a firm intention to disallow one-dimensional points. Since the condition and tests were added by @smichr , It would be good if he can comment on this. Are there strong reasons for excluding one-dimensional points? |
@bhrzbbk Can you open a PR with your fix for this issue ? |
@kshitij10496 The failing tests are not just from |
mm, think would be nice can see the changes, maybe link your branch with the tmp fix here?, or open a |
This is the example of the faulty behaviour from Issue sympy#11683: >>> Point(1) in Interval(0, 2) False >>> Point(1, 1) in Interval(0, 2)*Interval(0, 2) True * Allow a `Point` object to have a dimension less than two again (this was disallowed in commit 29268d3) * Explicitly extract the expression from the `Point` object when it is one-dimensional Signed-off-by: latot <felipematas@yahoo.com>
Hi, i check your change, i think i know why this fails, basically you change two behaviors:
This two cases now pass when it should return an error, the first case i think is a nice change, and it respect the idea written in the wiki i think we can open a new issue for that and can use it. Thx. Cya. |
@latot Thanks for checking out the change. About the first type of errors (upgrade to higher dimensionality), I also think that this is a good behaviour and probably the tests should be adapted to allow this. As for the second type of errors, I guess silent upgrade of numbers to one-dimensional points can be dangerous. I'll try to address that in my fix; i.e. make sure that the errors of second type will not happen. |
Hi!, only as a reference of the second behavior Thx. Cya. |
This now gives an error: In [184]: Point(1) in Interval(0, 2)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-184-5a2ba01f9f49> in <module>
----> 1 Point(1) in Interval(0, 2)
~/current/sympy/sympy/sympy/geometry/point.py in __new__(cls, *args, **kwargs)
127 raise TypeError(filldedent('''
128 Expecting sequence of coordinates, not `{}`'''
--> 129 .format(func_name(coords))))
130 # A point where only `dim` is specified is initialized
131 # to zeros.
TypeError:
Expecting sequence of coordinates, not `int` |
I personally don't think that the it's a good idea to make algebraic objects compatible with geometric elements without any context put into. I think that for the original case, the relational should not be defined at all. But we may need some other representations like that can create a new region from line segments. |
Is a point... In my case i think there is already a relation, in a context of measure, they are types, a point and a interval have the same type. I'm agree even if they are just different ways of measure is not enough to compare, there is the argument, "how are different types of measure, to compare would need to be the same type" I think should be necessary say explicitily the type of comparation what we are doing. To follow the ideas, maybe for example: Limit the comparision to something just can be "in" other thing if they are the same type, 2 dim with 2 dim, 1 dim with 1 dim, and send an error of "wrong types to compare" when we send 2 different types. here some cases: Point(1) in Point(2) = False To follow the measure types correctly wold be necessary some changes, like, Point(1) should be the same as Interval(1,1). I don't know if you will like the idea, but at least i think, should be necessary some order in how sympy works with measure. What is hard here too is, if is dissabled this feature, how can we know if a point is contained in a interval for example?, at least the "in" function would be less intuitive. Bye Bye |
The error comes from the creation of I agree with @sylee957 that it's not a good idea to mix geometric objects and sets. The logical conclusion of allowing this is that Point(1) should be identified with the number 1. A better way to check this would be to create the geometric object you want to check if the point is in, like |
We can also do this in a conceptually valid way using In [28]: S = ImageSet(Lambda((x, y), Point(x, y)), Interval(0, 2), Interval(0, 2))
In [29]: S
Out[29]: {Point2D(x, y) | x ∊ [0, 2] , y ∊ [0, 2]}
In [30]: Point(1, 1) in S
Out[30]: True
In [31]: Point(1, 3) in S
Out[31]: False |
As far as I can tell everything here is working fine except that 1D Points don't work. |
Currently, isympy
IPython console for SymPy 1.5.dev (Python 3.6.8-64-bit) (ground types: python)
These commands were executed:
>>> from __future__ import division
>>> from sympy import *
>>> x, y, z, t = symbols('x y z t')
>>> k, m, n = symbols('k m n', integer=True)
>>> f, g, h = symbols('f g h', cls=Function)
>>> init_printing()
Documentation can be found at https://docs.sympy.org/dev
In [1]: S = ImageSet(Lambda((x, y), Point(x, y)),
...: Interval(0, 2), Interval(0, 2))
In [2]: S
Out[2]: {Point2D(x, y) | x ∊ [0, 2] , y ∊ [0, 2]}
In [3]: Point(1, 0) in S
--------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-3-08b0876fc56d> in <module>
----> 1 Point(1, 0) in S
~/sympy/sympy/sets/sets.py in __contains__(self, other)
637 def __contains__(self, other):
638 other = sympify(other)
--> 639 c = self._contains(other)
640 b = tfn[c]
641 if b is None:
~/sympy/sympy/sets/fancysets.py in _contains(self, other)
456 variables = tuple(variables)
457 base_sets = [symsetmap[v] for v in variables]
--> 458 solnset = _solveset_multi(equations, variables, base_sets)
459 if solnset is None:
460 return None
~/sympy/sympy/solvers/solveset.py in _solveset_multi(eqs, syms, domains)
2052 if sym not in eqs[n].free_symbols:
2053 continue
-> 2054 sol = solveset(eqs[n], sym, domains[syms.index(sym)])
2055
2056 if isinstance(sol, FiniteSet):
~/sympy/sympy/solvers/solveset.py in solveset(f, symbol, domain)
1991 try:
1992 r = Dummy('r', **assumptions)
-> 1993 return solveset(f.xreplace({symbol: r}), r, domain
1994 ).xreplace({r: symbol})
1995 except InconsistentAssumptions:
~/sympy/sympy/solvers/solveset.py in solveset(f, symbol, domain)
2009 f = piecewise_fold(f)
2010
-> 2011 return _solveset(f, symbol, domain, _check=True)
2012
2013
~/sympy/sympy/solvers/solveset.py in _solveset(f, symbol, domain, _check)
924 result += solns
925 elif isinstance(f, Eq):
--> 926 result = solver(Add(f.lhs, - f.rhs, evaluate=False), symbol, domain)
927
928 elif f.is_Relational:
~/sympy/sympy/solvers/solveset.py in <lambda>(f, x, domain)
891
892 # assign the solvers to use
--> 893 solver = lambda f, x, domain=domain: _solveset(f, x, domain)
894 inverter = lambda f, rhs, symbol: _invert(f, rhs, symbol, domain)
895
~/sympy/sympy/solvers/solveset.py in _solveset(f, symbol, domain, _check)
885 elif f.is_Add:
886 a, h = f.as_independent(symbol)
--> 887 m, h = h.as_independent(symbol, as_Add=False)
888 if m not in set([S.ComplexInfinity, S.Zero, S.Infinity,
889 S.NegativeInfinity]):
AttributeError: 'Point2D' object has no attribute 'as_independent'
In [4]: Point(1, 1) in S
--------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-4-2063532373c8> in <module>
----> 1 Point(1, 1) in S
~/sympy/sympy/sets/sets.py in __contains__(self, other)
637 def __contains__(self, other):
638 other = sympify(other)
--> 639 c = self._contains(other)
640 b = tfn[c]
641 if b is None:
~/sympy/sympy/sets/fancysets.py in _contains(self, other)
456 variables = tuple(variables)
457 base_sets = [symsetmap[v] for v in variables]
--> 458 solnset = _solveset_multi(equations, variables, base_sets)
459 if solnset is None:
460 return None
~/sympy/sympy/solvers/solveset.py in _solveset_multi(eqs, syms, domains)
2052 if sym not in eqs[n].free_symbols:
2053 continue
-> 2054 sol = solveset(eqs[n], sym, domains[syms.index(sym)])
2055
2056 if isinstance(sol, FiniteSet):
~/sympy/sympy/solvers/solveset.py in solveset(f, symbol, domain)
1991 try:
1992 r = Dummy('r', **assumptions)
-> 1993 return solveset(f.xreplace({symbol: r}), r, domain
1994 ).xreplace({r: symbol})
1995 except InconsistentAssumptions:
~/sympy/sympy/solvers/solveset.py in solveset(f, symbol, domain)
2009 f = piecewise_fold(f)
2010
-> 2011 return _solveset(f, symbol, domain, _check=True)
2012
2013
~/sympy/sympy/solvers/solveset.py in _solveset(f, symbol, domain, _check)
924 result += solns
925 elif isinstance(f, Eq):
--> 926 result = solver(Add(f.lhs, - f.rhs, evaluate=False), symbol, domain)
927
928 elif f.is_Relational:
~/sympy/sympy/solvers/solveset.py in <lambda>(f, x, domain)
891
892 # assign the solvers to use
--> 893 solver = lambda f, x, domain=domain: _solveset(f, x, domain)
894 inverter = lambda f, rhs, symbol: _invert(f, rhs, symbol, domain)
895
~/sympy/sympy/solvers/solveset.py in _solveset(f, symbol, domain, _check)
885 elif f.is_Add:
886 a, h = f.as_independent(symbol)
--> 887 m, h = h.as_independent(symbol, as_Add=False)
888 if m not in set([S.ComplexInfinity, S.Zero, S.Infinity,
889 S.NegativeInfinity]):
AttributeError: 'Point2D' object has no attribute 'as_independent'
In [5]: Point(1, 3) in S
--------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-5-cae7a6a9a54c> in <module>
----> 1 Point(1, 3) in S
~/sympy/sympy/sets/sets.py in __contains__(self, other)
637 def __contains__(self, other):
638 other = sympify(other)
--> 639 c = self._contains(other)
640 b = tfn[c]
641 if b is None:
~/sympy/sympy/sets/fancysets.py in _contains(self, other)
456 variables = tuple(variables)
457 base_sets = [symsetmap[v] for v in variables]
--> 458 solnset = _solveset_multi(equations, variables, base_sets)
459 if solnset is None:
460 return None
~/sympy/sympy/solvers/solveset.py in _solveset_multi(eqs, syms, domains)
2052 if sym not in eqs[n].free_symbols:
2053 continue
-> 2054 sol = solveset(eqs[n], sym, domains[syms.index(sym)])
2055
2056 if isinstance(sol, FiniteSet):
~/sympy/sympy/solvers/solveset.py in solveset(f, symbol, domain)
1991 try:
1992 r = Dummy('r', **assumptions)
-> 1993 return solveset(f.xreplace({symbol: r}), r, domain
1994 ).xreplace({r: symbol})
1995 except InconsistentAssumptions:
~/sympy/sympy/solvers/solveset.py in solveset(f, symbol, domain)
2009 f = piecewise_fold(f)
2010
-> 2011 return _solveset(f, symbol, domain, _check=True)
2012
2013
~/sympy/sympy/solvers/solveset.py in _solveset(f, symbol, domain, _check)
924 result += solns
925 elif isinstance(f, Eq):
--> 926 result = solver(Add(f.lhs, - f.rhs, evaluate=False), symbol, domain)
927
928 elif f.is_Relational:
~/sympy/sympy/solvers/solveset.py in <lambda>(f, x, domain)
891
892 # assign the solvers to use
--> 893 solver = lambda f, x, domain=domain: _solveset(f, x, domain)
894 inverter = lambda f, rhs, symbol: _invert(f, rhs, symbol, domain)
895
~/sympy/sympy/solvers/solveset.py in _solveset(f, symbol, domain, _check)
885 elif f.is_Add:
886 a, h = f.as_independent(symbol)
--> 887 m, h = h.as_independent(symbol, as_Add=False)
888 if m not in set([S.ComplexInfinity, S.Zero, S.Infinity,
889 S.NegativeInfinity]):
AttributeError: 'Point2D' object has no attribute 'as_independent' |
Current status, >>> Point(1) in Interval(0, 2)
Traceback (most recent call last):
File "/usr/lib/python3.6/code.py", line 91, in runcode
exec(code, self.locals)
File "<console>", line 1, in <module>
File "/home/czgdp1807ssd/sympy_project/sympy/sympy/geometry/point.py", line 126, in __new__
.format(func_name(coords))))
TypeError:
Expecting sequence of coordinates, not `int`
>>> Point(1, 1) in Interval(0, 2)*Interval(0, 2)
False |
Now, it looks like Actually, I think that the logical problem of equating |
We could have an
I don't think we should identify the geometry objects directly as tuples. That kind of confusion around definitions comes up around sympy and always causes problems. It is almost always best just to keep things separate and have clear methods for converting between different types of objects. |
I agree, although I think it's more natural to convert the set object into a geometric entity rather than converting the point into a number or tuple. |
Hi, here a little weird thing
as you can see Point works fine in 2 dims, but in 1 we get that.
Thx. Cya.
The text was updated successfully, but these errors were encountered: