diff --git a/src/Utilities/functions.jl b/src/Utilities/functions.jl index 2d558f92e4..ed9884088b 100644 --- a/src/Utilities/functions.jl +++ b/src/Utilities/functions.jl @@ -2226,29 +2226,7 @@ Returns the vector of scalar quadratic functions in the form of a function vectorize( funcs::AbstractVector{MOI.ScalarQuadraticFunction{T}}, ) where {T} - num_affine_terms = - mapreduce(func -> number_of_affine_terms(T, func), +, funcs, init = 0) - num_quadratic_terms = mapreduce( - func -> number_of_quadratic_terms(T, func), - +, - funcs, - init = 0, - ) - out_dim = mapreduce(func -> output_dim(T, func), +, funcs, init = 0) - affine_terms = Vector{MOI.VectorAffineTerm{T}}(undef, num_affine_terms) - quadratic_terms = - Vector{MOI.VectorQuadraticTerm{T}}(undef, num_quadratic_terms) - constant = zeros(T, out_dim) - fill_vector(affine_terms, T, fill_terms, number_of_affine_terms, funcs) - fill_vector( - quadratic_terms, - T, - fill_terms, - number_of_quadratic_terms, - funcs, - ) - fill_vector(constant, T, fill_constant, output_dim, funcs) - return MOI.VectorQuadraticFunction(quadratic_terms, affine_terms, constant) + return MOI.VectorQuadraticFunction(funcs) end function vectorize(x::AbstractVector{MOI.ScalarNonlinearFunction}) diff --git a/src/functions.jl b/src/functions.jl index b6193e0192..f99e33b2a1 100644 --- a/src/functions.jl +++ b/src/functions.jl @@ -679,6 +679,26 @@ struct VectorQuadraticFunction{T} <: AbstractVectorFunction constants::Vector{T} end +function VectorQuadraticFunction( + rows::AbstractVector{ScalarQuadraticFunction{T}}, +) where {T} + ret = VectorQuadraticFunction{T}( + VectorQuadraticTerm{T}[], + VectorAffineTerm{T}[], + T[], + ) + for (idx, f) in enumerate(rows) + push!(ret.constants, f.constant) + for term in f.quadratic_terms + push!(ret.quadratic_terms, VectorQuadraticTerm(idx, term)) + end + for term in f.affine_terms + push!(ret.affine_terms, VectorAffineTerm(idx, term)) + end + end + return ret +end + output_dimension(f::VectorQuadraticFunction) = length(f.constants) constant(f::VectorQuadraticFunction) = f.constants diff --git a/test/functions.jl b/test/functions.jl index d6143d161b..e3cd3e3c83 100644 --- a/test/functions.jl +++ b/test/functions.jl @@ -7,6 +7,8 @@ module TestFunctions using Test +import LinearAlgebra + import MathOptInterface as MOI """ @@ -129,6 +131,31 @@ function test_functions_convert_ScalarQuadraticFunction() ) end +function test_VectorQuadraticFunction_constructor() + x = MOI.VariableIndex.(1:2) + expr1 = + LinearAlgebra.dot(1.0 * x, x) + LinearAlgebra.dot([2.0, 3.0], x) + 4.2 + expr2 = + LinearAlgebra.dot(3.0 * x, x) + LinearAlgebra.dot([1.0, 3.0], x) + 1.2 + f = MOI.VectorQuadraticFunction([expr1, expr2]) + f_vec = MOI.Utilities.vectorize([expr1, expr2]) + @test f ≈ f_vec + @test MOI.output_dimension(f) == 2 + @test f.constants == [4.2, 1.2] + @test f.quadratic_terms == [ + MOI.VectorQuadraticTerm(1, MOI.ScalarQuadraticTerm(2.0, x[1], x[1])), + MOI.VectorQuadraticTerm(1, MOI.ScalarQuadraticTerm(2.0, x[2], x[2])), + MOI.VectorQuadraticTerm(2, MOI.ScalarQuadraticTerm(6.0, x[1], x[1])), + MOI.VectorQuadraticTerm(2, MOI.ScalarQuadraticTerm(6.0, x[2], x[2])), + ] + @test f.affine_terms == [ + MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(2.0, x[1])), + MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(3.0, x[2])), + MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x[1])), + MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(3.0, x[2])), + ] +end + function test_isapprox_VectorOfVariables() x = MOI.VariableIndex(1) y = MOI.VariableIndex(2)