如何使用 Sympy 解决不等式?
目标:我想使用 Sympy 实现傅里叶-莫茨金消除。第一步是解决一些不平等问题。
问题:使用 Sympy 解决不等式的工具(例如solvet、solve_poly_inequality 或reduce_inequalities)似乎不起作用。
数据:
from sympy import *
u1, u2, x1, x2 = symbols('u1 u2 x1 x2')
y1, y2, y3, y4, y5 = symbols('y1 y2 y3 y4 y5')
list_of_inequalities = [50*u2 - y5, -x2 + y5, 0, -u2 + 1, -35*u2 + y4 + y5, 35*u2 + x1 + x2 - y4 - y5 - 35, 35*u2 - y4 - y5, -35*u2 - x1 - x2 + y4 + y5 + 35, 50*y1 - y4, 50*u1 - x1 - 50*y1 + y4, -50*y1 + y4, -50*u1 + x1 + 50*y1 - y4, u2 - y1, -u1 - u2 + y1 + 1, 50*u2 - y5, -50*u2 - x2 + y5 + 50, 65*y1, 65*u1 - 65*y1, 35*u2 + 65*y1 - y4 - y5]
这些都是>=0
的表达式。 我想用傅里叶-莫茨金消除法消除所有 y 变量。因此,第一步我想从 y1 开始。
所需的解决方案:
例如,对于list_of_inequalites[8]
,即50*y1 - y4
,我应该得到y1>=y4/50
或类似的。 最后我想要两个列表。一种表达式小于 y1
,其中包含 y4/50
,另一种表达式大于 y1
。 我将需要这些列表来进行傅里叶-莫茨金消除法的下一步。
我的尝试:
y_1=[]
for eq in list_of_equations:
expr= eq>=0
if y1 in eq.free_symbols:
y_1.append(solveset(expr.lhs>=0,y1,domain=S.Reals))
这样我得到一个这样的列表:
[ConditionSet(y1, 50*y1 - y4 >= 0, Reals), ConditionSet(y1, 50*u1 - x1 - 50*y1 + y4 >= 0, Reals), ConditionSet(y1, -50*y1 + y4 >= 0, Reals), ConditionSet(y1, -50*u1 + x1 + 50*y1 - y4 >= 0, Reals), ConditionSet(y1, u2 - y1 >= 0, Reals), ConditionSet(y1, -u1 - u2 + y1 + 1 >= 0, Reals), Interval(0, oo), ConditionSet(y1, 65*u1 - 65*y1 >= 0, Reals), ConditionSet(y1, 35*u2 + 65*y1 - y4 - y5 >= 0, Reals)]
我不明白如何处理这些条件集。它们当然不能解决我的问题。
另一种方法是使用solve_poly_inequality:
for eq in list_of_equations:
expr= eq>=0
if y1 in eq.free_symbols:
y_1.append(solve_poly_inequality(Poly(expr.lhs,y1),'>='))
这样我得到了
NotImplementedError Traceback (most recent call last)
<ipython-input-269-686426e9455b> in <module>
9 expr= eq>=0
10 if y1 in eq.free_symbols:
---> 11 y_1.append(solve_poly_inequality(Poly(expr.lhs,y1),'>='))
~\Anaconda3\lib\site-packages\sympy\solvers\inequalities.py in solve_poly_inequality(poly, rel)
56 "could not determine truth value of %s" % t)
57
---> 58 reals, intervals = poly.real_roots(multiple=False), []
59
60 if rel == '==':
~\Anaconda3\lib\site-packages\sympy\polys\polytools.py in real_roots(f, multiple, radicals)
3498
3499 """
-> 3500 reals = sympy.polys.rootoftools.CRootOf.real_roots(f, radicals=radicals)
3501
3502 if multiple:
~\Anaconda3\lib\site-packages\sympy\polys\rootoftools.py in real_roots(cls, poly, radicals)
385 def real_roots(cls, poly, radicals=True):
386 """Get real roots of a polynomial. """
--> 387 return cls._get_roots("_real_roots", poly, radicals)
388
389 @classmethod
~\Anaconda3\lib\site-packages\sympy\polys\rootoftools.py in _get_roots(cls, method, poly, radicals)
717 raise PolynomialError("only univariate polynomials are allowed")
718
--> 719 coeff, poly = cls._preprocess_roots(poly)
720 roots = []
721
~\Anaconda3\lib\site-packages\sympy\polys\rootoftools.py in _preprocess_roots(cls, poly)
696 if not dom.is_ZZ:
697 raise NotImplementedError(
--> 698 "sorted roots not supported over %s" % dom)
699
700 return coeff, poly
NotImplementedError: sorted roots not supported over ZZ[x1,y4,u1]
导致此错误的不等式为50*u1 - x1 - 50*y1 + y4 >= 0
。
我找到的解决不等式的最后一种方法是reduce_inequalities:
for eq in list_of_equations:
expr= eq>=0
if y1 in eq.free_symbols:
y_1.append(reduce_inequalities(expr>=0,[y1]))
但是,这次我收到以下错误:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-266-50cdf532f9fa> in <module>
22 expr= eq>=0
23 if y1 in eq.free_symbols:
---> 24 y_1.append(reduce_inequalities(expr>=0,[y1]))
25 # print(y_1[-1])
26
~\Anaconda3\lib\site-packages\sympy\solvers\inequalities.py in reduce_inequalities(inequalities, symbols)
985
986 # solve system
--> 987 rv = _reduce_inequalities(inequalities, symbols)
988
989 # restore original symbols and return
~\Anaconda3\lib\site-packages\sympy\solvers\inequalities.py in _reduce_inequalities(inequalities, symbols)
900 if len(common) == 1:
901 gen = common.pop()
--> 902 other.append(_solve_inequality(Relational(expr, 0, rel), gen))
903 continue
904 else:
~\Anaconda3\lib\site-packages\sympy\core\relational.py in __new__(cls, lhs, rhs, rop, **assumptions)
87 Eq and Ne; all other relationals expect
88 real expressions.
---> 89 '''))
90 # \\\
91 return rv
TypeError:
A Boolean argument can only be used in Eq and Ne; all other
relationals expect real expressions.
您有任何想法如何解决这个问题吗?
Objective: I want to implement a Fourier-Motzkin Elimination using Sympy. The first step for this would be to solve a number of inequalities.
Problem: The tools for solving inequalities with Sympy like solveset, solve_poly_inequality or reduce_inequalities do no seem to work.
Data:
from sympy import *
u1, u2, x1, x2 = symbols('u1 u2 x1 x2')
y1, y2, y3, y4, y5 = symbols('y1 y2 y3 y4 y5')
list_of_inequalities = [50*u2 - y5, -x2 + y5, 0, -u2 + 1, -35*u2 + y4 + y5, 35*u2 + x1 + x2 - y4 - y5 - 35, 35*u2 - y4 - y5, -35*u2 - x1 - x2 + y4 + y5 + 35, 50*y1 - y4, 50*u1 - x1 - 50*y1 + y4, -50*y1 + y4, -50*u1 + x1 + 50*y1 - y4, u2 - y1, -u1 - u2 + y1 + 1, 50*u2 - y5, -50*u2 - x2 + y5 + 50, 65*y1, 65*u1 - 65*y1, 35*u2 + 65*y1 - y4 - y5]
These are all expressions that are >=0
.
I want to get rid of all the y-variables with Fourier-Motzkin Elimination. So, in a first step I would like to start with y1
.
Desired Solution:
For example for list_of_inequalites[8]
which is 50*y1 - y4
I should get y1>=y4/50
or similar.
In the end I want to have two lists. One with expressions that are smaller than y1
which would contain y4/50
and one with expressions larger than y1
.
I will need these lists for the next step in the Fourier-Motzkin Elimination.
My Try:
y_1=[]
for eq in list_of_equations:
expr= eq>=0
if y1 in eq.free_symbols:
y_1.append(solveset(expr.lhs>=0,y1,domain=S.Reals))
This way I get a list like this:
[ConditionSet(y1, 50*y1 - y4 >= 0, Reals), ConditionSet(y1, 50*u1 - x1 - 50*y1 + y4 >= 0, Reals), ConditionSet(y1, -50*y1 + y4 >= 0, Reals), ConditionSet(y1, -50*u1 + x1 + 50*y1 - y4 >= 0, Reals), ConditionSet(y1, u2 - y1 >= 0, Reals), ConditionSet(y1, -u1 - u2 + y1 + 1 >= 0, Reals), Interval(0, oo), ConditionSet(y1, 65*u1 - 65*y1 >= 0, Reals), ConditionSet(y1, 35*u2 + 65*y1 - y4 - y5 >= 0, Reals)]
I do not understand how to deal with these ConditionSets. They are certainly not the solution of my problem.
Another way would be to work with solve_poly_inequality:
for eq in list_of_equations:
expr= eq>=0
if y1 in eq.free_symbols:
y_1.append(solve_poly_inequality(Poly(expr.lhs,y1),'>='))
This way I get a
NotImplementedError Traceback (most recent call last)
<ipython-input-269-686426e9455b> in <module>
9 expr= eq>=0
10 if y1 in eq.free_symbols:
---> 11 y_1.append(solve_poly_inequality(Poly(expr.lhs,y1),'>='))
~\Anaconda3\lib\site-packages\sympy\solvers\inequalities.py in solve_poly_inequality(poly, rel)
56 "could not determine truth value of %s" % t)
57
---> 58 reals, intervals = poly.real_roots(multiple=False), []
59
60 if rel == '==':
~\Anaconda3\lib\site-packages\sympy\polys\polytools.py in real_roots(f, multiple, radicals)
3498
3499 """
-> 3500 reals = sympy.polys.rootoftools.CRootOf.real_roots(f, radicals=radicals)
3501
3502 if multiple:
~\Anaconda3\lib\site-packages\sympy\polys\rootoftools.py in real_roots(cls, poly, radicals)
385 def real_roots(cls, poly, radicals=True):
386 """Get real roots of a polynomial. """
--> 387 return cls._get_roots("_real_roots", poly, radicals)
388
389 @classmethod
~\Anaconda3\lib\site-packages\sympy\polys\rootoftools.py in _get_roots(cls, method, poly, radicals)
717 raise PolynomialError("only univariate polynomials are allowed")
718
--> 719 coeff, poly = cls._preprocess_roots(poly)
720 roots = []
721
~\Anaconda3\lib\site-packages\sympy\polys\rootoftools.py in _preprocess_roots(cls, poly)
696 if not dom.is_ZZ:
697 raise NotImplementedError(
--> 698 "sorted roots not supported over %s" % dom)
699
700 return coeff, poly
NotImplementedError: sorted roots not supported over ZZ[x1,y4,u1]
The inequality that causes this error is 50*u1 - x1 - 50*y1 + y4 >= 0
.
The last way I found for solving inequalities is reduce_inequalities:
for eq in list_of_equations:
expr= eq>=0
if y1 in eq.free_symbols:
y_1.append(reduce_inequalities(expr>=0,[y1]))
But, this time I get the following error:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-266-50cdf532f9fa> in <module>
22 expr= eq>=0
23 if y1 in eq.free_symbols:
---> 24 y_1.append(reduce_inequalities(expr>=0,[y1]))
25 # print(y_1[-1])
26
~\Anaconda3\lib\site-packages\sympy\solvers\inequalities.py in reduce_inequalities(inequalities, symbols)
985
986 # solve system
--> 987 rv = _reduce_inequalities(inequalities, symbols)
988
989 # restore original symbols and return
~\Anaconda3\lib\site-packages\sympy\solvers\inequalities.py in _reduce_inequalities(inequalities, symbols)
900 if len(common) == 1:
901 gen = common.pop()
--> 902 other.append(_solve_inequality(Relational(expr, 0, rel), gen))
903 continue
904 else:
~\Anaconda3\lib\site-packages\sympy\core\relational.py in __new__(cls, lhs, rhs, rop, **assumptions)
87 Eq and Ne; all other relationals expect
88 real expressions.
---> 89 '''))
90 # \\\
91 return rv
TypeError:
A Boolean argument can only be used in Eq and Ne; all other
relationals expect real expressions.
Do you have any ideas how I can solve this problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不确切知道你的具体问题的性质。但也许我们可以解决这个问题。
第一个解决方案
solve
也能够解决不等式,尽管提取正确的解决方案可能并不容易:第二个解决方案
由于您的不等式似乎是线性的,也许我们可以将它们解为方程,从而节省我们的时间一些后处理。例如:
第三种解决方案
我相信
solveset
返回ConditionSet
因为它不知道符号的性质。如果您的符号代表真实变量,您可以对其进行假设:I don't know exactly the nature of your particular problem. But maybe we can work around it.
First solution
solve
is also capable of solving inequalities, though it might not be easy to extract the proper solution:Second solution
Since your inequalities appear to be linear, maybe we can solve them as equations, thus sparing us some post-processing. For example:
Third solution
I believe that
solveset
returnedConditionSet
because it doesn't know the nature of your symbols. If your symbols represent real variables, you can set assumptions on them: