Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dispatch decomposition using BD tree #103

Merged
merged 3 commits into from
May 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ version = "0.5.4"

[[BlockDecomposition]]
deps = ["DataStructures", "JuMP", "MathOptInterface", "Test"]
git-tree-sha1 = "caed35511b5d1dd20fbb53a7bac5bc8f63530973"
git-tree-sha1 = "8868596cdfa9de6ad31630d03ecd8556116fb33b"
repo-rev = "master"
repo-url = "https://github.com/atoptima/BlockDecomposition.jl.git"
uuid = "6cde8614-403a-11e9-12f1-c10d0f0caca0"
Expand Down
12 changes: 7 additions & 5 deletions src/MOIwrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function MOI.supports(optimizer::Optimizer,
return true
end

function update_annotations(srs::MOI.ModelLike,
function update_annotations!(srs::MOI.ModelLike,
annotation_set::Set{BD.Annotation},
vc_per_block::Dict{Int,C},
annotation::A,
Expand Down Expand Up @@ -106,7 +106,7 @@ function create_origvars!(f::Formulation,
moi_uid_to_coluna_id[moi_index.value] = var_id
annotation = MOI.get(src, BD.VariableDecomposition(), moi_index)
dest.varmap[moi_index_in_coluna] = var_id
update_annotations(
update_annotations!(
src, dest.annotations.annotation_set,
dest.annotations.vars_per_block, annotation, v
)
Expand Down Expand Up @@ -160,7 +160,7 @@ function create_origconstr!(f::Formulation,
matrix[constr_id, var_id] = term.coefficient
end
annotation = MOI.get(src, BD.ConstraintDecomposition(), moi_index)
update_annotations(
update_annotations!(
src, dest.annotations.annotation_set,
dest.annotations.constrs_per_block, annotation, c
)
Expand Down Expand Up @@ -206,15 +206,17 @@ function register_original_formulation!(dest::Optimizer,
problem = dest.inner
orig_form = Formulation{Original}(problem.form_counter)
set_original_formulation!(problem, orig_form)
moi_uid_to_coluna_id = Dict{Int,VarId}()

moi_uid_to_coluna_id = Dict{Int,VarId}()
create_origvars!(orig_form, dest, src, copy_names, moi_uid_to_coluna_id)
create_origconstrs!(orig_form, dest, src, copy_names, moi_uid_to_coluna_id)

load_obj!(orig_form, src, dest.moi_index_to_coluna_uid, moi_uid_to_coluna_id)

sense = MOI.get(src, MOI.ObjectiveSense())
min_sense = (sense == MOI.MIN_SENSE)
register_objective_sense!(orig_form, min_sense)

dest.annotations.tree = MOI.get(src, BD.DecompositionTree())
return
end

Expand Down
139 changes: 63 additions & 76 deletions src/decomposition.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,13 @@ function initialize_artificial_variables(master::Formulation, constrs_in_form)
# end
end

function find_vcs_in_block(uid::Int, vars_per_block::Dict{Int,VarDict},
constrs_per_block::Dict{Int,ConstrDict})
function find_vcs_in_block(uid::Int, annotations::Annotations)
vars_per_block = annotations.vars_per_block
vars = VarDict()
if haskey(vars_per_block, uid)
vars = vars_per_block[uid]
end
constrs_per_block = annotations.constrs_per_block
constrs = ConstrDict()
if haskey(constrs_per_block, uid)
constrs = constrs_per_block[uid]
Expand Down Expand Up @@ -160,88 +161,74 @@ function build_dw_pricing_sp!(prob::Problem,
return
end

function reformulate!(prob::Problem, annotations::Annotations,
strategy::GlobalStrategy)
# This function must be cleaned.
# subproblem formulations are modified in the function build_dw_master


# Create formulations & reformulations



# At the moment, BlockDecomposition supports only classic
# Dantzig-Wolfe decomposition.
# TODO : improve all drafts as soon as BlockDecomposition returns a
# decomposition-tree.

vars_per_block = annotations.vars_per_block
constrs_per_block = annotations.constrs_per_block
annotation_set = annotations.annotation_set

# Create reformulation
reformulation = Reformulation(prob, strategy)
set_re_formulation!(prob, reformulation)

# Create master formulation
master_form = Formulation{DwMaster}(
prob.form_counter; parent_formulation = reformulation,
function instanciatemaster!(prob::Problem, reform, ::Type{BD.Master}, ::Type{BD.DantzigWolfe})
form = Formulation{DwMaster}(
prob.form_counter; parent_formulation = reform,
obj_sense = getobjsense(get_original_formulation(prob))
)
setmaster!(reformulation, master_form)

# Create pricing subproblem formulations
ann_sorted_by_uid = sort(collect(annotation_set), by = ann -> ann.unique_id)

formulations = Dict{Int, Formulation}()
optimizer_builders = Dict{Int, Function}()
master_unique_id = -1

for annotation in ann_sorted_by_uid
if BD.getoptimizerbuilder(annotation) != nothing
optimizer_builders[BD.getid(annotation)] = BD.getoptimizerbuilder(annotation)
end
if BD.getformulation(annotation) == BD.Master
master_unique_id = BD.getid(annotation)
formulations[BD.getid(annotation)] = master_form
elseif BD.getformulation(annotation) == BD.DwPricingSp
f = Formulation{DwSp}(
prob.form_counter; parent_formulation = master_form,
obj_sense = getobjsense(master_form)
)
formulations[BD.getid(annotation)] = f
add_dw_pricing_sp!(reformulation, f)
else
error(string("Subproblem type ", BD.getformulation(annotation),
" not supported yet."))
end
end
setmaster!(reform, form)
return form
end

# Build Pricing Sp
for annotation in ann_sorted_by_uid
if BD.getformulation(annotation) == BD.DwPricingSp
vars, constrs = find_vcs_in_block(
BD.getid(annotation), vars_per_block, constrs_per_block
)
opt_builder = get(optimizer_builders, BD.getid(annotation), prob.default_optimizer_builder)
build_dw_pricing_sp!(prob, BD.getid(annotation),
formulations[BD.getid(annotation)],
vars, constrs, opt_builder)
end
function createmaster!(form, prob::Problem, reform, ann, annotations, ::Type{BD.Master}, ::Type{BD.DantzigWolfe})
vars, constrs = find_vcs_in_block(BD.getid(ann), annotations)
opt_builder = prob.default_optimizer_builder
if BD.getoptimizerbuilder(ann) != nothing
opt_builder = BD.getoptimizerbuilder(ann)
end
build_dw_master!(prob, BD.getid(ann), reform, form, vars, constrs, opt_builder)
end

# Build Master
vars, constrs = find_vcs_in_block(
master_unique_id, vars_per_block, constrs_per_block
function createsp!(prob::Problem, reform, mast, ann, annotations, ::Type{BD.DwPricingSp}, ::Type{BD.DantzigWolfe})
form = Formulation{DwSp}(
prob.form_counter; parent_formulation = mast,
obj_sense = getobjsense(mast)
)
opt_builder = get(optimizer_builders, master_unique_id, prob.default_optimizer_builder)
build_dw_master!(prob, master_unique_id, reformulation,
master_form, vars, constrs, opt_builder)
add_dw_pricing_sp!(reform, form)

@debug "\e[1;34m Master formulation \e[00m" master_form
for sp_form in reformulation.dw_pricing_subprs
@debug "\e[1;34m Pricing subproblems formulation \e[00m" sp_form
vars, constrs = find_vcs_in_block(BD.getid(ann), annotations)
opt_builder = prob.default_optimizer_builder
if BD.getoptimizerbuilder(ann) != nothing
opt_builder = BD.getoptimizerbuilder(ann)
end
build_dw_pricing_sp!(prob, BD.getid(ann), form, vars, constrs, opt_builder)
return form
end

function registerformulations!(prob::Problem, annotations::Annotations, reform,
parent, node::BD.Root)
ann = BD.annotation(node)
form_type = BD.getformulation(ann)
dec_type = BD.getdecomposition(ann)
form = instanciatemaster!(prob, reform, form_type, dec_type)
for (id, child) in BD.subproblems(node)
registerformulations!(prob, annotations, reform, node, child)
end
createmaster!(form, prob, reform, ann, annotations, form_type, dec_type)
return
end

function registerformulations!(prob::Problem, annotations::Annotations, reform,
parent, node::BD.Leaf)
ann = BD.annotation(node)
form_type = BD.getformulation(ann)
dec_type = BD.getdecomposition(ann)
mast = getmaster(reform)
createsp!(prob, reform, mast, ann, annotations, form_type, dec_type)
return
end

function reformulate!(prob::Problem, annotations::Annotations,
strategy::GlobalStrategy)
vars_per_block = annotations.vars_per_block
constrs_per_block = annotations.constrs_per_block
annotation_set = annotations.annotation_set
decomposition_tree = annotations.tree

root = BD.getroot(decomposition_tree)

# Create reformulation
reform = Reformulation(prob, strategy)
set_re_formulation!(prob, reform)
registerformulations!(prob, annotations, reform, reform, root)
end
5 changes: 4 additions & 1 deletion src/problem.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
struct Annotations
mutable struct Annotations
tree::Union{BD.Tree, Nothing}
vars_per_block::Dict{Int, Dict{Id{Variable},Variable}}
constrs_per_block::Dict{Int, Dict{Id{Constraint},Constraint}}
annotation_set::Set{BD.Annotation}
end

Annotations() = Annotations(
nothing,
Dict{Int, Dict{Id{Variable},Variable}}(),
Dict{Int, Dict{Id{Constraint},Constraint}}(),
Set{BD.Annotation}()
Expand Down