13

[SymPy][1] を使用して、式の複数の用語を同時に置換しようとしています。[subs 関数][2] を辞書をパラメータにして試してみたのですが、順番に代入することがわかりました。

In : a.subs({a:b, b:c})
Out: c

問題は、最初の置換によって、2 番目の置換で置換できる用語が生成されたことですが、そうすべきではありません (私の目的では)。

互いに干渉することなく、置換を同時に実行する方法について何か考えはありますか?

編集: これは実際の例です

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)
4

5 に答える 5

14

sympy の現在のバージョンでは、キーワード maximum が提供されています。以前の回答の複雑な操作はもう必要ありません。

In [1]: (x*sin(y)).subs([(x,y),(y,x)],simultaneous=True)
Out[1]: y⋅sin(x)
于 2012-06-09T18:41:46.537 に答える
2

subs(self,*args)メソッドは (部分的に) 次のように定義されます。

In [11]: x.subs??
...
sequence = args[0]
if isinstance(sequence, dict):
    return self._subs_dict(sequence)
elif isinstance(sequence, (list, tuple)):
    return self._subs_list(sequence)

subsdictを渡すと、置換の順序を制御できなくなります。subsリストまたはタプルを渡すと、順序を制御できます。

これにより、同時置換を行うことができなくなります。ユーザーが のようなものを渡すと、問題が発生しますx.subs([(x,y),(y,x)])。したがって、sympy に同時置換を行う方法があるとは思えません。代わりに、すべての置換は順序付けされていない (dict を渡す場合) か、せいぜい 1 パスの順序付けられた置換 (リストまたはタプルを渡す場合) によって行われると思います。

In [17]: x.subs([(x,y),(y,z)])
Out[18]: z

In [19]: x.subs([(y,z),(x,y)])
Out[19]: y

PS。_subs_list(self, sequence)は次のように (部分的に) 定義されます。

In [14]: x._subs_list??
...
    for old, new in sequence:
        result = result.subs(old, new)

これにより、潜水艦が行われる順序が明確になります。

于 2010-06-20T20:07:20.343 に答える
1

編集された質問に答えます。

あなたの例では、後続の置換で上書きされないいくつかの一時変数を使用できます。次に、重複する可能性のある置換がすべて行われると、一時変数を実際の変数に置き換えることができます。

この例は、問題全体にもっと複雑な置換が含まれている場合でも、置換の重複を避けるために一時変数を作成できるはずです。

from sympy import Symbol, sin, cos, pi

I_x, I_y, I_z = Symbol("I_x"), Symbol("I_y"), Symbol("I_z")
S_x, S_y, S_z = Symbol("S_x"), Symbol("S_y"), Symbol("S_z")
J_is = Symbol("J_IS")
t = Symbol("t")
I_x_temp, I_y_temp, I_z_temp = Symbol("I_x_temp"), Symbol("I_y_temp"), Symbol("I_z_temp")

f = 2*I_x*S_z
answer = I_y*sin(2*pi*J_is*t) + 2*I_x*S_z*cos(2*pi*J_is*t)

subs1a = [
    (2*I_x*S_z, 2*I_x_temp*S_z*cos(2*pi*J_is*t) + I_y_temp*sin(2*pi*J_is*t)),
    (I_x,  I_x_temp*cos(2* pi*J_is*t) + 2*I_x_temp*S_z*sin(2*pi*J_is*t)),
    (I_y,  I_y_temp*cos(2*pi*J_is*t) - 2*I_x_temp*S_z* sin(2*pi*J_is*t))
]

subs_temp = [(I_x_temp, I_x), (I_y_temp, I_y), (I_z_temp, I_z)]

print f
f = f.subs(subs1a)
print f
f = f.subs(subs_temp)
print f
print f == answer # True

2 つの置換を続けて実行することもできます。

f.subs(subs1a).subs(subs_temp) == answer
于 2010-06-23T15:31:50.997 に答える
1

@~unutbu の回答の例:

>>> import ordereddict # collections.OrderedDict in Python 2.7+
>>> from sympy import *
>>> x,y,z = symbols('xyz')
>>> x.subs(ordereddict.OrderedDict([(x,y),(y,z)]))
y
>>> x.subs(ordereddict.OrderedDict([(y,z),(x,y)]))
z
于 2010-06-20T20:18:06.493 に答える
0

キーワードsimultaneousは、入力 (辞書またはシーケンス) に関係なく、衝突しないサブルーチンを実行します。

>>> x.subs([(x,y),(y,z)],simultaneous=1)
y
>>> x.subs([(y,z),(x,y)],simultaneous=1)
y
于 2014-02-26T00:41:22.870 に答える