替换与模式匹配 · 符号操作的基本动作
求导、化简、解方程,底层都是同一个动作:在表达式树里找到一个模式,把它替换掉。这一章讲清 SymPy 的三件基本兵器——subs(替换)、match(模式匹配)、replace(按模式批量替换),它们是下一章「计算即重写」的砖石。
替换与模式匹配 · 符号操作的基本动作
地基搭好了,现在看符号计算最核心的动作。你会发现,无论多花哨的操作,拆到底都是两个字:替换——在表达式树里找到某个部分,换成别的。这一章讲三件实现「替换」的基本兵器。
subs:把符号换成别的
最常用的是 .subs()——把表达式里的某个符号,换成一个值或另一个表达式:
from sympy import *
x, y, z = symbols('x y z')
e = x**2 + 2*x + 1
print(e.subs(x, 3)) # 16 —— 把 x 换成数 3(即求值)
print(e.subs(x, y + 1)) # (y+1)**2 + 2*(y+1) + 1 —— 把 x 换成表达式
print((x + y).subs({x: 1, y: 2})) # 3 —— 一次换多个subs 就是「代入」。注意它的本质是树操作:在 的树里,找到所有 叶子,把每个都换成新的子树(数 3、或子树 y+1)。换成表达式时,新子树整个嫁接进去。
更妙的是,subs 不止能换符号,还能换整个子表达式——只要那棵子树在原树里出现:
print((x*y + z).subs(x*y, z)) # 2*z —— 把子式 x*y 整个换成 z它在树里找到 x*y 这棵子树,替换成 z,得到 z + z,自动化简成 2*z。这正是化简、变量代换、方程回代的底层机制。
match:在树里认出一个「模式」
subs 要求你精确说出要换什么。但很多时候我们想表达的是一类模式:「任何东西的平方」「 括号里任意倍的 」。这就需要通配符 Wild 和模式匹配 .match():
a, b = Wild('a'), Wild('b')
print((x**2).match(a**b)) # {a_: x, b_: 2} —— 认出「a 的 b 次方」
print(sin(2*x).match(sin(a*x))) # {a_: 2} —— 认出「sin(a 乘 x)」Wild('a') 是个通配符,能匹配任意子表达式。.match(pattern) 拿模式去套目标树:套得上,就返回一个字典,告诉你每个通配符匹配到了什么(,);套不上返回 None。
模式匹配是符号计算的「眼睛」。 一条数学规则,比如乘积法则 ,左边的 就是一个模式(两个任意表达式相乘)。CAS 要应用这条规则,第一步就是用模式匹配在树里认出「这是一个乘积」,并抓出 和 分别是谁。先「认出」,才能「改写」——这就是下一章的主题。
replace:找出所有匹配,一次换掉
match 只看整棵树是否匹配。实战中我们常要在树的各个角落找出所有符合模式的地方,统统替换——这是 .replace():
# 把表达式里所有的 sin 换成 cos
print((sin(x) + sin(y)**2).replace(sin, cos)) # cos(x) + cos(y)**2
# 配合 Wild:把任意「平方」换成「立方」
print((x**2 + y**2).replace(a**2, a**3)) # x**3 + y**3replace 遍历整棵树,每遇到一处匹配 sin(任意) 或 (任意)**2,就地替换。一条「模式 → 替换」的规则,加上 replace 的遍历,就能把一个变换施加到整个表达式。
三件兵器,一个内核
回头看这三件工具,它们其实是同一件事的三个层次:
| 工具 | 干什么 | 一句话 |
|---|---|---|
subs | 把指定的东西换掉 | 精确替换 |
match | 认出符合模式的树,抓出通配符 | 模式识别 |
replace | 找出所有匹配的地方,批量替换 | 模式识别 + 替换 |
它们共同指向一个内核:一条规则 =「模式(match 的对象)+ 替换(subs 的动作)」;应用规则 = 在树里找到模式,把它换成替换的样子。 求导规则、三角恒等式、化简规则……全都是这个形状。
小结与下一章
符号操作的基本动作是替换:subs(把指定符号 / 子式换成别的,本质是树的嫁接)、match(用 Wild 通配符在树里认出模式,返回匹配字典)、replace(找出所有匹配处批量替换)。三者合起来定义了「规则 = 模式 + 替换」这个符号计算的原子。
现在,最深刻的一章来了。既然求导、化简、解方程都是「按规则替换」,那我们不妨把这个想法推到底:符号计算的全部,是不是就是「反复应用重写规则」?更进一步——「计算」本身,是不是就是这件事? 答案是响亮的「是」,它把符号计算、λ 演算、Lisp 和数理逻辑连成了一体。👉 计算即重写:逻辑计算的本质。
参考文献
- [1] SymPy 文档.「Manipulation: subs, replace, match, Wild.」https://docs.sympy.org/latest/tutorials/intro-tutorial/manipulation.html
- [2] Joel S. Cohen.《Computer Algebra and Symbolic Computation: Elementary Algorithms》, ch. 3 —— 结构上的替换与匹配。
- [3] Bruno Buchberger et al.《Symbolic Computation》—— 模式匹配在 CAS 中的角色。