I have written the following code for a chemical reaction kinetics assignment. The problem actually involves rabbits being born and leaving a farm instead of reactions. I'm asked to develop an Explicit Euler method program to model the rabbit population.
My program was running fine (i.e. I wasn't receiving any errors but wasn't getting the results I wanted) until just recently where I've been getting the ValueError (ValueError: setting an array element with a sequence.) message. I'm unsure of what I did to my code to prompt the error.
Any help would be appreciated.
def explicit_euler(df, x0, h, n):
# df - ODE that you wish to solve numerically
# x0 - initials values for ODE
# h - step size
# n - number of steps
for i in range(0, len(x0)):
N = np.zeros((len(x0), n))
t = 0
N[i, 0] = x0[i]
for j in range(0, n - 1):
N[i, j + 1] = N[i, j] + h * df(t, N[i, j])
t += h
return N
def df(t, N):
return [(k2 - k5) * t * N,
(k3 - k4) * t * N,
(k1 - k2 - k3 - (k6 * N)) * t * N]
N0 = [2., 10., 0.] # initial number of rabbits [Male, Female, Baby]
# "Reaction rate" coefficients
k1 = 3.5 # [events/rabbits month]
k2 = k3 = 0.15 # [events/rabbits month]
k4 = 0.1 # [events/rabbits month]
k5 = 0.5 # [events/rabbits month]
k6 = 0.1 # [events/rabbits^2 month]
h = 1 # time steps [month]
tspan = 120 # length of time [month]
n = int(tspan / h) # number of time steps
N = explicit_euler(df, N0, h, n)
t = np.linspace(0, tspan, n)
plot1, = plt.plot(t, N[0, :])
plot2, = plt.plot(t, N[1, :])
plot3, = plt.plot(t, N[2, :])
plt.xlabel('Time [months]')
plt.ylabel('Rabbits')
plt.legend((plot1, plot2, plot3), ('Male', 'Female', 'Babies'))
plt.show()
print(N)
EDIT: Forgot to include the error traceback.
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-d31ce8d859bf> in <module>()
39 n = int(tspan / h) # number of time steps
40
---> 41 N = explicit_euler(df, N0, h, n)
42 t = np.linspace(0, tspan, n)
43
<ipython-input-4-d31ce8d859bf> in explicit_euler(df, x0, h, n)
14 for j in range(0, n - 1):
15
---> 16 N[i, j + 1] = N[i, j] + h * df(t, N[i, j])
17 t += h
18
ValueError: setting an array element with a sequence.
Related
I am trying to write an algorithm for simulating the steady flow in a windtunnel around a rectangle. I based my code heavily on the beam.py code in the book 'A survey of computational physics' by Landau.
The code in the book is the following:
import matplotlib.pylab as p;
from mpl_toolkits.mplot3d import Axes3D ;
from numpy import *;
import numpy;
print( "Working, look for figure window after 100 iterations")
Nxmax = 70; Nymax = 20; IL = 10; H = 8; T = 8; h = 1.
u = zeros( (Nxmax + 1, Nymax + 1), float) # Stream
w = zeros( (Nxmax + 1, Nymax + 1), float) # Vorticity
V0 = 1.0; omega = 0.1; nu = 1.; iter = 0; R = V0*h/nu # Renold #
def borders(): # Method borders: init & B.C
for i in range(0, Nxmax + 1): # Initialize stream function
for j in range(0, Nymax + 1 ): # And vorticity
w[i, j] = 0.
u[i, j] = j * V0
for i in range(0, Nxmax + 1 ): # Fluid surface
u[i, Nymax] = u[i, Nymax - 1] + V0 * h
w[i, Nymax - 1] = 0.
for j in range(0, Nymax + 1 ):
u[1, j] = u[0, j]
w[0, j] = 0. # Inlet
for i in range(0, Nxmax + 1 ): # Centerline
if i <= IL and i>= IL + T:
u[i, 0] = 0.
w[i, 0] = 0.
for j in range(1, Nymax ): # Outlet
w[Nxmax, j] = w[Nxmax - 1, j]
u[Nxmax, j] = u[Nxmax - 1, j] # Boundary conditions
def beam(): # Method beam; BC for beam
for j in range (0, H + 1): # Beam sides
w[IL, j] = - 2 * u[IL - 1, j]/(h*h) # Front side
w[IL + T, j] = - 2 * u[IL + T + 1, j]/(h*h) # Back side
for i in range(IL, IL + T + 1): w[i, H - 1] = - 2 * u[i, H]/(h*h);
for i in range(IL, IL + T + 1 ):
for j in range(0, H + 1):
u[IL, j] = 0. # Front
u[IL+T, j] = 0. # Back
u[i, H] = 0; # top
def relax(): # Method to relax stream
beam() # Reset conditions at beam
for i in range(1, Nxmax): # Relax stream function
for j in range (1, Nymax):
r1 = omega*((u[i+1,j]+u[i-1,j]+u[i,j+1]+u[i,j-1] + h*h*w[i,j])*0.25-u[i,j])
u[i, j] += r1
for i in range(1, Nxmax): # Relax vorticity
for j in range(1, Nymax):
a1 = w[i+1, j] + w[i-1,j] + w[i,j+1] + w[i,j-1]
a2 = (u[i,j+1] - u[i,j-1])*(w[i+1,j] - w[i - 1, j])
a3 = (u[i+1,j] - u[i-1,j])*(w[i,j+1] - w[i, j - 1])
r2 = omega *( (a1 - (R/4.)*(a2 - a3) )/4.0 - w[i,j])
w[i, j] += r2
borders()
while (iter <= 100):
iter += 1
if iter%10 == 0: print (iter)
relax()
for i in range (0, Nxmax + 1):
for j in range(0, Nymax + 1 ): u[i, j] = u[i, j]/(V0*h) # V0h units
x = range(0, Nxmax - 1); y = range(0, Nymax - 1) # returns stream flow to plot
# for several iterations
X, Y = p.meshgrid(x, y)
def functz(u): # Return transform
Z = u[X, Y]
return Z
Z = functz(u) # here the function is called
fig = p.figure() # creates the figure
ax = Axes3D(fig) # plots the axis for the figure
ax.plot_wireframe(X, Y, Z, color = 'r') # surface of wireframe in red
ax.set_xlabel('X') # label the three axes
ax.set_ylabel('Y')
ax.set_zlabel('Stream Function')
p.show()
I discovered that if I increase the value of V_0 above 2 or 3 then I get a RuntimeWarning: invalid value encountered in double_scalars error when r1 and r2 are calculated.
I want to simulate with much larger velocities and I couldn't find a way to fix this problem. I don't really understand why it is even an error when there are no divisions by really small numbers, close to 0.
Can anyone help me out and spot the problem?
Thanks in advance
I tried to look up the answer but only found special scipy libraries for certain operators but in this code none of them could be used.
I am trying to show the monte carlo barrier prices for different number of simultations in the x axis. This is what i tried so far but i'm getting the error -> ValueError: x and y must have same first dimension, but have shapes (10,) and (5,).
I am new to python and as hard as i try i cannot find the error
import numpy as np
import numpy.random as npr
import matplotlib.pyplot as plt
def mc_single_barrier_do(S0, K, T, H, r, vol, N, M):
# Constants
dt = T / N # change in time
nudt = (r - 0.5 * vol ** 2) * dt # deterministic component
volsdt = vol * np.sqrt(dt) # diffusion coefficient
erdt = np.exp(r * dt) # discount factor
# Standard Error Placeholders
sum_CT = 0
sum_CT2 = 0
# Monte Carlo Method
for i in range(M):
# Barrier Crossed Flag
BARRIER = False
St = S0
for j in range(N):
epsilon = np.random.normal()
Stn = St * np.exp(nudt + volsdt * epsilon)
St = Stn
Ptn = np.exp(-2. * (H - St) * (H - Stn) / (St ** 2. * volsdt ** 2.))
Pt = Ptn
if Pt >= npr.uniform():
BARRIER = True
if np.amin(St) > H and BARRIER == False:
CT = np.maximum(St - K, 0)
else:
CT = 0.
sum_CT = sum_CT + CT
sum_CT2 = sum_CT2 + CT * CT
C0_MC = np.exp(-r * T) * sum_CT / M
return C0_MC
def sim_iterator(max_sample, N, S0, T, r, vol, K, H, method):
assert (method in ['MC', 'AV', 'CV'])
mean_payoffs = np.zeros(int(np.ceil(max_sample / 10)))
if method == 'MC':
for n_sample in range(10, max_sample + 1, 10):
payoffs = mc_single_barrier_do(n_sample, S0, K, T, H, r, vol, N)
mean_payoffs[int(n_sample / 10 - 1)] = np.mean(payoffs)
return mean_payoffs
r = 0.1
vol = 0.2
T = 2
N = 20
dt = T / N
S0 = 50
K = 50
H = 45
max_sample = 100
MC_price_estimates = sim_iterator(S0, T, r, vol, K, H, max_sample, N, method='MC')
x_axis1 = range(10, max_sample + 1, 10)
plt.plot(x_axis1, MC_price_estimates)
plt.xlabel("No. of Simulations")
plt.ylabel("Estimated option price")
plt.title("Ordinary Monte Carlo Method")
plt.legend()
plt.show()
in your function definition you used:
def sim_iterator(max_sample, N, S0, T, r, vol, K, H, method):
while when using the function you used:
MC_price_estimates = sim_iterator(S0, T, r, vol, K, H, max_sample, N, method='MC')
python has positional arguments, which means the arguments are mapped according to their position, not their name, so in the first position is mapped to the first argument, which means S0 in the second line was mapped to max_sample in the first line, just fix the arguments arrangement, or use keyword arguments S0=S0.
MC_price_estimates = sim_iterator(S0=S0, T=T, r=r, vol=vol, K=K, H=H, max_sample=max_sample, N=N, method='MC')
this is what your code will look like when you fix all arguments to be keyword arguments.
def mc_single_barrier_do(S0, K, T, H, r, vol, N, M):
# Constants
dt = T / N # change in time
nudt = (r - 0.5 * vol ** 2) * dt # deterministic component
volsdt = vol * np.sqrt(dt) # diffusion coefficient
erdt = np.exp(r * dt) # discount factor
# Standard Error Placeholders
sum_CT = 0
sum_CT2 = 0
# Monte Carlo Method
for i in range(M):
# Barrier Crossed Flag
BARRIER = False
St = S0
for j in range(N):
epsilon = np.random.normal()
Stn = St * np.exp(nudt + volsdt * epsilon)
St = Stn
Ptn = np.exp(-2. * (H - St) * (H - Stn) / (St ** 2. * volsdt ** 2.))
Pt = Ptn
if Pt >= npr.uniform():
BARRIER = True
if np.amin(St) > H and BARRIER == False:
CT = np.maximum(St - K, 0)
else:
CT = 0.
sum_CT = sum_CT + CT
sum_CT2 = sum_CT2 + CT * CT
C0_MC = np.exp(-r * T) * sum_CT / M
return C0_MC
def sim_iterator(max_sample, N, S0, T, r, vol, K, H, method):
assert (method in ['MC', 'AV', 'CV'])
mean_payoffs = np.zeros(int(np.ceil(max_sample / 10)))
if method == 'MC':
for n_sample in range(10, max_sample + 1, 10):
payoffs = mc_single_barrier_do(M=n_sample,S0= S0, K=K, T=T, H=H, r=r, vol=vol, N=N)
mean_payoffs[int(n_sample / 10 - 1)] = np.mean(payoffs)
return mean_payoffs
r = 0.1
vol = 0.2
T = 2
N = 20
dt = T / N
S0 = 50
K = 50
H = 45
max_sample = 100
MC_price_estimates = sim_iterator(S0=S0, T=T, r=r, vol=vol, K=K, H=H, max_sample=max_sample, N=N, method='MC')
x_axis1 = range(10, max_sample + 1, 10)
plt.plot(x_axis1, MC_price_estimates)
plt.xlabel("No. of Simulations")
plt.ylabel("Estimated option price")
plt.title("Ordinary Monte Carlo Method")
plt.legend()
plt.show()
I was making Baysien model Type-II to finding the maximum likelihood to estimate “most probable” values for hyper-parameters. After I try to run the code below I got some of error that shown in compute_posterior function. It might be something wrong with the shape.
def compute_posterior(PHI, t, alph, s2):
M = PHI.shape[1]
beta = 1/s2
H = beta*(PHI.T # PHI) + alph*np.eye(M)
SIGMA = np.linalg.inv(H)
Mu = beta * (SIGMA # (PHI.T # t))
#
return Mu, SIGMA
# Marginal log likelihood
#
# Version 1 Log Marginal (ideal)
#
def compute_log_marginal(PHI, t, alph, s2):
#
# Exploit the shape of C and the fact that M < N (usually)
#
N, M = PHI.shape
beta = 1 / s2
Mu, SIGMA = compute_posterior(PHI, t, alph, s2)
#
# Constant factor
#
logML = -N * np.log(2 * np.pi)
#
# log determinant factor (log|C|)
#
# If SIGMA becomes singular, sgn<0
#
sgn, logdet = np.linalg.slogdet(SIGMA)
#
if sgn < 0:
print("Error with alpha={0}, s2={1}".format(alph, s2))
raise np.linalg.LinAlgError("logdet sign is negative - something is wrong!")
#
logML += logdet + N*np.log(beta) + M*np.log(alph)
#
# data term (t'Ct)
#
logML -= beta * (t.T # (t - PHI # Mu))
#
logML = logML / 2.0
#
return logML
log_alph = np.linspace(-3, 6, n)
log_s2 = np.linspace(-4, 4, n)
x = df.values[:, 0:8]
t = df.values[:, 8]
n = 100
Z = np.empty((n, n))
Z_max = []
al = []
rr = []
for i, a in enumerate(log_alph):
for j, r in enumerate(log_s2):
Z[i, j] = compute_log_marginal(x,t,log_alph,log_s2)
Z_max.append(Z[i, j])
maximum = max(Z_max)
print(maximum)
# if Z[i, j] == -11.627510277032485:
# al.append(a)
# rr.append(r)
# maximum = max(Z_max)
# print(al)
# print(rr)
# print(maximum)
# maximum = -11.627510277032485
plt.contourf(log_a, log_r, Z.T)
print('The maximum point is:',maximum )
print('The max log_alpha is:',al[0] )
print('The max log_r is:',rr[0] )
plt.xlabel('log alpha')
plt.ylabel('log r')
plt.title('Contour of log alpha and log r')
After I compile I got this error, I still don't know how to figure it out
'
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-260-c7f0396b4046> in <module>
14 for i, a in enumerate(log_alph):
15 for j, r in enumerate(log_s2):
---> 16 Z[i, j] = compute_log_marginal(x,t,log_alph,log_s2)
17 Z_max.append(Z[i, j])
18 maximum = max(Z_max)
<ipython-input-233-45cfae272a38> in compute_log_marginal(PHI, t, alph, s2)
19 N, M = PHI.shape
20 beta = 1 / s2
---> 21 Mu, SIGMA = compute_posterior(PHI, t, alph, s2)
22 #
23 # Constant factor
<ipython-input-233-45cfae272a38> in compute_posterior(PHI, t, alph, s2)
2 M = PHI.shape[1]
3 beta = 1/s2
----> 4 H = beta*(PHI.T # PHI) + alph*np.eye(M)
5 SIGMA = np.linalg.inv(H)
6 Mu = beta * (SIGMA # (PHI.T # t))
ValueError: operands could not be broadcast together with shapes (100,) (8,8)
'
H = beta*(PHI.T # PHI) + alph*np.eye(M)
split operations in this line and figure out which one is throwing errors
If your logic is ok, check if all matrices have the shape that you expect.
If shapes are ok note that # is matrix multiplication and * is elementwise multiplication.
Nex time you post code try to include smaller part that is more readable or include code that everyone will be able to execute, to debug it.
Hey guys I'm receiving an error and I'm not 100% sure why it's happening. I'm trying to perform both the eulers and heun's methods and plot them against one another. Any help or suggestions would be awesome! I'm pretty novice with python so this is a bit new to me.
import numpy
#eulers
yi = 0
h = 0.2
te = [0.0,2.0,0.2]
def euler(f, y0, t):
n = len(t)
y = numpy.array([y0] * n)
for i in range(n - 1):
y[i+1] = y[i] + (t[i+1] - t[i]) * f(y[i], t[i])
return y
fy = (y*t**3) - 1.5*y
y1 = euler(fy, yi, te)
#heun
def heun(f, y0, t):
n = len(t)
y = numpy.array( [y0] * n )
for i in range(n - 1):
h = t[i+1] - t[i]
k1 = h * f( y[i], t[i])
k2 = h * f( y[i] + k1, t[i+1])
y[i+1] = y[i] + (k1 + k2) / 2.0
return y
y2 = heun(fy, 1, te)
tp = numpy.linspace(0.0, 2.0, 0.2)
plt.plot(tp, y1,'r-',linewidth=2,label='Eulers')
plt.plot(tp, y2,'b--',linewidth=2,label='Heun')
plt.xlabel('time')
plt.ylabel('y(t)')
plt.legend()
plt.show()
This is my error code:
TypeError Traceback (most recent call last)
<ipython-input-152-395afeefc50a> in <module>()
11 return y
12 fy = (y*t**3) - 1.5*y
---> 13 y1 = euler(fy, yi, te)
14
15 #heun
<ipython-input-152-395afeefc50a> in euler(f, y0, t)
8 y = numpy.array([y0] * n)
9 for i in range(n - 1):
---> 10 y[i+1] = y[i] + (t[i+1] - t[i]) * f(y[i], t[i])
11 return y
12 fy = (y*t**3) - 1.5*y
TypeError: 'numpy.ndarray' object is not callable
My guess is that you're trying to define a function f(y,t) in the line
fy = (y*t**3) - 1.5*y
as your differential equation. However, that is not how you define a function in python.
Try
def f(y,t):
return y*t**3 - 1.5*y
You are getting an error because on line
---> 10 y[i+1] = y[i] + (t[i+1] - t[i]) * f(y[i], t[i])
f is a NumPy array, but you are treating it as a function.
I receive the following error for my code below when I try to run curve_fit in Python. "function call is not a proper array of floats". I read that it may be caused by not inputting an array, so I converted my list to array, but I still get the same error.
#Calculate initial price
def initial_price(stocks, V, T, M, N, K, r):
dt = float(T)/M
for i in range(M - 1, 0, -1):
#Define x data
xdata = list()
for k in range(0, N):
xdata.append(stocks[k * M + (i - 1)])
#Convert list into array
xdata = np.asarray(xdata)
#Define y data
ydata = list()
for k in range(0, N):
ydata.append(exp(-r * dt) * V[k * M + i])
#Convert list into array
ydata = np.asarray(ydata)
#get optimal values
popt, pcov = curve_fit(cubic, xdata, ydata)
for k in range(0, N):
V[k * M + (i - 1)] = \
max(C_payoff(stocks[k * M + (i - 1)],
cubic(stocks[k * M + (i - 1)], popt[0],
popt[1], popt[2], popt[3])))
#Compute initial price as discounted weighted average
#over initial prices for all paths
sum = 0.0
for k in range(0, N):
sum = sum + V[k * M]
V0 = exp(-r * dt) * (1.0/N) * sum
return V0
#Define a cubic polynomial function
def cubic(x, a0, a1, a2, a3):
return a0 + a1*x + a2 * x ** 2 + a3 * x ** 3