0

我在优化包含循环的函数时遇到问题。我从lista=[0.002,0.006,0.003,0.02,0.008,0.006,0.05] 浮点数和间隔 `(0,k*0.0025),(0.005,k*0.005),(0.005,k*0.0125) 开始,其中上边界取决于。因此,根据列表的浮点数属于哪个区间,我将值 k*0.005、k*0.01、k*0.025 和 k*0.05 之一分配给函数,这些值也取决于 k。

我想最小化,使得或k值的总和(新标量函数)等于 0.32。assign(k)sum(assign(k))

我使用scipy.optimize程序来做到这一点。我的约束是constraint=sum(assign(k))-0.32和目标函数 iz fun(k)=k。所以,我最小化k以满足约束。

import scipy
from scipy.optimize import minimize


lista=[0.002,0.006,0.003,0.02,0.008,0.006,0.05]

def assign(k):
    return list(map(lambda x:(k*0.005 if x in np.arange(0,k*0.0025,0.001) 
    else k*0.01 if x in np.arange(0.0025,k*0.005,0.001) else k*0.025 if x in 
    np.arange(0.005,k*0.0125,0.001) else k*0.05), lista))

def constraint(k):
    return sum(assign(k))-0.32

def fun(k):
    return k

k0=0
bnds=[(0,10)]
cons={'type':'eq','fun':constraint}
res=minimize(fun,k0,bounds=bnds,method='SLSQP',constraints=cons,options={'maxiter':2000})
print(res)

我得到k=1.1999这是一个奇怪的结果,它不满足约束。应该是2因为sum(assign(2))=0.52。我还收到一条错误消息:

  message: 'Iteration limit exceeded'

有谁知道如何克服这个限制?先感谢您!

4

1 回答 1

0

你写了:

lambda x:(k*0.005 if x in np.arange(0,k*0.0025,0.001) 
else k*0.01 if x in np.arange(0.0025,k*0.005,0.001) else k*0.025 if x in 
np.arange(0.005,k*0.0125,0.001) else k*0.05)

请不要那样做。一个简短的 lambda 函数很好,但是这个函数足够长,值得拥有一个名称和一个可读的函数定义:

def assign1(x, k):
    if x in np.arange(0, k * 0.0025, 0.001):
        return k * .01
    if x in np.arange(0.0025, k * 0.005, 0.001):
        return k * .025
    ...

但是花了一点时间开始写出来,它立即似乎是错误的。

  1. 我不敢相信你的意思是.0025,而不是k * .0025,作为一个下限。
  2. 假设添加了一些随机噪声,而不是x我们有x + epsilon。然后你的函数返回一个 5% 的常数k,这看起来很糟糕。

一般来说,我们不希望这样int(x * 1000) == x。因此,使用适当的范围对其进行编码:

def assign1(x, k):
    if 0 <= x < k * .0025:
        return k * .01
    if k * .0025 <= x < k * .0050:
        return k * .025
    ...

提供更好的约束,我相信您会对优化器的收敛方式更满意。

编辑

优化教程建议,对于这个 SLSQP 方法,您应该同时传入funjac

此外,full_output=True 退出模式 还提供有关问题所在的诊断建议。

于 2019-05-26T22:51:25.303 回答