Search code examples
pyomo

Evaluate constraint expression as boolean


I want to evaluate if a constraint is respected or not in Pyomo when the values of the variables contained in constraint expression are known.

Use case: We know that one particular constraint sometimes makes the problem infeasible, depending on the value of the variable. Instead of sending the problem to the solver to test if the problem is feasible, converting the constraint expression to a boolean type would be enough to determine if the constraint is the culprit.

For the sake of providing a feasible example, here would be the code:

from pyomo.environ import ConcreteModel, Var, Constraint
model = ConcreteModel()
model.X = Var()

def constraint_rule(model):
    return model.X <= 1
model.a_constraint = Constraint(rule=constraint_rule)

Now, let's try to work with the expression to evaluate:

# Let's define the expression in this way:
expression = constraint_rule(model)

# Let's show that the expression is what we expected:
print(str(expression))

The previous statement should print X <= 1.0.

Now, the tricky part is how to evaluate the expression.

if expression == True:
    print("feasible")
else:
    print("infeasible")

creates an TypeError Exception (TypeError: Cannot create an EqualityExpression where one of the sub-expressions is a relational expression: X <= 1.0).

The last example doesn't work because constraint_rule doesn't return a boolean but a Pyomo expression.

Finally, I know that something like

def evaluate_constraint_a_expression(model):
    return value(model.X) <= 1

would work, but I can't assume that I will always know the content of my constraint expression, so I need a robust way of evaluating it.

Is there a clever way of achieving this? Like, evaluating the expression as a boolean and evaluating the left hand side and right hand side of the expression at the same time?


Solution

  • The solution is to use value function. Even if it says that it evaluates an expression to a numeric value, it also converts the expression to a boolean value if it is an equality/inequality expression, like the rule of a constraint.

    Let's suppose that the model is defined the way it is in the question, then the rest of the code should be:

    from pyomo.environ import value
    if value(expression) == True:
        print("feasible")
    else:
        print("infeasible")
    

    where expression is defined as written in the question.

    However, be advised that numeric precision in Python using this method can be different than the one provided by the solver. Therefore, it is possible that this method will show that a constraint is infeasible while it is just a matter of numeric imprecision of under 1e-10. So, while it is useful in finding if most constraints are feasible, it also generates some false positives.