Reputation: 27
I create an optimization model in pyomo, and I have a list of tuples as a parameter “par”.
import pyomo.environ as pe
model = pe.ConcreteModel()
p_set = [(1,2), (2,3), (4,5)]
model.par = pe.Param(initialize=p_set, mutable= True)
def var_fix(model, i, j ):
if (i,j) in model.par:
constraint = (model.v[i,j] == 1) # v is a binary variable
else:
constraint = (model.v[i,j] == 0)
return constraint
model.var_fix = pe.Constraint(model.edges, rule=var_fix)
But, after printing “var_fix” constraint, all of them are equall to zero:
Key : Lower : Body : Upper : Active
(1, 2) : 0.0 : v[1,2] : 0.0 : True
(2, 3) : 0.0 : v[2,3] : 0.0 : True
(4, 5) : 0.0 : v[4,5] : 0.0 : True
I define the parameter and constraint in this way since I want to iteratively change this parameter “par” with a new one which may have different number of tuples, then solve the problem. In each iteration I will do :
# generating par_new based on some random processes
par_new = [(5,10), (2,3), (4,5), (11,8), (10,6)]
model.par = par_new
# solve the problem again
Upvotes: 1
Views: 528
Reputation: 2589
The crux of your problem is that you are defining a single ScalarParam that holds a list of tuples. Scalar objects in Pyomo are special cases of their Indexed counderparts that use an implicit index of None
. This is done so that code working with Pyomo models can treat all components as if they were indexed (which prevents code from being littered with if comp.is_indexed():
tests). The __contains__
test that you are doing (if (i,j) in model.par
) is testing if the tuple is in the Param's indexing set, and not in the Param's value.
The simplest change is to change the test to check the Param's value:
>>> from pyomo.environ import *
>>> m = ConcreteModel()
>>> m.p = Param(initialize=[(1,2),(3,4)], mutable=True, domain=Any)
>>> (1,2) in m.p
False
>>> (1,2) in m.p.value
True
However, if you intend on updating the model iteratively (without rebuilding it), I would recommend making the param hold the RHS of the constraint. That is, something more like:
model = pe.ConcreteModel()
p_set = [(1,2), (2,3), (4,5)]
def par(m, i, j):
return 1 if (i,j) in p_set else 0
model.par = pe.Param(model.edges, initialize=par, mutable=True)
def var_fix(model, i, j ):
return model.v[i,j] == model.par[i,j]
model.var_fix = pe.Constraint(model.edges, rule=var_fix)
This is because construction rules are not callbacks: they are called only when initially constructing the component and not during the solve. Updating the Params would then look more like:
model.par.set_values(0)
for i,j in par_new:
model.par[i,j] = 1
Upvotes: 3