1
+ # # How to implement the BLMO Interface using the cube as an example
2
+ using Boscia
3
+ using Bonobo
4
+ using Dates
1
5
2
6
"""
3
7
CubeBLMO
4
8
5
9
A Bounded Linear Minimization Oracle over a cube.
6
10
"""
7
- mutable struct CubeBLMO <: BoundedLinearMinimizationOracle
11
+ mutable struct CubeBLMO <: Boscia. BoundedLinearMinimizationOracle
8
12
n:: Int
9
13
int_vars:: Vector{Int}
10
- bounds:: IntegerBounds
14
+ bounds:: Boscia. IntegerBounds
11
15
solving_time:: Float64
12
16
end
13
17
@@ -16,7 +20,7 @@ CubeBLMO(n, int_vars, bounds) = CubeBLMO(n, int_vars, bounds, 0.0)
16
20
# # Necessary
17
21
18
22
# computing an extreme point for the cube amounts to checking the sign of the gradient
19
- function compute_extreme_point (blmo:: CubeBLMO , d; kwargs... )
23
+ function Boscia . compute_extreme_point (blmo:: CubeBLMO , d; kwargs... )
20
24
time_ref = Dates. now ()
21
25
v = zeros (length (d))
22
26
for i in eachindex (d)
28
32
29
33
# #
30
34
31
- function build_global_bounds (blmo:: CubeBLMO , integer_variables)
32
- global_bounds = IntegerBounds ()
35
+ function Boscia . build_global_bounds (blmo:: CubeBLMO , integer_variables)
36
+ global_bounds = Boscia . IntegerBounds ()
33
37
for i in 1 : blmo. n
34
38
if i in integer_variables
35
39
push! (global_bounds, (i, blmo. bounds[i, :lessthan ]), :lessthan )
41
45
42
46
43
47
# # Read information from problem
44
- function get_list_of_variables (blmo:: CubeBLMO )
48
+ function Boscia . get_list_of_variables (blmo:: CubeBLMO )
45
49
return blmo. n, collect (1 : blmo. n)
46
50
end
47
51
48
52
# Get list of integer variables, respectively.
49
- function get_integer_variables (blmo:: CubeBLMO )
53
+ function Boscia . get_integer_variables (blmo:: CubeBLMO )
50
54
return blmo. int_vars
51
55
end
52
56
53
- function get_int_var (blmo:: CubeBLMO , cidx)
57
+ function Boscia . get_int_var (blmo:: CubeBLMO , cidx)
54
58
return cidx
55
59
end
56
60
57
- function get_lower_bound_list (blmo:: CubeBLMO )
61
+ function Boscia . get_lower_bound_list (blmo:: CubeBLMO )
58
62
return keys (blmo. bounds. lower_bounds)
59
63
end
60
64
61
- function get_upper_bound_list (blmo:: CubeBLMO )
65
+ function Boscia . get_upper_bound_list (blmo:: CubeBLMO )
62
66
return keys (blmo. bounds. upper_bounds)
63
67
end
64
68
65
- function get_bound (blmo:: CubeBLMO , c_idx, sense:: Symbol )
69
+ function Boscia . get_bound (blmo:: CubeBLMO , c_idx, sense:: Symbol )
66
70
@assert sense == :lessthan || sense == :greaterthan
67
71
return blmo[c_idx, sense]
68
72
end
69
73
70
- # function get_lower_bound(blmo::CubeBLMO, c_idx)
71
- # return blmo.bounds[c_idx, :greaterthan]
72
- # end
73
-
74
- # function get_upper_bound(blmo::CubeBLMO, c_idx)
75
- # return blmo.bounds[c_idx, :lessthan]
76
- # end
77
-
78
74
# # Changing the bounds constraints.
79
- function set_bound! (blmo:: CubeBLMO , c_idx, value, sense:: Symbol )
75
+ function Boscia . set_bound! (blmo:: CubeBLMO , c_idx, value, sense:: Symbol )
80
76
if sense == :greaterthan
81
77
blmo. bounds. lower_bounds[c_idx] = value
82
78
elseif sense == :lessthan
@@ -86,29 +82,29 @@ function set_bound!(blmo::CubeBLMO, c_idx, value, sense::Symbol)
86
82
end
87
83
end
88
84
89
- function delete_bounds! (blmo:: CubeBLMO , cons_delete)
85
+ function Boscia . delete_bounds! (blmo:: CubeBLMO , cons_delete)
90
86
# For the cube this shouldn't happen! Otherwise we get unbounded!
91
87
if ! isempty (cons_delete)
92
88
error (" Trying to delete bounds of the cube!" )
93
89
end
94
90
end
95
91
96
- function add_bound_constraint! (blmo:: CubeBLMO , key, value, sense:: Symbol )
92
+ function Boscia . add_bound_constraint! (blmo:: CubeBLMO , key, value, sense:: Symbol )
97
93
# Should not be necessary
98
94
return error (" Trying to add bound constraints of the cube!" )
99
95
end
100
96
101
97
# # Checks
102
98
103
- function is_constraint_on_int_var (blmo:: CubeBLMO , c_idx, int_vars)
99
+ function Boscia . is_constraint_on_int_var (blmo:: CubeBLMO , c_idx, int_vars)
104
100
return c_idx in int_vars
105
101
end
106
102
107
- function is_bound_in (blmo:: CubeBLMO , c_idx, bounds)
103
+ function Boscia . is_bound_in (blmo:: CubeBLMO , c_idx, bounds)
108
104
return haskey (bounds, c_idx)
109
105
end
110
106
111
- function is_linear_feasible (blmo:: CubeBLMO , v:: AbstractVector )
107
+ function Boscia . is_linear_feasible (blmo:: CubeBLMO , v:: AbstractVector )
112
108
for i in eachindex (v)
113
109
if ! (
114
110
blmo. bounds[i, :greaterthan ] ≤ v[i] + 1e-6 ||
@@ -123,16 +119,15 @@ function is_linear_feasible(blmo::CubeBLMO, v::AbstractVector)
123
119
return true
124
120
end
125
121
126
- function has_integer_constraint (blmo:: CubeBLMO , idx)
122
+ function Boscia . has_integer_constraint (blmo:: CubeBLMO , idx)
127
123
return idx in blmo. int_vars
128
124
end
129
125
130
126
131
-
132
127
# ##################### Optional
133
128
# # Safety Functions
134
129
135
- function build_LMO_correct (blmo:: CubeBLMO , node_bounds)
130
+ function Boscia . build_LMO_correct (blmo:: CubeBLMO , node_bounds)
136
131
for key in keys (node_bounds. lower_bounds)
137
132
if ! haskey (blmo. bounds, (key, :greaterthan )) ||
138
133
blmo. bounds[key, :greaterthan ] != node_bounds[key, :greaterthan ]
@@ -148,60 +143,23 @@ function build_LMO_correct(blmo::CubeBLMO, node_bounds)
148
143
return true
149
144
end
150
145
151
- function check_feasibility (blmo:: CubeBLMO )
146
+ function Boscia . check_feasibility (blmo:: CubeBLMO )
152
147
for i in 1 : blmo. n
153
148
if ! haskey (blmo. bounds, (i, :greaterthan )) || ! haskey (blmo. bounds, (i, :lessthan ))
154
- return UNBOUNDED
149
+ return Boscia . UNBOUNDED
155
150
end
156
151
if blmo. bounds[i, :greaterthan ] > blmo. bounds[i, :lessthan ]
157
- return INFEASIBLE
152
+ return Boscia . INFEASIBLE
158
153
end
159
154
end
160
- return OPTIMAL
155
+ return Boscia . OPTIMAL
161
156
end
162
157
163
- function is_valid_split (tree:: Bonobo.BnBTree , blmo:: CubeBLMO , vidx:: Int )
158
+ function Boscia . is_valid_split (tree:: Bonobo.BnBTree , blmo:: CubeBLMO , vidx:: Int )
164
159
return blmo. bounds[vidx, :lessthan ] != blmo. bounds[vidx, :greaterthan ]
165
160
end
166
161
167
162
# # Logs
168
- function get_BLMO_solve_data (blmo:: CubeBLMO )
163
+ function Boscia . get_BLMO_solve_data (blmo:: CubeBLMO )
169
164
return blmo. solving_time, 0.0 , 0.0
170
- end
171
-
172
- # #######################################################################
173
- """
174
- CubeSimpleBLMO{T}(lower_bounds, upper_bounds)
175
-
176
- Hypercube with lower and upper bounds implementing the `SimpleBoundableLMO` interface.
177
- """
178
- struct CubeSimpleBLMO <: SimpleBoundableLMO
179
- lower_bounds:: Vector{Float64}
180
- upper_bounds:: Vector{Float64}
181
- int_vars:: Vector{Int}
182
- end
183
-
184
- function bounded_compute_extreme_point (sblmo:: CubeSimpleBLMO , d, lb, ub, int_vars; kwargs... )
185
- v = zeros (length (d))
186
- for i in eachindex (d)
187
- if i in int_vars
188
- idx = findfirst (x -> x == i, int_vars)
189
- v[i] = d[i] > 0 ? lb[idx] : ub[idx]
190
- else
191
- v[i] = d[i] > 0 ? sblmo. lower_bounds[i] : sblmo. upper_bounds[i]
192
- end
193
- end
194
- return v
195
- end
196
-
197
- function is_linear_feasible (sblmo:: CubeSimpleBLMO , v)
198
- for i in setdiff (eachindex (v), sblmo. int_vars)
199
- if ! (sblmo. lower_bounds[i] ≤ v[i] + 1e-6 || ! (v[i] - 1e-6 ≤ blmo. upper_bounds[i]))
200
- @debug (
201
- " Vertex entry: $(v[i]) Lower bound: $(blmo. bounds[i, :greaterthan ]) Upper bound: $(blmo. bounds[i, :lessthan ]) )"
202
- )
203
- return false
204
- end
205
- end
206
- return true
207
- end
165
+ end
0 commit comments