python - 告知 sympy 变量之间的不等式
问题描述
我正在尝试以 Sympy 形式解决系统
max(a,b+c) == a^2
例如,我想告诉 Sympy 搜索解决方案 where$max(a,b+c) = a$
和$max(a,b+c) = b+c$
. 这在某种程度上可能吗?我尝试通过解决和解决不平等系统来做到这一点,例如:
import sympy as sp
b = sp.Symbol('b', finite = True)
c = sp.Symbol('c', finite = True)
eq = sp.Max(a,b+c) - a**2
sp.solve([eq, a > b+c], a)
但我得到了错误:
不等式 Eq(-x**2 + Max(x, _b + _c), 0) 无法使用 solve_univariate_inequality 求解。
反正有这样的方程可以解吗?或者我至少可以替代$Max(a,b+c)$
某些情况以简化表达式?
解决方案
选项1
Min
SymPy 很难用和求解方程Max
。它在解决平等方面稍微好一点,Piecewise
但仍然不是很好。以下是我将如何使用以下方法解决这个特定问题rewrite(Piecewise)
:
from sympy import *
a, b, c = symbols('a b c', real=True)
eq = Max(a, b+c) - a**2
solution = solve(eq.rewrite(Piecewise), a)
print(solution)
这给
[Piecewise((0, b <= -c), (nan, True)), Piecewise((1, b + c <= 1), (nan, True)), Piecewise((-sqrt(b + c), b + c > -sqrt(b + c)), (nan, True)), Piecewise((sqrt(b + c), b + c > sqrt(b + c)), (nan, True))]
所以这告诉你 SymPy 找到了 4 个解决方案,所有这些解决方案都取决于什么b
和c
是。插入后它们似乎是有效的解决方案。我不确定这些是否都是解决方案。
如果方程比这更复杂,SymPy 可能会更加困难。
positive=True
如果您添加而不是real=True
在上面的代码中,解决方案可能看起来会更好。在定义符号时,请始终尝试提供尽可能多的信息。
选项 2
解决这些方程的另一种方法是替换Max(a, b+c)
并a
记住这些解决方案是 fora >= b+c
并重复 for b+c >= a
。对于更复杂的方程,这可能会更好。
对于这个特定的示例,可以通过执行以下操作来做到这一点:
from sympy import *
a, b, c = symbols('a b c', real=True)
eq = Max(a, b+c) - a**2
eq1 = eq.subs(Max(a, b+c), a)
solution1 = solveset(eq1, a)
eq2 = eq.subs(Max(a, b+c), b+c)
solution2 = solveset(eq2, a)
solution = Piecewise((solution1, a > b+c), (solution2, a < b+c), (solution1.union(solution2), True))
print(solution)
给出与上面相同的答案,但更具可读性:
Piecewise((FiniteSet(0, 1), a > b + c), (FiniteSet(sqrt(b + c), -sqrt(b + c)), a < b + c), (FiniteSet(0, 1, sqrt(b + c), -sqrt(b + c)), True))
请注意您如何需要知道Max
前面的论点并且只有一个Max
。将超过 1 个最大值的条件组合起来会很困难,尤其是因为两种解决方案在它们相等时都成立。
如果您以交互方式而不是自动方式求解方程,我建议您使用此选项。
选项 3
我还没有测试过这个,但我希望这在更一般的情况下能提供相同的答案,Max
因为每个Max
. 但是,每个Max
参数只能接受 2 个参数。
from sympy import *
a, b, c = symbols('a b c', real=True)
eq = Max(a, b+c) - a**2
eqs = [eq]
conditions = [True]
for f in preorder_traversal(eq):
new_eqs = []
new_conds = []
if f.func == Max:
for equation, condition in zip(eqs, conditions):
new_eqs.append(equation.subs(f, f.args[0]))
new_conds.append(And(condition, f.args[0] >= f.args[1]))
new_eqs.append(equation.subs(f, f.args[1]))
new_conds.append(And(condition, f.args[0] <= f.args[1]))
eqs = new_eqs
conditions = new_conds
solutions = []
for equation in eqs:
solutions.append(solveset(equation, a))
pieces = [(solution, condition) for solution, condition in zip(solutions, conditions)]
solution = Piecewise(*pieces)
print(solution)
除了最后一个相等部分之外,这与上面的相同:
Piecewise((FiniteSet(0, 1), a >= b + c), (FiniteSet(sqrt(b + c), -sqrt(b + c)), a <= b + c))
当两个不等式都成立时,我无法将这两种解决方案结合起来,所以你只需要记住这一点。
推荐阅读
- haskell - 将 RTS-opts 传递给“堆栈测试”
- sql - 如何在 PostgreSQL 的 ON 条件下优化 OR 子句?
- sql-server - sql 查询会阻止 node.js 事件循环吗?
- ruby-on-rails - Ruby on Rails - 使用 if 条件在 link_to 中传递参数?
- angular - 如何在子组件Angular中获取输入参数?
- javascript - 使用 jquery 处理 Angular OnInt 生命周期钩子中的窗口调整大小事件
- android - 为什么我在 setOnClickListener 中得到未解析的引用?
- postgresql - 创建一个数据库,然后使用 dockerfile 创建一个表
- javascript - Cytoscape.js 导出不包括动态/运行时节点样式
- python - 检查元素是否存在