如果您以正确的顺序执行,替换将被迭代执行(除非您使用subs(replacement, simultaneous=True),它会一次执行所有替换)。
您的问题是正确订购替换件。你想要的是替换的topological sort。即,每个替换都是图中的一个节点,如果new1包含old2,则从(old1, new1)到(old2, new2)有一条边(即应该先替换它)。
SymPy 在sympy.utilities.iterables 中实现了topological_sort。它需要一个顶点列表和一个边列表(顶点元组)。说你有
replace = [(y, z + 1), (x, y + z), (z, a)]
我们可以用
创建一个边列表
from itertools import combinations
edges = [(i, j) for i, j in permutations(replace, 2) if i[1].has(j[0])]
排序得到
>>> from sympy import default_sort_key, topological_sort
>>> topological_sort([replace, edges], default_sort_key)
[(x, y + z), (y, z + 1), (z, a)]
topological_sort 的第三个参数是用于打破关系的键。由于 SymPy 对象没有定义隐式排序(< 和 > raise TypeError),因此有一个名为 default_sort_key 的排序键实现,它提供了规范且一致(但任意)的排序SymPy 对象。
在 404 所示的情况下会出现无限循环,topological_sort 会提醒您存在循环
>>> replace = [(x, y+1), (y, x+1)]
>>> edges = [(i, j) for i, j in permutations(replace, 2) if i[1].has(j[0])]
>>> topological_sort([replace, edges], default_sort_key)
Traceback (most recent call last):
File "<ipython-input-51-72f3bfcfd4ad>", line 1, in <module>
topological_sort([replace, edges], default_sort_key)
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/utilities/iterables.py", line 882, in topological_sort
raise ValueError("cycle detected")
ValueError: cycle detected
老实说,这应该通过关键字参数直接在subs 中实现。见https://github.com/sympy/sympy/issues/6257。