Is it possible to vectorize scipy fsolve? - python

I know how to use fsolve in scipy
from scipy.optimize import fsolve
import numpy as np
k=4
def equations(p):
x,y=p
eq_1 = x+y-k
eq_2 = x-y
return (eq_1,eq_2)
fsolve(equations, (0,0))
But I don't know how to vectorize this function if k is a numpy array.
(I could do it in a loop for different value of k, but if will take a lot of time).
Is there a solution like :
from scipy.optimize import fsolve
import numpy as np
k=np.arange(10000)
def equations(p):
x,y=p
eq_1 = x+y-k
eq_2 = x-y
return (eq_1,eq_2)
fsolve(equations, (np.zeros(10000),np.zeros(10000)))
Thank's a lot if you have any idea
EDIT :
The link that some of you give below increases the calculation time as each line are not necessary independant.
For example, you can test those two code :
s=1000
#With array
t0=time.time()
k=np.arange(s)
def equations(p):
eq_1 = p**2-k
return (eq_1)
res=fsolve(equations, np.ones((s)))
print(time.time()-t0)
#With loop
t0=time.time()
res=np.zeros((s))
i=0
def equations(p):
eq_1 = p**2-i
return (eq_1)
while i<s:
res[i]=fsolve(equations, 1)[0]
i+=1
print(time.time()-t0)
Result
10.85175347328186
0.05588793754577637
Is there a way to avoid a loop but to keep a good speed with vectorize function

Not directly.
There is cython_optimize interface though, https://docs.scipy.org/doc/scipy/reference/optimize.cython_optimize.html
So you can drop to cython and implement the loops manually. YMMV though

Related

Optimize with another variable

sorry i am a real beginner in Python and I really need help to understand this:
So basically I have a function who takes 4 arguments:
def expected_utility(p,y,x,q):
return p*u(y-x+q-premium(p,q), theta)+(1-p)*u(y-premium(p,q))
(premium and u are function already defined)
I already have the value of p(=0.2) and y(=1) and I need to find the optimal q's* for several x between 0.01 and 0.9.
This is my entire code I have done so far:
import numpy as np
from scipy.optimize import minimize
import matplotlib.pyplot as plt
def premium(p,q):
return p*q
def u(z,theta):
return (z**(1+theta))/(1+theta)
def expected_utility(p,y,x,q):
return p*u(y-x+q-premium(p,q), theta)+(1-p)*u(y-premium(p,q))
theta=-2
y=1
p=0.2
N=100
x_array=np.linspace(0.01,0.9,N)
qs_optimal=np.empty(N)
And now I should create a loop for all x's in the x_array and use scipy.optimize.minimize_scalar to find all the optimals q's and store them in the qs_optimal array. How can I proceed? Thank you very very much for your help.

Numerical integration for matrix values in Python

I am trying to integrate over some matrix entries in Python. I want to avoid loops, because my tasks includes 1 Mio simulations. I am looking for a specification that will efficiently solve my problem.
I get the following error: only size-1 arrays can be converted to Python scalars
from scipy import integrate
import numpy.random as npr
n = 1000
m = 30
x = npr.standard_normal([n, m])
def integrand(k):
return k * x ** 2
integrate.quad(integrand, 0, 100)
This is a simplied example of my case. I have multiple nested functions, such that I cannot simple put x infront of the integral.
Well you might want to use parallel execution for this. It should be quite easy as long as you just want to execute integrate.quad 30000000 times. Just split your workload in little packages and give it to a threadpool. Of course the speedup is limited to the number of cores you have in your pc. I'm not a python programer but this should be possible. You can also increase epsabs and epsrel parameters in the quad function, depending on the implemetation this should speed up the programm as well. Of course you'll get a less precise result but this might be ok depending on your problem.
import threading
from scipy import integrate
import numpy.random as npr
n = 2
m = 3
x = npr.standard_normal([n,m])
def f(a):
for j in range(m):
integrand = lambda k: k * x[a,j]**2
i =integrate.quad(integrand, 0, 100)
print(i) ##write it to result array
for i in range(n):
threading.Thread(target=f(i)).start();
##better split it up even more and give it to a threadpool to avoid
##overhead because of thread init
This is maybe not the ideal solution but it should help a bit. You can use numpy.vectorize. Even the doc says: The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop. But still, a %timeit on the simple example you provided shows a 2.3x speedup.
The implementation is
from scipy import integrate
from numpy import vectorize
import numpy.random as npr
n = 1000
m = 30
x = npr.standard_normal([n,m])
def g(x):
integrand = lambda k: k * x**2
return integrate.quad(integrand, 0, 100)
vg = vectorize(g)
res = vg(x)
quadpy (a project of mine) does vectorized quadrature:
import numpy
import numpy.random as npr
import quadpy
x = npr.standard_normal([1000, 30])
def integrand(k):
return numpy.multiply.outer(x ** 2, k)
scheme = quadpy.line_segment.gauss_legendre(10)
val = scheme.integrate(integrand, [0, 100])
This is much faster than all other answers.

Python: ValueError: setting an array element with a sequence. Error while solving simple ode

I have written a simple python code to simulate adaptive fuzzy sliding mode control. My problem is no matter what I do, I get this error. I tried converting list to arrays etc. But to no effect. Kindly help me iron out this issue. What I am trying to do, is, I have created a function that returns 53 elements and then the ode method of scipy integrates it.
Here is my code. PFA-
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import ode
from numpy import exp,sin,cos,concatenate,transpose,pi,tanh
from mpl_toolkits.mplot3d import Axes3D
c,eta,k,gamma1,gamma2,gamma3,gamma4,gamma5,gamma21,gamma22,gamma23,gamma24,gamma25=2,1.5,2,1,2,3,4,5,6,7,8,9,10
x=np.linspace(0,10,100)
xdot=np.linspace(0,10,100)
def member(x,z):
return exp(-((x+z)/(pi/24))**2)
m=[]
b=[pi/6,pi/12,0,-pi/12,-pi/6]
def f(t,Y):
x1,x2,x3,eta1,eta2,eta3,eta4,eta5,eta6,eta7,eta8,eta9,eta10,eta11,eta12,eta13,eta14,eta15,eta16,eta17,eta18,eta19,eta20,eta21,eta22,eta23,eta24,eta25,geta1,geta2,geta3,geta4,geta5,geta6,geta7,geta8,geta9,geta10,geta11,geta12,geta13,geta14,geta15,geta16,geta17,geta18,geta19,geta20,geta21,geta22,geta23,geta24,geta25=Y
eta=np.array([eta1,eta2,eta3,eta4,eta5,eta6,eta7,eta8,eta9,eta10,eta11,eta12,eta13,eta14,eta15,eta16,eta17,eta18,eta19,eta20,eta21,eta22,eta23,eta24,eta25])
geta=np.array([geta1,geta2,geta3,geta4,geta5,geta6,geta7,geta8,geta9,geta10,geta11,geta12,geta13,geta14,geta15,geta16,geta17,geta18,geta19,geta20,geta21,geta22,geta23,geta24,geta25])
m,z=[],[]
for i in range(5):
for j in range(5):
m.append(member(x1,b[i])*member(x2,b[j]))
for i in range(25):
z.append(m[i]/sum(m))
z=np.array(z)
e,de=x1-sin(t),x2-cos(t)
s=de+c**2*x3+2*c*e
f=np.dot(eta,z)
g=np.dot(geta,z)
u=(1./g)*(-f-c**2*e-2*c*de-sin(t)-eta*tanh(s)-k*s)
x1dot=x2
x2dot=f+g*u
x3dot=e
eta1dot,eta2dot,eta3dot,eta4dot,eta5dot,eta6dot,eta7dot,eta8dot,eta9dot,eta10dot,eta11dot,eta12dot,eta13dot,eta14dot,eta15dot,eta16dot,eta17dot,eta18dot,eta19dot,eta20dot,eta21dot,eta22dot,eta23dot,eta24dot,eta25dot,geta1dot,geta2dot,geta3dot,geta4dot,geta5dot,geta6dot,geta7dot,geta8dot,geta9dot,geta10dot,geta11dot,geta12dot,geta13dot,geta14dot,geta15dot,geta16dot,geta17dot,geta18dot,geta19dot,geta20dot,geta21dot,geta22dot,geta23dot,geta24dot,geta25dot=-2*s*z[0],-2*s*z[1],-2*s*z[2],-2*s*z[3],-2*s*z[4],-2*s*z[5],-2*s*z[6],-2*s*z[7],-2*s*z[8],-2*s*z[9],-2*s*z[10],-2*s*z[11],-2*s*z[12],-2*s*z[13],-2*s*z[14],-2*s*z[15],-2*s*z[16],-2*s*z[17],-2*s*z[18],-2*s*z[19],-2*s*z[20],-2*s*z[21],-2*s*z[22],-2*s*z[23],-2*s*z[24],-3*s*z[0]*u,-3*s*z[1]*u,-3*s*z[2]*u,-3*s*z[3]*u,-3*s*z[4]*u,-3*s*z[5]*u,-3*s*z[6]*u,-3*s*z[7]*u,-3*s*z[8]*u,-3*s*z[9]*u,-3*s*z[10]*u,-3*s*z[11]*u,-3*s*z[12]*u,-3*s*z[13]*u,-3*s*z[14]*u,-3*s*z[15]*u,-3*s*z[16]*u,-3*s*z[17]*u,-3*s*z[18]*u,-3*s*z[19]*u,-3*s*z[20]*u,-3*s*z[21]*u,-3*s*z[22]*u,-3*s*z[23]*u,-3*s*z[24]*u
return[x1dot,x2dot,x3dot,eta1dot,eta2dot,eta3dot,eta4dot,eta5dot,eta6dot,eta7dot,eta8dot,eta9dot,eta10dot,eta11dot,eta12dot,eta13dot,eta14dot,eta15dot,eta16dot,eta17dot,eta18dot,eta19dot,eta20dot,eta21dot,eta22dot,eta23dot,eta24dot,eta25dot,geta1dot,geta2dot,geta3dot,geta4dot,geta5dot,geta6dot,geta7dot,geta8dot,geta9dot,geta10dot,geta11dot,geta12dot,geta13dot,geta14dot,geta15dot,geta16dot,geta17dot,geta18dot,geta19dot,geta20dot,geta21dot,geta22dot,geta23dot,geta24dot,geta25dot]
Y,t=[],[]
for i in range(50):
Y.append(0.1)
#Y=np.array(Y)
y0=[0,0,0]
y0=y0+Y
t0=0
def int_amar():
t1,dt=10,.01
x=[]
for i in range(53):
x.append([])
#import pdb; pdb.set_trace()
odee=ode(f).set_integrator('dopri5',method='bdf',nsteps=1e6)
odee.set_initial_value(y0,t0)
while odee.successful() and odee.t<t1:
odee.integrate(odee.t+dt)
for i in range(53):
x[i].append(odee.y[i])
t.append(odee.t)
#for i in range(53):
# x[i]=np.array(x[i])
print(x1.shape)
return x
def main():
fun=int_amar()
Z,f,g,m=[[],[],[],[],[]],[],[],[]
for i in range(5):
for j in range(5):
m.append(member(fun[0],b[i])*member(fun[1],b[j]))
for i in range(25):
Z[i].append(m[i]/sum(m))
zetta1,zetta2,zetta3,zetta4,zetta5,zetta6,zetta7,zetta8,zetta9,zetta10,zetta11,zetta12,zetta13,zetta14,zetta15,zetta16,zetta17,zetta18,zetta19,zetta20,zetta21,zetta22,zetta23,zetta24,zetta25=Z[0],Z[1],Z[2],Z[3],Z[4],Z[5],Z[6],Z[7],Z[8],Z[9],Z[10],Z[11],Z[12],Z[13],Z[14],Z[15],Z[16],Z[17],Z[18],Z[19],Z[20],Z[21],Z[22],Z[23],Z[24],Z[25]
e=fun[0]-sin(t)
s=fun[1]+c**2*fun[2]+2*c*e
for i in range(len(fun[2])):
f.append(np.dot(np.array([[fun[3][i],fun[4][i],fun[5][i],fun[6][i],fun[7][i],fun[8][i],fun[9][i],fun[10][i],fun[11][i],fun[12][i],fun[13][i],fun[14][i],fun[15][i],fun[16][i],fun[17][i],fun[18][i],fun[19][i],fun[20][i],fun[21][i],fun[22][i],fun[23][i],fun[24][i],fun[25][i],fun[26][i],fun[27][i]]]),np.array([[zetta1[i]],[zetta2[i]],[zetta3[i]],[zetta4[i]],[zetta5[i]],[zetta6[i]],[zetta7[i]],[zetta8[i]],[zetta9[i]],[zetta10[i]],[zetta11[i]],[zetta12[i]],[zetta13[i]],[zetta14[i]],[zetta15[i]],[zetta16[i]],[zetta17[i]],[zetta18[i]],[zetta19[i]],[zetta20[i]],[zetta21[i]],[zetta22[i]],[zetta23[i]],[zetta24[i]],[zetta25[i]]])))
g.append(np.dot(np.array([[fun[28][i],fun[29][i],fun[30][i],fun[31][i],fun[32][i],fun[33][i],fun[34][i],fun[35][i],fun[36][i],fun[37][i],fun[38][i],fun[39][i],fun[40][i],fun[41][i],fun[42][i],fun[43][i],fun[44][i],fun[45][i],fun[46][i],fun[47][i],fun[48][i],fun[49][i],fun[50][i],fun[51][i],fun[52][i]]]),np.array([[zetta1[i]],[zetta2[i]],[zetta3[i]],[zetta4[i]],[zetta5[i]],[zetta6[i]],[zetta7[i]],[zetta8[i]],[zetta9[i]],[zetta10[i]],[zetta11[i]],[zetta12[i]],[zetta13[i]],[zetta14[i]],[zetta15[i]],[zetta16[i]],[zetta17[i]],[zetta18[i]],[zetta19[i]],[zetta20[i]],[zetta21[i]],[zetta22[i]],[zetta23[i]],[zetta24[i]],[zetta25[i]]])))
f,g=np.array(f),np.array(g)
u=(1./g)*(-f-c*e-sin(t)-eta*tanh(s)-k*s)
print(u.shape)
for i in range(12):
plt.subplot(3,4,i+1)
plt.plot(t,fun[i])
#plt.figure(2)
#plt.plot(t,u)
plt.show()
if __name__=='__main__':
main()
The issue is on line 30:
u=(1./g)*(-f-c**2*e-2*c*de-sin(t)-eta*tanh(s)-k*s)
eta is an array but the rest of the terms are scalars. This causes u to be an array and the resulting return list has a mix of scalars and arrays.
You probably mistyped the equation here.

My variable is coming up as not defined, when I think I have defined it

This is my code
#project starts here
import numpy as np
import scipy.integrate
import matplotlib.pyplot as plt
from numpy import pi
from scipy.integrate import odeint
def deriv(cond,t):
for q in range (0,N):
i=6*q
dydt[i]=cond[i+3]
dydt[i+1]=cond[i+4]
dydt[i+2]=cond[i+5]
r=sqrt((cond[i])**2 +(cond[i+1])**2 +(cond[i+2])**2)
dydt[i+3]=-G*M*cond[i]/(r**3)
dydt[i+4]=-G*M*cond[i+1]/(r**3)
dydt[i+5]=-G*M*cond[i+2]/(r**3)
return dydt
G=1
M=1
N=12
vmag=((G*M)/(2))**(0.5)
theta = np.linspace(0,2*pi,N)
x=2*np.cos(theta)
y=2*np.sin(theta)
vx=-vmag*np.sin(theta)
vy=vmag*np.cos(theta)
z=np.zeros(N)
vz=np.zeros(N)
t=np.linspace(0,30,100)
cond=list(item for group in zip(x,y,z,vx,vy,vz) for item in group)
sln=odeint(deriv, cond, t, args=(G,M))
I am getting an error message about dydt not being defined. I thought I had defined it within my derivatives function. My intention is for it to be a vector with the appropriate derivatives in it (hence the use of i) of the cond array. Why is my definition wrong?
"dydt" is not defined, you should define it before you can use indexes on it.
Regarding your code, you could do something like this:
i = 6*q
dydt = list(range(i))

Optimising two arrays simultaneously with scipy optimize

I have a function that takes two m-dimensional arrays does some calculation with them (here it is very simplified) and returns one dimensional array. Also I have m-dimensional measurement data and would like to optimise those two arrays to fit the measurements. This worked fine with one arrays. I can just simply not get it to work with two arrays (or more). it always throws:
TypeError: Improper input: N=40 must not exceed M=20
Here is my Code. Thank you very much if anyone can help!
import numpy as np
from scipy import optimize
data=[np.arange(0,20.0,1),np.array([-52.368, 32.221, 40.102, 48.088, 73.106, 50.807, 52.235, 76.933, 65.737, 34.772, 94.376, 123.366, 92.71, 72.25, 165.051, 91.501, 118.92, 100.936, 56.747, 159.034])]
def line(m,b):
return m*b
guessm = np.ones(20) #initial guessed values for m
guessb = np.ones(20) #initial guesses values for b
guess = np.append(guessm,guessb)
errfunc= lambda p,y: (y-line(p[:20],p[20:]))
parameter, sucess = optimize.leastsq(errfunc, guess, args=(data[1]))
print(parameter)
plt.plot(data[0],d[1],'o')
plt.plot(data[0],line(parameter[0],parameter[1]))
plt.show()
If you want to fit a line, you should give the slope and intercept - two parameters, not 40. I suspect this is what you try to do:
import matplotlib.pyplot as plt
import numpy as np
from scipy import optimize
data=[np.arange(0,20.0,1),np.array([-52.368, 32.221, 40.102, 48.088, 73.106, 50.807, 52.235, 76.933, 65.737, 34.772, 94.376, 123.366, 92.71, 72.25, 165.051, 91.501, 118.92, 100.936, 56.747, 159.034])]
def line(m,b):
return np.arange(0, 20, 1)*m + b
guess = np.ones(2)
errfunc= lambda p,y: (y-line(p[0],p[1]))
parameter, sucess = optimize.leastsq(errfunc, guess, args=(data[1]))
print(parameter)
plt.plot(data[0],data[1],'o')
plt.plot(data[0],line(parameter[0],parameter[1]))
plt.show()

Categories