Relaxation of MIP to LP, getdual, CPLEX

Hi guys.
I’ve been reading this forum and the previous one (on Google) and I can’t seem to find an answer (although there are close examples) to my problem.

It is about getting dual values out of an MIP. The standard way I know is solving the MIP, relax the problem and fix all the integer variables to their results from the MIP. Then solve the resulting LP and get the duals.

I’ve been trying to do this through the following small example:

using JuMP
using CPLEX

model = Model(solver=CplexSolver())

@variable(model, x >= 0)
@variable(model, y, Bin)

@constraint(model, cop, x + y>= 1.33)
@constraint(model, cop2, x <= 0.5 )
@objective(model, Min, x+2y)

println(model)

status = solve(model)

println(getobjectivevalue(model))
println("x: ", getvalue(x))
println("y: ", getvalue(y))
println("dual: ", getdual(cop))

println(“============================”)

setcategory(y, :Cont)
println(model)

status = solve(model)

println(getobjectivevalue(model))
println("x: ", getvalue(x))
println("y: ", getvalue(y))
println("dual: ", getdual(cop))

As expected, the first attempt to print the dual throws a warning, because the dual is not available and getdual(cop) returns a NaN. The problem is that the same happens on the second attempt, even when the model looks like:

Min x + 2 y
Subject to
x + y ≥ 1.33
x ≤ 0.5
x ≥ 0
0 ≤ y ≤ 1

I have tried using the following, with no luck.

status = solve(model, relaxation=true)

CPLEX throws a

CPLEX Error 1017: Not available for mixed-integer problems

even when no duals are requested, only because either

relaxation=true

or

setcategory(y, :Cont)

are on. I haven’t tried other solvers at this point. For the sake of performance and conciseness I’m trying to avoid rebuilding the whole model with only continuous variables.

Anybody knows how the query to CPLEX is being done? Maybe there is a header or something that stays fixed to command mipopt instead of optimize. Well, any advise is very welcome.

Cheers

It’s possible that there is some bad state being maintained somewhere in CPLEX.jl (PRs accepted). As a workaround, you can call setsolver(model, CplexSolver()) to force JuMP to throw out the in-memory model and build a new one from scratch.

It’s actually a little complicated. CPLEX maintains a problem type that is independent of the variable types.

https://github.com/JuliaOpt/CPLEX.jl/issues/110

I am facing the same Issue when using Gurobi as solver. When asking for JuMP.hasduals(fixed_model) it will always return false.
I already tried using relax_integrality() as well with the same result. The optimization as LP looks fine and prints out the dual variables but won’t return the dual.

fixed_model = get_fixed_model(model)
JuMP.optimize!(fixed_model)

function get_fixed_model(model::Model)
    solution = Dict(
        v => value(v) for v in all_variables(model)
    )
    for v in all_variables(model)
        if is_binary(v)
            unset_binary(v)
            fix(v, solution[v]; force = true)
        elseif is_integer(v)
            unset_integer(v)
            fix(v, solution[v]; force = true)
        end
    end
    new_model = copy(model)
    set_optimizer(new_model, Gurobi.Optimizer)
    #set_silent(new_model)
    return new_model
end
1 Like

Please start a new post, rather than posting below a very old one.

You might be looking for relax_integrality:

https://jump.dev/JuMP.jl/dev/manual/models/#Relax-integrality