发布于2026-07-12 阅读(0)
扫一扫,手机访问
本文介绍如何在 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() 这些标准操作就行,完全不需要额外的 rewrite 或 replace。
需要提醒的是:
simplify(dot(x+1, y)),它不会自动触发展开——必须显式调用 dot_expr() 来构造。dot(k*a, b) → k*dot(a, b)),需要在 dot_expr 里增加对 Mul 类型的解析,检查首项是否为 Number 或 Symbol。sympy.tensor、galgebra 或者 cadabra——后者专门为广义相对论和场论设计,内置了强大的重写规则支持。归根结底,SymPy 的灵活之处就在于,它允许你把数学语义直接编码进 Python 函数逻辑里。通过组合 ordered、Add.as_ordered_terms() 和递归构造,就能高效实现定制化的代数运算。这种做法的简洁性和可控性,远胜于试图绕过 AST 去直接注入规则。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8