It's uncomfortable code, I know, and sorry. Especially, if it's a stupid question.
Here is an error with list, and I don't know why (I'm beginner). Can someone, please, tell me, how to fix it?
This is the output:
Traceback (most recent call last):
File "C:/Users/milom/PycharmProjects/ChislM/method.py", line 77, in <module>
vx, vy = rk3(diff1, 0, U0, 10, 100)
File "C:/Users/milom/PycharmProjects/ChislM/method.py", line 39, in rk3
x,v=step(f, h, i, x0, U0)
File "C:/Users/milom/PycharmProjects/ChislM/method.py", line 11, in step
k2 = f(x[i] + (1 / 3) * h[i], v[i] + (1 / 3) * k1)
IndexError: list index out of range
Code:
import matplotlib.pyplot as plt
import math as m
import pandas as pd
x =[0]*101
v =[0]*101
def step(f, h, i, x0, U0):
x[0] = x0
v[0] = U0
k1 = f(x[i], v[i])
k2 = f(x[i] + (1 / 3) * h[i], v[i] + (1 / 3) * k1)
k3 = f(x[i] + (2 / 3) * h[i], v[i] + (2 / 3) * h[i] * k2)
x[i] = x[i - 1] + h[i]
v[i] = v[i - 1] + (h[i]) * ((1 / 4) * k1 + (3 / 4) * k3)
return x, v
def rk3(f, x0, U0, x1, n):
h = [(x1 - x0) / float(n)]
for i in range(1, n+1):
x,v=step(f, h, i, x0, U0)
###h= control(f, h[i], i, v[i], x0, U0)
return x, v
def diff1(x, U):
return 0.1
def diff(x, U):
return -(m.cos(10 * x) + ((m.log(1 + x ** 2)) / (1 + x)) * (U ** 2) + U)
def exact_path():
plt.grid()
plt.plot(vx, vy)
plt.show()
def table():
mytable = pd.DataFrame({
'Xn': vx,
'Vn': vy,
}, index=[i for i in range(0, 101)])
mytable.index.name = 'number'
pd.set_option('display.max_rows', None)
print(mytable)
task = int(input("Task:"))
U0 = float(input("First value- U0:"))
if task == 2:
vx, vy = rk3(diff, 0, U0, 10, 100)
table()
exact_path()
if task == 1:
vx, vy = rk3(diff1, 0, U0, 10, 100)
table()
exact_path()
P.S. It's a simple 3th order Runge-Kutta method, but mostly problem with synthax. I tried to implement method with Python.
In the rk3() function you have h = [(x1 - x0) / float(n)] which creates an list with only a single element in it. This means that the only valid non-negative index that can be used with it would be h[0]—and an attempt to use any other index value, as is likely in the step() function in the for loop, will cause an IndexError.
Related
My function returns 2 different values which I want to utilise in 2 different graphs using Matplotlib. How can I achieve it?
def option_value_european_put(T, m, r, sigma, mu, E):
cost_value_at_initial_t_put = []
portfolio_payoff_put = []
for e in E:
delta_t = T / m
u = (1 + (sigma * math.sqrt(delta_t)) * (math.sqrt(1 + ((mu ** 2) * delta_t) / math.pow(sigma, 2))))
v = 2 - u
option_stock_price_matrix_put = np.zeros((m + 1, m + 1))
sum = 0
k = m
start = m
for i in range(m + 1):
option_stock_price_matrix_put[i][start] = max(
(e - stock_price_binomial_model(
mu, sigma, T, m,
S
)[i][start], 0)
)
for j in range(m - 1, -1, -1):
for i in range(0, j + 1):
v_plus = option_stock_price_matrix_put[i][j + 1]
v_minus = option_stock_price_matrix_put[i + 1][j + 1]
v_t = ((((v_plus - v_minus) / (u - v)) * (1 + r * delta_t)) + (u * v_minus - v * v_plus) / (u - v)) / (
1 + r * delta_t)
option_stock_price_matrix_put[i][j] = v_t
cost_value_at_initial_t_put.append(option_stock_price_matrix_put[0][0])
for i in range(0, m+1):
sum = sum + option_stock_price_matrix_put[k][i]
portfolio_return_average = math.average(sum)
portfolio_payoff_put.append(portfolio_return_average-option_stock_price_matrix_put[0][0] )
return cost_value_at_initial_t_put, portfolio_payoff_put
I want to use cost_value_at_initial_t_put in 1 Matplotlib plot and the other value in another plot. How can I use it?
Supposing that cost_value_at_initial_t_put and portfolio_payoff_cut are both lists you can create subplots:
import matplotlib.pyplot as plt
fig, (ax_cost, ax_payoff) = plt.subplots(nrows=2)
ax_cost.plot(cost_value_at_initial_t_put)
ax_payoff.plot(portfolio_payoff_cut)
I am seeking to find a finite difference solution to the 1D Nonlinear PDE
u_t = u_xx + u(u_x)^2
Code:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import math
'''
We explore three different numerical methods for solving the PDE, with solution u(x, t),
u_t = u_xx + u(u_x)^2
for (x, t) in (0, 1) . (0, 1/5)
u(x, 0) = 40 * x^2 * (1 - x) / 3
u(0, t) = u(1, t) = 0
'''
M = 30
dx = 1 / M
r = 0.25
dt = r * dx**2
N = math.floor(0.2 / dt)
x = np.linspace(0, 1, M + 1)
t = np.linspace(0, 0.2, N + 1)
U = np.zeros((M + 1, N + 1)) # Initial array for solution u(x, t)
U[:, 0] = 40 * x**2 * (1 - x) / 3 # Initial condition (: for the whole of that array)
U[0, :] = 0 # Boundary condition at x = 0
U[-1, :] = 0 # Boundary condition at x = 1 (-1 means end of the array)
'''
Explicit Scheme - Simple Forward Difference Scheme
'''
for q in range(0, N - 1):
for p in range(0, M - 1):
b = 1 / (1 - 2 * r)
C = r * U[p, q] * (U[p + 1, q] - U[p, q])**2
U[p, q + 1] = b * (U[p, q] + r * (U[p + 1, q + 1] + U[p - 1, q + 1]) - C)
T, X = np.meshgrid(t, x)
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(T, X, U)
#fig.colorbar(surf, shrink=0.5, aspect=5) # colour bar for reference
ax.set_xlabel('t')
ax.set_ylabel('x')
ax.set_zlabel('u(x, t)')
plt.tight_layout()
plt.savefig('FDExplSol.png', bbox_inches='tight')
plt.show()
The code I use produces the following error:
overflow encountered in double_scalars
C = r * U[p, q] * (U[p + 1, q] - U[p, q])**2
invalid value encountered in double_scalars
U[p, q + 1] = b * (U[p, q] + r * (U[p + 1, q + 1] + U[p - 1, q + 1]) - C)
invalid value encountered in double_scalars
C = r * U[p, q] * (U[p + 1, q] - U[p, q])**2
Z contains NaN values. This may result in rendering artifacts.
surf = ax.plot_surface(T, X, U)
I've looked up these errors and I assume that the square term generates values too small for the dtype. However when I try changing the dtype to account for a larger range of numbers (np.complex128) I get the same error.
The resulting plot obviously has most of its contents missing. So, my question is, what do I do?
Discretisation expression was incorrect.
Should be
for q in range(0, N - 1):
for p in range(0, M - 1):
U[p, q + 1] = r * (U[p + 1, q] - 2 * U[p, q] + U[p - 1, q]) + r * U[p, q] * (U[p + 1, q] - U[p, q])
I am intending to take a list of random variables and alter a previous list in each column by said random variables. However, for the purpose of my function, each variable must be used in a Gamma function as well as integrated.
x[t] = c * (1 / (2 ** (v / 2) + test[t - 1]) * (gamma((v / 2) + test[t - 1]))) * integrate.\
quad(lambda h: np.exp(-h / 2) * h ** ((v / 2) + test[t - 1] - 1), 0, np.inf)
x[ t ] is an np.zeros((x , y)) list, and test[t - 1] is an np.zeros((x - 1, y)) list
I have filled test[ ] with the appropriate random variables, but I am unable to pass them through this equation to complete the columns of row [ t ] in x
When I try to run my current code, I receive:
File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\lib\site-packages\scipy\integrate\quadpack.py", line 450, in _quad
return _quadpack._qagie(func,bound,infbounds,args,full_output,epsabs,epsrel,limit)
TypeError: only size-1 arrays can be converted to Python scalars
Is there a different special function which allows me to use each column's variable to solve for my desired x[ t ]?
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import stats
import mpmath as mp
import scipy.integrate as integrate
from scipy.special import gamma
T = 1
beta = 0.5
x0 = 0.05
q = 0
mu = x0 - q
alpha = - (2 - beta) * mu
sigma0 = 0.1
sigma = (2 - beta) * sigma0
b = - ((1 - beta) / (2 * mu) * (sigma0 ** 2))
simulations = 100
M = 50
dt = T / M
def srd_sampled_nxc2():
x = np.zeros((M + 1, simulations))
x[0] = x0
test = np.zeros((M, simulations))
for t in range(1, M + 1):
v = 4 * b * alpha / sigma ** 2
c = (sigma ** 2 * (1 - np.exp(-alpha * dt))) / (4 * alpha)
nc = np.exp(-alpha * dt) / c * x[t - 1]
if v > 1:
x[t] = c * ((np.random.standard_normal(simulations) + nc ** 0.5) ** 2 + mp.nsum(
lambda i: np.random.standard_normal(simulations) ** 2, [0, v - 1]))
else:
max_array = []
nc_over_2 = [l / 2 for l in nc]
for p in range(simulations):
sump = []
poisson_start = 0
while poisson_start <= 1:
x_i = sum(-np.log(np.random.uniform(0, 1, simulations)) / nc_over_2)
sump.append(
x_i
)
poisson_start += x_i
x_n = max(sump)
max_array.append(
x_n
)
sump = []
test[t - 1] = max_array
x[t] = c * (1 / (2 ** ((v / 2) + test[t - 1])) * (gamma((v / 2) + test[t - 1]))) * integrate.\
quad(lambda h: np.exp(-h / 2) * h ** ((v / 2) + test[t - 1] - 1), 0, np.inf)
max_array = []
return x
Ultimately ended up finding a workaround which is simple to implement:
else:
max_array = []
for p in range(simulations):
k = nc[t - 1, p]
lam = k / 2
poisson_samp = 0
while poisson_samp <= 1:
x_i = -math.log(np.random.uniform(0, 1)) / lam
max_array.append(
x_i
)
poisson_samp += x_i
test[t - 1, p] = len(max_array) - 1
max_array.clear()
for f in range(simulations):
n = test[t - 1, f]
z = integrate.quad(lambda h: np.exp(-h / 2) * h ** ((v / 2) + n - 1), 0, 1)
new[t - 1, f] = z[0]
x[t] = c * (1 / (2 ** ((v / 2) + test[t - 1]) * (gamma((v / 2) + test[t - 1]))) * new[0])
The only real problem is the shrinkage of x[t] which leads to dividing by zero--just a formula problem.
I wrote a code for solving ode using rk4 method.
Here is the code:
from __future__ import division
import math
import numpy as np
from math import exp
def f(t,y):
return 5*t**2-y/math.e**(t+y)
def rk4(t,y,h,i):
p=[0]*i
p[0] = y
for n in range(0,i):
g=11
k1=round(h*f((t+n*h),y),g)
k2=round(h*f((t+n*h)+(h/2),y+k1/2),g)
k3=round(h*f((t+n*h)+h/2,y+k2/2),g)
k4=round(h*f((t+n*h)+h,y+k3),g)
p[n+1]=p[n]+(1/6)*(k1+2*k2+2*k3+k4)
print(k1,k2,k3,k4)
a=rk4(0,1,0.1,3)
print(a)
When I try to print the k's coefficient,it shows list assignment index out of range error and when I try to print the value of p,output is
[1, 0.9666652135433333, 0]
I don't understand why the third item is 0.
How do I solve these problems?
I improve your code snippet:
from __future__ import division
import math
def f(t, y):
return 5 * t**2 - y/math.e**(t + y)
def rk4(t, y, h, i):
p = list()
p.append(y)
for n in range(0, i):
g = 11
k1 = round(h * f((t + n * h), y), g)
k2 = round(h * f((t + n * h) + (h/2), y + k1/2), g)
k3 = round(h * f((t + n * h) + (h/2), y + k2/2), g)
k4 = round(h * f((t + n * h) + h, y + k3), g)
p.append(p[n] + (1/6) * (k1 + 2 * k2 + 2 * k3 + k4))
print(k1, k2, k3, k4)
rk4(0, 1, 0.1, 3)
Out:
(-0.03678794412, -0.03373778195, -0.03373873966, -0.0282677314)
(-0.02828710837, -0.02041047991, -0.02041201684, -0.01011306051)
(-0.01011942119, 0.00259988829, 0.0025995445, 0.01774691262)
I'd like to use an implementation of RK4 I found online for something, but I'm having a bit of difficulty wrapping my head around the implementations I have found online.
For example:
def rk4(f, x0, y0, x1, n):
vx = [0] * (n + 1)
vy = [0] * (n + 1)
h = (x1 - x0) / float(n)
vx[0] = x = x0
vy[0] = y = y0
for i in range(1, n + 1):
k1 = h * f(x, y)
k2 = h * f(x + 0.5 * h, y + 0.5 * k1)
k3 = h * f(x + 0.5 * h, y + 0.5 * k2)
k4 = h * f(x + h, y + k3)
vx[i] = x = x0 + i * h
vy[i] = y = y + (k1 + k2 + k2 + k3 + k3 + k4) / 6
return vx, vy
Could someone please help me understand what exactly the parameters are? If possible, I'd like a more general explanation, but, if being more specific makes it easier to explain, I'm going to be using it specifically for an ideal spring system.
You are asking for the parameters here:
def rk4(f, x0, y0, x1, n):
...
return vx, vy
f is the ODE function, declared as def f(x,y) for the differential equation y'(x)=f(x,y(x)),
(x0,y0) is the initial point and value,
x1 is the end of the integration interval [x0,x1]
n is the number of sub-intervals or integration steps
vx,vx are the computed sample points, vy[k] approximates y(vx[k]).
You can not use this for the spring system, as that code only works for a scalar v. You would need to change it to work with numpy for vector operations.
def rk4(func, x0, y0, x1, n):
y0 = np.array(y0)
f = lambda x,y: np.array(func(x,y))
vx = [0] * (n + 1)
vy = np.zeros( (n + 1,)+y0.shape)
h = (x1 - x0) / float(n)
vx[0] = x = x0
vy[0] = y = y0[:]
for i in range(1, n + 1):
k1 = h * f(x, y)
k2 = h * f(x + 0.5 * h, y + 0.5 * k1)
k3 = h * f(x + 0.5 * h, y + 0.5 * k2)
k4 = h * f(x + h, y + k3)
vx[i] = x = x0 + i * h
vy[i] = y = y + (k1 + 2*(k2 + k3) + k4) / 6
return vx, vy