Scipy shgo优化器未遵守等式约束问题问询
SHGO优化返回结果违反等式约束的原因分析
问题重现
运行以下Scipy优化代码:
from scipy import optimize from math import log bounds = ((0, 1), (0, 1), (0, 1), (0, 1)) def finite_resources(x): return x[0] + x[2] - 1 # 注意:此处约束被定义为元组而非列表 cons = ({'type': 'eq', 'fun': finite_resources}) def global_satisfaction(x): return -(log(1+x[0])/(1+x[1]*10000) + log(1+x[2])/(1+x[3]*10000)) results = dict() print(optimize.shgo(global_satisfaction, bounds, constraints=cons))
得到输出:
message: Optimization terminated successfully. success: True fun: -1.3862943611198906 funl: [-1.386e+00] x: [ 1.000e+00 0.000e+00 1.000e+00 0.000e+00] xl: [[ 1.000e+00 0.000e+00 1.000e+00 0.000e+00]] nit: 1 nfev: 18 nlfev: 5 nljev: 1 nlhev: 0
返回的四元组x = [1.0, 0.0, 1.0, 0.0]明显违反等式约束x[0] + x[2] - 1 = 0。
原因分析
核心问题在于约束参数的格式错误:
- Scipy优化函数(包括
shgo)的constraints参数要求传入约束字典的序列(通常是列表),而你此处将单个约束字典用圆括号()包裹,创建了一个元组而非列表。 - 虽然元组属于序列类型,但Scipy的
shgo内部对约束的处理逻辑未正确识别元组形式的约束,导致约束完全未被应用——相当于在无约束条件下运行优化,此时目标函数的最大值自然出现在x[0]=1、x[2]=1(这两个变量的取值能最大化log(1+x)项),同时x[1]=0、x[3]=0消除分母的惩罚。
解决方案
将约束定义改为列表形式即可:
# 修正为列表格式的约束 cons = [{'type': 'eq', 'fun': finite_resources}]
修正后重新运行,优化结果会严格遵守等式约束,返回符合要求的最优解。
是否需要提交Issue?
不需要。这并非Scipy的bug,而是代码中约束参数的格式使用错误。只要按照官方文档要求传入列表形式的约束,问题即可解决。
内容的提问来源于stack exchange,提问作者user10165777
相关产品推荐
相关产品推荐

