solve complicated ODE groups using spicy.integrate solve_bvp unsuccessfully - python

When I run my code sentence by sentence, no errors exist. However, when I check out the results of AA (bvp solution in my code), it displays that I solve this ODE group falsely.
How can I run this code correctly?
import numpy as np
import scipy.integrate
from scipy.integrate import solve_bvp
import matplotlib.pyplot as plt
k=0.06
Theta=20
p=0.4 #porosity of the electrode
pi=3.14
L=4 #cm
R=8.314
F=96485
t2=0.78
C0=1
T=298.15
vs=1
aa=0.5
ac=0.5
a=23300
i0=2e-2
Dad=0.5
I=2
Da=900
B=(1/k*(p**(1.5)))+1/Theta
C=I/(2*pi*L*Theta)
D=2*R*T/F
E=Da*p**(1.5)
def battery(r,y):
A=np.exp((aa*F*y[0])/(R*T))-np.exp((-ac*F*y[0])/(R*T))
return np.vstack((y[1]*B-C/r+(D*y[3]/y[2])*(0.22+y[2]),
A/((1/a*i0)+A/Dad),
y[3],
((1-E)/E)*y[3]+(0.22/(E*F))*(A/((1/a*i0)+A/Dad))))
def boundary(ya,yb):
return [ya[1]-2/(2*3.14*4*10*4.2),yb[1],ya[2]-9,yb[3]]
n = 25
r = np.linspace(4.2, 6.9, n)
y = np.ones((4,r.size))
AA=solve_bvp(battery,boundary,r,y)
The results are below:
sol: <scipy.interpolate.interpolate.PPoly object at 0x11303f728>
status: 2
success: False

Related

interpolate, derivate and integrate a function -- some math fun

I have a problem. I have three lists. The list_umf are the x values and list list_kf are the y values, while list_kfm are y values, too. kfm is the integral of kf. The values are the output of my code.
To show that kfm is the integral of kf, I want to calculate the derivative of kfm, which shuold be the same as kf. But the re calculated kfm (list_kf_re) is just 101.0 every time.
Whats wrong with my code?
import numpy as np
from scipy import integrate, interpolate
from scipy.misc import derivative as deriv
import matplotlib.pyplot as plt
list_kfm = [15.348748494618041, 26.240336614039776, 37.76846357985518, 49.80068952374503, 62.25356792292074, 75.0692188764684, 88.20491343740369, 101.6276911997135,
115.31128207665246, 129.2342114999071, 143.37856687640036, 157.72915825067278, 172.27292637703843, 186.9985127198004, 201.89593919604192, 216.95636451973587]
list_kf = [168.08871431597626, 179.78615963605742, 188.728883379148, 196.0371678709251, 202.25334207341422, 207.68364358717665, 212.51893919883966, 216.88670040685466,
220.87653440371076, 224.55397301446894, 227.96847485999652, 231.15833919688876, 234.1538643061246, 236.97945558527186, 239.65507793294745, 242.19728380107006]
list_umf = [0.1, 0.15000000000000002, 0.20000000000000004, 0.25000000000000006, 0.30000000000000004, 0.3500000000000001, 0.40000000000000013, 0.45000000000000007,
0.5000000000000001, 0.5500000000000002, 0.6000000000000002, 0.6500000000000001, 0.7000000000000002, 0.7500000000000002, 0.8000000000000002, 0.8500000000000002]
f = interpolate.interp1d(
list_umf, list_kfm, bounds_error=False, fill_value=(15, 217))
list_kf_re = [deriv(f, x) for x in list_umf]
plt.plot(list_umf, list_kfm, label='kfm')
plt.plot(list_umf, list_kf, label='kf')
plt.plot(list_umf, list_kf_re, label='kfre')
print(list_kf_re)
print(list_kf)
Use UnivariateSpline to create an interpolator that you can later apply integral or derivative functions (see this post)
Sample:
import numpy as np
#from scipy import integrate, interpolate
from scipy.interpolate import UnivariateSpline as US, InterpolatedUnivariateSpline as IUS
#from scipy.misc import derivative as deriv
import matplotlib.pyplot as plt
list_kfm = [15.348748494618041, 26.240336614039776, 37.76846357985518, 49.80068952374503, 62.25356792292074, 75.0692188764684, 88.20491343740369, 101.6276911997135,
115.31128207665246, 129.2342114999071, 143.37856687640036, 157.72915825067278, 172.27292637703843, 186.9985127198004, 201.89593919604192, 216.95636451973587]
list_kf = [168.08871431597626, 179.78615963605742, 188.728883379148, 196.0371678709251, 202.25334207341422, 207.68364358717665, 212.51893919883966, 216.88670040685466,
220.87653440371076, 224.55397301446894, 227.96847485999652, 231.15833919688876, 234.1538643061246, 236.97945558527186, 239.65507793294745, 242.19728380107006]
list_umf = [0.1, 0.15000000000000002, 0.20000000000000004, 0.25000000000000006, 0.30000000000000004, 0.3500000000000001, 0.40000000000000013, 0.45000000000000007,
0.5000000000000001, 0.5500000000000002, 0.6000000000000002, 0.6500000000000001, 0.7000000000000002, 0.7500000000000002, 0.8000000000000002, 0.8500000000000002]
f = US(list_umf, list_kfm)
list_kf_re = [f.derivative()(x) for x in list_umf]
plt.plot(list_umf, list_kfm, label='kfm')
plt.plot(list_umf, list_kf, label='kf')
plt.plot(list_umf, list_kf_re, label='kfre')
plt.plot(list_umf, list_kf, 'o', label='kfre_2')
print(list_kf_re)
print(list_kf)

How to evaluate sympy piecewise-like expressions so it's easy to obtain numerical only output?

I have the following code which is part of a practice I'm working on:
Here is a function that obtains 2*N+1 coefficients of the Fourier series for the input function "ft" written in terms of sym.Heaviside(t), the goal is to get from this function only the numerical values so it is possible to perform operations with the obtained Power Spectral Density (PSD):
def ck_power(ft,f,N=5):
c_k_coeff=f*sym.integrate(ft*sym.exp(-2*j*np.pi*t*k*f),(t,-1/(2*f),1/(2*f)))
#C_k_coeff=sym.lambdify(k,c_k_coeff,modules=['numpy'])
#PSD=[abs((c_k_coeff(i)))**2 for i in range(-N,N+1)]
##PSD=[(c_k_coeff.subs(k,i))*(c_k_coeff.subs(k,-i)) for i in range(-N,N+1)]
### "worked" but keeps the same behavior. PSD=[(c_k_coeff.evalf(subs={k:i}))*(c_k_coeff.evalf(subs={k:-i})) for i in range(-N,N+1)]
PSD=[(c_k_coeff.evalf(subs={k:i}))*(c_k_coeff.evalf(subs={k:-i})) for i in range(-N,N+1)]
PSD=[sym.N(abs(i.subs({u(0):0.5})).evalf(3)) for i in PSD]
positive_PSD=PSD[len(PSD)//2:]
# because the k=0 c_k isn't twice in the k axis apporting power:
positive_PSD[1:]=[2*i for i in positive_PSD[1:]]
PSD=np.array(PSD)
positive_PSD=np.array(positive_PSD)
return PSD,positive_PSD
The problem is that when I use the function with the code below the figures I'm still having a weird piecewise function as the output (especially with the sawtooth wave)
The other functions don't have the same problem
But the sawtooth shows directly the piecewise output
these are the output expressions for k=0:
#vertical
type_hash=("Frequency","Power")
frequency_hash=("100KHz","1MHz","100MHz")
frequency=(100e+3,1e+6,100e+6)
waveform_hash=("Pulsetrain","Sawtooth","Triangle")
#horizontal
armonic=list(range(6))
signal={
"Pulsetrain":my.pulsetrain,
"Sawtooth":my.sawtooth,
"Triangle":my.triangle
}
t1={"waveform":[],"frequency":[],"type\\armonic":[]}
for i in armonic:
t1[str(i)]=[]
(A,D,Aoff,toff)=(1,0.5,0,0)
for iwav in waveform_hash:
for ifreq in range(len(frequency)):
ftemp=frequency[ifreq]
for itype in range(len(type_hash)):
f_now=signal[iwav](A,1/ftemp,D,Aoff,toff)
PSD,pPSD=my.ck_power(f_now,ftemp,N=5) #<<--right here is where the functions is called
for i in armonic:
if not itype:
t1[str(i)].append(f"{ftemp*i:.2e}")
else:
t1[str(i)].append(pPSD[i])# add here Power
t1["type\\armonic"].append(type_hash[itype])
t1["frequency"].append(frequency_hash[ifreq])
t1["waveform"].append(iwav)
d1=pd.DataFrame(t1)
d1
these are my imports:
import numpy as np
import matplotlib.pyplot as plt
from scipy.io.wavfile import read
from scipy import signal
import sympy as sym
import sigplot as my
import pandas as pd
Lastly, this is part of my sigplot.py file
import numpy as np
import matplotlib.pyplot as plt
from scipy.io.wavfile import read
from scipy import signal
import sympy as sym
from sympy import Heaviside as u
from IPython.display import display, Math
import pandas as pd
t=sym.symbols('t')
k=sym.symbols('k', integer=True)
j=sym.I
#Fourier
def ck(ft,T):
c_k=1/T*sym.integrate(ft*sym.exp(-j*k*(2*np.pi/T)*t),(t,-T/2,T/2))
c_0=c_k.subs(k,0)
#c_k_mag =[sym.simplify((abs(c_n_coeff.subs(n,i)))) for i in range (-N,N+1)]
return (c_k,c_0)
def espectral(c_k,f,N):
PSD=[abs((c_k.subs(k,i)))**2 for i in range(-N,N+1)]
positive_PSD=[2*abs((c_k.subs(k,i)))**2 if i!=0 else (c_k.subs(k,0))**2 for i in range(N+1)]
return PSD,positive_PSD
def ck_power(ft,f,N=5):
c_k_coeff=f*sym.integrate(ft*sym.exp(-2*j*np.pi*t*k*f),(t,-1/(2*f),1/(2*f)))
#C_k_coeff=sym.lambdify(k,c_k_coeff,modules=['numpy'])
#PSD=[abs((c_k_coeff(i)))**2 for i in range(-N,N+1)]
##PSD=[(c_k_coeff.subs(k,i))*(c_k_coeff.subs(k,-i)) for i in range(-N,N+1)]
### worked. PSD=[(c_k_coeff.evalf(subs={k:i}))*(c_k_coeff.evalf(subs={k:-i})) for i in range(-N,N+1)]
PSD=[(c_k_coeff.evalf(subs={k:i}))*(c_k_coeff.evalf(subs={k:-i})) for i in range(-N,N+1)]
PSD=[sym.N(abs(i.subs({u(0):0.5})).evalf(3)) for i in PSD]
positive_PSD=PSD[len(PSD)//2:]
# because the k=0 c_k isn't twice in the k axis apporting power.
positive_PSD[1:]=[2*i for i in positive_PSD[1:]]
PSD=np.array(PSD)
positive_PSD=np.array(positive_PSD)
return PSD,positive_PSD
def espectrump(c_k,f,N):
# this function should not be used for performance purposes
PSD=[abs((c_k.subs(k,i)))**2 for i in range(-N,N+1)]
positive_PSD=[2*abs((c_k.subs(k,i)))**2 if i!=0 else (c_k.subs(k,0))**2 for i in range(N+1)]
plt.stem(list(range(-N,N+1)),PSD,markerfmt='^',use_line_collection=True)
plt.xlabel("$k$")
plt.grid()
plt.show()
return positive_PSD
def psdplot(N,PSD):
plt.stem(list(range(-N,N+1)),PSD,markerfmt='^',use_line_collection=True)
plt.xlabel("$k$")
plt.ylabel("$y=10{log()}$")
plt.grid()
plt.show()
return None #excuse me, I can't hide it. Is that simple
#waveforms
def pulsetrain(A,T,D,off=0,toff=0):
f=A*(-u(t+T/2)+2*(u(t+D*T/2)-u(t-D*T/2))+u(t-T/2))
foff=f+off*(u(t+T/2)-u(t-T/2))
foff=foff.subs(t,t-toff)
return foff
def triangle(A,T,D=None,off=0,toff=0):
m = (2*A)/T
toff_temp=0.5
tri=m*t*u(t+T/2)-2*m*t*u(t)+m*t*u(t-T/2)
foff = tri+(off+toff_temp)*(u(t+T/2)-u(t-T/2))
foff = foff.subs(t,t-toff)
return foff
def sawtooth(A,T,D=None,off=0,toff=0):
m = A/T
saw =m*t*u(t+T/2)-m*t*u(t-T/2)-(m/2)*u(t-T/2)
foff = saw+off*(u(t+T/2)-u(t-T/2))
foff = foff.subs(t,t-toff)
return foff
Thanks in advance!

logistic regression/puzzled about scipy.optimize function

I was trying to figure out a problem with logistic regression. So the problem is asking to find some parameters to separate points into two groups.
After I completed the costFunction and the gradient function, I decided to use the fmin_tnc function
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import scipy.optimize as opt
def sigmoid(x):
return 1/(1+np.exp(-x))
def costFunction(theta,X,y):
# print(X.shape,theta.shape)
A=(-y)*np.log(sigmoid(X # theta))
# print(A.shape)
B=(1-y)*np.log(1-sigmoid(X.dot(theta)))
# print(B.shape)
return np.mean(A-B)
data=pd.read_csv("D:\Files\Coursera-ML-AndrewNg-Notes-master\code\ex2-logistic regression\ex2data1.txt",
names=['exam1','exam2','admitted'])
data.insert(0,'Ones',1)
cols=data.shape[1]
X=data.iloc[:,0:cols-1]
y=data.iloc[:,cols-1:cols]
X=np.array(X.values) #100*3
y=np.array(y.values) #100*1
theta=np.zeros(shape=[3,1])
#X:100*3 y:100*1 theta:3*1
def gradient(theta,X,y):
return (X.T # (sigmoid(X # theta) - y))/len(X)
theta.reshape([3,1])
res=opt.fmin_tnc(func=costFunction,x0=theta,fprime=gradient,args=(X,y))
positive = data[data.admitted.isin(['1'])]
negetive = data[data.admitted.isin(['0'])]
plt.scatter(positive['exam1'],positive['exam2'],c='r',label='Admitted')
plt.scatter(negetive['exam1'],negetive['exam2'],c='yellow',marker='x',label='NotAdmitted')
x1=np.linspace(30,100)
x2=-1*(final_theta[0]+final_theta[1]*x1)/final_theta[2]
plt.plot(x1,x2,c='blue')
plt.savefig('./fig2.png')
plt.show()
the error

scipy can't optimize parameters gives error- RuntimeWarning: invalid value encountered in reduce

I'm trying to optimize parameters using data for my model with scipy optimize but scipy fails to minimize the function and find values of the parameters. It just returns the initial guess which the user gives as input.Also, it gives the following error: RuntimeWarning: invalid value encountered in reduce.
import pandas as pd
import numpy as np
from math import log10
import math
import scipy.optimize as op
from scipy.integrate import odeint
df1 = pd.read_csv('dataset1.csv')
z=df1.loc[: , "z"]
za=z.as_matrix(columns=None)
mu=df1.loc[: , "mu"]
mua=mu.as_matrix(columns=None)
si=df1.loc[: , "sig"]
sia=si.as_matrix(columns=None)
c = 299792.458;
H0 = 70;
m_t=0.3
d_t=0.7
mu0 = 25 + 5*log10(c/H0);
def model(x,t,m,d):
dydt = 1/(math.sqrt((((1+x)**2)*(1+m*x))-(x*d*(2+x))))
return dydt
def Io(zb,m,d):
return odeint(model,0,zb, args=(m,d))
def lnlike(theta,zb, mub,sib):
m, d = theta
isia2 = 1.0/np.square(sib)
return 0.5*(np.sum(((((5*(np.log10((1+zb)*Io(zb,m,d)))+mu0)-mub)**2)*isia2)- np.log(isia2)))
nll = lambda *args: -lnlike(*args)
result = op.minimize(nll, [m_t, d_t], args=(za, mua,sia))
m_ml, d_ml = result["x"]
print(m_ml, d_ml)
I think scipy is not able to handle illegal values generated due to the square root.If so, how can one bypass the illegal values?
the dataset1 file can be found at the link:https://drive.google.com/file/d/1HDzQ7rz_u9y63ECNkhtB49T2KBvu0qu6/view?usp=sharing

'numpy.ndarray' object is not callable when using a CALLABLE function in minimization

I keep getting the numpy.ndarray object is not callable error. I know that this mistake happens because one uses an np.array instead of a function. The problem in my code, is that I am indeed using a function to run the minimize python function.
Could someone please let me know what is happening?
The code is here:
# -*- coding: utf-8 -*-
"""
Created on Thu Oct 15 06:27:54 2015
"""
# -*- coding: utf-8 -*-
"""
Created on Mon Oct 12 20:22:27 2015
"""
# Midterm Macroeconometrics
import numpy as np
from numpy import log
import numpy.linalg as linalg
from scipy import *
from scipy.optimize import fminbound, broyden1, brentq, bisect, minimize
from scipy import interp
import pylab as pl
#from numdifftools import Gradient, Jacobian, Derivative
import matplotlib.pyplot as plt
import pandas as pd
from mpl_toolkits.mplot3d import axes3d
from matplotlib import cm
import scipy.io as sio
import os
"""
IMPORTING DATA FROM PANDAS
"""
#Importing data from text file- using Pandas.
os.chdir(r'/Users/camilahenao/Dropbox/UIUC Phd Econ/Year 3/Fall/macroeconometrics shin/Homework/ps3-MIDTERM')
os.path.abspath(os.path.curdir)
data=pd.read_csv(r'midterm2015.csv', header= None)
data.columns = ['GDP_I', 'GDP_E']
GDP_I=np.array(data.GDP_I)
GDP_E=np.array(data.GDP_E)
y= np.vstack((GDP_I,GDP_E))
def kalman2(a_old, p_old, Z, gamma, theta, y):
mu, rho, h_I, h_E, h_G = theta[0], theta[1], np.log(theta[2]), np.log(theta[3]), np.log(theta[4])
sigma_I= np.exp(h_I)
sigma_E= np.exp(h_E)
sigma_G= np.exp(h_G)
H = np.array([[sigmaI,0],[0, sigmaE]])
H=np.matrix(H)
list_a = np.array([a_old])
list_p = np.array([p_old])
list_f = np.array([])
list_v = np.array([])
log_likelihood_Y= np.array([ ])
list_log_like_sum = np.array([])
for i in range(y[0].size):
N=y.shape[0]
Time=y[0].size
inv= np.matrix(linalg.inv(Z*p_old*Z.T+H))
cosa= Z.T*inv
temp= p_old*cosa
a_new= np.array(a_old +temp*(np.array([[y[0][i]],[y[1][i]]])-Z*a_old-gamma*w))[0]
list_a=np.hstack((list_a,a_new))
p_new= np.array(p_old - temp* Z*p_old)[0]
list_p=np.hstack((list_p, p_new))
#Transform the previous posterior into prior-
a_old=T*a_new
a_old=a_old[0]
p_old=T*p_new*T + R*Q*R #25
#Moments for log-likelihood:
f= np.linalg.det(Z*p_old*Z.T + H)
list_f= np.hstack((list_f,f))
#print list_f
v= np.array([[y[0][i]],[y[1][i]]])-Z*a_old - gamma*w
v_element= np.array((v.T *np.matrix(np.linalg.inv(Z*p_old*Z.T + H)) *v))[0]
list_v=np.hstack((list_v,v_element))
#print list_v
#Log likelihood function for each period of time:
log_like= (-N*(Time-1)/2*np.log(2*pi)-(1/2)*sum(log(list_f)) -(1/2)*sum(list_v))
log_likelihood_Y=np.hstack((log_likelihood_Y, log_like))
#Create the sum over all Time of the log-likelihood
log_like_sum=np.sum(log_likelihood_Y)
list_log_like_sum=np.hstack((list_log_like_sum, log_like_sum))
return list_a, list_p, log_likelihood_Y, list_log_like_sum
#Define the "callable function"
def mle(a_old, p_old, Z, gamma, theta, y, bds):
a, P, py, py_sum = kalman2(a_old, p_old, Z, gamma, theta, y)
mle= -1*py_sum
return mle
#Run the minimization algorithm
theta2=(.8, 3.0, 5.0, 5.0, 5.0)
a_old=0.0
p_old= sigmaG/(1-rho**2)
Z=np.array([[1.0],[1.0]])
gamma=np.array([[1.0],[1.0]])
bds = [[-10e100, 10e100], [-10e100, 10e100], [1e-6, 10e100], [1e-6, 10e100], [1e-6, 10e100]]
theta_guess = [3, 0.8, np.sqrt(5), np.sqrt(5), np.sqrt(5)]
result = minimize(mle(a_old, p_old, Z, gamma, theta, y, bds), theta_guess, bounds = bds)
As Warren Weckesser mentioned in a comment, you're passing the result of calling mle(a_old, p_old, Z, gamma, theta, y, bds) — which is a floating point value — as the first argument to the minimize() function. According to the scipy documentation the first argument to minimize() should be a callable function, so for starters you're going to need to change the call it so it's something like this:
result = minimize(mle, (a_old, p_old, Z, gamma, theta, y, bds),
theta_guess, bounds=bds)
However you're going to run into new problems because your mle() function doesn't accept a vector as its first argument, which is required of the function you pass to minimize() — so you're also going to need to modify its definition accordingly.
Unfortunately I don't understand enough of what you're actually trying to accomplish to suggest how you should do that.

Categories