-
Notifications
You must be signed in to change notification settings - Fork 1.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
python symbolic::Formula returns True for matrices (but not scalars)? #8315
Comments
It's because
So, in the end, we have |
First thing I can do is to provide |
I'm not sure I'm 100% understanding the bug report or subsequent discussion here. Russ, are you saying that the desired output should look like this? [x(0) x(1)]
(x(0) = 0)
[(x(0) = 0) (x(1) = 0)] |
@jwnimmer-tri , I think that's what Russ wants. |
So we'll have:
I like this. |
FYI, this is what we already have as
I'll open a PR shortly. But the thing is that it will not give us what Russ wants for the above I think there are no good solutions as long as we want to use both of
I'm happy to learn if there is a better option here. |
@EricCousineau-TRI says he might know a solution |
One thing is However, looking more at the discussion, it may seem to be something else; I'm guessing it's because NumPy's I'll see if there's a way around that. EDIT: Can reproduce the issue per Soonho's comment in a simplified example: EricCousineau-TRI/repro@c6398b5 |
I just found that numpy provides the function that I looked for: https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.logic.html#comparison |
I tested
:( There is a possibility of extending a custom But that means that (a) we have to cast in |
:-( Just found the same problem. It has |
Nay :( Seems to be constrained by
It seems that your option (2) (perhaps have |
sigh... I'll dig it up this evening. |
One other option: From the results of #8116, if it is possible to write a custom dtype, and possibly register custom ufuncs, then perhaps there is a chance that we can register a ufunc for That being said, I'm not sure if that will affect the behavior of |
Will update this post with some other options:
Tracing up where I think
|
Hup, it looks like there's a method We could use this to do something like:
and see if there's a way to teach the ufunc about how to handle different dtypes, so that we don't impact performance of other objects. Example of a simple override (which would cause everything to slow down / suck):
|
Looks nice! I'll try that in the coming PR. |
Hmm... Is it OK if we hold off on incorporating this just yet? What kind of timeline would you want this resolved on? (I've talked with @m-chaturvedi, and we'll start addressing #8116) |
@RussTedrake can answer this (he marked this with high priority). |
it depends on the cost of resolving it... but I'm about to lecture about trajectory optimization, and this occurs very frequently when formulating trajectory optimizations. |
i also marked it as "high" priority because in it's current form, it's a bit of a landmine... |
Sounds good. I'll focus on the next few of days, because after having worked on it for a bit, I'm fairly confident that the solution for #8116 will most likely solve this too (if it goes like I planned it). BTW: Posted StackOverflow as well: https://stackoverflow.com/questions/49205075/possible-to-have-logical-operations-e-g-ndarray-eq-not-return-bool-in |
Finally finished the spike test (with some generalizing / polishing), and it seems like user-defined dtypes in NumPy will solve both this issue and #8116: Output from those lines in the Python script (out of sheer laziness, I had
Required some shifty appeasements of both While it sucks to leak memory, I think is the cleanest solution. In reviewing PyTorch, Tensorflow, etc., I realized that each of those might have some niceties, but would be a longer-term goal (using this article as a quick overview / guide: Will start polishing this to push into |
Right now I think the problem is that I think it would be pretty reasonable for numpy to add a |
Per Slack convo with @hongkai-dai, this is one workaround that can be used with NumPy 1.13.3, used on Bionic, which predates upstream patches which are NumPy ~1.15: Output:
Will write up a PR thing. |
Just to leave a clear update (even for my own memory), the current status is that
results in
|
btw @EricCousineau-TRI -- the "DeprecationWarning" above actually terminates my program. |
Yup, that is intentional. If it didn't, then you'd just have a crappier error later on: drake/bindings/pydrake/common/deprecation.py Lines 177 to 179 in 1f26da1
|
Now NEP 15 is done and numpy doc recommends
Any updates on this? Any plan to subclass np.ndarray in the future so built-in operators like <, > will be supported (and thus allow vectorized constraints)? |
if |
Note that our minimum required version of |
I looked further into this today and found a temporary solution. If we want a high-performance version of this (actual multi-threaded vectorized creation of new formulas), overriding This is because of there is no signature for logical operators to return objects. from numpy documentation, it's always bool.
However, if we don't mind having the same performance as list comprehension, the solution is actually really easy, as shown in my code block below. We can use Here is a temporary workaround for us:
Output will be
|
It shouldn't be hard to write a patch to change this. IIRC, numpy now has "object loops" for the |
Excellent! Thank you @buoyancy99 and @eric-wieser ! I would definitely like to resolve this. @buoyancy99 , does Eric's hint give you enough to go on to explore that version of the solution? |
In fact, the object loop already exists as far back as numpy 1.16.5 (numpy/numpy#10745), which I referred to in #8315 (comment) above In [30]: from sympy import symbols
In [31]: x, y = symbols('x y')
In [32]: np.greater([x], [y]) # errors
TypeError: cannot determine truth value of Relational
In [33]: np.greater([x], [y], dtype=object) # works
Out[33]: array([x > y], dtype=object) |
Just updated the patched subclass code following Eric's suggestion and it works. However, I believe that with this update, we will still need to subclass np.ndarray and link all C++ Expression arrays to it. This has to be done in our fork of pybind11 I believe. I need some additional guidance on how to start there. Updated subclass code
|
Probably you want the more conservative: class PatchedArray(np.ndarray):
to_patch = { # no need for a `dict` any more
np.greater,
np.greater_equal,
np.less,
np.less_equal,
np.equal,
np.not_equal
}
def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
with np.testing.suppress_warnings() as sup:
sup.filter(RuntimeWarning, "invalid value encountered in")
casted_inputs = (item.view(np.ndarray) if isinstance(item, PatchedArray) else item for item in inputs)
if ufunc in self.to_patch:
kwargs.setdefault('dtype', object)
return getattr(ufunc, method)(*casted_inputs, **kwargs)
else:
return getattr(ufunc, method)(*casted_inputs, **kwargs).view(PatchedArray) which doesn't override the |
any suggestion for the pybind11 part? |
Not really, I haven't touched pybind11 for a few years |
Our goal in Drake is to get rid of our fork of
As I understand it, the goal is to return |
Actually, we want to patch |
Sounds great! I would love to finally resolve this. |
I get the following output:
The text was updated successfully, but these errors were encountered: