Find roots using scipy.optimize.fsolve. What went wrong? - python

I have the code:
import numpy as np
import scipy.optimize
Basic variables:
eee=0.289;
nn=0.63;
E1k=0.0935;
pp=1.25;
B1k=0.12;
v1k=0.126;
Bkk=3.14;
VKb=0.76;
rKb=1.754;
Motion model, these equations are numerically integrated over:
def D2(y,t):
Vr,Vn,r,v,Q,dQ_dt=y
dVr_dt=(aob2*np.sin(Q))/(1-(aob2*t/wb))-1/(r**2)+(Vn**2)/r
dVn_dt=(aob2*np.cos(Q))/(1-((aob2*t)/wb))-(Vr*Vn)/r
dr_dt=Vr
dB_dt=Vn/r
Qt=0
dQ_dtt=0
return [dVr_dt,dVn_dt,dr_dt,dB_dt,Qt,dQ_dtt]
Function, the roots of which we seek:
#-----------------------------------------------------------------
def VrVnRB(x):
v2oA=2*np.arctan(np.sqrt((1+eee)/(1-eee))*np.tan(x[0]/2))
if v2oA>v1k:
v2o=v2oA
else:
v2o=v2oA+2*np.pi
t2=np.linspace(0,x[3],500)
tpas=1/nn*(x[0]-E1k+eee*(np.sin(E1k)-np.sin(x[0])))
Vro2=eee*np.sin(v2o)/np.sqrt(pp)
Vno2=(1+eee*np.cos(v2o))/np.sqrt(pp)
ro2=pp/(1+eee*np.cos(v2o))
Bo2=B1k+v2o-v1k
yo2=[Vro2,Vno2,ro2,Bo2,x[1],x[2]]
EE2=odeint(D2,yo2,t2)
Vrk=EE2[:,0]
Vrk=Vrk[-1]
Vnk=EE2[:,1]
Vnk=Vnk[-1]
rk =EE2[:,2]
rk= rk[-1]
Bk =EE2[:,3]
Bk= Bk[-1]
return [Vrk,Vnk-VKb,rk-rKb,Bk-Bkk]
x0=[E20,Qo2,dQ_dt2,t2b]
#-----------------------------------------------------------------
t1k=scipy.optimize.fsolve(VrVnRB,x0)
But interpreter resents:
File "<tmp 2>", line 36, in <module>
t1k=scipy.optimize.fsolve(VrVnRB,x0)
File "C:\pyzo2013c\lib\site-packages\scipy\optimize\minpack.py", line 139, in fsolve
res = _root_hybr(func, x0, args, jac=fprime, **options)
File "C:\pyzo2013c\lib\site-packages\scipy\optimize\minpack.py", line 208, in _root_hybr
ml, mu, epsfcn, factor, diag)
TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'
I do not understand what my mistake. Please, help.

Related

"Could not broadcast input array" in system of stiff odes inside a loop

I'm trying to solve a system of stiff odes which describes a catalytic heterogeneous reaction. I want to solve this equations for different temperatures, so I'm using a for loop.
import scipy as sc
from scipy.integrate import odeint, solve_ivp
import numpy as np
import matplotlib.pyplot as plt
T=np.array([250,300,350,400,450,500])
for y in T:
y=T
def f(t,x,T=y,tfirst=True):
FA,FB,FC,FD,FE,FF=x
e=2.711828
R=8.314
Tm=723.15
A1=5.5
A2=0.686
A3=1.58
A4=2.6
A5=0.787
E1=90500
E2=165000
E3=150000
E4=139000
E5=132000
SB=-215
HB=-45600
SD=-42
HD=-128000
DH1=-105000
DH2=-1428000
DH3=-862000
DH4=-1323000
DH5=-757000
k1=e**(A1-(E1/R)*((1/T)-(1/Tm)))
k2=e**(A2-(E2/R)*((1/T)-(1/Tm)))
k3=e**(A3-(E3/R)*((1/T)-(1/Tm)))
k4=e**(A4-(E4/R)*((1/T)-(1/Tm)))
k5=e**(A5-(E5/R)*((1/T)-(1/Tm)))
KB=6.54e-12
KD=1.19
m2=0.922
m3=0.906
m4=1.23
m5=0.905
Patm=0.8*101325
FT=178.47
PA=(FA/FT)*Patm
PB=(FB/FT)*Patm
PC=(FC/FT)*Patm
PD=(FD/FT)*Patm
PE=(FE/FT)*Patm
PF=(FF/FT)*Patm
Tast=1/(1+((KB*PB)**0.5)+(KD*PD))
TB=((KB*PB)**0.5)*Tast
TD=KD*PD*Tast
r1=(k1/1000)*TB*PA #mol
r2=(k2/1000)*(TB**m2)*PA
r3=(k3/1000)*(TB**m3)*PA
r4=(k4/1000)*(TB**m4)*PC
r5=(k5/1000)*(TB**m5)*PC
rA=-r1-r2-r3
rB=-r1-7*r2-5*r3-6*r4-4*r5
rC=r1-r4-r5
rD=r1+3*r2+3*r3+2*r4+2*r5
rE=2*r2+2*r4
rF=2*r3+2*r5
FAdot=rA
FBdot=rB
FCdot=rC
FDdot=rD
FEdot=rE
FFdot=rF
return [FAdot,FBdot,FCdot,FDdot,FEdot,FFdot]
x0=(5,5,0,0,0,0)
t0=0
t1=40
soln=solve_ivp(f,(t0,t1),x0,method="Radau",args=(T,))
print(soln.y)
I get the following error:
c:\Users\Axel Flores\Documents\Escuela\Proyectos\Python\import scipy as sc.py:51: RuntimeWarning: invalid value encountered in sqrt
Tast=1/(1+((KB*PB)**0.5)+(KD*PD))
c:\Users\Axel Flores\Documents\Escuela\Proyectos\Python\import scipy as sc.py:52: RuntimeWarning: invalid value encountered in sqrt
TB=((KB*PB)**0.5)*Tast
Traceback (most recent call last):
File "c:\Users\Axel Flores\Documents\Escuela\Proyectos\Python\import scipy as sc.py", line 75, in <module>
soln=solve_ivp(f,(t0,t1),x0,method="Radau",args=(T,))
File "C:\Users\Axel Flores\AppData\Local\Programs\Python\Python310\lib\site-packages\scipy\integrate\_ivp\ivp.py", line 546, in solve_ivp
solver = method(fun, t0, y0, tf, vectorized=vectorized, **options)
File "C:\Users\Axel Flores\AppData\Local\Programs\Python\Python310\lib\site-packages\scipy\integrate\_ivp\radau.py", line 310, in __init__
self.jac, self.J = self._validate_jac(jac, jac_sparsity)
File "C:\Users\Axel Flores\AppData\Local\Programs\Python\Python310\lib\site-packages\scipy\integrate\_ivp\radau.py", line 356, in _validate_jac
J = jac_wrapped(t0, y0, self.f)
File "C:\Users\Axel Flores\AppData\Local\Programs\Python\Python310\lib\site-packages\scipy\integrate\_ivp\radau.py", line 352, in jac_wrapped
J, self.jac_factor = num_jac(self.fun_vectorized, t, y, f,
File "C:\Users\Axel Flores\AppData\Local\Programs\Python\Python310\lib\site-packages\scipy\integrate\_ivp\common.py", line 316, in num_jac
return _dense_num_jac(fun, t, y, f, h, factor, y_scale)
File "C:\Users\Axel Flores\AppData\Local\Programs\Python\Python310\lib\site-packages\scipy\integrate\_ivp\common.py", line 326, in _dense_num_jac
f_new = fun(t, y[:, None] + h_vecs)
File "C:\Users\Axel Flores\AppData\Local\Programs\Python\Python310\lib\site-packages\scipy\integrate\_ivp\base.py", line 133, in fun_vectorized
f[:, i] = self._fun(t, yi)
ValueError: could not broadcast input array from shape (6,6) into shape (6,)
PS C:\Users\Axel Flores>
Anyone could help?
I believe the error is related to the for loop. But everything that I've tried hasn't worked.
Take a hard look on the effect of
for y in T:
y=T
def f(t,x,T=y,tfirst=True):
and how that introduces the extra dimension of size 6.

non linear optimization with incomplete gamma function in constraint in scipy

I want to solve the following optimization problem with scipy (python3):
where I[.,.] is the "incomplete gamma function" (scipy.special.gammainc)
I followed the scipy optimization guide and came up with this code:
from scipy.special import gammainc
from scipy.optimize import NonlinearConstraint
from scipy.optimize import BFGS
from scipy.optimize import minimize
import numpy as np
q = 200
k = 1.5625
alpha = 0.03125
def func(s):
return s
def constraints(s):
return q - k/alpha * (gammainc(k+1, s*alpha) + gammainc(k+1, (s+q)*alpha)) + s*gammainc(k, s*alpha) + (s+q)*gammainc(k, (s+q)*alpha)
nonlinear_constraint = NonlinearConstraint(constraints, -np.inf, 10.0, jac='2-point', hess=BFGS())
s0 = 1000
res = minimize(func, s0, method='trust-constr', jac='2-point', hess=BFGS(), constraints=[nonlinear_constraint], options={'verbose': 1})
print(res.x)
when I run the code, I get this (error) output:
/home/andreasziegler/miniconda3/lib/python3.7/site-packages/scipy/optimize/_hessian_update_strategy.py:187: UserWarning: delta_grad == 0.0. Check if the approximated function is linear. If the function is linear better results can be obtained by defining the Hessian as zero instead of using quasi-Newton approximations.
'approximations.', UserWarning)
Traceback (most recent call last):
File "s_opt.py", line 23, in <module>
res = minimize(func, s0, method='trust-constr', jac='2-point', hess=BFGS(), constraints=[nonlinear_constraint], options={'verbose': 1})
File "/home/andreasziegler/miniconda3/lib/python3.7/site-packages/scipy/optimize/_minimize.py", line 622, in minimize
callback=callback, **options)
File "/home/andreasziegler/miniconda3/lib/python3.7/site-packages/scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py", line 519, in _minimize_trustregion_constr
factorization_method)
File "/home/andreasziegler/miniconda3/lib/python3.7/site-packages/scipy/optimize/_trustregion_constr/tr_interior_point.py", line 329, in tr_interior_point
factorization_method, trust_lb, trust_ub, subprob.scaling)
File "/home/andreasziegler/miniconda3/lib/python3.7/site-packages/scipy/optimize/_trustregion_constr/equality_constrained_sqp.py", line 121, in equality_constrained_sqp
lb_t, ub_t)
File "/home/andreasziegler/miniconda3/lib/python3.7/site-packages/scipy/optimize/_trustregion_constr/qp_subproblem.py", line 499, in projected_cg
r = Z.dot(H.dot(x) + c)
File "/home/andreasziegler/miniconda3/lib/python3.7/site-packages/scipy/sparse/linalg/interface.py", line 415, in dot
return self.matvec(x)
File "/home/andreasziegler/miniconda3/lib/python3.7/site-packages/scipy/sparse/linalg/interface.py", line 229, in matvec
y = self._matvec(x)
File "/home/andreasziegler/miniconda3/lib/python3.7/site-packages/scipy/sparse/linalg/interface.py", line 527, in _matvec
return self.__matvec_impl(x)
File "/home/andreasziegler/miniconda3/lib/python3.7/site-packages/scipy/optimize/_trustregion_constr/projections.py", line 193, in null_space
aux2 = scipy.linalg.solve_triangular(R, aux1, lower=False)
File "/home/andreasziegler/miniconda3/lib/python3.7/site-packages/scipy/linalg/basic.py", line 336, in solve_triangular
b1 = _asarray_validated(b, check_finite=check_finite)
File "/home/andreasziegler/miniconda3/lib/python3.7/site-packages/scipy/_lib/_util.py", line 246, in _asarray_validated
a = toarray(a)
File "/home/andreasziegler/miniconda3/lib/python3.7/site-packages/numpy/lib/function_base.py", line 499, in asarray_chkfinite
"array must not contain infs or NaNs")
ValueError: array must not contain infs or NaNs
which tells me that I did something wrong. It's the first time I use the optimizer in scipy and therefore chances are high, that I misunderstand something (essential). I'm glad for any hint.

Passing jacobian to scipy.optimize.fsolve, when optimising a univariate function

import math
from scipy.optimize import fsolve
def sigma(s, Bpu):
return s - math.sin(s) - math.pi * Bpu
def jac_sigma(s):
return 1 - math.cos(s)
if __name__ == '__main__':
Bpu = 0.5
sig_r = fsolve(sigma, x0=[math.pi], args=(Bpu), fprime=jac_sigma)
Running the above script throws the following error,
Traceback (most recent call last):
File "C:\Users\RP12808\Desktop\_test_fsolve.py", line 12, in <module>
sig_r = fsolve(sigma, x0=[math.pi], args=(Bpu), fprime=jac_sigma)
File "C:\Users\RP12808\AppData\Local\Programs\Python\Python36\lib\site-packages\scipy\optimize\minpack.py", line 146, in fsolve
res = _root_hybr(func, x0, args, jac=fprime, **options)
File "C:\Users\RP12808\AppData\Local\Programs\Python\Python36\lib\site-packages\scipy\optimize\minpack.py", line 226, in _root_hybr
_check_func('fsolve', 'fprime', Dfun, x0, args, n, (n, n))
File "C:\Users\RP12808\AppData\Local\Programs\Python\Python36\lib\site-packages\scipy\optimize\minpack.py", line 26, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
TypeError: jac_sigma() takes 1 positional argument but 2 were given
I am unsure how to pass jacobian to fsolve function... how do solve this?
Thanks in advance..RP
The function that computes the Jacobian matrix must take the same arguments as the function to be solved, and it must return an array:
def jac_sigma(s, Bpu):
return np.array([1 - math.cos(s)])
In general, the Jacobian matrix is a two-dimensional array, but
when the variable is a scalar (as it is here) and the Jacobian "matrix" is 1x1, the code accepts a one- or two-dimensional value. (It might be nice if it also accepted a scalar in this case, but it doesn't.)
Actually, it is sufficient that the return value be "array-like"; e.g. a list is also acceptable:
def jac_sigma(s, Bpu):
return [1 - math.cos(s)]

Python: Scipy.optimize Levenberg-marquardt method

I have a question about how to use the Levenberg-Marquardt optimize method in Python. In the library SCIPY there are many optimization methods.
I tried two methods (Nelder-Mead and Basin-hopping) and both work well with the follow command:
# Nelder-Mead
res0_10 = optimize.minimize(f0_10, x0, method='Nelder-Mead', options={'disp': True, 'maxiter': 2000})
# Basin-hopping
res0_10 = optimize.basinhopping(f0_10, x0, niter=100, disp=True)
The problem emerge when I use the Levenberg-Marquardt (I copy only the part of error, because the program is long)
def f0_10(x):
m, u, z, s = x
for i in range(alt_max):
if i==alt_min: suma=0
if i > alt_min:
suma = suma + (B(x, i)-b0_10(x, i))**2
return np.sqrt(suma/alt_max)
x0 = np.array([40., 0., 500., 50.])
res0_10 = root(f0_10, x0, jac=True, method='lm')
I only change the last sentence (res0_10 = root...). The program compile well, but when I execute the program:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Quini SB\AppData\Local\Enthought\Canopy\App\appdata\canopy-1.7.4.3348.win-x86_64\lib\lib-tk\Tkinter.py", line 1536, in __call__
return self.func(*args)
File "C:\Users\Quini SB\Desktop\tfg\Steyn - levmar.py", line 384, in askopenfilename
res0_10 = root(f0_10, x0, jac=True, method='lm')
File "C:\Users\Quini SB\AppData\Local\Enthought\Canopy\User\lib\site-packages\scipy\optimize\_root.py", line 188, in root
sol = _root_leastsq(fun, x0, args=args, jac=jac, **options)
File "C:\Users\Quini SB\AppData\Local\Enthought\Canopy\User\lib\site-packages\scipy\optimize\_root.py", line 251, in _root_leastsq
factor=factor, diag=diag)
File "C:\Users\Quini SB\AppData\Local\Enthought\Canopy\User\lib\site-packages\scipy\optimize\minpack.py", line 377, in leastsq
shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
File "C:\Users\Quini SB\AppData\Local\Enthought\Canopy\User\lib\site-packages\scipy\optimize\minpack.py", line 26, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
File "C:\Users\Quini SB\AppData\Local\Enthought\Canopy\User\lib\site-packages\scipy\optimize\optimize.py", line 64, in __call__
self.jac = fg[1]
IndexError: invalid index to scalar variable.
Why does this error happen?
From documentation:
jac : bool or callable, optional
If jac is a Boolean and is True, fun is assumed to return the value
of Jacobian along with the objective function. If False, the
Jacobian will be estimated numerically. jac can also be a callable
returning the Jacobian of fun. In this case, it must accept the
same arguments as fun.
So, your function 'f0_10' needs to return two values, because you set jac to True

Use of fsolve and numpy

I have an issu when i'm trying to minimize my (complex matrix) function using fsolve or scipy.optimize.newton but both of them didn't worked. Indeed, my function is 2*2 matrix with complex value. First, I defined my function in a Class i called real() and it is called by my main program MAin.py:
import sys,os
import numpy as np
import random, math
from scipy.optimize import fsolve
from scipy import optimize
class real :
def __init__(self):
self.w = 2
def func1(self,eps):
self.k_ch=2.5*np.exp(eps)
f=np.array([[0,eps*3*self.k_ch+0.032],[0,self.w]])
return f
And my Main program is:
import sys,os
import numpy as np
import random, math, cmath
from scipy.optimize import fsolve
from Carlo import *
A=real()
eps=0.003+0.0042j
C=A.func1(eps)
Cp=0
track=1e-03
variable=np.arange(track,0.1,1)
for track in variable:
Cp=Cp+1
if Cp==1:
eps_real=0
elif Cp==1:
fray=np.array([Cp-1,2])
eps_real=fray/2*3.14*track
R_0= fsolve(C,eps.real)
print R_0
if xtol<=1e-04:
value_stock= np.array([Cp-1,2])
print 'R_0 value is', R_0
But I got this error:
Traceback (most recent call last):
File "Main.py", line 29, in <module>
R_0= fsolve(C,eps.real)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/minpack.py", line 127, in fsolve
res = _root_hybr(func, x0, args, jac=fprime, **options)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/minpack.py", line 183, in _root_hybr
_check_func('fsolve', 'func', func, x0, args, n, (n,))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/minpack.py", line 14, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
TypeError: 'numpy.ndarray' object is not callable
Since i'm a new beginner with python, I don't know how to deal with it. Can you help me please if you have any idea. It seems like maybe fsolve does not like complex value but I got the same error using scipy.optimize.newton.
Thank you.
fsolve needs a function in the first argument. You provided C which is a numpy.ndarray, not a function.
I wonder why you use fsolve while you state you want to minimize a function? In case minimization is what you want, this example straight from the scipy.optimize tutorial might set you on track:
import numpy as np
from scipy.optimize import minimize
def rosen(x):
"""The Rosenbrock function"""
return sum(100.0*(x[1:]-x[:-1]**2.0)**2.0 + (1-x[:-1])**2.0)
x0 = np.array([1.3, 0.7, 0.8, 1.9, 1.2])
res = minimize(rosen, x0, method='nelder-mead',
options={'xtol': 1e-8, 'disp': True})
print(res.x)
[ 1. 1. 1. 1. 1.]

Categories