Make all symbols commutative in a sympy expression - python

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)

Related

Is it possible to unreserve the reserved letters in SymPy Such as sympy.E and make it a sympy.Symbol?

Let's say for some reason you need or you prefer to have E or any of other reserved letters of SymPy as a symbol. So when you ask sympy.sympify("E"), you want a <class 'sympy.core.symbol.Symbol'> not a <class 'sympy.core.numbers.Exp1'>. For a simple small example look at the following code.
import sympy
symbols_list = sympy.symbols(' '.join(["A","E","Y"]))
expr = sympy.sympify("Y + 2 * E")
print(f"variables in expr are {expr.free_symbols}")
for x in symbols_list:
print(f"coefficient of {x} in expr is {expr.coeff(x)}")
Then the printed message is
variables in expr are {Y}
coefficient of A in expr is 0
coefficient of E in expr is 0
coefficient of Y in expr is 1
while I want to see
variables in expr are {Y, E}
coefficient of A in expr is 0
coefficient of E in expr is 2
coefficient of Y in expr is 1
Is there anyway to force SymPy like declaring something at the beginning of the script to forget its own E in this script?
You should use parse_expr directly rather than sympify to customise the behaviour of the parser. With parse_expr you can specify the local_dict and global_dict to be used when executing the parsed code. In this case it is the global_dict that defines E but you can override that using the local_dict:
In [14]: parse_expr("Y + E", local_dict={'E':Symbol('E')}).free_symbols
Out[14]: {E, Y}
https://docs.sympy.org/latest/modules/parsing.html#sympy.parsing.sympy_parser.parse_expr

How do I do multiple things inside one lambda function?

I am learning Python and I want to do multiple things inside one lambda function.
Just for a small example if I want to do addition, subtraction, and multiplication in one function, how do I do that?
I tried to use code like this just to see if it would work and it didn't:
a = 1
b = 2
myFunction = lambda a, b: a + b, b - a, a * b
print(myFunction(a, b))
You can group those operations in a tuple
a = 1
b = 2
myFunction = lambda a, b: (a + b, b - a, a * b)
myFunction(a, b)
output:
(3, 1, 2)
NB. The mistake in you code is that myFunction was a tuple containing your lambda as first element, not a function.
I think there is a slight syntax issue around a lambda returning a tuple.
Use this syntax:
a = 1
b = 2
myFunction = lambda a, b: (a + b, b - a, a * b)
print(myFunction(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))

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

How to calculate expression using sympy in 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

Categories