如何在Gekko中使用分层条件约束

2 投票
1 回答
19 浏览
提问于 2025-04-13 03:20

我正在尝试在Gekko中实现条件逻辑,使用的是“if3”,但不太确定如何在不同的细节层次上成功地叠加两个条件。

“x1”是一个二进制值的向量(0或1),它控制在第i个元素上何时使用替代的右侧值来约束x2和x3。

“x2”是一个浮点数的向量,我想根据上面“x1”的二进制值动态设置第i个元素的上下限。如果第i个元素的x1值为1,我想用“window_lnuc_min_promo_price”(同样长度的向量)作为下限,用“window_lnuc_max_promo_price”作为上限。如果第i个元素的x1值为0,我想用“min_promo_price”作为下限,用“max_promo_price”作为上限。

同样,“x3”也是一个浮点数的向量,我想应用相同的逻辑,但只对下限进行处理。当x1的第i个元素为1时,使用“window_lnuc”的值;当为0时,使用“lnuc”的值。

最后,我想限制x1等于1的次数(在下面的例子中是4次)。这意味着替代值的总出现次数限制为4次。

我觉得我遇到的问题是,因为x1是一个0到1的变量,优化器正在改变“lnuc_weeks”中的默认“0”值(我不想这样做)。我希望优化器基本上保持“lnuc_weeks”中所有为0的值不变,并且只从最初为1的“lnuc_weeks”元素中选择最多4个值。

可能有更好的写法,但任何帮助或反馈都很感激。完整的解决方案有点长,不方便展示以便重现输出,但希望以上内容足以描述问题。

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 个回答

1

在模型初始化的时候,.lower.upper 的边界值就已经确定了,这些值不会因为后续优化而改变。要实现这些边界,可以使用不等式表达式。为了避免在处理大于1或者大于等于1的整数值时出现数字问题,建议使用 0.5 作为切换点。默认情况下,求解器的容忍度是 1e-6,这意味着值为 0.999999 和 1.000001 在方程收敛时被视为相同。

i = 0
for xi in x2:
    xi.value = blended_srp[i]
    m.Equation(xi >= m.if3((x1[i]) - 0.5, min_promo_price[i], window_lnuc_min_promo_price[i]))
    m.Equation(xi <= m.if3((x1[i]) - 0.5, max_promo_price[i], window_lnuc_max_promo_price[i]))
    i += 1

并且

i = 0
for xi in x3:
    xi.value = blended_nuc[i]
    m.Equation(xi >= m.if3((x1[i]) - 0.5, lnuc[i], window_lnuc[i]))
    xi.upper = 10
    i += 1

使用 m.Equation(sum(x1)<=4) 来选择任意四个元素是正确的。

撰写回答