My code for a linear interpolation is functioning strangely.
n = np.linspace(t[0],t[-1],101)
print(n)
ypl = np.zeros(len(n))
def closestPoint(x,ydat):
return ydat[int(round(x))]
def linearInt(T,ydat):
t0 = round(T+0.01-1)
y0 = closestPoint(T-1,ydat)
yn = closestPoint(T,ydat)
return y0 + (yn-y0)*(T-t0)
for i in range(len(n)):
if(i != 0):
ypl[i] = linearInt(n[i],y)
pl.plot(t,y,'o')
pl.plot(n,ypl)
The variable t is an array from 0 to 10 with a stepsize of 1.
The variable y is an array of data points (same size as t).
When I run this code the interpolation runs through all of the points, and looks almost correct, except for the weird spikes. What could be causing this?
Image of the output
Related
I am trying to implement a numerical solver for a 1D Harmonic well's ground state using the Metropolis algorithm and the Feynman Path Integral technique in Python. When I run my program, I end with a distribution of the different points that my particle has gone to; this distribution ought to match up with that of a particle trapped in a 1D harmonic well. It does not. I have gone through and rewritten my code; I have checked it to similar code used for the same purpose; it all looks like it should work, yet it doesn't.
In blue is the histogram of my results, with Density set to True; the orange line is the function describing the expected distribution
As can be seen in the image, what I have ended up with is a distribution that isn't dissimilar to what I was expecting, but it isn't the correct distribution. The code I used (see below), is based on Lepage (2005) work on the same topic, although I used a slightly different formula to describe the same physical system.
import numpy as np
import random
import matplotlib.pyplot as plt
time = 4 #time over which we evolve our function
steps = 7 #number of steps we take
epsilon = 3 #the pos & neg bounds of our rand variable
N_cor = 100 #the number of times we need to thermalise our function before we take a path
N_cf = 20000 #the number of paths we take
def S(x, j, t, s): #the action of our potential well
e = t / s
return (1/(2*e))*(x[j] - x[j - 1])**2 + ((x[j] + x[j-1])/2)**2/2
def update(x, t, s, eps):
for j in range(0, s):
old_x = x[j] #old x value
old_Sj = S(x, j, t, s) #original action value
x[j] = x[j] + random.uniform(-eps,eps) #new x value
dS = S(x, j, t, s) - old_Sj #change in action
if dS > 0 and np.exp(-dS) < random.uniform(0,1): #check for Metropolis alg
x[j] = old_x
return x
def gamma(t, s, eps, thermal_num, num_paths):
zeros = np.zeros(s) #our initial path with s steps
gamma_arr = np.empty(0) #our initial empty result
for i in range(0, 10*thermal_num): #thermalisation
zeros = update(zeros, t, s, eps)
for j in range(0, num_paths):
for i in range(0, thermal_num): #thermalising again
zeros = update(zeros, t, s, eps)
gamma_arr = np.append(gamma_arr, zeros) #add new path post thermalising
#print(zeros)
#print(gamma_arr)
return gamma_arr
test = gamma(time, steps, epsilon, N_cor, N_cf)
x = np.arange(-4, 4, 0.1)
y = 1/np.sqrt(np.pi)*np.exp(-(x**2)) #expected result
plt.hist(test, bins= 500, density = True)
plt.plot(x, y)
plt.show()
I want to implement the composite Gaussian quadrature in Python to evaluate the integral ∫01 ex2 dx. Evaluting this using Python's quad command, I get ∫01 ex2 dx ≈ 1.46
Below is my attempt at implementing this in Python. What I expect is that as n gets larger, the closer the quadrature gets to the 'real' integral. However, as I vary n, the results gets smaller and smaller. What mistake am I making?
def gauss(f,a,b,n):
h = float(b-a)/n
[x,w] = np.polynomial.legendre.leggauss(n)
result = 0
for i in range(n):
result += w[i] * f(x[i])
result *= h
return result
for i in range(1,10):
print(gauss(exp,0,1,i))
2.0
1.3956124250860895
0.9711551112557443
0.731135234765899
0.5850529284514102
0.4875503086966867
0.41790049038666144
0.36566293624426005
0.32503372130693325
Here is the working code based on your attempt:
import numpy as np
def gauss(f,a,b,n):
half = float(b-a)/2.
mid = (a+b)/2.
[x,w] = np.polynomial.legendre.leggauss(n)
result = 0.
for i in range(n):
result += w[i] * f(half*x[i] + mid)
result *= half
return result
def fun(x):
return np.exp(x**2)
for i in range(1,10):
print(gauss(fun,0,1,i))
The problem was that the integral has to be rescaled to the domain of the Legendre polynomials you are using. Also, you have not used the quadrature rule correctly (it does not use the stepsize h that you have in your code.)
The correct rule is:
∫ab f(x) dx ≈ (b-a)/2 ∑i=1nwi f((b-a)/2ξi + (a+b)/2).
With this the code above outputs:
1.2840254166877414
1.4541678892391303
1.462409711477322
1.462646815656646
1.4626516680186825
1.4626517449041974
1.4626517458962964
1.4626517459070796
1.462651745907181
I am writing a code to plot several projectile trajectories of various theta values in Python.
theta = np.arange(np.pi/6, np.pi/3)
t = np.linspace(0,2,num=100)
while y0>=0:
for i in theta:
x = []
y = []
for k in t:
x0= v_0*np.cos(i)*k
y0= v_0*np.sin(i)*k - 1/2*g*(k**2)
x.append(x0)
x.append(y0)
After forming the arrays and putting in the necessary conditions for projectile, I have used a while loop to put the terminating instruction in the program. I think, I am missing a crucial point. Thanks!
I think you want your terminating condition inside your inner-most loop. See below, where I also defined a couple of missing constants (v_0, g) and fixed one x to y. also printing the results
theta = np.arange(np.pi/6, np.pi/3)
t = np.linspace(0,2,num=100)
v_0 = 1
g=10
for i in theta:
x = []
y = []
for k in t:
x0= v_0*np.cos(i)*k
y0= v_0*np.sin(i)*k - 1/2*g*(k**2)
x.append(x0)
y.append(y0)
if y0 < 0: # the main change here. Stop looping when y_0 below zero
break
print(f'theta:{i}')
print(f'x:{x}')
print(f'y:{y}')
produces
theta:0.5235987755982988
x:[0.0, 0.017495462702715934, 0.03499092540543187, 0.052486388108147805, 0.06998185081086374, 0.08747731351357968]
y:[0.0, 0.008060401999795939, 0.012039587797163551, 0.011937557392102841, 0.007754310784613805, -0.0005101520253035577]
Plotting it (y vs x), looks reasonable
It is also worth noting that your definition of theta = np.arange(np.pi/6, np.pi/3) looks rather strange, what are you trying to achieve here?
I have created code that calculates the maximum Lyapunov exponents against two parameters a and b. This plots ok, however there is a chunk of the graph that is white where the graph is collapsing due to my x and y values equalling zero. Therefore, I need to set these equal to say 100 or similar to prevent this from happening and producing a fully coloured meshgrid plot.
I have already tried if statements but I either get a syntax error or another error a.any() a.all() when I substitute one of these into my if statement it returns another error. I have tried if elif and else statements and returning values. There is an error in them statements returning
ValueError: not enough values to unpack (expected 2, got 0)
d= 0.1
eps = 0.000001
#xnew equation
def f(a,b,xold,yold):
m= a*xold*(1-b*yold)*(1-xold*(1-b*yold))
if np.any(m>eps):
return m
else:
return 50
#ynew equation
def g(b,d,xold,yold):
n= (1-d)*yold*(1+b*xold)
if np.any(n>eps):
return n
else:
return 100
#Jacobian matrix equations. A,B,C,D
def A(a,b,xold,yold):
return a*(1-2*xold- b*yold+ 4*b*xold*yold- 2*(b**2)*xold*(yold**2))
def B(b,a,xold,yold):
return a*b*xold*(2*xold- 1- 2*b*xold*yold)
def C(b,d,yold):
return (1-d)*b*yold
def D(b,d,xold):
return (1-d)*(1+b*xold)
#ml equation using ABCD
def e(a,b,xold,yold,ydash):
return (((A(a,b,xold,yold)+(B(b,a,xold,yold)*ydash))**2 +(C(a,b,yold)+(D(b,d,xold)*ydash))**2) / (1 + ydash**2))
#ydash equation using ABCD
def yz(a,b,xold,yold,ydash):
return (C(b,d,yold)+(D(b,d,xold)*ydash))/(A(a,b,xold,yold)+(B(b,a,xold,yold)*ydash))
The equations are in another cell defined as functions.
#diff values of a and b looping
a=np.linspace(0,6,80)
b=np.linspace(0,5,80)
def lyapunov(a,b):
#initial conditions
a,b = np.meshgrid(a,b)
d = 0.1
xold = 0.5
yold = 0.01
ee = 0.000001
#xnew and ynew values
for k in range(1000):
xnew=f(a,b,xold,yold)
ynew=g(b,d,xold,yold)
xold = xnew
yold = ynew
if np.any(xnew<ee) and np.any(ynew<ee):
ml = 100
return ml
elif np.any(xnew>ee) and np.any(ynew<ee):
ml = 50
return ml
else:
ml=0
for l in range(100):
ydash=1
ml = ml + np.log(abs(e(a,b,xold,yold,ydash)))
ydash = yz(a,b,xold,yold,ydash)
xold=f(a,b,xold,yold)
yold=g(b,d,xold,yold)
ml = (ml/(2*100))
return ml
z = lyapunov(a,b)
ax.set_title('Lyapunov Exponent')
c = ax.pcolormesh(z)
fig.colorbar(c)
plt.show()
I expect a completed mesh grid with no white of colour showing the system collapsing therefore very small 0 and therefore halfing the run time. At present only half the plot is coloured. ERROR is returning 'ValueError: not enough values to unpack (expected 2, got 0)
Im trying to change the rows of an array with new values in a for loop, but cannot get it to work.
Problem is related to propagation of a wave packet in quantum physics.
Ive tried using the numpy.dot() function, but that doesnt work, and i tried making an easier for loop, that works.
import numpy as np
sig = 10**(-8)
x0 = 50*10**(-9)
L = 200*10**(-9)
N = 400
Nx = 1000
x = np.linspace(x0, L, N)
expsig = np.exp(-((1/2)*(x-x0)**2)/(sig**2))
expimg = np.exp(1j*(x-x0))
Phi = (1/(np.pi**(1/4)*np.sqrt(sig))*expsig*expimg)
Boxfunc = np.zeros(shape = (N, Nx))
for i in range(0, N):
SINnpi = np.sin(((i*np.pi)/L)*x)
Boxfunc[i,:] = np.sqrt(2/L)*SINnpi
Y = Boxfunc[i,:]*Phi
I expect the output to be a 400x1000 array with new calculated values from the multiplication between Phi and Boxfunc.
I just get the error message "could not broadcast input array from shape (400) into shape (1000)" when i get to the Boxfunc in the for-loop.
There is a problem with array x, it should be x = np.linspace(x0, L, Nx), then your code works.
Or you can define Boxfunc = np.zeros(shape = (Nx, N)). The problem is from the shape between x and Boxfunc.