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

Pyomo中基于起始变量关联调度变量的线性约束语法实现求助

Pyomo线性规划优化问题求解

背景与问题

之前采用@Airsquid的方案已实现问题的正确求解,但在能源供应量远小于请求数的场景下,求解时长过长。已添加早停设置:

solver.options = { 'sec': 600,  'threads':6, 'ratio': 5} #early stopping settings

但希望通过重构代码进一步优化。

根据@Airsquid在参考资料[2]中的建议:可通过start变量确定请求的运行状态,无需额外辅助变量,仅需跟踪每个请求的功率分配变量。本人作为线性规划及Pyomo新手,在语法实现上遇到困难。

尝试的方法及问题

方法1

尝试定义当m.start[t,r] == 1时,m.dispatch[t,r]在对应时长内等于请求功率,编写的约束代码如下:

@m.Constraint(m.windows_flat)
def request_length(m, t, r):
    request_length_periods = int(m.duration_periods[r])
    request_periods = set(list(range(t,t+request_length_periods+1)))
    return (m.dispatch[t,r] == m.request_power_size[r] for t in request_periods if m.start[t,r] == 1)

运行后报错:

ERROR: Rule failed when generating expression for Constraint request_length
with index (910192, 88): ValueError: Constraint 'request_length[910192,88]'
does not have a proper value. Found '<generator object
generalOptimisation.<locals>.request_length.<locals>.<genexpr> at
0x168022b20>' Expecting a tuple or relational expression. Examples:
       sum(model.costs) == model.income (0, model.price[item], 50)
ERROR: Constructing component 'request_length' from data=None failed:
ValueError: Constraint 'request_length[910192,88]' does not have a proper
value. Found '<generator object

已知request_periods的定义方式不正确,但不知如何在未知m.start[t,r] == 1时机的前提下正确定义该集合。

方法2

尝试用m.start[t,r] *(m.dispatch[t,r]...m.dispatch[t+request_length_periods,r]) == 1,但不清楚Pyomo语法,且该方式会导致问题非线性。

解决方案

线性约束实现(符合@Airsquid建议)

要通过start变量线性约束dispatch的取值,需拆解为两个核心约束:

  1. 请求启动互斥约束:确保每个请求最多被启动一次
@m.Constraint(m.R)
def single_start_per_request(m, r):
    duration = int(m.duration_periods[r])
    # 筛选请求r所有合法的启动时段(启动后能完整运行整个时长)
    valid_starts = [t for t in m.T if t + duration <= m.T[-1] + 1]
    return sum(m.start[t, r] for t in valid_starts) <= 1
  1. 启动后的功率锁定约束:当请求在t时段启动时,后续duration个时段的dispatch必须等于请求功率。采用线性的大M法实现:
@m.Constraint(m.T, m.R)
def dispatch_lock_after_start(m, t_prime, r):
    duration = int(m.duration_periods[r])
    # 找到所有能覆盖当前时段t'的合法启动时段
    valid_starts = [t for t in m.T if t <= t_prime < t + duration]
    # 设置足够大的M值(建议取请求功率最大值的2倍)
    M = max(m.request_power_size[r] for r in m.R) * 2

    if not valid_starts:
        # 若当前时段不在任何请求的运行窗口内,dispatch必须为0(可根据业务需求调整)
        return m.dispatch[t_prime, r] == 0
    else:
        # 线性约束:当任意一个valid_start的start变量为1时,dispatch必须等于请求功率
        return (
            m.dispatch[t_prime, r] >= m.request_power_size[r] - M * (1 - sum(m.start[t, r] for t in valid_starts)),
            m.dispatch[t_prime, r] <= m.request_power_size[r] + M * (1 - sum(m.start[t, r] for t in valid_starts))
        )

早停参数优化建议

  • sec:当前设置600秒(10分钟),大规模问题可先测试缩短到300秒,观察解的质量;若质量下降明显再逐步延长。
  • threads:设置为CPU核心数的70%-80%(如8核CPU设为6是合理的),避免线程竞争拖慢效率。
  • ratio:当前设置5(找到比最优解差5%以内的解就停止),对精度要求不高可提高到10以缩短时间;要求高精度则降低到2-3,但会增加求解时长。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 22:07:51