Infeasibility AnalysisΒΆ
The optimization model is not ways feasible, and the optimizer may tell us some information about the infeasibility to diagnose the problem. There are two ways to handle the infeasibilities:
Find the IIS (Irreducible Infeasible Set) to identify the minimal set of constraints that cause the infeasibility.
Relax the constraints and solve a weaker problem to find out which constraints are violated and how much.
PyOptInterface currently supports the first method to find the IIS (only with Gurobi and COPT). The following code snippet shows how to find the IIS of an infeasible model:
import pyoptinterface as poi
from pyoptinterface import copt
model = copt.Model()
x = model.add_variable(lb=0.0, name="x")
y = model.add_variable(lb=0.0, name="y")
con1 = model.add_linear_constraint(x + y, poi.Geq, 5.0)
con2 = model.add_linear_constraint(x + 2 * y, poi.Leq, 1.0)
model.set_objective(x)
model.computeIIS()
con1_iis = model.get_constraint_attribute(con1, poi.ConstraintAttribute.IIS)
con2_iis = model.get_constraint_attribute(con2, poi.ConstraintAttribute.IIS)
print(f"Constraint 1 IIS: {con1_iis}")
print(f"Constraint 2 IIS: {con2_iis}")
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
Cell In[1], line 4
1 import pyoptinterface as poi
2 from pyoptinterface import copt
----> 4 model = copt.Model()
6 x = model.add_variable(lb=0.0, name="x")
7 y = model.add_variable(lb=0.0, name="y")
File /opt/hostedtoolcache/Python/3.12.10/x64/lib/python3.12/site-packages/pyoptinterface/_src/copt.py:373, in Model.__init__(self, env)
371 def __init__(self, env=None):
372 if env is None:
--> 373 init_default_env()
374 env = DEFAULT_ENV
375 super().__init__(env)
File /opt/hostedtoolcache/Python/3.12.10/x64/lib/python3.12/site-packages/pyoptinterface/_src/copt.py:83, in init_default_env()
81 global DEFAULT_ENV
82 if DEFAULT_ENV is None:
---> 83 DEFAULT_ENV = Env()
RuntimeError: COPT library is not loaded
This code snippet creates an infeasible model with two constraints and finds the IIS of the model. Obviously, the constraints are contradictory because x + 2 * y <= 1
and x + y >= 5
cannot be satisfied at the same time when x
and y
are non-negative. The optimizer will detect that the model is infeasible and return the IIS, which is the set of constraints that cause the infeasibility. We can query whether a constraint is in the IIS by calling get_constraint_attribute
with the ConstraintAttribute.IIS
attribute.
Sometimes, the bounds of the variables are not consistent with the constraints, and we need to query the IIS of the bounds of variables by calling get_variable_attribute
with the VariableAttribute.IISLowerBound
and VariableAttribute.IISUpperBound
attributes.
The following code snippet shows how to tell if the bounds of a variable are in the IIS:
model = copt.Model()
x = model.add_variable(lb=0.0, ub=2.0, name="x")
y = model.add_variable(lb=0.0, ub=3.0, name="y")
con1 = model.add_linear_constraint(x + y, poi.Geq, 6.0)
model.set_objective(x)
model.computeIIS()
con1_iis = model.get_constraint_attribute(con1, poi.ConstraintAttribute.IIS)
x_lb_iis = model.get_variable_attribute(x, poi.VariableAttribute.IISLowerBound)
x_ub_iis = model.get_variable_attribute(x, poi.VariableAttribute.IISUpperBound)
y_lb_iis = model.get_variable_attribute(y, poi.VariableAttribute.IISLowerBound)
y_ub_iis = model.get_variable_attribute(y, poi.VariableAttribute.IISUpperBound)
print(f"Constraint 1 IIS: {con1_iis}")
print(f"Variable x lower bound IIS: {x_lb_iis}")
print(f"Variable x upper bound IIS: {x_ub_iis}")
print(f"Variable y lower bound IIS: {y_lb_iis}")
print(f"Variable y upper bound IIS: {y_ub_iis}")