如何通过 SymPy 中的给定子表达式自动简化表达式
How to automate simplifying an expression by given sub-expressions in SymPy
我想用更短的表达式缩短一个长方程。
这是一个简单的例子:
from sympy.abc import z, h, m, G
y = 0.2 * m + 0.2 * z * m +z - h
y_1 = y.subs({m + z * m: G})
print(y_1)
预期结果是 z - h + 0.2 * G
但它不会替换表达式。我知道问题是 0.2
。有什么方法可以自动修复这个问题吗?
或者另一个解决方案可以是:
公共子表达式消除 (cse(y)),效率不高,因为它使用默认条件创建子表达式。
我认为 subs
方法并不像您认为的那样有效。它只是用传递的输入值替换术语。例如,
expr = cos(x)
expr.subs(x, 0)#here 0 is replaced with x
print(expr) # 1, sinces cos(0) is 1
#Or
expr = x**3 + 4*x*y - z
expr.subs([(x, 2), (y, 4), (z, 0)])
print(expr) #40
如您所见,在您的 subs 方法中,您没有明确说明应该替换什么。按照上面的示例作为指导,它应该可以工作。您可以阅读更多 here
不幸的是,据我所知,subs
还没有那么强大(还没有?)。您可以尝试将替换 m + z * m: G
自动拆分为两个单独的替换 z: G / m - 1
和 m: G / (z + 1)
并在两者之间进行简化。
from sympy.abc import z, h, m, G
y = 0.2 * m + z - h + 0.2 * z * m
y_1 = y.subs({m + z * m: G})
print(y_1)
y_2 = y.subs({z: G / m - 1, m: G / (z + 1)}).simplify()
print(y_2)
y_3 = y_2.subs({G / m - 1: z, G / (z + 1): m}).simplify()
print(y_3)
输出如下:
-h + 0.2*m*z + 0.2*m + z
0.2*G + G/m - h - 1
0.2*G - h + z
更新: 当我说您可以尝试自动化该过程时,我的意思是类似于以下代码示例。我不知道这对你的情况适用多少。
from sympy import *
from sympy.abc import z, h, m, G
def elaborate_subs(expr, old, new):
subs = {}
for symbol in old.free_symbols:
solution = solve(Eq(old, new), symbol, simplify=False)
if solution:
subs[symbol] = solution[0]
expr = expr.subs(subs).simplify()
expr = expr.subs({v: k for k, v in subs.items()}).simplify()
return expr
y = 0.2 * m + z - h + 0.2 * z * m
print(elaborate_subs(y, m + z * m, G))
其中有预期的输出:
0.2*G - h + z
我想用更短的表达式缩短一个长方程。 这是一个简单的例子:
from sympy.abc import z, h, m, G
y = 0.2 * m + 0.2 * z * m +z - h
y_1 = y.subs({m + z * m: G})
print(y_1)
预期结果是 z - h + 0.2 * G
但它不会替换表达式。我知道问题是 0.2
。有什么方法可以自动修复这个问题吗?
或者另一个解决方案可以是: 公共子表达式消除 (cse(y)),效率不高,因为它使用默认条件创建子表达式。
我认为 subs
方法并不像您认为的那样有效。它只是用传递的输入值替换术语。例如,
expr = cos(x)
expr.subs(x, 0)#here 0 is replaced with x
print(expr) # 1, sinces cos(0) is 1
#Or
expr = x**3 + 4*x*y - z
expr.subs([(x, 2), (y, 4), (z, 0)])
print(expr) #40
如您所见,在您的 subs 方法中,您没有明确说明应该替换什么。按照上面的示例作为指导,它应该可以工作。您可以阅读更多 here
不幸的是,据我所知,subs
还没有那么强大(还没有?)。您可以尝试将替换 m + z * m: G
自动拆分为两个单独的替换 z: G / m - 1
和 m: G / (z + 1)
并在两者之间进行简化。
from sympy.abc import z, h, m, G
y = 0.2 * m + z - h + 0.2 * z * m
y_1 = y.subs({m + z * m: G})
print(y_1)
y_2 = y.subs({z: G / m - 1, m: G / (z + 1)}).simplify()
print(y_2)
y_3 = y_2.subs({G / m - 1: z, G / (z + 1): m}).simplify()
print(y_3)
输出如下:
-h + 0.2*m*z + 0.2*m + z
0.2*G + G/m - h - 1
0.2*G - h + z
更新: 当我说您可以尝试自动化该过程时,我的意思是类似于以下代码示例。我不知道这对你的情况适用多少。
from sympy import *
from sympy.abc import z, h, m, G
def elaborate_subs(expr, old, new):
subs = {}
for symbol in old.free_symbols:
solution = solve(Eq(old, new), symbol, simplify=False)
if solution:
subs[symbol] = solution[0]
expr = expr.subs(subs).simplify()
expr = expr.subs({v: k for k, v in subs.items()}).simplify()
return expr
y = 0.2 * m + z - h + 0.2 * z * m
print(elaborate_subs(y, m + z * m, G))
其中有预期的输出:
0.2*G - h + z