@@ -21,14 +21,22 @@ function _get_tight_M(func::AbstractJuMPScalar, set::_MOI.AbstractSet, method::B
21
21
end
22
22
23
23
# Get user-specified Big-M value
24
- function _get_M (:: AbstractJuMPScalar , :: Union{_MOI.LessThan, _MOI.GreaterThan, _MOI.Nonnegatives, _MOI.Nonpositives} , method:: BigM )
24
+ function _get_M (
25
+ :: AbstractJuMPScalar ,
26
+ :: Union{_MOI.LessThan, _MOI.GreaterThan, _MOI.Nonnegatives, _MOI.Nonpositives} ,
27
+ method:: BigM
28
+ )
25
29
M = method. value
26
30
if isinf (M)
27
31
error (" A finite Big-M value must be used. The value given was $M ." )
28
32
end
29
33
return M
30
34
end
31
- function _get_M (:: AbstractJuMPScalar , :: Union{_MOI.Interval, _MOI.EqualTo, _MOI.Zeros} , method:: BigM )
35
+ function _get_M (
36
+ :: AbstractJuMPScalar ,
37
+ :: Union{_MOI.Interval, _MOI.EqualTo, _MOI.Zeros} ,
38
+ method:: BigM
39
+ )
32
40
M = method. value
33
41
if isinf (M)
34
42
error (" A finite Big-M value must be used. The value given was $M ." )
@@ -37,79 +45,102 @@ function _get_M(::AbstractJuMPScalar, ::Union{_MOI.Interval, _MOI.EqualTo, _MOI.
37
45
end
38
46
39
47
# Apply interval arithmetic on a linear constraint to infer the tightest Big-M value from the bounds on the constraint.
40
- function _calculate_tight_M (func:: AffExpr , set:: _MOI.LessThan , method:: BigM )
48
+ function _calculate_tight_M (
49
+ func:: JuMP.GenericAffExpr ,
50
+ set:: _MOI.LessThan ,
51
+ method:: BigM
52
+ )
41
53
return _interval_arithmetic_LessThan (func, - set. upper, method)
42
54
end
43
- function _calculate_tight_M (func:: AffExpr , set:: _MOI.GreaterThan , method:: BigM )
55
+ function _calculate_tight_M (
56
+ func:: JuMP.GenericAffExpr ,
57
+ set:: _MOI.GreaterThan ,
58
+ method:: BigM
59
+ )
44
60
return _interval_arithmetic_GreaterThan (func, - set. lower, method)
45
61
end
46
- function _calculate_tight_M (func:: AffExpr , :: _MOI.Nonpositives , method:: BigM )
47
- return _interval_arithmetic_LessThan (func, 0.0 , method)
62
+ function _calculate_tight_M (
63
+ func:: JuMP.GenericAffExpr{C, V} ,
64
+ :: _MOI.Nonpositives ,
65
+ method:: BigM
66
+ ) where {C, V}
67
+ return _interval_arithmetic_LessThan (func, zero (C), method)
48
68
end
49
- function _calculate_tight_M (func:: AffExpr , :: _MOI.Nonnegatives , method:: BigM )
50
- return _interval_arithmetic_GreaterThan (func, 0.0 , method)
69
+ function _calculate_tight_M (
70
+ func:: JuMP.GenericAffExpr{C, V} ,
71
+ :: _MOI.Nonnegatives ,
72
+ method:: BigM
73
+ ) where {C, V}
74
+ return _interval_arithmetic_GreaterThan (func, zero (C), method)
51
75
end
52
- function _calculate_tight_M (func:: AffExpr , set:: _MOI.Interval , method:: BigM )
76
+ function _calculate_tight_M (
77
+ func:: JuMP.GenericAffExpr ,
78
+ set:: _MOI.Interval ,
79
+ method:: BigM
80
+ )
53
81
return (
54
82
_interval_arithmetic_GreaterThan (func, - set. lower, method),
55
83
_interval_arithmetic_LessThan (func, - set. upper, method)
56
84
)
57
85
end
58
- function _calculate_tight_M (func:: AffExpr , set:: _MOI.EqualTo , method:: BigM )
86
+ function _calculate_tight_M (
87
+ func:: JuMP.GenericAffExpr ,
88
+ set:: _MOI.EqualTo ,
89
+ method:: BigM
90
+ )
59
91
return (
60
92
_interval_arithmetic_GreaterThan (func, - set. value, method),
61
93
_interval_arithmetic_LessThan (func, - set. value, method)
62
94
)
63
95
end
64
- function _calculate_tight_M (func:: AffExpr , :: _MOI.Zeros , method:: BigM )
96
+ function _calculate_tight_M (
97
+ func:: JuMP.GenericAffExpr{C, V} ,
98
+ :: _MOI.Zeros ,
99
+ method:: BigM
100
+ ) where {C, V}
65
101
return (
66
- _interval_arithmetic_GreaterThan (func, 0.0 , method),
67
- _interval_arithmetic_LessThan (func, 0.0 , method)
102
+ _interval_arithmetic_GreaterThan (func, zero (C) , method),
103
+ _interval_arithmetic_LessThan (func, zero (C) , method)
68
104
)
69
105
end
70
106
# fallbacks for other scalar constraints
71
- _calculate_tight_M (func:: Union{QuadExpr, NonlinearExpr} , set:: Union{_MOI.Interval, _MOI.EqualTo, _MOI.Zeros} , method:: BigM ) = (Inf , Inf )
72
- _calculate_tight_M (func:: Union{QuadExpr, NonlinearExpr} , set:: Union{_MOI.LessThan, _MOI.GreaterThan, _MOI.Nonnegatives, _MOI.Nonpositives} , method:: BigM ) = Inf
73
- _calculate_tight_M (func, set, method:: BigM ) = error (" BigM method not implemented for constraint type $(typeof (func)) in $(typeof (set)) " )
74
-
75
- # get variable bounds for interval arithmetic
76
- function _update_variable_bounds (vref:: VariableRef , method:: BigM )
77
- if is_binary (vref)
78
- lb = 0
79
- elseif ! has_lower_bound (vref)
80
- lb = - Inf
81
- else
82
- lb = lower_bound (vref)
83
- end
84
- if is_binary (vref)
85
- ub = 1
86
- elseif ! has_upper_bound (vref)
87
- ub = Inf
88
- else
89
- ub = upper_bound (vref)
90
- end
91
- return lb, ub
107
+ function _calculate_tight_M (
108
+ func:: Union{JuMP.GenericQuadExpr, JuMP.GenericNonlinearExpr} ,
109
+ set:: Union{_MOI.Interval, _MOI.EqualTo, _MOI.Zeros} ,
110
+ method:: BigM
111
+ )
112
+ return (Inf , Inf )
113
+ end
114
+ function _calculate_tight_M (
115
+ func:: Union{JuMP.GenericQuadExpr, JuMP.GenericNonlinearExpr} ,
116
+ set:: Union{_MOI.LessThan, _MOI.GreaterThan, _MOI.Nonnegatives, _MOI.Nonpositives} ,
117
+ method:: BigM
118
+ )
119
+ return Inf
120
+ end
121
+ function _calculate_tight_M (:: F , :: S , :: BigM ) where {F, S}
122
+ error (" BigM method not implemented for constraint type `$(F) ` in `$(S) `." )
92
123
end
93
124
94
125
# perform interval arithmetic to update the initial M value
95
- function _interval_arithmetic_LessThan (func:: AffExpr , M:: Float64 , method :: BigM )
126
+ function _interval_arithmetic_LessThan (func:: JuMP.GenericAffExpr , M, :: BigM )
96
127
for (var,coeff) in func. terms
97
- is_binary (var) && continue # skip binary variables
128
+ JuMP . is_binary (var) && continue
98
129
if coeff > 0
99
- M += coeff* method . variable_bounds[ var] [2 ]
130
+ M += coeff* variable_bound_info ( var) [2 ]
100
131
else
101
- M += coeff* method . variable_bounds[ var] [1 ]
132
+ M += coeff* variable_bound_info ( var) [1 ]
102
133
end
103
134
end
104
135
return M + func. constant
105
136
end
106
- function _interval_arithmetic_GreaterThan (func:: AffExpr , M:: Float64 , method :: BigM )
137
+ function _interval_arithmetic_GreaterThan (func:: JuMP.GenericAffExpr , M, :: BigM )
107
138
for (var,coeff) in func. terms
108
- is_binary (var) && continue # skip binary variables
139
+ JuMP . is_binary (var) && continue
109
140
if coeff < 0
110
- M += coeff* method . variable_bounds[ var] [2 ]
141
+ M += coeff* variable_bound_info ( var) [2 ]
111
142
else
112
- M += coeff* method . variable_bounds[ var] [1 ]
143
+ M += coeff* variable_bound_info ( var) [1 ]
113
144
end
114
145
end
115
146
return - (M + func. constant)
@@ -118,15 +149,27 @@ end
118
149
# ###############################################################################
119
150
# BIG-M REFORMULATION
120
151
# ###############################################################################
121
- function _reformulate_disjunctions (model:: Model , method:: BigM )
122
- method. tighten && _query_variable_bounds (model, method)
123
- _reformulate_all_disjunctions (model, method)
152
+ requires_variable_bound_info (method:: BigM ) = method. tighten
153
+
154
+ # get variable bounds for interval arithmetic (note these cannot be binary)
155
+ function set_variable_bound_info (vref:: JuMP.AbstractVariableRef , :: BigM )
156
+ if ! has_lower_bound (vref)
157
+ lb = - Inf
158
+ else
159
+ lb = lower_bound (vref)
160
+ end
161
+ if ! has_upper_bound (vref)
162
+ ub = Inf
163
+ else
164
+ ub = upper_bound (vref)
165
+ end
166
+ return lb, ub
124
167
end
125
168
126
169
function reformulate_disjunct_constraint (
127
- model:: Model ,
170
+ model:: JuMP.AbstractModel ,
128
171
con:: ScalarConstraint{T, S} ,
129
- bvref:: VariableRef ,
172
+ bvref:: JuMP.AbstractVariableRef ,
130
173
method:: BigM
131
174
) where {T, S <: _MOI.LessThan }
132
175
M = _get_M_value (con. func, con. set, method)
@@ -135,9 +178,9 @@ function reformulate_disjunct_constraint(
135
178
return [reform_con]
136
179
end
137
180
function reformulate_disjunct_constraint (
138
- model:: Model ,
181
+ model:: JuMP.AbstractModel ,
139
182
con:: VectorConstraint{T, S, R} ,
140
- bvref:: VariableRef ,
183
+ bvref:: JuMP.AbstractVariableRef ,
141
184
method:: BigM
142
185
) where {T, S <: _MOI.Nonpositives , R}
143
186
M = [_get_M_value (func, con. set, method) for func in con. func]
@@ -148,9 +191,9 @@ function reformulate_disjunct_constraint(
148
191
return [reform_con]
149
192
end
150
193
function reformulate_disjunct_constraint (
151
- model:: Model ,
194
+ model:: JuMP.AbstractModel ,
152
195
con:: ScalarConstraint{T, S} ,
153
- bvref:: VariableRef ,
196
+ bvref:: JuMP.AbstractVariableRef ,
154
197
method:: BigM
155
198
) where {T, S <: _MOI.GreaterThan }
156
199
M = _get_M_value (con. func, con. set, method)
@@ -159,9 +202,9 @@ function reformulate_disjunct_constraint(
159
202
return [reform_con]
160
203
end
161
204
function reformulate_disjunct_constraint (
162
- model:: Model ,
205
+ model:: JuMP.AbstractModel ,
163
206
con:: VectorConstraint{T, S, R} ,
164
- bvref:: VariableRef ,
207
+ bvref:: JuMP.AbstractVariableRef ,
165
208
method:: BigM
166
209
) where {T, S <: _MOI.Nonnegatives , R}
167
210
M = [_get_M_value (func, con. set, method) for func in con. func]
@@ -172,9 +215,9 @@ function reformulate_disjunct_constraint(
172
215
return [reform_con]
173
216
end
174
217
function reformulate_disjunct_constraint (
175
- model:: Model ,
218
+ model:: JuMP.AbstractModel ,
176
219
con:: ScalarConstraint{T, S} ,
177
- bvref:: VariableRef ,
220
+ bvref:: JuMP.AbstractVariableRef ,
178
221
method:: BigM
179
222
) where {T, S <: Union{_MOI.Interval, _MOI.EqualTo} }
180
223
M = _get_M_value (con. func, con. set, method)
@@ -186,9 +229,9 @@ function reformulate_disjunct_constraint(
186
229
return [reform_con_gt, reform_con_lt]
187
230
end
188
231
function reformulate_disjunct_constraint (
189
- model:: Model ,
232
+ model:: JuMP.AbstractModel ,
190
233
con:: VectorConstraint{T, S, R} ,
191
- bvref:: VariableRef ,
234
+ bvref:: JuMP.AbstractVariableRef ,
192
235
method:: BigM
193
236
) where {T, S <: _MOI.Zeros , R}
194
237
M = [_get_M_value (func, con. set, method) for func in con. func]
@@ -201,4 +244,4 @@ function reformulate_disjunct_constraint(
201
244
reform_con_nn = build_constraint (error, new_func_nn, _MOI. Nonnegatives (con. set. dimension))
202
245
reform_con_np = build_constraint (error, new_func_np, _MOI. Nonpositives (con. set. dimension))
203
246
return [reform_con_nn, reform_con_np]
204
- end
247
+ end
0 commit comments