You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pyomo混合整数规划:如何让二进制变量首次达阈值时置1?

问题描述

需要定义一个二进制变量$inv_year[i,t]$,用于标记项目$i$的首次投资年份——也就是投资变量$I[i,t]$首次大于0的时间点。要求每个项目$i$的$inv_year$仅在首次投资时取值为1,其余时间均为0。

当前使用Big M方法实现时,$inv_year[i,t]$会在$I[i,t]$每次大于0时都置1,导致一个项目多次触发该变量,不符合需求。现有Pyomo代码如下:

#First constraint, Big-M method for binary variable inv_year 
def bigM_constraint1(model, i, t):
    lhs_1 = model.inv_year[i,t]
    rhs_1 = model.I[i,t]
    return lhs_1<=rhs_1

#add the rule to the model as a constraint
model.BigM_Constraint1 = Constraint(model.project_type, model.time, rule=bigM_constraint1)

#Second constraint, Big-M method for binary variable inv_year 
def bigM_constraint2(model, i, t):
    lhs_2 = model.I[i,t]
    rhs_2 = model.M[i] * model.inv_year[i,t]
    return lhs_2<=rhs_2

#add the rule to the model as a constraint
model.BigM_Constraint2 = Constraint(model.project_type, model.time, rule=bigM_constraint2)
解决方案

可以通过补充约束条件调整Big M方法,实现仅标记首次投资年份的需求,无需更换方法。需要新增两类核心约束:

1. 限制每个项目仅触发一次$inv_year$

确保每个项目$i$的所有时间点$inv_year[i,t]$之和不超过1,避免多次标记:

def single_investment_constraint(model, i):
    return sum(model.inv_year[i,t] for t in model.time) <= 1

model.Single_Investment_Constraint = Constraint(model.project_type, rule=single_investment_constraint)

2. 强制首次投资后不再触发$inv_year$

确保一旦某个时间点$t$的$inv_year[i,t]$为1,所有后续时间点$t' > t$的$inv_year[i,t']$必须为0。通过累加前置时间点的$inv_year$实现:

def no_subsequent_inv_constraint(model, i, t):
    if t == model.time.first():
        return Constraint.Skip
    # 累加截至t-1的inv_year,若已标记过投资,后续不能再标记
    return sum(model.inv_year[i,t_prev] for t_prev in model.time if t_prev < t) >= model.inv_year[i,t]

model.No_Subsequent_Inv_Constraint = Constraint(model.project_type, model.time, rule=no_subsequent_inv_constraint)

3. 可选:强制投资必须标记首次年份

如果需要避免“有投资发生但$inv_year$全为0”的情况,可添加以下约束:

def inv_implies_mark_constraint(model, i):
    # M_total[i]为项目i所有时间点I的最大可能总和,需提前定义
    return sum(model.I[i,t] for t in model.time) <= model.M_total[i] * sum(model.inv_year[i,t] for t in model.time)

model.Inv_Implies_Mark_Constraint = Constraint(model.project_type, rule=inv_implies_mark_constraint)

原有的两个Big M约束已保证:$inv_year[i,t]=1$时$I[i,t]>0$,且$I[i,t]>0$时$inv_year[i,t]$可取值1。结合新增约束后,就能严格实现“仅在首次投资时标记$inv_year$”的需求。


内容的提问来源于stack exchange,提问作者Julia Schepp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 09:35:06