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

Custom information about Dantzig-Wolfe subproblems #542

Merged
merged 1 commit into from
Jun 13, 2021
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
6 changes: 1 addition & 5 deletions src/MOIcallbacks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,11 @@ function MOI.submit(
custom_data::Union{Nothing, AbstractCustomData} = nothing
)
form = cb.callback_data.form
S = getobjsense(form)
solval = cost
colunavarids = [_get_orig_varid_in_form(model, form, v) for v in variables]

# setup variable
setup_var_id = [id for (id,v) in Iterators.filter(
v -> (iscuractive(form, v.first) && isexplicit(form, v.first) && getduty(v.first) <= DwSpSetupVar),
getvars(form)
)][1]
setup_var_id = form.duty_data.setup_var
push!(colunavarids, setup_var_id)
push!(values, 1.0)
solval += getcurcost(form, setup_var_id)
Expand Down
38 changes: 20 additions & 18 deletions src/MathProg/duties.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ struct DwMaster <: AbstractMasterDuty end
struct BendersMaster <: AbstractMasterDuty end

"A pricing subproblem of a formulation decomposed using Dantzig-Wolfe."
struct DwSp <: AbstractSpDuty end
mutable struct DwSp <: AbstractSpDuty
setup_var::Union{VarId, Nothing}
lower_multiplicity::Int
upper_multiplicity::Int
end

"A Benders subproblem of a formulation decomposed using Benders."
struct BendersSp <: AbstractSpDuty end
Expand All @@ -27,7 +31,7 @@ struct BendersSp <: AbstractSpDuty end
Duty{Variable}
AbstractOriginalVar <= Duty{Variable}
OriginalVar <= AbstractOriginalVar
OriginalExpression <= AbstractOriginalVar
#OriginalExpression <= AbstractOriginalVar
AbstractMasterVar <= Duty{Variable}
AbstractOriginMasterVar <= AbstractMasterVar
MasterPureVar <= AbstractOriginMasterVar
Expand All @@ -52,7 +56,6 @@ struct BendersSp <: AbstractSpDuty end
BendSpSepVar <= AbstractBendSpVar
BendSpPureVar <= AbstractBendSpVar
BendSpPrimalSol <= AbstractBendSpVar
UndefinedVarDuty <= Duty{Variable}
end

#
Expand All @@ -68,36 +71,35 @@ end
MasterMixedConstr <= AbstractMasterOriginConstr
AbstractMasterAddedConstr <= AbstractMasterConstr
MasterConvexityConstr <= AbstractMasterAddedConstr
MasterSecondStageCostConstr <= AbstractMasterAddedConstr
AbstractMasterImplicitConstr <= AbstractMasterConstr
AbstractMasterRepBendSpConstr <= AbstractMasterImplicitConstr
MasterRepBendSpSecondStageCostConstr <= AbstractMasterRepBendSpConstr
MasterRepBendSpTechnologicalConstr <= AbstractMasterRepBendSpConstr
#MasterSecondStageCostConstr <= AbstractMasterAddedConstr
#AbstractMasterImplicitConstr <= AbstractMasterConstr
#AbstractMasterRepBendSpConstr <= AbstractMasterImplicitConstr
#MasterRepBendSpSecondStageCostConstr <= AbstractMasterRepBendSpConstr
#MasterRepBendSpTechnologicalConstr <= AbstractMasterRepBendSpConstr
AbstractMasterCutConstr <= AbstractMasterConstr
MasterBendCutConstr <= AbstractMasterCutConstr
MasterUserCutConstr <= AbstractMasterCutConstr
AbstractMasterBranchingConstr <= AbstractMasterConstr
MasterBranchOnOrigVarConstr <= AbstractMasterBranchingConstr
MasterBranchOnOrigVarConstr <= AbstractMasterBranchingConstr
AbstractDwSpConstr <= Duty{Constraint}
DwSpPureConstr <= AbstractDwSpConstr
DwSpDualSol <= AbstractDwSpConstr
DwSpRepMastBranchConstr <= AbstractDwSpConstr
AbstractBendSpPureConstr <= Duty{Constraint}
# <= AbstractDwSpConstr
#DwSpRepMastBranchConstr <= AbstractDwSpConstr
#AbstractBendSpPureConstr <= Duty{Constraint}
AbstractBendSpConstr <= Duty{Constraint}
AbstractBendSpMasterConstr <= AbstractBendSpConstr
BendSpSecondStageCostConstr <= AbstractBendSpMasterConstr
BendSpTechnologicalConstr <= AbstractBendSpMasterConstr
BendSpPureConstr <= AbstractBendSpConstr
BendSpDualSol <= AbstractBendSpConstr
UndefinedConstrDuty <= Duty{Constraint}
end

#
# Methods to get extra information about duties
#
function isaStaticDuty(duty::NestedEnum)
return duty <= OriginalVar ||
duty <= OriginalExpression ||
#duty <= OriginalExpression ||
duty <= MasterPureVar ||
duty <= MasterArtVar ||
duty <= MasterBendSecondStageCostVar ||
Expand All @@ -117,7 +119,7 @@ function isaStaticDuty(duty::NestedEnum)
duty <= MasterPureConstr ||
duty <= MasterMixedConstr ||
duty <= MasterConvexityConstr ||
duty <= MasterSecondStageCostConstr ||
#duty <= MasterSecondStageCostConstr ||
duty <= DwSpPureConstr ||
duty <= BendSpPureConstr ||
duty <= BendSpDualSol ||
Expand All @@ -130,9 +132,9 @@ function isaDynamicDuty(duty::NestedEnum)
duty <= MasterCol ||
duty <= MasterBranchOnOrigVarConstr ||
duty <= MasterBendCutConstr ||
duty <= MasterBranchOnOrigVarConstr ||
duty <= DwSpRepMastBranchConstr ||
duty <= DwSpRepMastBranchConstr
duty <= MasterBranchOnOrigVarConstr
#duty <= DwSpRepMastBranchConstr ||
#duty <= DwSpRepMastBranchConstr
end

function isanOriginalRepresentatives(duty::NestedEnum)
Expand Down
17 changes: 10 additions & 7 deletions src/MathProg/formulation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,37 @@ mutable struct Formulation{Duty <: AbstractFormDuty} <: AbstractFormulation
obj_sense::Type{<:Coluna.AbstractSense}
buffer::FormulationBuffer
storage::Storage
duty_data::Duty
end


"""
`Formulation` stores a mixed-integer linear program.

create_formulation!(
env::Coluna.Env,
duty::Type{<:AbstractFormDuty};
duty::AbstractFormDuty;
parent_formulation = nothing,
obj_sense::Type{<:Coluna.AbstractSense} = MinSense
)

Create a new formulation in the Coluna's environment `env` with duty `duty`,
parent formulation `parent_formulation`, and objective sense `obj_sense`.
Create a new formulation in the Coluna's environment `env`.
Arguments are `duty` that contains specific information related to the duty of
the formulation, `parent_formulation` that is the parent formulation (master for a subproblem,
reformulation for a master, `nothing` by default), and `obj_sense` the sense of the objective
function (`MinSense` or `MaxSense`).
"""
function create_formulation!(
env,
duty::Type{<:AbstractFormDuty};
duty::AbstractFormDuty;
parent_formulation = nothing,
obj_sense::Type{<:Coluna.AbstractSense} = MinSense
)
if env.form_counter >= MAX_NB_FORMULATIONS
error("Maximum number of formulations reached.")
end
return Formulation{duty}(
return Formulation(
env.form_counter += 1, 0, 0, parent_formulation, AbstractOptimizer[],
FormulationManager(), obj_sense, FormulationBuffer(), Storage()
FormulationManager(), obj_sense, FormulationBuffer(), Storage(), duty
)
end

Expand Down
2 changes: 1 addition & 1 deletion src/MathProg/problem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ end
Constructs an empty `Problem`.
"""
function Problem(env)
original_formulation = create_formulation!(env, Original)
original_formulation = create_formulation!(env, Original())
return Problem(
nothing, nothing, original_formulation, nothing,
no_optimizer_builder
Expand Down
64 changes: 32 additions & 32 deletions src/decomposition.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function instantiatemaster!(
)
form = create_formulation!(
env,
MathProg.DwMaster;
MathProg.DwMaster();
parent_formulation = reform,
obj_sense = getobjsense(get_original_formulation(prob))
)
Expand All @@ -46,7 +46,7 @@ function instantiatemaster!(
)
masterform = create_formulation!(
env,
MathProg.BendersMaster;
MathProg.BendersMaster();
parent_formulation = reform,
obj_sense = getobjsense(get_original_formulation(prob))
)
Expand All @@ -60,7 +60,7 @@ function instantiatesp!(
)
spform = create_formulation!(
env,
MathProg.DwSp;
MathProg.DwSp(nothing, 1, 1);
parent_formulation = masterform,
obj_sense = getobjsense(masterform)
)
Expand All @@ -74,7 +74,7 @@ function instantiatesp!(
)
spform = create_formulation!(
env,
MathProg.BendersSp;
MathProg.BendersSp();
parent_formulation = masterform,
obj_sense = getobjsense(masterform)
)
Expand Down Expand Up @@ -156,6 +156,9 @@ function create_side_vars_constrs!(
kind = Essential, sense = Less, inc_val = 100.0,
loc_art_var_abs_cost = env.params.local_art_var_cost
)
spform.duty_data.lower_multiplicity = lb_mult
spform.duty_data.upper_multiplicity = ub_mult
spform.duty_data.setup_var = getid(setupvar)
masterform.parent_formulation.dw_pricing_sp_ub[spuid] = getid(ub_conv_constr)
coefmatrix[getid(ub_conv_constr), getid(setuprepvar)] = 1.0
end
Expand Down Expand Up @@ -189,23 +192,23 @@ end
function instantiate_orig_constrs!(
spform::Formulation{DwSp},
origform::Formulation{Original},
env::Env,
::Env,
annotations::Annotations,
sp_ann
)
!haskey(annotations.constrs_per_ann, sp_ann) && return
constrs = annotations.constrs_per_ann[sp_ann]
for (id, constr) in constrs
for (_, constr) in constrs
cloneconstr!(origform, spform, spform, constr, DwSpPureConstr)
end
return
end

function create_side_vars_constrs!(
spform::Formulation{DwSp},
origform::Formulation{Original},
env::Env,
annotations::Annotations
::Formulation{Original},
::Env,
::Annotations
)
name = "PricingSetupVar_sp_$(getuid(spform))"
setvar!(
Expand All @@ -219,7 +222,7 @@ function _dutyexpofbendmastvar(
var::Variable, annotations::Annotations, origform::Formulation{Original}
)
orig_coef = getcoefmatrix(origform)
for (constrid, coef) in @view orig_coef[:, getid(var)]
for (constrid, _) in @view orig_coef[:, getid(var)]
constr_ann = annotations.ann_per_constr[constrid]
#if coef != 0 && BD.getformulation(constr_ann) == BD.Benders # TODO use haskey instead testing != 0
if BD.getformulation(constr_ann) == BD.BendersSepSp
Expand All @@ -239,8 +242,7 @@ function instantiate_orig_vars!(
)
!haskey(annotations.vars_per_ann, mast_ann) && return
vars = annotations.vars_per_ann[mast_ann]
for (id, var) in vars
duty, explicit = _dutyexpofbendmastvar(var, annotations, origform)
for (_, var) in vars
clonevar!(origform, masterform, masterform, var, MasterPureVar, is_explicit = true)
end
return
Expand All @@ -249,13 +251,13 @@ end
function instantiate_orig_constrs!(
masterform::Formulation{BendersMaster},
origform::Formulation{Original},
env::Env,
::Env,
annotations::Annotations,
mast_ann
)
!haskey(annotations.constrs_per_ann, mast_ann) && return
constrs = annotations.constrs_per_ann[mast_ann]
for (id, constr) in constrs
for (_, constr) in constrs
cloneconstr!(
origform, masterform, masterform, constr, MasterPureConstr, is_explicit = true
)
Expand All @@ -265,13 +267,11 @@ end

function create_side_vars_constrs!(
masterform::Formulation{BendersMaster},
origform::Formulation{Original},
env::Env,
annotations::Annotations
::Formulation{Original},
::Env,
::Annotations
)
coefmatrix = getcoefmatrix(masterform)

for (spuid, spform) in get_benders_sep_sps(masterform.parent_formulation)
for (_, spform) in get_benders_sep_sps(masterform.parent_formulation)
nu_var = collect(values(filter(
v -> getduty(v.first) == BendSpSlackSecondStageCostVar,
getvars(spform)
Expand All @@ -291,7 +291,7 @@ function create_side_vars_constrs!(
return
end

create_artificial_vars!(masterform::Formulation{BendersMaster}, env::Env) = return
create_artificial_vars!(::Formulation{BendersMaster}, ::Env) = return

function instantiate_orig_vars!(
spform::Formulation{BendersSp},
Expand All @@ -302,18 +302,18 @@ function instantiate_orig_vars!(
masterform = getmaster(spform)
if haskey(annotations.vars_per_ann, sp_ann)
vars = annotations.vars_per_ann[sp_ann]
for (id, var) in vars
for (_, var) in vars
clonevar!(origform, spform, spform, var, BendSpSepVar, cost = 0.0)
end
end
mast_ann = get(annotations, masterform)
if haskey(annotations.vars_per_ann, mast_ann)
vars = annotations.vars_per_ann[mast_ann]
for (id, var) in vars
duty, explicit = _dutyexpofbendmastvar(var, annotations, origform)
duty, _ = _dutyexpofbendmastvar(var, annotations, origform)
if duty == MasterBendFirstStageVar
name = "μ[$(split(getname(origform, var), "[")[end])"
mu = setvar!(
setvar!(
spform, name, BendSpSlackFirstStageVar;
cost = getcurcost(origform, var),
lb = getcurlb(origform, var),
Expand All @@ -330,7 +330,7 @@ end

function _dutyexpofbendspconstr(constr, annotations::Annotations, origform)
orig_coef = getcoefmatrix(origform)
for (varid, coef) in orig_coef[getid(constr), :]
for (varid, _) in orig_coef[getid(constr), :]
var_ann = annotations.ann_per_var[varid]
if BD.getformulation(var_ann) == BD.Master
return BendSpTechnologicalConstr, true
Expand All @@ -342,13 +342,13 @@ end
function instantiate_orig_constrs!(
spform::Formulation{BendersSp},
origform::Formulation{Original},
env::Env,
::Env,
annotations::Annotations,
sp_ann
)
!haskey(annotations.constrs_per_ann, sp_ann) && return
constrs = annotations.constrs_per_ann[sp_ann]
for (id, constr) in constrs
for (_, constr) in constrs
duty, explicit = _dutyexpofbendspconstr(constr, annotations, origform)
cloneconstr!(origform, spform, spform, constr, duty, is_explicit = explicit)
end
Expand All @@ -358,13 +358,13 @@ end
function create_side_vars_constrs!(
spform::Formulation{BendersSp},
origform::Formulation{Original},
env::Env,
annotations::Annotations
::Env,
::Annotations
)
sp_has_second_stage_cost = false
global_costprofit_ub = 0.0
global_costprofit_lb = 0.0
for (varid, var) in getvars(spform)
for (varid, _) in getvars(spform)
getduty(varid) == BendSpSepVar || continue
orig_var = getvar(origform, varid)
cost = getperencost(origform, orig_var)
Expand Down Expand Up @@ -405,7 +405,7 @@ function create_side_vars_constrs!(
)
sp_coef[getid(cost), getid(nu)] = 1.0

for (varid, var) in getvars(spform)
for (varid, _) in getvars(spform)
getduty(varid) == BendSpSepVar || continue
sp_coef[getid(cost), varid] = - getperencost(origform, varid)
end
Expand Down Expand Up @@ -447,7 +447,7 @@ function buildformulations!(
masterform = instantiatemaster!(env, prob, reform, form_type, dec_type)
store!(annotations, masterform, ann)
origform = get_original_formulation(prob)
for (id, child) in BD.subproblems(node)
for (_, child) in BD.subproblems(node)
buildformulations!(prob, reform, env, annotations, node, child)
end
assign_orig_vars_constrs!(masterform, origform, env, annotations, ann)
Expand Down
Loading