Skip to content

Commit

Permalink
Merge 9e85194 into 70faf97
Browse files Browse the repository at this point in the history
  • Loading branch information
guimarqu authored Feb 3, 2021
2 parents 70faf97 + 9e85194 commit c89bb81
Show file tree
Hide file tree
Showing 28 changed files with 213 additions and 212 deletions.
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ version = "0.3.4"
[deps]
BlockDecomposition = "6cde8614-403a-11e9-12f1-c10d0f0caca0"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
DynamicSparseArrays = "8086fd22-9a0c-46a5-a6c8-6e24676501fe"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
Expand Down
5 changes: 3 additions & 2 deletions src/Algorithm/basic/cutcallback.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ end

struct RobustCutCallbackContext
form::Formulation
env::Env
proj_sol::PrimalSolution # ordered non zero but O(log^2(n)) lookup time
proj_sol_dict::Dict{VarId, Float64} # O(1) lookup time
viol_vals::Vector{Float64}
Expand All @@ -30,7 +31,7 @@ function get_storages_usage(algo::CutCallbacks, form::Formulation{MathProg.Abstr
return [(form, MasterCutsStoragePair, READ_AND_WRITE)]
end

function run!(algo::CutCallbacks, data::ModelData, input::CutCallbacksInput)
function run!(algo::CutCallbacks, env::Env, data::ModelData, input::CutCallbacksInput)
form = getmodel(data)
nb_cuts = 0
robust_generators = get_robust_constr_generators(form)
Expand All @@ -39,7 +40,7 @@ function run!(algo::CutCallbacks, data::ModelData, input::CutCallbacksInput)

projsol1 = proj_cols_on_rep(input.primalsol, form)
projsol2 = Dict{VarId, Float64}(varid => val for (varid, val) in projsol1)
context = RobustCutCallbackContext(form, projsol1, projsol2, Float64[])
context = RobustCutCallbackContext(form, env, projsol1, projsol2, Float64[])

for constrgen in robust_generators
if constrgen.kind == Facultative && algo.call_robust_facultative
Expand Down
6 changes: 3 additions & 3 deletions src/Algorithm/basic/solveipform.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function check_if_optimizer_supports_ip(optimizer::MoiOptimizer)
end
check_if_optimizer_supports_ip(optimizer::UserOptimizer) = true

function run!(algo::SolveIpForm, data::ModelData, input::OptimizationInput)::OptimizationOutput
function run!(algo::SolveIpForm, env::Env, data::ModelData, input::OptimizationInput)::OptimizationOutput
form = getmodel(data)

result = OptimizationState(
Expand Down Expand Up @@ -100,8 +100,8 @@ function run!(algo::SolveIpForm, data::ModelData, input::OptimizationInput)::Opt
return OptimizationOutput(result)
end

run!(algo::SolveIpForm, data::ReformData, input::OptimizationInput) =
run!(algo, getmasterdata(data), input)
run!(algo::SolveIpForm, env::Env, data::ReformData, input::OptimizationInput) =
run!(algo, env, getmasterdata(data), input)

function termination_status!(result::OptimizationState, optimizer::MoiOptimizer)
terminationstatus = MOI.get(getinner(optimizer), MOI.TerminationStatus())
Expand Down
2 changes: 1 addition & 1 deletion src/Algorithm/basic/solvelpform.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function optimize_lp_form!(
return
end

function run!(algo::SolveLpForm, data::ModelData, input::OptimizationInput)::OptimizationOutput
function run!(algo::SolveLpForm, env::Env, data::ModelData, input::OptimizationInput)::OptimizationOutput
form = getmodel(data)
result = OptimizationState(form)

Expand Down
38 changes: 18 additions & 20 deletions src/Algorithm/benders.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ function get_storages_usage(algo::BendersCutGeneration, reform::Reformulation)
for (id, spform) in get_benders_sep_sps(reform)
push!(storages_usage, (spform, StaticVarConstrStoragePair, READ_ONLY))
end

return storages_usage
end

Expand Down Expand Up @@ -51,14 +50,14 @@ end

getoptstate(data::BendersCutGenRuntimeData) = data.optstate

function run!(algo::BendersCutGeneration, rfdata::ReformData, input::OptimizationInput)::OptimizationOutput

function run!(
algo::BendersCutGeneration, env::Env, rfdata::ReformData, input::OptimizationInput
)::OptimizationOutput
reform = getreform(rfdata)
relax_integrality!(getmaster(reform))
bndata = BendersCutGenRuntimeData(reform, getoptstate(input))
@logmsg LogLevel(-1) "Run BendersCutGeneration."
Base.@time bend_rec = bend_cutting_plane_main_loop!(algo, bndata, reform)

Base.@time bend_rec = bend_cutting_plane_main_loop!(algo, env, bndata, reform)
return OptimizationOutput(bndata.optstate)
end

Expand Down Expand Up @@ -127,7 +126,6 @@ function update_benders_sp_problem!(
setcurcost!(spform, var, rc)
end
end

return false
end

Expand Down Expand Up @@ -224,7 +222,7 @@ function compute_benders_sp_lagrangian_bound_contrib(
end

function solve_sp_to_gencut!(
algo::BendersCutGeneration, algdata::BendersCutGenRuntimeData,
algo::BendersCutGeneration, env::Env, algdata::BendersCutGenRuntimeData,
masterform::Formulation, spform::Formulation,
master_primal_sol::PrimalSolution, master_dual_sol::DualSolution,
up_to_phase::FormulationPhase
Expand Down Expand Up @@ -268,7 +266,7 @@ function solve_sp_to_gencut!(
# Solve sub-problem and insert generated cuts in master
# @logmsg LogLevel(-3) "optimizing benders_sp prob"
TO.@timeit Coluna._to "Bender Sep SubProblem" begin
optstate = run!(SolveLpForm(get_dual_solution = true), ModelData(spform), OptimizationInput(OptimizationState(spform)))
optstate = run!(SolveLpForm(get_dual_solution = true), env, ModelData(spform), OptimizationInput(OptimizationState(spform)))
end

optresult = getoptstate(optstate)
Expand Down Expand Up @@ -350,7 +348,7 @@ end


function solve_sps_to_gencuts!(
algo::BendersCutGeneration, algdata::BendersCutGenRuntimeData,
algo::BendersCutGeneration, env::Env, algdata::BendersCutGenRuntimeData,
reform::Reformulation, master_primalsol::PrimalSolution,
master_dualsol::DualSolution, up_to_phase::FormulationPhase
)
Expand All @@ -371,7 +369,7 @@ function solve_sps_to_gencuts!(
for (spuid, spform) in sps
recorded_sp_dual_solution_ids[spuid] = Vector{ConstrId}()
gen_status, spsol_relaxed, recorded_dual_solution_ids, benders_sp_primal_bound_contrib, benders_sp_lagrangian_bound_contrib = solve_sp_to_gencut!(
algo, algdata, masterform, spform,
algo, env, algdata, masterform, spform,
master_primalsol, master_dualsol,
up_to_phase
)
Expand Down Expand Up @@ -419,15 +417,15 @@ function update_lagrangian_pb!(algdata::BendersCutGenRuntimeData, reform::Reform
return lagran_bnd
end

function solve_relaxed_master!(master::Formulation)
function solve_relaxed_master!(master::Formulation, env::Env)
elapsed_time = @elapsed begin
optresult = TO.@timeit Coluna._to "relaxed master" run!(SolveLpForm(get_dual_solution = true), ModelData(master), OptimizationInput(OptimizationState(master)))
optresult = TO.@timeit Coluna._to "relaxed master" run!(SolveLpForm(get_dual_solution = true), env, ModelData(master), OptimizationInput(OptimizationState(master)))
end
return optresult, elapsed_time
end

function generatecuts!(
algo::BendersCutGeneration, algdata::BendersCutGenRuntimeData, reform::Reformulation,
algo::BendersCutGeneration, env::Env, algdata::BendersCutGenRuntimeData, reform::Reformulation,
master_primal_sol::PrimalSolution, master_dual_sol::DualSolution, phase::FormulationPhase
)::Tuple{Int, Bool, PrimalBound}
masterform = getmaster(reform)
Expand All @@ -437,7 +435,7 @@ function generatecuts!(
## TODO stabilization : move the following code inside a loop
nb_new_cuts, spsols_relaxed, pb_correction, sp_pb_contrib =
solve_sps_to_gencuts!(
algo, algdata, reform, master_primal_sol, filtered_dual_sol, phase
algo, env, algdata, reform, master_primal_sol, filtered_dual_sol, phase
)
update_lagrangian_pb!(algdata, reform, master_dual_sol, sp_pb_contrib)
if nb_new_cuts < 0
Expand All @@ -453,7 +451,7 @@ function generatecuts!(
end

function bend_cutting_plane_main_loop!(
algo::BendersCutGeneration, algdata::BendersCutGenRuntimeData, reform::Reformulation
algo::BendersCutGeneration, env::Env, algdata::BendersCutGenRuntimeData, reform::Reformulation
)

nb_bc_iterations = 0
Expand All @@ -472,7 +470,7 @@ function bend_cutting_plane_main_loop!(
nb_new_cuts = 0
cur_gap = 0.0

optoutput, master_time = solve_relaxed_master!(masterform)
optoutput, master_time = solve_relaxed_master!(masterform, env)
optresult = getoptstate(optoutput)

if getterminationstatus(optresult) == INFEASIBLE
Expand Down Expand Up @@ -507,7 +505,7 @@ function bend_cutting_plane_main_loop!(
sp_time = @elapsed begin
nb_new_cuts, one_spsol_is_a_relaxed_sol, primal_bound =
generatecuts!(
algo, algdata, reform, master_primal_sol, master_dual_sol, up_to_phase
algo, env, algdata, reform, master_primal_sol, master_dual_sol, up_to_phase
)
end

Expand All @@ -523,7 +521,7 @@ function bend_cutting_plane_main_loop!(
cur_gap = gap(primal_bound, dual_bound)

print_benders_statistics(
bnd_optstate, nb_new_cuts, nb_bc_iterations, master_time, sp_time
env, bnd_optstate, nb_new_cuts, nb_bc_iterations, master_time, sp_time
)

if cur_gap < algo.optimality_tol
Expand Down Expand Up @@ -585,15 +583,15 @@ function bend_cutting_plane_main_loop!(
end

function print_benders_statistics(
optstate::OptimizationState, nb_new_cut::Int,
env::Env, optstate::OptimizationState, nb_new_cut::Int,
nb_bc_iterations::Int, mst_time::Float64, sp_time::Float64
)
mlp = getvalue(get_lp_dual_bound(optstate))
db = getvalue(get_ip_dual_bound(optstate))
pb = getvalue(get_ip_primal_bound(optstate))
@printf(
"<it=%3i> <et=%5.2f> <mst=%5.2f> <sp=%5.2f> <cuts=%i> <DB=%10.4f> <mlp=%10.4f> <PB=%10.4f>\n",
nb_bc_iterations, Coluna._elapsed_solve_time(), mst_time, sp_time, nb_new_cut, db, mlp, pb
nb_bc_iterations, elapsed_optim_time(env), mst_time, sp_time, nb_new_cut, db, mlp, pb
)
end

18 changes: 9 additions & 9 deletions src/Algorithm/branching/branchingalgo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ end
struct NoBranching <: AbstractDivideAlgorithm
end

function run!(algo::NoBranching, data::ReformData, input::DivideInput)::DivideOutput
function run!(algo::NoBranching, env::Env, data::ReformData, input::DivideInput)::DivideOutput
return DivideOutput([], OptimizationState(getmodel(getmasterdata(data))))
end

Expand Down Expand Up @@ -90,7 +90,7 @@ function exploits_primal_solutions(algo::StrongBranching)
end

function perform_strong_branching_with_phases!(
algo::StrongBranching, data::ReformData, input::DivideInput, groups::Vector{BranchingGroup}
algo::StrongBranching, env::Env, data::ReformData, input::DivideInput, groups::Vector{BranchingGroup}
)::OptimizationState

parent = getparent(input)
Expand Down Expand Up @@ -131,7 +131,7 @@ function perform_strong_branching_with_phases!(
#TO DO: verify if time limit is reached

if phase_index == 1
generate_children!(group, data, parent)
generate_children!(group, env, data, parent)
else
regenerate_children!(group, parent)
end
Expand All @@ -154,7 +154,7 @@ function perform_strong_branching_with_phases!(
update_ip_primal!(getoptstate(node), sbstate, exploitsprimalsolutions)

apply_conquer_alg_to_node!(
node, current_phase.conquer_algo, data, conquer_storages_to_restore
node, current_phase.conquer_algo, env, data, conquer_storages_to_restore
)

update_all_ip_primal_solutions!(sbstate, getoptstate(node))
Expand Down Expand Up @@ -194,7 +194,7 @@ function perform_strong_branching_with_phases!(
return sbstate
end

function run!(algo::StrongBranching, data::ReformData, input::DivideInput)::DivideOutput
function run!(algo::StrongBranching, env::Env, data::ReformData, input::DivideInput)::DivideOutput
parent = getparent(input)
optstate = getoptstate(parent)

Expand Down Expand Up @@ -251,7 +251,7 @@ function run!(algo::StrongBranching, data::ReformData, input::DivideInput)::Divi
min_priority = priority

# generate candidates
output = run!(rule, data, BranchingRuleInput(
output = run!(rule, env, data, BranchingRuleInput(
original_solution, true, nb_candidates_needed, algo.selection_criterion,
local_id, algo.int_tol
))
Expand All @@ -260,7 +260,7 @@ function run!(algo::StrongBranching, data::ReformData, input::DivideInput)::Divi
local_id = output.local_id

if projection_is_possible(master) && extended_solution !== nothing
output = run!(rule, data, BranchingRuleInput(
output = run!(rule, env, data, BranchingRuleInput(
extended_solution, false, nb_candidates_needed, algo.selection_criterion,
local_id, algo.int_tol
))
Expand All @@ -287,11 +287,11 @@ function run!(algo::StrongBranching, data::ReformData, input::DivideInput)::Divi

#in the case of simple branching, it remains to generate the children
if isempty(algo.phases)
generate_children!(kept_branch_groups[1], data, parent)
generate_children!(kept_branch_groups[1], env, data, parent)
return DivideOutput(kept_branch_groups[1].children, OptimizationState(getmaster(reform)))
end

sbstate = perform_strong_branching_with_phases!(algo, data, input, kept_branch_groups)
sbstate = perform_strong_branching_with_phases!(algo, env, data, input, kept_branch_groups)

return DivideOutput(kept_branch_groups[1].children, sbstate)
end
7 changes: 4 additions & 3 deletions src/Algorithm/branching/branchinggroup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ abstract type AbstractBranchingCandidate end

getdescription(candidate::AbstractBranchingCandidate) = ""
generate_children!(
candidate::AbstractBranchingCandidate, lhs::Float64, data::ReformData, node::Node
candidate::AbstractBranchingCandidate, lhs::Float64, env::Env, data::ReformData,
node::Node
) = nothing

"""
Expand Down Expand Up @@ -42,9 +43,9 @@ get_lhs_distance_to_integer(group::BranchingGroup) =
min(group.lhs - floor(group.lhs), ceil(group.lhs) - group.lhs)

function generate_children!(
group::BranchingGroup, data::ReformData, parent::Node
group::BranchingGroup, env::Env, data::ReformData, parent::Node
)
group.children = generate_children(group.candidate, group.lhs, data, parent)
group.children = generate_children(group.candidate, group.lhs, env, data, parent)
return
end

Expand Down
2 changes: 1 addition & 1 deletion src/Algorithm/branching/branchingrule.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ abstract type AbstractBranchingRule <: AbstractAlgorithm end
ismanager(algo::AbstractBranchingRule) = true

function run!(
rule::AbstractBranchingRule, data::AbstractData, input::BranchingRuleInput
rule::AbstractBranchingRule, env::Env, data::AbstractData, input::BranchingRuleInput
)::BranchingRuleOutput
algotype = typeof(rule)
error("Method run! in not defined for branching rule $(typeof(rule)), data $(typeof(data)), and input $(typeof(input)).")
Expand Down
9 changes: 5 additions & 4 deletions src/Algorithm/branching/varbranching.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ end
getdescription(candidate::VarBranchingCandidate) = candidate.description

function generate_children(
candidate::VarBranchingCandidate, lhs::Float64, data::ReformData, parent::Node
candidate::VarBranchingCandidate, lhs::Float64, env::Env, data::ReformData, parent::Node
)
master = getmaster(getreform(data))
var = getvar(master, candidate.varid)
Expand All @@ -33,7 +33,7 @@ function generate_children(
master, string(
"branch_geq_", getdepth(parent), "_", getname(master,candidate.varid)
), MasterBranchOnOrigVarConstr;
sense = Greater, rhs = ceil(lhs), loc_art_var = true,
sense = Greater, rhs = ceil(lhs), loc_art_var_abs_cost = env.params.local_art_var_cost,
members = Dict{VarId,Float64}(candidate.varid => 1.0)
)
end
Expand All @@ -47,7 +47,8 @@ function generate_children(
master, string(
"branch_leq_", getdepth(parent), "_", getname(master,candidate.varid)
), MasterBranchOnOrigVarConstr;
sense = Less, rhs = floor(lhs), loc_art_var = true,
sense = Less, rhs = floor(lhs),
loc_art_var_abs_cost = env.params.local_art_var_cost,
members = Dict{VarId,Float64}(candidate.varid => 1.0)
)
end
Expand Down Expand Up @@ -75,7 +76,7 @@ function get_storages_usage(algo::VarBranchingRule, reform::Reformulation)
end

function run!(
rule::VarBranchingRule, data::ReformData, input::BranchingRuleInput
rule::VarBranchingRule, env::Env, data::ReformData, input::BranchingRuleInput
)::BranchingRuleOutput
# variable branching works only for the original solution
!input.isoriginalsol && return BranchingRuleOutput(input.local_id, Vector{BranchingGroup}())
Expand Down
Loading

0 comments on commit c89bb81

Please sign in to comment.