sensitivity_c++.cpp


/* Copyright 2016, Gurobi Optimization, Inc. */

/* A simple sensitivity analysis example which reads a MIP model
   from a file and solves it. Then each binary variable is set
   to 1-X, where X is its value in the optimal solution, and
   the impact on the objective function value is reported.
*/

#include "gurobi_c++.h"
using namespace std;

int
main(int   argc,
     char *argv[])
{
  if (argc < 2) {
    cout << "Usage: sensitivity_c++ filename" << endl;
    return 1;
  }

  GRBVar* vars = NULL;
  double* origX = NULL;

  try {

    // Create environment

    GRBEnv env = GRBEnv();

    // Read and solve model

    GRBModel model = GRBModel(env, argv[1]);

    if (model.get(GRB_IntAttr_IsMIP) == 0) {
      cout << "Model is not a MIP" << endl;
      return 1;
    }

    model.optimize();

    if (model.get(GRB_IntAttr_Status) != GRB_OPTIMAL) {
      cout << "Optimization ended with status "
           << model.get(GRB_IntAttr_Status) << endl;
      return 1;
    }

    // Store the optimal solution

    double origObjVal = model.get(GRB_DoubleAttr_ObjVal);
    vars = model.getVars();
    int numVars = model.get(GRB_IntAttr_NumVars);
    origX = model.get(GRB_DoubleAttr_X, vars, numVars);

    // Disable solver output for subsequent solves

    model.set(GRB_IntParam_OutputFlag, 0);

    // Iterate through unfixed, binary variables in model

    for (int i = 0; i < numVars; i++) {
      GRBVar v = vars[i];
      char vType = v.get(GRB_CharAttr_VType);

      if (v.get(GRB_DoubleAttr_LB) == 0 && v.get(GRB_DoubleAttr_UB) == 1
          && (vType == GRB_BINARY || vType == GRB_INTEGER)) {

        // Set variable to 1-X, where X is its value in optimal solution

        if (origX[i] < 0.5) {
          v.set(GRB_DoubleAttr_LB, 1.0);
          v.set(GRB_DoubleAttr_Start, 1.0);
        } else {
          v.set(GRB_DoubleAttr_UB, 0.0);
          v.set(GRB_DoubleAttr_Start, 0.0);
        }

        // Update MIP start for the other variables

        for (int j = 0; j < numVars; j++) {
          if (j != i) {
            vars[j].set(GRB_DoubleAttr_Start, origX[j]);
          }
        }

        // Solve for new value and capture sensitivity information

        model.optimize();

        if (model.get(GRB_IntAttr_Status) == GRB_OPTIMAL) {
          cout << "Objective sensitivity for variable "
               << v.get(GRB_StringAttr_VarName) << " is "
               << (model.get(GRB_DoubleAttr_ObjVal) - origObjVal) << endl;
        } else {
          cout << "Objective sensitivity for variable "
               << v.get(GRB_StringAttr_VarName) << " is infinite" << endl;
        }

        // Restore the original variable bounds

        v.set(GRB_DoubleAttr_LB, 0.0);
        v.set(GRB_DoubleAttr_UB, 1.0);
      }
    }

  } catch (GRBException e) {
    cout << "Error code = " << e.getErrorCode() << endl;
    cout << e.getMessage() << endl;
  } catch (...) {
    cout << "Error during optimization" << endl;
  }

  delete[] vars;
  delete[] origX;

  return 0;
}