如何在 pyomo 中操作多索引对象仅访问其一个索引?

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

我想知道如何仅通过使用其中一个索引来操作 pyomo 多个索引对象。

这个问题可能有点愚蠢,但我还没有找到可能的解决方案。在我的模型中,决策变量 (x) 是每年 (t) 中每种作物 (j) 的面积。因此,x 是一个多索引变量:

model.x = pyomo.Var(model.crop, model.t, domain = pyomo.NonNegativeIntegers)

例如,model.x 应该像 model.x[crop,year] 那样进行索引

我想创建两个资源约束,将耕作面积和用水量(只有 j 指数)限制在每年既定的最大值。类似下面的代码:

def area_constr(model, year):
    return sum(model.x[crop, year] for crop in model.crop for year in model.t) <=\
          model.total_cropping_area_n[year] 
model.area_constr = pyomo.Constraint(model.a, model.n, rule = area_constr, 
doc = 'Restricción de superficie disponible')
def water_constr(model, crop, year):
return sum(model.x\[crop, year\] \* model.crop_water_demand\[crop\]
for crop in model.a for year in model.n) \<= total_water_endowment\[year\]
model.water_constr = pyomo.Constraint(model.a, model.n, rule = water_constr)

自从我收到以下消息以来,我无法使其工作:

KeyError: "Index '0' is not valid for indexed component 'x'" 

对于面积约束和 f 以及水约束,将所有年份中所有作物的耗水量相加,而不是逐年计算。

如何只使用一个索引进行操作?或者还有其他解决方案吗?

python optimization linear-programming pyomo gurobi
1个回答
0
投票

您的

area_constr
的问题在于,虽然您正确地将年份值传递给规则,因为您想要为每年设置面积约束,但您通过在规则内部再次提供变量
year
来覆盖该限制。总结。

这是一个示例,显示了我认为您的意图。请注意,在这两个约束中,您应该使用作为函数参数传入的值,如图所示。

如果您的区域限制逐年变化,那么您可以(并且应该)使用字典中的

(crop, year)
元组索引该数据,并以相同的方式索引相应的参数。

代码:

import pyomo.environ as pyo

### DATA

years = [2023, 2024, 2025]

water_demand = {    'corn': 1.5,
                    'rice': 2.3,
                    'wheat': 1.1}

water_limit = {     2023: 10.1,
                    2024: 12.3,
                    2025: 9.8}

area_limit = {      'corn': 10_000,
                    'rice': 12_500,
                    'wheat': 8_800}

### MODEL

m = pyo.ConcreteModel('crops')

# SETS
m.Y = pyo.Set(initialize=years, doc='year')
m.C = pyo.Set(initialize=water_demand.keys(), doc='crop')

# PARAMS
m.demand     = pyo.Param(m.C, initialize=water_demand)
m.limit      = pyo.Param(m.Y, initialize=water_limit)
m.area_limit = pyo.Param(m.C, initialize=area_limit)

# VARS
m.plant = pyo.Var(m.C, m.Y, domain=pyo.NonNegativeReals, doc='amount to plant of crop c in year y')

# CONSTRAINTS

# 1.  Don't bust the water limit FOR EVERY YEAR
def water_lim_constraint(m, y):
    # the "y" in this comes from the function params, we just need to supply "c" internally
    return sum(m.plant[c, y]*water_demand[c] for c in m.C) <= m.limit[y]
m.C1 = pyo.Constraint(m.Y, rule=water_lim_constraint, doc='total water limit by year')

# 2.  Don't overplant FOR EVERY CROP, FOR EVERY YEAR
def plant_limit(m, c, y):
    # in this constraint, the limit is applied for every year and crop, which
    # are supplied as function arguments
    return m.plant[c, y] <= m.area_limit[c]
m.C2 = pyo.Constraint(m.C, m.Y, rule=plant_limit, doc='area planting limit by crop and year')

m.pprint()

输出:

4 Set Declarations
    C : crop
        Size=1, Index=None, Ordered=Insertion
        Key  : Dimen : Domain : Size : Members
        None :     1 :    Any :    3 : {'corn', 'rice', 'wheat'}
    C2_index : Size=1, Index=None, Ordered=True
        Key  : Dimen : Domain : Size : Members
        None :     2 :    C*Y :    9 : {('corn', 2023), ('corn', 2024), ('corn', 2025), ('rice', 2023), ('rice', 2024), ('rice', 2025), ('wheat', 2023), ('wheat', 2024), ('wheat', 2025)}
    Y : year
        Size=1, Index=None, Ordered=Insertion
        Key  : Dimen : Domain : Size : Members
        None :     1 :    Any :    3 : {2023, 2024, 2025}
    plant_index : Size=1, Index=None, Ordered=True
        Key  : Dimen : Domain : Size : Members
        None :     2 :    C*Y :    9 : {('corn', 2023), ('corn', 2024), ('corn', 2025), ('rice', 2023), ('rice', 2024), ('rice', 2025), ('wheat', 2023), ('wheat', 2024), ('wheat', 2025)}

3 Param Declarations
    area_limit : Size=3, Index=C, Domain=Any, Default=None, Mutable=False
        Key   : Value
         corn : 10000
         rice : 12500
        wheat :  8800
    demand : Size=3, Index=C, Domain=Any, Default=None, Mutable=False
        Key   : Value
         corn :   1.5
         rice :   2.3
        wheat :   1.1
    limit : Size=3, Index=Y, Domain=Any, Default=None, Mutable=False
        Key  : Value
        2023 :  10.1
        2024 :  12.3
        2025 :   9.8

1 Var Declarations
    plant : amount to plant of crop c in year y
        Size=9, Index=plant_index
        Key             : Lower : Value : Upper : Fixed : Stale : Domain
         ('corn', 2023) :     0 :  None :  None : False :  True : NonNegativeReals
         ('corn', 2024) :     0 :  None :  None : False :  True : NonNegativeReals
         ('corn', 2025) :     0 :  None :  None : False :  True : NonNegativeReals
         ('rice', 2023) :     0 :  None :  None : False :  True : NonNegativeReals
         ('rice', 2024) :     0 :  None :  None : False :  True : NonNegativeReals
         ('rice', 2025) :     0 :  None :  None : False :  True : NonNegativeReals
        ('wheat', 2023) :     0 :  None :  None : False :  True : NonNegativeReals
        ('wheat', 2024) :     0 :  None :  None : False :  True : NonNegativeReals
        ('wheat', 2025) :     0 :  None :  None : False :  True : NonNegativeReals

2 Constraint Declarations
    C1 : total water limit by year
        Size=3, Index=Y, Active=True
        Key  : Lower : Body                                                                : Upper : Active
        2023 :  -Inf : 1.5*plant[corn,2023] + 2.3*plant[rice,2023] + 1.1*plant[wheat,2023] :  10.1 :   True
        2024 :  -Inf : 1.5*plant[corn,2024] + 2.3*plant[rice,2024] + 1.1*plant[wheat,2024] :  12.3 :   True
        2025 :  -Inf : 1.5*plant[corn,2025] + 2.3*plant[rice,2025] + 1.1*plant[wheat,2025] :   9.8 :   True
    C2 : area planting limit by crop and year
        Size=9, Index=C2_index, Active=True
        Key             : Lower : Body              : Upper   : Active
         ('corn', 2023) :  -Inf :  plant[corn,2023] : 10000.0 :   True
         ('corn', 2024) :  -Inf :  plant[corn,2024] : 10000.0 :   True
         ('corn', 2025) :  -Inf :  plant[corn,2025] : 10000.0 :   True
         ('rice', 2023) :  -Inf :  plant[rice,2023] : 12500.0 :   True
         ('rice', 2024) :  -Inf :  plant[rice,2024] : 12500.0 :   True
         ('rice', 2025) :  -Inf :  plant[rice,2025] : 12500.0 :   True
        ('wheat', 2023) :  -Inf : plant[wheat,2023] :  8800.0 :   True
        ('wheat', 2024) :  -Inf : plant[wheat,2024] :  8800.0 :   True
        ('wheat', 2025) :  -Inf : plant[wheat,2025] :  8800.0 :   True

10 Declarations: Y C demand limit area_limit plant_index plant C1 C2_index C2
[Finished in 267ms]
© www.soinside.com 2019 - 2024. All rights reserved.