Skip to content

Commit 5b9e114

Browse files
authored
Merge pull request #504 from JuliaOpt/bl/convert
Define convert
2 parents 6b237a3 + 22bacab commit 5b9e114

File tree

5 files changed

+81
-18
lines changed

5 files changed

+81
-18
lines changed

src/Test/UnitTests/objectives.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ function get_objective_function(model::MOI.ModelLike, config::TestConfig)
7878
end
7979
obj_fun = MOI.get(model, obj_attr)
8080
@test obj_fun expected_obj_fun
81+
quad_obj_attr = MOI.ObjectiveFunction{MOI.ScalarQuadraticFunction{Float64}}()
82+
quad_obj_fun = MOI.get(model, quad_obj_attr)
83+
@test convert(MOI.ScalarAffineFunction{Float64}, quad_obj_fun) expected_obj_fun
8184
end
8285
unittests["get_objective_function"] = get_objective_function
8386

src/Utilities/functions.jl

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,6 @@ end
9797
constant(f::Union{SAF, SQF}) = [f.constant]
9898
constant(f::Union{VAF, VQF}) = f.constants
9999

100-
# Define conversion SingleVariable -> ScalarAffineFunction and VectorOfVariables -> VectorAffineFunction{T}
101-
function SAF{T}(f::SVF) where T
102-
SAF([MOI.ScalarAffineTerm(one(T), f.variable)], zero(T))
103-
end
104-
function VAF{T}(f::VVF) where T
105-
n = length(f.variables)
106-
return VAF(map(i -> MOI.VectorAffineTerm(i, MOI.ScalarAffineTerm(one(T), f.variables[i])), 1:n), zeros(T, n))
107-
end
108-
109100
# Implements iterator interface
110101
"""
111102
scalar_type(F::Type{<:MOI.AbstractVectorFunction})

src/Utilities/model.jl

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -232,14 +232,7 @@ function MOI.get(model::AbstractModel, ::MOI.ObjectiveFunctionType)
232232
return MOI.typeof(model.objective)
233233
end
234234
function MOI.get(model::AbstractModel, ::MOI.ObjectiveFunction{T})::T where T
235-
if typeof(model.objective) != T
236-
if VERSION >= v"0.7-"
237-
throw(InexactError(:get, T, model.objective))
238-
else
239-
throw(InexactError())
240-
end
241-
end
242-
model.objective
235+
return model.objective
243236
end
244237
MOI.supports(model::AbstractModel, ::MOI.ObjectiveFunction) = true
245238
function MOI.set(model::AbstractModel, ::MOI.ObjectiveFunction, f::MOI.AbstractFunction)

src/functions.jl

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ function MultirowChange(variable::VariableIndex, new_coefficients::Vector{Tuple{
269269
MultirowChange(variable, [(convert(Int64, i), j) for (i,j) in new_coefficients])
270270
end
271271

272-
# Implementation of comparison for MOI functions
272+
# Implementation of comparison for functions
273273
Base.:(==)(f::VectorOfVariables, g::VectorOfVariables) = f.variables == g.variables
274274

275275
Base.isapprox(f::Union{SingleVariable, VectorOfVariables}, g::Union{SingleVariable, VectorOfVariables}; kwargs...) = f == g
@@ -369,3 +369,63 @@ Return a new quadratic function with a shallow copy of the terms and constant(s)
369369
from `func`.
370370
"""
371371
Base.copy(func::F) where {F <: Union{ScalarQuadraticFunction, VectorQuadraticFunction}} = F(copy(func.affine_terms), copy(func.quadratic_terms), copy(_constant(func)))
372+
373+
# Define shortcuts for
374+
# SingleVariable -> ScalarAffineFunction
375+
function ScalarAffineFunction{T}(f::SingleVariable) where T
376+
ScalarAffineFunction([ScalarAffineTerm(one(T), f.variable)], zero(T))
377+
end
378+
# VectorOfVariables -> VectorAffineFunction
379+
function VectorAffineFunction{T}(f::VectorOfVariables) where T
380+
n = length(f.variables)
381+
return VectorAffineFunction(map(i -> VectorAffineTerm(i, ScalarAffineTerm(one(T), f.variables[i])), 1:n), zeros(T, n))
382+
end
383+
384+
if VERSION < v"0.7-"
385+
isone(x) = x == one(x)
386+
end
387+
388+
# Conversion between scalar functions
389+
# Conversion to SingleVariable
390+
function Base.convert(::Type{SingleVariable}, f::ScalarAffineFunction)
391+
if !iszero(f.constant) || !isone(length(f.terms)) || !isone(f.terms[1].coefficient)
392+
if VERSION >= v"0.7-"
393+
throw(InexactError(:convert, SingleVariable, f))
394+
else
395+
throw(InexactError())
396+
end
397+
end
398+
return SingleVariable(f.terms[1].variable_index)
399+
end
400+
function Base.convert(::Type{SingleVariable},
401+
f::ScalarQuadraticFunction{T}) where T
402+
return convert(SingleVariable, convert(ScalarAffineFunction{T}, f))
403+
end
404+
405+
# Conversion to ScalarAffineFunction
406+
function Base.convert(::Type{ScalarAffineFunction{T}},
407+
f::SingleVariable) where T
408+
return ScalarAffineFunction{T}(f)
409+
end
410+
function Base.convert(::Type{ScalarAffineFunction{T}},
411+
f::ScalarQuadraticFunction{T}) where T
412+
if !Base.isempty(f.quadratic_terms)
413+
if VERSION >= v"0.7-"
414+
throw(InexactError(:convert, ScalarAffineFunction{T}, f))
415+
else
416+
throw(InexactError())
417+
end
418+
end
419+
return ScalarAffineFunction{T}(f.affine_terms, f.constant)
420+
end
421+
422+
# Conversion to ScalarQuadraticFunction
423+
function Base.convert(::Type{ScalarQuadraticFunction{T}},
424+
f::SingleVariable) where T
425+
convert(ScalarQuadraticFunction{T}, convert(ScalarAffineFunction{T}, f))
426+
end
427+
function Base.convert(::Type{ScalarQuadraticFunction{T}},
428+
f::ScalarAffineFunction{T}) where T
429+
return ScalarQuadraticFunction{T}(f.terms, ScalarQuadraticTerm{T}[],
430+
f.constant)
431+
end

test/functions.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,15 @@
191191
end
192192
f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([2, 4], [x, y]),
193193
5)
194+
@testset "convert" begin
195+
@test_throws InexactError convert(MOI.SingleVariable, f)
196+
quad_f = MOI.ScalarQuadraticFunction(f.terms,
197+
MOI.ScalarQuadraticTerm{Int}[],
198+
f.constant)
199+
@test convert(MOI.ScalarQuadraticFunction{Int}, f) quad_f
200+
g = convert(MOI.ScalarAffineFunction{Float64}, MOI.SingleVariable(x))
201+
@test convert(MOI.SingleVariable, g) == MOI.SingleVariable(x)
202+
end
194203
@testset "operate" begin
195204
f = MOIU.canonical(MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([1, 3, 1, 2, -3, 2],
196205
[w, y, w, x, x, z]), 2) +
@@ -253,6 +262,13 @@
253262
@test MOIU.isapprox_zero(g, 1e-5)
254263
@test !MOIU.isapprox_zero(g, 1e-7)
255264
end
265+
@testset "convert" begin
266+
@test_throws InexactError convert(MOI.SingleVariable, f)
267+
@test_throws InexactError convert(MOI.ScalarAffineFunction{Int},
268+
f)
269+
g = convert(MOI.ScalarQuadraticFunction{Float64}, fx)
270+
@test convert(MOI.SingleVariable, g) == fx
271+
end
256272
@testset "operate" begin
257273
@test f 7 + (fx + 2fy) * (1fx + fy) + 3fx
258274
@test f 7 + MOIU.operate(*, Int, fx, fx) + 3fx * (fy + 1) + 2fy * fy

0 commit comments

Comments
 (0)