在 Pyomo 中无法直接用 model.x[t] in set(...) 约束连续变量取离散值;需引入二元变量和大M/凸组合技巧,将离散选项线性化表达。本文详解如何为热电联产(CHP)负荷与对应价格联合建模,确保二者同步取自预定义的离散点对。
在 pyomo 中无法直接用 `model.x[t] in set(...)` 约束连续变量取离散值;需引入二元变量和大m/凸组合技巧,将离散选项线性化表达。本文详解如何为热电联产(chp)负荷与对应价格联合建模,确保二者同步取自预定义的离散点对。
在优化区域能源系统(如区域供热网络)时,常遇到非线性或分段定价行为——例如 CHP 机组的热价随其实际热出力呈离散阶梯变化(由设备特性曲线或报价表给出)。Pyomo 本身不支持对连续变量施加 in {a, b, c} 类型的集合约束(该语法在约束规则中非法),若强行使用 model.x[t] in set(...) 将导致运行时报错或求解器拒绝解析。
✅ 正确解法:采用指示型(indicator-based)凸组合建模,即引入一组二元变量 y[t, i],每个时间步 t 有且仅有一个 i 满足 y[t, i] = 1,其余为 0。通过该变量“激活”对应的离散负荷值与价格,实现严格一对一映射。
假设你已定义:
- chp.Line_PQ = [0.0, 25.5, 50.0, 75.3, 100.0](单位:MW,5 个离散热负荷点)
- chp.Price_PQ[0] = [85.2, 78.6, 72.1, 69.4, 67.0](单位:€/MWh,对应价格)
首先扩展模型索引集,显式声明离散选项维度:
# 假设 n = len(chp.Line_PQ) = 5
model.n = pyomo.Set(initialize=range(len(chp.Line_PQ))) # 索引 {0,1,2,3,4}
# 定义参数:将离散点加载为 Pyomo Param(推荐,提升可读性与性能)
model.set_Loads = pyomo.Param(model.n, initialize={i: chp.Line_PQ[i] for i in model.n})
model.Price_CHP_Set = pyomo.Param(model.n, initialize={i: chp.Price_PQ[0][i] for i in model.n})
# 引入二元决策变量:y[t,i] = 1 表示在时刻 t 选择第 i 个离散工作点
model.y = pyomo.Var(model.T, model.n, domain=pyomo.Binary)接着添加两类核心约束:
- 单选约束(Exactly-One):确保每个时刻 t 恰好启用一个离散点
- 线性重构约束(Load & Price):用加权和表达实际负荷与价格
# 【约束1】每时刻只能选一个工作点
def exactly_one_rule(model, t):
return sum(model.y[t, i] for i in model.n) == 1
model.exactly_one_constraint = pyomo.Constraint(model.T, rule=exactly_one_rule)
# 【约束2】CHP 实际热负荷 = Σ (离散负荷_i × y[t,i])
def compute_Load_rule(model, t):
return model.CHP[t] == sum(model.set_Loads[i] * model.y[t, i] for i in model.n)
model.compute_load_constraint = pyomo.Constraint(model.T, rule=compute_Load_rule)
# 【约束3】CHP 对应价格 = Σ (离散价格_i × y[t,i])
def compute_Price_rule(model, t):
return model.price_CHP[t] == sum(model.Price_CHP_Set[i] * model.y[t, i] for i in model.n)
model.compute_price_constraint = pyomo.Constraint(model.T, rule=compute_Price_rule)? 关键说明与注意事项:
- ✅ 此建模方式将原非凸、不可微的离散依赖转化为混合整数线性规划(MILP),兼容 CBC、Gurobi、CPLEX 等主流求解器;
- ⚠️ model.n 必须是 pyomo.Set(非 Python list),否则索引报错;initialize 推荐用字典映射而非位置索引(避免 i+1 错位风险);
- ? 若离散点数量较大(>100),需关注整数变量规模对求解效率的影响,可考虑分段线性近似(Piecewise 组件)作为替代;
- ? 所有参与 sum(... * y[t,i]) 的参数(如 set_Loads, Price_CHP_Set)必须预先定义为 pyomo.Param,不可动态计算;
- ✅ 目标函数无需修改——model.CHP[t]*model.price_CHP[t] 自动继承线性结构,因两者均由同一组 y[t,i] 驱动,乘积项虽为二次,但在此特定结构下仍保持分段线性可建模性(若求解器要求纯线性,可引入辅助变量线性化乘积,但本例中因 price_CHP[t] 已由 y 线性定义,目标函数实为 Σ_i (Load_i × Price_i) × y[t,i],仍是线性的)。
最终,该建模范式确保了 CHP 出力与价格始终协同匹配于物理可行的工作点,既满足工程真实性,又保持问题数学可解性。

















