Симптическая "глобальная" замена - PullRequest
5 голосов
/ 05 марта 2012

У меня есть несколько символических выражений в sympy, и я могу прийти к выводу, что один из коэффициентов равен нулю. Я думаю, возможно, потому что я привык к математике, что имеет смысл следующее:

from sympy import Symbol
x = Symbol('x')
y = Symbol('y')
f = x + y
x = 0
f

Удивительно, но возвращается x + y. Есть ли способ, кроме явного вызова «subs» в каждом уравнении, чтобы f вернул просто y?

Ответы [ 3 ]

8 голосов
/ 05 марта 2012

Я думаю subs - единственный способ сделать это.Похоже, что симпатичное выражение - это нечто само по себе.Это не относится к частям, которые составили это.То есть f имеет только выражение x+y, но не знает, что оно имеет какую-либо ссылку на объекты Python x и y.Рассмотрим приведенный ниже код:

from sympy import Symbol
x = Symbol('x')
y = Symbol('y')
z = Symbol('z')

f1 = x + y
f2 = z + f1
f1 = f1.subs(x,0)
print(f1)
print(f2)

Вывод этого:

y
x + y + z

Так что, хотя f1 изменился f2 не изменился.Насколько мне известно, subs - это единственный способ сделать то, что вы хотите.

7 голосов
/ 05 марта 2012

Я не думаю, что есть способ сделать это автоматически (или, по крайней мере, без изменения SymPy).

Следующий вопрос из FAQ SymPy объясняет почему:

Почему изменение одной переменной не приводит к изменению другой, зависящей от нее?

Короткий ответ: «потому что не зависит от этого». :-) Даже если вы работаете с уравнениями, вы все еще работаете с Python объекты. Уравнения, которые вы вводите, используют значения, присутствующие в время создания, чтобы "заполнить" значения, как обычный питон определения. Они не изменены изменениями, сделанными впоследствии. Рассматривать следующее:

>>> a = Symbol('a') # create an object with name 'a' for variable a to point to
>>> b = a + 1; b    # create another object that refers to what 'a' refers to
a + 1
>>> a = 4; a        # a now points to the literal integer 4, not Symbol('a')
4
>>> b               # but b is still pointing at Symbol('a')
a + 1

Изменяемое количество a не изменяется b; ты не работаешь с сетом одновременных уравнений. Может быть полезно помнить, что строка, которая печатается при печати переменной, ссылающейся на объект - это строка, которая была передана ему при создании; тот строка не обязательно должна совпадать с той переменной, которую вы ей присвоили чтобы:

>>> r, t, d = symbols('rate time short_life')
>>> d = r*t; d
rate*time
>>> r=80; t=2; d    # we haven't changed d, only r and t
rate*time
>>> d=r*t; d        # now d is using the current values of r and t
160
2 голосов
/ 09 ноября 2014

Может быть, это не то, что вы ищете (как это уже объяснили другие), но это мое решение для замены нескольких значений одновременно.

def GlobalSubs(exprNames, varNames, values=[]):

    if ( len(values) == 0 ):                # Get the values from the
        for varName in varNames:            # variables when not defined
            values.append( eval(varName) )  # as argument.
        # End for.
    # End if.

    for exprName in exprNames:                        # Create a temp copy
        expr = eval(exprName)                         # of each expression
        for i in range(len(varNames)):                # and substitute
            expr = expr.subs(varNames[i], values[i])  # each variable.
        # End for.
        yield expr     # Return each expression.
    # End for.

Работает даже для матриц!

>>> x, y, h, k = symbols('x, y, h, k')
>>> A = Matrix([[ x, -h],
...             [ h,  x]])
>>> B = Matrix([[ y,  k],
...             [-k,  y]])
>>> x = 2; y = 4; h = 1; k = 3
>>> A, B = GlobalSubs(['A', 'B'], ['x', 'h', 'y', 'k'])
>>> A
Matrix([
[2, -1],
[1,  2]])
>>> B
Matrix([
[ 4, 3],
[-3, 4]])

Но не пытайтесь сделать модуль с этим. Это не сработает. Это будет работать только тогда, когда выражения, переменные и функция определены в одном файле, поэтому все функции являются глобальными для функции, и она может получить к ним доступ.

...