Sympy глобальная подмена

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

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

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


person process91    schedule 05.03.2012    source источник


Ответы (3)


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

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

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

Короткий ответ: «потому что не от него зависит». :-) Даже если вы работаете с уравнениями, вы все равно работаете с объектами Python. Уравнения, которые вы вводите, используют значения, присутствующие во время создания, для «заполнения» значений, как и в обычных определениях 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; вы не работаете с системой одновременных уравнений. Было бы полезно помнить, что строка, которая печатается, когда вы печатаете переменную, ссылающуюся на объект sympy, - это строка, которая была передана ему при его создании; эта строка не обязательно должна совпадать с переменной, которой вы ее назначаете:

>>> 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
person Mariano Desanze    schedule 05.03.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 - это единственный способ сделать то, что вы хотите.

person Brad Campbell    schedule 05.03.2012

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

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

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

person aaguirre    schedule 08.11.2014