Reputation: 41
I have a problem with formulating constraints for 3d indexed variables with Pyomo: I have the following variable list:
1 Var Declarations
E : Size=6, Index=N
Key : Lower : Value : Upper : Fixed : Stale : Domain
(0, 0, 2) : 0 : 10 : None : False : False : NonNegativeReals
(0, 0, 3) : 0 : 10 : None : False : False : NonNegativeReals
(0, 2, 0) : 0 : 10 : None : False : False : NonNegativeReals
(0, 3, 0) : 0 : 10 : None : False : False : NonNegativeReals
(1, 3, 1) : 0 : 10 : None : False : False : NonNegativeReals
(1, 4, 1) : 0 : 10 : None : False : False : NonNegativeReals
they are essentially values in a 3D array (2x5x5) which can take a value other then 0. I try to optimize them, with some constraints: - the sum value of the variables in a row should be maximized - the sum value of the variables in a column should take a certain value
My question is regarded to both constraints: I tried to formulate the first constraint like this:
def max_perf_rule(model, a, b):
return sum(model.E[a,b,c] for c in range(5) if (a,b,c) in model.N) <= H[a,b]
model.max_perf = Constraint(range(2), range(5), rule = max_perf_rule)
, where model.N= [(0, 0, 2), (0, 0, 3), (0, 2, 0), (0, 3, 0), (1, 3, 1), (1, 4, 1)]
The variables are originally given by model.N (list of 3d tuples) but I need the two "range(2)" and "range(5)" as inputs in this constraint in order to be able to refer to the proper row.
No matter what I try I cannot create the desired constraints. They should look something like this:
max_perf : Size=10, Index=max_perf_index, Active=True
(0, 0) : E[0,0,2] + E[0,0,3] : <= 0.0
(0, 2) : E[0,2,0] : <= 2688.0
(0, 3) : E[0,3,0] : <= 896.0
(1, 3) : E[1,3,1] : <= 448.0
(1, 4) : E[1,4,1] : <= 9999999.0
...but I keep getting the following error:
"ERROR: Constructing component 'max_perf' from data=None failed: ValueError:
Invalid constraint expression. The constraint expression resolved to a
trivial Boolean (True) instead of a Pyomo object. Please modify your rule
to return Constraint.Feasible instead of True.
Error thrown for Constraint 'max_perf[0,1]'"
I have no idea what this is; I even tried to reproduce the situation with a dictionary instead of model.E and it worked nicely.
Do you have any solution for the problem? Thanks in advance!
Upvotes: 0
Views: 758
Reputation: 2818
The problem is that with the way you set up your indexing sets, not every combination of range(2) x range(5) x range(5) appears in model.N
. For some combinations the sum
in the constraint rule will not have any terms and therefore evaluate to a constant value of 0. The easiest way to get around this would be to add a check in your constraint rule to make sure the sum is not empty:
def max_perf_rule(model, a, b):
temp = sum(model.E[a,b,c] for c in range(5) if (a,b,c) in model.N)
if type(temp) is int: # This will be true if the sum was empty
return Constraint.Skip
return temp <= H[a,b]
model.max_perf = Constraint(range(2), range(5), rule = max_perf_rule)
Upvotes: 1