Markus Kaukonen
Markus Kaukonen

Reputation: 414

sympy: A simple symbolic equation solution followed by substitution with numbers

I have an equation 1x+2y=40 . I'd like to solve it for y (ie. get it to form y=...) And then substitute numbers for x to get numbers for y. My current semi-manual solution is as follows:

import matplotlib.pyplot as plt
import numpy as np
from sympy import symbols, solve

m=40
pa=1
pb=2

x, y = symbols('x, y')
eq = pa*x+pb*y-m

y= solve(eq, y)
print(y)
print(type(y))
print(type(y[0]))

# then watch on screen what y is and substitute by hand
x=np.linspace(1,4,41)
y=2-x/2

plt.plot(x,y)

Is there a better way to substitute numbers for x into solution and get numbers for y? (after 'solve' y seems to be of type list with one item of mystical type of 'sympy.core.add.Add')

Terveisin, Markus

Upvotes: 1

Views: 727

Answers (2)

Markus Kaukonen
Markus Kaukonen

Reputation: 414

Thanks, I could not find this piece of very basic information in the tutorials or in the documentation.

Here is a full working example based on the previous answer:

from sympy import symbols, solve, lambdify
import numpy as np

m=40
pa=1
pb=2

x, y = symbols('x, y')
eq = pa*x+pb*y-m

[soly]= solve(eq, y)
print(f"y= {soly}")

print(f"y(2)= {soly.subs(x, 2)}")

yfx = lambdify([x], soly, 'numpy')

print(f"y(np.arange(10))= {yfx(np.arange(10))}")

Upvotes: 1

Oscar Benjamin
Oscar Benjamin

Reputation: 14500

The solve function returns a list of expressions. It returns a list because in general there can be more than one solution to an equation:

In [17]: solve(x**2 - 2, x)
Out[17]: [-√2, √2]

If you know that there should only be one solution then you can extract it from the list any way you like e.g.:

In [12]: m=40
    ...: pa=1
    ...: pb=2
    ...: 
    ...: x, y = symbols('x, y')
    ...: eq = pa*x+pb*y-m
    ...: 
    ...: [soly] = solve(eq, y)

In [13]: soly
Out[13]: 
     x
20 - ─
     2

The solution is given here as a symbolic expression involving the symbol x. You can substitute values for x with subs:

In [14]: soly.subs(x, 2)
Out[14]: 19

The subs method performs a symbolic substitution that can handle substituting other symbolic expressions for x:

In [19]: soly.subs(x, sqrt(2))
Out[19]: 
     √2
20 - ──
     2 

To evaluate the expression efficiently in ordinary floating point for many possible values of x using you can use lambdify:

In [15]: yfx = lambdify([x], soly, 'numpy')

In [16]: yfx(np.arange(10))
Out[16]: array([20. , 19.5, 19. , 18.5, 18. , 17.5, 17. , 16.5, 16. , 15.5])

Note that it is a bad idea to overwrite a variable that you are using for a symbol like this:

y = solve(eq, y)  # use a different name like ysol

It is a bad idea to do this because any subsequent use of the Python variable y no longer refers to the original symbol y which is a common cause of confusion for inexperienced users of SymPy.

Most of the points I mentioned above are covered in the official tutorial which I recommend reading:

https://docs.sympy.org/latest/tutorial/index.html

The lambdify function is documented with a lengthy explanation here:

https://docs.sympy.org/latest/modules/utilities/lambdify.html#sympy.utilities.lambdify.lambdify

Upvotes: 1

Related Questions