Python的Pyomo中对“无法使用单个表达式初始化约束的多个索引”的更深入解释

thtygnil  于 2022-12-17  发布在  Python
关注(0)|答案(2)|浏览(352)

当尝试在Pyomo中创建below约束时遇到Cannot initialize multiple indices of a constraint with a single expression错误,我已经阅读了其他不相关的答案,但不确定如何翻译这里的学习。我相信问题是一些变量由两个集合而不是一个集合索引。然而,我在Pyomo中对这些索引求和,因此认为我的约束可以由单个变量索引。

def armington_composite_demand_constraint(self, k):
    return self.MODEL.armington_composite_demand[k] == (
        sum(
            self.MODEL.armington_composite_intermediate_demand[(k, a)]
            for a in self.__activities()
        )
        + sum(
            self.MODEL.armington_composite_household_demand[(k, h)]
            for h in self.__household_types()
        )
        + sum(
            self.MODEL.armington_composite_government_demand[(k, g)]
            for g in self.__government_types()
        )
        + sum(
            self.MODEL.armington_composite_investment_demand[(k, i)]
            for i in self.__investment_types()
        )
    )

尝试使用此函数创建约束:

# armington_composite_price_constraint
  setattr(
      self.MODEL,
      "armington_composite_price_constraint",
      po.Constraint(
          self.__commodities(), rule=self.armington_composite_price_constraint
      ),
  )

不知道如何修复这个错误,我不确定我是否正确理解了这个错误。有人能解释一下这个错误吗?为什么Pyomo在对约束函数中的另一个索引求和时会遇到困难?
我的猜测是可能会分裂出求和函数...希望能得到一些帮助

dnph8jn4

dnph8jn41#

我认为这个错误是由你定义规则的方式引起的,你有一个类的方法,所以当你把self.armington_composite_demand传递给rule参数时,类示例会自动作为方法的第一个参数传递进来。在Pyomo调用该规则来构造约束时,它在模型中作为第一个参数传递,后跟来自任何索引集的单个值。所以你的规则有一个太少的参数。我认为解决办法是在你的规则方法中添加模型作为中间参数:

def armington_composite_demand_constraint(self, model, k):
yacmzcpb

yacmzcpb2#

你的约束构造没有问题。正如在另一个解决方案中提到的,这可能是类模型或语法的问题。如果你试图将模型构建为更大类(self.MODEL?)的示例的一部分,或者如果对框架有误解,那么从你的示例中并不完全清楚。
你的示例化语法有点不标准,也许有些东西还在那里。也许(?)下面的一个更清晰的表示可以显示你对如何创建这个约束的一般概念。注意:示出了两种方式。(1)使用装饰器,以及(2)使用使用函数的函数-规则组合(不需要装饰器)。这些动作产生正确但冗余的约束:

import pyomo.environ as po

MODEL = po.ConcreteModel()

MODEL.k = po.Set(initialize=[1, 2, 3])
MODEL.a = po.Set(initialize=[4, 5])
MODEL.h = po.Set(initialize=['A', 'B'])
MODEL.g = po.Set(initialize=['Hi', 'Low'])
MODEL.i = po.Set(initialize=[10, 20])

MODEL.armington_composite_demand = po.Var(MODEL.k)
MODEL.armington_composite_intermediate_demand = po.Var(MODEL.k, MODEL.a)
MODEL.armington_composite_household_demand = po.Var(MODEL.k, MODEL.h)
MODEL.armington_composite_government_demand = po.Var(MODEL.k, MODEL.g)
MODEL.armington_composite_investment_demand = po.Var(MODEL.k, MODEL.i)

@MODEL.Constraint(MODEL.k)
def armington_composite_demand_constraint(self, k):
    return MODEL.armington_composite_demand[k] == (
        sum(
            MODEL.armington_composite_intermediate_demand[(k, a)]
            for a in MODEL.a
        )
        + sum(
            MODEL.armington_composite_household_demand[(k, h)]
            for h in MODEL.h
        )
        + sum(
            MODEL.armington_composite_government_demand[(k, g)]
            for g in MODEL.g
        )
        + sum(
            MODEL.armington_composite_investment_demand[(k, i)]
            for i in MODEL.i
        )
    )

#  Alternatively... without using the decorator
MODEL.C1 = po.Constraint(MODEL.k, rule=armington_composite_demand_constraint)

MODEL.pprint()

相关问题