如何在Pyomo中创建支持可变RangeSet的Param以适配动态变化的二维输入数组
Pyomo动态传入可变长度轨迹数组的解决方案
你代码运行后m.x形状不变的核心原因是:RangeSet的边界在初始化时就已经静态计算完成,你定义m.x的第一个索引时,m.num[0]还是默认值0,所以RangeSet(0, value(m.num[0])-1)初始化为空集,后续修改m.num的值不会触发已创建RangeSet的边界更新,因此m.x的索引永远为空。
以下是两种可行的适配方案:
方案1:每个时间步重建模型(推荐用于滚动优化场景)
你做的是每个时间步求解的滚动优化任务,每个时间步直接根据当前车辆数动态构建模型是最简洁、不易出错的方案,完全适配动态变化的输入:
import pyomo.environ as pyo import numpy as np # 每个时间步获取当前周边车辆的预测轨迹数组 x_data = np.array([[1,2,3,4],[5,6,7,8]]) n_veh = x_data.shape[0] pred_len = x_data.shape[1] # 新建模型 m = pyo.ConcreteModel() # 动态生成车辆索引和预测时域索引 m.veh_set = pyo.RangeSet(0, n_veh - 1) m.pred_set = pyo.RangeSet(0, pred_len - 1) # 直接传入轨迹数据初始化Param m.x = pyo.Param(m.veh_set, m.pred_set, initialize={(i,j): x_data[i,j] for i in range(n_veh) for j in range(pred_len)}, mutable=True) # 目标函数直接遍历集合求和,自动适配当前车辆数 def obj_rule(m): return sum(m.x[i,j] for i in m.veh_set for j in m.pred_set) m.obj = pyo.Objective(rule=obj_rule)
方案2:复用模型,使用可变Set动态更新
如果需要复用同一个模型避免重复初始化的开销,可以将车辆索引定义为可变Set,每次更新轨迹时先修改Set成员,再更新Param的值:
import pyomo.environ as pyo import numpy as np # 初始化模型,预测时域固定的话可以提前定义 m = pyo.ConcreteModel() m.pred_set = pyo.RangeSet(0, 3) # 定义可变的车辆集合,支持动态增删成员 m.veh_set = pyo.Set(initialize=[], ordered=True, mutable=True) # 定义依赖可变Set的Param m.x = pyo.Param(m.veh_set, m.pred_set, mutable=True) # 目标函数定义一次即可,会自动适配veh_set的当前成员 def obj_rule(m): return sum(m.x[i,j] for i in m.veh_set for j in m.pred_set) m.obj = pyo.Objective(rule=obj_rule) # ========== 每个时间步更新数据 ========== x_new = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]]) n_veh_new = x_new.shape[0] # 清空旧的车辆集合 m.veh_set.clear() # 添加新的车辆索引 m.veh_set.update(range(n_veh_new)) # 给Param赋新值 for i in range(n_veh_new): for j in range(4): m.x[i,j] = x_new[i,j]
内容的提问来源于stack exchange,提问作者Exasor
相关产品推荐
相关产品推荐

