Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add distance between point and set to API #3722

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/src/lib/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ volume(::LazySet)

```@docs
affine_map(::AbstractMatrix, ::LazySet, ::AbstractVector)
distance(::AbstractVector, ::LazySet)
exponential_map(::AbstractMatrix, ::LazySet)
∈(::AbstractVector, ::LazySet)
is_interior_point(::AbstractVector, ::LazySet)
Expand Down
2 changes: 1 addition & 1 deletion docs/src/lib/interfaces/AbstractHyperrectangle.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ CurrentModule = LazySets
```
```@docs
volume(::AbstractHyperrectangle)
distance(::AbstractVector, ::AbstractHyperrectangle{N}; ::Real=N(2)) where {N}
```
```@meta
CurrentModule = LazySets.API
Expand Down Expand Up @@ -239,6 +238,7 @@ CurrentModule = LazySets.API
* [`high`](@ref high(::LazySet, ::Int))
* [`low`](@ref low(::LazySet))
* [`low`](@ref low(::LazySet, ::Int))
* [`distance`](@ref distance(::AbstractVector, ::LazySet))
* [`project`](@ref project(::LazySet, ::AbstractVector{Int}))
* [`ρ`](@ref ρ(::AbstractVector, ::LazySet))
* [`cartesian_product`](@ref cartesian_product(::LazySet, ::LazySet))
Expand Down
1 change: 1 addition & 0 deletions docs/src/lib/sets/BallInf.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ Inherited from [`AbstractZonotope`](@ref):

Inherited from [`AbstractHyperrectangle`](@ref):
* [`constraints_list`](@ref constraints_list(::AbstractHyperrectangle))
* [`distance`](@ref distance(::AbstractVector, ::AbstractHyperrectangle))
* [`extrema`](@ref extrema(::AbstractHyperrectangle))
* [`extrema`](@ref extrema(::AbstractHyperrectangle, ::Int))
* [`generators`](@ref generators(::AbstractHyperrectangle))
Expand Down
1 change: 1 addition & 0 deletions docs/src/lib/sets/EmptySet.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ Undocumented implementations:
* [`vertices_list`](@ref vertices_list(::LazySet))
* [`vertices`](@ref vertices(::LazySet))
* [`volume`](@ref volume(::LazySet))
* [`distance`](@ref distance(::AbstractVector, ::LazySet))
* [`exponential_map`](@ref exponential_map(::AbstractMatrix, ::LazySet))
* [`∈`](@ref ∈(::AbstractVector, ::LazySet))
* [`is_interior_point`](@ref is_interior_point(::AbstractVector, ::LazySet))
Expand Down
2 changes: 1 addition & 1 deletion docs/src/lib/sets/HalfSpace.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ rand(::Type{HalfSpace})
remove_redundant_constraints(::AbstractVector{<:HalfSpace})
remove_redundant_constraints!(::AbstractVector{<:HalfSpace})
tosimplehrep(::AbstractVector{<:HalfSpace})
distance(::AbstractVector, ::HalfSpace)
```
```@meta
CurrentModule = LazySets.API
Expand Down Expand Up @@ -170,6 +169,7 @@ Undocumented implementations:
* [`isbounded`](@ref isbounded(::LazySet))
* [`isempty`](@ref isempty(::LazySet))
* [`isoperationtype`](@ref isoperationtype(::Type{LazySet}))
* [`distance`](@ref distance(::AbstractVector, ::LazySet))
* [`permute`](@ref permute(::LazySet, ::AbstractVector{Int}))

```@meta
Expand Down
2 changes: 1 addition & 1 deletion docs/src/lib/sets/Hyperplane.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ CurrentModule = LazySets.HyperplaneModule
```
```@docs
rand(::Type{Hyperplane})
distance(::AbstractVector, ::Hyperplane)
```
```@meta
CurrentModule = LazySets.API
Expand Down Expand Up @@ -134,6 +133,7 @@ Undocumented implementations:
* [`dim`](@ref dim(::LazySet))
* [`isempty`](@ref isempty(::LazySet))
* [`isoperationtype`](@ref isoperationtype(::Type{LazySet}))
* [`distance`](@ref distance(::AbstractVector, ::LazySet))
* [`project`](@ref project(::LazySet, ::AbstractVector{Int}))
* [`isdisjoint`](@ref isdisjoint(::LazySet, ::LazySet))

Expand Down
2 changes: 1 addition & 1 deletion docs/src/lib/sets/Hyperrectangle.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ Inherited from [`AbstractHyperrectangle`](@ref):
* [`reflect`](@ref reflect(::AbstractHyperrectangle))
* [`vertices_list`](@ref vertices_list(::AbstractHyperrectangle))
* [`volume`](@ref volume(::AbstractHyperrectangle))
* [`distance`](@ref distance(::AbstractVector, ::AbstractHyperrectangle{N}; ::Real=N(2)) where {N})
* [`distance`](@ref distance(::AbstractVector, ::AbstractHyperrectangle))
* [`∈`](@ref ∈(::AbstractVector, ::AbstractHyperrectangle))
* [`project`](@ref project(::AbstractHyperrectangle, ::AbstractVector{Int}))
* [`split`](@ref split(::AbstractHyperrectangle, ::AbstractVector{Int}))
Expand Down
2 changes: 1 addition & 1 deletion docs/src/lib/sets/Line.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ CurrentModule = LazySets.LineModule
```
```@docs
rand(::Type{Line})
distance(::AbstractVector, ::Line; ::Real=2.0)
```
```@meta
CurrentModule = LazySets.API
Expand Down Expand Up @@ -86,6 +85,7 @@ Undocumented implementations:
* [`isbounded`](@ref isbounded(::LazySet))
* [`isempty`](@ref isempty(::LazySet))
* [`isoperationtype`](@ref isoperationtype(::Type{LazySet}))
* [`distance`](@ref distance(::AbstractVector, ::LazySet))
* [`project`](@ref project(::LazySet, ::AbstractVector{Int}))
* [`ρ`](@ref ρ(::AbstractVector, ::LazySet))
* [`σ`](@ref σ(::AbstractVector, ::LazySet))
Expand Down
9 changes: 5 additions & 4 deletions src/API/API.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export
low, norm, radius, rectify, reflect, surface, vertices_list, vertices,
volume,
# mixed set operations (typically with vectors or matrices)
affine_map, exponential_map, is_interior_point, linear_map, permute,
project, sample, scale!, scale, support_function, ρ, support_vector, σ,
translate!, translate,
affine_map, distance, exponential_map, is_interior_point, linear_map,
permute, project, sample, scale!, scale, support_function, ρ,
support_vector, σ, translate!, translate,
# binary set operations
cartesian_product, difference, distance, exact_sum, intersection,
cartesian_product, difference, exact_sum, intersection,
is_intersection_empty, isequivalent, ⊂, linear_combination,
minkowski_difference, pontryagin_difference, minkowski_sum

Expand Down Expand Up @@ -64,6 +64,7 @@ include("Unary/vertices.jl")
include("Unary/volume.jl")

include("Mixed/affine_map.jl")
include("Mixed/distance.jl")
include("Mixed/exponential_map.jl")
include("Mixed/in.jl")
include("Mixed/is_interior_point.jl")
Expand Down
6 changes: 3 additions & 3 deletions src/API/Binary/distance.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ A real number representing the distance between `X` and `Y`.

### Notes

The standard distance is zero if the sets intersect and otherwise the ``p``-norm
of the shortest line segment between any pair of points. Formally,
The standard distance is zero if the sets intersect, and infinite if one of the sets is empty.
Otherwise, it is the ``p``-norm of the shortest line segment between any pair of points. Formally,

```math
\\inf_{x ∈ H_1, y ∈ H_2} \\{ d(x, y) \\}.
\\inf_{x ∈ X, y ∈ Y} \\{ d(x, y) \\}.
```
"""
function distance(::LazySet, ::LazySet; p::Real=2) end
27 changes: 27 additions & 0 deletions src/API/Mixed/distance.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""
distance(x::AbstractVector, X::LazySet; [p]::Real=2)
distance(X::LazySet, x::AbstractVector; [p]::Real=2)

Compute the standard distance (induced by the ``p``-norm) between a point and a set.

### Input

- `x` -- point/vector
- `X` -- set
- `p` -- (optional; default: `2`) value of the ``p``-norm

### Output

A real number representing the distance between `x` and `X`.

### Notes

The standard distance is zero if the point lies inside the set, and infinite if the set is empty.
Otherwise, it is the ``p``-norm of the shortest line segment between the point and any other point
in the set. Formally,

```math
\\inf_{y ∈ X} \\{ d(x, y) \\}.
```
"""
function distance(::AbstractVector, ::LazySet; p::Real=2) end
20 changes: 2 additions & 18 deletions src/Interfaces/AbstractHyperrectangle.jl
Original file line number Diff line number Diff line change
Expand Up @@ -591,24 +591,7 @@ function project(H::AbstractHyperrectangle, block::AbstractVector{Int};
return Hyperrectangle(πc, πr; check_bounds=false)
end

"""
distance(x::AbstractVector, H::AbstractHyperrectangle{N};
[p]::Real=N(2)) where {N}

Compute the distance between a point `x` and a hyperrectangular set `H` with
respect to the given `p`-norm.

### Input

- `x` -- point/vector
- `H` -- hyperrectangular set

### Output

A scalar representing the distance between point `x` and hyperrectangle `H`.
"""
@commutative function distance(x::AbstractVector, H::AbstractHyperrectangle{N};
p::Real=N(2)) where {N}
@commutative function distance(x::AbstractVector, H::AbstractHyperrectangle; p::Real=2)
@assert length(x) == dim(H) "a vector of length $(length(x)) is " *
"incompatible with a set of dimension $(dim(H))"

Expand All @@ -631,6 +614,7 @@ A scalar representing the distance between point `x` and hyperrectangle `H`.

if !outside
# point is inside
N = promote_type(eltype(x), eltype(H))
return zero(N)
end

Expand Down
1 change: 1 addition & 0 deletions src/Sets/EmptySet/EmptySetModule.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ using Reexport, Requires

using ..LazySets: LazySet, ConvexSet, _witness_result_empty
using Random: AbstractRNG, GLOBAL_RNG
using ReachabilityBase.Commutative: @commutative
using ReachabilityBase.Comparison: _rtol
using ReachabilityBase.Distribution: reseed!
using ReachabilityBase.Iteration: EmptyIterator
Expand Down
11 changes: 11 additions & 0 deletions src/Sets/EmptySet/distance.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# distance point <-> set

@commutative function distance(x::AbstractVector, ∅::EmptySet; p::Real=2)
@assert length(x) == dim(∅) "incompatible dimensions $(length(x)) and $(dim(∅))"

N = promote_type(eltype(x), eltype(∅))
return N(Inf)
end

# distance set <-> set

function distance(∅₁::EmptySet, ∅₂::EmptySet; p::Real=2.0)
return _distance_emptyset(∅₁, ∅₂; p=p)
end
Expand Down
19 changes: 5 additions & 14 deletions src/Sets/HalfSpace/distance.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
"""
distance(x::AbstractVector, H::HalfSpace)
@commutative function distance(x::AbstractVector, H::HalfSpace; p::Real=2)
@assert length(x) == dim(H) "incompatible dimensions $(length(x)) and $(dim(H))"

Compute the distance between point `x` and half-space `H` with respect to the
Euclidean norm.
if p != 2
throw(ArgumentError("`distance` is only implemented for Euclidean norm"))
end

### Input

- `x` -- vector
- `H` -- half-space

### Output

A scalar representing the distance between point `x` and half-space `H`.
"""
@commutative function distance(x::AbstractVector, H::HalfSpace)
N = promote_type(eltype(x), eltype(H))
a, b = _normalize_halfspace(H, N(2))
return max(dot(x, a) - b, zero(N))
Expand Down
19 changes: 5 additions & 14 deletions src/Sets/Hyperplane/distance.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
"""
distance(x::AbstractVector, H::Hyperplane)
@commutative function distance(x::AbstractVector, H::Hyperplane; p::Real=2)
@assert length(x) == dim(H) "incompatible dimensions $(length(x)) and $(dim(H))"

Compute the distance between point `x` and hyperplane `H` with respect to the
Euclidean norm.
if p != 2
throw(ArgumentError("`distance` is only implemented for Euclidean norm"))
end

### Input

- `x` -- vector
- `H` -- hyperplane

### Output

A scalar representing the distance between point `x` and hyperplane `H`.
"""
@commutative function distance(x::AbstractVector, H::Hyperplane)
N = promote_type(eltype(x), eltype(H))
a, b = _normalize_halfspace(H, N(2))
return abs(dot(x, a) - b)
Expand Down
19 changes: 2 additions & 17 deletions src/Sets/Line/distance.jl
Original file line number Diff line number Diff line change
@@ -1,21 +1,6 @@
"""
distance(x::AbstractVector, L::Line; [p]::Real=2.0)
@commutative function distance(x::AbstractVector, L::Line; p::Real=2)
@assert length(x) == dim(L) "incompatible dimensions $(length(x)) and $(dim(L))"

Compute the distance between point `x` and the line with respect to the given
`p`-norm.

### Input

- `x` -- point/vector
- `L` -- line
- `p` -- (optional, default: `2.0`) the `p`-norm used; `p = 2.0` corresponds to
the usual Euclidean norm

### Output

A scalar representing the distance between `x` and the line `L`.
"""
@commutative function distance(x::AbstractVector, L::Line; p::Real=2.0)
d = L.d # direction of the line
t = dot(x - L.p, d) / dot(d, d)
return distance(x, L.p + t * d; p=p)
Expand Down
2 changes: 1 addition & 1 deletion test/API.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ end
for f in (permute, project, translate!, translate)
@test isnothing(f(X, v))
end
for f in (is_interior_point, ∈, support_function, ρ, support_vector, σ)
for f in (distance, is_interior_point, ∈, support_function, ρ, support_vector, σ)
@test isnothing(f(v, X))
end
M = hcat(1)
Expand Down
9 changes: 8 additions & 1 deletion test/Sets/EmptySet.jl
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ for N in [Float64, Rational{Int}, Float32]
E2 = affine_map(ones(N, 3, 2), E, N[1, 1, 3])
@test E2 isa EmptySet{N} && dim(E2) == 3

# distance (between point and set)
@test_throws AssertionError distance(E, N[0])
x = N[0, 0]
for res in (distance(E, x), distance(E, x))
@test res isa N && res == N(Inf)
end

# exponential_map / linear_map
for f in (exponential_map, linear_map)
@test_throws AssertionError f(ones(N, 2, 3), E)
Expand Down Expand Up @@ -231,7 +238,7 @@ for N in [Float64, Rational{Int}, Float32]
E2 = difference(B, E)
@test E2 isa BallInf{N} && E2 == B

# distance
# distance (between sets)
res = distance(E, E)
@test res isa N && res == N(Inf)
E2 = EmptySet{N}(3)
Expand Down
Loading