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))
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:
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:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With