From 940dcedce94c780359157cf954ae09b64e589e79 Mon Sep 17 00:00:00 2001 From: Vitor Nesello Date: Tue, 14 May 2019 17:33:13 +0200 Subject: [PATCH 1/3] initial feature commit with maximization model --- test/models/gap.jl | 25 +++++++++++++++++++++++++ test/runtests.jl | 8 ++++++++ 2 files changed, 33 insertions(+) diff --git a/test/models/gap.jl b/test/models/gap.jl index fbed22f8b..c36b18cd0 100644 --- a/test/models/gap.jl +++ b/test/models/gap.jl @@ -34,3 +34,28 @@ function gap_with_penalties(data) return gap end + +function maximization_gap(data) + gap = BlockModel(with_optimizer(Coluna.Optimizer,# #params = params, + master_factory = with_optimizer(GLPK.Optimizer), + pricing_factory = with_optimizer(GLPK.Optimizer)), + bridge_constraints=false + ) + + rewards = data.cost + capacities = data.capacity + + @axis(M, data.machines) + + @variable(gap, x[m in M, j in data.jobs], Bin) + @constraint(gap, cov[j in data.jobs], sum(x[m,j] for m in M) <= 1) + + @constraint(gap, knp[m in M], + sum(data.weight[j,m]*x[m,j] for j in data.jobs) <= capacities[m]) + + @objective(gap, Max, sum(rewards[j,m]*x[m,j] for m in M, j in data.jobs)) + + @dantzig_wolfe_decomposition(gap, dec, M) + + return gap +end diff --git a/test/runtests.jl b/test/runtests.jl index 7f8e736f4..c406cabcc 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -35,6 +35,14 @@ end #@show JuMP.objective_value(problem) end +@testset "gap with maximisation objective function" begin + # JuMP.objective_value(problem) = 416.4 + problem = maximization_gap(data_gap) + println("\e[1;42m GAP maximization objective function \e[00m") + JuMP.optimize!(problem) + #@show JuMP.objective_value(problem) +end + # model, x = sgap_5_100() # JuMP.optimize!(model) From 35e56aef6aed4c9a798826928abfdace333c8647 Mon Sep 17 00:00:00 2001 From: Vitor Nesello Date: Wed, 15 May 2019 20:13:09 +0200 Subject: [PATCH 2/3] Maximization bug fixes (#72) * art_var cost and coeff depending on objective sense * set correct objective sense in decomposition * add function contrib_improves mlp to decide if a columns has an improving contribution on master depending on objective sense * compute reduced cost depending on objective sense * update to_be_pruned * revert cost change --- src/decomposition.jl | 21 ++++++++++++++------- src/formulation.jl | 6 +++++- src/node.jl | 1 + src/solsandbounds.jl | 1 + src/solvers/colgen.jl | 13 ++++++++----- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/decomposition.jl b/src/decomposition.jl index 4acad0d84..d22e82de2 100644 --- a/src/decomposition.jl +++ b/src/decomposition.jl @@ -1,12 +1,13 @@ set_loc_art_var(f::Formulation, constr_id::ConstrId) = setvar!( - f, string("local_art_", constr_id), MastArtVar; cost = 10.0, + f, string("local_art_", constr_id), MastArtVar; + cost = (getobjsense(f) == MinSense ? 10.0 : -10.0), lb = 0.0, ub = Inf, kind = Continuous, sense = Positive ) set_glob_art_var(f::Formulation, is_pos::Bool) = setvar!( f, string("global_", (is_pos ? "pos" : "neg"), "_art_var"), - MastArtVar; cost = 100000.0, lb = 0.0, ub = Inf, - kind = Continuous, sense = Positive + MastArtVar; cost = (getobjsense(f) == MinSense ? 100000.0 : -100000.0), + lb = 0.0, ub = Inf, kind = Continuous, sense = Positive ) function initialize_local_art_vars(master::Formulation, @@ -15,11 +16,15 @@ function initialize_local_art_vars(master::Formulation, for (constr_id, constr) in constrs_in_form v = setvar!( master, string("local_art_of_", getname(constr)), - MastArtVar; cost = 10000.0, lb = 0.0, ub = Inf, -# cost = getincval(constr), lb = 0.0, ub = Inf, - kind = Continuous, sense = Positive + MastArtVar; + cost = (getobjsense(master) == MinSense ? 10000.0 : -10000.0), + lb = 0.0, ub = Inf, kind = Continuous, sense = Positive ) - matrix[constr_id, getid(v)] = 1.0 + if setsense(getcurdata(constr)) == Greater + matrix[constr_id, getid(v)] = 1.0 + elseif setsense(getcurdata(constr)) == Less + matrix[constr_id, getid(v)] = -1.0 + end end return end @@ -181,6 +186,7 @@ function reformulate!(prob::Problem, annotations::Annotations, # Create master formulation master_form = Formulation{DwMaster}( prob.form_counter; parent_formulation = reformulation, + obj_sense = getobjsense(get_original_formulation(prob)), moi_optimizer = prob.master_factory() ) setmaster!(reformulation, master_form) @@ -198,6 +204,7 @@ function reformulate!(prob::Problem, annotations::Annotations, elseif BD.getformulation(annotation) == BD.DwPricingSp f = Formulation{DwSp}( prob.form_counter; parent_formulation = master_form, + obj_sense = getobjsense(master_form), moi_optimizer = prob.pricing_factory() ) formulations[BD.getid(annotation)] = f diff --git a/src/formulation.jl b/src/formulation.jl index 860f181b6..2f6d11a5e 100644 --- a/src/formulation.jl +++ b/src/formulation.jl @@ -591,7 +591,11 @@ function computereducedcost(form::Formulation, var_id, dual_sol::DualSolution) for (constr_id, dual_val) in getsol(dual_sol) coeff = coefficient_matrix[constr_id, var_id] - rc = rc - dual_val * coeff + if getobjsense(form) == MinSense + rc = rc - dual_val * coeff + else + rc = rc + dual_val * coeff + end end return rc diff --git a/src/node.jl b/src/node.jl index 948e57263..aa9e9e4ab 100644 --- a/src/node.jl +++ b/src/node.jl @@ -84,6 +84,7 @@ get_solver_record!(n::Node, S::Type{<:AbstractSolver}) = n.solver_records[S] function to_be_pruned(n::Node) # How to determine if a node should be pruned?? By the lp_gap? lp_gap(n.incumbents) <= 0.0000001 && return true + ip_gap(n.incumbents) <= 0.0000001 && return true return false end diff --git a/src/solsandbounds.jl b/src/solsandbounds.jl index 191234612..ffb037be8 100644 --- a/src/solsandbounds.jl +++ b/src/solsandbounds.jl @@ -87,6 +87,7 @@ Base.:+(b1::B, b2::B) where {B <: AbstractBound} = B(float(b1) + float(b2)) Base.:/(b1::B, b2::B) where {B <: AbstractBound} = B(float(b1) / float(b2)) Base.isless(b::AbstractBound, r::Real) = b.value < r +Base.isless(r::Real, b::AbstractBound) = r < b.value Base.isless(b1::B, b2::B) where {B <: AbstractBound} = float(b1) < float(b2) abstract type AbstractSolution end diff --git a/src/solvers/colgen.jl b/src/solvers/colgen.jl index ac0deefee..0755358f3 100644 --- a/src/solvers/colgen.jl +++ b/src/solvers/colgen.jl @@ -57,7 +57,7 @@ function insert_cols_in_master!(master_form::Formulation, nb_of_gen_col = 0 for sp_sol in sp_sols - if getvalue(sp_sol) < -0.0001 # TODO use tolerance + if contrib_improves_mlp(getbound(sp_sol)) nb_of_gen_col += 1 ref = getvarcounter(master_form) + 1 name = string("MC", sp_uid, "_", ref) @@ -93,16 +93,19 @@ function insert_cols_in_master!(master_form::Formulation, return nb_of_gen_col end +contrib_improves_mlp(sp_primal_bound::PrimalBound{MinSense}) = (sp_primal_bound < 0.0 - 1e-8) +contrib_improves_mlp(sp_primal_bound::PrimalBound{MaxSense}) = (sp_primal_bound > 0.0 + 1e-8) + function compute_pricing_db_contrib(sp_form::Formulation, - sp_sol_value::PrimalBound{S}, + sp_sol_primal_bound::PrimalBound{S}, sp_lb::Float64, sp_ub::Float64) where {S} # Since convexity constraints are not automated and there is no stab # the pricing_dual_bound_contrib is just the reduced cost * multiplicty - if sp_sol_value <= 0 - contrib = sp_sol_value * sp_ub + if contrib_improves_mlp(sp_sol_primal_bound) + contrib = sp_sol_primal_bound * sp_ub else - contrib = sp_sol_value * sp_lb + contrib = sp_sol_primal_bound * sp_lb end return contrib end From 4f329aa0b62bdd3af15a6e70caf0f63b1b17dd6e Mon Sep 17 00:00:00 2001 From: Vitor Nesello Date: Thu, 16 May 2019 20:44:11 +0200 Subject: [PATCH 3/3] revert setsense function --- src/decomposition.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/decomposition.jl b/src/decomposition.jl index 374196efb..45989968e 100644 --- a/src/decomposition.jl +++ b/src/decomposition.jl @@ -20,9 +20,9 @@ function initialize_local_art_vars(master::Formulation, cost = (getobjsense(master) == MinSense ? 10000.0 : -10000.0), lb = 0.0, ub = Inf, kind = Continuous, sense = Positive ) - if setsense(getcurdata(constr)) == Greater + if getsense(getcurdata(constr)) == Greater matrix[constr_id, getid(v)] = 1.0 - elseif setsense(getcurdata(constr)) == Less + elseif getsense(getcurdata(constr)) == Less matrix[constr_id, getid(v)] = -1.0 end end