在 Pyomo 中,是否可以编写一个 objective 函数或基于多个表达式的约束?

In Pyomo, Is it possible to write an objective function or a constraint based on several Expressions?

我是 Pyomo 的新手,我尝试使用多种方法编写 objective 函数和我的模型的约束。实际上,我想根据在不同 python 脚本中实现的不同对象类型的几个贡献来构造 objective function/constraint。

为此,我使用了 pyomo Expression 对象。我不知道这个对象是否适合使用。

为了说明我的问题,下面是一个实现我想做的事情的示例代码:

import pyomo.environ
model = pyomo.environ.ConcreteModel()

model.market = pyomo.environ.Set(initialize=['market'])

model.ask_price = pyomo.environ.Param(model.market, initialize={'market' : 12})
model.bid_price = pyomo.environ.Param(model.market, initialize={'market' : 10})
model.ask_liquidity = pyomo.environ.Param(model.market, initialize={'market' : 100})
model.bid_liquidity = pyomo.environ.Param(model.market, initialize={'market' : 100})

model.VOLUME_BUY = pyomo.environ.Var(model.market, within = pyomo.environ.NonNegativeReals)
model.VOLUME_SELL = pyomo.environ.Var(model.market, within = pyomo.environ.NonNegativeReals)

def max_buy(model, market):
    return model.VOLUME_BUY[market] <= model.ask_liquidity[market]

model.max_buy_equation = pyomo.environ.Constraint(model.market, rule=max_buy)

def max_sell(model, market):
    return model.VOLUME_SELL[market] <= model.bid_liquidity[market]

model.max_sell_equation = pyomo.environ.Constraint(model.market, rule=max_sell)

然后我尝试实现我的 objective 功能。如果我基本上尝试实现它,一切正常:

def total_objective(model):
    return   sum(model.VOLUME_BUY[market] * model.ask_price[market] for market in model.market) \
           - sum(model.VOLUME_SELL[market] * model.bid_price[market] for market in model.market)

model.objective = pyomo.environ.Objective(rule=total_objective, sense=-1)

但是如果我尝试使用表达式对象:

def objective_component1(model):
    return sum(model.VOLUME_BUY[market] * model.ask_price[market] for market in model.market)

model.obj_component1 = pyomo.environ.Expression(rule=objective_component1)

def objective_component2(model):
    return - sum(model.VOLUME_SELL[market] * model.bid_price[market] for market in model.market)

model.obj_component2 = pyomo.environ.Expression(rule=objective_component2)

model.objective = pyomo.environ.Objective(rule=model.obj_component1 + model.obj_component2, sense=-1)

我收到一个错误:

ValueError: No value for uninitialized NumericValue object VOLUME_BUY[market]

我什至试着写下表达式:

obj1 = sum(model.VOLUME_BUY[market] * model.ask_price[market] for market in model.market)
obj2 = - sum(model.VOLUME_SELL[market] * model.bid_price[market] for market in model.market)
model.objective = pyomo.environ.Objective(rule=obj1 + obj2, sense=-1)

但是我得到了同样的错误。

我不明白为什么我会收到变量对象未初始化的错误消息。也许表达式 pyomo 对象不是用于构造我的 objective 函数的正确对象?

请注意,我还想使用不同的表达式来构造我的模型的平衡约束,但我也没有做到。

我正在使用 Python 2.7 和 pyomo 4.4.1。

在此先感谢您的帮助!

我认为问题在于您正在使用 rule 关键字来初始化 Objective 对象。您实际上只需要在从 AbstractModel 开始时(或在声明索引组件时)执行此操作。由于 Pyomo 表达式是可调用的,因此它不会将您传递给它的内容与标准函数区分开来(因此它调用它,期望它是 return 一个表达式,但它实际上只是计算表达式)。

rule= 更改为 expr= 应该可以解决问题。