Minimum value for each element in array

Viewed 129

I have a basic question as I am new to both Python and Pyomo. I have set a constraint that works properly to set the sum of the elements in array equal to 1.

def Allocation(model):
    return sum(model.alloc[i] for i in model.alloc) == 1
model.allocationSum  = Constraint(rule=Allocation)

What must I do to then have each element of the array be greater than or equal to 0.01? The following did not work:

def allocationMinimum(model):
    for i in model.alloc
        return model.alloc[i] >= 0.01
model.minimumWeight = Constraint(rule=allocationMinimum)

Thanks.

3 Answers

Good points above on code structure, but I'm not sure if the central question was covered. Erwin is correct that this can be done by setting bounds on the variables when they are created. The general form for doing a constraint "for each" value of the index with a function-rule combo is below.

def allocation_minimum(model, i):
    return model.alloc[i] >= 0.01
model.min_weight = Constraint(model.i, rule=allocation_minimum)

In this construct, the first variable (or variables) of the Constraint constructor are the indexing variable(s) and the "rule" will be called with each value of the index set(s), creating 1 constraint expression for each value of the index (model.i in this case). In this case where it is a simple min, this is equivalent to setting a lower bound on the variable.

By having a return within the loop, you ensure that the function exits on the first iteration, so you will get the rule applied to the first element. One way to do this is with the builtin all:

def allocation_minimum(model):
    return all(i >= 0.01 for i in model.alloc)

Another way is to use any on the inverse condition:

def allocation_minimum(model):
    return not any(i < 0.01 for i in model.alloc)

If you must use an explicit for loop, you need to wait til the end of the loop, when you've checked all the elements, before returning True:

def allocation_minimum(model):
    for i in model.allocation:
        if i < 0.01:
            return False
    return True

On a related note, it's conventional to name objects, including functions, using snake_case, except classes, which use CamelCase. I've renamed allocation_minimum to conform to this convention.

All loops and conditionals need a colon at the end of the line. That was the cause of your original syntax error.

Related