Solving set of inequalities

849 views
Skip to first unread message

Rainer Dorsch

unread,
Aug 6, 2022, 3:31:51 AM8/6/22
to sympy
Hi,

I just started with sympy, and try to understand how to tell sympy, what I
want. I tried
print(sympy.solvers.inequalities.reduce_rational_inequalities([[x + 2 > 0],[x
< 5]], x))
and expected
(-2 < x) & (x < 5)
but got
(-oo < x) & (x < oo)
Can anybody tell how I can tell sympy that x should satisfy both inequalities
the same time?
For me it seems sympy rather interprets the set of equations rather as an "or"
and not an "and"

Here is the full example

rd@h370:~/tmp.nobackup$ cat test-sympy.py
import sympy

x, y, z = sympy.symbols('x y z')
sympy.init_printing(use_unicode=True)

print(sympy.solvers.inequalities.reduce_rational_inequalities([[x + 2 > 0]],
x))


print(sympy.solvers.inequalities.reduce_rational_inequalities([[x + 2 > 0],[x
< 5]], x))
rd@h370:~/tmp.nobackup$ python3 test-sympy.py
(-2 < x) & (x < oo)
(-oo < x) & (x < oo)
rd@h370:~/tmp.nobackup$


Any hint is welcome.

Thanks
Rainer


--
Rainer Dorsch
http://bokomoko.de/


Jeremy Monat

unread,
Aug 6, 2022, 11:20:04 AM8/6/22
to sy...@googlegroups.com
Hi Ranier,

Here's a way to do it:

>>> import sympy
>>> x, y, z = sympy.symbols('x y z')
>>> sympy.solvers.inequalities.reduce_inequalities([x + 2 > 0, x < 5], x)
(-2 < x) & (x < 5)

reduce_inequalities is the top-level inequality reducer, which will call other lower-level functions (such as reduce_rational_inequalities) as needed. reduce_inequalities takes a simple list, rather than a nested list, of inequalities.

I'm actually drafting a guide page on this topic now; glad to know it's of interest! You can access the draft, and I'd appreciate any feedback (either here or on the pull request on GitHub).

Best,
Jeremy

P.S. If you like, you can use less-verbose function calls by importing reduce_inequalities and symbols from SymPy:

>>> from sympy import reduce_inequalities, symbols
>>> x, y, z = symbols('x y z')
>>> reduce_inequalities([x + 2 > 0, x < 5], x)
(-2 < x) & (x < 5)
--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/4120287.OZXsGyJSKq%40h370.

Rainer Dorsch

unread,
Aug 9, 2022, 11:46:55 AM8/9/22
to sy...@googlegroups.com
Hi Jeremy,

thanks for sharing your link and thanks for compiling the documentation. And
indeed it helped, with the information I could easily fix it:

rd@h370:~/tmp.nobackup$ cat test-sympy.py
import sympy

x, y, z = sympy.symbols('x y z')
sympy.init_printing(use_unicode=True)

print(sympy.solvers.inequalities.reduce_rational_inequalities([[x + 2 > 0]],
x))


print(sympy.solvers.inequalities.reduce_rational_inequalities([[x + 2 > 0,x <
5]], x))
rd@h370:~/tmp.nobackup$ python3 test-sympy.py
(-2 < x) & (x < oo)
(-2 < x) & (x < 5)
rd@h370:~/tmp.nobackup$

I read through your page and posted some feedback at

https://github.com/sympy/sympy/pull/23768

My real problem is somewhat more complex though:

I want to find out if

f_vec+a*x_vec+b*y_vec+n*s_vec=sh_vec+c*xsh_vec+d*ysh_vec

has a solution with

0<=a,b,c,d<=1

All quantities with _vec are 3 dimensional vectors. I want to to find out if
for a given set of vectors a solution exists or not.

Extending my testcase in this direction does not work though:

rd@h370:~/tmp.nobackup$ cat test-sympy.py
import sympy

x, y, z = sympy.symbols('x y z')
sympy.init_printing(use_unicode=True)

print(sympy.solvers.inequalities.reduce_rational_inequalities([[x + 2 > 0]],
x))

print(sympy.solvers.inequalities.reduce_rational_inequalities([[x*5 + y*2 =
10,x <= 1, x >= 0, y <= 1, y >= 0]], x))
rd@h370:~/tmp.nobackup$ python3 test-sympy.py
File "/home/rd/tmp.nobackup/test-sympy.py", line 9
print(sympy.solvers.inequalities.reduce_rational_inequalities([[x*5 + y*2
= 10,x <= 1, x >= 0, y <= 1, y >= 0]], x))
^
SyntaxError: invalid syntax
rd@h370:~/tmp.nobackup$

I suspect that reduce_rational_inequalities is the wrong approach here, but
what would the the right functions to use?

Any hint is welcome :-)

Many thanks
Rainer

PS: Also thanks for hint towards less-verbose function calls. I typically
write it verbose, since I am not writing Python code too frequently, and for
me the verbose version is something like a documentation, since I see where
the functions come from.

Am Samstag, 6. August 2022, 17:19:45 CEST schrieb Jeremy Monat:
> Hi Ranier,
>
> Here's a way to do it:
> >>> import sympy
> >>> x, y, z = sympy.symbols('x y z')
> >>> sympy.solvers.inequalities.reduce_inequalities([x + 2 > 0, x < 5], x)
>
> (-2 < x) & (x < 5)
>
> reduce_inequalities is the top-level inequality reducer, which will call
> other lower-level functions (such as reduce_rational_inequalities) as
> needed. reduce_inequalities takes a simple list, rather than a nested list,
> of inequalities.
>
> I'm actually drafting a guide page on this topic now; glad to know it's of
> interest! You can access the draft
> <https://output.circle-artifacts.com/output/job/a1f8297d-6be8-4627-9f47-a969
> 709f9293/artifacts/0/doc/_build/html/guides/solving/solve-system-of-inequali
> ties-algebraically.html>, and I'd appreciate any feedback (either here or on
> the pull request <https://github.com/sympy/sympy/pull/23768> on GitHub).

Chris Smith

unread,
Aug 10, 2022, 5:03:29 PM8/10/22
to sympy
You can't enter your expressions with `=` to create and Equality. You would have to reenter as Eq(5*x+2*y,10) or `parse_expr('5*x+2*y=10',transformations=T[1,9]')` (see [here](https://stackoverflow.com/a/73307040/1089161)).

Past that, there is no SymPy function that will solve this, but in PR https://github.com/sympy/sympy/pull/22389 I added code today that will do so.

Your equality will be treated like a function to maximize under the constrains that x<=1 and y<=1 (and both are nonnegative):

>>> func = 5*x+2*y-10
>>> cond = [x<=1, y<=1]
>>> LP(func, cond, [x,y])[:2]
(-3, {x: 1, y: 1})

So that function has a maximum value of -3 when x and y are 1. Now negate the function and repeat

>>> LP(-func, cond, [x,y])[:2]
(10, {x: 0, y: 0})

The max of the negated function is 10 when x and y are 0. So the min of the function is -10. You are interested in the case when the function is 0. Since the function is linear and has as bounds [-10, -3] which does not contain 0, it seems to me that this proves there is no solution.

/c

Rainer Dorsch

unread,
Aug 15, 2022, 4:30:43 AM8/15/22
to sy...@googlegroups.com
Hi Chris,

many thanks for the link to the stack overflow answer and in particular the PR
and also the elegant suggestion on how to address the problem with linear
programming.

I realized that I oversimplified the example though:

The problem I want to solve is a vector equation:

f_vec+a*x_vec+b*y_vec+n*s_vec=sh_vec+c*xsh_vec+d*ysh_vec

and I am looking for a solution with

0<=a,b,c,d<=1

I.e. there is more than one equation which need to be satisfied for the same x
and y:

print(sympy.solvers.inequalities.reduce_rational_inequalities([[x*5 + y*2
+z*3=5,x*2-y-z>5,x <= 1, x >= 0, y <= 1, y >= 0,z <= 1, z >= 0]], [x,y,z]))

I see no obvious way to apply your method to a set of multiple equations, but
it might due to my lack of experience with linear programming.

Thanks again
Rainer

Chris Smith

unread,
Aug 15, 2022, 10:48:14 PM8/15/22
to sympy
Ignore your equality `5*x + 2*y+3*z=5` and see if a solution exists for the condition you specify:

>>> LP(
... x*2-y-z-5,[x <= 1, y <= 1,z <= 1,x>0,y>0,z>0],[x,y,z])
(-3, {x: 1, y: 0, z: 0}, _y0 + _y1 + _y2 - 5, [_y0 - _y3 - 2 >= 0, _y1 - _y4 + 1 >= 0, _y2 - _y5 + 1 >= 0], {_y0: 2, _y1: 0, _y2: 0, _y3: 0, _y4: 0, _y5: 0})

The maximum that 2*x - y - z - 5 can be is -3 but you want it to be greater than 0. So there is no solution, is there?

/c

Jeremy Monat

unread,
Aug 16, 2022, 12:03:31 AM8/16/22
to sy...@googlegroups.com
SymPy cannot (currently) reduce for multiple variables. As the draft guide page mentions, to reduce for more than one symbol, try SciPy’s linprog(). (If there is no solution, obviously no function will find one.)

Jeremy

Rainer Dorsch

unread,
Aug 16, 2022, 6:34:08 AM8/16/22
to sy...@googlegroups.com
Hi Chris,

thanks for your quick reply.

If I understand you correctly, this works only for this specific case (and on
top of that I had a typo, I have multiple, here 2, equations). But this was
just an example, it also should work for a more general case, like

print(sympy.solvers.inequalities.reduce_rational_inequalities([[x*5 +
y*2+z*3=5,x*10-y-z=5,x <= 1, x >= 0, y <= 1, y >= 0,z <= 1, z >= 0]],
[x,y,z]))

Thanks again,
Rainer

Rainer Dorsch

unread,
Aug 16, 2022, 6:39:17 AM8/16/22
to sy...@googlegroups.com
Hi Jeremy,

many thanks for the scipy link. I will experiment with it.

Rainer

Am Dienstag, 16. August 2022, 06:03:16 CEST schrieb Jeremy Monat:
> SymPy cannot (currently) reduce for multiple variables. As the draft guide
> page
> <https://output.circle-artifacts.com/output/job/99b313eb-c111-406f-81e3-22dc
> f5d7c9fa/artifacts/0/doc/_build/html/guides/solving/solve-system-of-inequali
> ties-algebraically.html> mentions, to reduce for more than one symbol, try
> SciPy’s linprog()
> <https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.linpro
> g.html#scipy.optimize.linprog>. (If there is no solution, obviously no
> > https://groups.google.com/d/msgid/sympy/6f40ebd5-46f0-4bd9-b5d4-1e703ff1db
> > f2n%40googlegroups.com
> > <https://groups.google.com/d/msgid/sympy/6f40ebd5-46f0-4bd9-b5d4-1e703ff1
> > dbf2n%40googlegroups.com?utm_medium=email&utm_source=footer> .
Reply all
Reply to author
Forward
0 new messages