Kristof
Kristof

Reputation: 41

Constraint formulation in Pyomo with 3d-indexed varaibles

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

Answers (1)

Bethany Nicholson
Bethany Nicholson

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

Related Questions