寻求可自动优化表达式重复计算的工具(优先Python)
问题描述
假设有如下简单表达式:
c = ((a * b) / (x * y)) * sqrt(a * b + 1 + x * y)
计算机只需计算a * b和x * y各一次,但直接计算该表达式会让它们被重复计算两次。更优的写法是:
d = a * b e = x * y f = d / e g = d + 1 + e c = f * sqrt(g)
请问是否存在可将第一种代码块转化为第二种的函数(优先Python,其他语言也可)?我有一个从Mathematica Solve输出的超长表达式(长达数页),其中包含大量重复出现的唯一子项(远多于上述示例中的2个),手动优化不现实。此外,a * b这类子项后续可能用于计算其他量,我的应用对速度要求较高,此类优化十分必要。我曾尝试搜索相关功能,但可能未使用正确关键词。
可行解决方案
使用SymPy的公共子表达式提取功能
SymPy是Python的符号计算库,内置了提取公共子表达式(Common Subexpression Elimination, CSE)的工具,完全匹配你的需求。示例用法如下:from sympy import symbols, sqrt, cse, codegen # 定义符号变量 a, b, x, y = symbols('a b x y') # 原表达式 expr = ((a * b) / (x * y)) * sqrt(a * b + 1 + x * y) # 提取公共子表达式 subexprs, simplified_expr = cse(expr) # 打印提取后的分步代码 for var, subexpr in subexprs: print(f"{var} = {subexpr}") print(f"c = {simplified_expr[0]}")运行后会输出类似示例的分步赋值代码,还能通过
codegen模块直接生成可执行的Python代码,适配超长表达式毫无压力。利用Mathematica自身的CSE功能
既然表达式来自Mathematica,可直接用其内置的CSE函数处理,再导出为Python代码。比如在Mathematica中执行:expr = ((a*b)/(x*y))*Sqrt[a*b + 1 + x*y]; CSE[expr]得到优化后的分步表达式后,再转换为Python代码即可,省去跨工具转换的额外麻烦。
自定义提取逻辑(针对特定场景)
如果你的表达式结构规则,也可以自行编写遍历逻辑,统计子表达式出现次数,将重复多次的子项替换为临时变量。但这种方法通用性不如前两种,适合处理特定格式的表达式。
内容的提问来源于stack exchange,提问作者Philliph
相关产品推荐
相关产品推荐

