Does my model have numerical issues?

You can follow these steps to help determine whether a model is experiencing numerical issues:

  1. Isolate the model for testing by exporting a model file and a parameter file. The easiest way to do this is to create a gurobi.env file in your working directory that contains the following line:
    Record 1
    
    Then, run your Gurobi program, which will produce gurobi.rec files. Afterwards, you can replay this recording file using gurobi_cl.
  2. Using the Gurobi Interactive shell, run some simple Python code to read the model that the replay produces, and print the summary statistics:
    m = read('gurobi.rew')
    m.printStats()
    
    The output will look like:
    Statistics for model (null) :
      Linear constraint matrix    : 25050 Constrs, 15820 Vars, 94874 NZs
      Variable types              : 14836 Continuous, 984 Integer
      Matrix coefficient range    : [ 0.00099, 6e+06 ]
      Objective coefficient range : [ 0.2, 65 ]
      Variable bound range        : [ 1, 5e+07 ]
      RHS coefficient range       : [ 1, 5e+07 ]
    
    The range of numerical coefficients is one indication of potential numerical issues. As a very rough guideline, the ratio of the largest to the smallest coefficient should be less than <span>$</span>10^9<span>$</span>; smaller is better.

    In this example, the matrix range is

    \begin{displaymath}6\cdot10^6 / 0.00099 = 6.0606\cdot10^9.\end{displaymath}

  3. If possible, re-solve the model using the same parameters and review the logs. With the Python shell, use code like the following:
    m.read('gurobi.prm')
    m.optimize()
    
    Here are some examples of warning messages that suggest numerical issues:
    Warning: Model contains large matrix coefficient range
             Consider reformulating model or setting NumericFocus parameter
             to avoid numerical issues.
    Warning: Markowitz tolerance tightened to 0.5
    Warning: switch to quad precision
    Numeric error
    Numerical trouble encountered
    Restart crossover...
    Sub-optimal termination
    Warning: ... variables dropped from basis
    Warning: unscaled primal violation = ... and residual = ...
    Warning: unscaled dual violation = ... and residual = ...
    
  4. When the optimize function completes, print solution statistics. With the Python shell, use code like the following:
    m.printQuality()
    
    which provides a summary of solution quality:
    Solution quality statistics for model Unnamed :
      Maximum violation:
        Bound       : 2.98023224e-08 (X234)
        Constraint  : 9.30786133e-04 (C5)
        Integrality : 0.00000000e+00
    

    Violations that are larger than the tolerances are another indication of numerical issues. Also, for a pure LP (without integer variables), print the condition number via the following Python command:

    m.KappaExact
    
    The condition number measures the potential for error in linear calculations; a large condition number, such as <span>$</span>10^{12}<span>$</span>, is another indication of possible numerical issues, see this section for more details.
  5. If changing parameters (e.g., Method or Seed) leads to a different optimization status (e.g., Infeasible instead of optimal), or if the optimal objective values changes, this is usually a sign of numerical issues. To further assess this you can tighten tolerances (to the order of <span>$</span>10^{-8}<span>$</span> or even <span>$</span>10^{-9}<span>$</span>), and see if the behavior of the solver becomes consistent again. Note that tightening tolerances usually comes at the price of more computing time, and should not be considered as a solution for numerical issues.