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.
Related
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.
I am trying to compute a definite integral of a 2*10 matrix. I need to compute its definite integral from zero to t as we know the results must coincide to the sinus table.
Here is the code before reaching the goal gives error. The error probably is for the last lines.
I would be so thankful if you guide me please.
import numpy as np
import math
import matplotlib.pyplot as plt
from scipy import integrate
from scipy.integrate import quad
from numpy import linalg as LA
from numpy.linalg import matrix_power
from scipy import linalg
from sympy import *
import scipy.integrate as it
from numpy import vectorize
############
from numba import vectorize, float64
##############################
# Constants
tmax = 20
t = np.arange(0.0, tmax, 1)
t0=0
m=len(t)
#print(t)
etest=np.matrix([[np.sqrt(0),np.sqrt(1),np.sqrt(2) ,np.sqrt(3),np.sqrt(4),np.sqrt(5),np.sqrt(6),np.sqrt(7),np.sqrt(8),np.sqrt(9)],
[np.sqrt(10),np.sqrt(11),np.sqrt(12), np.sqrt(13),np.sqrt(14),np.sqrt(15),np.sqrt(16),np.sqrt(17),np.sqrt(18),np.sqrt (19)]])
pow = np.power( etest, 2 )
pow0=pow[0]
pow1=pow[1]
def norm2etest(xx):
sum= pow0+pow1
return sum
ans2=norm2etest(etest)
print(ans2)
def outerfun(norm2etest):
return np.cos(norm2etest)
def integrandtest(xx):
return outerfun(norm2etest(xx))
ttt=outerfun(norm2etest(etest))
#print(ttt)
for tnow in np.arange(0.0, tmax, 1):
numnow=1*tnow
num=np.array(numnow,dtype=int)
#np.vectorize
def integratetest(i):
def integrandtest(t):
return outerfun(norm2etest(t))[i]
I, ff = quad(integrandtest, t0,tnow)
return I
###########################
INTERVALtest=np.arange(0,10)
ANS1=integratetest(INTERVALtest)
print(INTERVALtest)
#print(ANS1.size)
gives this error
Traceback (most recent call last):
File "C:\Users\user\OneDrive\Desktop\44integral.py", line 58, in <module>
ANS1=integratetest(INTERVALtest)
File "C:\Users\user\AppData\Local\Programs\Python\Python37\lib\site-packages\numpy\lib\function_base.py", line 2163, in __call__
return self._vectorize_call(func=func, args=vargs)
File "C:\Users\user\AppData\Local\Programs\Python\Python37\lib\site-packages\numpy\lib\function_base.py", line 2241, in _vectorize_call
ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args)
File "C:\Users\user\AppData\Local\Programs\Python\Python37\lib\site-packages\numpy\lib\function_base.py", line 2201, in _get_ufunc_and_otypes
outputs = func(*inputs)
File "C:\Users\user\OneDrive\Desktop\44integral.py", line 54, in integratetest
I, ff = quad(integrandtest, t0,tnow)
File "C:\Users\user\AppData\Local\Programs\Python\Python37\lib\site-packages\scipy\integrate\quadpack.py", line 352, in quad
points)
File "C:\Users\user\AppData\Local\Programs\Python\Python37\lib\site-packages\scipy\integrate\quadpack.py", line 463, in _quad
return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
TypeError: only size-1 arrays can be converted to Python scalars
I'm trying to estimate a maximum likelihood model in python. I set up both the likelihood function and the analytic jacobian. When I run scipy minimize, I get a bizarre error (displayed below). This error doesn't seem to occur when I omit the jacobian, but I can't figure out why.
from numpy import log,sum,var
from numba import njit
#njit
def log_likelihood(params,surg_fx,surg_fx_ses):
mu_var = params[0]
exp_var = mu_var + surg_fx_ses**2
log_lik = -((surg_fx)**2 / (2*exp_var)) - .5*log(exp_var)
neg_sum_log_lik = -sum(log_lik)
print(mu_var)
print(neg_sum_log_lik)
if np.isnan(neg_sum_log_lik):
return 1e20
else:
return neg_sum_log_lik
#njit
def log_lik_jac(params,surg_fx,surg_fx_ses):
mu_var = params[0]
exp_var = mu_var + surg_fx_ses**2
jc = -sum(((surg_fx)**2 / (2*(exp_var**2))) - (.5/exp_var))
print(mu_var)
print(jc)
return jc
x0 = [np.var(cost_params3)]
shrinkage_est = minimize(log_likelihood,x0,args=(cost_params3,cost_SEs3),jac=log_lik_jac,options={'disp':True},method='BFGS')
cost_params3 and cost_SEs3 are (205,)-shaped numpy arrays.
And the return is:
0.10423462356390442
-580.1534424527905
0.10423462356390442
-67.02947836460727
[ 1.11423462]
26.84532144252225
[ 1.11423462]
77.95606471086792
[ 0.3741784]
-54.28224588483895
[ 0.3741784]
150.90730570822998
[ 0.19152581]
-79.19268133113846
[ 0.19152581]
68.81484893304786
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/anaconda3/lib/python3.5/site-packages/scipy/optimize/_minimize.py", line 444, in minimize
return _minimize_bfgs(fun, x0, args, jac, callback, **options)
File "/usr/local/anaconda3/lib/python3.5/site-packages/scipy/optimize/optimize.py", line 973, in _minimize_bfgs
A1 = I - sk[:, numpy.newaxis] * yk[numpy.newaxis, :] * rhok
TypeError: 'float' object is not subscriptable
I'm not really sure why this runs for a few iterations and just fails, especially given that nothing is being subscripted here. I'm also not sure why it seems to become a list after the first iteration? I tried running it without numba but it stopped at the same place with a different error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/anaconda3/lib/python3.5/site-packages/scipy/optimize/_minimize.py", line 444, in minimize
return _minimize_bfgs(fun, x0, args, jac, callback, **options)
File "/usr/local/anaconda3/lib/python3.5/site-packages/scipy/optimize/optimize.py", line 973, in _minimize_bfgs
A1 = I - sk[:, numpy.newaxis] * yk[numpy.newaxis, :] * rhok
IndexError: invalid index to scalar variable.
Any help would be much appreciated!
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
I'm trying to code a multiple linear regression. Here's the line of code where my program raises an error:
least = optimize.minimize(residsq(xmat, ylist, coeff), coeff, constraints = ({'type': 'eq', 'fun': sum(resid(xmat, ylist, coeff))}), method = 'BFGS') # Choose the coefficients that minimize the sum of the residuals squared subject to keeping the sum of the residuals equal to 0.
xmat is a list of vectors: [[3,5,2],[3,1,6],[7,2,3], [9,-2,0]]. ylist is a list of the same length as xmat: [5,2,7,7]. coeff is the coefficient list, initially [mean(ylist), 0, 0, 0] ([constant, b_0, b_1, b_2]). resid is the list of residuals for each point, and residsq is the N2 norm of the residuals (sqrt of sum of squares).
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
import linregtest
File "C:\Python33\lib\site-packages\linregtest.py", line 4, in <module>
out = linreg.multilinreg(xmat, ylist, True)
File "C:\Python33\lib\site-packages\linreg.py", line 120, in multilinreg
least = optimize.minimize(residsq(xmat, ylist, coeff), coeff, constraints = ({'type': 'eq', 'fun': sum(resid(xmat, ylist, coeff))}), method = 'BFGS') # Choose the coefficients that minimize the sum of the residuals squared subject to keeping the sum of the residuals equal to 0.
File "C:\Python33\lib\site-packages\scipy\optimize\_minimize.py", line 302, in minimize
RuntimeWarning)
File "C:\Python33\lib\idlelib\PyShell.py", line 60, in idle_showwarning
file.write(warnings.formatwarning(message, category, filename,
AttributeError: 'NoneType' object has no attribute 'write'
Where does file come from, and how do I suppress this error?
EDIT: Solve one problem, find another. Maybe you can help me determine where SciPy is calling a float?
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
import linregtest
File "C:\Python33\lib\site-packages\linregtest.py", line 4, in <module>
out = linreg.multilinreg(xmat, ylist, True)
File "C:\Python33\lib\site-packages\linreg.py", line 123, in multilinreg
least = optimize.minimize(residsq(xmat, ylist, coeff), coeff, constraints = ({'type': 'eq', 'fun': sumresid(xmat, ylist, coeff)}), method = 'SLSQP') # Choose the coefficients that minimize the sum of the residuals squared subject to keeping the sum of the residuals equal to 0.
File "C:\Python33\lib\site-packages\scipy\optimize\_minimize.py", line 364, in minimize
constraints, **options)
File "C:\Python33\lib\site-packages\scipy\optimize\slsqp.py", line 301, in _minimize_slsqp
meq = sum(map(len, [atleast_1d(c['fun'](x, *c['args'])) for c in cons['eq']]))
File "C:\Python33\lib\site-packages\scipy\optimize\slsqp.py", line 301, in <listcomp>
meq = sum(map(len, [atleast_1d(c['fun'](x, *c['args'])) for c in cons['eq']]))
TypeError: 'float' object is not callable
I just edited my python 3.2 IDLE, PyShell.py (fixing lines 59 and 62)
def idle_showwarning(message, category, filename, lineno,
file=None, line=None):
if file is None:
file = sys.stderr #warning_stream
try:
file.write(warnings.formatwarning(message, category, filename,
lineno, line=line))
use sys.stderr instead of the global warning_stream which uses sys.__stderr__. sys.__stderr__ is None in my case. I don't know why a global is used.
the call to warnings.formatwarning had an extra invalid file keyword.
Now, I get the warning printed, for example
>>> import numpy as np
>>> np.uint(1) - np.uint(2)
Warning (from warnings module):
File "C:\Programs\Python32\Lib\idlelib\idle.pyw", line 1
try:
RuntimeWarning: overflow encountered in ulong_scalars
>>> 4294967295
>>>
edit:
searching for python bug reports
http://bugs.python.org/issue12438 wrong file argument has been fixed
http://bugs.python.org/issue13582 problems with sys.__stderr__ is None is open