I need to obtain a derivative to use it later in numerical calculations. And my code doesn't work at all. I tried to use lambdify but the error is "can't convert symbols int". I read other answers for similar questions but it still doesn't work.
import numpy as np
from scipy.integrate import odeint
from scipy.integrate import quad
from scipy.integrate import solve_bvp as bvp
import matplotlib.pyplot as plt
from scipy.special import genlaguerre as L
from scipy.special import gamma as G
from math import factorial
from math import sqrt
import sympy as sym
from sympy.utilities.lambdify import lambdify
mp = 938.2720813
mn = 939.5654133
mu = (mn + mp)/4
hbar = 197.3270533
h2m = hbar**2/(2*mu)
V0 = 20
Rv = 1.5
Q0 = 1.5
Rq = 4.5
EIm = 0.3
ERe = 1
V = lambda r : -V0*np.exp(-r/Rv)
Q = lambda r : -Q0*np.exp(-r/Rq)
chi = lambda r, l : sqrt(factorial(l)*beta**3/(G(3 + l))) * r * L(l,2)(beta * r) * np.exp(- beta * r / 2)
r, l, beta = sym.symbols('r, l, beta')
def chifD(r, l, beta):
return sqrt(factorial(l)*beta**3/(G(3 + l))) * r * L(l,2)(beta * r) * np.exp(- beta * r / 2)
def chiD(r, l, beta):
return sym.diff(chifD(r ,l, beta), r)
print(chiD(r, l, beta))
chiLambdified = lambdify(((r,l, beta),),chiD(r,l, beta),"numpy")
print(chiD(1, 1, 1))
I'm pretty sure you're mixing modules you shouldn't. I kept modifying your chi function until I got something that works. Nothing short of removing all math and scipy functions returned something that wasn't a TypeError.
# works with sympy sqrt.
chi = lambda r, l : sym.sqrt(l*r)
print(chi(r,l))
# doesn't work with math or numpy sqrt.
chi = lambda r, l : math.sqrt(l*r)
print(chi(r,l))
If you want to use functions, you'll have to use the ones that come with sympy, define your own using basic operators (so that sympy objects will be accepted) or find simpler ways to define your operations: sqrt() can simply be substituted by **(1/2).
Maybe you should look for a way that can make sympy accept functions from other modules because writing all of the special functions from scipy yourself looks like it will be a pain.
Related
I try to solve an equation with solve from Sympy. But my approach doesn't work as desired.
My equation : 0.00622765954483725 = (x * 24.39 * 0.921107170819325) / 143860432.178345.
My code :
from sympy import symbols, solve
import numpy as np
x = symbols('x')
sol = solve((np.array([[x],[x]]) * np.array([[24.39],[293.6]]) * np.array([[0.921107170819325],[1]])) / np.array([[143860432.178345],[143860432.178345]]) - np.array([[0.00622765954483725],[0.0089267519953503]]))
I had success with a linear expression, but I have a DataFrame and I want to solve all data at the same time.
from sympy import symbols, solve
x = symbols('x')
sol = solve((x * 24.39 * 0.921107170819325) / 143860432.178345 - 0.00622765954483725)
Numpy doesn't understand about sympy's symbols, nor does sympy understand about numpy arrays. The only way to make them work together, is with sympy's lambdify which can convert a symbolic sympy expression to a numpy function. In your case, you first need to create a symbolic solution, lambdify it, and call it on your arrays:
from sympy import symbols, solve, Eq, lambdify
a, b, c, d = symbols('a b c d', real=True)
x = symbols('x')
sol = solve(Eq(x * a * b / c, d), x) # solve returns a list of solutions, in this case a list with just one element
np_sol = lambdify((a, b, c, d), sol[0]) # convert the first solution to a (numpy) function
# everything before is only sympy, everything from here is only numpy
import numpy as np
a_np = np.array([[24.39], [293.6]])
b_np = np.array([[0.921107170819325], [1]])
c_np = np.array([[143860432.178345], [143860432.178345]])
d_np = np.array([[0.00622765954483725], [0.0089267519953503]])
np_sol(a_np, b_np, c_np, d_np)
Result:
array([[39879.],
[ 4374.]])
I would like to solve the (x+1)e^x=c equation in Python.
The equation has been successfully solved by hand using lambert w functions as depicted in the figure below:
Using same steps, I would like to solve (x+1)e^x programmatically. I have coded it using the module SymPy as per the step shown in the figure above , but without success.
Is there any to solve these kinds of equations in Python?
import numpy as np
from sympy import *
n = symbols('n')
sigmao=0.06866
sigmas=0.142038295
theta=38.9
rad=(np.pi/180)*38.9076
cos=np.cos(rad)
sec=1/np.cos(rad)
out = (0.06*0.7781598455*n*(1-exp(-2*0.42*sec*n))+exp(-2*0.42*n*sec)*sigmas)/sigmao
#Apply diff for the above expression.
fin=diff(out, n)
print(solve(fin,n))
from scipy.optimize import fsolve
import numpy as np
const = 20
def func(x):
return [(x[0]+1) * np.exp(x[0]) - const]
result = fsolve(func, [1])[0]
print('constant: ', const, ', solution: ', result)
#check
print('check: ', (result+1) * np.exp(result))
#Output[]:
constant: 20.0 , solution: 1.9230907433218063
check: 20.0
Preview : https://onlinegdb.com/By8Z2Jwgw
Your expression is very numeric. As sympy's solve tries to find a perfect symbolic solution, sympy gets into troubles.
To find numeric solutions, sympy has nsolve (which allows sympy's expressions but behind the scenes calls mpmath's numeric solver). Unlike solve, here an initial guess is needed:
from sympy import symbols, exp, diff, nsolve, pi, cos
n = symbols('n')
sigmao = 0.06866
sigmas = 0.142038295
theta = 38.9076
rad = (pi / 180) * theta
sec = 1 / cos(rad)
out = (0.06 * 0.7781598455 * n * (1 - exp(-2 * 0.42 * sec * n)) + exp(-2 * 0.42 * n * sec) * sigmas) / sigmao
# Apply diff for the above expression.
fin = diff(out, n)
result = nsolve(fin, n, 1)
print(result, fin.subs(n, result).evalf())
Result: 1.05992379637846 -7.28565300819065e-17
Note that when working with numeric values, you should be very careful to use as many digits as possible to avoid accumulation of errors. Whenever you have an exact expression, it is recommended to leave that expression into the code, instead of replacing it with digits. (Usually, 64 bits or about 16 digits are used in calculations, but for intermediate calculations 80 bits can be taken into account).
To solve the original question with sympy:
from sympy import symbols, Eq, exp, solve
x = symbols('x')
solutions = solve(Eq((x + 1) * exp(x), 20))
for s in solutions:
print(s.evalf())
Result: 1.92309074332181
I'm comparing the results of convolution in Python (using sympy's symbolic variables) and Mathematica with its Convolve function.
In Python, my MWE is
from numpy import linspace, pi
from numpy.random import randn
from scipy.signal import fftconvolve
import matplotlib.pyplot as plt
from sympy import symbols
from sympy.utilities.lambdify import lambdify
a = 0.43
b = 0.41
c = 0.65
d = 0.71
x = symbols('x')
f = 2*b / ((x-a)**2 + b**2)
g = 2*d / ((x-c)**2 + d**2)
fog = fftconvolve(f,g,mode='same')
fog_fun = lambdify(x,fog,'numpy') # returns a numpy-ready function
x = linspace(-20,20,int(1e3))
dx = x[1]-x[0]
fogS = fog_fun(x)
fogA = 4*pi*(b+d)/((x-a-c)**2+(b+d)**2) # correct analytic solution
plt.figure()
plt.plot(x,fogA,lw=2,label='analytic')
plt.plot(x,fogS,lw=2,label='sympy')
plt.grid()
plt.legend(loc='best')
plt.show()
which calculates a convolution using symbolic variable x. The resulting function (before lambdifying) is
fog = 1.1644/(((x - 0.65)**2 + 0.5041)*((x - 0.43)**2 + 0.1681))
There is no agreement between analytic (fogA, Mathematica) and sympy (fogS, Python):
My Mathematica code is:
a = 0.43; b = 0.41; c = 0.65; d = 0.71;
fogA = FullSimplify[Convolve[2*b/((t-a)^2+b^2),2*d/((t-c)^2+d^2), t, x]];
fogS = 1.1644/(((x - 0.65)^2 + 0.5041)*((x - 0.43)^2 + 0.1681));
where
fogA = (17.683+x*(-30.4006+14.0743*x))/(3.04149+x*(-7.9428+x*(8.3428+x*(-4.32+1.*x))))
and graphs for fogS and fogA are the same as for Python.
Why is there such a large disagreement between the analytic and sympy solution? I suspect the problem lies with sympy. Another Pythonic method is to convolve two arrays which seems to agree with the analytic solution.
f = 2*b / ((x-a)**2 + b**2)
g = 2*d / ((x-c)**2 + d**2)
fogN = fftconvolve(f,g,mode='same')*dx # numeric
(Note: this is a MWE. The actual f and g I want to convolve are much more complicated than the Lorentzians defined in this post.)
I do not think this is a reasonable way of using scipy + sympy.
I am actually quite surprised that you get a result from lambdify at all.
What you should be doing, instead of using scipy.signal.fftconvolve(), is to use a symbolic definition of the convolution, e.g.:
from sympy import oo, Symbol, integrate
def convolve(f, g, t, lower=-oo, upper=oo):
tau = Symbol('__very_unlikely_name__', real=True)
return integrate(
f.subs(t, tau) * g.subs(t, t - tau), (tau, lower, upper))
adapted from here.
I am trying to integrate a definite integral with respect to dE for a function that depends on E and x, x being another parameter that I will use later. I defined a function of x that could help me with this, but it does not seem to work. When I give the new function a certain value--such as 1 or 10--it always returns 0. Here is my code:
%matplotlib inline
import matplotlib.pyplot as plt
from scipy.integrate import quad
import numpy as np
from numpy import pi
from numpy import arange
gg=100.0
ms=100.0
def integrand(E, xx):
return (gg/2*pi)*E*(E**2-ms**2)**(1/2)/(np.exp(E*xx*ms)-1)
def nn(x):
return quad(integrand, ms, np.inf, args=(x)) ## quad(funcion, lim inf, lim sup, args)
What I need is to be able to later call the function nn with the parameter x being the variable.
You could simply define all the values outside of the function:
from scipy.integrate import quad
import numpy as np
from numpy import pi
gg = 100.0
ms = 100.0
xx = 5.0
ms = 1.0
def integrand(E):
return (gg / 2 * pi) * E * (E ** 2 - ms ** 2) ** (1 / 2) / (np.exp(E * xx * ms) - 1)
val, err = quad(integrand, ms, np.inf)
print(val)
0.16712443596152543
This code only works for solving the differential equation v_equation if v(t) isn't squared. When I squared it it returned the error PolynomialDivisionFailed. Is there another way of doing this with Sympy or should I find a different python package for doing these sorts of calculations.
from sympy import *
from matplotlib import pyplot as plt
import numpy as np
m = float(raw_input('Mass:\n> '))
g = 9.8
k = float(raw_input('Drag Coefficient:\n> '))
f1 = g * m
t = Symbol('t')
v = Function('v')
v_equation = dsolve(f1 - k * (v(t) ** 2) - m * Derivative(v(t)), 0)
C1 = Symbol('C1')
C1_ic = solve(v_equation.rhs.subs({t:0}),C1)[0]
v_equation = v_equation.subs({C1:C1_ic})
func = lambdify(t, v_equation.rhs,'numpy')
From my experience with symbolic math packages, I would not recommend performing (symbolic) calculations using floating point constants. It is better to define equations using symbolic constants, perform calculations as far as possible, and then substitute with numerical values.
With this approach, Sympy can provide a solution for this D.E.
First, define symbolic constants. To aid calculations, note that we can provide additional information about these constants (e.g., real, positive, e.t.c)
import sympy as sp
t = sp.symbols('t', real = True)
g, k, m = sp.symbols('g, k, m', real = True, positive = True)
v = sp.Function('v')
The symbolic solution for the DE can be obtained as follows
f1 = g * m
eq = f1 - k * (v(t) ** 2) - m * sp.Derivative(v(t))
sol = sp.dsolve(eq,v(t)).simplify()
The solution sol will be a function of k, m, g, and a constant C1. In general, there will be two, complex C1 values corresponding to the initial condition. However, both values of C1 result in the same (real-valued) solution when substituted in sol.
Note that if you don't need a symbolic solution, a numerical ODE solver, such as Scipy's odeint, may be used. The code would be the following (for an initial condition 0):
from scipy.integrate import odeint
def fun(v, t, m, k, g):
return (g*m - k*v**2)/m
tn = np.linspace(0, 10, 101)
soln = odeint(fun, 0, tn, args=(1000, 0.2, 9.8))
soln is an array of samples v(t) corresponding to the tn elements