How to get the dual value of a constraint using C++&Gurobi?

First thing first, if you are solving mixed-integer programs (MIP), including mixed-integer linear programs (MILP), you are out of luck, because Gurobi does not support getting dual values for mixed-integer problems. You could only get dual values if your problem is a continuous problem (Reference: https://support.gurobi.com/hc/en-us/articles/360034305272-Why-can-t-I-get-the-Pi-values-for-a-MIP-problem-).

If your problem is a continuous problem, congrats! Let’s see how you can get the dual values.

  1. Define the constraints with a name. What does this mean?

    • If you didn’t want to get the dual, you would not need to name the constraint and could just use Model.addConstr(Your_Constraint_Here).
    • But if you wanted to get the dual, you need to define the constraint as follows: GRBConstr MyConst = Model.addConstr(Your_Constraint_Here). In this code, GRBConstr is the type of the variable (Gurobi Constraint) and MyConst is the name of the variable (the name of the constraint).
  2. Get the value of the dual using MyConst.get(GRB_DoubleAttr_Pi). In this case, MyConst is the name of the constraint.

  3. At last, output the dual value. You have a few options:

  • You could print out the dual value directly using
std::cout << "Dual = " << MyConst.get(GRB_DoubleAttr_Pi) << endl;
  • Or save it into a txt file:
ofstream results;
results.open ("results.txt");
results << "Dual: " << MyConst.get(GRB_DoubleAttr_Pi) << endl;	
results.close();
  • You could also save the dual value into a variable for later use:
double DualValue = MyConst.get(GRB_DoubleAttr_Pi);

The following is a complete example code for a linear program, which prints the value of the dual at the end.

#include "gurobi_c++.h"
#include<iostream>
using namespace std;
int main()
{
	try {
		GRBEnv env = GRBEnv(); // Set up the Gurobi environment
		GRBModel SimpleExample = GRBModel(env); // Define the model as "SimpleExample" - but you could name the model whatever you like
		GRBVar x = SimpleExample.addVar(0, 50, 20, GRB_CONTINUOUS, "x"); // Define variable x in the model and its range (0-50)
		GRBVar y = SimpleExample.addVar(0, 100, 30, GRB_CONTINUOUS, "y"); // Define variable y in the model and its range (0-100)
		SimpleExample.set(GRB_IntAttr_ModelSense, GRB_MINIMIZE); // Define the objective function as to minimize 20x+30y
		GRBConstr MyConst = SimpleExample.addConstr(x + y == 70); // Define the third constraint (x+y=70)
		SimpleExample.optimize(); // Solve the model
		std::cout << "Objective value: " << SimpleExample.get(GRB_DoubleAttr_ObjVal) << endl; // Output the objective value
		std::cout << "x = " << x.get(GRB_DoubleAttr_X) << endl; // Output the value of x
		std::cout << "y = " << y.get(GRB_DoubleAttr_X) << endl; // Output the value of y
		std::cout << "Dual = " << MyConst.get(GRB_DoubleAttr_Pi) << endl;
	} catch(GRBException e) {
		cout << "Error code = " << e.getErrorCode() << endl;
		cout << e.getMessage() << endl;
	} catch (...) {
		cout << "Error during optimization" << endl;
	}
	return 0;
}