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

Pyomo中基于初始化集合定义二维参数及索引错误解决

问题描述

我有一个二维列表s:

s = [
[0,0,9,6,8,1,6,2,3,9],
[0,0,0,3,1,1,2,5,7,8],
[3,10,0,2,6,4,0,4,8,3],
[7,10,10,0,9,0,2,3,10,7],
[1,10,8,9,0,9,6,6,8,8], 
[1,1,9,8,5,0,5,7,10,0],
[3,2,2,6,7,1,0,6,0,6],
[7,1,0,5,5,7,5,0,9,6],
[10,5,7,3,0,10,1,4,0,7],
[10,4,6,0,9,1,3,10,6,0]
]

需要将其转换为Pyomo参数,用于以下约束方程:

start[i] + p[i] + s[i,j] >= start[j]    for all i,j in J: i < j

尝试用以下代码定义参数时触发错误:

m.PAIRS_1 = Set(initialize = m.J * m.J, dimen=2, filter=lambda m, j, k : j < k)
m.setup   = Param(initialize = m.PAIRS_1, default = s)

错误信息:

KeyError: "Cannot treat the scalar component 'setup' as an indexed component"

我的模型主函数结构如下:

def schedule_machines(A, B):

  # create model
  m = ConcreteModel()

  # index set to simplify notation
  m.J       = Set(initialize=JOBS.keys())
  m.PAIRS_1 = Set(initialize = m.J * m.J, dimen=2, filter=lambda m, j, k : j < k)

  def s_initializer(m, i, j):
    return s[i][j]
  m.setup = Param(m.J, m.J, initialize=s_initializer)

  # decision variables
   ....

  # for binary assignment
  ...

  # optimization model
  ...

  # SolverFactory()
  ...

  return SCHEDULE

SCHEDULE = schedule_machines(A,B)

所有数据定义在主函数外部,求解决方法。


错误原因与解决方法

错误根源

你定义Param的写法存在两个核心问题:

  1. 未指定索引集就直接用initialize=m.PAIRS_1,导致setup被识别为标量参数,但你实际需要的是可通过(i,j)索引的二维参数。
  2. 用default=s完全错误,default是给未初始化的索引对设置默认值,不能直接传入二维列表。

正确实现方式

根据需求,有两种可行方案:

方案1:定义全二维参数(覆盖所有i,j组合)

如果需要保留所有(i,j)的参数值(即使i>=j),可直接基于m.J×m.J定义二维参数,初始化函数映射列表索引即可:

def schedule_machines(A, B):
    m = ConcreteModel()
    # 确保JOBS的keys和s的列表索引匹配(比如都是0-9的整数)
    m.J = Set(initialize=JOBS.keys())
    
    # 定义覆盖所有i,j∈J的二维参数
    def s_init(m, i, j):
        return s[i][j]
    m.setup = Param(m.J, m.J, initialize=s_init)
    
    # 定义i<j的索引集合用于约束
    m.PAIRS_1 = Set(initialize=m.J*m.J, dimen=2, filter=lambda m, i, j: i<j)
    
    # 编写约束规则
    def seq_rule(m, i, j):
        return m.start[i] + m.p[i] + m.setup[i,j] >= m.start[j]
    m.sequence_constraint = Constraint(m.PAIRS_1, rule=seq_rule)
    
    # 其余变量定义、求解器调用代码...
    return SCHEDULE

方案2:仅定义i<j的参数(更高效)

如果只需要i<j的参数值,可直接基于PAIRS_1集合定义参数:

def schedule_machines(A, B):
    m = ConcreteModel()
    m.J = Set(initialize=JOBS.keys())
    # 先定义i<j的索引集合
    m.PAIRS_1 = Set(initialize=m.J*m.J, dimen=2, filter=lambda m, i, j: i<j)
    
    # 针对PAIRS_1集合初始化参数
    def s_init(m, i, j):
        return s[i][j]
    m.setup = Param(m.PAIRS_1, initialize=s_init)
    
    # 直接用PAIRS_1集合定义约束
    def seq_rule(m, i, j):
        return m.start[i] + m.p[i] + m.setup[i,j] >= m.start[j]
    m.sequence_constraint = Constraint(m.PAIRS_1, rule=seq_rule)
    
    # 其余变量定义、求解器调用代码...
    return SCHEDULE

关键注意事项

  • 必须保证JOBS.keys()返回的索引值和二维列表s的索引完全匹配(比如都是0到9的整数),否则会出现索引不匹配错误。
  • 如果JOBS的key不是整数(比如字符串),需要先建立key到列表索引的映射字典:
    job_idx = {job: idx for idx, job in enumerate(JOBS.keys())}
    
    然后在初始化函数中用job_idx[i]和job_idx[j]去取s中的对应值。

内容的提问来源于stack exchange,提问作者A.Omidi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 00:16:05