diff --git a/docs/src/submodules/Utilities/reference.md b/docs/src/submodules/Utilities/reference.md index b5df0f6361..ccbeeb24ea 100644 --- a/docs/src/submodules/Utilities/reference.md +++ b/docs/src/submodules/Utilities/reference.md @@ -113,6 +113,7 @@ Utilities.set_index Utilities.set_types Utilities.add_set Utilities.rows +Utilities.set_with_dimension ``` ```@docs diff --git a/src/Utilities/matrix_of_constraints.jl b/src/Utilities/matrix_of_constraints.jl index cee2305cc1..aa0ecbfe6b 100644 --- a/src/Utilities/matrix_of_constraints.jl +++ b/src/Utilities/matrix_of_constraints.jl @@ -525,8 +525,53 @@ end function_constants(b::Vector, rows) = b[rows] -# FIXME does not work for all sets -set_from_constants(::Vector, ::Type{S}, rows) where {S} = S(length(rows)) +""" + set_with_dimension(::Type{S}, dim) where {S<:MOI.AbstractVectorSet} + +Returns the instance of `S` of [`MathOptInterface.dimension`](@ref) `dim`. +This needs to be implemented for sets of type `S` to be useable with +[`MatrixOfConstraints`](@ref). +""" +function set_with_dimension(::Type{S}, dim) where {S<:MOI.AbstractVectorSet} + return S(dim) +end + +function set_with_dimension( + ::Type{S}, + dim, +) where {S<:MOI.AbstractSymmetricMatrixSetTriangle} + side_dimension = side_dimension_for_vectorized_dimension(dim) + return S(side_dimension) +end + +function set_with_dimension( + ::Type{S}, + dim, +) where {S<:MOI.AbstractSymmetricMatrixSetSquare} + return S(isqrt(dim)) +end + +function set_with_dimension(::Type{MOI.LogDetConeTriangle}, dim) + side_dimension = side_dimension_for_vectorized_dimension(dim - 2) + return MOI.LogDetConeTriangle(side_dimension) +end + +function set_with_dimension(::Type{MOI.LogDetConeSquare}, dim) + return MOI.LogDetConeSquare(isqrt(dim - 2)) +end + +function set_with_dimension(::Type{MOI.RootDetConeTriangle}, dim) + side_dimension = side_dimension_for_vectorized_dimension(dim - 1) + return MOI.RootDetConeTriangle(side_dimension) +end + +function set_with_dimension(::Type{MOI.RootDetConeSquare}, dim) + return MOI.RootDetConeSquare(isqrt(dim - 1)) +end + +function set_from_constants(::Vector, ::Type{S}, rows) where {S} + return set_with_dimension(S, length(rows)) +end function MOI.get( model::MatrixOfConstraints, diff --git a/test/Utilities/matrix_of_constraints.jl b/test/Utilities/matrix_of_constraints.jl index 9b0d6bc864..d130ca662d 100644 --- a/test/Utilities/matrix_of_constraints.jl +++ b/test/Utilities/matrix_of_constraints.jl @@ -398,6 +398,51 @@ function test_multicone() return end +MOI.Utilities.@product_of_sets( + MatrixSets, + MOI.PositiveSemidefiniteConeTriangle, + MOI.PositiveSemidefiniteConeSquare, + MOI.LogDetConeTriangle, + MOI.LogDetConeSquare, + MOI.RootDetConeTriangle, + MOI.RootDetConeSquare, +) + +function test_matrix_sets(::Type{T} = Int) where {T} + model = MOI.Utilities.GenericOptimizer{ + T, + MOI.Utilities.ObjectiveContainer{T}, + MOI.Utilities.VariablesContainer{T}, + MOI.Utilities.MatrixOfConstraints{ + T, + MOI.Utilities.MutableSparseMatrixCSC{ + T, + T, + MOI.Utilities.OneBasedIndexing, + }, + Vector{T}, + MatrixSets{T}, + }, + }() + function test_set(set) + MOI.empty!(model) + func = MOI.Utilities.zero_with_output_dimension( + MOI.VectorAffineFunction{T}, + MOI.dimension(set), + ) + ci = MOI.add_constraint(model, func, set) + MOI.Utilities.final_touch(model, nothing) + @test MOI.get(model, MOI.ConstraintSet(), ci) == set + end + test_set(MOI.PositiveSemidefiniteConeTriangle(2)) + test_set(MOI.PositiveSemidefiniteConeSquare(2)) + test_set(MOI.LogDetConeTriangle(2)) + test_set(MOI.LogDetConeSquare(2)) + test_set(MOI.RootDetConeTriangle(2)) + test_set(MOI.RootDetConeSquare(2)) + return +end + end TestMatrixOfConstraints.runtests()