I have been trying to perform some global optimization with SciPy optimizer SHGO
and I've had issues with the sampling metod 'sobol'
. Specifically, I get an error of the type: TypeError: <lambda>() takes 1 positional argument but 3 were given
.
The thing that makes me suspect it may be related with something wrong with the sampling method per se is that the error doesn't happen when I use simplicial
as sampling method or a different (still constrained) optimization algorithm such as SLSQP
.
Here's the code, I'm interested in understanding if someone else can reproduce this error.
import numpy as np
from numpy import linalg as la
import scipy as sc
import scipy.optimize as opt
print("numpy version: ", np.__version__)
print("scipy version: ", sc.__version__)
# d-dim Shannon entropy
def ShEntr(x):
s=0
for p_i in x:
if p_i > 1e-16 and p_i < 1-1e-16:
s = s - p_i*np.log2(p_i)
return s
# Function to be optimized
def fun(y, k, g):
p,c = y
mat = [[p,c],[c,1-p]]
return -ShEntr(la.eigvals(mat)) #- sign in front of it due to the fact that scipy.otimize is a minimization
# Optimization parameters
x0 = [0.5,0.2] # Starting point for SLSQP
boun = [(0,1),(0,1)] # Optimization parameters bounds
cons = ({'type':'ineq', 'fun': lambda y: y[0]-y[0]**2-y[1]**2}) # Optimization parameters constraints
## Optimization
# SLSQP
res = opt.minimize(fun, x0, (0.3,0.3), method='SLSQP', constraints=cons, bounds=boun, options={'maxiter':10000})
print("SLSQP: ", -res.fun)
# SHGO: simplicial
res = opt.shgo(fun, bounds=boun, args=(0.3,0.3), n = 30, iters = 5, sampling_method = 'simplicial', constraints=cons)
print("SHGO simplicial: ", -res.fun)
# SHGO: sobol
res = opt.shgo(fun, bounds=boun, args=(0.3,0.3), n = 30, iters = 5, sampling_method = 'sobol', constraints=cons)
print("SHGO sobol: ", -res.fun)
And here's what I get
numpy version: 1.20.3
scipy version: 1.7.3
SLSQP: 0.9999999999999942
SHGO simplicial: 1.0
Traceback (most recent call last):
File "... path /test.py", line 36, in <module>
res = opt.shgo(fun, bounds=boun, args=(0.3,0.3), n = 30, iters = 5, sampling_method = 'sobol', constraints=cons)
File "... path \Anaconda3\lib\site-packages\scipy\optimize\_shgo.py", line 419, in shgo
shc.construct_complex()
File "... path \Anaconda3\lib\site-packages\scipy\optimize\_shgo.py", line 733, in construct_complex
self.iterate()
File "... path \Anaconda3\lib\site-packages\scipy\optimize\_shgo.py", line 876, in iterate
self.iterate_complex()
File "... path \Anaconda3\lib\site-packages\scipy\optimize\_shgo.py", line 912, in iterate_delaunay
self.sampled_surface(infty_cons_sampl=self.infty_cons_sampl)
File "... path \Anaconda3\lib\site-packages\scipy\optimize\_shgo.py", line 1243, in sampled_surface
self.fun_ref()
File "... path \Anaconda3\lib\site-packages\scipy\optimize\_shgo.py", line 1356, in fun_ref
if g(self.C[i, :], *self.args) < 0.0:
TypeError: <lambda>() takes 1 positional argument but 3 were given
P.S.: I understand that the function fun(y, k, g)
here doesn't need args k
and g
, but I just (over)simplified the original function I was using (that needs k
and g
) to reproduce the error.