Using scipy to integrate a function? - python

I am trying to use SciPy to integrate this function:
y(x) = (e^-ax)*cos(x) between 0 and 4pi.
Here is the code I have so far:
from numpy import *
from scipy.integrate import simps
a = 0
x = linspace(0 , 4*pi, 100)
y = (e^-(a*x))*cos(x)
integral_value = simps(y,x)
print integral_value
However it doesn't seem to be working. Any help would be appreciated, thanks!

Well if you run the program you obtain the following error:
TypeError: ufunc 'bitwise_xor' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
So you know the problem is with the ^ (bitwise xor) in your function. In Python one uses ** to take the exponent.
If one writes:
y = (e**-(a*x))*cos(x)
instead, one gets:
>>> print integral_value
-0.000170200006112
The full program:
from numpy import *
from scipy.integrate import simps
a = 0
x = linspace(0 , 4*pi, 100)
y = (e**-(a*x))*cos(x)
integral_value = simps(y,x)
print integral_value
You can also make explicit use of numpy functions with:
from numpy import *
from scipy.integrate import simps
a = 0
x = linspace(0 , 4*pi, 100)
y = exp(-a*x)*cos(x)
integral_value = simps(y,x)
print integral_value
In order to increase the precision, you can increase the number of points (100 is not that much).

import numpy as np
import math
from scipy.integrate import simps
a = 0
x = np.linspace(0 , 4*math.pi, 100)
#create a vectorized function which can be applied directly to an array
fn = np.vectorize(lambda x: math.exp(-a*x)*math.cos(x))
y = fn(x)
integral_value = simps(y, x)
print integral_value
this indeed yields value of -0.000170200006112. Note that for a=0, the integral is equal to zero, so in order to get "closer" you would need to refine the grid...

Cracking a nut with a sledgehammer ...
>>> from sympy import *
>>> var('a x')
(a, x)
>>> y = exp(-a*x)*cos(x)
>>> y.subs(a,0)
cos(x)
Should it surprise any of us to find that this integrates to 0 (zero) over the given interval?

Related

Sympy dsolve with plots

I am solving an ODE with Sympy. The equation is
ODE
To solve it, I used this little code, which returns this result.
from sympy import *
from numpy import *
import matplotlib.pyplot as plt
x = symbols('x')
y = Function('y')
f = y(x)
print(f)
edo = Eq(f.diff()+3*x**2*f, 6*x**2)
print(edo)
edoSolve = dsolve(edo, f)
print(edoSolve)
C1*exp(-x**3) + 2
My question is, how can I plot the result with x being a range from 0 to 10?
Firstly it's problematic to combine these two lines:
from sympy import *
from numpy import *
These two libraries define many functions with the same names and mixing those together will lead to problems. For clarity it is better to do something like:
import sympy as sym
import numpy as np
You can only plot a sympy expression if you give numbers for all of the symbols apart from the one that you want to plot against (i.e. x in this example). That means that you need to have a concrete value for the integration constant C1. You can get that by giving an initial conditions (ics) argument to dsolve. Also since dsolve returns an equation you need to choose a side of the equation as the expression that you want to plot. Having done that the sym.plot function will do precisely what you ask for:
In [10]: import sympy as sym
In [11]: sol = sym.dsolve(edo, f, ics={f.subs(x, 0): 1})
In [12]: sol
Out[12]:
3
-x
y(x) = 2 - ℯ
In [13]: sym.plot(sol.rhs, (x, 0, 10))
Out[13]: <sympy.plotting.plot.Plot at 0x7f346de1caf0>
If you want to show solutions for multiple values for C1 together, you could append plots:
from sympy import symbols, Function, Eq, dsolve, plot
x = symbols('x')
y = Function('y')
f = y(x)
edo = Eq(f.diff() + 3 * x ** 2 * f, 6 * x ** 2)
edoSolve = dsolve(edo, f)
plot1 = plot(show=False)
for c1 in range(-5, 6):
plotc1 = plot(edoSolve.subs('C1', c1).rhs, (x, 0, 10), show=False)
plot1.append(plotc1[0])
plot1.show()

How to Insert an Array of Values to a Symbolic Function in Python

I want to study symbolic functions in python. I want to create y(x) = x^2 + 2x + 3 and plot it in the range [1, 255]. I want to use the subs() function to calculate the values by using the for loop. However, when I run that I get this error:
IndexError('list index out of range')
Can you help me please?
import numpy as np
import matplotlib.pyplot as plot
from sympy import *
a = [1,2,3]
x = Symbol('x')
fx = a[0]*x**2 + a[1]*x + a[2]
t = list(range(1,256))
y = np.zeros(256)
for i in t:
y[i] = fx.subs({x:t[i]})
plot.plot(t,y)
plot.show()
Just replace with the following lines:
y = np.zeros(len(t))
for i in range(len(t)):
y[i] = fx.subs({x:t[i]})
The problem was that the length of t was only 255 but the len of y was 256 in your code because you define y = np.zeros(256), hence the Index Error because there is no t[256]. I am using y = np.zeros(len(t)) because you have as many y points as t (or x) points. By the way, you are most likely to get an error in your plot command the way it is right now because you have called import matplotlib.pyplot as plot. I would simply call it plt instead of plot
Output

ask for help for a sum (sigma) function

need help to calculate this:
so, the total number of y is equal to number of x, and each y is calculated with one x and several a.
My code list below, it gives the correct results for a0. what is a simple way to calculate this? maybe a different version can also verify the results.
Thanks a lot.
import numpy as np
import matplotlib.pyplot as plt
a = np.array([1,2,3,4],float) # here we can give several a
b = np.asarray(list(enumerate(a)))
x = np.linspace(0.0,1.0,10)
y1 = []
for r in x:
y1.append(np.exp(np.sum((1-r)**2*a*((2*b[:,0]+1)*r-1+r)*(r-1+r)**(b[:,0]-1))))
y1=np.asarray(y1)
You can write almost literally the same in numpy:
def f(x, a):
x, a = np.asanyarray(x), np.asanyarray(a)
x = x[:, None] # create new dimension to sum along
i = np.arange(len(a)) # create counter
return np.sum((1-x)**2 * a * ((2*i + 1) * x - (1-x)) * (x - (1-x))**(i-1), axis=-1)
As a side note: there are obvious algebraic simplifications you could take advantage of.

Find an Inverse for the Exponential Integral function

I have a program where I have to find x.
But I have to use the special function Ei - the exponential integral, and x is inside the argument of Ei.
So Python isn't recognizing it.
ei(mx) = te^r + ei(c)
Here the RHS is a constant alongwith m.
I want to find the value of x, and then append it to a list. But Python isn't able to do this.
from scipy import special
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
Y = []
X = np.arange(0,10,.1)
for i in X:
y = scipy.special.expi(i)
Y.append(y)
N_0 = 2
t_f = 100
r = 2
K = 100
N_t = [N_0,]
t = np.arange(0,100,1)
for i in t:
l = i*e**r + scipy.special.expi(r*N_t[i]/K)
N_t.append(l)
plt.plot(X,Y)
plt.plot(t,N_t)
plt.show
I've corrected some mistakes in your code to give the following. You should compare this with your code line by line.
from scipy.special import expi
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
Y = []
X = np.arange(0,10,.1)
for i in X:
y = expi(i)
Y.append(y)
N_0 = 2
t_f = 100
r = 2
K = 100
N_t = [N_0,]
t = np.arange(0,100,1)
for i in t:
l = i*np.exp(r) + expi(r*N_t[i]/K)
N_t.append(l)
plt.plot(X,Y)
plt.plot(t,N_t)
plt.show()
However, there is still one possible flaw that I notice and can't resolve. You plot X and t together in the same graph at the end yet X ranges over 0 to 10 and t ranges over 0 to 100. Is this what you intended?
Also matplotlib complains that the lengths of the vectors supplied to it in the second call to plot are not the same.

Python -- sympy solve() returning another equation instead of value

This creates a list of points and the sympy solve() method should be returning the value of x. Instead it's returning yet another equation, and I'm not sure why. The ogrid() and ravel() are creating a list of points in the plot and this is on Matplotlib, if that makes a difference but I don't think it should. It should be finding root(s) of the equation. I'm not sure what I'm doing wrong here that causes it to not return a value, but instead returns another equation:
from mpl_toolkits.axes_grid.axislines import SubplotZero
from pylab import *
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
from matplotlib import rc
import random
from sympy.solvers import solve
from sympy import *
a = -2; b = 1
y, x = np.ogrid[-10:10:100j, -10:10:100j]
xlist = x.ravel(); ylist = y.ravel()
elliptic_curve = pow(y, 2) - pow(x, 3) - x * a - b
plt.contour(xlist, ylist, elliptic_curve, [0])
randmid = random.randint(30,70)
#y = ylist[randmid]; x = xlist[randmid]
xsym, ysym = symbols('x ylist[randmid]')
x_result = solve(pow(ysym, 2) - pow(xsym, 3) - xsym * a - b, xsym) # 11/5/13 needs to return a value
I'm teaching myself Python so this is probably something a junior programmer can help me out with, but if a pro sees this and can spare a moment to help that'd be great.
EDIT:
Returns a value for y roughly 3.xx where there's not 3 possible x-values:
x_result is a list of expressions, which is the solutions of your equation. It's not a list of value because ysym is a symbol. If you want the numeric results, you need call subs() and evalf():
[e.subs({ysym:ylist[randmid]}).evalf() for e in x_result]
output:
[0.0871073310916539 - 8.0e-17*I,
1.36864647418387 + 4.37e-17*I,
-1.45575380527552 + 3.63e-17*I]

Categories

Resources