0

使用盆地跳跃时出现此错误: basinhopping_bounds() got an unexpected keyword argument 'f_new'

我正在尝试在 Python 中实现对X、F 模型的分析以解决DTLZ7 问题

所以,我从 4 线性 FO 的问题开始,结果我知道。当尝试使用盆地跳跃来解决问题时,我得到了上面的错误(scipy-1.2.1.)。有谁知道出了什么问题?

下面是部分代码:

f1 = f_linear([0.06, 0.53, 0.18, 0.18, 0.06], "max")
f2 = f_linear([25, 70, 60, 95, 45], "max")
f3 = f_linear([0, 32.5, 300, 120, 0], "min")
f4 = f_linear([0.1, 0.1, 0.11, 0.35, 0.33], "min")
A_eq = np.array([[1, 1, 1, 1, 1]])
b_eq = np.array([3000])
x0_bounds = (0, 850)
x1_bounds = (0, 220)
x2_bounds = (0, 1300)
x3_bounds = (0, 1615)
x4_bounds = (0, 700)
F = [f1, f2, f3, f4]
def mu_D(x, F):
    x = np.array(x)
    return max([f_.mu(x) for f_ in F])
def basinhopping_bounds(x):
    resp = True
    if np.dot(x, A_eq[0]) != b_eq[0]:
        resp = False
    if x[0] < x0_bounds[0] or x[0] > x0_bounds[1]:
        resp = False
    if x[1] < x1_bounds[0] or x[1] > x1_bounds[1]:
        resp = False
    if x[2] < x2_bounds[0] or x[2] > x2_bounds[1]:
        resp = False
    if x[3] < x3_bounds[0] or x[3] > x3_bounds[1]:
        resp = False
    if x[4] < x4_bounds[0] or x[4] > x4_bounds[1]:
        resp = False
    return resp


cobyla_constraints = [
    {"type": "ineq", "fun": lambda x: x[0]},
    {"type": "ineq", "fun": lambda x: x0_bounds[1] - x[0]},
    {"type": "ineq", "fun": lambda x: x[1]},
    {"type": "ineq", "fun": lambda x: x1_bounds[1] - x[1]},
    {"type": "ineq", "fun": lambda x: x[2]},
    {"type": "ineq", "fun": lambda x: x2_bounds[1] - x[2]},
    {"type": "ineq", "fun": lambda x: x[3]},
    {"type": "ineq", "fun": lambda x: x3_bounds[1] - x[3]},
    {"type": "ineq", "fun": lambda x: x[4]},
    {"type": "ineq", "fun": lambda x: x4_bounds[1] - x[4]},
    {"type": "eq", "fun": lambda x: np.dot(x, A_eq[0]) - b_eq[0]},
]
minimizer_kwargs = {"args": F, "method": "SLSQP", "constraints": cobyla_constraints}
opt.basinhopping(
    mu_D,
    f1.x_max,
    minimizer_kwargs=minimizer_kwargs,
    accept_test=basinhopping_bounds,
    disp=True,
)
basinhopping step 0: f 1

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-11-ba4f3efaec5d> in <module>
      5     minimizer_kwargs=minimizer_kwargs,
      6     accept_test=basinhopping_bounds,
----> 7     disp=True,
      8 )

~/anaconda3/lib/python3.6/site-packages/scipy/optimize/_basinhopping.py in basinhopping(func, x0, niter, T, stepsize, minimizer_kwargs, take_step, accept_test, callback, interval, disp, niter_success, seed)
    674                " successfully"]
    675     for i in range(niter):
--> 676         new_global_min = bh.one_cycle()
    677 
    678         if callable(callback):

~/anaconda3/lib/python3.6/site-packages/scipy/optimize/_basinhopping.py in one_cycle(self)
    152         new_global_min = False
    153 
--> 154         accept, minres = self._monte_carlo_step()
    155 
    156         if accept:

~/anaconda3/lib/python3.6/site-packages/scipy/optimize/_basinhopping.py in _monte_carlo_step(self)
    127         for test in self.accept_tests:
    128             testres = test(f_new=energy_after_quench, x_new=x_after_quench,
--> 129                            f_old=self.energy, x_old=self.x)
    130             if testres == 'force accept':
    131                 accept = True

TypeError: basinhopping_bounds() got an unexpected keyword argument 'f_new'

4

2 回答 2

0

https://docs.scipy.org/doc/scipy-0.19.0/reference/generated/scipy.optimize.basinhopping.html

这个文档描述了这个accept_test论点。它必须是可调用的,可以识别一组关键字参数(或者至少在给定它们时不会阻塞):

accept_test : callable, accept_test(f_new=f_new, x_new=x_new, f_old=fold, x_old=x_old), optional

Define a test which will be used to judge whether or not to accept the step. 
This will be used in addition to the Metropolis test based on “temperature” T. 
The acceptable return values are True, False, or "force accept". If any of the 
tests return False then the step is rejected. If the latter, then this will 
override any other tests in order to accept the step. This can be used, for 
example, to forcefully escape from a local minimum that basinhopping is 
trapped in.

您的函数只接受位置参数:

def basinhopping_bounds(x):

您还可以minimize在错误回溯中查看如何调用您的函数:

testres = test(f_new=energy_after_quench, x_new=x_after_quench,
--> 129                            f_old=self.energy, x_old=self.x)
于 2019-05-26T06:12:58.980 回答
0

您的界限定义不正确。在basinhopping您的范围内应该定义为一个类实例。您应该使用以下内容:

import numpy as np
import scipy.optimize as opt


class MyBounds(object):
    ''' 
    bounds class to make sure your variable is with in the inspected bounds
    '''
    def __init__(self, xmin, xmax):
        self.xmax = np.array(xmax)
        self.xmin = np.array(xmin)

    def __call__(self, **kwargs):
        x = kwargs["x_new"]
        tmax = bool(np.all(x <= self.xmax))
        tmin = bool(np.all(x >= self.xmin))
        return tmax and tmin

# init bounds
lower_bounds = [  0,   0,    0,    0,   0]
upper_bounds = [850, 220, 1300, 1615, 700]
my_bounds    = MyBounds(lower_bounds, upper_bounds)

...

# optimize 
result = opt.basinhopping(mu_D,
                          f1.x_max,
                          minimizer_kwargs = minimizer_kwargs,
                          accept_test      = my_bounds,
                          disp             = True)

还可以考虑合并您的约束。如果你使用数组而不是元素约束,你将只有三个约束。但是,查看您的约束(最后一个除外),您只是再次定义了您的界限。

于 2019-05-26T09:43:01.807 回答