diff --git a/src/Utilities/distance_to_set.jl b/src/Utilities/distance_to_set.jl index 045bfddebc..be2cb9f191 100644 --- a/src/Utilities/distance_to_set.jl +++ b/src/Utilities/distance_to_set.jl @@ -579,3 +579,32 @@ function distance_to_set( set.eval_f(y, x) return LinearAlgebra.norm(y .- clamp.(y, set.l, set.u)) end + +# This is the minimal L2-norm. +function distance_to_set( + distance::ProjectionUpperBoundDistance, + x::AbstractVector{T}, + set::MOI.Indicator{MOI.ACTIVATE_ON_ONE}, +) where {T<:Real} + _check_dimension(x, set) + return min( + # Distance of x[1] from 0 + abs(x[1]), + # Distance of x[1] from 1 + distance to set + sqrt((1 - x[1])^2 + distance_to_set(distance, x[2], set.set)^2), + ) +end + +function distance_to_set( + distance::ProjectionUpperBoundDistance, + x::AbstractVector{T}, + set::MOI.Indicator{MOI.ACTIVATE_ON_ZERO}, +) where {T} + _check_dimension(x, set) + return min( + # Distance of x[1] from 1 + abs(one(T) - x[1]), + # Distance of x[1] from 0 + distance to set + sqrt(x[1]^2 + distance_to_set(distance, x[2], set.set)^2), + ) +end diff --git a/test/Utilities/distance_to_set.jl b/test/Utilities/distance_to_set.jl index 411b1cfd71..2db868afa3 100644 --- a/test/Utilities/distance_to_set.jl +++ b/test/Utilities/distance_to_set.jl @@ -376,6 +376,30 @@ function test_vectornonlinearoracle() return end +function test_indicator() + _test_set( + MOI.Indicator{MOI.ACTIVATE_ON_ZERO}(MOI.EqualTo(1.0)), + [0.0, 1.0] => 0.0, + [0.01, 1.0] => 0.01, + [-0.01, 1.0] => 0.01, + [-0.01, 1.1] => sqrt(0.01^2 + 0.1^2), + [0.5, 1.1] => 0.5, + [0.2, 1.1] => sqrt(0.2^2 + 0.1^2); + mismatch = [1.0], + ) + _test_set( + MOI.Indicator{MOI.ACTIVATE_ON_ONE}(MOI.EqualTo(1.0)), + [1.0, 1.0] => 0.0, + [1.01, 1.0] => 0.01, + [0.99, 1.0] => 0.01, + [0.99, 1.1] => sqrt(0.01^2 + 0.1^2), + [0.5, 1.1] => 0.5, + [0.8, 1.1] => sqrt(0.2^2 + 0.1^2), + mismatch = [1.0], + ) + return +end + end TestFeasibilityChecker.runtests()