How to calculate expression using sympy in python - python

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

Related

Make all symbols commutative in a sympy expression

Say you have a number of non commutative symbols within a sympy expression, something like
a, c = sympy.symbols('a c', commutative=False)
b = sympy.Symbol('b')
expr = a * c + b * c
What is the preferred way to make all symbols in the expression commutative, so that, for example, sympy.simplify(allcommutative(expr)) = c * (a + b)?
In this answer it is stated that there is no way to change the commutativity of a symbol after creation without replacing a symbol, but maybe there is an easy way to change in blocks all symbols of an expression like this?
If you want Eq(expr, c * (a + b)) to evaluate to True, you'll need to replace symbols by other symbols that commute. For example:
replacements = {s: sympy.Dummy(s.name) for s in expr.free_symbols}
sympy.Eq(expr, c * (a + b)).xreplace(replacements).simplify()
This returns True.
Two comments:
noncommutatives will factor (though they respect the side that the nc expr appears on)
although you have a robust answer, a simple answer that will often be good enough is to just sympify the string version of the expression
Both are shown below:
>>> import sympy
>>> a, c = sympy.symbols('a c', commutative=False)
>>> b = sympy.Symbol('b')
>>> expr = a * c + b * c
>>> factor(expr)
(b + a)*c
>>> S(str(_))
c*(a + b)

Use Lambdify for multiple symbolic variables

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

add two numpy arrays using lamdify - pass expression as function argument

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.

Printing a whole equation (including variables) in Python

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.

Python Logarithm Function

I'm looking for an example of operations with logarithms in Python. I've tried with sympy and numpy and I still can't do what I want. For example, for an input like this:
log(x+1)+log(4-x)=log(100) # it's just an example
the output should give me the x value. I need to do this with any other functions like log(x+1)=4 or log(x)-log(x+1)=log(x).
Is there some method or somewhere (documentation or similar) where can I find how to do this?
I may be misunderstanding what you need to do because you said you tried sympy already. However, it looks like you just want to solve for x in an algebraic equation.
Solving for x in the equation
log(x+1)+log(4-x)=log(100)
using sympy would be
>>> from sympy import Symbol, solve, log
>>> x = Symbol('x')
>>> solve(log(x+1) + log(4-x) - log(100), x)
[3/2 - 5*sqrt(15)*I/2, 3/2 + 5*sqrt(15)*I/2]
If you want, you can check that these two solutions are correct with numpy.
>>> import numpy as np
>>> a = 3/2 - 5*np.sqrt(15)*1j/2
>>> b = 3/2 + 5*np.sqrt(15)*1j/2
>>> np.log(a + 1) + np.log(4-a)
(4.6051701859880918+0j)
>>> np.log(b + 1) + np.log(4-b)
(4.6051701859880918+0j)
>>> np.log(100)
4.6051701859880918
Is that not what you are looking for?
Since log is a non-linear function, you will need to use a non-linear solver like scipy.optimize.fsolve. It take in a function and a guess value and returns the answer in the form of an array. For simplicity reason, I defined the function as a lambda function since we don't need it outside of this line, but creating a function using standard def methods would work as well. The [0] on the back end get the value out of the array to return just the float.
import scipy.optimize
import math
scipy.optimize.fsolve(lambda x: math.log(x+1) - 4, 5)[0] # 5 is guess value
>>> 53.598
# Check
math.exp(4) - 1
>>> 53.598
Good advice already given. I just note that you can also check the answer in SymPy.
>>> L, R = log(x+1)+log(4-x), log(100)
>>> eq = Eq(L, R)
>>> eq
log(-x + 4) + log(x + 1) == log(100)
>>> sol = solve(eq)
>>> [eq.subs(x, i) for i in sol]
[True, True]
So in the Eq form the solutions were verified automatically. This is not always
true but you can use numerical evaluation to check the value:
>>> f = eq.lhs - eq.rhs; f
log(-x + 4) + log(x + 1) - log(100)
>>> f.subs(x, sol[0])
-log(100) + log(5/2 - 5*sqrt(15)*I/2) + log(5/2 + 5*sqrt(15)*I/2)
>>> _.n()
0.e-124 + 0.e-125*I
>>> f.subs(x, sol[0]).n(chop=True) # the small numbers can be chopped
0

Categories