
本文介绍如何在 sympy 中自定义一个具有双线性(对第一变量可加)和对称性(dot(a,b) = dot(b,a))的符号点积函数,并通过递归规则实现表达式的自动 expand 与 simplify,无需依赖模式匹配引擎。
本文介绍如何在 sympy 中自定义一个具有双线性(对第一变量可加)和对称性(dot(a,b) = dot(b,a))的符号点积函数,并通过递归规则实现表达式的自动 expand 与 simplify,无需依赖模式匹配引擎。
在 SymPy 中,原生不支持基于用户定义规则的符号重写(如 Mathematica 的 ReplaceRepeated 或 Maple 的 simplify with side relations),但可通过自定义 Python 函数 + SymPy 表达式结构分析,模拟“代数规则驱动”的展开行为。核心思路是:将 dot 实现为一个智能构造器函数,在构建时即递归应用线性性与对称性,而非后期调用 simplify() 触发规则匹配。
以下是一个稳健、可嵌套使用的 dot 实现:
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() 等标准运算,无需额外 rewrite 或 replace。
⚠️ 注意事项:
- 此方案不修改 SymPy 内部求值逻辑,因此 simplify(dot(x+1,y)) 不会自动触发展开 —— 必须显式调用 dot_expr() 构造;
- 若需支持标量乘法分配律(如 dot(k*a, b) → k*dot(a,b)),需在 dot_expr 中增加对 Mul 类型的解析(检查首项是否为 Number 或 Symbol);
- 对于更复杂的代数系统(如张量缩并、Clifford 代数),建议考虑专用库:sympy.tensor、galgebra 或 cadabra(后者专为广义相对论/场论设计,支持内置重写规则)。
总结:SymPy 的灵活性在于允许用户将数学语义编码进 Python 函数逻辑中。通过结合 ordered、Add.as_ordered_terms() 和递归构造,我们能高效实现定制化代数运算,其简洁性与可控性远超尝试绕过 AST 直接注入规则的方式。

















