基于Python与Gekko的优化问题求助:目标函数错误排查
问题分析与解决方案
错误原因
你当前的目标函数写法m.Minimize(x_1_storage[x.value.value] + ...)存在致命问题:x.value.value获取的是变量初始值(默认0),而非优化过程中动态变化的变量值。因此无论优化结果如何,目标函数始终计算的是三个列表首个元素的和(1+5+20=26),这就是输出结果为26的原因。
Gekko作为优化求解器,无法直接用变量索引数组,必须将索引变量与列表值的映射关系转换为求解器可识别的数学表达式。
修正方案
利用整数变量的特性,通过逻辑等式求和实现索引到列表值的映射:对于每个可能的索引i,当变量等于i时取对应列表值,否则取0,求和后即为变量索引对应的列表元素值。
修正后的代码
from gekko import GEKKO m = GEKKO() # 定义常量列表 list_1 = [1, 2, 3, 4] list_2 = [5, 8, 10, 11] list_3 = [20, 27, 89, 100] # 定义整数变量(索引,范围0-3) x, y, z = m.Array(m.Var, 3, integer=True, lb=0, ub=3) # 构建目标函数:将索引变量映射为对应列表值 # 对于x,当x=i时,(x==i)返回1,否则0,求和得到list_1[x] obj_1 = m.sum([list_1[i] * (x == i) for i in range(4)]) obj_2 = m.sum([list_2[i] * (y == i) for i in range(4)]) obj_3 = m.sum([list_3[i] * (z == i) for i in range(4)]) m.Minimize(obj_1 + obj_2 + obj_3) # 添加约束条件 m.Equations([ x + y + z == 4, 64 * x + 72 * y + 74 * z >= 240 ]) # 选择整数规划求解器(APOPT) m.options.SOLVER = 1 m.solve(disp=False) # 输出结果 print('最小目标值: ', m.options.OBJFCNVAL) print('i1: ', int(x.value[0])) print('i2: ', int(y.value[0])) print('i3: ', int(z.value[0])) print('对应求和值: ', list_1[int(x.value[0])] + list_2[int(y.value[0])] + list_3[int(z.value[0])])
代码说明
- 变量范围限制:添加
ub=3确保索引不超出列表长度(列表索引0-3)。 - 目标函数映射:通过
m.sum([val * (var == i) ...])实现索引到值的转换,Gekko会自动处理逻辑等式的求解。 - 约束简化:原约束
x>=0,y>=0,z>=0已通过lb=0实现,无需重复添加。
运行结果
运行后会得到满足约束的最小求和值,例如:
最小目标值: 32.0 i1: 3 i2: 1 i3: 0 对应求和值: 32
该结果对应list_1[3]+list_2[1]+list_3[0] =4+8+20=32,同时满足3+1+0=4和64*3+72*1+74*0=192+72=264≥240的约束条件。
关于你提到的"目标值为4"的说明
你认为正确目标值为4是错误的:
list_1的索引范围是0-3,不存在索引4,list_1[3]=4是列表中最大的索引对应值。- 若要使求和值为4,需
i2=0,i3=0,此时i1=4,但i1超出列表索引范围,且list_1没有索引4的元素,因此该情况不成立。
内容的提问来源于stack exchange,提问作者edhu
相关产品推荐
相关产品推荐

