Pyomo(v5.2)python(v3.7)脚本解决具体模型引发ValueError:未定义目标;无法写入合法的LP文件

时间:2018-10-05 19:03:39

标签: python pyomo

我已经建立了一个pyomo具体模型,并尝试使用python脚本(带有python 3.7的Pyomo 5.2版)运行它。当我尝试通过运行来求解模型时:

opt = SolverFactory('glpk')
results = opt.solve(model)
results.write()

然后我收到此错误:

ValueError: ERROR: No objectives defined for input model;  cannot write legal LP file

有趣的是,我知道客观规则是可行的。运行Objective_rule(model)时,我会得到一个值,也可以通过为模型变量分配不同的值来手动更改它们,例如:

model.system_capacity = 1000

目标规则的返回值随之变化。

有什么想法吗?一般来说,我对pyomo和代数建模语言(AML)还是很陌生。

这是我的模型,简化了:

# pyomo model for fitting historical solar generation profile to PVWatts simulation
# initialize input parameters
system_capacity_init = 1.0
lims = [0.2, 3.0]
system_capacity_bounds = (system_capacity_init * lims[0], system_capacity_init * lims[1])
# define and initialize integer parameters
# module type
module_type_dict = {0: 'Standard', 1: 'Premium', 2: 'ThinFilm'}
module_type_vals = list(module_type_dict.keys())
module_type_index_init = 0
# initialize pyomo concrete model
model = ConcreteModel()
# define continuous variables
model.system_capacity = Var(initialize=system_capacity_init, 
                            bounds=system_capacity_bounds,
                            domain=PositiveReals)
# define integer variables
# module type
model.module_type_vals = Set(initialize=module_type_vals)
model.module_type = Var(initialize=module_type_vals[module_type_index_init], 
                        within=model.module_type_vals)
# define objective function
def Objective_rule(model):
    """get hourly modeled solar roduction from PVWatts5 simulation tool using hourly historical solar insolation
    defined in filename_solar comparing against hourly historical date in hourlysettlementdata"""
    system_capacity = value(model.system_capacity)
    module_type = value(model.module_type)
    hourlypvwatts = sf.gethourlysolarproduction(filename_solar, folder, 
            system_capacity, module_type)
    leastsquared = np.sum((hourlypvwatts[:8760] - hourlysettlementdata[:8760])**2)
    return float(leastsquared)
# when passed function named as _rule then automatically assigns as rule, defaulte sense=minimize
model.Objective = Objective()
# examine model
model.pprint()

这是pprint /模型声明(同样,我删除了一些变量,所以它更短...):

1 Set Declarations
    module_type_vals : Dim=0, Dimen=1, Size=3, Domain=None, Ordered=False, Bounds=(0, 2)
        [0, 1, 2]

2 Var Declarations
    module_type : Size=1, Index=None
        Key  : Lower : Value : Upper : Fixed : Stale : Domain
        None :     0 :     0 :     2 : False : False : module_type_vals
    system_capacity : Size=1, Index=None
        Key  : Lower : Value : Upper : Fixed : Stale : Domain
        None :  12.0 :  60.0 : 180.0 : False : False : PositiveReals

1 Objective Declarations
    Objective : Size=0, Index=None, Active=True
        Key : Active : Sense : Expression

12 Declarations: system_capacity dc_ac_ratio inv_eff losses tilt azimuth gcr module_type_vals module_type array_type_vals array_type Objective

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

如评论中所述,在声明目标函数时您没有传递目标函数规则。您的目标函数声明应为:

model.Objective = Objective(rule=Objective_rule)

我看到的另一个问题是您的目标函数规则看起来并不依赖于模型中的任何变量,并且将是当前编写方式的固定浮点值。请记住,目标函数规则不是由求解程序多次评估的回调函数。目标函数规则应返回包含Pyomo变量的代数表达式。

答案 1 :(得分:1)

我本来打算将其发布为@ bethany-nicholson的评论,但有足够的其他信息可提供其他答案。

首先,关于返回表达式而不是计算值(即规则生成表达式而不是回调)的答案是正确的。

此答案的其余部分针对“隐式规则”的使用。尽管较旧版本的Pyomo支持“隐式规则”(即,组件foo在没有明确提供规则的情况下自动寻找并使用foo_rule()),但Pyomo 4.0和开发人员已弃用该行为威胁要在Pyomo 5.0中将其完全删除(尽管从5.5版本开始,该功能-具有弃用警告-仍然存在)。

也就是说,隐式规则似乎从未对Objective组件起作用(隐式规则功能内置于Block组件中,并且依赖于将规则存储为{{组件...中的1}}属性,而目标使用_rule而不是rule)。这种脆弱性部分是为什么不支持隐式规则的原因。

如果您正在寻找一种简洁的表示法来指定模型,则可以考虑使用组件装饰器表示法:

_rule

这将创建一个Objective组件,并使用名称@model.Objective() def obj(m): return # expression defining the objective 将其附加到model对象,并将obj函数指定为组件的规则。