@@ -241,27 +241,64 @@ function simplify!(::Val{:*}, f::MOI.ScalarNonlinearFunction)
241
241
return f
242
242
end
243
243
244
+ # The MOI.Utilities.operate!(+, T, x, y) methods do not cope with mixed input
245
+ # types. However, ScalarNonlinearFunction can hold various <:Real coefficient
246
+ # types.
247
+ _add_to! (x:: Real , y:: Real ) = x + y
248
+
249
+ _add_to! (x:: Real , y:: MOI.ScalarAffineFunction{<:Real} ) = _add_to! (y, x)
250
+
251
+ function _add_to! (x:: MOI.ScalarAffineFunction{T} , y:: T ) where {T<: Real }
252
+ return MOI. Utilities. operate! (+ , T, x, y)
253
+ end
254
+
255
+ function _add_to! (x:: MOI.ScalarAffineFunction{S} , y:: T ) where {S<: Real ,T<: Real }
256
+ U = promote_type (S, T)
257
+ F = MOI. ScalarAffineFunction{U}
258
+ return MOI. Utilities. operate! (+ , U, convert (F, x), convert (U, y))
259
+ end
260
+
261
+ function _add_to! (
262
+ x:: MOI.ScalarAffineFunction{T} ,
263
+ y:: MOI.ScalarAffineFunction{T} ,
264
+ ) where {T<: Real }
265
+ return MOI. Utilities. operate! (+ , T, x, y)
266
+ end
267
+
268
+ function _add_to! (
269
+ x:: MOI.ScalarAffineFunction{S} ,
270
+ y:: MOI.ScalarAffineFunction{T} ,
271
+ ) where {S<: Real ,T<: Real }
272
+ U = promote_type (S, T)
273
+ F = MOI. ScalarAffineFunction{U}
274
+ return MOI. Utilities. operate! (+ , U, convert (F, x), convert (F, y))
275
+ end
276
+
244
277
function simplify! (:: Val{:+} , f:: MOI.ScalarNonlinearFunction )
245
278
new_args = Any[]
246
- first_constant = 0
279
+ first_affine_term = 0
247
280
for arg in f. args
248
281
if _isexpr (arg, :+ )
249
282
# If a child is a :+, lift its arguments to the parent
250
283
append! (new_args, arg. args)
251
284
elseif _iszero (arg)
252
285
# Skip any zero arguments
253
- elseif arg isa Real
254
- # Collect all constant arguments into a single value
255
- if first_constant == 0
286
+ elseif arg isa Real || arg isa MOI . ScalarAffineFunction{ <: Real }
287
+ # Collect all affine arguments into a single value
288
+ if first_affine_term == 0
256
289
push! (new_args, arg)
257
- first_constant = length (new_args)
290
+ first_affine_term = length (new_args)
258
291
else
259
- new_args[first_constant] += arg
292
+ new_args[first_affine_term] =
293
+ _add_to! (new_args[first_affine_term], arg)
260
294
end
261
295
else
262
296
push! (new_args, arg)
263
297
end
264
298
end
299
+ if first_affine_term != = 0 && ! (new_args[first_affine_term] isa Real)
300
+ MOI. Utilities. canonicalize! (new_args[first_affine_term])
301
+ end
265
302
if length (new_args) == 0
266
303
# +() -> false
267
304
return false
0 commit comments