Skip to content

Commit ea4c989

Browse files
committed
[Utilities] add distance_to_set for PositiveSemidefiniteCone
1 parent 3c19dec commit ea4c989

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

src/Utilities/distance_to_set.jl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,3 +489,39 @@ function distance_to_set(
489489
elements = [x[i] for i in eachindex(x) if !(i in pairs[k])]
490490
return LinearAlgebra.norm(elements, 2)
491491
end
492+
493+
function _reshape(x::AbstractVector, set::MOI.PositiveSemidefiniteConeSquare)
494+
n = MOI.side_dimension(set)
495+
return reshape(x, (n, n))
496+
end
497+
498+
function _reshape(x::AbstractVector, set::MOI.PositiveSemidefiniteConeTriangle)
499+
n = MOI.side_dimension(set)
500+
X = zeros(eltype(x), n, n)
501+
k = 1
502+
for i in 1:n
503+
for j in 1:i
504+
X[j,i] = X[i,j] = x[k]
505+
k += 1
506+
end
507+
end
508+
return LinearAlgebra.Symmetric(X)
509+
end
510+
511+
function distance_to_set(
512+
::ProjectionUpperBoundDistance,
513+
x::AbstractVector{T},
514+
set::Union{
515+
MOI.PositiveSemidefiniteConeSquare,
516+
MOI.PositiveSemidefiniteConeTriangle,
517+
},
518+
) where {T<:Real}
519+
_check_dimension(x, set)
520+
λ, U = LinearAlgebra.eigen(_reshape(x, set))
521+
if minimum(λ) >= 0
522+
return 0.0
523+
end
524+
λ_negative = LinearAlgebra.Diagonal(min.(zero(T), λ))
525+
A = LinearAlgebra.Symmetric(U * λ_negative * U')
526+
return LinearAlgebra.norm(A, 2)
527+
end

test/Utilities/distance_to_set.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,28 @@ function test_sos2()
308308
return
309309
end
310310

311+
function test_positivesemidefiniteconesquare()
312+
_test_set(
313+
MOI.PositiveSemidefiniteConeSquare(2),
314+
[1.0, 0.0, 0.0, 1.0] => 0.0,
315+
[1.0, -1.0, -1.0, 1.0] => 0.0,
316+
[1.0, -2.0, -2.0, 1.0] => 1.0;
317+
mismatch = [1.0],
318+
)
319+
return
320+
end
321+
322+
function test_positivesemidefiniteconetriangle()
323+
_test_set(
324+
MOI.PositiveSemidefiniteConeTriangle(2),
325+
[1.0, 0.0, 1.0] => 0.0,
326+
[1.0, -1.0, 1.0] => 0.0,
327+
[1.0, -2.0, 1.0] => 1.0;
328+
mismatch = [1.0],
329+
)
330+
return
331+
end
332+
311333
end
312334

313335
TestFeasibilityChecker.runtests()

0 commit comments

Comments
 (0)