Optimize a set of coordinates based on a cost function - python

I have a set of (x_i,y_i) coordinates defining a path between an initial point and a final position, that I do not want to move. Right now I am optimizing the path based on distance between points (to reduce the length of the path) and curvature of the points which are included into the cost function and jacobian. The problem is that to accomplish that I have to create a state vector wit all the stacked and find the minimum. The state space gets length 2*N where N is the number of samples that I have and it runs extremely slow even for small number of points. The layout is the following one (just including distance between points):
def jacobian_function(self, state_vector):
"""
The jacobian of the cost function to be used by the optimizer
:param state_vector : The extended state vector
"""
gradient_array = np.zeros(len(state_vector))
for i in range(1, int(len(state_vector) / self.num_states) - 1): # -1 to not modify last point
state_before = state_vector[2 * (i - 1):2 * i]
state_curr = state_vector[2 * i:2 * (i + 1)]
state_next = state_vector[2 * (i + 1):2 * (i + 2)]
factor = 0.1 * 2 * (
state_before - 2 * state_curr + state_next)
gradient_array[2 * i:2 * (i + 1)] += -2 * factor
gradient_array[2 * (i - 1):2 * i] += factor
gradient_array[2 * (i + 1):2 * (i + 2)] += factor
return gradient_array
def cost_function(self, state_vector):
"""
The cost function to be used by the optimizer
:param state_vector : The extended state vector
"""
cost = 0
for i in range(1, int(len(state_vector) / 2) - 1): # -1 to not modify last point
smooth_vector = state_vector[2 * (i + 1):2 * (i + 2)] + state_vector[
2 * (i - 1):2 * i] - 2 * state_vector[
2 * i:2 * (i + 1)]
cost += 0.1 * np.dot(smooth_vector, smooth_vector)
return cost
states = np.array([[1,2,3,4,5],[1,2,3,4,5]])
states_extended = np.reshape(states, states.shape[0] * states.shape[1], order='F')
result = optimize.minimize(fun=self.cost_function, states_extended, method="BFGS",jac=self.jacobian_function, options={'disp': True})
Do you have any idea to speed up the process while considering all the data points (normally N is around 800)?

Related

Price approximation of European call option using the explicit finite difference method in python not working

I'm trying to approximate the European call option price of the Black-Scholes model (PDE) by the explicit finite difference method in python. For reference, the exact solution using the Black-Scholes formula is 10.247013813310648
Here is a link about the PDE Black-Scholes Equation and the discretized version of the equation can be found here Explicit finite difference method for Black-Scholes model
Can anyone point out why I'm not getting an approximation?
import numpy as np
# Terminal time
T = 0.25
# Strike price
K = 10
# risk free rate
r = 0.1
# volatility (systemic/market risk)
sigma = 0.4
# initial asset value
S0 = 20
# Assume an upper limit for the underlying stock that is 3 - 4 times the exercise price
S_max = 3 * K
# Number of space intervals
M = 200
# space mesh and space step
space_mesh, space_step = np.linspace(0, S_max, M, retstep=True)
# Stability condition
stability_cond = 1 / ( sigma**2 * (M-1) + 0.5* r )
# Find the number of time intervals and time steps that satisfy the stability condition
for percentage in np.arange(.99, .0001, -.0001):
time_step = np.round(percentage * stability_cond, 6)
N = T / time_step
if N.is_integer():
print("Number of time intervals = ", N," ", "time step = ", time_step)
# Choose number of time intervals
N = 2000
# time mesh
time_mesh, time_step = np.linspace(0, T, N, retstep= True)
# time step
time_step = np.round(time_step, 6)
# unknown u at new time level
u = np.zeros(M)
# u at the previous time level
u_prev = np.zeros(M)
# initial condition
for m in range(0, M):
u_prev[m] = np.maximum(space_mesh[m] - K, 0)
# Explicit finite difference scheme
for n in range(0, N):
for m in range(1,M-1):
a = 0.5 * time_step * ( sigma**2 *m**2 - r * m )
b = 1 - time_step * ( sigma**2 * m**2 + r )
c = 0.5 * time_step * ( sigma**2 * m**2 + r * m)
# The discretized version of the Black-Scoles PDE
u[m] = a * u_prev[m-1] + b* u_prev[m] + c * u_prev[m+1]
# insert boundry conditions
u[0] = 0
u[M-1] = S_max
# update u_prev before next iteration
u_prev[:] = u

Python Magnitude of FFT Signal

I want to calculate First HPF and then FFT of an acceleration data for which I use the following code.
# Make Function
def filter(s):
# Signal after HPF
fc = 0.1
b = 0.08
N = int(np.ceil((4 / b)))
if not N % 2: N += 1
n = np.arange(N)
sinc_func = np.sinc(2 * fc * (n - (N - 1) / 2.))
window = np.blackman(N)
sinc_func = sinc_func * window
sinc_func = sinc_func / np.sum(sinc_func)
# reverse function
sinc_func = -sinc_func
sinc_func[int((N - 1) / 2)] += 1
#s = list(df[' acc.y'])
new_signal = np.convolve(s, sinc_func)
a=np.fft.fft(new_signal)
return a
The question is this returns an array now I want to calculate the single-valued Magnitude of this Numpy ie I need the Magnitude for the signal whose FFT i calculate

Shifted Chebyshev polynomials in Python

I am trying to extract the coefficients of a shifted Chebyshev Polynomial in Python, but I couldn't find the function to do that.
There is this function:
scipy.special.eval_sh_chebyt
scipy.special.eval_sh_chebyt(n, x, out=None) = <ufunc 'eval_sh_chebyt'>
but I can't extract only the coefficients.
The shifted Chebyshev polynomials are:
T^{*}_n(x) = T_n (2x -1)
and then:
T_1^{*}(x) = 2x - 1
T_2^{*}(x) = 8x^2 - 8x -1
I would like to extract a matrix only with the coefficients, like 2 and 1 or 8,8 and 1.
scipy.special.eval_sh_chebyt evaluates the function T* at a given point x. Unless you are very smart in choosing your arguments, this is not an appropriate way to get the coeffcients.
You can instead calculate the coefficients directly from the recurrence formula T0 = 1, T1 = x, T{n} = 2xT{n-1} - T{n-2}. And then calculate the shifted polynomials from _T*{n} = T{n}(2x - 1).
degree = 10
coeffs = []
# for T_0
coeffLine = [1]
coeffs.append(coeffLine)
# for T_1
coeffLine = [0, 1]
coeffs.append(coeffLine)
for i in range(2, degree + 1):
coeffLine = [0] * (1 + i)
coeffLine[0] = -coeffs[i - 2][0]
for j in range(1, i - 1):
coeffLine[j] = 2 * coeffs[i - 1][j - 1] - coeffs[i - 2][j]
coeffLine[-2] = 2 * coeffs[i - 1][-2]
coeffLine[-1] = 2 * coeffs[i - 1][-1]
coeffs.append(coeffLine)
print("T_%d" % degree, coeffs[-1])
shiftedCoeffs = [0] * (degree + 1);
for i in range(degree + 1):
binom = 1
for j in range(i + 1):
shiftedCoeffs[i - j] += coeffs[-1][i] * 2 ** (i - j) * (-1) ** j * binom
binom *= (i - j) / (j + 1)
print("T*_%d" % degree, shiftedCoeffs)
Edit: I originally misread the formula for T*{n} as _T{n}(x) * (2x - 1). However it is T*{n} = T{n}(2x - 1). We therefore need to calculate the binomial coefficients sum them up depending on the order of x.

Filling points in a grid - Forward Euler algorithm - wrong output

I will very briefly try to explain what I'm doing to those who are less experienced with mathematics, it's really quite simple.
We are trying to fill a grid, as follows:
We find the orange point, U(j,n+1), using three points in a row below it, U(j-1,n), U(j,n), U(j,n+1)
Where the value of U in the entire bottom row is given, and is periodic. So theoretically we can fill this entire grid.
The formula for calculating the orange point is:
U(j,n+1) = U(j,n) + (delta_t / (2 * delta_x)) * (U(j+1,n) - U(j-1,n))
We can write it easily as a system of linear equations as follows:
And now we just repeat this process of multiplying by this matrix (iterating through the time variable) as much as we want. That's a simple way to numerically approximate a solution to a partial differential equation.
I wrote a code that does this, and then I compare my final row, to the known solution of the differential equation.
This is the code
import math
import numpy
def f(x):
return math.cos(2 * math.pi * x)
def solution(x, t):
return math.cos(2 * math.pi * (x + t))
# setting everything up
N = 16
Lambda = 10 ** (-20)
Delta_x = 1/(N+1)
Delta_t = Lambda * Delta_x * Delta_x
t_f = 5
v_0 = numpy.zeros((N, 1))
# Filling first row, initial condition was given
for i in range(N):
v_0[i, 0] = f(i * Delta_x)
# Create coefficient matrix
M = numpy.zeros((N, N))
for i in range(N):
M[i, i - 1] = -Delta_t / (2 * Delta_x)
M[i, i] = 1
M[i, (i + 1) % N] = Delta_t / (2 * Delta_x)
# start iterating through time
v_i = v_0
for i in range(math.floor(t_f / Delta_t) - 1):
v_i = numpy.dot(M, v_i)
v_final = v_i
if (Delta_t * math.ceil(t_f / Delta_t) != t_f): #we don't reach t_f exactly using Delta_t
v_final = (1/2) * (v_i + numpy.dot(M, v_i))
u = numpy.zeros(v_final.shape)
for i in range(N):
u[i, 0] = solution(i * Delta_x, t_f)
for x in range(v_final.shape[0]):
print (v_final[x], u[x])
theoretically speaking, I should be able to find lambda small enough such that v_final and the known solution, u, will be very similar.
But I can't. No matter how small I make lambda, how finde I make the grid, I seem to converge to something incorrect. They aren't close.
I can't for the life of me figure out the problem.
Does anyone have an idea what might be wrong?
You should have Delta_x = 1.0/N, as you divide the interval into N cells.
You get N+1 points on the grid from u[0] to u[N], but as per boundary condition u[N]=u[0], there you also only use an array of length N to hold all the node values.
Per your given formulas you have gamma = dt/(2*dx), thus the reverse computation should be dt = gamma*2*dx or in your variable names
Delta_t = Lambda * 2 * Delta_x
Or you are aiming at the error of the method which is O(dt, dx²) so that it would make sense to have dt = c*dx^2, but not with a ridiculous factor like of c=1e-20, if you want the time discretization error small against the space discretization error, c=0.1 or c=0.01 should be sufficient.
import numpy as np
def f(x):
return np.cos(2 * np.pi * x)
def solution(x, t):
return f(x + t)
# setting everything up
N_x = 16
Lambda = 1e-2
Delta_x = 1./N_x
Delta_t = Lambda * Delta_x * Delta_x
t_f = 5
N_t = int(t_f/Delta_t+0.5); t_f = N_t*Delta_t
# Filling first row, initial condition was given
x = np.arange(0,N_x,1) * Delta_x
v_0 = f(x)
# Create coefficient matrix
M = np.zeros((N_x, N_x))
for i in range(N_x):
M[i, i - 1] = -Delta_t / (2 * Delta_x)
M[i, i] = 1
M[i, (i + 1) % N_x] = Delta_t / (2 * Delta_x)
# start iterating through time
v_i = v_0[:]
for i in range(N_t):
v_i = np.dot(M, v_i)
v_final = v_i
u = solution(x, t_f)
for vx, ux in zip(v_final, u):
print (vx, ux)
The Euler method is also not the most precise method, the expected error is in the range exp(L*t_f)*dx^2 = e^5/N_x^2=0.58 for N_x=16 where L=1 was taken as approximate Lipschitz constant. Now if you increase to N_x=50 this error estimate reduces to 0.06 which is also visible in the results.
The t exact solution of the x discretized problem is cos(2*pi*(x+c*t)) where c=sin(2*pi*dx)/(2*pi*dx). If you compare against that formula, the errors should be really small of size O(dt).

Type Errors (Expected type Float, got set[Float]; etc. errors) in Program

I am relatively new to Python and I was using it to solve a system of equations in a Cosmology project. Here is the code:
#Import Math Module for Square Root Function, Numpy for Computations and Matplot for Plotting
import math
import numpy as np
import matplotlib.pyplot as plt
#Planck Mass
Mpl=2.43*10**18*10**9*1.6*10**-19 #Mpl value is 2.43*10^18 GeV
#Compute Initial Values of the Densities
RhoM_today= 2.746*(10**(-27)) #Today's Value of Matter Density
RhoRad_today= 4.546*(10**(-31)) #Today's Value of Radiation Density
RhoL_today=0.0 #Value of Cosmological Constant Density
Rho=RhoM_today+RhoRad_today+RhoL_today #Initial Value of the Overall Density
#Set Initial Values
#Initial Values of the Fields
Sigma = 1.0 # Initial Value of Sigma (a=10)
Phi=1.0
#Values of Parameters
Omega=1.0 #Dummy Value of Omega
Alpha_Three=1.0 #Dummy Value of Alpha_3
Alpha_Four=1.0 #Dummy Value of Alpha_4
Alpha_Sigma=1.0 #Dummy Value of Alpha_Sigma
C1=1.0 #Dummy Value of C1
mg=1.0 #Dummy Value of the Graviton Mass
Lambda=0.0 #Value of the Cosmological Constant
H=2.27*10**-18 #Initial Value of H
# Initial Values for computing the number of Steps for RK4
x=0 #Corresponding to a = 1 (today)
xn=-11.5 #Corresponding to a ~ 10^-5
h = 0.115 #Step Size
n = int((x-xn)/h) #Number of Steps/Points
#Note: n+1 points but n Steps?
print(n)
#Creating Arrays for Storing Data
xp=np.linspace(x,xn,n+1) #Array for Storing x
Sigmap=np.empty(n+1,float) #Array for Storing Sigma
up=np.empty(n+1,float) #Array for Storing u
Hp=np.empty(n+1,float) #Array for Storing H
#Hxp=np.empty(n+1,float) #Array for Storing Hx
#Sigmap[0]=Sigma #Save Initial Value of Sigma
#up[0]=u #Save Initial Value of u
#Hp[0]=H #Save Initial Value of H
#Hp[0]=H/H0 #Save Initial Value of H
#Hxp[0]=Hx #Save Initial Value of Hx
#CHp=np.empty(n+1,float) #Array for Conformal Hubble Parameter
#CHp[0]=H*math.exp(x)
#for i in range (0,n+1):
# print (Hp[i])
#Print Parameters and Initial Values
print('Planck Mass is',Mpl)
print('Initial Value of H is ',H )
print('Initial Value of Sigma is ',Sigma)
print('Initial Value of Energy Density Rho is ',Rho)
print('a goes from ',math.exp(x),'to ',math.exp(xn))
print('x (lna) goes from ',x,'to ',xn)
print('Total Number of Steps in RK1 is ',n)
#The Header of the output table
print('x \t\t\t\t\t\t \t\tSigma\t\t\t\t\t\t u \t\t\t\t\t \t\t\t\t H')
#print(x,'\t\t\t\t\t\t\t',Sigma,'\t\t\t\t\t\t',u,'\t\t\t\t\t\t',H)
#print('%f \t\t\t\t\t \t %f \t\t\t\t \t %f \t\t\t\t\t \t %f'% (x,Sigma,u,H)) # The Initial Values of x, Sigma & u
#Start of RK1
#Start of The RK1 Loop
for i in range(0, n):
# Generate Values of Rho (from RhoM, RhoRad & H, re-written in terms of x)
RhoM = RhoM_today / (math.exp(x) ** 3)
RhoRad = RhoRad_today / (math.exp(x) ** 4)
RhoL = 0.0
Rho = RhoM + RhoRad + RhoL # New Value of the Overall Density
# Generate Values of the Pressures
Pressure_Matter = 0
Pressure_Radiation = RhoRad / 3
Pressure = Pressure_Matter + Pressure_Radiation
#Save the Values of Sigma and H
Sigmap[i] = Sigma # Save the Value of Sigma
Hp[i] = H #Save the Value of H
# Compute Values for X, J, Lambda_X & Their Derivatives
X = math.exp(Sigma) / math.exp(x)
print(X)
J = 3 + 3 * Alpha_Three * (1 - X) + Alpha_Four * (1 - X) ** 2
print(J)
Lambda_X = (mg ** 2) * (X - 1) * [J + (X - 1) * {(Alpha_Three) * (X - 1) - 3}]
# Compute Value of u
u = (1 / H) * (math.sqrt(2 / Omega)) * math.sqrt(3 * H * 2 - Lambda - Lambda_X - Rho / Mpl ** 2)
up[i]=u
print('%.3f \t\t\t\t\t \t %.6f \t\t\t\t \t%.6f \t\t\t\t\t \t %9.3e' % (x, Sigma, u, H)) # Newer Computed values of x,Sigma,u & H
# Compute Value of Lambda_X_Dot & Lambda_X_Dash
Lambda_X_Dot = 3 * (mg ** 2) * math.exp(Sigma) * H * [u - 1] * [J + X * {Alpha_Three * (X - 1) - 2}] / math.exp(x)
Lambda_X_Dash = Lambda_X_Dot / H
# Compute Value of q
q = (Alpha_Sigma ** 0.5) * [u / (X * mg)] / math.sqrt([(1 / H ** 2) - {C1 / (math.exp(x) ** 4 * X * (1 - X) * J * H)}])
# Compute Value of H_Dash
H_Dash = (q - 1) * Lambda_X_Dash / (6 * H * (u - 1)) - Omega * H * u ** 2 / 2 - (Rho + Pressure) / (2 * H)
#Compute the next Values of H and Sigma
H=H+H_Dash*h
Sigma=Sigma+u*h
#Increment x (Move on to next h)
x-=h
I have included the entire code for completeness. The errors I get are towards the end of the code in the three equations- the one in Lambda_X, another in Lambda_X_Dot and the last one in q).
The errors I am getting are of the form: 'Expected Float, got set[float] instead
' & 'Expected Float got list[float] instead'etc.
I am unsure where they come from since I had written a similar program which did not have such errors. I donno if it helpsbut I am using PyCharm to write the code. Any input are greatly appreciated! Thanks in advance.
In your code see this line specifically,
Lambda_X = (mg ** 2) * (X - 1) * [J + (X - 1) * {(Alpha_Three) * (X - 1) - 3}]
Usually, in mathematics, we use square braces and curly brace along with normal braces, but in python, they mean the different thing. {} this makes a set and [] this makes a list. So you can't use them as you have used here. You might want to replace them with normal braces.
For example, above mentioned line will become
Lambda_X = (mg ** 2) * (X - 1) * (J + (X - 1) * ((Alpha_Three) * (X - 1) - 3))
You will have to do the same for other statements in the code.

Categories

Resources