如何在Gekko中实现分层条件约束并固定指定二进制变量值
Gekko中if3条件约束与二进制变量固定问题
问题描述
- 需在Gekko中通过
if3实现两层条件约束逻辑:- 二进制向量
x1(0/1)控制x2、x3对应元素的约束取值:- 浮点向量
x2:x1[i]=1时,下界取window_lnuc_min_promo_price[i]、上界取window_lnuc_max_promo_price[i];x1[i]=0时,下界取min_promo_price[i]、上界取max_promo_price[i]。 - 浮点向量
x3:下界遵循类似逻辑,x1[i]=1时取window_lnuc[i],x1[i]=0时取lnuc[i],上界固定为10。
- 浮点向量
- 要求
x1中值为1的元素总数不超过4个。
- 二进制向量
- 现有问题:
x1作为0-1变量,优化器会修改lnuc_weeks中初始为0的元素值,需固定这些初始为0的元素保持0不变,仅允许从lnuc_weeks初始为1的元素中最多选4个保留为1。
当前代码
x1 = m.Array(m.Var,(n), integer=True) #LNUC weeks i = 0 for xi in x1: xi.value = lnuc_weeks[i] xi.lower = 0 xi.upper = 1 i += 1 x2 = m.Array(m.Var,(n)) #Blended SRP i = 0 for xi in x2: xi.value = blended_srp[i] xi.lower = m.if3((x1[i]) - 1, min_promo_price[i], window_lnuc_min_promo_price[i]) xi.upper = m.if3((x1[i]) - 1, max_promo_price[i], window_lnuc_max_promo_price[i]) i += 1 x3 = m.Array(m.Var,(n)) #Blended NUC i = 0 for xi in x3: xi.value = blended_nuc[i] xi.lower = m.if3((x1[i]) - 1, lnuc[i], window_lnuc[i]) xi.upper = 10 i += 1 #Limit max lnuc weeks m.Equation(sum(x1)<=4)
解决方案
1. 固定初始为0的x1元素
针对lnuc_weeks[i]=0的元素,直接将x1[i]的上下界都设为0,强制其值保持不变:
x1 = m.Array(m.Var,(n), integer=True) #LNUC weeks i = 0 for xi in x1: xi.value = lnuc_weeks[i] # 固定初始为0的元素,禁止优化器修改 if lnuc_weeks[i] == 0: xi.lower = 0 xi.upper = 0 else: xi.lower = 0 xi.upper = 1 i += 1
2. 修正if3的判断逻辑
原代码中m.if3((x1[i]) - 1, ...)的条件逻辑错误:if3的规则是第一个参数>0时取第二个值,否则取第三个值,原条件导致取值逻辑与需求相反。修正后代码如下:
x2 = m.Array(m.Var,(n)) #Blended SRP i = 0 for xi in x2: xi.value = blended_srp[i] # x1[i]=1时取window相关约束,否则取常规约束 xi.lower = m.if3(x1[i], window_lnuc_min_promo_price[i], min_promo_price[i]) xi.upper = m.if3(x1[i], window_lnuc_max_promo_price[i], max_promo_price[i]) i += 1 x3 = m.Array(m.Var,(n)) #Blended NUC i = 0 for xi in x3: xi.value = blended_nuc[i] xi.lower = m.if3(x1[i], window_lnuc[i], lnuc[i]) xi.upper = 10 i += 1
3. 保留总数约束
原约束m.Equation(sum(x1)<=4)可直接保留,因为初始为0的x1元素已被固定,求和时只会统计初始为1的元素中最终保留为1的数量,自然满足“最多选4个”的要求。
内容的提问来源于stack exchange,提问作者datadude558
相关产品推荐
相关产品推荐

