-
-
Notifications
You must be signed in to change notification settings - Fork 390
/
callbacks.jl
157 lines (140 loc) · 5.04 KB
/
callbacks.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
# Copyright 2017, Iain Dunning, Joey Huchette, Miles Lubin, and contributors
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#############################################################################
# JuMP
# An algebraic modeling language for Julia
# See http://github.com/jump-dev/JuMP.jl
#############################################################################
using GLPK
using JuMP
using Random
using Test
"""
example_lazy_constraint()
An example using a lazy constraint callback.
"""
function example_lazy_constraint()
model = Model(GLPK.Optimizer)
@variable(model, 0 <= x <= 2.5, Int)
@variable(model, 0 <= y <= 2.5, Int)
@objective(model, Max, y)
lazy_called = false
function my_callback_function(cb_data)
lazy_called = true
x_val = callback_value(cb_data, x)
y_val = callback_value(cb_data, y)
if y_val - x_val > 1 + 1e-6
con = @build_constraint(y - x <= 1)
MOI.submit(model, MOI.LazyConstraint(cb_data), con)
elseif y_val + x_val > 3 + 1e-6
con = @build_constraint(y - x <= 1)
MOI.submit(model, MOI.LazyConstraint(cb_data), con)
end
end
MOI.set(model, MOI.LazyConstraintCallback(), my_callback_function)
optimize!(model)
@test termination_status(model) == MOI.OPTIMAL
@test primal_status(model) == MOI.FEASIBLE_POINT
@test lazy_called
@test value(x) == 1
@test value(y) == 2
end
example_lazy_constraint()
"""
example_user_cut_constraint()
An example using a user-cut callback.
"""
function example_user_cut_constraint()
Random.seed!(1)
N = 30
item_weights, item_values = rand(N), rand(N)
model = Model(GLPK.Optimizer)
@variable(model, x[1:N], Bin)
@constraint(model, sum(item_weights[i] * x[i] for i = 1:N) <= 10)
@objective(model, Max, sum(item_values[i] * x[i] for i = 1:N))
callback_called = false
function my_callback_function(cb_data)
callback_called = true
# TODO(odow): remove Ref once GLPK supports broadcasting over cb_data.
x_vals = callback_value.(Ref(cb_data), x)
accumulated = sum(item_weights[i] for i=1:N if x_vals[i] > 1e-4)
n_terms = sum(1 for i=1:N if x_vals[i] > 1e-4)
if accumulated > 10
con = @build_constraint(
sum(x[i] for i = 1:N if x_vals[i] > 0.5) <= n_terms - 1
)
MOI.submit(model, MOI.UserCut(cb_data), con)
end
end
MOI.set(model, MOI.UserCutCallback(), my_callback_function)
optimize!(model)
@test termination_status(model) == MOI.OPTIMAL
@test primal_status(model) == MOI.FEASIBLE_POINT
@test callback_called
end
example_user_cut_constraint()
"""
example_heuristic_solution()
An example using a heuristic solution callback.
"""
function example_heuristic_solution()
Random.seed!(1)
N = 30
item_weights, item_values = rand(N), rand(N)
model = Model(GLPK.Optimizer)
@variable(model, x[1:N], Bin)
@constraint(model, sum(item_weights[i] * x[i] for i = 1:N) <= 10)
@objective(model, Max, sum(item_values[i] * x[i] for i = 1:N))
callback_called = false
function my_callback_function(cb_data)
callback_called = true
# TODO(odow): remove Ref once GLPK supports broadcasting over cb_data.
x_vals = callback_value.(Ref(cb_data), x)
@test MOI.submit(
model, MOI.HeuristicSolution(cb_data), x, floor.(x_vals)
) in (MOI.HEURISTIC_SOLUTION_ACCEPTED, MOI.HEURISTIC_SOLUTION_REJECTED)
end
MOI.set(model, MOI.HeuristicCallback(), my_callback_function)
optimize!(model)
@test termination_status(model) == MOI.OPTIMAL
@test primal_status(model) == MOI.FEASIBLE_POINT
@test callback_called
end
example_heuristic_solution()
"""
example_solver_dependent_callback()
An example using a solver_dependent callback.
"""
function example_solver_dependent_callback()
model = Model(GLPK.Optimizer)
@variable(model, 0 <= x <= 2.5, Int)
@variable(model, 0 <= y <= 2.5, Int)
@objective(model, Max, y)
lazy_called = false
function my_callback_function(cb_data)
lazy_called = true
reason = GLPK.ios_reason(cb_data.tree)
if reason != GLPK.IROWGEN
return
end
x_val = callback_value(cb_data, x)
y_val = callback_value(cb_data, y)
if y_val - x_val > 1 + 1e-6
con = @build_constraint(y - x <= 1)
MOI.submit(model, MOI.LazyConstraint(cb_data), con)
elseif y_val + x_val > 3 + 1e-6
con = @build_constraint(y - x <= 1)
MOI.submit(model, MOI.LazyConstraint(cb_data), con)
end
end
MOI.set(model, GLPK.CallbackFunction(), my_callback_function)
optimize!(model)
@test termination_status(model) == MOI.OPTIMAL
@test primal_status(model) == MOI.FEASIBLE_POINT
@test lazy_called
@test value(x) == 1
@test value(y) == 2
end
example_solver_dependent_callback()