You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用SymPy实现两个函数的公共偏应用分解?

用SymPy提取双表达式公共子结构并重构函数

问题背景

给定两个SymPy表达式$f(a,b,c)$和$g(a,b,d)$,需要找到函数$h(a,b)$、$f'(x,c)$、$g'(x,d)$,满足:
$$f'(h(a,b),c) = f(a,b,c)$$
$$g'(h(a,b),d) = g(a,b,d)$$

举个具体例子:

from sympy import symbols, sin

a,b,c,d = symbols('a b c d')

eq1 = a - b + c
eq2 = sin(2*a - 2*b)*d

# 期望得到:
# h(a,b) = a-b
# f'(x,c) = x + c
# g'(x,d) = sin(2x)*d

SymPy没有直接内置该功能,这个问题本质是提取两个表达式中指定变量组的公共子表达式,再将原表达式重构为以该子式为新变量的函数。

实现思路与代码

核心步骤分为两步:

  1. 提取两个表达式中仅包含目标变量(这里是{a,b})的公共子表达式,选取最复杂的那个作为$h(a,b)$(避免匹配单个变量这类无意义的公共子式)
  2. 用新变量替换原表达式中的$h(a,b)$,得到$f'$和$g'$

以下是实现代码:

from sympy import symbols, sin, replace
from sympy.core.expr import Expr

a,b,c,d,x = symbols('a b c d x')

def common_partial(expr1: Expr, expr2: Expr, shared_vars: set):
    # 递归提取表达式中仅包含指定变量的所有子式
    def extract_subexprs(expr, target_vars):
        subexprs = set()
        # 处理当前表达式的所有子节点
        for arg in expr.args:
            if all(var in target_vars for var in arg.free_symbols):
                subexprs.add(arg)
                subexprs.update(extract_subexprs(arg, target_vars))
        # 处理表达式本身
        if all(var in target_vars for var in expr.free_symbols):
            subexprs.add(expr)
        return subexprs

    # 获取两个表达式的目标变量子式集合
    subexprs1 = extract_subexprs(expr1, shared_vars)
    subexprs2 = extract_subexprs(expr2, shared_vars)
    common_subexprs = subexprs1 & subexprs2

    if not common_subexprs:
        raise ValueError("未找到指定变量组中的公共子表达式")

    # 选取最复杂的公共子式作为h(a,b)(用表达式结构复杂度衡量)
    h = max(common_subexprs, key=lambda e: len(e.args) + len(str(e)))

    # 替换得到f'和g'
    f_prime = expr1.replace(h, x)
    g_prime = expr2.replace(h, x)

    return h, f_prime, g_prime

# 测试示例
eq1 = a - b + c
eq2 = sin(2*a - 2*b)*d
h, f_p, g_p = common_partial(eq1, eq2, {a, b})

print(f"h(a,b) = {h}")
print(f"f'(x,c) = {f_p}")
print(f"g'(x,d) = {g_p}")

注意事项

  • 对于含因式的表达式(如示例中的2a-2b),可以先对表达式执行factor()处理,让公共子式更明显(比如2*(a-b)),这样能匹配到更简洁的$h(a,b)$
  • 如果存在多个公共子式,当前逻辑会选取结构最复杂的那个,符合多数场景的需求
  • 对于嵌套层级较深的表达式,递归提取逻辑可以覆盖大部分常规情况,特殊场景可能需要调整子式匹配规则

内容的提问来源于stack exchange,提问作者Abogical

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 10:11:14