# Gather Optimal Tableau Information using CPLEX.jl

Hey! I’m currently working on implementing fractional Gomory cuts, and I need to know the optimal simplex tableau in order to obtain these constraints.

In this post on Simplex tableau, they suggested using `ccall` and mentioned the following code: `ccall((:CPXbinvarow,CPLEX.libcplex),Cint,(Ptr{Void},Ptr{Void},Cint,Ptr{Cdouble}),ci.env.ptr, ci.lp, j,row)`

I tried using this code, but the row results are only 1 or 0.

To better understand the result, I started with a small problem. Here’s the code:

``````# Create a model with the CPLEX solver

model = Model(CPLEX.Optimizer)

# Define variables as continuous (for the linear relaxation)

@variable(model, x1 >= 0)

@variable(model, x2 >= 0)

# Define constraints

@constraint(model, x1 + x2 <= 7)

@constraint(model, 2*x1 <= 11)

@constraint(model, 2*x2 <= 7)

# Define the objective function

@objective(model, Max, x1 + 2*x2)
``````

I attempted to retrieve the tableau like this:

``````# Solve the model
optimize!(model)

# Retrieve the number of constraints
num_const = MOI.get(model, MOI.NumberOfConstraints{MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}}())

# Retrieve the number of variables plus slack variables
num_vars = MOI.get(model, MOI.NumberOfVariables()) + num_const

# Initialize the tableau
tableau = zeros(num_const, num_vars)

for j in 0:num_const-1
tableau[j+1,:] = getrow(j, model)
end
``````

The `getrow` function is defined as follows:

``````function getrow(j, model)
ci = backend(model).optimizer.model
num_vars = MOI.get(model, MOI.NumberOfVariables()) + MOI.get(model, MOI.NumberOfConstraints{MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}}())
row = zeros(num_vars)
status = ccall((:CPXbinvarow, CPLEX.libcplex), Cint,
(Ptr{Nothing}, Ptr{Nothing}, Cint, Ptr{Cdouble}),
ci.env.ptr, ci.lp, j, row)
if status != 0
error("CPXbinvarow failed, return code \$status.")
end
return row
end
``````

In a video I watched, I learned that the optimal tableau should look like this:

Did you want `CPXbinvrow` instead? Here’s how I would call it:

``````using JuMP, CPLEX
model = direct_model(CPLEX.Optimizer())
@variable(model, x1 >= 0)
@variable(model, x2 >= 0)
@constraint(model, x1 + x2 <= 7)
@constraint(model, 2*x1 <= 11)
@constraint(model, 2*x2 <= 7)
@objective(model, Max, x1 + 2*x2)
optimize!(model)
num_const = num_constraints(model, AffExpr, MOI.LessThan{Float64})
num_vars = num_variables(model) + num_const
tableau = zeros(num_const, num_vars)
cpx = backend(model)
data = zeros(num_vars)
for j in 1:num_const
status = CPLEX.CPXbinvrow(cpx.env, cpx.lp, Cint(j - 1), data)
@assert status == 0
tableau[j, :] .= data
end
``````

Here are the docs: IBM Documentation

If I understood correctly, `CPXbinvrow` is used to gather the inverse basis, while `CPXbinvarow` is used for the tableau. Could you please confirm if my understanding is accurate? Thank you very much for your quick response as always, @odow.

I wanted to update you and let you know that I have figured out what was causing the issue. Thanks to @odow for clarifying the functions. As I initially mentioned, I’ve been using the `CPXbinvarow` to gather rows from the tableau. The error occurred because I hadn’t incorporated the slack variables into the model. Once I added these slack variables, the results from `CPXbinvarow` matched up correctly.

1 Like