Does my model have numerical issues?

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
    
    Once you have done this, running your program will produce one recordingXYZ.grbr file for each Gurobi environment your program creates (where XYZ is a three-digit, 0-padded value that increases from 000). You can replay this recording file using gurobi_cl (e.g., gurobi_cl recording000.grbr). Consult this section for more information on recording files.
  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

    <span>$</span>6\cdot10^6 / 0.00099 = 6.0606\cdot10^9.<span>$</span>
  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.