本文介绍如何在 SymPy 中自定义一个具有双线性(对第一变量可加)和对称性(dot(a,b) = dot(b,a))的符号点积函数,并通过递归规则实现表达式的自动 expand 与 simplify,无需依赖模式匹配引擎。

先说一个核心判断:在 SymPy 里,原生并不支持那种基于用户定义规则的符号重写——比如 Mathematica 的 ReplaceRepeated,或者 Maple 的 simplify with side relations。但这不代表咱们自己就没办法。核心思路其实很简单:把 dot 实现成一个“智能构造器”函数,在构建阶段就递归应用线性性与对称性,而不是等表达式生成之后再调用 simplify() 去硬匹配规则

下面给出一份我觉得特别稳的实现,直接可用,还能嵌套调用:

from sympy import Function, symbols, Add, ordered
from sympy.abc import a, b, c, x, y

dot = Function('dot')

def dot_expr(a, b):
    """安全、规范化的点积构造器,自动应用:
    - 对称性:dot(a,b) → dot(min(a,b), max(a,b))(按符号顺序)
    - 对第一变量的线性性:dot(A+B, C) → dot(A,C) + dot(B,C)
    """
    # 步骤1:强制对称性 —— 按 canonical order 排序参数
    A, B = ordered((a, b))
    if A != a:  # 需交换
        return dot_expr(B, A)

    # 步骤2:展开左参数的加法(线性性)
    if isinstance(a, Add):
        terms = a.as_ordered_terms()
        return Add(*[dot_expr(term, b) for term in terms])

    # 步骤3:若右参数为和式,利用对称性转为左参数展开
    if isinstance(b, Add):
        return dot_expr(b, a)  # 交由对称性触发步骤2

    # 基础情形:返回未展开的符号点积
    return dot(A, B)

咱们来试试效果:

# 基础对称性
print(dot_expr(y, x))           # → dot(x, y)

# 单边线性展开
print(dot_expr(x + 1, y))       # → dot(1, y) + dot(x, y)

# 双边展开(借助对称性)
print(dot_expr(x + 1, y + 2))   # → dot(1, 2) + dot(1, y) + dot(2, x) + dot(x, y)

这个方案的精髓在于:表达式在构建阶段就已经完成了代数化简,生成的结果天然符合规则。后续直接用 expand()collect() 这些标准操作就行,完全不需要额外的 rewritereplace

需要提醒的是:

归根结底,SymPy 的灵活之处就在于,它允许你把数学语义直接编码进 Python 函数逻辑里。通过组合 orderedAdd.as_ordered_terms() 和递归构造,就能高效实现定制化的代数运算。这种做法的简洁性和可控性,远胜于试图绕过 AST 去直接注入规则。

本文转载于:https://www.php.cn/faq/2812629.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。