问题
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