Gurobi Error 10005: Unable to retrieve attribute 'Pi'

I am trying to retrieve some Gurobi attributes for through MOI.get() function with direct_model() enabled. Everything seems to be working but when I try to get “Pi” (dual value for a constraint), I encounter the error:

Gurobi Error 10005: Unable to retrieve attribute 'Pi'
in top-level scope at initial_test.jl:53
in get at JuMP\e0Uc2\src\JuMP.jl:889
in get at Gurobi\Lci9Q\src\MOI_wrapper.jl:3657
in _get_attribute at Gurobi\Lci9Q\src\MOI_wrapper.jl:3619
in _check_ret at Gurobi\Lci9Q\src\MOI_wrapper.jl:277
versioninfo():
Commit 2d5741174c (2019-12-30 21:36 UTC)
Platform Info:
OS: Windows (x86_64-w64-mingw32)
CPU: Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-6.0.1 (ORCJIT, skylake)
Environment:
JULIA_EDITOR = "C:\Users\Reza\AppData\Local\atom\app-1.54.0\atom.exe" -a
JULIA_NUM_THREADS = 4

Pkg.status():
`C:\Users\Reza\.julia\environments\v1.3\Project.toml`
[c52e3926] Atom v0.12.30
[fa961155] CEnum v0.3.0
[be33ccc6] CUDAnative v3.1.0
[8f4d0f93] Conda v1.5.0
[7806a523] DecisionTree v0.10.10
[31c24e10] Distributions v0.23.8
[587475ba] Flux v0.10.4
[60bf3e95] GLPK v0.14.5
[61eb1bfa] GPUCompiler v0.2.0
[2e9cd046] Gurobi v0.9.7
[7073ff75] IJulia v1.23.1
[b6b21f68] Ipopt v0.6.5
[4076af6c] JuMP v0.21.4
[e5e0dc1b] Juno v0.8.4
[1902f260] Knet v1.3.6
[91a5bcdd] Plots v1.6.12
[438e738f] PyCall v1.92.2
[3646fa90] ScikitLearn v0.6.3
[2913bbd2] StatsBase v0.33.2
[9a3f8284] Random

steps to reproduce:

using Gurobi
using JuMP

# define a simple UC problem

n_u = 8
n_t = 4
U = collect(1:n_u) # num units
T = collect(1:n_t) # num time steps
p_g_min = round.(0.3 <em>rand(n_u), digits=2)
p_g_max = 1 .+ round.(rand(n_u), digits=2)
cost_g = 10 .+ round.(10.0</em> rand(n_u), digits=1)
cost_g0 = round.(3.0 <em>rand(n_u), digits=1)
d0 = rand((sum(p_g_min):.01:.5</em> sum(p_g_max)),n_t)

# basic_uc_model = Model(Gurobi.Optimizer)

basic_uc_model = direct_model(Gurobi.Optimizer())
    @variable(basic_uc_model, p_g[i in U, t in T])
    @variable(basic_uc_model, I_g[i in U, t in T], Bin)
    @constraint(basic_uc_model, lower_band[i in U, t in T], p_g[i,t] >= p_g_min[i]*I_g[i,t])
    @constraint(basic_uc_model, upper_band[i in U, t in T], p_g[i,t] <= p_g_max[i]*I_g[i,t])
    @constraint(basic_uc_model, demand[t in T], sum(p_g[i,t] for i in U) == d0[t])
    @objective(basic_uc_model, Min, sum(p_g[i,t]*cost_g[i] + I_g[i,t]*cost_g0[i] for i in U, t in T))

optimize!(basic_uc_model)
JuMP.objective_value(basic_uc_model)
JuMP.value.(p_g)
JuMP.value.(I_g)

MOI.get(basic_uc_model, Gurobi.ModelAttribute("ObjVal")) # Objective value for current solution
MOI.get(basic_uc_model, Gurobi.VariableAttribute("Obj"), p_g[2,2]) # Linear objective coefficient
MOI.get(basic_uc_model, Gurobi.ConstraintAttribute("Slack"), lower_band[2,2]) #
MOI.get(basic_uc_model, Gurobi.ConstraintAttribute("Pi"), upper_band[2,2]) # Dual value (also known as the shadow price)

I can obtain other attributes as can be seen, this only happens when I try “Pi”. Also, I tried different versions of Gurobi (version 8.1 gurobi software with according julia gurobi package, instead of 9.1) but it did not help. I even tried it on both JuliaPro and Atom+Juno but that did not help neither. Finally, this is not certainly a syntax issue since if I change “Pi” with a random name that is not included, e.g. “Dual”, the error code changes : Gurobi Error 10004: Unknown attribute ‘Dual’. I would appreciate your feedback.

Please provide a link when cross-posting: Gurobi Error 10005: Unable to retrieve attribute 'Pi' · Issue #390 · jump-dev/Gurobi.jl · GitHub.

As I explained, dual values are not available for models with binary variables.

1 Like

Thank you for your responses and I appreciate you bearing with me. I am going to delete this post if possible.

1 Like

No need to delete. It may be helpful for others. The link for cross posting is just so that two people don’t reply with the same answer to a question in two places.

This post was super helpful to me as I ran into the same issue today. Thank you :slight_smile:

1 Like

Glad to hear!

A reminder to future readers that you should query dual_status(model) to see if the solver has a solution before querying dual or shadow_price. Not doing so can throw an error or silently return incorrect solutions.

Relevant section in the JuMP documentation: Solutions · JuMP