@@ -74,32 +74,30 @@ function reformulate_disjunct_constraint(
7474 return new_ref_cons
7575end
7676
77+ # Per-row M values: method.M[d] is a Vector, index with [j] for row j
7778function reformulate_disjunct_constraint (
7879 model:: JuMP.AbstractModel ,
7980 con:: JuMP.VectorConstraint{T, S, R} ,
8081 bconref:: Union {Dict{<: LogicalVariableRef ,<: JuMP.AbstractVariableRef },
8182 Dict{<: LogicalVariableRef ,<: JuMP.GenericAffExpr }},
8283 method:: _MBM
8384) where {T, S <: _MOI.Nonpositives , R}
84- m_sum = sum (method. M[i] * bconref[i] for i in keys (method. M))
85- new_func = JuMP. @expression (model, [i= 1 : con. set. dimension],
86- con. func[i] - m_sum
85+ new_func = JuMP. @expression (model, [j= 1 : con. set. dimension],
86+ con. func[j] - sum (method. M[d][j] * bconref[d] for d in keys (method. M))
8787 )
8888 reform_con = JuMP. build_constraint (error, new_func, con. set)
8989 return [reform_con]
9090end
9191
92-
9392function reformulate_disjunct_constraint (
9493 model:: JuMP.AbstractModel ,
9594 con:: JuMP.VectorConstraint{T, S, R} ,
9695 bconref:: Union {Dict{<: LogicalVariableRef ,<: JuMP.AbstractVariableRef },
9796 Dict{<: LogicalVariableRef ,<: JuMP.GenericAffExpr }},
9897 method:: _MBM
9998) where {T, S <: _MOI.Nonnegatives , R}
100- m_sum = sum (method. M[i] * bconref[i] for i in keys (method. M))
101- new_func = JuMP. @expression (model, [i= 1 : con. set. dimension],
102- con. func[i] + m_sum
99+ new_func = JuMP. @expression (model, [j= 1 : con. set. dimension],
100+ con. func[j] + sum (method. M[d][j] * bconref[d] for d in keys (method. M))
103101 )
104102 reform_con = JuMP. build_constraint (error, new_func, con. set)
105103 return [reform_con]
@@ -112,17 +110,16 @@ function reformulate_disjunct_constraint(
112110 Dict{<: LogicalVariableRef ,<: JuMP.GenericAffExpr }},
113111 method:: _MBM
114112) where {T, S <: _MOI.Zeros , R}
115- m_sum = sum (method. M[i] * bconref[i] for i in keys (method. M))
116- upper_expr = JuMP. @expression (model, [i= 1 : con. set. dimension],
117- con. func[i] + m_sum
113+ upper_expr = JuMP. @expression (model, [j= 1 : con. set. dimension],
114+ con. func[j] + sum (method. M[d][j] * bconref[d] for d in keys (method. M))
118115 )
119- lower_expr = JuMP. @expression (model, [i = 1 : con. set. dimension],
120- con. func[i ] - m_sum
116+ lower_expr = JuMP. @expression (model, [j = 1 : con. set. dimension],
117+ con. func[j ] - sum (method . M[d][j] * bconref[d] for d in keys (method . M))
121118 )
122- upper_con = JuMP. build_constraint (error, upper_expr,
119+ upper_con = JuMP. build_constraint (error, upper_expr,
123120 MOI. Nonnegatives (con. set. dimension)
124121 )
125- lower_con = JuMP. build_constraint (error, lower_expr,
122+ lower_con = JuMP. build_constraint (error, lower_expr,
126123 MOI. Nonpositives (con. set. dimension)
127124 )
128125 return [upper_con, lower_con]
@@ -156,25 +153,26 @@ function reformulate_disjunct_constraint(
156153 return [reform_con]
157154end
158155
156+ # Per-bound M values: method.M[d] = [M_lower, M_upper]
159157function reformulate_disjunct_constraint (
160158 model:: JuMP.AbstractModel ,
161159 con:: JuMP.ScalarConstraint{T, S} ,
162160 bconref:: Union {Dict{<: LogicalVariableRef ,<: JuMP.AbstractVariableRef },
163161 Dict{<: LogicalVariableRef ,<: JuMP.GenericAffExpr }},
164162 method:: _MBM
165163) where {T, S <: _MOI.EqualTo }
166- upper_func = JuMP. @expression (model,
167- con. func - sum (method. M[i] * bconref[i] for i in keys (method. M))
168- )
169- lower_func = JuMP. @expression (model,
170- con. func + sum (method. M[i] * bconref[i] for i in keys (method. M))
164+ lower_func = JuMP. @expression (model,
165+ con. func + sum (method. M[d][1 ] * bconref[d] for d in keys (method. M))
171166 )
172- upper_con = JuMP. build_constraint (error, upper_func,
173- MOI . LessThan (con . set . value )
167+ upper_func = JuMP. @expression (model,
168+ con . func - sum (method . M[d][ 2 ] * bconref[d] for d in keys (method . M) )
174169 )
175- lower_con = JuMP. build_constraint (error, lower_func,
170+ lower_con = JuMP. build_constraint (error, lower_func,
176171 MOI. GreaterThan (con. set. value)
177172 )
173+ upper_con = JuMP. build_constraint (error, upper_func,
174+ MOI. LessThan (con. set. value)
175+ )
178176 return [lower_con, upper_con]
179177end
180178
@@ -185,21 +183,19 @@ function reformulate_disjunct_constraint(
185183 Dict{<: LogicalVariableRef ,<: JuMP.GenericAffExpr }},
186184 method:: _MBM
187185) where {T, S <: _MOI.Interval }
188- set_values = _set_values (con. set)
189- upper_func = JuMP. @expression (model,
190- con. func - sum (method. M[i] * bconref[i ] for i in keys (method. M))
186+ set_values = _set_values (con. set)
187+ lower_func = JuMP. @expression (model,
188+ con. func + sum (method. M[d][ 1 ] * bconref[d ] for d in keys (method. M))
191189 )
192- upper_con = JuMP. build_constraint (error, upper_func,
193- MOI. LessThan (set_values[2 ])
194- )
195-
196- lower_func = JuMP. @expression (model,
197- con. func + sum (method. M[i] * bconref[i] for i in keys (method. M))
190+ upper_func = JuMP. @expression (model,
191+ con. func - sum (method. M[d][2 ] * bconref[d] for d in keys (method. M))
198192 )
199- lower_con = JuMP. build_constraint (error, lower_func,
193+ lower_con = JuMP. build_constraint (error, lower_func,
200194 MOI. GreaterThan (set_values[1 ])
201195 )
202-
196+ upper_con = JuMP. build_constraint (error, upper_func,
197+ MOI. LessThan (set_values[2 ])
198+ )
203199 return [lower_con, upper_con]
204200end
205201
@@ -219,65 +215,74 @@ end
219215# ###############################################################################
220216# Dispatches over constraint types to reformulate into >= or <=
221217# in order to solve the mini-model
218+ # Per-row M values for vector constraints: returns Vector{T}
222219function _maximize_M (
223- model:: JuMP.AbstractModel ,
224- objective:: JuMP.VectorConstraint{T, S, R} ,
225- constraints:: Vector{<:DisjunctConstraintRef} ,
220+ model:: JuMP.AbstractModel ,
221+ objective:: JuMP.VectorConstraint{T, S, R} ,
222+ constraints:: Vector{<:DisjunctConstraintRef} ,
226223 method:: _MBM
227224) where { T, S <: _MOI.Nonpositives , R}
228225 val_type = JuMP. value_type (typeof (model))
229- return maximum (
226+ return [
230227 _maximize_M (
231- model,
232- JuMP. ScalarConstraint (objective. func[i], MOI. LessThan (zero (val_type))),
233- constraints,
228+ model,
229+ JuMP. ScalarConstraint (objective. func[i], MOI. LessThan (zero (val_type))),
230+ constraints,
234231 method
235232 ) for i in 1 : objective. set. dimension
236- )
233+ ]
237234end
238235
239236function _maximize_M (
240- model:: JuMP.AbstractModel ,
241- objective:: JuMP.VectorConstraint{T, S, R} ,
242- constraints:: Vector{<:DisjunctConstraintRef} ,
237+ model:: JuMP.AbstractModel ,
238+ objective:: JuMP.VectorConstraint{T, S, R} ,
239+ constraints:: Vector{<:DisjunctConstraintRef} ,
243240 method:: _MBM
244241) where { T, S <: _MOI.Nonnegatives , R}
245242 val_type = JuMP. value_type (typeof (model))
246- return maximum (
243+ return [
247244 _maximize_M (
248- model,
249- JuMP. ScalarConstraint (objective. func[i], MOI. GreaterThan (zero (val_type))),
250- constraints,
245+ model,
246+ JuMP. ScalarConstraint (
247+ objective. func[i],
248+ MOI. GreaterThan (zero (val_type))
249+ ),
250+ constraints,
251251 method
252252 ) for i in 1 : objective. set. dimension
253- )
253+ ]
254254end
255255
256+ # For Zeros, each row is an equality: return per-row M = max(M_lower, M_upper)
256257function _maximize_M (
257- model:: JuMP.AbstractModel ,
258- objective:: JuMP.VectorConstraint{T, S, R} ,
259- constraints:: Vector{<:DisjunctConstraintRef} ,
258+ model:: JuMP.AbstractModel ,
259+ objective:: JuMP.VectorConstraint{T, S, R} ,
260+ constraints:: Vector{<:DisjunctConstraintRef} ,
260261 method:: _MBM
261262) where { T, S <: _MOI.Zeros , R}
262263 val_type = JuMP. value_type (typeof (model))
263- return max (
264- maximum (
264+ return [
265+ max (
265266 _maximize_M (
266- model,
267- JuMP. ScalarConstraint (objective. func[i],MOI. GreaterThan (zero (val_type))),
268- constraints,
267+ model,
268+ JuMP. ScalarConstraint (
269+ objective. func[i],
270+ MOI. GreaterThan (zero (val_type))
271+ ),
272+ constraints,
269273 method
270- ) for i in 1 : objective. set. dimension
271- ),
272- maximum (
274+ ),
273275 _maximize_M (
274- model,
275- JuMP. ScalarConstraint (objective. func[i], MOI. LessThan (zero (val_type))),
276- constraints,
276+ model,
277+ JuMP. ScalarConstraint (
278+ objective. func[i],
279+ MOI. LessThan (zero (val_type))
280+ ),
281+ constraints,
277282 method
278- ) for i in 1 : objective . set . dimension
279- )
280- )
283+ )
284+ ) for i in 1 : objective . set . dimension
285+ ]
281286end
282287
283288function _maximize_M (
@@ -289,56 +294,65 @@ function _maximize_M(
289294 return _mini_model (model, objective, constraints, method)
290295end
291296
297+ # Per-bound M values for bidirectional constraints: returns [M_lower, M_upper]
292298function _maximize_M (
293- model:: JuMP.AbstractModel ,
294- objective:: JuMP.ScalarConstraint{T, S} ,
295- constraints:: Vector{<:DisjunctConstraintRef} ,
299+ model:: JuMP.AbstractModel ,
300+ objective:: JuMP.ScalarConstraint{T, S} ,
301+ constraints:: Vector{<:DisjunctConstraintRef} ,
296302 method:: _MBM
297303) where {T, S <: _MOI.EqualTo }
298304 set_value = objective. set. value
299- return max (
300- _mini_model (
301- model,
302- JuMP. ScalarConstraint (objective. func, MOI. GreaterThan (set_value)),
303- constraints,
304- method
305- ),
306- _mini_model (
307- model,
308- JuMP. ScalarConstraint (objective. func, MOI. LessThan (set_value)),
309- constraints,
310- method
311- )
305+ M_lower = _mini_model (
306+ model,
307+ JuMP. ScalarConstraint (objective. func, MOI. GreaterThan (set_value)),
308+ constraints,
309+ method
310+ )
311+ M_upper = _mini_model (
312+ model,
313+ JuMP. ScalarConstraint (objective. func, MOI. LessThan (set_value)),
314+ constraints,
315+ method
312316 )
317+ return [M_lower, M_upper]
313318end
314319
315320function _maximize_M (
316- model:: JuMP.AbstractModel ,
317- objective:: JuMP.ScalarConstraint{T, S} ,
318- constraints:: Vector{<:DisjunctConstraintRef} ,
321+ model:: JuMP.AbstractModel ,
322+ objective:: JuMP.ScalarConstraint{T, S} ,
323+ constraints:: Vector{<:DisjunctConstraintRef} ,
319324 method:: _MBM
320325) where {T, S <: _MOI.Interval }
321326 set_values = _set_values (objective. set) # Returns (lower, upper)
322- return max (
323- _mini_model (
324- model,
325- JuMP. ScalarConstraint (objective. func, MOI. GreaterThan (set_values[1 ])),
326- constraints,
327- method
328- ),
329- _mini_model (
330- model,
331- JuMP. ScalarConstraint (objective. func, MOI. LessThan (set_values[2 ])),
332- constraints,
333- method
334- )
327+ M_lower = _mini_model (
328+ model,
329+ JuMP. ScalarConstraint (objective. func, MOI. GreaterThan (set_values[1 ])),
330+ constraints,
331+ method
335332 )
333+ M_upper = _mini_model (
334+ model,
335+ JuMP. ScalarConstraint (objective. func, MOI. LessThan (set_values[2 ])),
336+ constraints,
337+ method
338+ )
339+ return [M_lower, M_upper]
336340end
337341
342+ # Nested Disjunctions: M computation skipped, handler creates fresh MBM
338343function _maximize_M (
339- :: JuMP.AbstractModel ,
340- :: F ,
341- :: Vector{<:DisjunctConstraintRef} ,
344+ :: JuMP.AbstractModel ,
345+ :: Disjunction ,
346+ :: Vector{<:DisjunctConstraintRef} ,
347+ :: _MBM
348+ )
349+ return nothing
350+ end
351+
352+ function _maximize_M (
353+ :: JuMP.AbstractModel ,
354+ :: F ,
355+ :: Vector{<:DisjunctConstraintRef} ,
342356 :: _MBM
343357) where {F}
344358 error (" This type of constraints and objective constraint has " *
0 commit comments