Skip to content

Commit

Permalink
add isuniversal to interfaces and basic set types
Browse files Browse the repository at this point in the history
  • Loading branch information
schillic committed Nov 28, 2019
1 parent 31ffc1c commit 698deed
Show file tree
Hide file tree
Showing 22 changed files with 206 additions and 35 deletions.
3 changes: 3 additions & 0 deletions docs/src/lib/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ This interface defines the following functions:
```@docs
dim(::AbstractCentrallySymmetric)
isbounded(::AbstractCentrallySymmetric)
isuniversal(::AbstractCentrallySymmetric{N}, ::Bool=false) where {N<:Real}
an_element(::AbstractCentrallySymmetric{N}) where {N<:Real}
isempty(::AbstractCentrallySymmetric)
```
Expand All @@ -121,6 +122,7 @@ This interface defines the following functions:

```@docs
∈(::AbstractVector{N}, ::AbstractPolyhedron{N}) where {N<:Real}
isuniversal(::AbstractPolyhedron{N}, ::Bool=false) where {N<:Real}
constrained_dimensions(::AbstractPolyhedron)
linear_map(::AbstractMatrix{N}, ::AbstractPolyhedron{N}) where {N<:Real}
chebyshev_center(::AbstractPolyhedron{N}) where {N<:AbstractFloat}
Expand All @@ -147,6 +149,7 @@ This interface defines the following functions:

```@docs
isbounded(::AbstractPolytope)
isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real}
singleton_list(::AbstractPolytope{N}) where {N<:Real}
isempty(::AbstractPolytope)
```
Expand Down
21 changes: 20 additions & 1 deletion docs/src/lib/representations.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Inherited from [`AbstractCentrallySymmetric`](@ref):
* [`dim`](@ref dim(::AbstractCentrallySymmetric))
* [`isbounded`](@ref isbounded(::AbstractCentrallySymmetric))
* [`isempty`](@ref isempty(::AbstractCentrallySymmetric))
* [`isuniversal`](@ref isuniversal(::AbstractCentrallySymmetric{N}, ::Bool=false) where {N<:Real})
* [`an_element`](@ref an_element(::AbstractCentrallySymmetric{N}) where {N<:Real})

### Infinity norm ball
Expand All @@ -55,6 +56,7 @@ Inherited from [`LazySet`](@ref):

Inherited from [`AbstractPolytope`](@ref):
* [`isbounded`](@ref isbounded(::AbstractPolytope))
* [`isuniversal`](@ref isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real})
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})

Inherited from [`AbstractCentrallySymmetricPolytope`](@ref):
Expand Down Expand Up @@ -97,6 +99,7 @@ Inherited from [`LazySet`](@ref):

Inherited from [`AbstractPolytope`](@ref):
* [`isbounded`](@ref isbounded(::AbstractPolytope))
* [`isuniversal`](@ref isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real})
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})

Inherited from [`AbstractCentrallySymmetricPolytope`](@ref):
Expand All @@ -123,6 +126,7 @@ Inherited from [`AbstractCentrallySymmetric`](@ref):
* [`dim`](@ref dim(::AbstractCentrallySymmetric))
* [`isbounded`](@ref isbounded(::AbstractCentrallySymmetric))
* [`isempty`](@ref isempty(::AbstractCentrallySymmetric))
* [`isuniversal`](@ref isuniversal(::AbstractCentrallySymmetric{N}, ::Bool=false) where {N<:Real})
* [`an_element`](@ref an_element(::AbstractCentrallySymmetric{N}) where {N<:Real})

## Ellipsoid
Expand All @@ -145,6 +149,7 @@ Inherited from [`AbstractCentrallySymmetric`](@ref):
* [`dim`](@ref dim(::AbstractCentrallySymmetric))
* [`isbounded`](@ref isbounded(::AbstractCentrallySymmetric))
* [`isempty`](@ref isempty(::AbstractCentrallySymmetric))
* [`isuniversal`](@ref isuniversal(::AbstractCentrallySymmetric{N}, ::Bool=false) where {N<:Real})
* [`an_element`](@ref an_element(::AbstractCentrallySymmetric{N}) where {N<:Real})

## Empty set
Expand All @@ -160,6 +165,7 @@ an_element(::EmptySet)
rand(::Type{EmptySet})
isbounded(::EmptySet)
isempty(::EmptySet)
isuniversal(::EmptySet{N}, ::Bool=false) where {N<:Real}
norm(::EmptySet, ::Real=Inf)
radius(::EmptySet, ::Real=Inf)
diameter(::EmptySet, ::Real=Inf)
Expand Down Expand Up @@ -239,6 +245,7 @@ Inherited from [`LazySet`](@ref):

Inherited from [`AbstractPolytope`](@ref):
* [`isbounded`](@ref isbounded(::AbstractPolytope))
* [`isuniversal`](@ref isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real})
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})

Inherited from [`AbstractCentrallySymmetricPolytope`](@ref):
Expand Down Expand Up @@ -296,6 +303,7 @@ Inherited from [`LazySet`](@ref):

Inherited from [`AbstractPolytope`](@ref):
* [`isbounded`](@ref isbounded(::AbstractPolytope))
* [`isuniversal`](@ref isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real})
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})

Inherited from [`AbstractCentrallySymmetricPolytope`](@ref):
Expand Down Expand Up @@ -361,6 +369,7 @@ Inherited from [`LazySet`](@ref):

Inherited from [`AbstractPolytope`](@ref):
* [`isbounded`](@ref isbounded(::AbstractPolytope))
* [`isuniversal`](@ref isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real})

Inherited from [`AbstractCentrallySymmetricPolytope`](@ref):
* [`isempty`](@ref isempty(::AbstractCentrallySymmetricPolytope))
Expand All @@ -386,6 +395,7 @@ Inherited from [`LazySet`](@ref):

Inherited from [`AbstractPolytope`](@ref):
* [`isempty`](@ref isempty(::AbstractPolytope))
* [`isuniversal`](@ref isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real})
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})
* [`linear_map`](@ref linear_map(::AbstractMatrix{N}, ::AbstractPolyhedron{N}) where {N<:Real})

Expand Down Expand Up @@ -418,6 +428,7 @@ Inherited from [`LazySet`](@ref):

Inherited from [`AbstractPolytope`](@ref):
* [`isempty`](@ref isempty(::AbstractPolytope))
* [`isuniversal`](@ref isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real})
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})

Inherited from [`AbstractPolygon`](@ref):
Expand Down Expand Up @@ -459,6 +470,7 @@ Inherited from [`LazySet`](@ref):
Inherited from [`AbstractPolytope`](@ref):
* [`isbounded`](@ref isbounded(::AbstractPolytope))
* [`isempty`](@ref isempty(::AbstractPolytope))
* [`isuniversal`](@ref isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real})
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})
* [`linear_map`](@ref linear_map(::AbstractMatrix{N}, ::AbstractPolyhedron{N}) where {N<:Real})

Expand Down Expand Up @@ -527,6 +539,7 @@ isbounded(::HPolytope, ::Bool=true)

Inherited from [`AbstractPolytope`](@ref):
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})
* [`isuniversal`](@ref isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real})

#### Polyhedra

Expand All @@ -535,11 +548,13 @@ The following methods are specific for `HPolyhedron`.
```@docs
rand(::Type{HPolyhedron})
isbounded(::HPolyhedron)
isuniversal(::HPolyhedron{N}, ::Bool=false) where {N<:Real}
vertices_list(::HPolyhedron{N}) where {N<:Real}
singleton_list(::HPolyhedron{N}) where {N<:Real}
```

Inherited from [`AbstractPolyhedron`](@ref):
* [`isuniversal`](@ref isuniversal(::AbstractPolyhedron{N}, ::Bool=false) where {N<:Real})

### Vertex representation

```@docs
Expand All @@ -565,6 +580,7 @@ Inherited from [`LazySet`](@ref):
Inherited from [`AbstractPolytope`](@ref):
* [`isbounded`](@ref isbounded(::AbstractPolytope))
* [`isempty`](@ref isempty(::AbstractPolytope))
* [`isuniversal`](@ref isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real})
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})
* [`linear_map`](@ref linear_map(::AbstractMatrix{N}, ::AbstractPolyhedron{N}) where {N<:Real})

Expand Down Expand Up @@ -595,6 +611,7 @@ Inherited from [`LazySet`](@ref):

Inherited from [`AbstractPolytope`](@ref):
* [`isbounded`](@ref isbounded(::AbstractPolytope))
* [`isuniversal`](@ref isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real})
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})

Inherited from [`AbstractCentrallySymmetricPolytope`](@ref):
Expand Down Expand Up @@ -664,6 +681,7 @@ Inherited from [`LazySet`](@ref):

Inherited from [`AbstractPolytope`](@ref):
* [`isbounded`](@ref isbounded(::AbstractPolytope))
* [`isuniversal`](@ref isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real})
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})

Inherited from [`AbstractCentrallySymmetricPolytope`](@ref):
Expand Down Expand Up @@ -710,6 +728,7 @@ Inherited from [`LazySet`](@ref):

Inherited from [`AbstractPolytope`](@ref):
* [`isbounded`](@ref isbounded(::AbstractPolytope))
* [`isuniversal`](@ref isuniversal(::AbstractPolytope{N}, ::Bool=false) where {N<:Real})
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})

Inherited from [`AbstractCentrallySymmetricPolytope`](@ref):
Expand Down
32 changes: 32 additions & 0 deletions src/Interfaces/AbstractCentrallySymmetric.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,35 @@ Return if a centrally symmetric set is empty or not.
function isempty(::AbstractCentrallySymmetric)::Bool
return false
end

"""
isuniversal(S::AbstractCentrallySymmetric{N}, [witness]::Bool=false
)::Union{Bool, Tuple{Bool, Vector{N}}} where {N<:Real}
Check whether a centrally symmetric set is universal.
### Input
- `S` -- centrally symmetric set
- `witness` -- (optional, default: `false`) compute a witness if activated
### Output
* If `witness` option is deactivated: `false`
* If `witness` option is activated: `(false, v)` where ``v ∉ S``
### Algorithm
A witness is obtained by computing the support vector in direction
`d = [1, 0, …, 0]` and adding `d` on top.
"""
function isuniversal(S::AbstractCentrallySymmetric{N}, witness::Bool=false
)::Union{Bool, Tuple{Bool, Vector{N}}} where {N<:Real}
if witness
d = SingleEntryVector{N}(1, dim(S))
w = σ(d, S) + d
return (false, w)
else
return false
end
end
34 changes: 34 additions & 0 deletions src/Interfaces/AbstractPolyhedron_functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,40 @@ function ∈(x::AbstractVector{N}, P::AbstractPolyhedron{N})::Bool where {N<:Rea
return true
end

"""
isuniversal(P::AbstractPolyhedron{N}, [witness]::Bool=false
)::Union{Bool, Tuple{Bool, Vector{N}}} where {N<:Real}
Check whether a polyhedron is universal.
### Input
- `P` -- polyhedron
- `witness` -- (optional, default: `false`) compute a witness if activated
### Output
* If `witness` option is deactivated: `true` iff ``P`` is universal
* If `witness` option is activated:
* `(true, [])` iff ``P`` is universal
* `(false, v)` iff ``P`` is not universal and ``v ∉ P``
### Algorithm
`P` is universal iff it has no constraints.
A witness is produced using `isuniversal(H)` where `H` is the first linear
constraint of `P`.
"""
function isuniversal(P::AbstractPolyhedron{N}, witness::Bool=false
)::Union{Bool, Tuple{Bool, Vector{N}}} where {N<:Real}
if isempty(P.constraints)
return witness ? (true, N[]) : true
else
return witness ? isuniversal(constraints_list(P)[1], true) : false
end
end

"""
constrained_dimensions(P::AbstractPolyhedron)::Vector{Int} where {N<:Real}
Expand Down
26 changes: 26 additions & 0 deletions src/Interfaces/AbstractPolytope.jl
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,32 @@ function isempty(P::AbstractPolytope)::Bool
return isempty(vertices_list(P))
end

"""
isuniversal(P::AbstractPolytope{N}, [witness]::Bool=false
)::Union{Bool, Tuple{Bool, Vector{N}}} where {N<:Real}
Check whether a polyhedron is universal.
### Input
- `P` -- polyhedron
- `witness` -- (optional, default: `false`) compute a witness if activated
### Output
* If `witness` option is deactivated: `false`
* If `witness` option is activated: `(false, v)` where ``v ∉ P``
### Algorithm
A witness is produced using `isuniversal(H)` where `H` is the first linear
constraint of `P`.
"""
function isuniversal(P::AbstractPolytope{N}, witness::Bool=false
)::Union{Bool, Tuple{Bool, Vector{N}}} where {N<:Real}
return witness ? isuniversal(constraints_list(P)[1], true) : false
end

# given a polytope P, apply the linear map P to each vertex of P
# it is assumed that the interface function `vertices_list(P)` is available
@inline function _linear_map_vrep(M::AbstractMatrix{N}, P::AbstractPolytope{N}) where {N<:Real}
Expand Down
27 changes: 27 additions & 0 deletions src/Sets/EmptySet.jl
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,33 @@ function isbounded(::EmptySet)::Bool
return true
end

"""
isuniversal(∅::EmptySet{N}, [witness]::Bool=false
)::Union{Bool, Tuple{Bool, Vector{N}}} where {N<:Real}
Check whether an empty is universal.
### Input
- `∅` -- empty set
- `witness` -- (optional, default: `false`) compute a witness if activated
### Output
* If `witness` option is deactivated: `false`
* If `witness` option is activated: `(false, v)` where ``v ∉ S``, although
we currently throw an error
"""
function isuniversal(∅::EmptySet{N}, witness::Bool=false
)::Union{Bool, Tuple{Bool, Vector{N}}} where {N<:Real}
if witness
error("witness production is currently not supported")
# return (false, zeros(N, dim(∅))) # deactivated, see #1201
else
return false
end
end

"""
∈(x::AbstractVector{N}, ∅::EmptySet{N})::Bool where {N<:Real}
Expand Down
34 changes: 0 additions & 34 deletions src/Sets/HPolyhedron.jl
Original file line number Diff line number Diff line change
Expand Up @@ -215,40 +215,6 @@ function isbounded(P::HPolyhedron)::Bool
return isbounded_unit_dimensions(P)
end

"""
isuniversal(P::HPolyhedron{N}, [witness]::Bool=false
)::Union{Bool, Tuple{Bool, Vector{N}}} where {N<:Real}
Check whether a polyhedron is universal.
### Input
- `P` -- polyhedron
- `witness` -- (optional, default: `false`) compute a witness if activated
### Output
* If `witness` option is deactivated: `true` iff ``P`` is universal
* If `witness` option is activated:
* `(true, [])` iff ``P`` is universal
* `(false, v)` iff ``P`` is not universal and ``v ∉ P``
### Algorithm
`P` is universal iff it has no constraints.
A witness is produced using `isuniversal(H)` where `H` is the first linear
constraint of `P`.
"""
function isuniversal(P::HPolyhedron{N}, witness::Bool=false
)::Union{Bool, Tuple{Bool, Vector{N}}} where {N<:Real}
if isempty(P.constraints)
return witness ? (true, N[]) : true
else
return witness ? isuniversal(P.constraints[1], true) : false
end
end

"""
rand(::Type{HPolyhedron}; [N]::Type{<:Real}=Float64, [dim]::Int=2,
[rng]::AbstractRNG=GLOBAL_RNG, [seed]::Union{Int, Nothing}=nothing
Expand Down
4 changes: 4 additions & 0 deletions test/unit_Ball1.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ for N in [Float64, Rational{Int}, Float32]
# isempty
@test !isempty(b)

# isuniversal
answer, w = isuniversal(b, true)
@test !isuniversal(b) && !answer && w b

# an_element & membership function
@test an_element(b) b

Expand Down
4 changes: 4 additions & 0 deletions test/unit_Ball2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ for N in [Float64, Float32]
# isempty
@test !isempty(b)

# isuniversal
answer, w = isuniversal(b, true)
@test !isuniversal(b) && !answer && w b

# an_element function
b = Ball2(N[1, 2], N(2))
@test an_element(b) b
Expand Down
4 changes: 4 additions & 0 deletions test/unit_BallInf.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ for N in [Float64, Rational{Int}, Float32]
# isempty
@test !isempty(b)

# isuniversal
answer, w = isuniversal(b, true)
@test !isuniversal(b) && !answer && w b

# membership
b = BallInf(N[1, 1], N(1))
@test N[0.5, -0.5] b
Expand Down
Loading

0 comments on commit 698deed

Please sign in to comment.