How to solve multivariate inequalities with python and sympy?
Asked Answered
S

2

11

I'm quite new using python and Sympy... And got a problem to solve multivariate inequalities using sympy.

Let's say I have a lot of functions in a file which look like this :

    cst**(sqrt(x)/2)/cst
    exp(sqrt(cst*x**(1/4)))
    log(log(sqrt(cst + exp(x))))
    (y**(1/4) + y)**cst
    sqrt(y/log(x))/cst
    sqrt(cst**log(cst) + x)
    (y**2)**(x/4)
    sqrt(y*sqrt(cst**y))
    log(sqrt(2)*sqrt(cst)*x)

I need to derivate them, set the value of the constant and check if, for each functions f,

    df/dx > 0
    df/dy < 0 

With x in [0, +oo) and y in [0, 1].

To derivate i use :

    dx = diff(f, x)
    dy = diff(f, y)

Then when i try :

    cst = 2 #(for example) 
    solve(dx > 0) 

I got this error :

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/usr/local/lib/python2.7/dist-packages/sympy/solvers/solvers.py", line 634, in solve
symbols=symbols)
    File "/usr/local/lib/python2.7/dist-packages/sympy/solvers/inequalities.py", line 374, in reduce_inequalities
    raise NotImplementedError("only univariate inequalities are supported")
    NotImplementedError: only univariate inequalities are supported

But if i try that :

    x=Symbol('x', real=True, postive=True, nonzero=True)
    y=Symbol('y', real=True, postive=True, nonzero=True)
    solve(x**2+y > 0)

I got :

    True

Which is good and workable answer. Is there anyway to solve multivariate inequalities and always get an workable answer?

For example I would like to get : solve(x**2-y>0) Or(x>-sqrt(y), x>sqrt(y))

Striated answered 11/6, 2013 at 15:36 Comment(2)
Welcome! Do not forget that the etiquette here is to explain what you have tried and why it did not work when asking a questions.Polypropylene
Aïe, i'll not forget next time! I did try the same code as you... And get the same answer : "NotImplementedError".Striated
P
9

When trying to solve this with SymPy you get a pretty clear error message: NotImplementedError: only univariate inequalities are supported. Be aware that this means that the SymPy team will be very happy if you contribute an algorithm that solves this problem.

Now that it is clear that sympy.solve is not powerful enough you can try another approach. Recently (in 0.7.2) an implicit plotting routine was added to sympy that can plot where an expression evaluates to True. Regretfully it is only a numeric solution, not a symbolic one that you can get from solve but it might be enough:

enter image description here

From the image you can see that there is only a single line where the expression changes sign, so solving for expr==0 might give you what you want. And this is indeed the case:

enter image description here

Polypropylene answered 11/6, 2013 at 15:59 Comment(3)
Thand for answering, but it'll not be good for what I need. I have to generate all possible functions f(x,y), for example with 10 characters, and then evaluate all derivatives to check if : df/dx > 0 and df/dy < 0. There are to much possibilities to be able to check everything by myself... Got any idea about that?Striated
I really do not understand how what you ask in the comment is in any way related to what you have asked in the question above? Feel free to ask a new question, or if you insist to modify the original one so it clear what you want. Upvote if you find an answer useful.Polypropylene
Excellent and thorough answer. The explanation helped with my game theory core allocation calculation.Brescia
T
4

There is a multivariate inequality solver in mystic, which is built on top of sympy. It uses optimization and the (mathematical) mapping of sets to provide this feature. It's not perfect, but works for many cases.

>>> equations = '''
... 2*A + 3*B >= C
... A*B > D
... C < 4*A    
... D == 0
... '''
>>> 
>>> import mystic.symbolic as ms
>>> var = list('ABCD')
>>> eqns = ms.simplify(equations, variables=var)
>>> print eqns
D == 0
B > 0
A > C/4
A >= -3*B/2 + C/2
A > D/B
>>> 
>>> # generate a constraints function, which maps one space to another
>>> constrain = ms.generate_constraint(ms.generate_solvers(eqns, var))
>>> solution = constrain([1,2,3,4])
>>> print solution
[1, 2, 3, 0] 
>>> # here's the solution...
>>> dict(zip(var,solution))
{'A': 1, 'C': 3, 'B': 2, 'D': 0}
>>>
>>> A=1; C=3; B=2; D=0
>>> 2*A + 3*B >= C
True
>>> A*B > D
True
>>> C < 4*A
True
>>> D == 0
True
>>> 

Let's do it again, with the suggested test:

>>> equations = """x**2 - y >= 0
... x + y = 0
... """
>>> eqns = ms.simplify(equations, variables=var)
>>> constrain = ms.generate_constraint(ms.generate_solvers(eqns, var))
>>> solution = constrain([1,3])
>>> solution
[-3, 3]
>>> dict(zip(var, solution))
{'y': 3, 'x': -3}
>>> y=3; x=-3
>>> x**2 - y >= 0
True
>>> x+y == 0
True
>>>

mystic uses a combination of sympy and numerical optimization to simplify inequalities; and when presented with an initial guess solution, can (most of the time, but not always) generate a valid solution to the equations. mystic won't actually solve the inequalities per se, but it will (usually) generate a valid solution to the inequalities.

Thriftless answered 30/9, 2015 at 16:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.