There exist various reasons why a solver could not find the optimal solution. You must always check why a solver terminated. Typical reasons are:
- optimal solution was found
- termination criteria was reached, e.g. time limit or a limit on the optimality gap
- solver proved that problem is infeasible
Popular solvers such as cplex/gurobi can report their status through a getStatus
function. When a solver terminates due to some termination criteria, you can end up in any of the following situations:
- Some solution was found. The optimality gap gives you insight into the quality of this solution. However, there might exist better solutions, i.e. it is unknown whether this solution is optimal or not.
- No solution was found. There might however exist feasible solutions. This status is usually indicated as 'undefined/unknown', as it is unknown whether the solution space is empty or not.
Frequently, the solver is quickly able to determine feasibility of a problem. This can already happen in the pre-solve status. Modern solvers can search for a Minimal irreducible inconsistent subsystem. This is a subset of constraints which collectively render your problem infeasible. Deleting any constraint of this set would render the subproblem defined by these constraints feasible. Note that there may exist multiple causes of infeasibility in your model, i.e. multiple different IISs.
If you want to know more about this subject, I recommend the following papers:
- Finding the minimum weight IIS cover of an infeasible system of linear inequalities by Parker and Ryan, 1996
- Minimal Infeasible Subsystems and Benders cuts by Fischetti, Salvagnin, Zanette, 2008
Finding a minimum IIS, i.e. the smallest IIS is an NP-hard problem. Therefore, many solvers use heuristics to find a minimal, but not necessarily minimum IIS. I my experience, trying to find an IIS using CPLEX or Gurobi is a game of hit and miss: finding an IIS might take quite some time, especially in large models. Also, the IIS returned can be big, so interpreting the source of infeasibility might not be trivial. In practice I often use the following approach:
- Compute a feasible solution to your problem using for instance a simple heuristic.
- Fix all variables in your model to their corresponding values in the solution found in the previous step.
- Solve the model and search for an IIS. Gurobi:
Model.computeIIS()
. Cplex: Cplex.getIIS
.
- Since all variables are fixed, the IIS returned by the solvers is typically very small.