Why Does Pyomo Behavior Change When Passing parameters to constraint function?

独自空忆成欢 提交于 2021-01-29 08:25:33

问题


This code works correctly.

def m(model, i):
    return model.fd_amt[i] <= getattr(model, 'br_sa_ind')[i] * global_m

setattr(model, ind+"_m",Constraint(model.br_standalone_I, rule=m))

But this

def m(model, i, ind_name):
    return model.fd_amt[i] <= getattr(model, ind_name)[i] * global_m

setattr(model, ind+"_m",Constraint(rule=m(model,model.model.br_standalone_I, 'br_sa_ind') ))

results in this error:

ERROR: evaluating expression: No value for uninitialized NumericValue object fd_amt[br_standalone_I] (expression: fd_amt[br_standalone_I] <= 13 * br_sa_ind[br_standalone_I]) ERROR: Rule failed when generating expression for constraint br_sa_ind_m: ValueError: No value for uninitialized NumericValue object fd_amt[br_standalone_I] ERROR: Constructing component 'br_sa_ind_m' from data=None failed: ValueError: No value for uninitialized NumericValue object fd_amt[br_standalone_I]

Is there a reason Pyomo constraints behave this way with explicit parameters?


回答1:


You can achieve the desired behavior by replacing rule= with expr=:

setattr(model, ind+"_m",Constraint(model.br_standalone_I))
for i in model.br_standalone_I:
    getattr(model, ind+"_m")[i].set_value(expr=m(model, i, 'br_sa_ind'))

The purpose of rule is so that indexed constraint expressions can be constructed using a common rule. If you have a singleton constraint, you can specify the expression using expr.




回答2:


Your code doesn't work because you use a function call rule=m(...) instead of a function reference rule=m.

While this solution may not answer to your problem directly, it may offer a workarround. I still don't know if Pyomo allows what you are asking (passing a parameter to a rule).

Create a new set with your parameter that you want to pass as your only element. You could add more elements later if you want, if you handle your parameters in your rule's function adequately. For simplicity, let's begin with only one element.

model.S = Set(initialize=['br_sa_ind'])

Then use this set as your parameter to your rule. It's like using a for all notation, with only one element. (For all element in set S and in set br_standalone_I, apply rule m). You should create your constraint using

Constraint(model.br_standalone_I, model.S, rule=m)

So your entire code would look like

def m(model, i, ind_name):
    return model.fd_amt[i] <= getattr(model, ind_name)[i] * global_m

setattr(model, ind+"_m",Constraint(model.br_standalone_I, model.S, rule=m))

This is not entirely elegant, but it should work. I yet want to hear if you can specify parameters to a rule while creating a constraint.



来源:https://stackoverflow.com/questions/54109887/why-does-pyomo-behavior-change-when-passing-parameters-to-constraint-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!