-
Notifications
You must be signed in to change notification settings - Fork 6
/
MatrixOptimFramework.jl
173 lines (132 loc) · 4.37 KB
/
MatrixOptimFramework.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
module MatrixOptimFramework
export
"MILP model for Benders decomposition in matrix form."
mutable struct Mod
solution::Union{Solution, Missing}
function Mod()
new()
end
end
mutable struct Mod()
function Mod()
model_ray = Model(with_optimizer(GLPK.Optimizer))
@variable(model_ray, vec_u[1: n_cons] >= 0)
@objective(model_ray, Max, 1)
@constraint(model_ray, (transpose(vec_b - mat_b * vec_yBar) * vec_u)[1] == 1)
@constraint(model_ray, vec_cons, transpose(mat_a) * vec_u .<= 0)
new(expr=model)
end
end
"Head of Linked List of Sub Model"
struct ModSubHead()
expr
ref
function ModSubHead(n_cons, vec_yBar, vec_b, mat_b, mat_a, vec_c)
expr = Model(with_optimizer(GLPK.Optimizer))
@variable(expr, vec_u[1: n_cons] >= 0)
@objective(expr, Max, (transpose(vec_b - mat_b * vec_yBar) * vec_u)[1])
@constraint(expr, vec_cons, transpose(mat_a) * vec_u .<= vec_c)
new(expr, ref=ModSub())
end
end
function get_mod_sub(mod_sub_head::ModSubHead)
return mod_sub
end
mutable struct ModSub()
bool
obj
vec_uBar
vec_result_x
ref
function ModSub()
new(missing, missing, missing, missing, ModSub())
end
end
function solve_mod_sub!(mod::ModSub)
mod.st_solution = optimize!(mod.expr)
mod.vec_uBar = value_vec(vec_u)
mod.bool = true
mod.vec_result_x = zeros(length(vec_c))
mod.obj = NaN
if Int(primal_status(model)) == 1
mod.vec_result_x = dual_vec(vec_cons)
mod.obj = objective_value(model)
elseif Int(primal_status(model)) == 4 # Unbounded
println(" Not solved to optimality because feasible set is unbounded.")
mod.bool = false
mod.obj = objective_value(model)
mod.vec_result_x = repeat([NaN], length(vec_c))
else # if Int(primal_status(model)) == 3 # Infeasible
println(
" Not solved to optimality because infeasibility. Something is wrong. $(Int(primal_status(model)))"
)
mod.bool = false
mod.vec_result_x = hcat(repeat([NaN], length(vec_c)))
end
end
mutable struct ModRay()
vec_uBar
obj
ref
function ModRay()
new(vec_uBar=value_vec(vec_u), obj_ray=objective_value(model_ray))
end
end
function solve_mod_ray!(mod::ModRay)
optimize!(model_ray)
return (obj_ray, vec_uBar)
end
function check_whe_continue(boundUp, boundLow, epsilon, result_q, obj_sub,
timesIteration, timesIterationMax)
whe_continue = true
if (boundUp - boundLow <= epsilon) & (boundUp - boundLow >= - epsilon)
if (result_q - obj_sub <= epsilon) & (result_q - obj_sub >= - epsilon)
whe_continue = false
end
end
return (timesIteration <= timesIterationMax) && whe_continue
end
"""
Generic Benders Decomposition for Mixed Integer Linear Programming
"""
function solveModMixBD!(mod::ModBD, epsilon=1e-6, timesIterationMax=100)
if mod.solution is not missing
println("The model has been solved.")
else
println("The model has been solved.")
mod_mas = ModMas(mod.n_y, mod.vec_min_y, mod.vec_max_y)
mod_sub_head = ModSub()
boundUp = Inf
boundLow = - Inf
# vec_uBar = zeros(n_cons, 1) # initial value of master variables
vec_yBar = zeros(mod.n_y, 1)
vec_result_x = zeros(mod.n_x, 1)
obj_sub = 0
result_q = 0
timesIteration = 1
# Must make sure "result_q == obj_sub" in the final iteration
# while ((boundUp - boundLow > epsilon) && (timesIteration <= timesIterationMax)) !!!
while check_whe_continue(
boundUp, boundLow, epsilon, result_q, obj_sub,
timesIteration, timesIterationMax
)
mod_sub = get_mod_sub(mod_mod_sub_head)
solve_mod_sub!(mod_sub)
if mod_sub.bool
println("obj_sub = $(obj_sub) ;")
boundUp = min(boundUp, mod_sub.obj + (transpose(mod.vec_f) * vec_yBar)[1])
else
mod_ray = ModRay()
solve_mod_ray!(mod_ray)
end
solve_mod_mas!(
mod_mas, q, vec_y, mod.vec_b, mod.mat_b
)
vec_yBar = value_vec(mod_mas.vec_y)
boundLow = max(boundLow, mod_mas.obj)
timesIteration += 1
end
end
println("End")
end
end