diff --git a/src/Cuts/tableau/gmi.jl b/src/Cuts/tableau/gmi.jl index c83d520..506ad2e 100644 --- a/src/Cuts/tableau/gmi.jl +++ b/src/Cuts/tableau/gmi.jl @@ -85,7 +85,7 @@ function collect_gmi( # Optimize standard form optimize!(model_s) stats_time_solve += solve_time(model_s) - obj = objective_value(model_s) + data_s.obj_offset + obj = objective_value(model_s) if round == 1 # Assert standard form problem has same value as original diff --git a/src/Cuts/tableau/gmi_dual.jl b/src/Cuts/tableau/gmi_dual.jl index 181de39..a46b0d8 100644 --- a/src/Cuts/tableau/gmi_dual.jl +++ b/src/Cuts/tableau/gmi_dual.jl @@ -87,7 +87,7 @@ function collect_gmi_dual( @info "Optimizing standard model..." optimize!(model_s) if round == 1 - obj = objective_value(model_s) + data_s.obj_offset + obj = objective_value(model_s) push!(stats_obj, obj) push!(stats_gap, gap(obj)) push!(stats_ncuts, 0) @@ -130,25 +130,31 @@ function collect_gmi_dual( end @timeit "Add GMI cuts to original model" begin - # Convert cuts - cuts = backwards(transforms, cuts_s) + @timeit "Convert to original form" begin + cuts = backwards(transforms, cuts_s) + end - # Update data structs - bv = repeat([basis], length(selected_rows)) - if round == 1 - all_cuts = cuts - all_cuts_bases = bv - all_cuts_rows = selected_rows - else - all_cuts.lhs = [all_cuts.lhs; cuts.lhs] - all_cuts.lb = [all_cuts.lb; cuts.lb] - all_cuts.ub = [all_cuts.ub; cuts.ub] - all_cuts_bases = [all_cuts_bases; bv] - all_cuts_rows = [all_cuts_rows; selected_rows] + @timeit "Prepare bv" begin + bv = repeat([basis], length(selected_rows)) + end + + @timeit "Append matrices" begin + if round == 1 + all_cuts = cuts + all_cuts_bases = bv + all_cuts_rows = selected_rows + else + all_cuts.lhs = [all_cuts.lhs; cuts.lhs] + all_cuts.lb = [all_cuts.lb; cuts.lb] + all_cuts.ub = [all_cuts.ub; cuts.ub] + all_cuts_bases = [all_cuts_bases; bv] + all_cuts_rows = [all_cuts_rows; selected_rows] + end end - # Add to model - constrs, gmi_exps = add_constraint_set_dual_v2(model, all_cuts) + @timeit "Add to model" begin + constrs, gmi_exps = add_constraint_set_dual_v2(model, all_cuts) + end end @timeit "Optimize original model" begin @@ -322,22 +328,28 @@ function add_constraint_set_dual_v2(model::JuMP.Model, cs::ConstraintSet) c = nothing gmi_exp = nothing gmi_exp2 = nothing - expr = @expression(model, sum(cs.lhs[i, j] * vars[j] for j = 1:ncols)) - if isinf(cs.ub[i]) - c = @constraint(model, cs.lb[i] <= expr) - gmi_exp = cs.lb[i] - expr - elseif isinf(cs.lb[i]) - c = @constraint(model, expr <= cs.ub[i]) - gmi_exp = expr - cs.ub[i] - else - c = @constraint(model, cs.lb[i] <= expr <= cs.ub[i]) - gmi_exp = cs.lb[i] - expr - gmi_exp2 = expr - cs.ub[i] + @timeit "Build expr" begin + expr = @expression(model, sum(cs.lhs[i, j] * vars[j] for j = 1:ncols)) + end + @timeit "Add constraints" begin + if isinf(cs.ub[i]) + c = @constraint(model, cs.lb[i] <= expr) + gmi_exp = cs.lb[i] - expr + elseif isinf(cs.lb[i]) + c = @constraint(model, expr <= cs.ub[i]) + gmi_exp = expr - cs.ub[i] + else + c = @constraint(model, cs.lb[i] <= expr <= cs.ub[i]) + gmi_exp = cs.lb[i] - expr + gmi_exp2 = expr - cs.ub[i] + end end - push!(constrs, c) - push!(gmi_exps, gmi_exp) - if !isnothing(gmi_exp2) - push!(gmi_exps, gmi_exp2) + @timeit "Update structs" begin + push!(constrs, c) + push!(gmi_exps, gmi_exp) + if !isnothing(gmi_exp2) + push!(gmi_exps, gmi_exp2) + end end end return constrs, gmi_exps diff --git a/src/Cuts/tableau/moi.jl b/src/Cuts/tableau/moi.jl index 49d6455..83c0b9d 100644 --- a/src/Cuts/tableau/moi.jl +++ b/src/Cuts/tableau/moi.jl @@ -9,6 +9,8 @@ function ProblemData(model::Model)::ProblemData # Objective function obj = objective_function(model) + obj_offset = obj.constant + obj_sense = objective_sense(model) obj = [v ∈ keys(obj.terms) ? obj.terms[v] : 0.0 for v in vars] # Variable types, lower bounds and upper bounds @@ -86,8 +88,9 @@ function ProblemData(model::Model)::ProblemData @assert length(constr_ub) == m return ProblemData( - obj_offset = 0.0; obj, + obj_offset, + obj_sense, constr_lb, constr_ub, constr_lhs, @@ -102,6 +105,7 @@ function to_model(data::ProblemData, tol = 1e-6)::Model model = Model() # Variables + obj_expr = AffExpr(data.obj_offset) nvars = length(data.obj) @variable(model, x[1:nvars]) for i = 1:nvars @@ -117,8 +121,9 @@ function to_model(data::ProblemData, tol = 1e-6)::Model if isfinite(data.var_ub[i]) set_upper_bound(x[i], data.var_ub[i]) end - set_objective_coefficient(model, x[i], data.obj[i]) + add_to_expression!(obj_expr, x[i], data.obj[i]) end + @objective(model, data.obj_sense, obj_expr) # Constraints lhs = data.constr_lhs * x diff --git a/src/Cuts/tableau/structs.jl b/src/Cuts/tableau/structs.jl index cbdab11..fc1fb75 100644 --- a/src/Cuts/tableau/structs.jl +++ b/src/Cuts/tableau/structs.jl @@ -7,6 +7,7 @@ using SparseArrays Base.@kwdef mutable struct ProblemData obj::Vector{Float64} obj_offset::Float64 + obj_sense constr_lb::Vector{Float64} constr_ub::Vector{Float64} constr_lhs::SparseMatrixCSC