Python 从预定义集为scipy.optimize选择变量
我试图用三个输入变量最小化一个函数,其中两个是有界的,一个必须从一组值中选择。为了确保从预定义的值集中选择第三个变量,我引入了以下约束:Python 从预定义集为scipy.optimize选择变量,python,optimization,minimization,scipy-optimize,Python,Optimization,Minimization,Scipy Optimize,我试图用三个输入变量最小化一个函数,其中两个是有界的,一个必须从一组值中选择。为了确保从预定义的值集中选择第三个变量,我引入了以下约束: from scipy.optimize import rosin, shgo import numpy as np # Set from which the third variable to be optimized can hold Z = np.array([-1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6,
from scipy.optimize import rosin, shgo
import numpy as np
# Set from which the third variable to be optimized can hold
Z = np.array([-1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1])
def Reson_Test(x): # arbitrary objective function
print (x)
return rosen(x)**2 - np.sin(x[0])
def Cond_1(x):
if x[2] in Z:
return 1
else:
return -1
bounds = [(-512,512),]*3
conds = ({'type': 'ineq' , 'fun' : Cond_1})
result = shgo(Rosen_Test, bounds, constraints=conds)
print (result)
但是,当查看来自Rosen_测试的打印结果时,很明显该条件没有被强制执行-可能条件定义不正确
我想知道是否有人有任何想法来确保第三个变量可以从集合中选择
注:选择shgo方法的目的是为了引入和更改约束。此外,如果满足此条件,我愿意使用其他优化包
谢谢你的帮助 不等式约束不是这样工作的
如本节所述,它们的定义如下:
g(x) <= 0
也许您应该尝试以允许在整个Z
范围内使用不等式约束的方式来定义问题
但是让我们看看它是如何工作的
等式约束定义为
h(x) == 0
所以你可以用
def Cond_1(x):
if x[2] in Z:
return numpy.zeros_like(x)
else:
return numpy.ones_like(x) * 1.0 # maybe multiply with some scalar?
其思想是返回一个数组[0.0,0.0,0.0]
,如果找到该数字,则该数组满足等式约束。否则返回[1.0,1.0,1.0]
,表示不满意
注意事项:
1.)
您可能需要对此进行调整,以返回类似[0.0,0.0,1.0]
的数组,向优化器显示您不满意的维度,以便优化器只需调整单个维度即可做出更好的猜测
(二)
您可能必须返回大于1.0的值才能声明不满足的相等约束。这取决于实施情况。优化器可能认为1.0很好,因为它接近0.0。因此,也许你必须尝试一些[0.0,0.0,999.0]
这就解决了尺寸标注的问题。但是仍然找不到任何数字做的关于上面提到的浮点数的事情
但我们可以试着像这样解决这个问题
import numpy as np
Z = np.array([-1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1])
def Cond_1(x):
# how close you want to get to the numbers in your array
tolerance = 0.001
delta = np.abs(x[2] - Z)
print(delta)
print(np.min(delta) < tolerance)
if np.min(delta) < tolerance:
return np.zeros_like(x)
else:
# maybe you have to multiply this with some scalar
# I have no clue how it is implemented
# we need a value stating to the optimizer "NOT THIS ONE!!!"
return np.ones_like(x) * 1.0
sol = np.array([0.5123, 0.234, 0.2])
print(Cond_1(sol)) # True
sol = np.array([0.5123, 0.234, 0.202])
print(Cond_1(sol)) # False
将numpy导入为np
Z=np.数组([-1,-0.8,-0.6,-0.4,-0.2,0.2,0.4,0.6,0.8,1])
def Cond_1(x):
#您希望接近数组中的数字的距离有多近
公差=0.001
δ=np.abs(x[2]-Z)
打印(增量)
打印(np.最小值(增量)<公差)
如果np.最小值(增量)<公差:
返回np.zero_like(x)
其他:
#也许你得用一些标量乘以这个
#我不知道它是如何实施的
#我们需要一个值向优化器声明“不是这个!!!”
返回np.ones_(x)*1.0
sol=np.数组([0.5123,0.234,0.2])
打印(条件1(溶胶))#真实
sol=np.数组([0.5123,0.234,0.202])
打印(条件1(溶胶))#错误
下面是一些关于优化的建议。为了确保它以可靠的方式工作,请尝试在不同的初始值开始优化。如果与边界一起使用,全局优化算法可能没有初始值。优化器以某种方式将空间离散化
如何检查优化的可靠性并获得更好的总体结果:
- 优化整个区域
[-512,512]
(适用于所有三维)
- 尝试其中的1/2:
[-512,0]
和[0512]
(8个子优化,每个维度2个)
- 尝试其中的三分之一:
[-512,-171]
,[-171170]
,[170512]
(27个子优化,每个维度3个)
- 现在比较收敛的结果,看看完整的全局优化是否发现了相同的结果
- 如果全局优化器没有找到“真实”最小值,而是找到了子优化:
- 你的目标函数在整个领域都太难了
- 尝试其他全局优化器
- 调整参数(可能是等式约束的999)
- 我经常使用子优化作为正常过程的一部分,而不仅仅是用于测试。特别是黑盒问题
请参阅以下答案:
非常感谢您的回答,这似乎很有效!!
import numpy as np
Z = np.array([-1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1])
def Cond_1(x):
# how close you want to get to the numbers in your array
tolerance = 0.001
delta = np.abs(x[2] - Z)
print(delta)
print(np.min(delta) < tolerance)
if np.min(delta) < tolerance:
return np.zeros_like(x)
else:
# maybe you have to multiply this with some scalar
# I have no clue how it is implemented
# we need a value stating to the optimizer "NOT THIS ONE!!!"
return np.ones_like(x) * 1.0
sol = np.array([0.5123, 0.234, 0.2])
print(Cond_1(sol)) # True
sol = np.array([0.5123, 0.234, 0.202])
print(Cond_1(sol)) # False