Skip to content

Commit

Permalink
Dispatch decomposition using BD tree (#103)
Browse files Browse the repository at this point in the history
* store decomposition tree in optimizer

* draft new way to decompose

* clean
  • Loading branch information
guimarqu authored May 28, 2019
1 parent 4dbf288 commit 25dab60
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 83 deletions.
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

0 comments on commit 25dab60

Please sign in to comment.