Question

I have a number of symbolic expressions in sympy, and I may come to realize that one of the coefficients is zero. I would think, perhaps because I am used to mathematica, that the following makes sense:

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

Surprisingly, what is returned is x + y. Is there any way, aside from explicitly calling "subs" on every equation, for f to return just y?

Was it helpful?

Solution

I don't think there is a way to do that automatically (or at least no without modifying SymPy).

The following question from SymPy's FAQ explains why:

Why doesn't changing one variable change another that depends it?

The short answer is "because it doesn't depend on it." :-) Even though you are working with equations, you are still working with Python objects. The equations you are typing use the values present at the time of creation to "fill in" values, just like regular python definitions. They are not altered by changes made afterwards. Consider the following:

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

Changing quantity a does not change b; you are not working with a set of simultaneous equations. It might be helpful to remember that the string that gets printed when you print a variable refering to a sympy object is the string that was give to it when it was created; that string does not have to be the same as the variable that you assign it to:

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

OTHER TIPS

I think subs is the only way to do this. It looks like a sympy expression is something unto itself. It does not reference the pieces that made it up. That is f only has the expression x+y, but doesn't know it has any link back to the python objects x and y. Consider the code below:

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)

The output from this is

y
x + y + z

So even though f1 has changed f2 hasn't. To my knowledge subs is the only way to get done what you want.

Maybe this is not what you're looking for (as it was already explained by others), but this is my solution to substitute several values at once.

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.

It works even for matrices!

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

But don't try to make a module with this. It won't work. This will only work when the expressions, the variables and the function are defined into the same file, so everything is global for the function and it can access them.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top