如何用多个键在字典内部循环以在Pyomo中定义优化问题?

问题描述 投票:0回答:1

作为优化问题的一部分,我试图在具有多个键的字典中循环(请看UNIT_TASKS)。特别是由于Python返回“关键错误:('Reactor_2','Reaction_3','Juan')”,因此我在遍历索引以定义“目标和约束”时遇到了问题。脚本的片段如下:

import numpy as np
from pyomo.environ import *
from pyomo.gdp import 

STATES = {
        'Feed_A'   : {'capacity': 500, 'initial': 500, 'price':  0},
        'Feed_B'   : {'capacity': 500, 'initial': 500, 'price':  0},
        'Feed_C'   : {'capacity': 500, 'initial': 500, 'price':  0},
        'Hot_A'    : {'capacity': 100, 'initial':   0, 'price': -1},
        'Int_AB'   : {'capacity': 200, 'initial':   0, 'price': -1},
        'Int_BC'   : {'capacity': 150, 'initial':   0, 'price': -1},
        'Impure_E' : {'capacity': 100, 'initial':   0, 'price': -1},
        'Product_1': {'capacity': 500, 'initial':   0, 'price': 10},
        'Product_2': {'capacity': 500, 'initial':   0, 'price': 10},
    }

UNIT_TASKS = {
        ('Heater',    'Heating', 'Pablo')   : {'Bmin': 0, 'Bmax': 100},
        ('Reactor_1', 'Reaction_1', 'Juan'): {'Bmin': 0, 'Bmax':  80}, 
        ('Reactor_1', 'Reaction_2', 'Pedro'): {'Bmin': 0, 'Bmax':  80}, 
        ('Reactor_1', 'Reaction_3', 'Pablo'): {'Bmin': 0, 'Bmax':  80}, 
        ('Reactor_2', 'Reaction_1', 'Pablo'): {'Bmin': 0, 'Bmax':  80},
        ('Reactor_2', 'Reaction_2', 'Juan'): {'Bmin': 0, 'Bmax':  80}, 
        ('Reactor_2', 'Reaction_3', 'Pablo'): {'Bmin': 0, 'Bmax':  80},
        ('Still',     'Separation', 'Pablo'): {'Bmin': 0, 'Bmax': 200}, 
        ('Heater',    'Heating', 'Juan')   : {'Bmin': 0, 'Bmax': 300}, 
        }

TASKS = set([i for (j,i,k) in UNIT_TASKS])
UNITS = set([j for (j,i,k) in UNIT_TASKS])
NAMES = set([k for (j,i,k) in UNIT_TASKS])
TIME = range(0,11)
TIME = np.array(TIME)

model = ConcreteModel()

model.W = Var(TASKS, UNITS, TIME, domain = Boolean)
model.B = Var(TASKS, UNITS, TIME, domain = NonNegativeReals)
model.S = Var(STATES.keys(), TIME, domain = NonNegativeReals)
model.Q = Var(UNITS, TIME, domain = NonNegativeReals)


Bmax = {(i,j,k): UNIT_TASKS[(j,i,k)]['Bmax'] for (j,i,k) in UNIT_TASKS}

UNITS_DIC = {j: set() for j in UNITS}
for (j,i,k) in UNIT_TASKS:
    UNITS_DIC[j].add(i)

UNITS_DIC_N = {j: set() for j in UNITS}
for (j,i,k) in UNIT_TASKS:
    UNITS_DIC_N[j].add(k)

NAMES_DIC = {k: set() for k in NAMES}
for (j,i,k) in UNIT_TASKS:
    NAMES_DIC[k].add(i)

TASKS_DIC = {i: set() for i in TASKS}
for (j,i,k) in UNIT_TASKS:
    TASKS_DIC[i].add(k)

TASKS_DIC_U = {i: set() for i in TASKS}
for (j,i,k) in UNIT_TASKS:
    TASKS_DIC_U[i].add(j)


model.Cost = Var(domain=NonNegativeReals)
model.costc = Constraint(expr = model.Cost == sum([UNIT_TASKS[(j,i,k)]['Bmin']*model.W[i,j,t] 
                                                    + UNIT_TASKS[(j,i,k)]['Bmax']*model.B[i,j,t] for i in TASKS for j in  TASKS_DIC_U[i] for k in UNITS_DIC_N[j]  for t in TIME]))

model.cons = ConstraintList()

for t in TIME:
    for j in UNITS:
        for i in UNITS_DIC[j]:
            for k in TASKS_DIC[i]:
                model.cons.add(model.B[i,j,t] <= model.W[i,j,t]*Bmax[i,j,k])
python dictionary key pyomo
1个回答
0
投票

需要清理的几件事...:)

首先,当您获得要为其输入关键错误的约束时,这是因为您正在使用多个'for'表达式,这将创建所有项目的叉积...请尝试在一边。

您的值矩阵稀疏,因此应仅使用这些值初始化集合并使用它。我也喜欢在制作模型时使用Pyomo的Set(请注意大写的S),尽管您也可以使用。

而且,您的索引很难遵循。如果您使用(i,j,k),请以该顺序(标准)使用它们,而不要使用(j,i,k)(容易混淆)。当您拥有名称时,我喜欢使用更直观的名称...这样可以提高可读性。

还请注意,在上面的代码中,您的索引在此行中翻转:

Bmax = {(i,j,k): UNIT_TASKS[(j,i,k)]['Bmax'] for (j,i,k) in UNIT_TASKS}

这里是建议的清理。请注意,您会收到一些“警告”,因为我们正在使用词典密钥的一部分进行设置,并且存在一些冗余。

model = ConcreteModel()
model.TASKS = Set(initialize = (i for (j,i,k) in UNIT_TASKS))       # note capital "S" Set for pyomo set
model.UNITS = Set(initialize = (j for (j,i,k) in UNIT_TASKS))
model.NAMES = Set(initialize = (k for (j,i,k) in UNIT_TASKS))

model.UTN = Set(within=model.UNITS * model.TASKS * model.NAMES,
                initialize=UNIT_TASKS.keys())           # this is now a Set of the keys (U, T, N)

model.TIMES = Set(initialize=range(0,11))
#TIME = np.array(TIME)



model.W = Var(model.TASKS, model.UNITS, model.TIMES, domain = Boolean)
model.B = Var(model.TASKS, model.UNITS, model.TIMES, domain = NonNegativeReals)
model.S = Var(STATES.keys(), model.TIMES, domain = NonNegativeReals)
model.Q = Var(model.UNITS, model.TIMES, domain = NonNegativeReals)


Bmax = {key: UNIT_TASKS[key]['Bmax'] for key in model.UTN}   # NOTE:  YOU HAD FLIPPED (i,j,k) -> (j, i, k)

# none of these "helper" dictionaries should be required!!  You should be able to delete these lines
# UNITS_DIC = {j: set() for j in UNITS}         # UNIT: {TASKS}
# for (j,i,k) in UNIT_TASKS:
#     UNITS_DIC[j].add(i)

# UNITS_DIC_N = {j: set() for j in UNITS}   # UNIT: {NAMES}
# for (j,i,k) in UNIT_TASKS:
#     UNITS_DIC_N[j].add(k)

# NAMES_DIC = {k: set() for k in NAMES}     # NAME: {TASKS}
# for (j,i,k) in UNIT_TASKS:
#     NAMES_DIC[k].add(i)

# TASKS_DIC = {i: set() for i in TASKS}     # TASK: {NAMES}
# for (j,i,k) in UNIT_TASKS:
#     TASKS_DIC[i].add(k)

# TASKS_DIC_U = {i: set() for i in TASKS}       # TASK: {UNITS}
# for (j,i,k) in UNIT_TASKS:
#     TASKS_DIC_U[i].add(j)

# for k in UNIT_TASKS:
#   print (k,  UNIT_TASKS[k])
model.Cost = Var(domain=NonNegativeReals)
model.costc = Constraint(expr = model.Cost == sum(    UNIT_TASKS[(u,t,n)]['Bmin']*model.W[t,u,time] 
                                                    + UNIT_TASKS[(u,t,n)]['Bmax']*model.B[t,u,time] 
                                                    for u,t,n in model.UTN
                                                    for time in model.TIMES))
© www.soinside.com 2019 - 2024. All rights reserved.