Bounds for Duals in a JuMP Model With the Gurobi Solver

It’s rare that I come across a problem whose solution is, as far as I can tell, nowhere on the Internet. I’m posting this here in case someone else, like me, wonders: after solving a linear optimization problem using JuMP with the Gurobi solver in Julia, what are the upper and lower bounds to the duals (shadow values)? If that’s why you’re here, at least you know you’re not alone!

There is a method to access the duals themselves in Julia’s Gurobi interface: simply run getduals(constraint). There is no similar method to extract the upper and lower bounds for these duals, however. They exist within Gurobi constraints as the attributes SARHSUp and SARHSLow, respectively. After poking around the Julia Gurobi interface source code, I suspected I could access the bounds directly via some of its methods.

Sure enough, if jumpModel is a JuMP LP model with continuous variables, here is how to access arrays of the constraints’ dual upper bounds, dual lower bounds, and slack:

# extract the raw Gurobi solver
grbmodel = getrawsolver(jumpModel)

# count its number of constraints
cs = num_constrs(grbmodel)

# extract the attributes' values as arrays
Gurobi.get_dblattrarray(grbmodel, "SARHSUp", 1, cs)
Gurobi.get_dblattrarray(grbmodel, "SARHSLow", 1, cs)
Gurobi.get_dblattrarray(grbmodel, "Slack", 1, cs)

The function get_dblattrarray is part of the Gurobi interface that returns an array of attributes. We’re simply spoon-feeding it the raw solver, the property name, the index of the first constraint, and the number of constraints. You can also use this technique to expose the underlying model’s variable attributes, in which case the fourth parameter should be the number of model variables.