The python script below evaluates the first term in the expression,
4.939e-3xAxB+8.7989 at (A,B) = (1.0,1.0):
import sympy
from sympy import *
A = sympy.Symbol(A)
B = sympy.Symbol(B)
F = 4.939e-3*A*B+8.7989
G = str(F).split("+")[0]
H = lambdify([A,B], G, "numpy")
print H(1,1)
The ouput is: 0.004939
Now the code below aims to achieve the same objective:
A = sympy.Symbol(A)
B = sympy.Symbol(B)
F = 4.939e-3*A*B+8.7989
G = str(F).split("+")[0]
H = lambdify(A, G, "numpy")
I = lambdify(B, H(1), "numpy")
print I(1)
But this returns the error:
NameError: global name 'B' is not defined
Can someone kindly explain this?
You are conflating strings and symbols at multiple instances. The only reason that any of this works at all is that SymPy applies sympify to many inputs (sympify("A")==Symbol("A")) and Python’s duck typing. Specifically, G is a string, when it should be a symbolic expression, and all first arguments passed to lambdify are strings or lists of strings, when they should be symbols or lists thereof.
A clean version of your first code would be:
from sympy.abc import A,B
import sympy
G = 4.939e-3*A*B # now this is a symbolic expression, not a string
H = lambdify( [A,B], G, "numpy" )
print(H(1,1))
And the same for your second code:
from sympy.abc import A,B
import sympy
G = 4.939e-3*A*B # now this is a symbolic expression, not a string
H = lambdify( A, G, "numpy" )
I = lambdify( B, H(1), "numpy" )
print(I(1))
Related
Given an expression, we can convert it into a function using sympy.lambdify. Similarly, given a function, we can convert it into an expression by evaluating it at symbol x. We would naturally expect that these two operations are inverses of each other. And, this expected behaviour is displayed when I use polynomial expressions. For example,
import sympy as sym
x = sym.symbols('x')
expr = 5*x**2 + 2*x + 3
f = sym.lambdify([x],expr)
f_expr = f(x)
print(expr == f_expr)
gives True as its output.
On the other hand, the following code does not run
import sympy as sym
x = sym.symbols('x')
expr = sym.sin(x)
f = sym.lambdify([x],expr)
f_expr = f(x)
print(expr == f_expr)
and throws the error "TypeError: loop of ufunc does not support argument 0 of type Symbol which has no callable sin method". Could you please explain why this is happening? My guess would be that sym.sin(x) does not return an "expression" analogous to 5x**2 + 2x + 3. But, I would like to understand it a bit better. Thanks in advance.
For a non-numeric object the lambdify code tries to do x.sin()
with making sure the sin function is from library sympy not numpy to avoid confusions.
you can try :
import sympy as sym
from sympy import sin
x = sym.symbols('x')
expr = sin(x)
# f = sym.lambdify(x,expr)
f = lambda x:sin(x)
f_expr = f(x)
print(expr == f_expr)
I have this piece of code:
import numpy as np
import sympy
from sympy import symbols
from sympy.utilities.autowrap import ufuncify
from sympy.utilities.lambdify import lambdify
def test(expr,a,b):
a_var, b_var = symbols("a b")
#f = ufuncify((a_var, b_var), expr, backend='numpy')
f = lambdify( (a_var, b_var), expr, 'numpy')
return f(a_var, b_var)
a = np.array([2,3])
b = np.array([1,2])
expr = a + b
print(test(expr, a, b))
which give me:
../anaconda3/envs/python3/lib/python3.6/site-packages/sympy/core/sympify.py:282: VisibleDeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
rational=rational) for x in a])
File "<string>", line 1
lambda _Dummy_52,_Dummy_53: ([3 5])
SyntaxError: invalid syntax
If I use the ufuncify :
...
TypeError: unhashable type: 'numpy.ndarray'
During handling of the above exception, another exception occurred:
...
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
====== UPDATE ================
One solution I found is to use expr like a string and then inside function use sympify:
data_a = np.array([2,3])
data_b = np.array([1,2])
expr = "data_a + data_b"
def test(expr,data_a, data_b):
a, b = symbols("data_a data_b")
expr = sympify(expr)
f = lambdify( (a, b), expr, 'numpy')
return f(data_a, data_b)
and I am taking:
[3 5]
But how can I avoid using the expression as a string?
lambdify converts SymPy expressions into NumPy functions. You are trying to convert a NumPy array into a NumPy function. The arguments to lambdify need to be SymPy objects.
You want something like
a_var, b_var = symbols("a b")
expr = a_var + b_var
f = lambdify((a_var, b_var), expr, 'numpy')
You'll then get
>>> a = np.array([2,3])
>>> b = np.array([1,2])
>>> f(a, b)
array([3, 5])
The basic code flow for lambdify is SymPy expression => NumPy function. To keep things clear in your head and in your code, you should start with just SymPy, and manipulate the expressions until you have a lambdified function. Then use it with your NumPy data. Start with defining symbol names. Then you can define an expression in terms of those symbols, without using a string (for instance, as I have done above). Once you have an expression and the symbols, you create a lambdified function. At that point, you pass NumPy arrays into the function. I recommend using different variable names for SymPy symbols/expressions and NumPy arrays, so that they don't get mixed up. I also recommend using the same variable name for symbols as the symbol names themselves, so that when you print the expression it will appear exactly as you would write it (e.g., below if you print(expr), you will get a + b, which is exactly what you would write to get expr).
In your updated example, you can use
a, b = symbols("a b")
expr = a + b
f = lambdify((a, b), expr, 'numpy')
data_a = np.array([2,3])
data_b = np.array([1,2])
f(data_a, data_b)
Note how I start with creating SymPy symbols and a SymPy expression from those symbols. Then I lambdify it. Once it's lambdified, I have the lambdified function (f). At this point, I'm not using SymPy at all anymore, just NumPy arrays (the data) and the lambdified function f.
To get all variables from a sympy expression, one can call .free_symbols on the expression. I would like to retrieve all functions used in an expression. For example, from y in
from sympy import *
f = Function('f')
g = Function('g')
x = Symbol('x')
y = f(x) + 2*g(x)
I'd like to get f and g.
Any hints?
atoms does the trick:
for f in y.atoms(Function):
print(f.func)
For all functions, use atoms(Function).
In [40]: (f(x) + sin(x)).atoms(Function)
Out[40]: set([f(x), sin(x)])
For only undefined functions, use atoms(AppliedUndef).
In [41]: from sympy.core.function import AppliedUndef
In [42]: (f(x) + sin(x)).atoms(AppliedUndef)
Out[42]: set([f(x)])
say I want to print the equation g(x) in the form g(x) = x^2 *........
how do I do it? This is my first time using python
import numpy as np
import matplotlib.pyplot as plt
import math
from sympy.mpmath import *
f = lambda x: ((x^2)*math.exp(-x))
dfdx = lambda x: diff(f,x)
d2fdx2 = lambda x: diff(dfdx,x)
g = lambda x: ((math.exp(x)/math.factorial(2))*d2fdx2)
print(g)
(edit) the output im getting is
function lambda at 0x0671C198
First of drop all the the unnecessary imports and stick to what you really need. Symbolic math is what sympy was made for so check out the documentation for that.
In sympy you have to define symbols first
import sympy
x = symbols('x')
Now you would use the symbol x to construct an expression using builtin operators and functions in the sympy module. Be aware that ** is exponentiation and ^ is logical xor.
f = x ** 2 * sympy.exp(-x)
dfdx = sympy.diff(f, x)
d2fdx2 = sympy.diff(f, x, x)
g = sympy.exp(x) / sympy.factorial(2) * d2fdx2
When you write g in the interactive interpreter it will write the expression the way you want it. Can't show that here but atleast I can do this:
>>> print(g)
x**2/2 - 2*x + 1
You cannot do what you want with the math, sympy.mpmath and numpy modules as they exist for numerical evalutions - they want numbers and give you number.
If you later want to evaluate your expression for a given value of x you could do
val_at_point = g.evalf(subs={x: 1.5})
where subs is a dictionary.
Or you could turn g into a python lambda function:
fun_g = sympy.lambdify(x, g)
val_at_point = fun_g(1.5)
If you're doing this for a math class you probably want to be working in the interpreter anyway in which case you can start by writing
>>> from sympy import *
so that you can skip all the sympy. stuff in the above code samples. I left them there just to show where symbols come from.
I need a calculate below expression using sympy in python?
exp = '(a+b)*40-(c-a)/0.5'
In a=6, b=5, c=2 this case how to calculate expression using sympy in python? Please help me.
The documentation is here: http://docs.sympy.org/. You should really read it!
To "calculate" your expression, write something like this:
from sympy import Symbol
a = Symbol("a")
b = Symbol("b")
c = Symbol("c")
exp = (a+b)*40-(c-a)/0.5
And that's it. If you meant something else by "calculate", you could also solve exp = 0:
sympy.solve(exp)
> {a: [0.0476190476190476*c - 0.952380952380952*b],
> b: [0.05*c - 1.05*a],
> c: [20.0*b + 21.0*a]}
For everything else, you should really read the docs. Maybe start here: http://docs.sympy.org/0.7.1/tutorial.html#tutorial
UPDATE: since you added the values for a, b, c to the question, you can add this to the solution:
exp.evalf(subs={a:6, b:5, c:2})
You can convert your string into a sympy expression using the parse_expr() function in the module sympy.parsing.sympy_parser.
>>> from sympy.abc import a, b, c
>>> from sympy.parsing.sympy_parser import parse_expr
>>> sympy_exp = parse_expr('(a+b)*40-(c-a)/0.5')
>>> sympy_exp.evalf(subs={a:6, b:5, c:2})
448.000000000000
I realise this was already answered above, but in the case of getting a string expression with unknown symbols and needing access to those symbols, here is the code I used
# sympy.S is a shortcut to sympify
from sympy import S, Symbol
# load the string as an expression
expression = S('avar**2 + 3 * (anothervar / athirdvar)')
# get the symbols from the expression and convert to a list
# all_symbols = ['avar', 'anothervar', 'athirdvar']
all_symbols = [str(x) for x in expression.atoms(Symbol)]
# do something with the symbols to get them into a dictionary of values
# then we can find the result. e.g.
# symbol_vals = {'avar': 1, 'anothervar': 2, 'athirdvar': 99}
result = expression.subs(symbols_vals)
Well, I know that eval is evil, but if you have a,b and c defined in your program, and you can make sure that it's safe to do the eval, you don't need sympy.
>>> a=5
>>> b=5
>>> c=2
>>> exp = '(a+b)*40-(c-a)/0.5'
>>> eval(exp)
406.0
>>> a, b, c = sympy.symbols('a b c')
>>> exp = (a + b) * 40 - (c - a) / 0.5
>>> exp.evalf(6, subs={a:6, b:5, c:2})
448.000