JuMPSolver: Collect variable basis status

master
Alinson S. Xavier 4 years ago
parent 65a78ebdfe
commit 6262751fdc

@ -25,6 +25,7 @@ mutable struct JuMPSolverData
cb_data::Any cb_data::Any
var_lb_constr::Dict{MOI.VariableIndex,ConstraintRef} var_lb_constr::Dict{MOI.VariableIndex,ConstraintRef}
var_ub_constr::Dict{MOI.VariableIndex,ConstraintRef} var_ub_constr::Dict{MOI.VariableIndex,ConstraintRef}
basis_status::Dict{ConstraintRef,MOI.BasisStatusCode}
end end
@ -59,6 +60,8 @@ function _update_solution!(data::JuMPSolverData)
if has_duals(data.model) if has_duals(data.model)
data.reduced_costs = [] data.reduced_costs = []
data.basis_status = Dict()
for var in vars for var in vars
rc = 0.0 rc = 0.0
if has_upper_bound(var) if has_upper_bound(var)
@ -74,12 +77,25 @@ function _update_solution!(data::JuMPSolverData)
push!(data.reduced_costs, rc) push!(data.reduced_costs, rc)
end end
try
data.sensitivity_report = lp_sensitivity_report(data.model)
catch
# solver does not support sensitivity analysis; ignore
end
data.dual_values = Dict() data.dual_values = Dict()
for (ftype, stype) in JuMP.list_of_constraint_types(data.model) for (ftype, stype) in JuMP.list_of_constraint_types(data.model)
for constr in JuMP.all_constraints(data.model, ftype, stype) for constr in JuMP.all_constraints(data.model, ftype, stype)
# FIXME: Remove negative sign # Dual values (FIXME: Remove negative sign)
data.dual_values[constr] = -JuMP.dual(constr) data.dual_values[constr] = -JuMP.dual(constr)
# Basis status
if data.sensitivity_report !== nothing
data.basis_status[constr] =
MOI.get(data.model, MOI.ConstraintBasisStatus(), constr)
end
# Build map between variables and bound constraints
if ftype == VariableRef if ftype == VariableRef
var = MOI.get(data.model, MOI.ConstraintFunction(), constr).variable var = MOI.get(data.model, MOI.ConstraintFunction(), constr).variable
if stype == MOI.GreaterThan{Float64} if stype == MOI.GreaterThan{Float64}
@ -93,15 +109,11 @@ function _update_solution!(data::JuMPSolverData)
end end
end end
try
data.sensitivity_report = lp_sensitivity_report(data.model)
catch
# solver does not support sensitivity analysis; ignore
end
else else
data.reduced_costs = [] data.reduced_costs = []
data.dual_values = Dict() data.dual_values = Dict()
data.sensitivity_report = nothing data.sensitivity_report = nothing
data.basis_status = Dict()
data.var_lb_constr = Dict() data.var_lb_constr = Dict()
data.var_ub_constr = Dict() data.var_ub_constr = Dict()
end end
@ -355,6 +367,7 @@ function get_variables(data::JuMPSolverData; with_static::Bool)
sa_obj_down, sa_obj_up = nothing, nothing sa_obj_down, sa_obj_up = nothing, nothing
sa_lb_down, sa_lb_up = nothing, nothing sa_lb_down, sa_lb_up = nothing, nothing
sa_ub_down, sa_ub_up = nothing, nothing sa_ub_down, sa_ub_up = nothing, nothing
basis_status = nothing
values, rc = nothing, nothing values, rc = nothing, nothing
# Variable names # Variable names
@ -384,13 +397,16 @@ function get_variables(data::JuMPSolverData; with_static::Bool)
types = [JuMP.is_binary(v) ? "B" : JuMP.is_integer(v) ? "I" : "C" for v in vars] types = [JuMP.is_binary(v) ? "B" : JuMP.is_integer(v) ? "I" : "C" for v in vars]
end end
# Sensitivity analysis # Sensitivity analysis and basis status
if data.sensitivity_report !== nothing if data.sensitivity_report !== nothing
sa_obj_down, sa_obj_up = Float64[], Float64[] sa_obj_down, sa_obj_up = Float64[], Float64[]
sa_lb_down, sa_lb_up = Float64[], Float64[] sa_lb_down, sa_lb_up = Float64[], Float64[]
sa_ub_down, sa_ub_up = Float64[], Float64[] sa_ub_down, sa_ub_up = Float64[], Float64[]
basis_status = []
for (i, v) in enumerate(vars) for (i, v) in enumerate(vars)
basis_status_v = "B"
# Objective function # Objective function
(delta_down, delta_up) = data.sensitivity_report[v] (delta_down, delta_up) = data.sensitivity_report[v]
push!(sa_obj_down, delta_down + obj_coeffs[i]) push!(sa_obj_down, delta_down + obj_coeffs[i])
@ -402,6 +418,9 @@ function get_variables(data::JuMPSolverData; with_static::Bool)
(delta_down, delta_up) = data.sensitivity_report[constr] (delta_down, delta_up) = data.sensitivity_report[constr]
push!(sa_lb_down, lower_bound(v) + delta_down) push!(sa_lb_down, lower_bound(v) + delta_down)
push!(sa_lb_up, lower_bound(v) + delta_up) push!(sa_lb_up, lower_bound(v) + delta_up)
if data.basis_status[constr] == MOI.NONBASIC
basis_status_v = "L"
end
else else
push!(sa_lb_down, -Inf) push!(sa_lb_down, -Inf)
push!(sa_lb_up, -Inf) push!(sa_lb_up, -Inf)
@ -413,10 +432,15 @@ function get_variables(data::JuMPSolverData; with_static::Bool)
(delta_down, delta_up) = data.sensitivity_report[constr] (delta_down, delta_up) = data.sensitivity_report[constr]
push!(sa_ub_down, upper_bound(v) + delta_down) push!(sa_ub_down, upper_bound(v) + delta_down)
push!(sa_ub_up, upper_bound(v) + delta_up) push!(sa_ub_up, upper_bound(v) + delta_up)
if data.basis_status[constr] == MOI.NONBASIC
basis_status_v = "U"
end
else else
push!(sa_ub_down, Inf) push!(sa_ub_down, Inf)
push!(sa_ub_up, Inf) push!(sa_ub_up, Inf)
end end
push!(basis_status, basis_status_v)
end end
end end
@ -436,6 +460,7 @@ function get_variables(data::JuMPSolverData; with_static::Bool)
sa_lb_up = sa_lb_up, sa_lb_up = sa_lb_up,
sa_ub_down = sa_ub_down, sa_ub_down = sa_ub_down,
sa_ub_up = sa_ub_up, sa_ub_up = sa_ub_up,
basis_status = to_str_array(basis_status),
) )
return vf return vf
end end
@ -542,6 +567,7 @@ function __init_JuMPSolver__()
nothing, # cb_data nothing, # cb_data
Dict(), # var_lb_constr Dict(), # var_lb_constr
Dict(), # var_ub_constr Dict(), # var_ub_constr
Dict(), # basis_status
) )
end end
@ -614,7 +640,6 @@ function __init_JuMPSolver__()
function get_variable_attrs(self) function get_variable_attrs(self)
attrs = [ attrs = [
"names", "names",
# "basis_status",
"categories", "categories",
"lower_bounds", "lower_bounds",
"obj_coeffs", "obj_coeffs",
@ -628,6 +653,7 @@ function __init_JuMPSolver__()
append!( append!(
attrs, attrs,
[ [
"basis_status",
"sa_obj_down", "sa_obj_down",
"sa_obj_up", "sa_obj_up",
"sa_lb_down", "sa_lb_down",

Loading…
Cancel
Save