diff --git a/Project.toml b/Project.toml index f2bd7daec..133ffb0ed 100644 --- a/Project.toml +++ b/Project.toml @@ -26,7 +26,7 @@ GenericLinearAlgebra = "0.3" IterativeSolvers = "0.9" LinearMaps = "3" LowRankOpt = "0.2" -MathOptInterface = "1" +MathOptInterface = "1.20" PolynomialRoots = "1" Requires = "1" SpecialFunctions = "2" diff --git a/examples/JuMP_utils.jl b/examples/JuMP_utils.jl index 7be32ad4d..5ab7c643c 100644 --- a/examples/JuMP_utils.jl +++ b/examples/JuMP_utils.jl @@ -25,7 +25,7 @@ MOIU.@model( MOI.SecondOrderCone, MOI.RotatedSecondOrderCone, MOI.ExponentialCone, - MOI.PositiveSemidefiniteConeTriangle, + MOI.Scaled{MOI.PositiveSemidefiniteConeTriangle}, ), (), (), @@ -45,7 +45,7 @@ MOIU.@model( MOI.Nonnegatives, MOI.Nonpositives, MOI.ExponentialCone, - MOI.PositiveSemidefiniteConeTriangle, + MOI.Scaled{MOI.PositiveSemidefiniteConeTriangle}, ), (), (), diff --git a/src/MathOptInterface/cones.jl b/src/MathOptInterface/cones.jl index 8afa862a1..572ccf434 100644 --- a/src/MathOptInterface/cones.jl +++ b/src/MathOptInterface/cones.jl @@ -22,7 +22,7 @@ end function cone_from_moi( ::Type{T}, - cone::MOI.PositiveSemidefiniteConeTriangle, + cone::MOI.Scaled{MOI.PositiveSemidefiniteConeTriangle}, ) where {T <: Real} return Cones.PosSemidefTri{T, T}(MOI.dimension(cone)) end @@ -77,7 +77,10 @@ function cone_from_moi(::Type{T}, cone::MOI.GeometricMeanCone) where {T <: Real} return (l = MOI.dimension(cone) - 1; Cones.HypoGeoMean{T}(1 + l)) end -function cone_from_moi(::Type{T}, cone::MOI.RootDetConeTriangle) where {T <: Real} +function cone_from_moi( + ::Type{T}, + cone::MOI.Scaled{MOI.RootDetConeTriangle}, +) where {T <: Real} return Cones.HypoRootdetTri{T, T}(MOI.dimension(cone)) end @@ -89,7 +92,10 @@ function cone_from_moi(::Type{T}, cone::MOI.DualExponentialCone) where {T <: Rea return Cones.HypoPerLog{T}(3, use_dual = true) end -function cone_from_moi(::Type{T}, cone::MOI.LogDetConeTriangle) where {T <: Real} +function cone_from_moi( + ::Type{T}, + cone::MOI.Scaled{MOI.LogDetConeTriangle}, +) where {T <: Real} return Cones.HypoPerLogdetTri{T, T}(MOI.dimension(cone)) end @@ -795,7 +801,7 @@ const HypatiaCones{T <: Real} = Union{ const SupportedCone{T <: Real} = Union{ HypatiaCones{T}, MOI.Nonnegatives, - MOI.PositiveSemidefiniteConeTriangle, + MOI.Scaled{MOI.PositiveSemidefiniteConeTriangle}, MOI.HermitianPositiveSemidefiniteConeTriangle, MOI.NormInfinityCone, MOI.NormOneCone, @@ -806,10 +812,10 @@ const SupportedCone{T <: Real} = Union{ MOI.PowerCone{T}, MOI.DualPowerCone{T}, MOI.GeometricMeanCone, - MOI.RootDetConeTriangle, + MOI.Scaled{MOI.RootDetConeTriangle}, MOI.ExponentialCone, MOI.DualExponentialCone, - MOI.LogDetConeTriangle, + MOI.Scaled{MOI.LogDetConeTriangle}, MOI.RelativeEntropyCone, _PrimalRankOnePSD{T}, _DualRankOnePSD{T}, diff --git a/src/MathOptInterface/transform.jl b/src/MathOptInterface/transform.jl index d8e6b98c9..002b58313 100644 --- a/src/MathOptInterface/transform.jl +++ b/src/MathOptInterface/transform.jl @@ -48,46 +48,6 @@ function permute_affine(cone::SpecNucCone, func::VAF{T}) where {T} return idxs_new end -# transformations (svec rescaling) for MOI symmetric matrix cones not -# in svec (scaled lower triangle) form -const SvecCone = Union{ - MOI.PositiveSemidefiniteConeTriangle, - MOI.LogDetConeTriangle, - MOI.RootDetConeTriangle, -} - -svec_offset(::MOI.PositiveSemidefiniteConeTriangle) = 1 -svec_offset(::MOI.RootDetConeTriangle) = 2 -svec_offset(::MOI.LogDetConeTriangle) = 3 - -needs_untransform(::SvecCone) = true - -function untransform_affine(cone::SvecCone, vals::AbstractVector{T}) where {T} - @views svec_vals = vals[svec_offset(cone):end] - Cones.scale_svec!(svec_vals, inv(sqrt(T(2)))) - return vals -end - -needs_rescale(::SvecCone) = true - -function rescale_affine(cone::SvecCone, vals::AbstractVector{T}) where {T} - @views svec_vals = vals[svec_offset(cone):end] - Cones.scale_svec!(svec_vals, sqrt(T(2))) - return vals -end - -function rescale_affine(cone::SvecCone, func::VAF{T}, vals::AbstractVector{T}) where {T} - scal_start = svec_offset(cone) - 1 - rt2 = sqrt(T(2)) - for i in eachindex(vals) - k = func.terms[i].output_index - scal_start - if k > 0 && !MOI.Utilities.is_diagonal_vectorized_index(k) - vals[i] *= rt2 - end - end - return vals -end - # transformation (svec rescaling and real/imag parts reordering) for MOI Hermitian PSD cone not in svec (scaled upper triangle) form needs_untransform(::MOI.HermitianPositiveSemidefiniteConeTriangle) = true diff --git a/test/moicones.jl b/test/moicones.jl index 9815081c5..7d8d255b9 100644 --- a/test/moicones.jl +++ b/test/moicones.jl @@ -22,7 +22,7 @@ function test_moi_cones(T::Type{<:Real}) # MOI predefined cones @testset "PositiveSemidefiniteConeTriangle" begin - moi_cone = MOI.PositiveSemidefiniteConeTriangle(3) + moi_cone = MOI.Scaled(MOI.PositiveSemidefiniteConeTriangle(3)) hyp_cone = Hypatia.cone_from_moi(T, moi_cone) @test hyp_cone isa Cones.PosSemidefTri{T, T} @test MOI.dimension(moi_cone) == Cones.dimension(hyp_cone) == 6 @@ -114,7 +114,7 @@ function test_moi_cones(T::Type{<:Real}) end @testset "RootDetConeTriangle" begin - moi_cone = MOI.RootDetConeTriangle(3) + moi_cone = MOI.Scaled(MOI.RootDetConeTriangle(3)) hyp_cone = Hypatia.cone_from_moi(T, moi_cone) @test hyp_cone isa Cones.HypoRootdetTri{T, T} @test MOI.dimension(moi_cone) == Cones.dimension(hyp_cone) == 7 @@ -138,7 +138,7 @@ function test_moi_cones(T::Type{<:Real}) end @testset "LogDetConeTriangle" begin - moi_cone = MOI.LogDetConeTriangle(3) + moi_cone = MOI.Scaled(MOI.LogDetConeTriangle(3)) hyp_cone = Hypatia.cone_from_moi(T, moi_cone) @test hyp_cone isa Cones.HypoPerLogdetTri{T, T} @test MOI.dimension(moi_cone) == Cones.dimension(hyp_cone) == 8