diff --git a/docs/src/lib/representations.md b/docs/src/lib/representations.md index 2fb1848ebc..612e96e4fe 100644 --- a/docs/src/lib/representations.md +++ b/docs/src/lib/representations.md @@ -24,6 +24,18 @@ support_function support_vector ``` +## LazySet interfaces + +```@docs +AbstractSingleton +AbstractHPolygon +AbstractPolygon +AbstractHyperrectangle +AbstractPointSymmetric +AbstractPolytope +AbstractPointSymmetricPolytope +``` + ## Balls ### Euclidean norm ball @@ -33,6 +45,7 @@ Ball2 dim(::Ball2) σ(::AbstractVector{Float64}, ::Ball2) ∈(::AbstractVector{Float64}, ::Ball2{Float64}) +center(::Ball2{Float64}) ``` ### Infinity norm ball @@ -40,12 +53,16 @@ dim(::Ball2) ```@docs BallInf dim(::BallInf) -σ(::AbstractVector{Float64}, ::BallInf) -vertices_list(::BallInf) +σ(::AbstractVector{Float64}, ::BallInf{Float64}) +∈(::AbstractVector{Float64}, ::BallInf{Float64}) norm(::BallInf, ::Real=Inf) radius(::BallInf, ::Real=Inf) diameter(::BallInf, ::Real=Inf) -∈(::AbstractVector{Float64}, ::BallInf{Float64}) +vertices_list(::BallInf{Float64}) +singleton_list(::BallInf{Float64}) +center(::BallInf{Float64}) +radius_hyperrectangle(::BallInf{Float64}) +radius_hyperrectangle(::BallInf{Float64}, ::Int) ``` ### Manhattan norm ball @@ -53,8 +70,11 @@ diameter(::BallInf, ::Real=Inf) ```@docs Ball1 dim(::Ball1) -σ(::AbstractVector{Float64}, ::Ball1) +σ(::AbstractVector{Float64}, ::Ball1{Float64}) ∈(::AbstractVector{Float64}, ::Ball1{Float64}) +vertices_list(::Ball1{Float64}) +singleton_list(::Ball1{Float64}) +center(::Ball1{Float64}) ``` ### p-norm ball @@ -64,6 +84,7 @@ Ballp dim(::Ballp) σ(::AbstractVector{Float64}, ::Ballp) ∈(::AbstractVector{Float64}, ::Ballp{Float64}) +center(::Ballp{Float64}) ``` ## Polygons @@ -72,24 +93,28 @@ dim(::Ballp) ```@docs HPolygon -addconstraint!(::HPolygon{Float64}, ::LinearConstraint{Float64}) dim(::HPolygon) -σ(::AbstractVector{Float64}, ::HPolygon) +σ(::AbstractVector{Float64}, ::HPolygon{Float64}) ∈(::AbstractVector{Float64}, ::HPolygon{Float64}) -tovrep(::HPolygon) -vertices_list(::HPolygon) +vertices_list(::HPolygon{Float64}) +singleton_list(::HPolygon{Float64}) +tohrep(::HPolygon{Float64}) +tovrep(::HPolygon{Float64}) +addconstraint!(::HPolygon{Float64}, ::LinearConstraint{Float64}) ``` ### Optimized constraint representation ```@docs HPolygonOpt -addconstraint!(::HPolygonOpt{Float64}, ::LinearConstraint{Float64}) dim(::HPolygonOpt) σ(::AbstractVector{Float64}, ::HPolygonOpt{Float64}) ∈(::AbstractVector{Float64}, ::HPolygonOpt{Float64}) -tovrep(::HPolygonOpt) -vertices_list(::HPolygonOpt) +vertices_list(::HPolygonOpt{Float64}) +singleton_list(::HPolygonOpt{Float64}) +tohrep(::HPolygonOpt{Float64}) +tovrep(::HPolygonOpt{Float64}) +addconstraint!(::HPolygonOpt{Float64}, ::LinearConstraint{Float64}) ``` ### Vertex representation @@ -97,10 +122,12 @@ vertices_list(::HPolygonOpt) ```@docs VPolygon dim(::VPolygon) -σ(::AbstractVector{Float64}, ::VPolygon) -vertices_list(::VPolygon) -singleton_list(::VPolygon) +σ(::AbstractVector{Float64}, ::VPolygon{Float64}) ∈(::AbstractVector{Float64}, ::VPolygon{Float64}) +vertices_list(::VPolygon{Float64}) +singleton_list(::VPolygon{Float64}) +tohrep(::VPolygon{Float64}) +tovrep(::VPolygon{Float64}) ``` ## Lines and linear constraints @@ -117,12 +144,16 @@ intersection(::Line{Float64}, L2::Line{Float64}) Hyperrectangle Hyperrectangle(;kwargs...) dim(::Hyperrectangle) -σ(::AbstractVector{Float64}, ::Hyperrectangle) -vertices_list(::Hyperrectangle) +σ(::AbstractVector{Float64}, ::Hyperrectangle{Float64}) +∈(::AbstractVector{Float64}, ::Hyperrectangle{Float64}) norm(::Hyperrectangle, ::Real=Inf) radius(::Hyperrectangle, ::Real=Inf) diameter(::Hyperrectangle, ::Real=Inf) -∈(::AbstractVector{Float64}, ::Hyperrectangle{Float64}) +vertices_list(::Hyperrectangle{Float64}) +singleton_list(::Hyperrectangle{Float64}) +center(::Hyperrectangle{Float64}) +radius_hyperrectangle(::Hyperrectangle{Float64}) +radius_hyperrectangle(::Hyperrectangle{Float64}, ::Int) high(::Hyperrectangle) low(::Hyperrectangle) ``` @@ -136,23 +167,42 @@ dim(::EmptySet) ∈(::AbstractVector{Float64}, ::EmptySet) ``` -## ZeroSet - -```@docs -ZeroSet -dim(::ZeroSet) -σ(::AbstractVector{Float64}, ::ZeroSet) -∈(::AbstractVector{Float64}, ::ZeroSet) -``` - ## Singletons ```@docs Singleton dim(::Singleton) -σ(::AbstractVector{Float64}, ::Singleton) +σ(::AbstractVector{Float64}, ::Singleton{Float64}) ∈(::AbstractVector{Float64}, ::Singleton{Float64}) ⊆(::Singleton, ::LazySet) +norm(::Singleton, ::Real=Inf) +diameter(::Singleton, ::Real=Inf) +vertices_list(::Singleton{Float64}) +singleton_list(::Singleton{Float64}) +center(::Singleton{Float64}) +radius_hyperrectangle(::Singleton{Float64}) +radius_hyperrectangle(::Singleton{Float64}, ::Int) +element(::Singleton{Float64}) +element(::Singleton{Float64}, ::Int) +``` + +### ZeroSet + +```@docs +ZeroSet +dim(::ZeroSet) +σ(::AbstractVector{Float64}, ::ZeroSet) +∈(::AbstractVector{Float64}, ::ZeroSet{Float64}) +⊆(::ZeroSet, ::LazySet) +norm(::ZeroSet, ::Real=Inf) +diameter(::ZeroSet, ::Real=Inf) +vertices_list(::ZeroSet{Float64}) +singleton_list(::ZeroSet{Float64}) +center(::ZeroSet{Float64}) +radius_hyperrectangle(::ZeroSet{Float64}) +radius_hyperrectangle(::ZeroSet{Float64}, ::Int) +element(::ZeroSet{Float64}) +element(::ZeroSet{Float64}, ::Int) ``` ## Zonotopes @@ -160,8 +210,10 @@ dim(::Singleton) ```@docs Zonotope dim(::Zonotope) -σ(d::AbstractVector{Float64}, Z::Zonotope) +σ(::AbstractVector{Float64}, Z::Zonotope) +∈(::AbstractVector{Float64}, ::Zonotope{Float64}) +center(::Zonotope{Float64}) vertices_list(::Zonotope{Float64}) +singleton_list(::Zonotope{Float64}) order(::Zonotope) -∈(::AbstractVector{Float64}, ::Zonotope{Float64}) ``` diff --git a/src/AbstractHPolygon.jl b/src/AbstractHPolygon.jl new file mode 100644 index 0000000000..ad4e4a5d72 --- /dev/null +++ b/src/AbstractHPolygon.jl @@ -0,0 +1,160 @@ +import Base.∈ + +export AbstractHPolygon, + addconstraint! + +""" + AbstractHPolygon{N<:Real} <: AbstractPolygon{N} + +Abstract type for polygons in H-representation (i.e., constraints). + +### Notes + +Every concrete `AbstractHPolygon` must have the following fields: +- `constraints_list::Vector{LinearConstraint{N}}` -- the constraints + +```jldoctest +julia> subtypes(AbstractHPolygon) +2-element Array{Union{DataType, UnionAll},1}: + LazySets.HPolygon + LazySets.HPolygonOpt +``` +""" +abstract type AbstractHPolygon{N<:Real} <: AbstractPolygon{N} end + + +# --- AbstractPolygon interface functions --- + + +""" + tovrep(P::AbstractHPolygon{N})::VPolygon{N} where {N<:Real} + +Build a vertex representation of the given polygon. + +### Input + +- `P` -- polygon in constraint representation + +### Output + +The same polygon but in vertex representation, a `VPolygon`. +""" +function tovrep(P::AbstractHPolygon{N})::VPolygon{N} where {N<:Real} + return VPolygon(vertices_list(P)) +end + + +""" + tohrep(P::AbstractHPolygon{N})::AbstractHPolygon{N} where {N<:Real} + +Build a contraint representation of the given polygon. + +### Input + +- `P` -- polygon in constraint representation + +### Output + +The identity, i.e., the same polygon instance. +""" +function tohrep(P::AbstractHPolygon{N})::AbstractHPolygon{N} where {N<:Real} + return P +end + + +# --- AbstractPolytope interface functions --- + + +""" + vertices_list(P::AbstractHPolygon{N})::Vector{Vector{N}} where {N<:Real} + +Return the list of vertices of a polygon in constraint representation. + +### Input + +- `P` -- polygon in constraint representation + +### Output + +List of vertices. +""" +function vertices_list(P::AbstractHPolygon{N} + )::Vector{Vector{N}} where {N<:Real} + n = length(P.constraints_list) + points = Vector{Vector{N}}(n) + if n == 0 + return points + end + @inbounds for i in 1:n-1 + points[i] = intersection(Line(P.constraints_list[i]), + Line(P.constraints_list[i+1])) + end + points[n] = intersection(Line(P.constraints_list[n]), + Line(P.constraints_list[1])) + return points +end + + +# --- LazySet interface functions --- + + +""" + ∈(x::AbstractVector{N}, P::AbstractHPolygon{N})::Bool where {N<:Real} + +Check whether a given 2D point is contained in a polygon in constraint +representation. + +### Input + +- `x` -- two-dimensional point/vector +- `P` -- polygon in constraint representation + +### Output + +`true` iff ``x ∈ P``. + +### Algorithm + +This implementation checks if the point lies on the outside of each edge. +""" +function ∈(x::AbstractVector{N}, P::AbstractHPolygon{N})::Bool where {N<:Real} + @assert length(x) == 2 + + for c in P.constraints_list + if dot(c.a, x) > c.b + return false + end + end + return true +end + + +# --- common AbstractHPolygon functions --- + + +""" + addconstraint!(P::AbstractHPolygon{N}, + constraint::LinearConstraint{N})::Void where {N<:Real} + +Add a linear constraint to a polygon in constraint representation, keeping the +constraints sorted by their normal directions. + +### Input + +- `P` -- polygon in constraint representation +- `constraint` -- linear constraint to add + +### Output + +Nothing. +""" +function addconstraint!(P::AbstractHPolygon{N}, + constraint::LinearConstraint{N})::Void where {N<:Real} + i = length(P.constraints_list) + while i > 0 && constraint.a <= P.constraints_list[i].a + i -= 1 + end + # here P.constraints_list[i] < constraint + insert!(P.constraints_list, i+1, constraint) + return nothing +end diff --git a/src/AbstractHyperrectangle.jl b/src/AbstractHyperrectangle.jl new file mode 100644 index 0000000000..9629f90c2d --- /dev/null +++ b/src/AbstractHyperrectangle.jl @@ -0,0 +1,161 @@ +import Base.LinAlg:norm, + Base.∈ + +export AbstractHyperrectangle, + radius_hyperrectangle + +""" + AbstractHyperrectangle{N<:Real} <: AbstractPointSymmetricPolytope{N} + +Abstract type for box-shaped sets. + +### Notes + +Every concrete `AbstractHyperrectangle` must define the following functions: +- `radius_hyperrectangle(::AbstractHyperrectangle{N})::Vector{N}` -- return the + hyperrectangle's radius, which is a full-dimensional vector +- `radius_hyperrectangle(::AbstractHyperrectangle{N}, i::Int)::N` -- return the + hyperrectangle's radius in the `i`-th dimension + +```jldoctest +julia> subtypes(AbstractHyperrectangle) +3-element Array{Union{DataType, UnionAll},1}: + LazySets.AbstractSingleton + LazySets.BallInf + LazySets.Hyperrectangle +``` +""" +abstract type AbstractHyperrectangle{N<:Real} <: AbstractPointSymmetricPolytope{N} +end + + +# --- AbstractPolytope interface functions --- + + +""" + vertices_list(B::AbstractHyperrectangle{N})::Vector{Vector{N}} where {N<:Real} + +Return the list of vertices of a box-shaped set. + +### Input + +- `B` -- box-shaped set + +### Output + +A list of vertices. + +### Notes + +For high dimensions, it is preferable to develop a `vertex_iterator` approach. +""" +function vertices_list(B::AbstractHyperrectangle{N} + )::Vector{Vector{N}} where {N<:Real} + return [center(B) .+ si .* radius_hyperrectangle(B) + for si in IterTools.product([[1, -1] for i = 1:dim(B)]...)] +end + + +# --- LazySet interface functions --- + + +""" + σ(d::AbstractVector{N}, B::AbstractHyperrectangle{N} + )::AbstractVector{N} where {N<:Real} + +Return the support vector of a box-shaped set in a given direction. + +### Input + +- `d` -- direction +- `B` -- box-shaped set + +### Output + +The support vector in the given direction. +If the direction has norm zero, the vertex with biggest values is returned. +""" +function σ(d::AbstractVector{N}, + B::AbstractHyperrectangle{N})::AbstractVector{N} where {N<:Real} + return center(B) .+ sign_cadlag.(d) .* radius_hyperrectangle(B) +end + +""" + norm(B::AbstractHyperrectangle, [p]::Real=Inf)::Real + +Return the norm of a box-shaped set. + +### Input + +- `B` -- box-shaped set +- `p` -- (optional, default: `Inf`) norm + +### Output + +A real number representing the norm. + +### Notes + +The norm of a box-shaped set is defined as the norm of the enclosing ball, of +the given ``p``-norm, of minimal volume. +""" +function norm(B::AbstractHyperrectangle, p::Real=Inf)::Real + return maximum(map(x -> norm(x, p), vertices_list(B))) +end + +""" + diameter(B::AbstractHyperrectangle, [p]::Real=Inf)::Real + +Return the diameter of a box-shaped set. + +### Input + +- `H` -- box-shaped set +- `p` -- (optional, default: `Inf`) norm + +### Output + +A real number representing the diameter. + +### Notes + +The diameter is defined as the maximum distance in the given ``p``-norm between +any two elements of the set. +Equivalently, it is the diameter of the enclosing ball of the given ``p``-norm +of minimal volume with the same center. +""" +function diameter(B::AbstractHyperrectangle, p::Real=Inf)::Real + return radius(B, p) * 2 +end + +""" + ∈(x::AbstractVector{N}, B::AbstractHyperrectangle{N})::Bool where {N<:Real} + +Check whether a given point is contained in a box-shaped set. + +### Input + +- `x` -- point/vector +- `B` -- box-shaped set + +### Output + +`true` iff ``x ∈ B``. + +### Algorithm + +Let ``B`` be an ``n``-dimensional box-shaped set, ``c_i`` and ``r_i`` be +the box's center and radius and ``x_i`` be the vector ``x`` in dimension ``i``, +respectively. +Then ``x ∈ B`` iff ``|c_i - x_i| ≤ r_i`` for all ``i=1,…,n``. +""" +function ∈(x::AbstractVector{N}, + B::AbstractHyperrectangle{N})::Bool where {N<:Real} + @assert length(x) == dim(B) + for i in eachindex(x) + if abs(center(B)[i] - x[i]) > radius_hyperrectangle(B, i) + return false + end + end + return true +end diff --git a/src/AbstractPointSymmetric.jl b/src/AbstractPointSymmetric.jl new file mode 100644 index 0000000000..89875a1fc3 --- /dev/null +++ b/src/AbstractPointSymmetric.jl @@ -0,0 +1,39 @@ +export AbstractPointSymmetric, + center + +""" + AbstractPointSymmetric{N<:Real} <: LazySet + +Abstract type for point symmetric sets. + +### Notes + +Every concrete `AbstractPointSymmetric` must define the following functions: +- `center(::AbstractPointSymmetric{N})::Vector{N}` -- return the center point + +```jldoctest +julia> subtypes(AbstractPointSymmetric) +2-element Array{Union{DataType, UnionAll},1}: + LazySets.Ball2 + LazySets.Ballp +``` +""" +abstract type AbstractPointSymmetric{N<:Real} <: LazySet end + + +""" + dim(S::AbstractPointSymmetric)::Int + +Return the ambient dimension of a point symmetric set. + +### Input + +- `S` -- set + +### Output + +The ambient dimension of the set. +""" +@inline function dim(S::AbstractPointSymmetric)::Int + return length(center(S)) +end diff --git a/src/AbstractPointSymmetricPolytope.jl b/src/AbstractPointSymmetricPolytope.jl new file mode 100644 index 0000000000..f7c0beb6ac --- /dev/null +++ b/src/AbstractPointSymmetricPolytope.jl @@ -0,0 +1,77 @@ +export AbstractPointSymmetricPolytope, + center, + vertices_list, + singleton_list + +""" + AbstractPointSymmetricPolytope{N<:Real} <: LazySet + +Abstract type for point symmetric, polytopic sets. +It combines the `AbstractPointSymmetric` and `AbstractPolytope` interfaces. +Such a type combination is necessary as long as Julia does not support +[multiple inheritance](https://github.com/JuliaLang/julia/issues/5). + +### Notes + +Every concrete `AbstractPointSymmetricPolytope` must define the following +functions: +- from `AbstractPointSymmetric`: + + - `center(::AbstractPointSymmetric{N})::Vector{N}` -- return the center point +- from `AbstractPolytope`: + - `vertices_list(::AbstractPointSymmetricPolytope{N})::Vector{Vector{N}}` + -- return a list of all vertices + +```jldoctest +julia> subtypes(AbstractPointSymmetricPolytope) +3-element Array{Union{DataType, UnionAll},1}: + LazySets.AbstractHyperrectangle + LazySets.Ball1 + LazySets.Zonotope +``` +""" +abstract type AbstractPointSymmetricPolytope{N<:Real} <: LazySet end + + +# --- common AbstractPointSymmetric functions (copy-pasted) --- + + +""" + dim(S::AbstractPointSymmetricPolytope)::Int + +Return the ambient dimension of a point symmetric set. + +### Input + +- `S` -- set + +### Output + +The ambient dimension of the set. +""" +@inline function dim(S::AbstractPointSymmetricPolytope)::Int + return length(center(S)) +end + + +# --- common AbstractPolytope functions (copy-pasted) --- + + +""" + singleton_list(P::AbstractPointSymmetricPolytope{N} + )::Vector{Singleton{N}} where {N<:Real} + +Return the vertices of a polytopic as a list of singletons. + +### Input + +- `P` -- a polytopic set + +### Output + +List containing a singleton for each vertex. +""" +function singleton_list(P::AbstractPointSymmetricPolytope{N} + )::Vector{Singleton{N}} where {N<:Real} + return [Singleton(vi) for vi in P.vertices_list] +end diff --git a/src/AbstractPolygon.jl b/src/AbstractPolygon.jl new file mode 100644 index 0000000000..bc531b70ca --- /dev/null +++ b/src/AbstractPolygon.jl @@ -0,0 +1,46 @@ +export AbstractPolygon, + tohrep, + tovrep + +""" + AbstractPolygon{N<:Real} <: AbstractPolytope{N} + +Abstract type for polygons (i.e., 2D polytopes). + +### Notes + +Every concrete `AbstractPolygon` must define the following functions: +- `tovrep(::AbstractPolygon{N})::VPolygon{N}` -- transform into + V-representation +- `tohrep(::AbstractPolygon{N})::AbstractHPolygon{N}` -- transform into + H-representation + +```jldoctest +julia> subtypes(AbstractPolygon) +2-element Array{Union{DataType, UnionAll},1}: + LazySets.AbstractHPolygon + LazySets.VPolygon +``` +""" +abstract type AbstractPolygon{N<:Real} <: AbstractPolytope{N} end + + +# --- LazySet interface functions --- + + +""" + dim(P::AbstractPolygon)::Int + +Return the ambient dimension of a polygon. + +### Input + +- `P` -- polygon + +### Output + +The ambient dimension of the polygon, which is 2. +""" +@inline function dim(P::AbstractPolygon)::Int + return 2 +end diff --git a/src/AbstractPolytope.jl b/src/AbstractPolytope.jl new file mode 100644 index 0000000000..4fc578786a --- /dev/null +++ b/src/AbstractPolytope.jl @@ -0,0 +1,46 @@ +export AbstractPolytope, + vertices_list, + singleton_list + +""" + AbstractPolytope{N<:Real} <: LazySet + +Abstract type for polytopic sets, i.e., sets with finitely many flat facets, or +equivalently, sets defined as an intersection of a finite number of halfspaces, +or equivalently, sets with finitely many vertices. + +### Notes + +Every concrete `AbstractPolytope` must define the following functions: +- `vertices_list(::AbstractPolytope{N})::Vector{Vector{N}}` -- return a list of + all vertices + +```jldoctest +julia> subtypes(AbstractPolytope) +1-element Array{Union{DataType, UnionAll},1}: + LazySets.AbstractPolygon +``` +""" +abstract type AbstractPolytope{N<:Real} <: LazySet end + + +# --- common AbstractPolytope functions --- + + +""" + singleton_list(P::AbstractPolytope{N})::Vector{Singleton{N}} where {N<:Real} + +Return the vertices of a polytopic as a list of singletons. + +### Input + +- `P` -- a polytopic set + +### Output + +List containing a singleton for each vertex. +""" +function singleton_list(P::AbstractPolytope{N} + )::Vector{Singleton{N}} where {N<:Real} + return [Singleton(vi) for vi in P.vertices_list] +end diff --git a/src/AbstractSingleton.jl b/src/AbstractSingleton.jl new file mode 100644 index 0000000000..f00a2394c4 --- /dev/null +++ b/src/AbstractSingleton.jl @@ -0,0 +1,176 @@ +import Base: ∈, ⊆ + +export AbstractSingleton, + element + +""" + AbstractSingleton{N<:Real} <: AbstractHyperrectangle{N} + +Abstract type for sets with a single value. + +### Notes + +Every concrete `AbstractSingleton` must define the following functions: +- `element(::AbstractSingleton{N})::Vector{N}` -- return the single element +- `element(::AbstractSingleton{N}, i::Int)::N` -- return the single element's + entry in the `i`-th dimension + +```jldoctest +julia> subtypes(AbstractSingleton) +2-element Array{Union{DataType, UnionAll},1}: + LazySets.Singleton + LazySets.ZeroSet +``` +""" +abstract type AbstractSingleton{N<:Real} <: AbstractHyperrectangle{N} end + + +# --- AbstractHyperrectangle interface functions --- + + +""" + radius_hyperrectangle(S::AbstractSingleton{N}, i::Int)::N where {N<:Real} + +Return the box radius of a set with a single value in a given dimension. + +### Input + +- `S` -- set with a single value + +### Output + +Zero. +""" +function radius_hyperrectangle(S::AbstractSingleton{N}, i::Int + )::N where {N<:Real} + return zero(N) +end + + +""" + radius_hyperrectangle(S::AbstractSingleton{N})::Vector{N} where {N<:Real} + +Return the box radius of a set with a single value in every dimension. + +### Input + +- `S` -- set with a single value + +### Output + +The zero vector. +""" +function radius_hyperrectangle(S::AbstractSingleton{N} + )::Vector{N} where {N<:Real} + return zeros(N, dim(S)) +end + + +# --- AbstractPointSymmetric interface functions --- + + +""" + center(S::AbstractSingleton{N})::Vector{N} where {N<:Real} + +Return the center of a set with a single value. + +### Input + +- `S` -- set with a single value + +### Output + +The only element of the set. +""" +function center(S::AbstractSingleton{N})::Vector{N} where {N<:Real} + return element(S) +end + + +# --- AbstractPolytope interface functions --- + + +""" + vertices_list(S::AbstractSingleton{N})::Vector{Vector{N}} where {N<:Real} + +Return the list of vertices of a set with a single value. + +### Input + +- `S` -- set with a single value + +### Output + +A list containing only a single vertex. +""" +function vertices_list(S::AbstractSingleton{N} + )::Vector{Vector{N}} where {N<:Real} + return [element(S)] +end + + +# --- LazySet interface functions --- + + +""" + σ(d::AbstractVector{N}, S::AbstractSingleton{N})::Vector{N} where {N<:Real} + +Return the support vector of a set with a single value. + +### Input + +- `d` -- direction +- `B` -- set with a single value + +### Output + +The support vector, which is the set's vector itself, irrespective of the given +direction. +""" +function σ(d::AbstractVector{N}, + S::AbstractSingleton{N})::Vector{N} where {N<:Real} + return element(S) +end + + +""" + ∈(x::AbstractVector{N}, S::AbstractSingleton{N})::Bool where {N<:Real} + +Check whether a given point is contained in a set with a single value. + +### Input + +- `x` -- point/vector +- `S` -- set with a single value + +### Output + +`true` iff ``x ∈ S``. + +### Notes + +This implementation performs an exact comparison, which may be insufficient with +floating point computations. +""" +function ∈(x::AbstractVector{N}, S::AbstractSingleton{N})::Bool where {N<:Real} + return x == element(S) +end + + +""" + ⊆(S::AbstractSingleton, set::LazySet)::Bool + +Check whether a given set with a single value is contained in a convex set. + +### Input + +- `S` -- set with a single value +- `set` -- convex set + +### Output + +`true` iff ``S ⊆ \\text{set}``. +""" +function ⊆(S::AbstractSingleton, set::LazySet)::Bool + return ∈(element(S), set) +end diff --git a/src/Ball1.jl b/src/Ball1.jl index f870188db8..d407cd051a 100644 --- a/src/Ball1.jl +++ b/src/Ball1.jl @@ -3,7 +3,7 @@ import Base.∈ export Ball1 """ - Ball1 <: LazySet + Ball1{N<:Real} <: AbstractPointSymmetricPolytope{N} Type that represents a ball in the 1-norm, also known as Manhattan or Taxicab norm. @@ -40,7 +40,7 @@ julia> σ([0.,1], B) 1.0 ``` """ -struct Ball1{N<:Real} <: LazySet +struct Ball1{N<:Real} <: AbstractPointSymmetricPolytope{N} center::Vector{N} radius::N @@ -51,39 +51,67 @@ end # type-less convenience constructor Ball1(center::Vector{N}, radius::N) where {N<:Real} = Ball1{N}(center, radius) + +# --- AbstractPointSymmetric interface functions --- + + """ - dim(B::Ball1)::Int + center(B::Ball1{N})::Vector{N} where {N<:Real} -Return the dimension of a `Ball1`. +Return the center of a ball in the 1-norm. ### Input -- `B` -- a ball in the 1-norm +- `B` -- ball in the 1-norm ### Output -The ambient dimension of the ball. +The center of the ball in the 1-norm. """ -function dim(B::Ball1)::Int - return length(B.center) +function center(B::Ball1{N})::Vector{N} where {N<:Real} + return B.center end + +# --- AbstractPolytope interface functions --- + + +""" + vertices_list(B::Ball1{N})::Vector{Vector{N}} where {N<:Real} + +Return the list of vertices of a ball in the 1-norm. + +### Input + +- `B` -- ball in the 1-norm + +### Output + +A list containing only a single vertex. +""" +function vertices_list(B::Ball1{N})::Vector{Vector{N}} where {N<:Real} + error("this function is not implemented yet, see issue #84") +end + + +# --- LazySet interface functions --- + + """ σ(d::AbstractVector{N}, B::Ball1)::AbstractVector{N} where {N<:Real} -Return the support vector of a `Ball1` in a given direction. +Return the support vector of a ball in the 1-norm in a given direction. ### Input -- `d` -- a direction -- `B` -- a ball in the p-norm +- `d` -- direction +- `B` -- ball in the 1-norm ### Output Support vector in the given direction. """ -function σ(d::AbstractVector{N}, - B::Ball1)::AbstractVector{N} where {N<:AbstractFloat} +function σ(d::AbstractVector{N}, B::Ball1{N})::AbstractVector{N} where {N<:Real} res = copy(B.center) imax = indmax(abs.(d)) res[imax] = sign(d[imax]) * B.radius diff --git a/src/Ball2.jl b/src/Ball2.jl index 20486b70ab..b3e8024162 100644 --- a/src/Ball2.jl +++ b/src/Ball2.jl @@ -3,7 +3,7 @@ import Base.∈ export Ball2 """ - Ball2{N<:Real} <: LazySet + Ball2{N<:Real} <: AbstractPointSymmetric{N} Type that represents a ball in the 2-norm. @@ -48,7 +48,7 @@ julia> σ([1.,2.,3.,4.,5.], B) 0.3371 ``` """ -struct Ball2{N<:Real} <: LazySet +struct Ball2{N<:Real} <: AbstractPointSymmetric{N} center::Vector{N} radius::N @@ -59,10 +59,14 @@ end # type-less convenience constructor Ball2(center::Vector{N}, radius::N) where {N<:Real} = Ball2{N}(center, radius) + +# --- AbstractPointSymmetric interface functions --- + + """ - dim(B::Ball2)::Int + center(B::Ball2{N})::Vector{N} where {N<:Real} -Return the dimension of a ball in the 2-norm. +Return the center of a ball in the 2-norm. ### Input @@ -70,12 +74,16 @@ Return the dimension of a ball in the 2-norm. ### Output -The ambient dimension of the ball. +The center of the ball in the 2-norm. """ -function dim(B::Ball2)::Int - return length(B.center) +function center(B::Ball2{N})::Vector{N} where {N<:Real} + return B.center end + +# --- LazySet interface functions --- + + """ σ(d::AbstractVector{N}, B::Ball2)::AbstractVector{<:AbstractFloat} where {N<:AbstractFloat} @@ -151,8 +159,7 @@ julia> ∈([.5, 1.5], B) true ``` """ -function ∈(x::AbstractVector{<:Real}, - B::Ball2{N})::Bool where {N<:AbstractFloat} +function ∈(x::AbstractVector{N}, B::Ball2{N})::Bool where {N<:Real} @assert length(x) == dim(B) sum = zero(N) for i in eachindex(x) diff --git a/src/BallInf.jl b/src/BallInf.jl index 1456a8ef56..384ed45779 100644 --- a/src/BallInf.jl +++ b/src/BallInf.jl @@ -1,15 +1,9 @@ -import Base.LinAlg:norm, - Base.∈ +import Base.LinAlg:norm -export BallInf, - vertices_list, - norm, - radius, - diameter, - ∈ +export BallInf """ - BallInf{N<:Real} <: LazySet + BallInf{N<:Real} <: AbstractHyperrectangle{N} Type that represents a ball in the infinity norm. @@ -44,7 +38,7 @@ julia> ρ([1., 1.], B) 2.0 ``` """ -struct BallInf{N<:Real} <: LazySet +struct BallInf{N<:Real} <: AbstractHyperrectangle{N} center::Vector{N} radius::N @@ -56,100 +50,70 @@ end BallInf(center::Vector{N}, radius::N) where {N<:Real} = BallInf{N}(center, radius) -""" - dim(B::BallInf)::Int - -Return the dimension of a ball in the infinity norm. - -### Input -- `B` -- ball in the infinity norm - -### Output +# --- AbstractHyperrectangle interface functions --- -The ambient dimension of the ball. -""" -function dim(B::BallInf)::Int - return length(B.center) -end """ - σ(d::AbstractVector{<:Real}, B::BallInf)::AbstractVector{<:Real} + radius_hyperrectangle(B::BallInf{N}, i::Int)::N where {N<:Real} -Return the support vector of an infinity norm ball in a given direction. +Return the box radius of a infinity norm ball in a given dimension. ### Input -- `d` -- direction -- `B` -- ball in the infinity norm +- `B` -- infinity norm ball ### Output -The support vector in the given direction. -If the direction has norm zero, the vertex with biggest values is returned. +The box radius of the ball in the infinity norm in the given dimension. """ -function σ(d::AbstractVector{<:Real}, B::BallInf)::AbstractVector{<:Real} - return @. B.center + sign_cadlag(d) * B.radius +function radius_hyperrectangle(B::BallInf{N}, i::Int)::N where {N<:Real} + return B.radius end """ - vertices_list(B::BallInf{N})::Vector{Vector{N}} where {N<:Real} + radius_hyperrectangle(B::BallInf{N})::Vector{N} where {N<:Real} -Return the list of vertices of a ball in the infinity norm. +Return the box radius of a infinity norm ball, which is the same in every +dimension. ### Input -- `B` -- ball in the infinity norm +- `B` -- infinity norm ball ### Output -A list of vertices. - -### Notes +The box radius of the ball in the infinity norm. +""" +function radius_hyperrectangle(B::BallInf{N})::Vector{N} where {N<:Real} + return fill(B.radius, dim(B)) +end -For high dimensions, it is preferable to develop a `vertex_iterator` approach. -### Examples +# --- AbstractPointSymmetric interface functions --- -```jldoctest -julia> B = BallInf(zeros(2), 0.1) -LazySets.BallInf{Float64}([0.0, 0.0], 0.1) -julia> vertices_list(B) -4-element Array{Array{Float64,1},1}: - [0.1, 0.1] - [-0.1, 0.1] - [0.1, -0.1] - [-0.1, -0.1] -``` -""" -function vertices_list(B::BallInf{N})::Vector{Vector{N}} where {N<:Real} - return [B.center .+ si .* B.radius - for si in IterTools.product([[1, -1] for i = 1:dim(B)]...)] -end """ - norm(B::BallInf, [p]::Real=Inf)::Real + center(B::BallInf{N})::Vector{N} where {N<:Real} -Return the norm of a ball in the infinity norm. +Return the center of a ball in the infinity norm. ### Input - `B` -- ball in the infinity norm -- `p` -- (optional, default: `Inf`) norm ### Output -A real number representing the norm. - -### Notes - -The norm of an infinity ball is defined as the norm of the enclosing ball, of -the given ``p``-norm, of minimal volume. +The center of the ball in the infinity norm. """ -function norm(B::BallInf, p::Real=Inf)::Real - return maximum(map(x -> norm(x, p), vertices_list(B))) +function center(B::BallInf{N})::Vector{N} where {N<:Real} + return B.center end + +# --- LazySet interface functions --- + + """ radius(B::BallInf, [p]::Real=Inf)::Real @@ -172,70 +136,3 @@ The radius is defined as the radius of the enclosing ball of the given function radius(B::BallInf, p::Real=Inf)::Real return (p == Inf) ? B.radius : norm(fill(B.radius, dim(B)), p) end - -""" - diameter(B::BallInf, [p]::Real=Inf)::Real - -Return the diameter of a ball in the infinity norm. - -### Input - -- `B` -- ball in the infinity norm -- `p` -- (optional, default: `Inf`) norm - -### Output - -A real number representing the diameter. - -### Notes - -The diameter is defined as the maximum distance in the given ``p``-norm between -any two elements of the set. -Equivalently, it is the diameter of the enclosing ball of the given ``p``-norm -of minimal volume with the same center. -""" -function diameter(B::BallInf, p::Real=Inf)::Real - return radius(B, p) * 2 -end - -""" - ∈(x::AbstractVector{N}, B::BallInf{N})::Bool where {N<:Real} - -Check whether a given point is contained in a ball in the infinity norm. - -### Input - -- `x` -- point/vector -- `B` -- ball in the infinity norm - -### Output - -`true` iff ``x ∈ B``. - -### Algorithm - -Let ``B`` be an ``n``-dimensional ball in the infinity norm with radius ``r`` -and let ``c_i`` and ``x_i`` be the ball's center and the vector ``x`` in -dimension ``i``, respectively. -Then ``x ∈ B`` iff ``|c_i - x_i| ≤ r`` for all ``i=1,…,n``. - -### Examples - -```jldoctest -julia> B = BallInf([1., 1.], 1.); - -julia> ∈([.5, -.5], B) -false -julia> ∈([.5, 1.5], B) -true -``` -""" -function ∈(x::AbstractVector{N}, B::BallInf{N})::Bool where {N<:Real} - @assert length(x) == dim(B) - for i in eachindex(x) - if abs(B.center[i] - x[i]) > B.radius - return false - end - end - return true -end diff --git a/src/Ballp.jl b/src/Ballp.jl index f0c459a646..ccc01d653a 100644 --- a/src/Ballp.jl +++ b/src/Ballp.jl @@ -3,7 +3,7 @@ import Base.∈ export Ballp """ - Ballp <: LazySet + Ballp{N<:Real} <: AbstractPointSymmetric{N} Type that represents a ball in the p-norm, for ``1 ≤ p ≤ ∞``. @@ -52,7 +52,7 @@ julia> σ(1.:5, B) 0.3379 ``` """ -struct Ballp{N<:Real} <: LazySet +struct Ballp{N<:Real} <: AbstractPointSymmetric{N} p::Real center::Vector{N} radius::N @@ -78,23 +78,31 @@ end Ballp(p::Real, center::Vector{N}, radius::N) where {N<:Real} = Ballp{N}(p, center, radius) + +# --- AbstractPointSymmetric interface functions --- + + """ - dim(B::Ballp)::Int + center(B::Ballp{N})::Vector{N} where {N<:Real} -Return the dimension of a Ballp. +Return the center of a ball in the p-norm. ### Input -- `B` -- a ball in the p-norm +- `B` -- ball in the p-norm ### Output -The ambient dimension of the ball. +The center of the ball in the p-norm. """ -function dim(B::Ballp)::Int - return length(B.center) +function center(B::Ballp{N})::Vector{N} where {N<:Real} + return B.center end + +# --- LazySet interface functions --- + + """ σ(d::AbstractVector{N}, B::Ballp)::AbstractVector{N} where {N<:AbstractFloat} @@ -102,8 +110,8 @@ Return the support vector of a `Ballp` in a given direction. ### Input -- `d` -- a direction -- `B` -- a ball in the p-norm +- `d` -- direction +- `B` -- ball in the p-norm ### Output diff --git a/src/HPolygon.jl b/src/HPolygon.jl index 93700104a0..739d481acc 100644 --- a/src/HPolygon.jl +++ b/src/HPolygon.jl @@ -1,13 +1,9 @@ -import Base: <=, ∈ +import Base.<= -export HPolygon, - addconstraint!, - ∈, - tovrep, - vertices_list +export HPolygon """ - HPolygon{N<:Real} <: LazySet + HPolygon{N<:Real} <: AbstractHPolygon{N} Type that represents a convex polygon in constraint representation whose edges are sorted in counter-clockwise fashion with respect to their normal directions. @@ -27,7 +23,7 @@ Use `addconstraint!` to iteratively add the edges in a sorted way. - `HPolygon()` -- constructor with no constraints """ -struct HPolygon{N<:Real} <: LazySet +struct HPolygon{N<:Real} <: AbstractHPolygon{N} constraints_list::Vector{LinearConstraint{N}} end # constructor for an HPolygon with no constraints @@ -35,48 +31,9 @@ HPolygon{N}() where {N<:Real} = HPolygon{N}(Vector{N}(0)) # constructor for an HPolygon with no constraints of type Float64 HPolygon() = HPolygon{Float64}() -""" - addconstraint!(P::HPolygon{N}, constraint::LinearConstraint{N})::Void where {N<:Real} - -Add a linear constraint to a polygon in constraint representation, keeping the -constraints sorted by their normal directions. -### Input +# --- LazySet interface functions --- -- `P` -- polygon -- `constraint` -- linear constraint to add - -### Output - -Nothing. -""" -function addconstraint!(P::HPolygon{N}, - constraint::LinearConstraint{N})::Void where {N<:Real} - i = length(P.constraints_list) - while i > 0 && constraint.a <= P.constraints_list[i].a - i -= 1 - end - # here P.constraints_list[i] < constraint - insert!(P.constraints_list, i+1, constraint) - return nothing -end - -""" - dim(P::HPolygon)::Int - -Return the dimension of a polygon. - -### Input - -- `P` -- polygon in constraint representation - -### Output - -The ambient dimension of the polygon. -""" -function dim(P::HPolygon)::Int - return 2 -end """ σ(d::AbstractVector{<:Real}, P::HPolygon{N})::Vector{N} where {N<:Real} @@ -116,78 +73,3 @@ function σ(d::AbstractVector{<:Real}, P::HPolygon{N})::Vector{N} where {N<:Real Line(P.constraints_list[k-1])) end end - -""" - ∈(x::AbstractVector{N}, P::HPolygon{N})::Bool where {N<:Real} - -Check whether a given 2D point is contained in a polygon in constraint -representation. - -### Input - -- `x` -- two-dimensional point/vector -- `P` -- polygon in constraint representation - -### Output - -`true` iff ``x ∈ P``. - -### Algorithm - -This implementation checks if the point lies on the outside of each edge. -""" -function ∈(x::AbstractVector{N}, P::HPolygon{N})::Bool where {N<:Real} - @assert length(x) == 2 - - for c in P.constraints_list - if dot(c.a, x) > c.b - return false - end - end - return true -end - -""" - tovrep(P::HPolygon)::VPolygon - -Build a vertex representation of the given polygon. - -### Input - -- `P` -- polygon in constraint representation - -### Output - -The same polygon but in vertex representation, a `VPolygon`. -""" -function tovrep(P::HPolygon)::VPolygon - return VPolygon(vertices_list(P)) -end - -""" - vertices_list(P::HPolygon{N})::Vector{Vector{N}} where {N<:Real} - -Return the list of vertices of a polygon in constraint representation. - -### Input - -- `P` -- polygon in constraint representation - -### Output - -List of vertices. -""" -function vertices_list(P::HPolygon{N})::Vector{Vector{N}} where {N<:Real} - n = length(P.constraints_list) - points = Vector{Vector{N}}(n) - if n == 0 - return points - end - @inbounds for i in 1:n-1 - points[i] = intersection(Line(P.constraints_list[i]), - Line(P.constraints_list[i+1])) - end - points[n] = intersection(Line(P.constraints_list[n]), - Line(P.constraints_list[1])) - return points -end diff --git a/src/HPolygonOpt.jl b/src/HPolygonOpt.jl index 2f0fe4d8a8..f0917e7d61 100644 --- a/src/HPolygonOpt.jl +++ b/src/HPolygonOpt.jl @@ -1,13 +1,9 @@ -import Base: <=, ∈ +import Base.<= -export HPolygonOpt, - addconstraint!, - ∈, - tovrep, - vertices_list +export HPolygonOpt """ - HPolygonOpt{N<:Real} <: LazySet + HPolygonOpt{N<:Real} <: AbstractHPolygon{N} Type that represents a convex polygon in constraint representation whose edges are sorted in counter-clockwise fashion with respect to their normal directions. @@ -37,7 +33,7 @@ Use `addconstraint!` to iteratively add the edges in a sorted way. - `HPolygonOpt(H::HPolygon{<:Real})` -- constructor from an HPolygon """ -mutable struct HPolygonOpt{N<:Real} <: LazySet +mutable struct HPolygonOpt{N<:Real} <: AbstractHPolygon{N} constraints_list::Vector{LinearConstraint{N}} ind::Int @@ -59,47 +55,9 @@ HPolygonOpt(constraints_list::Vector{LinearConstraint{N}}) where {N<:Real} = HPolygonOpt(H::HPolygon{N}) where {N<:Real} = HPolygonOpt{N}(H.constraints_list, 1) -""" - addconstraint!(P::HPolygonOpt{N}, constraint::LinearConstraint{N})::Void where {N<:Real} - -Add a linear constraint to an optimized polygon in constraint representation, -keeping the constraints sorted by their normal directions. - -### Input - -- `P` -- optimized polygon -- `constraint` -- linear constraint to add - -### Output - -Nothing. -""" -function addconstraint!(P::HPolygonOpt{N}, - constraint::LinearConstraint{N})::Void where {N<:Real} - i = length(P.constraints_list) - while i > 0 && constraint.a <= P.constraints_list[i].a - i -= 1 - end - insert!(P.constraints_list, i+1, constraint) - return nothing -end - -""" - dim(P::HPolygonOpt)::Int - -Return the dimension of an optimized polygon. -### Input - -- `P` -- optimized polygon in constraint representation +# --- LazySet interface functions --- -### Output - -The ambient dimension of the optimized polygon. -""" -function dim(P::HPolygonOpt)::Int - return 2 -end """ σ(d::AbstractVector{<:Real}, P::HPolygonOpt{N})::Vector{N} where {N<:Real} @@ -158,57 +116,3 @@ function σ(d::AbstractVector{<:Real}, end end end - -""" - ∈(x::AbstractVector{N}, P::HPolygonOpt{N})::Bool where {N<:Real} - -Check whether a given 2D point is contained in an optimized polygon in -constraint representation. - -### Input - -- `x` -- two-dimensional point/vector -- `P` -- optimized polygon in constraint representation - -### Output - -`true` iff ``x ∈ P``. -""" -function ∈(x::AbstractVector{N}, P::HPolygonOpt{N})::Bool where {N<:Real} - return ∈(x, HPolygon(P.constraints_list)) -end - -""" - tovrep(P::HPolygonOpt)::VPolygon - -Build a vertex representation of the given optimized polygon. - -### Input - -- `P` -- optimized polygon in constraint representation - -### Output - -The same polygon but in vertex representation, a `VPolygon`. -""" -function tovrep(P::HPolygonOpt)::VPolygon - return tovrep(HPolygon(P.constraints_list)) -end - -""" - vertices_list(P::HPolygonOpt{N})::Vector{Vector{N}} where {N<:Real} - -Return the list of vertices of an optimized polygon in constraint -representation. - -### Input - -- `P` -- an optimized polygon in constraint representation - -### Output - -List of vertices. -""" -function vertices_list(P::HPolygonOpt{N})::Vector{Vector{N}} where {N<:Real} - return vertices_list(HPolygon(P.constraints_list)) -end diff --git a/src/Hyperrectangle.jl b/src/Hyperrectangle.jl index e815e00ddc..599319b862 100644 --- a/src/Hyperrectangle.jl +++ b/src/Hyperrectangle.jl @@ -1,17 +1,11 @@ -import Base.LinAlg:norm, - Base.∈ +import Base.LinAlg:norm export Hyperrectangle, - vertices_list, - norm, - radius, - diameter, low, - high, - ∈ + high """ - Hyperrectangle{N<:Real} <: LazySet + Hyperrectangle{N<:Real} <: AbstractHyperrectangle{N} Type that represents a hyperrectangle. @@ -24,7 +18,7 @@ Cartesian product of one-dimensional intervals. - `radius` -- radius of the ball as a real vector, i.e., half of its width along each coordinate direction """ -struct Hyperrectangle{N<:Real} <: LazySet +struct Hyperrectangle{N<:Real} <: AbstractHyperrectangle{N} center::Vector{N} radius::Vector{N} @@ -90,46 +84,31 @@ function Hyperrectangle(;kwargs...) "'center' and 'radius' or 'high' and 'low'.")) end -""" - dim(H::Hyperrectangle)::Int - -Return the dimension of a hyperrectangle. - -### Input -- `H` -- hyperrectangle - -### Output +# --- AbstractHyperrectangle interface functions --- -The ambient dimension of the hyperrectangle. -""" -function dim(H::Hyperrectangle)::Int - return length(H.center) -end """ - σ(d::AbstractVector{<:Real}, H::Hyperrectangle)::AbstractVector{<:Real} + radius_hyperrectangle(H::Hyperrectangle{N}, i::Int)::N where {N<:Real} -Return the support vector of a hyperrectangle in a given direction. +Return the box radius of a hyperrectangle in a given dimension. ### Input -- `d` -- direction - `H` -- hyperrectangle ### Output -The support vector in the given direction. -If the direction has norm zero, the vertex with biggest values is returned. +Zero. """ -function σ(d::AbstractVector{<:Real}, H::Hyperrectangle)::AbstractVector{<:Real} - return @. H.center + sign_cadlag(d) * H.radius +function radius_hyperrectangle(H::Hyperrectangle{N}, i::Int)::N where {N<:Real} + return H.radius[i] end """ - vertices_list(H::Hyperrectangle{N})::Vector{Vector{N}} where {N<:Real} + radius_hyperrectangle(H::Hyperrectangle{N})::Vector{N} where {N<:Real} -Return the vertices of a hyperrectangle. +Return the box radius of a hyperrectangle in every dimension. ### Input @@ -137,40 +116,37 @@ Return the vertices of a hyperrectangle. ### Output -A list of vertices. - -### Notes - -For high dimensions, it is preferable to develop a `vertex_iterator` approach. +The box radius of the hyperrectangle. """ -function vertices_list(H::Hyperrectangle{N})::Vector{Vector{N}} where {N<:Real} - return [H.center .+ si .* H.radius - for si in IterTools.product([[1, -1] for i = 1:dim(H)]...)] +function radius_hyperrectangle(H::Hyperrectangle{N})::Vector{N} where {N<:Real} + return H.radius end + +# --- AbstractPointSymmetric interface functions --- + + """ - norm(H::Hyperrectangle, [p]::Real=Inf)::Real + center(H::Hyperrectangle{N})::Vector{N} where {N<:Real} -Return the norm of a hyperrectangle. +Return the center of a hyperrectangle. ### Input - `H` -- hyperrectangle -- `p` -- (optional, default: `Inf`) norm ### Output -A real number representing the norm. - -### Notes - -The norm of a hyperrectangle is defined as the norm of the enclosing ball, of -the given ``p``-norm, of minimal volume. +The center of the hyperrectangle. """ -function norm(H::Hyperrectangle, p::Real=Inf)::Real - return maximum(map(x -> norm(x, p), vertices_list(H))) +function center(H::Hyperrectangle{N})::Vector{N} where {N<:Real} + return H.center end + +# --- LazySet interface functions --- + + """ radius(H::Hyperrectangle, [p]::Real=Inf)::Real @@ -195,30 +171,9 @@ function radius(H::Hyperrectangle, p::Real=Inf)::Real return norm(H.radius, p) end -""" - diameter(H::Hyperrectangle, [p]::Real=Inf)::Real - -Return the diameter of a hyperrectangle. - -### Input - -- `H` -- hyperrectangle -- `p` -- (optional, default: `Inf`) norm - -### Output -A real number representing the diameter. +# --- Hyperrectangle functions --- -### Notes - -The diameter is defined as the maximum distance in the given ``p``-norm between -any two elements of the set. -Equivalently, it is the diameter of the enclosing ball of the given ``p``-norm -of minimal volume with the same center. -""" -function diameter(H::Hyperrectangle, p::Real=Inf)::Real - return radius(H, p) * 2 -end """ high(H::Hyperrectangle{N})::Vector{N} where {N<:Real} @@ -255,45 +210,3 @@ dimension. function low(H::Hyperrectangle{N})::Vector{N} where {N<:Real} return H.center .- H.radius end - -""" - ∈(x::AbstractVector{N}, H::Hyperrectangle{N})::Bool where {N<:Real} - -Check whether a given point is contained in a hyperrectangle. - -### Input - -- `x` -- point/vector -- `H` -- hyperrectangle - -### Output - -`true` iff ``x ∈ H``. - -### Algorithm - -Let ``H`` be an ``n``-dimensional hyperrectangle, ``c_i`` and ``r_i`` be -the ball's center and radius and ``x_i`` be the vector ``x`` in dimension ``i``, -respectively. -Then ``x ∈ H`` iff ``|c_i - x_i| ≤ r_i`` for all ``i=1,…,n``. - -### Examples - -```jldoctest -julia> H = Hyperrectangle([1.0, 1.0], [2.0, 3.0]); - -julia> ∈([-1.1, 4.1], H) -false -julia> ∈([-1.0, 4.0], H) -true -``` -""" -function ∈(x::AbstractVector{N}, H::Hyperrectangle{N})::Bool where {N<:Real} - @assert length(x) == dim(H) - for i in eachindex(x) - if abs(H.center[i] - x[i]) > H.radius[i] - return false - end - end - return true -end diff --git a/src/LazySets.jl b/src/LazySets.jl index 02ba1f0d40..e5eaef8882 100644 --- a/src/LazySets.jl +++ b/src/LazySets.jl @@ -11,6 +11,9 @@ export LazySet, ρ, support_function, σ, support_vector, dim, + norm, + radius, + diameter, Approximations """ @@ -20,9 +23,10 @@ Abstract type for a lazy set. ### Notes -Every concrete `LazySet` must define a function `σ(d, X)`, representing the -support vector of `X` in a given direction `d`, and `dim`, the ambient dimension -of the set `X`. +Every concrete `LazySet` must define the following functions: +- `σ(d::AbstractVector{N}, S::LazySet)::AbstractVector{N}` -- the support vector + of `S` in a given direction `d` +- `dim(::LazySet)::Int` -- the ambient dimension of `S` `LazySet` types should be parameterized with a type `N`, typically `N<:Real`, to support computations with different numeric types. @@ -38,6 +42,15 @@ include("helper_functions.jl") # =============================== # Types that inherit from LazySet # =============================== +# abstract types +include("AbstractPolytope.jl") +include("AbstractPointSymmetric.jl") +include("AbstractPointSymmetricPolytope.jl") +include("AbstractHyperrectangle.jl") +include("AbstractPolygon.jl") +include("AbstractHPolygon.jl") +include("AbstractSingleton.jl") +# concrete types include("EmptySet.jl") include("ZeroSet.jl") include("Singleton.jl") diff --git a/src/Polyhedron.jl b/src/Polyhedron.jl index d4f32b7abb..92892d780b 100644 --- a/src/Polyhedron.jl +++ b/src/Polyhedron.jl @@ -5,7 +5,7 @@ export Polyhedron, constraints_list """ - Polyhedron{N<:Real} <: LazySet + Polyhedron{N<:Real} <: AbstractPolytope{N} Type that represents a convex polyhedron in H-representation. @@ -13,7 +13,7 @@ Type that represents a convex polyhedron in H-representation. - `constraints` -- vector of linear constraints """ -struct Polyhedron{N<:Real} <: LazySet +struct Polyhedron{N<:Real} <: AbstractPolytope{N} constraints::Vector{LinearConstraint{N}} end # constructor for a Polyhedron with no constraints @@ -70,7 +70,8 @@ function σ(d::AbstractVector{<:Real}, P::Polyhedron)::Vector{<:Real} end """ - addconstraint!(P::Polyhedron{N}, constraint::LinearConstraint{N})::Void where {N<:Real} + addconstraint!(P::Polyhedron{N}, + constraint::LinearConstraint{N})::Void where {N<:Real} Add a linear constraint to a polyhedron in H-representation. @@ -103,6 +104,7 @@ Return the list of constraints defining a polyhedron in H-representation. - `P` -- polyhedron in H-representation """ -function constraints_list(P::Polyhedron{N})::Vector{LinearConstraint{N}} where {N<:Real} +function constraints_list(P::Polyhedron{N} + )::Vector{LinearConstraint{N}} where {N<:Real} return P.constraints end diff --git a/src/Singleton.jl b/src/Singleton.jl index 112e0de6ed..76d3b4f4f4 100644 --- a/src/Singleton.jl +++ b/src/Singleton.jl @@ -3,7 +3,7 @@ import Base: ∈, ⊆ export Singleton """ - Singleton{N<:Real} <: LazySet + Singleton{N<:Real} <: AbstractSingleton{N} Type that represents a singleton, that is, a set with a unique element. @@ -11,95 +11,45 @@ Type that represents a singleton, that is, a set with a unique element. - `element` -- the only element of the set """ -struct Singleton{N<:Real} <: LazySet +struct Singleton{N<:Real} <: AbstractSingleton{N} element::Vector{N} end -""" - dim(S::Singleton)::Int - -Return the dimension of a singleton. -### Input +# --- AbstractSingleton interface functions --- -- `S` -- singleton -### Output - -The ambient dimension of the singleton. """ -function dim(S::Singleton)::Int - return length(S.element) -end + element(S::Singleton{N})::Vector{N} where {N<:Real} -""" - σ(d::AbstractVector{<:Real}, S::LazySets.Singleton{N})::Vector{N} where {N<:Real} - -Return the support vector of a singleton. +Return the element of a singleton. ### Input -- `d` -- direction -- `B` -- singleton +- `S` -- singleton ### Output -The support vector, which is the singleton's vector itself, irrespective of the -given direction. +The element of the singleton. """ -function σ(d::AbstractVector{<:Real}, - S::LazySets.Singleton{N})::Vector{N} where {N<:Real} +function element(S::Singleton{N})::Vector{N} where {N<:Real} return S.element end """ - ∈(x::AbstractVector{N}, S::Singleton{N})::Bool where {N<:Real} + element(S::Singleton{N}, i::Int)::N where {N<:Real} -Check whether a given point is contained in a singleton. +Return the i-th entry of the element of a singleton. ### Input -- `x` -- point/vector - `S` -- singleton +- `i` -- dimension ### Output -`true` iff ``x ∈ S``. - -### Notes - -This implementation performs an exact comparison, which may be insufficient with -floating point computations. - -### Examples - -```jldoctest -julia> S = Singleton([1., 1.]); - -julia> ∈([0.9, 1.1], S) -false -julia> ∈([1.0, 1.0], S) -true -``` -""" -function ∈(x::AbstractVector{N}, S::Singleton{N})::Bool where {N<:Real} - return x == S.element -end - -""" - ⊆(S::Singleton, set::LazySet)::Bool - -Check whether a given singleton is contained in a convex set. - -### Input - -- `S` -- singleton -- `set` -- convex set - -### Output - -`true` iff ``S ⊆ \\text{set}``. +The i-th entry of the element of the singleton. """ -function ⊆(S::Singleton, set::LazySet)::Bool - return ∈(S.element, set) +function element(S::Singleton{N}, i::Int)::N where {N<:Real} + return S.element[i] end diff --git a/src/VPolygon.jl b/src/VPolygon.jl index 33bd98a3c4..aa4cda5bdb 100644 --- a/src/VPolygon.jl +++ b/src/VPolygon.jl @@ -1,11 +1,9 @@ -import Base: <=, ∈ +import Base: ∈ -export VPolygon, - vertices_list, - singleton_list +export VPolygon """ - VPolygon{N<:Real} <: LazySet + VPolygon{N<:Real} <: AbstractPolygon{N} Type that represents a polygon by its vertices. @@ -24,7 +22,7 @@ the convex hull. apply_convex_hull::Bool=true, algorithm::String="monotone_chain")` """ -struct VPolygon{N<:Real} <: LazySet +struct VPolygon{N<:Real} <: AbstractPolygon{N} vertices_list::Vector{Vector{N}} # default constructor that applies a convex hull algorithm @@ -39,10 +37,14 @@ struct VPolygon{N<:Real} <: LazySet end end + +# --- AbstractPolygon interface functions --- + + """ - dim(P::VPolygon)::Int + tovrep(P::VPolygon{N})::VPolygon{N} where {N<:Real} -Return the dimension of a polygon in vertex representation. +Build a vertex representation of the given polygon. ### Input @@ -50,53 +52,32 @@ Return the dimension of a polygon in vertex representation. ### Output -The ambient dimension of the polygon. +The identity, i.e., the same polygon instance. """ -function dim(P::VPolygon)::Int - return 2 +function tovrep(P::VPolygon{N})::VPolygon{N} where {N<:Real} + return P end """ - σ(d::AbstractVector{<:Real}, P::VPolygon{N})::Vector{N} where {N<:Real} + tohrep(P::VPolygon{N})::AbstractHPolygon{N} where {N<:Real} -Return the support vector of a polygon in a given direction. +Build a constraint representation of the given polygon. ### Input -- `d` -- direction - `P` -- polygon in vertex representation ### Output -The support vector in the given direction. -If the direction has norm zero, the first vertex is returned. - -### Algorithm +The same polygon but in constraint representation, an `AbstractHPolygon`. +""" +function tohrep(P::VPolygon{N})::AbstractHPolygon{N} where {N<:Real} + error("this function is not implemented yet, see issue #5") +end -This implementation performs a brute-force search, comparing the projection of -each vector along the given direction. -It runs in ``O(n)`` where ``n`` is the number of vertices. -### Notes +# --- AbstractPolytope interface functions --- -For arbitrary points without structure this is the best one can do. -However, a more efficient approach can be used if the vertices of the polygon -have been sorted in counter-clockwise fashion. -In that case a binary search algorithm can be used that runs in ``O(\\log n)``. -See issue [#40](https://github.com/JuliaReach/LazySets.jl/issues/40). -""" -function σ(d::AbstractVector{<:Real}, P::VPolygon{N})::Vector{N} where {N<:Real} - if isempty(P.vertices_list) - error("this polygon is empty") - end - i_max = 1 - @inbounds for i in 2:length(P.vertices_list) - if dot(d, P.vertices_list[i] - P.vertices_list[i_max]) > zero(N) - i_max = i - end - end - return P.vertices_list[i_max] -end """ vertices_list(P::VPolygon{N})::Vector{Vector{N}} where {N<:Real} @@ -115,22 +96,51 @@ function vertices_list(P::VPolygon{N})::Vector{Vector{N}} where {N<:Real} return P.vertices_list end + +# --- LazySet interface functions --- + + """ - singleton_list(P::VPolygon{N})::Vector{Singleton{N}} where {N<:Real} + σ(d::AbstractVector{<:Real}, P::VPolygon{N})::Vector{N} where {N<:Real} -Return the vertices of a convex polygon in vertex representation as a list of -singletons. +Return the support vector of a polygon in a given direction. ### Input -- `P` -- a polygon vertex representation +- `d` -- direction +- `P` -- polygon in vertex representation ### Output -List containing a singleton for each vertex. +The support vector in the given direction. +If the direction has norm zero, the first vertex is returned. + +### Algorithm + +This implementation performs a brute-force search, comparing the projection of +each vector along the given direction. +It runs in ``O(n)`` where ``n`` is the number of vertices. + +### Notes + +For arbitrary points without structure this is the best one can do. +However, a more efficient approach can be used if the vertices of the polygon +have been sorted in counter-clockwise fashion. +In that case a binary search algorithm can be used that runs in ``O(\\log n)``. +See issue [#40](https://github.com/JuliaReach/LazySets.jl/issues/40). """ -function singleton_list(P::VPolygon{N})::Vector{Singleton{N}} where {N<:Real} - return [Singleton(vi) for vi in P.vertices_list] +function σ(d::AbstractVector{<:Real}, + P::VPolygon{N})::Vector{N} where {N<:Real} + if isempty(P.vertices_list) + error("this polygon is empty") + end + i_max = 1 + @inbounds for i in 2:length(P.vertices_list) + if dot(d, P.vertices_list[i] - P.vertices_list[i_max]) > zero(N) + i_max = i + end + end + return P.vertices_list[i_max] end """ diff --git a/src/ZeroSet.jl b/src/ZeroSet.jl index 27cf160428..c19d68bfdc 100644 --- a/src/ZeroSet.jl +++ b/src/ZeroSet.jl @@ -3,7 +3,7 @@ import Base.∈ export ZeroSet """ - ZeroSet <: LazySet + ZeroSet{N<:Real} <: AbstractSingleton{N} Type that represents the zero set, i.e., the set that only contains the origin. @@ -11,9 +11,54 @@ Type that represents the zero set, i.e., the set that only contains the origin. - `dim` -- the ambient dimension of this zero set """ -struct ZeroSet <: LazySet +struct ZeroSet{N<:Real} <: AbstractSingleton{N} dim::Int end +# type-less convenience constructor +ZeroSet(dim::Int) = ZeroSet{Float64}(dim) + + +# --- AbstractSingleton interface functions --- + + +""" + element(S::ZeroSet{N})::Vector{N} where {N<:Real} + +Return the element of a zero set. + +### Input + +- `S` -- zero set + +### Output + +The element of the zero set, i.e., a zero vector. +""" +function element(S::ZeroSet{N})::Vector{N} where {N<:Real} + return zeros(N, S.dim) +end + +""" + element(S::ZeroSet{N}, ::Int)::N where {N<:Real} + +Return the i-th entry of the element of a zero set. + +### Input + +- `S` -- zero set +- `i` -- dimension + +### Output + +The i-th entry of the element of the zero set, i.e., 0. +""" +function element(S::ZeroSet{N}, ::Int)::N where {N<:Real} + return zero(N) +end + + +# --- LazySet interface functions --- + """ dim(Z::ZeroSet)::Int @@ -33,7 +78,7 @@ function dim(Z::ZeroSet)::Int end """ - σ(d, Z) + σ(d::AbstractVector{N}, Z::ZeroSet)::Vector{N} where {N<:Real} Return the support vector of a zero set. @@ -51,7 +96,7 @@ function σ(d::AbstractVector{N}, Z::ZeroSet)::Vector{N} where {N<:Real} end """ - ∈(x::AbstractVector, Z::ZeroSet)::Bool + ∈(x::AbstractVector{N}, Z::ZeroSet{N})::Bool where {N<:Real} Check whether a given point is contained in a zero set. @@ -75,7 +120,7 @@ julia> ∈([0.0, 0.0], Z) true ``` """ -function ∈(x::AbstractVector{N}, Z::ZeroSet)::Bool where {N<:Real} +function ∈(x::AbstractVector{N}, Z::ZeroSet{N})::Bool where {N<:Real} @assert length(x) == dim(Z) zero_N = zero(N) diff --git a/src/Zonotope.jl b/src/Zonotope.jl index 3dc71693e9..ef1bf17c9c 100644 --- a/src/Zonotope.jl +++ b/src/Zonotope.jl @@ -1,11 +1,10 @@ import Base.∈ export Zonotope, - vertices_list, order """ - Zonotope{N<:Real} <: LazySet + Zonotope{N<:Real} <: AbstractPointSymmetricPolytope{N} Type that represents a zonotope. @@ -32,7 +31,8 @@ ball in ``\\mathbb{R}^n`` by an affine transformation. generators::AbstractMatrix{N}) where {N<:Real}` - `Zonotope(center::AbstractVector{N}, - generators_list::AbstractVector{T}) where {N<:Real, T<:AbstractVector{N}}` + generators_list::AbstractVector{T} + ) where {N<:Real, T<:AbstractVector{N}}` ### Examples @@ -76,7 +76,7 @@ julia> Z.generators 0.0 1.0 1.0 ``` """ -struct Zonotope{N<:Real} <: LazySet +struct Zonotope{N<:Real} <: AbstractPointSymmetricPolytope{N} center::AbstractVector{N} generators::AbstractMatrix{N} end @@ -85,43 +85,31 @@ Zonotope(center::AbstractVector{N}, generators_list::AbstractVector{T}) where {N<:Real, T<:AbstractVector{N}} = Zonotope(center, hcat(generators_list...)) -""" - dim(Z::Zonotope)::Int -Return the dimension of a zonotope. +# --- AbstractPointSymmetric interface functions --- -### Input -- `Z` -- zonotope - -### Output - -The ambient dimension of the zonotope. """ -function dim(Z::Zonotope)::Int - return length(Z.center) -end + center(Z::Zonotope{N})::Vector{N} where {N<:Real} -""" - σ(d::AbstractVector{<:Real}, Z::Zonotope)::AbstractVector{<:Real} - -Return the support vector of a zonotope in a given direction. +Return the center of a zonotope. ### Input -- `d` -- direction - `Z` -- zonotope ### Output -Support vector in the given direction. -If the direction has norm zero, the vertex with ``ξ_i = 1 \\ \\ ∀ i = 1,…, p`` -is returned. +The center of the zonotope. """ -function σ(d::AbstractVector{<:Real}, Z::Zonotope)::AbstractVector{<:Real} - return Z.center .+ Z.generators * sign_cadlag.(Z.generators.' * d) +function center(Z::Zonotope{N})::Vector{N} where {N<:Real} + return Z.center end + +# --- AbstractPolytope interface functions --- + + """ vertices_list(Z::Zonotope{N})::Vector{Vector{N}} where {N<:Real} @@ -154,26 +142,28 @@ function vertices_list(Z::Zonotope{N})::Vector{Vector{N}} where {N<:Real} return convex_hull!(vlist) end + +# --- LazySet interface functions --- + + """ - order(Z::Zonotope)::Rational + σ(d::AbstractVector{<:Real}, Z::Zonotope)::AbstractVector{<:Real} -Return the order of a zonotope. +Return the support vector of a zonotope in a given direction. ### Input +- `d` -- direction - `Z` -- zonotope ### Output -A rational number representing the order of the zonotope. - -### Notes - -The order of a zonotope is defined as the quotient of its number of generators -and its dimension. +Support vector in the given direction. +If the direction has norm zero, the vertex with ``ξ_i = 1 \\ \\ ∀ i = 1,…, p`` +is returned. """ -function order(Z::Zonotope)::Rational - return size(Z.generators, 2) // dim(Z) +function σ(d::AbstractVector{<:Real}, Z::Zonotope)::AbstractVector{<:Real} + return Z.center .+ Z.generators * sign_cadlag.(Z.generators.' * d) end """ @@ -239,3 +229,29 @@ function ∈(x::AbstractVector{N}, Z::Zonotope{N})::Bool where {N<:Real} return false end end + + +# --- Zonotope functions --- + + +""" + order(Z::Zonotope)::Rational + +Return the order of a zonotope. + +### Input + +- `Z` -- zonotope + +### Output + +A rational number representing the order of the zonotope. + +### Notes + +The order of a zonotope is defined as the quotient of its number of generators +and its dimension. +""" +function order(Z::Zonotope)::Rational + return size(Z.generators, 2) // dim(Z) +end diff --git a/src/helper_functions.jl b/src/helper_functions.jl index b21cf88e27..6c018bd42c 100644 --- a/src/helper_functions.jl +++ b/src/helper_functions.jl @@ -1,7 +1,8 @@ import Base.<= export sign_cadlag, - jump2pi + jump2pi, + check_method_implementation """ sign_cadlag(x::N)::N where {N<:Real} @@ -86,3 +87,68 @@ direction (1, 0). function <=(u::AbstractVector{Float64}, v::AbstractVector{Float64})::Bool return jump2pi(atan2(u[2], u[1])) <= jump2pi(atan2(v[2], v[1])) end + +""" + check_method_implementation(interface::Type, + func_name, + args_funcs::AbstractVector{Function}, + [print_results]::Bool=false + )::Bool + +Check that a given (interface) function is implemented by all subtypes. + +### Input + +- `interface` -- parent interface type +- `func_name` -- function name +- `args_funcs` -- list of functions that each map a type to an argument + signature tuple +- `print_results` -- (optional, default: `false`) flag for printing intermediate + results + +### Output + +`true` iff all subtypes implement the given function. + +### Notes + +It is sufficient that a subinterface implements the function, i.e., it is not +required that every *concrete* type implements the function. + +This function can also print all intermediate results to STDOUT. + +### Examples + +```julia +check_method_implementation(LazySet, σ, + Function[S -> (AbstractVector{Float64}, S)]) +true +``` +""" +function check_method_implementation(interface::Type, + func_name, + args_funcs::AbstractVector{Function}; + print_results::Bool=false + )::Bool + for subtype in subtypes(interface) + found = false + for args_func in args_funcs + if method_exists(func_name, args_func(subtype)) + if print_results + println("found implementation of $func_name for $subtype") + end + found = true + break + end + end + if !found && !check_method_implementation(subtype, func_name, + args_funcs, + print_results=print_results) + if print_results + println("no implementation of $func_name for $subtype") + end + return false + end + end + return true +end diff --git a/test/runtests.jl b/test/runtests.jl index 928bb00d54..5b002d90a7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,10 +1,10 @@ #!/usr/bin/env julia using LazySets, Base.Test -# ======================================= -# Testing common API of all LazySet types -# ======================================= -@time @testset "LazySets.LazySet" begin include("unit_LazySet.jl") end +# ==================================== +# Testing common API of all interfaces +# ==================================== +@time @testset "LazySets.interfaces" begin include("unit_interfaces.jl") end # ======================================= # Testing types that inherit from LazySet diff --git a/test/unit_BallInf.jl b/test/unit_BallInf.jl index e83ea1614d..086549d834 100644 --- a/test/unit_BallInf.jl +++ b/test/unit_BallInf.jl @@ -49,3 +49,8 @@ d = [-1., -1.] @test σ(d, b) == [-2., -2.] d = [1., -1.] @test σ(d, b) == [2., -2.] + +# membership +b = BallInf([1., 1.], 1.) +@test !∈([.5, -.5], b) +@test ∈([.5, 1.5], b) diff --git a/test/unit_Hyperrectangle.jl b/test/unit_Hyperrectangle.jl index 48c9cf3bca..5085a9fcbb 100644 --- a/test/unit_Hyperrectangle.jl +++ b/test/unit_Hyperrectangle.jl @@ -93,3 +93,8 @@ H3 = Hyperrectangle(low=l, high=h) H = Hyperrectangle(center=[-2.1, 5.6, 0.9], radius=fill(0.5, 3)) @test low(H) == [-2.6, 5.1, 0.4] @test high(H) == [-1.6, 6.1, 1.4] + +# membership +H = Hyperrectangle([1.0, 1.0], [2.0, 3.0]) +@test !∈([-1.1, 4.1], H) +@test ∈([-1.0, 4.0], H) diff --git a/test/unit_LazySet.jl b/test/unit_LazySet.jl deleted file mode 100644 index 82df9e7a2b..0000000000 --- a/test/unit_LazySet.jl +++ /dev/null @@ -1,8 +0,0 @@ -# check that the following functions are provided by all LazySet types -for S in subtypes(LazySet) - # support vector - @test method_exists(σ, (AbstractVector{Float64}, S)) || - method_exists(σ, (AbstractVector{Float64}, S{Float64})) - # dimension - @test method_exists(dim, (S,)) -end diff --git a/test/unit_Singleton.jl b/test/unit_Singleton.jl index b145e394e4..b40d7da7fe 100644 --- a/test/unit_Singleton.jl +++ b/test/unit_Singleton.jl @@ -15,3 +15,8 @@ d = [-1., .5] @test σ(d, s) == [1., 2.] d = [0., 0.] @test σ(d, s) == [1., 2.] + +# membership +S = Singleton([1., 1.]) +!∈([0.9, 1.1], S) +∈([1.0, 1.0], S) diff --git a/test/unit_interfaces.jl b/test/unit_interfaces.jl new file mode 100644 index 0000000000..9bf05f8b4a --- /dev/null +++ b/test/unit_interfaces.jl @@ -0,0 +1,46 @@ +# check that all interace functions are provided + +# --- LazySet --- + +# support vector +@test check_method_implementation(LazySet, σ, + Function[S -> (AbstractVector{Float64}, S)]) +# dimension +@test check_method_implementation(LazySet, dim, Function[S -> (S,)]) + +# --- AbstractPolytope --- + +# vertices list +@test check_method_implementation(AbstractPolytope, vertices_list, + Function[S -> (S{Float64},)]) +@test check_method_implementation(AbstractPointSymmetricPolytope, vertices_list, + Function[S -> (S{Float64},)]) + +# --- AbstractPointSymmetric --- + +# center +@test check_method_implementation(AbstractPointSymmetric, center, + Function[S -> (S{Float64},)]) +@test check_method_implementation(AbstractPointSymmetricPolytope, center, + Function[S -> (S{Float64},)]) + +# --- AbstractHyperrectangle --- + +# radius_hyperrectangle (2x) +@test check_method_implementation(AbstractHyperrectangle, radius_hyperrectangle, + Function[S -> (S{Float64},)]) +@test check_method_implementation(AbstractHyperrectangle, radius_hyperrectangle, + Function[S -> (S{Float64}, Int)]) + +# --- AbstractPolygon --- + +# tohrep +@test check_method_implementation(AbstractPolygon, tohrep, + Function[S -> (S{Float64},)]) +# tovrep +@test check_method_implementation(AbstractPolygon, tovrep, + Function[S -> (S{Float64},)]) + +# --- AbstractHPolygon --- + +# no functions yet