I have a modular optimisation problem that can be LP or MIP depending on the setting. To get the shadow price I query via JuMP.has_duals(model) whether I can receive the shadow price with the corresponding JuMP (JuMP.shadow_price) function.
If this is not the case, I have found the possibility to relax the problem via various forum entries.
Unfortunately, I get this error with the following shadow price query:
However, it appears to me that there is a dual result…
I have already tried various solutions, including using relax_integrality(). Nevertheless, the error message remains the same. I’m using Gurobi as a Solver for both problems.
Here is the corresponding source code to relax the MIP:
"""
get_fixed_model(model::Model)
takes the MIP Problem and fixes all binary and integer variables to the solutions and returns a copy of the 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)
return new_model
end
"""
get_shadow_price_mip(cep::OptModel, config::OptConfig, scale::Dict)
creates a fixed copy of the model, runs an optimization and calculates the shadow prices from this.
"""
function get_shadow_price_mip(model::Model)
fixed_model = get_fixed_model(model)
#undo = relax_integrality(fixed_model);
JuMP.optimize!(fixed_model)
return get_shadow_price(fixed_model)
end
Here is a minimal example which shows the described behaviour. I hope this will help!
Thanks in advance
using JuMP
using Gurobi
# create dummy model
model = Model(Gurobi.Optimizer)
# setup variables, constraints and objective
@variable(model, x)
@variable(model, a, Bin)
@constraint(model, reference, a * 2 * x >= 1)
@objective(model, Min, x)
# optimize
JuMP.optimize!(model)
JuMP.has_duals(model) # should return false
# new fixed model
#### test with fixed binaries
fixed_model = get_fixed_model(model)
#### alternative test with relax_integrality
#=
fixed_model = copy(model)
set_optimizer(fixed_model, Gurobi.Optimizer)
undo = relax_integrality(fixed_model);
set_optimizer_attributes(fixed_model, "NonConvex" => 2)
=#
JuMP.optimize!(fixed_model)
JuMP.has_duals(fixed_model) # returns false but expected to return true
JuMP.shadow_price(reference) # throws an error
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)
return new_model
end