This post is the continuation of the post "Create different restrictions with a single rule"
In this case I show my all code, trying to use the @AirSquid response to create my constraint called
model.node_limit
from pyomo.environ import*
model = ConcreteModel (name='WFLP')
import mydataWFLP
model.SP = Var(mydataWFLP.N, within=NonNegativeReals)
def obj_rule(model):
return sum(mydataWFLP.h[n]*model.SP[n] for n in mydataWFLP.N)
model.obj = Objective(rule=obj_rule)
def SP_upper_bound_rule (model,n):
return model.SP[n] <= mydataWFLP.P[n]
model.SP_upper_bound = Constraint(mydataWFLP.N, rule=SP_upper_bound_rule)
model.Nodo = Set(initialize = mydataWFLP.Nodo.keys())
model.C = Set(model.Nodo, initialize=mydataWFLP.Nodo)
def node_limit_rule (model,nodo):
return sum(model.SP[nodo] for other in model.C[nodo]) <= sum(mydataWFLP.P[nodo] for other in model.C)
model.node_limit = Constraint(model.Nodo, rule=node_limit_rule)
opt = SolverFactory('glpk')
results = opt.solve(model)
model.display()
model.obj.pprint()
model.SP_upper_bound.pprint()
model.node_limit.pprint()
The dataset used is
N = [1,2,3,4,5,6,7]
M = [1,2,3]
h = {1:400,2:300,3:200,4:100,5:50,6:150,7:250}
P = {1:20,2:12,3:18,4:27,5:30,6:39,7:34}
Nodo = {1: [1,2,3,4], \
2: [3,4,5], \
3: [5,6,7],}
I'm doing something wrong, because, now my constraint is the following
node_limit : Size=3, Index=Nodo, Active=True
Key : Lower : Body : Upper : Active
1 : -Inf : SP[1] + SP[1] + SP[1] + SP[1] : 77.0 : True
2 : -Inf : SP[2] + SP[2] + SP[2] : 75.0 : True
3 : -Inf : SP[3] + SP[3] + SP[3] : 103.0 : True
Now, it does create the constraints with the number of variables I have defined, but it does not create the constraints with the variables I want, that are
node_limit : Size=3, Index=Nodo, Active=True
Key : Lower : Body : Upper : Active
1 : -Inf : SP[1] + SP[2] + SP[3] + SP[4] : 60.0 : True
2 : -Inf : SP[3] + SP[4] + SP[5] : 36.0 : True
3 : -Inf : SP[5] + SP[6] + SP[7] : 54.0 : True
How can I fix it?
The fist post is here
You are close. You just have an error within both of your sum()
statements. This is yours:
def node_limit_rule (model,nodo):
return sum(model.SP[nodo] for other in model.C[nodo]) <= sum(mydataWFLP.P[nodo] for other in model.C)
In both sums you are summing copies of the same thing because you are summing (in the first part) SP[nodo]
multiple times. You can see the repetition in the output that you posted above. You want to some over other
like so:
def node_limit_rule (model,nodo):
return sum(model.SP[other] for other in model.C[nodo]) <= sum(mydataWFLP.P[other] for other in model.C)
You are using nodo
to look into model.C
to get the set of the others
and then you want to sum over all of the others
... make sense?
A couple other nit-picks...
In the future, you'll get better response on this site if you make a tiny reproducible example that others can just copy and tinker with. Yours is close, but you could just put your data into your example with a little extra work so that it "just runs"
I don't see where you are printing/inspecting the results of your optimization. This will bite you. You need to ensure that the termination condition is what you expect.
Lastly, just a recommendation, you should organize your models a little better and comment them. Much easier to share/collaborate. Put the sets together, say what they mean, etc. See my other posts on this site with [pyomo] tag for examples.