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

基于Pyomo子集条件求和生成约束的实现问题

能源分配Pyomo模型核心约束实现方案

问题背景

作为Pyomo和线性优化新手,正在处理固定时间范围内的能源分配问题,目标是最大化能源利用率,无需满足所有请求。

已定义的模型元素

集合

model.t = pyomo.Set(initialize = (supply_unix_ts.index))  # 时间集合
model.r = pyomo.Set(initialize = request_ids)  # 能源消耗请求集合

参数

  • 各时段可用能源:
model.available_supply = pyomo.Param(model.t, initialize = supply_unix_ts.to_dict(), domain=pyomo.NonNegativeReals)
  • 请求相关参数:
model.request_earliest_start_time = pyomo.Param(model.r, initialize = request_earliest_start_times_dict, domain=pyomo.NonNegativeReals)  # 请求最早开始时间
model.request_latest_end_time = pyomo.Param(model.r, initialize = request_latest_end_time_dict, domain=pyomo.NonNegativeReals)  # 请求最晚结束时间
model.request_max_power_dict = pyomo.Param(model.r, initialize = request_max_power_dict, domain=pyomo.NonNegativeReals)  # 请求最大供电功率
model.request_energy_needed_dict = pyomo.Param(model.r, initialize = request_energy_needed_dict, domain=pyomo.NonNegativeReals)  # 请求所需总能量
  • 采样周期(功率转能量用):
model.sampling_period_dict = pyomo.Param(model.t, initialize = sampling_period_dict, domain=pyomo.NonNegativeReals)

决策变量

model.booked_supply = pyomo.Var(model.t, domain = pyomo.NonNegativeReals)  # 各时段已预订的总能源
model.request_status = pyomo.Var(model.t, model.r, domain = pyomo.Binary)  # 指示请求r在时段t是否被分配能源
model.request_satisfied = pyomo.Var(model.r, domain = pyomo.Binary)  # 指示请求r是否被完全满足

目标函数

def obj_rule(model):
    return sum(model.booked_supply[t] for t in model.t)
model.obj = pyomo.Objective(rule = obj_rule, sense = pyomo.maximize)

已实现约束

  1. 各时段预订能源不超过可用能源:model.booked_supply[t] <= model.available_supply[t](针对每个t∈model.t)
  2. 预订能源等于该时段所有分配请求的总和:model.booked_supply[t] = sum(model.request_status[t,r] * model.request_max_power_dict[r] * model.sampling_period_dict[t] for r in model.r)(针对每个t∈model.t)

待实现核心约束

当请求r被完全满足(model.request_satisfied[r] = 1)时,其在时间区间[model.request_earliest_start_time[r], model.request_latest_end_time[r]]内分配的总能量等于model.request_energy_needed_dict[r];若未被满足(model.request_satisfied[r] = 0)则无要求。

错误尝试分析

  1. 为每个请求创建时间子集:请求数量达数千个,动态创建大量集合会引发性能问题,不可行。
  2. 错误约束规则:
    • 第一个约束错误地将t作为索引参数,内部又遍历所有t导致索引冲突,且使用了未定义的model.request_confirmed_power变量。
    • 第二个约束存在逻辑错误(条件写错最晚结束时间参数),且遍历所有请求和时间,不符合Pyomo约束规则的定义逻辑。

可行方案及代码示例

核心思路

采用大M法将二元变量的逻辑转化为线性约束:

  1. 当model.request_satisfied[r] = 1时,总分配能量必须等于需求能量;
  2. 当model.request_satisfied[r] = 0时,总分配能量可在合理范围内自由取值(结合目标函数会尽可能分配)。

代码实现

# 定义大M参数:针对每个请求计算其最大可能分配能量,避免数值稳定性问题
def M_rule(model, r):
    max_possible_energy = model.request_max_power_dict[r] * sum(model.sampling_period_dict[t] for t in model.t)
    return max_possible_energy
model.M = pyomo.Param(model.r, rule=M_rule, domain=pyomo.NonNegativeReals)

# 核心约束:绑定请求满足状态与能量分配量
def satisfied_energy_constraint(model, r):
    # 计算请求r在允许时间区间内的总分配能量
    allocated_energy = sum(
        model.request_status[t, r] * model.request_max_power_dict[r] * model.sampling_period_dict[t]
        for t in model.t
        if model.request_earliest_start_time[r] <= t <= model.request_latest_end_time[r]
    )
    # 约束1:请求被满足时,分配能量不低于需求;未满足时自动满足下限
    constraint1 = allocated_energy >= model.request_energy_needed_dict[r] * model.request_satisfied[r]
    # 约束2:请求被满足时,分配能量不超过需求;未满足时限制在最大可能值内
    constraint2 = allocated_energy <= model.request_energy_needed_dict[r] * model.request_satisfied[r] + model.M[r] * (1 - model.request_satisfied[r])
    return constraint1 and constraint2

model.satisfied_energy = pyomo.Constraint(model.r, rule=satisfied_energy_constraint)

补充说明

  • 若需灵活分配功率而非仅用最大功率,可将model.request_status改为连续变量model.request_power_fraction = pyomo.Var(model.t, model.r, domain=pyomo.UnitInterval),表示时段内使用最大功率的比例,此时分配能量为model.request_power_fraction[t,r] * model.request_max_power_dict[r] * model.sampling_period_dict[t]。
  • 大M值需合理选择:过小会导致约束失效,过大影响求解器稳定性,建议针对每个请求单独计算。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 01:22:47