Skip to content

Commit 47f281f

Browse files
authored
Merge pull request #800 from JuliaOpt/bl/operate_typed
Fix operator overload with SingleVariable
2 parents b40a397 + a6f58e4 commit 47f281f

File tree

2 files changed

+47
-13
lines changed

2 files changed

+47
-13
lines changed

src/Utilities/functions.jl

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,11 @@ const ScalarQuadraticLike{T} = Union{ScalarAffineLike{T}, MOI.ScalarQuadraticFun
710710
# avoid overloading e.g. `+(::Float64, ::Float64)`
711711
const ScalarLike{T} = Union{MOI.SingleVariable, MOI.ScalarAffineFunction{T},
712712
MOI.ScalarQuadraticFunction{T}}
713+
# `ScalarLike` for which `T` is defined to avoid defining, e.g.,
714+
# `+(::SingleVariable, ::Any)` which should rather be
715+
# `+(::SingleVariable, ::Number)`.
716+
const TypedScalarLike{T} = Union{MOI.ScalarAffineFunction{T},
717+
MOI.ScalarQuadraticFunction{T}}
713718

714719
# Functions convertible to a VectorAffineFunction
715720
const VectorAffineLike{T} = Union{Vector{T}, MOI.VectorOfVariables, MOI.VectorAffineFunction{T}}
@@ -905,21 +910,34 @@ end
905910
function Base.:+(arg::ScalarLike{T}, args::ScalarLike{T}...) where T
906911
return operate(+, T, arg, args...)
907912
end
908-
function Base.:+::T, arg::ScalarLike{T}, args::ScalarLike{T}...) where T
913+
function Base.:+::T, arg::TypedScalarLike{T}, args::ScalarLike{T}...) where T
909914
return operate(+, T, α, arg, args...)
910915
end
911-
function Base.:+(f::ScalarLike{T}, α::T) where T
916+
function Base.:+::Number, f::MOI.SingleVariable)
917+
return operate(+, typeof(α), α, f)
918+
end
919+
function Base.:+(f::TypedScalarLike{T}, α::T) where T
912920
return operate(+, T, f, α)
913921
end
922+
function Base.:+(f::MOI.SingleVariable, α::Number)
923+
return operate(+, typeof(α), f, α)
924+
end
914925
function Base.:-(arg::ScalarLike{T}, args::ScalarLike{T}...) where T
915926
return operate(-, T, arg, args...)
916927
end
917-
function Base.:-(f::ScalarLike{T}, α::T) where T
928+
function Base.:-(f::TypedScalarLike{T}, α::T) where T
918929
return operate(-, T, f, α)
919930
end
920-
function Base.:-::T, f::ScalarLike{T}) where T
931+
function Base.:-(f::MOI.SingleVariable, α::Number)
932+
return operate(-, typeof(α), f, α)
933+
end
934+
function Base.:-::T, f::TypedScalarLike{T}) where T
921935
return operate(-, T, α, f)
922936
end
937+
function Base.:-::Number, f::MOI.SingleVariable)
938+
return operate(-, typeof(α), α, f)
939+
end
940+
923941

924942
# Vector +/-
925943
###############################################################################
@@ -1150,7 +1168,10 @@ function operate!(::typeof(*), ::Type{T}, f::MOI.SingleVariable, α::T) where T
11501168
return operate(*, T, α, f)
11511169
end
11521170
function operate(::typeof(*), ::Type{T}, α::T, f::MOI.SingleVariable) where T
1153-
MOI.ScalarAffineFunction{T}([MOI.ScalarAffineTerm(α, f.variable)], zero(T))
1171+
return MOI.ScalarAffineFunction{T}([MOI.ScalarAffineTerm(α, f.variable)], zero(T))
1172+
end
1173+
function operate(::typeof(*), ::Type{T}, f::MOI.SingleVariable, α::T) where T
1174+
return operate(*, T, α, f)
11541175
end
11551176

11561177
function operate!(::typeof(*), ::Type{T},
@@ -1223,15 +1244,23 @@ function operate(::typeof(*), ::Type{T}, f::MOI.ScalarAffineFunction{T},
12231244
return MOI.ScalarQuadraticFunction(aff_terms, quad_terms, constant)
12241245
end
12251246

1226-
function Base.:*(args::ScalarLike{T}...) where T
1227-
return operate(*, T, args...)
1247+
# To avoid type piracy, we add at least one `ScalarLike` outside of the `...`.
1248+
function Base.:*(arg::ScalarLike{T}, args::ScalarLike{T}...) where T
1249+
return operate(*, T, arg, args...)
12281250
end
1229-
function Base.:*(f::T, g::ScalarLike{T}) where T
1251+
function Base.:*(f::T, g::TypedScalarLike{T}) where T
12301252
return operate(*, T, f, g)
12311253
end
1232-
function Base.:*(f::ScalarLike{T}, g::T) where T
1254+
function Base.:*(f::Number, g::MOI.SingleVariable)
1255+
return operate(*, typeof(f), f, g)
1256+
end
1257+
function Base.:*(f::TypedScalarLike{T}, g::T) where T
12331258
return operate(*, T, g, f)
12341259
end
1260+
function Base.:*(f::MOI.SingleVariable, g::Number)
1261+
return operate(*, typeof(g), f, g)
1262+
end
1263+
12351264

12361265
####################################### / ######################################
12371266
function promote_operation(::typeof(/), ::Type{T},
@@ -1278,12 +1307,12 @@ function operate(::typeof(/), ::Type{T},
12781307
return operate!(/, T, copy(f), α)
12791308
end
12801309

1281-
function Base.:/(args::ScalarLike{T}...) where T
1282-
return operate(/, T, args...)
1283-
end
1284-
function Base.:/(f::ScalarLike{T}, g::T) where T
1310+
function Base.:/(f::TypedScalarLike{T}, g::T) where T
12851311
return operate(/, T, f, g)
12861312
end
1313+
function Base.:/(f::MOI.SingleVariable, g::Number)
1314+
return operate(/, typeof(g), f, g)
1315+
end
12871316

12881317
## sum
12891318
function operate(::typeof(sum), ::Type{T}, vis::Vector{MOI.VariableIndex}) where T

test/Utilities/functions.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,11 @@ end
199199
g = MOI.SingleVariable(MOI.VariableIndex(1))
200200
@test !iszero(f)
201201
@test !iszero(g)
202+
@test f + 1 1 + f
203+
@test (f + 1.0) - 1.0 (2.0f) / 2.0
204+
@test (f - 1.0) + 1.0 (2.0f) / 2.0
205+
@test (1.0 + f) - 1.0 (f * 2.0) / 2.0
206+
@test 1.0 - (1.0 - f) (f / 2.0) * 2.0
202207
end
203208
end
204209
@testset "Affine" begin

0 commit comments

Comments
 (0)