Multiple inequalities in a single Python expression?

4,517 views
Skip to first unread message

Kevin Hunter

unread,
Jan 7, 2012, 3:53:51 AM1/7/12
to sy...@googlegroups.com
Hullo Sympy Group,

How can I get Sympy to recognize 2+ inequalities in the same expression?  In mathematical optimization it is common to see (and often very convenient to use) constraint expressions like these:

3*x <= 2*y +10 <= 3*z
10*x >= 15*y >= 20*z >= t

Which are actually 2 and 3 inequalities.  However, when I put those in directly, it seems only the first or last inequality evaluated is returned:

-----
In [1]: ineq1 = 3*x <= 2*y +10 <= 3*z

In [2]: print ineq1
2*y + 10 <= 3*z

In [3]: ineq2 = 10*x >= 15*y >= 20*z >= t

In [4]: ineq2
15*y <= 10*x
-----

Right now, I can create multiple inequalities, but I have to build it via an inequality per python statement.  It would be much more convenient to be able to do this in one statement.

Thanks,

Kevin

P.S.  Sympy is already proving to be a boon to my project, spotting some bugs and inconsistencies in my logic.  Thanks!

Aaron Meurer

unread,
Jan 7, 2012, 4:29:00 AM1/7/12
to sy...@googlegroups.com
Hi.

There's an issue for this too:
http://code.google.com/p/sympy/issues/detail?id=2960

Python evaluates "a < b < c" as "(a < b) and (b < c)". Since it's
impossible to override the "and" operator, this always returns the
first one if it evaluate to True or the second one if it evaluate to
True (or False if neither do). Right now, this happens arbitrarily
(see http://code.google.com/p/sympy/issues/detail?id=2832).

This can be done, however, just not using that syntax. Use the And()
object. For example:

In [30]: And(10 < x, x < 13)
Out[30]: x < 13 ∧ 10 < x

In [14]: And(10 < x, x < 13).subs(x, 9)
Out[14]: False

In [15]: And(10 < x, x < 13).subs(x, 11)
Out[15]: True

Depending on what you are doing, you might be able to also make use of
the Interval() object:

In [18]: Interval(10, 13, True, True)
Out[18]: (10, 13)

We don't have an In() object yet, though (there's an issue for this
somewhere, but I couldn't find it, as In is a hard word to search
for), so if you want to explicitly represent the fact that some value
x is inside an interval, for now, you will have to use And() and
inequalities. What you can do is use Interval and it's useful
operations (such as union and intersection) until you need an explicit
relationship, and then use .as_relational()

In [31]: Interval(10, 13, True, True).as_relational(x)
Out[31]: x < 13 ∧ 10 < x

Of course, whether to use And() and inequalities or intervals depends
on what you are doing.

Aaron Meurer

> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/sympy/-/_BmcIHE29zcJ.
> To post to this group, send email to sy...@googlegroups.com.
> To unsubscribe from this group, send email to
> sympy+un...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/sympy?hl=en.

Kevin Hunter

unread,
Jan 7, 2012, 6:16:00 AM1/7/12
to sy...@googlegroups.com
Hmm, so I have some example code that I just threw together that implements a multiple inequality.  It isn't pretty in that I spent 5 minutes working it, and it uses a global, etc., but it's a proof of concept:

-----
In [1]: a, b, c, d = test('A'), test('B'), test('C'), test('D')

In [2]: x = a < b < c < d

In [3]: x
Out[3]: A < B < C < D
-----

If this is of interest, I'll ... attach the code for this to that issue.

Christophe BAL

unread,
Jan 7, 2012, 6:50:48 AM1/7/12
to sy...@googlegroups.com
Hello,
I am interested by your code.

Christophe.

Aaron Meurer

unread,
Jan 7, 2012, 8:11:12 AM1/7/12
to sy...@googlegroups.com
Hi.

I posted my comments on the issue page.

Aaron Meurer

> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To view this discussion on the web visit

> https://groups.google.com/d/msg/sympy/-/0Jl0-og4sgQJ.

Reply all
Reply to author
Forward
0 new messages