/
BlockDecomposition.jl
99 lines (82 loc) · 3.06 KB
/
BlockDecomposition.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
module BlockDecomposition
using Combinatorics: powerset
using JuMP
using Graphs: SimpleGraph, add_vertices!, nv
using MathOptInterface
using MetaGraphs: MetaGraph, add_edge!, connected_components, edges, intersect,
set_indexing_prop!, set_prop!, vertices
import MathOptInterface
import MathOptInterface.Utilities
const MOI = MathOptInterface
const MOIU = MOI.Utilities
const JC = JuMP.Containers
export BlockModel, annotation, specify!, gettree, getmaster, getsubproblems, ×, indice,
objectiveprimalbound!, objectivedualbound!, branchingpriority!, branchingpriority,
customvars!, customconstrs!, customvars, customconstrs, subproblemrepresentative,
customdata!, customdata, UnregisteredCustomDataFamily
export @axis, @dantzig_wolfe_decomposition, @benders_decomposition
export AutoDwStrategy
include("axis.jl")
include("annotations.jl")
include("tree.jl")
include("formulations.jl")
include("subproblem_representative.jl")
include("checker.jl")
include("decomposition.jl")
include("objective.jl")
include("customdata.jl")
include("callbacks.jl")
include("automatic_dantzig_wolfe.jl")
include("utils.jl")
include("branchingpriority.jl")
include("soldisaggregation.jl")
function model_factory(::Val{true}, optimizer; kw...)::JuMP.Model
m = JuMP.direct_model(optimizer.optimizer_constructor())
for (param, val) in optimizer.params
set_optimizer_attribute(m, param, val)
end
for (key, val) in kw
if key !== :direct_model
@warn "Unsupported keyword argument $key when creating a BlockModel with direct_model=true."
end
end
return m
end
function model_factory(::Val{false}, args...; kw...)::JuMP.Model
return JuMP.Model(args...; kw...)
end
"""
BlockModel(optimizer [, direct_model = false])
Return a JuMP model which BlockDecomposition will decompose using instructions given by the user.
If you define `direct_model = true`, the method creates the model with `JuMP.direct_model`,
otherwise it uses `JuMP.Model`.
"""
function BlockModel(args...; automatic_dantzig_wolfe::AutoDwStrategy = inactive, kw...)
dm = haskey(kw, :direct_model) ? kw[:direct_model] : false
m = model_factory(Val(dm), args...; kw...)
JuMP.set_optimize_hook(m, optimize!)
m.ext[:automatic_dantzig_wolfe] = automatic_dantzig_wolfe
return m
end
function optimize!(m::JuMP.Model)
if haskey(m.ext, :automatic_dantzig_wolfe) && m.ext[:automatic_dantzig_wolfe] != inactive
automatic_dw_decomposition!(m)
end
register_decomposition(m)
return JuMP.optimize!(m, ignore_optimize_hook = true)
end
"""
annotation(node)
Return the annotation that describes the master/subproblem of a given node of
the decomposition tree.
annotation(model, variable)
annotation(model, constraint)
Return the subproblem to which a variable or a constraint belongs.
"""
function annotation(model::JuMP.Model, objref::JuMP.ConstraintRef)
MOI.get(model, ConstraintDecomposition(), objref)
end
function annotation(model::JuMP.Model, objref::JuMP.VariableRef)
MOI.get(model, VariableDecomposition(), objref)
end
end # module