首页 > 解决方案 > 告知 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)$某些情况以简化表达式?

标签: pythonsympy

解决方案


选项1

MinSymPy 很难用和求解方程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 个解决方案,所有这些解决方案都取决于什么bc是。插入后它们似乎是有效的解决方案。我不确定这些是否都是解决方案。

如果方程比这更复杂,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))

当两个不等式都成立时,我无法将这两种解决方案结合起来,所以你只需要记住这一点。


推荐阅读