首页 > 解决方案 > sympy 中不需要的布尔表达式求值

问题描述

我试图在 sympy 中制定一个分段函数然后绘制它,但我无法制定想要的函数。问题在于,在将其传递给 Piecewise 构造函数之前,它的(x > 0) & (x < 1)计算x > 0结果总是为。True这可以通过不在positive=True符号构造函数中设置来规避,但这会使平方根简化为√(x^2),在这种情况下,我希望它简化为x。我目前正在 Windows 上最新版本的 Anaconda Distribution 中使用基本(根)环境。代码在上述环境中使用 JupyterLab 笔记本进行测试。

当前代码:

from sympy import *
x = symbols('x', real=True, positive=True)
f = sqrt(x**2)

f_piecewise = Piecewise((2, (x > 0) & (x < 1) ),
          ( 3 * f, (x > 1) & (x < 2) ),
          ( -3 * f, (x > 2) & (x < 3)),
          (0, True)
         )

pprint(f_piecewise)
display(f_piecewise)
plot(f_piecewise, (x, -0.01, 3.01))

当前代码的结果:

⎧ 2        for x < 1    
⎪                       
⎪3⋅x   for x > 1 ∧ x < 2
⎨                       
⎪-3⋅x  for x > 2 ∧ x < 3
⎪                       
⎩ 0        otherwise    

Latex 和 matplotlib 输出缺少布尔值

预期输出:

⎧ 2    for x > 0 ∧ x < 1
⎪                       
⎪3⋅x   for x > 1 ∧ x < 2
⎨                       
⎪-3⋅x  for x > 2 ∧ x < 3
⎪                       
⎩ 0        otherwise

Latex 和 matplotlib 预期输出

我已经找到了一个解决方案,当只使用一个布尔评估时,例如使用更大的然后。错误代码:

test = Piecewise((f, (x > 0)),
                 (1, True) 
                )
pprint(test)
display(test)
plot(test)

工作代码:

test = Piecewise((f, Gt(x, 0, evaluate=False)),
                 (1, True) 
                )
pprint(test)
display(test)
plot(test)

我尝试了以下方法以使其与“and”一起使用,但它们都不起作用:

from sympy.parsing.sympy_parser import parse_expr
test = Piecewise((f, parse_expr("GreaterThan(x, 0, evaluate=False) & (x < 1)", {'x':x}, evaluate=False)),
                 (1, True) 
                )

test = Piecewise((f, And(GreaterThan(x, 0, evaluate=False), (x < 1), evaluate=False)),
                 (1, True) 
                )

感谢任何花时间看这个的人:D。

标签: pythonanacondabooleansympypiecewise

解决方案


Sympy 形成了正确的方程组。关键是您将符号变量设置为正数。在这种情况下,系统:

⎧ 2        for x < 1    
⎪                       
⎪3⋅x   for x > 1 ∧ x < 2
⎨                       
⎪-3⋅x  for x > 2 ∧ x < 3
⎪                       
⎩ 0        otherwise   

将是正确的。

要获得您期望的系统,您需要移除积极性约束。以下代码有效。

from sympy import *
x = symbols('x', real=True)
f = sqrt(x**2)

f_piecewise = Piecewise((2, (x > 0) & (x < 1) ),
          ( 3 * f, (x > 1) & (x < 2) ),
          ( -3 * f, (x > 2) & (x < 3)),
          (0, True)
         )

pprint(f_piecewise)

这是它返回的内容:

⎧  2     for x > 0 ∧ x < 1
⎪                         
⎪3⋅│x│   for x > 1 ∧ x < 2
⎨                         
⎪-3⋅│x│  for x > 2 ∧ x < 3
⎪                         
⎩  0         otherwise

PS 请注意,您的函数在第 1 点和第 2 点被定义为零。使用 '>=' 或 '<=' 以获得正确的行为。不幸的是,这些点在图表上并未反映为 0。


推荐阅读