Skip to content

Commit 0057d65

Browse files
authored
Add support for - in convert (#2987)
1 parent f604fc1 commit 0057d65

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

src/functions.jl

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,9 +1086,27 @@ end
10861086

10871087
_add_to_function(::ScalarAffineFunction, ::Any) = nothing
10881088

1089-
# This is a very rough-and-ready conversion function that only works for very
1090-
# basic expressions, such as those created by
1091-
# `convert(ScalarNonlinearFunction, f)`.
1089+
function _to_scalar_affine(::Type{ScalarAffineFunction{T}}, x::Real) where {T}
1090+
return ScalarAffineFunction{T}(ScalarAffineTerm{T}[], T(x))
1091+
end
1092+
1093+
function _to_scalar_affine(
1094+
::Type{ScalarAffineFunction{T}},
1095+
x::VariableIndex,
1096+
) where {T}
1097+
return ScalarAffineFunction{T}(x)
1098+
end
1099+
1100+
function _to_scalar_affine(
1101+
::Type{ScalarAffineFunction{T}},
1102+
f::ScalarNonlinearFunction,
1103+
) where {T}
1104+
return convert(ScalarAffineFunction{T}, f)
1105+
end
1106+
1107+
# This conversion function handles expressions created by
1108+
# `convert(ScalarNonlinearFunction, f)` and also expressions using `:+`, `:-`,
1109+
# and `:*` operators with affine structure.
10921110
function Base.convert(
10931111
::Type{ScalarAffineFunction{T}},
10941112
f::ScalarNonlinearFunction,
@@ -1097,6 +1115,15 @@ function Base.convert(
10971115
term = convert(ScalarAffineTerm{T}, f)
10981116
return ScalarAffineFunction{T}([term], zero(T))
10991117
end
1118+
if f.head == :- && length(f.args) == 2
1119+
lhs = _to_scalar_affine(ScalarAffineFunction{T}, f.args[1])
1120+
rhs = _to_scalar_affine(ScalarAffineFunction{T}, f.args[2])
1121+
return Utilities.operate(-, T, lhs, rhs)
1122+
end
1123+
if f.head == :- && length(f.args) == 1
1124+
inner = _to_scalar_affine(ScalarAffineFunction{T}, f.args[1])
1125+
return Utilities.operate(-, T, inner)
1126+
end
11001127
if f.head != :+
11011128
throw(InexactError(:convert, ScalarAffineFunction{T}, f))
11021129
end

test/General/test_functions.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,17 @@ function test_convert_ScalarNonlinearFunction_ScalarAffineFunction()
371371
convert(MOI.ScalarAffineFunction{Float64}, f_error),
372372
)
373373
end
374+
# Test :- support (binary subtraction and unary negation)
375+
f_sub = MOI.ScalarNonlinearFunction(:-, Any[x, 1.0])
376+
@test convert(MOI.ScalarAffineFunction{Float64}, f_sub) 1.0 * x - 1.0
377+
f_sub2 = MOI.ScalarNonlinearFunction(
378+
:-,
379+
Any[MOI.ScalarNonlinearFunction(:+, Any[x, y]), 2.0],
380+
)
381+
@test convert(MOI.ScalarAffineFunction{Float64}, f_sub2)
382+
1.0 * x + 1.0 * y - 2.0
383+
f_neg = MOI.ScalarNonlinearFunction(:-, Any[x])
384+
@test convert(MOI.ScalarAffineFunction{Float64}, f_neg) -1.0 * x
374385
return
375386
end
376387

0 commit comments

Comments
 (0)