How do I evaluate a Sympy function in Python? - python

I am facing a major issues in python using sympy. I didn't find any solutions to my problem or at least, I couldn't apply the solutions I found on my problem.
import sympy as sp
import math as ma
import numpy as np
E1=72500
A1=15
U01,s,C1,U02 = sp.symbols("U01,s,C1,U02")
u1 = sp.symbols("u1", cls=sp.Function)
eqs=sp.Eq(E1*A1*u1(s).diff(s)+180+U02,0)
sol=sp.dsolve(eqs,dict=True)
expr=sol.args[1]
u1=sp.lambdify(s,expr.subs(C1,U01))
print(u1(s))
#gives me : U01 - 9.19540229885057e-7*U02*s - 0.00016551724137931*s
expression1=u1(10)-54
expression2=u1(7)-99
eq1=sp.Eq(expression1,0)
eq2=sp.Eq(expression2,0)
solution = sp.solve([eq1,eq2],[U01,U02])
U01=float(solution[U01])
U02=float(solution[U02])
print(u1(55))
# gives me : U01 - 5.05747126436782e-5*U02 - 0.00910344827586207
I want to evaluate u1(55), but I still get the expression.
Thank you very much in advance.
I expect to get :
-621.0000000000018

Don't override U01 and U02 by numerical values, use intermediate variables. You have to evaluate your lambda function with solution previously found:
...
solution = sp.solve([eq1, eq2], [U01, U02])
U01_val = float(solution[U01])
U02_val = float(solution[U02])
result = u1(55).evalf(subs={U01: U01_val, U02: U02_val})
print(result)
# Output
-621.000000000001
Or simply:
...
solution = sp.solve([eq1, eq2], [U01, U02])
result = u1(55).evalf(subs=solution)
print(result)
# Output
-621.000000000001

Related

Issue with differentiation using sympy

I am trying to differentiate this equation using SymPy:
What I wanted to achieve is this result:
But when I type this code into to execute, it gives me this result:
Here is my current code:
import sympy as sp
# declare symbols
t = sp.Symbol('t')
deriv = sp.diff((t*(sp.cos(t)))/(1-t)**2)
# Find the derivative
sp.simplify(deriv)
Is there a way to achieve the desired result?
That is the same result. Break the result you get on the "+" and you get the same thing
Looking for the "simplest" form is not a well-defined problem and sympy can't guess which form you are looking for. You can always call sp.simplify on both the result you get and the desired answer. sympy will derive the same expression for both. In your case
result = sp.simplify(deriv)
desired = sp.simplify((-2 * t * sp.cos(t))/(t - 1)**3 + (-t * sp.sin(t) + sp.cos(t))/(t - 1)**2)
# result == desired

How to implement a function with Python(Sympy), realizing the same as '_' and replacement rule in Wolfram Mathematica?

In Wolfram Mathematica, I can define named patterns where _ (called Blank) matches any expression and then use the match in a replacement rule.
An example:
testexpr = p1[MM]*p2[NN] + p1[XX]*p2[MM] + p1[XX]^2;
FunTest[expr_] := Expand[expr] /. {(p1[l1_]*p2[l2_]) -> FF1[l1]*FF2[l2],
p1[l1_]^n_ -> 0, p2[l1_]^n_ -> 0}
FunTest[testexpr]
The result is FF1[XX] FF2[MM] + FF1[MM] FF2[NN]
However, I don't know how to use sympy in Python to do the same thing.
import sympy as sp
p1 = sp.IndexedBase("p1")
p2 = sp.IndexedBase("p2")
FF1 = sp.IndexedBase("FF1")
FF2 = sp.IndexedBase("FF2")
MM,NN,XX=sp.symbols('MM NN XX')
SSlist=[MM,NN,XX]
testexpr=p1[MM]*p2[NN] + p1[XX]*p2[MM] + p1[XX]**2
def FunTest(expr):
expr=expr.subs([(p1[SS]*p2[SS2],FF1[SS]*FF2[SS2]) for SS in SSlist
for SS2 in SSlist]+[(p1[SS]**2,0) for SS in SSlist]+[(p2[SS]**2,0)
for SS in SSlist],simultaneous=True)
return expr
rest=FunTest(testexpr)
print(rest)
So the result is also FF1[MM]*FF2[NN] + FF1[XX]*FF2[MM].
But I want to know if there is an easy way to make it more general, as in Wolfram Mathematica. If SSlist is a large list and there are many different variables, it will be a difficult to implement with my solution.
I wonder whether there is an easy way without writing a loop over the whole list, for SS in SSlist, as in Mathematica. Can someone familiar with sympy give me any hints?
Thanks a lot!
I have found out one solution to my own question. It works out as I want. Instead of using subs(), I use wild operator and replace().
import sympy as sp
p1 = sp.IndexedBase("p1")
p2 = sp.IndexedBase("p2")
FF1 = sp.IndexedBase("FF1")
FF2 = sp.IndexedBase("FF2")
MM,NN,XX=sp.symbols('MM NN XX')
SSlist=[MM,NN,XX]
SS = sp.Wild('SS')
SS1 = sp.Wild('SS1')
testexpr=p1[MM]*p2[NN] + p1[XX]*p2[MM] + p1[XX]**2
replacements = {p1[SS]*p2[SS1] : FF1[SS]*FF2[SS1], p1[SS]**2: 0, p2[SS]**2 : 0}
def replaceall(expr, repls):
for i, j in repls.items():
expr = expr.replace(i, j, map=False, simultaneous=True, exact=False)
return expr
rest=replaceall(testexpr,replacements)
print(rest)
The result gives exactly the same as I did before:
FF1[MM]*FF2[NN] + FF1[XX]*FF2[MM]
One thing I want to know is this efficient when there are many symbols because of the for loop. It seems that the two methods are similar, just the one I found recently looks more concise.
I would like to know whether there is a more general way to do such things as Wolfram Mathematica does.
Any comments are welcomed. Thanks!

Error evaluating a derivative on Python (with .subs, .evalf and .lambdify)

I am trying to separately compute the elements of a Taylor expansion and did not obtain the results I was supposed to. The function to approximate is x**321, and the first three elements of that Taylor expansion around x=1 should be:
1 + 321(x-1) + 51360(x-1)**2
For some reason, the code associated with the second term is not working.
See my code below.
import sympy as sy
import numpy as np
import math
import matplotlib.pyplot as plt
x = sy.Symbol('x')
f = x**321
x0 = 1
func0 = f.diff(x,0).subs(x,x0)*((x-x0)**0/factorial(0))
print(func0)
func1 = f.diff(x,1).subs(x,x0)*((x-x0)**1/factorial(1))
print(func1)
func2 = f.diff(x,2).subs(x,x0)*((x-x0)**2/factorial(2))
print(func2)
The prints I obtain running this code are
1
321x - 321
51360*(x - 1)**2
I also used .evalf and .lambdify but the results were the same. I can't understand where the error is coming from.
f = x**321
x = sy.Symbol('x')
def fprime(x):
return sy.diff(f,x)
DerivativeOfF = sy.lambdify((x),fprime(x),"numpy")
print(DerivativeOfF(1)*((x-x0)**1/factorial(1)))
321*x - 321
I'm obviously just starting with the language, so thank you for your help.
I found a beginners guide how to Taylor expand in python. Check it out perhaps all your questions are answered there:
http://firsttimeprogrammer.blogspot.com/2015/03/taylor-series-with-python-and-sympy.html
I tested your code and it works fine. like Bazingaa pointed out in the comments it is just an issue how python saves functions internally. One could argument that for a computer it takes less RAM to save 321*x - 321 instead of 321*(x - 1)**1.
In your first output line it also gives you 1 instead of (x - 1)**0

CVXPY throws SolverError

When using CVXPY, I frequently get "SolverError". Their doc just says this is caused by numerical issues, but no further information is given about how to avoid them.
The following code snippet is an example, the problem is trivial, but the 'CVXOPT' solver just throws "SolverError". It is true that if we change the solver to another one, like 'ECOS', the problem will be solved as expected. But the point is, 'CVXOPT' should in principle solve this trivial problem and it really baffles me why it doesn't work.
import numpy as np
import cvxpy as cv
np.random.seed(0)
temp = np.random.rand(5)
T = 2
x = cv.Variable(T)
u = cv.Variable(2, T)
pbs = []
for t in range(T):
cost = cv.sum_squares(x[t]-temp[t])
constr = [x[t] == u[0,t]+u[1,t],]
pbs.append(cv.Problem(cv.Minimize(cost), constr))
prob = sum(pbs)
prob.solve(solver='CVXOPT')
Use prob.solve(solver='CVXOPT', kktsolver=cv.ROBUST_KKTSOLVER) to make the optimisation process more robust.

Sympy coeff not consistent with as_independent

I have the following snippet of code
import sympy
a = sympy.symbols('a')
b = sympy.symbols('b')
c = sympy.symbols('c')
print((a*b).coeff(c,0))
print((a*b).as_independent(c)[0])
I don't understand why the two print statements print different output. According to the documentation of coeff:
You can select terms independent of x by making n=0; in this case
expr.as_independent(x)[0] is returned (and 0 will be returned instead
of None):
>>> (3 + 2*x + 4*x**2).coeff(x, 0)
3
Is this a bug in sympy, or do I miss something?
It's a bug. I have a pull request fixing it here.

Categories

Resources