SymPy 中的非顺序替换
我正在尝试使用 [SymPy][1] 同时替换表达式中的多个术语。我尝试使用字典作为参数的 [subs 函数][2],但发现它是按顺序替换的。
In : a.subs({a:b, b:c})
Out: c
问题是第一次替换产生的术语可以被第二次替换所替换,但它不应该(出于我的原因)。
知道如何同时执行替换而不互相干扰吗?
编辑: 这是一个真实的例子,
In [1]: I_x, I_y, I_z = Symbol("I_x"), Symbol("I_y"), Symbol("I_z")
In [2]: S_x, S_y, S_z = Symbol("S_x"), Symbol("S_y"), Symbol("S_z")
In [3]: J_is = Symbol("J_IS")
In [4]: t = Symbol("t")
In [5]: substitutions = (
(2 * I_x * S_z, 2 * I_x * S_z * cos(2 * pi * J_is * t) + I_y * sin(2 * pi * J_is * t)),
(I_x, I_x * cos(2 * pi * J_is * t) + 2 * I_x * S_z * sin(2 * pi * J_is * t)),
(I_y, I_y * cos(2 * pi * J_is * t) - 2 * I_x * S_z * sin(2 * pi * J_is * t))
)
In [6]: (2 * I_x * S_z).subs(substitutions)
Out[7]: (I_y*cos(2*pi*J_IS*t) - 2*I_x*S_z*sin(2*pi*J_IS*t))*sin(2*pi*J_IS*t) + 2*S_z*(I_x*cos(2*pi*J_IS*t) + 2*I_x*S_z*sin(2*pi*J_IS*t))*cos(2*pi*J_IS*t)
只应进行适当的替换,在本例中仅进行第一个替换。所以预期的输出应该如下:
In [6]: (2 * I_x * S_z).subs(substitutions)
Out[7]: I_y*sin(2*pi*J_IS*t) + 2*I_x*S_z*cos(2*pi*J_IS*t)
I'm trying to use [SymPy][1] to substitute multiple terms in an expression at the same time. I tried the [subs function][2] with a dictionary as parameter, but found out that it substitutes sequentially.
In : a.subs({a:b, b:c})
Out: c
The problem is the first substitution resulted in a term that can be substituted by the second substitution, but it should not (for my cause).
Any idea on how to perform the substitutions simultaneously, without them interfering with each other?
Edit:
This is a real example
In [1]: I_x, I_y, I_z = Symbol("I_x"), Symbol("I_y"), Symbol("I_z")
In [2]: S_x, S_y, S_z = Symbol("S_x"), Symbol("S_y"), Symbol("S_z")
In [3]: J_is = Symbol("J_IS")
In [4]: t = Symbol("t")
In [5]: substitutions = (
(2 * I_x * S_z, 2 * I_x * S_z * cos(2 * pi * J_is * t) + I_y * sin(2 * pi * J_is * t)),
(I_x, I_x * cos(2 * pi * J_is * t) + 2 * I_x * S_z * sin(2 * pi * J_is * t)),
(I_y, I_y * cos(2 * pi * J_is * t) - 2 * I_x * S_z * sin(2 * pi * J_is * t))
)
In [6]: (2 * I_x * S_z).subs(substitutions)
Out[7]: (I_y*cos(2*pi*J_IS*t) - 2*I_x*S_z*sin(2*pi*J_IS*t))*sin(2*pi*J_IS*t) + 2*S_z*(I_x*cos(2*pi*J_IS*t) + 2*I_x*S_z*sin(2*pi*J_IS*t))*cos(2*pi*J_IS*t)
Only the appropriate substitution should happen, in this case only the first one. So the expected output should be the following:
In [6]: (2 * I_x * S_z).subs(substitutions)
Out[7]: I_y*sin(2*pi*J_IS*t) + 2*I_x*S_z*cos(2*pi*J_IS*t)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
当前版本的 sympy 提供了关键字同时。前面答案中的复杂操作不再需要:
The current version of sympy provides the keyword simultaneous. The complicated operations in the previous answers are no more necessary:
subs(self,*args)
方法(部分)是这样定义的:如果你传递
subs
一个字典,你就失去了对替换顺序的控制。而如果您传递
subs
列表或元组,则可以控制顺序。这不允许您同时进行替换。如果用户传递像 x.subs([(x,y),(y,x)]) 这样的东西,这会导致困难。所以我怀疑 sympy 是否有同时进行替换的方法。相反,我相信所有替换要么是无序的(如果您传递一个字典),要么最多通过 1 遍有序替换完成(如果您传递一个列表或元组):
PS。
_subs_list(self,equence)
的定义(部分)如下:这确定了 subs 完成的顺序。
The
subs(self,*args)
method is defined (in part) this way:If you pass
subs
a dict, you lose control over the order of the substitutions.While if you pass
subs
a list or tuple, you can control the order.This doesn't allow you to do simultaneous substitutions. That would lead to difficulties if the user were to pass stuff like
x.subs([(x,y),(y,x)])
. So I doubt sympy has a method for doing simultaneous substitutions. Instead I believe all substutions are either unordered (if you pass a dict) or, at best, done by a 1-pass ordered substitution (if you pass a list or tuple):PS.
_subs_list(self, sequence)
is defined (in part) like this:This nails down the order in which the subs are done.
@~unutbu 的回答示例:
Example for @~unutbu's answer:
回答编辑后的问题。
在您的示例中,您可以使用一些临时变量,这些变量不会被后续替换覆盖。然后,一旦完成所有可能重叠的替换,您就可以用真实变量替换临时变量。
这个示例适用于这个问题,如果您的完整问题包含更复杂的替换,我认为您仍然应该能够创建临时变量以避免重叠替换。
请注意,您还可以连续执行两次替换:
Answering the edited question.
In your example you can use some temporary variables which will not be over-written be subsequent substitutions. Then, once all of the potentially overlapping substitutions have been made, you can replace the temporary variables with the real ones.
This example works for the question, if your full problem contains more complex substitutions, I think you should still be able to create temporary variables to avoid overlapping substitutions.
Note, you can also perform two substitutions back to back:
无论输入(字典或序列)如何,关键字
simultaneous
都会执行非冲突的替换:The Keyword
simultaneous
will do non-clashing subs regardless of the input (dict or sequence):