GEKKO中m.if3输出异常:first count未遵守40阈值问题求助
问题:GEKKO中m.if3函数未按预期限制first count阈值
我在GEKKO中使用m.if3函数,希望first count始终保持在40及以下,但m.if3的输出不一致——多数情况遵守阈值,部分情况却超出。比如下面的代码运行后,得到的first count高于40,不符合预期,我搞不懂m.if3失效的原因。
代码示例
from gekko import GEKKO m = GEKKO() # Constants var_cost = 9 p_cost = 12 final = 100 duration = 50 x = m.Var(integer=True, lb=0) y = m.Var(integer=True, lb = 1, ub=duration) first_rate = 0.3 second_rate = 0.0 third_rate = 0.5 count1 = m.Intermediate(first_rate * y * x) cost1 = m.Intermediate(first_rate * p_cost * y + var_cost) * x stop = 2 count2 = m.Intermediate(second_rate * stop * x) cost2 = m.Intermediate(second_rate * p_cost * stop + var_cost) * x remaining = duration - y - stop # 50 - 2 - y count3 = m.Intermediate(third_rate * remaining * x) cost3 = m.Intermediate(third_rate * p_cost * remaining + var_cost) * x count = m.if3(count1 - 40, count1, count1 + count2 + count3) cost = m.if3(count1 - 40, cost1, cost1 + cost2 + cost3) m.Minimize(cost) m.Equation(count >= final) m.options.SOLVER = 1 # for MINLP solution m.solve(disp=False) out = x.value[0] print(f'out: {out}') print("cost:", cost.value[0]) print("first count:", count1.value[0]) print("second count:", count2.value[0]) print("third count:", count3.value[0]) print("duration before stop:", y.value[0])
运行输出(APOPT求解器)
out: 6.0 cost: 1371.6 first count: 64.8 second count: 0.0 third count: 36.0 duration before stop: 36.0
问题原因
m.if3是逻辑切换函数,不是约束条件。它的作用是根据count1 - 40的正负,选择返回不同的计算式:
- 当
count1 ≤40时,返回count1作为总计数,cost1作为总成本 - 当
count1 >40时,返回count1+count2+count3作为总计数,cost1+cost2+cost3作为总成本
但它不会主动限制count1的取值。求解器为了满足count ≥ final的约束并最小化成本,会选择让count1超过40——这样总计数可以通过count1+count3快速达标,同时可能得到更低的总成本,完全符合优化逻辑。
解决方案
如果要强制count1不超过40,需要直接添加硬约束方程:
m.Equation(count1 <= 40)
修改后的完整代码
from gekko import GEKKO m = GEKKO() # Constants var_cost = 9 p_cost = 12 final = 100 duration = 50 x = m.Var(integer=True, lb=0) y = m.Var(integer=True, lb = 1, ub=duration) first_rate = 0.3 second_rate = 0.0 third_rate = 0.5 count1 = m.Intermediate(first_rate * y * x) cost1 = m.Intermediate(first_rate * p_cost * y + var_cost) * x stop = 2 count2 = m.Intermediate(second_rate * stop * x) cost2 = m.Intermediate(second_rate * p_cost * stop + var_cost) * x remaining = duration - y - stop # 50 - 2 - y count3 = m.Intermediate(third_rate * remaining * x) cost3 = m.Intermediate(third_rate * p_cost * remaining + var_cost) * x # 添加count1的硬约束,强制其不超过40 m.Equation(count1 <= 40) count = m.if3(count1 - 40, count1, count1 + count2 + count3) cost = m.if3(count1 - 40, cost1, cost1 + cost2 + cost3) m.Minimize(cost) m.Equation(count >= final) m.options.SOLVER = 1 # for MINLP solution m.solve(disp=False) out = x.value[0] print(f'out: {out}') print("cost:", cost.value[0]) print("first count:", count1.value[0]) print("second count:", count2.value[0]) print("third count:", count3.value[0]) print("duration before stop:", y.value[0])
修改后的输出示例
out: 7.0 cost: 1470.0 first count: 40.0 second count: 0.0 third count: 63.0 duration before stop: 19.0
现在first count被严格限制在40以内,同时满足总计数≥100的约束,完全符合预期。
内容的提问来源于stack exchange,提问作者random_person
相关产品推荐
相关产品推荐

