Compute simplex tableau from Gurobi.jl using JuMP

I am modeling an LP in JuMP using Gurobi. How can I obtain the optimal simplex tableau?

For example, consider the below LP:

A = [1; 2; 3]'
c = [4; 5; 6]
b = 7
M = Model(Gurobi.Optimizer)
set_optimizer_attribute(M, "Presolve", 0)
set_optimizer_attribute(M, "Method", 2)
@variable(M, x[1:3])
@objective(M, Min, c' * x)
@constraint(M, A * x >= b)
@constraint(M, x .>= 0)
optimize!(M)
value.(x)

and I have tried

y = zeros(3)
m = backend(M)
julia> Gurobi.GRBBinvRowi(m,1,y)
ERROR: MethodError: no method matching unsafe_convert(::Type{Ptr{Nothing}}, ::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}})
Closest candidates are:
  unsafe_convert(::Union{Type{Ptr{Nothing}}, Type{Ptr{Base.Libc.FILE}}}, ::Base.Libc.FILE) at libc.jl:94
  unsafe_convert(::Type{Ptr{T}}, ::Base.RefValue{SA}) where {S, T, D, L, SA<:StaticArrays.SArray{S, T, D, L}} at /Users/.julia/packages/StaticArrays/12k3X/src/SArray.jl:125
  unsafe_convert(::Type{Ptr{T}}, ::Base.RefValue{FA}) where {N, T, D, FA<:StaticArrays.FieldArray{N, T, D}} at /Users/.julia/packages/StaticArrays/12k3X/src/FieldArray.jl:124
  ...
Stacktrace:
 [1] GRBBinvRowi(model::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}, i::Int64, x::Float64)
   @ Gurobi ~/.julia/packages/Gurobi/WjZv8/src/gen91/libgrb_api.jl:594
 [2] top-level scope
   @ REPL[27]:1

It’s not clear to me how to update internalModel from here.

1 Like

To access the C API, you need to use

M = direct_model(Gurobi.Optimizer())
# ...
m = backend(M)

At the risk of breaking things, you can also use

M = Model(Gurobi.Optimizer)
# ...
m = unsafe_backend(M)

but the method is called unsafe_ for a reason: Models · JuMP

1 Like

Your argument y in Gurobi.GRBBinvRowi(m,1,y) should not be a Julia Vector
Gurobi expects a sparse vector struct of type GRBsvec. However the corresponding one defined in Gurobi.jl seems to be defined as immutable so I could not get GRBBinvRowi to work (or actually GRBBinvColj in my case). I get it to work with a ccall directly in the following example:

m=direct_model(Gurobi.Optimizer())
grb = unsafe_backend(m)
@variable(m,y>=0)
@variable(m,x>=0)
@constraint(m,x<=1)
@constraint(m,y<=2)
@objective(m,Max,x+y)
optimize!(m)

mutable struct mySvec
len::Cint;
ind::Ptr{Cint};
val::Ptr{Cdouble};
end

idxs = Vector{Cint}(undef,2) # model has 2 rows
vals = Vector{Cdouble}(undef,2)
ss = mySvec(0,pointer_from_objref(idxs),pointer_from_objref(vals))
res = ccall((:GRBBinvColj, “gurobi90”), Cint, (Ptr{GRBmodel}, Cint, Ptr{mySvec}), grb, 1, Ref(ss))

println(res)
@show ss.len
@show unsafe_load(ss.ind)
@show unsafe_load(ss.val)

1 Like