diff --git a/docs/src/lib/representations.md b/docs/src/lib/representations.md index 366063c48d..1e736d6832 100644 --- a/docs/src/lib/representations.md +++ b/docs/src/lib/representations.md @@ -24,6 +24,7 @@ Ball2 σ(::AbstractVector{AbstractFloat}, ::Ball2{AbstractFloat}) ∈(::AbstractVector{AbstractFloat}, ::Ball2{AbstractFloat}) center(::Ball2) +rand(::Type{Ball2}) ``` Inherited from [`LazySet`](@ref): * [`norm`](@ref norm(::LazySet, ::Real)) @@ -43,6 +44,7 @@ center(::BallInf) radius(::BallInf, ::Real) radius_hyperrectangle(::BallInf) radius_hyperrectangle(::BallInf, ::Int) +rand(::Type{BallInf}) ``` Inherited from [`LazySet`](@ref): * [`diameter`](@ref diameter(::LazySet, ::Real)) @@ -72,6 +74,7 @@ Ball1 ∈(::AbstractVector{Real}, ::Ball1{Real}) vertices_list(::Ball1) center(::Ball1) +rand(::Type{Ball1}) constraints_list(::Ball1) ``` Inherited from [`LazySet`](@ref): @@ -95,6 +98,7 @@ Ballp σ(::AbstractVector{AbstractFloat}, ::Ballp{AbstractFloat}) ∈(::AbstractVector{AbstractFloat}, ::Ballp{AbstractFloat}) center(::Ballp) +rand(::Type{Ballp}) ``` Inherited from [`LazySet`](@ref): * [`norm`](@ref norm(::LazySet, ::Real)) diff --git a/docs/src/lib/utils.md b/docs/src/lib/utils.md index b542554ace..6f3d1e7f49 100644 --- a/docs/src/lib/utils.md +++ b/docs/src/lib/utils.md @@ -30,6 +30,7 @@ binary_search_constraints nonzero_indices samedir reseed +rand_ball ``` ### Types diff --git a/src/Ball1.jl b/src/Ball1.jl index 7d9248fd1d..6dcf8b530d 100644 --- a/src/Ball1.jl +++ b/src/Ball1.jl @@ -1,4 +1,5 @@ -import Base.∈ +import Base: rand, + ∈ export Ball1 @@ -183,6 +184,39 @@ function ∈(x::AbstractVector{N}, B::Ball1{N})::Bool where {N<:Real} return sum <= B.radius end +""" + rand(::Type{Ball1}; [N]::Type{<:Real}=Float64, [dim]::Int=2, + [rng]::AbstractRNG=GLOBAL_RNG, [seed]::Union{Int, Nothing}=nothing + )::Ball1{N} + +Create a random ball in the 1-norm. + +### Input + +- `Ball1` -- type for dispatch +- `N` -- (optional, default: `Float64`) numeric type +- `dim` -- (optional, default: 2) dimension +- `rng` -- (optional, default: `GLOBAL_RNG`) random number generator +- `seed` -- (optional, default: `nothing`) seed for reseeding + +### Output + +A random ball in the 1-norm. + +### Algorithm + +See [`rand_ball`](@ref) for creating a random ball. +""" +function rand(::Type{Ball1}; + N::Type{<:Real}=Float64, + dim::Int=2, + rng::AbstractRNG=GLOBAL_RNG, + seed::Union{Int, Nothing}=nothing + )::Ball1{N} + center, radius = rand_ball(N, dim, rng, seed) + return Ball1(center, radius) +end + """ constraints_list(P::Ball1{N})::Vector{LinearConstraint{N}} where {N<:Real} diff --git a/src/Ball2.jl b/src/Ball2.jl index 69b7ff7aa0..97083dfc23 100644 --- a/src/Ball2.jl +++ b/src/Ball2.jl @@ -1,4 +1,5 @@ -import Base.∈ +import Base: rand, + ∈ export Ball2 @@ -173,3 +174,36 @@ function ∈(x::AbstractVector{N}, B::Ball2{N})::Bool where {N<:AbstractFloat} end return sqrt(sum) <= B.radius end + +""" + rand(::Type{Ball2}; [N]::Type{<:Real}=Float64, [dim]::Int=2, + [rng]::AbstractRNG=GLOBAL_RNG, [seed]::Union{Int, Nothing}=nothing + )::Ball2{N} + +Create a random ball in the 2-norm. + +### Input + +- `Ball2` -- type for dispatch +- `N` -- (optional, default: `Float64`) numeric type +- `dim` -- (optional, default: 2) dimension +- `rng` -- (optional, default: `GLOBAL_RNG`) random number generator +- `seed` -- (optional, default: `nothing`) seed for reseeding + +### Output + +A random ball in the 2-norm. + +### Algorithm + +See [`rand_ball`](@ref) for creating a random ball. +""" +function rand(::Type{Ball2}; + N::Type{<:Real}=Float64, + dim::Int=2, + rng::AbstractRNG=GLOBAL_RNG, + seed::Union{Int, Nothing}=nothing + )::Ball2{N} + center, radius = rand_ball(N, dim, rng, seed) + return Ball2(center, radius) +end diff --git a/src/BallInf.jl b/src/BallInf.jl index 023cde7fed..db9719f8a9 100644 --- a/src/BallInf.jl +++ b/src/BallInf.jl @@ -1,3 +1,5 @@ +import Base.rand + export BallInf """ @@ -51,6 +53,7 @@ end BallInf(center::Vector{N}, radius::N) where {N<:Real} = BallInf{N}(center, radius) + # --- AbstractHyperrectangle interface functions --- @@ -136,3 +139,36 @@ 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 + +""" + rand(::Type{BallInf}; [N]::Type{<:Real}=Float64, [dim]::Int=2, + [rng]::AbstractRNG=GLOBAL_RNG, [seed]::Union{Int, Nothing}=nothing + )::BallInf{N} + +Create a random ball in the infinity norm. + +### Input + +- `BallInf` -- type for dispatch +- `N` -- (optional, default: `Float64`) numeric type +- `dim` -- (optional, default: 2) dimension +- `rng` -- (optional, default: `GLOBAL_RNG`) random number generator +- `seed` -- (optional, default: `nothing`) seed for reseeding + +### Output + +A random ball in the infinity norm. + +### Algorithm + +See [`rand_ball`](@ref) for creating a random ball. +""" +function rand(::Type{BallInf}; + N::Type{<:Real}=Float64, + dim::Int=2, + rng::AbstractRNG=GLOBAL_RNG, + seed::Union{Int, Nothing}=nothing + )::BallInf{N} + center, radius = rand_ball(N, dim, rng, seed) + return BallInf(center, radius) +end diff --git a/src/Ballp.jl b/src/Ballp.jl index 1c70ee216e..306697c670 100644 --- a/src/Ballp.jl +++ b/src/Ballp.jl @@ -1,4 +1,5 @@ -import Base.∈ +import Base: rand, + ∈ export Ballp @@ -195,3 +196,39 @@ function ∈(x::AbstractVector{N}, B::Ballp{N})::Bool where {N<:AbstractFloat} end return sum^(one(N)/B.p) <= B.radius end + +""" + rand(::Type{Ballp}; [N]::Type{<:Real}=Float64, [dim]::Int=2, + [rng]::AbstractRNG=GLOBAL_RNG, [seed]::Union{Int, Nothing}=nothing + )::Ballp{N} + +Create a random ball in the p-norm. + +### Input + +- `Ballp` -- type for dispatch +- `N` -- (optional, default: `Float64`) numeric type +- `dim` -- (optional, default: 2) dimension +- `rng` -- (optional, default: `GLOBAL_RNG`) random number generator +- `seed` -- (optional, default: `nothing`) seed for reseeding + +### Output + +A random ball in the p-norm. + +### Algorithm + +See [`rand_ball`](@ref) for creating a random ball. +The p-norm is a normally distributed number ≥ 1 with mean 1 and standard +deviation 1. +""" +function rand(::Type{Ballp}; + N::Type{<:Real}=Float64, + dim::Int=2, + rng::AbstractRNG=GLOBAL_RNG, + seed::Union{Int, Nothing}=nothing + )::Ballp{N} + center, radius = rand_ball(N, dim, rng, seed) + p = one(N) + abs(randn(rng, N)) + return Ballp(p, center, radius) +end diff --git a/src/helper_functions.jl b/src/helper_functions.jl index eb4704d7f6..f0f692309a 100644 --- a/src/helper_functions.jl +++ b/src/helper_functions.jl @@ -204,6 +204,40 @@ function reseed(rng::AbstractRNG, seed::Union{Int, Nothing})::AbstractRNG return rng end +""" + rand_ball(N::Type{<:Real}=Float64, dim::Int=2, + rng::AbstractRNG=Base.GLOBAL_RNG, + seed::Union{Int, Nothing}=nothing)::Tuple{Vector{N}, N} + +Create a raw random ball (center and radius). + +### Input + +- `N` -- (optional, default: `Float64`) numeric type +- `dim` -- (optional, default: 2) dimension +- `rng` -- (optional, default: `GLOBAL_RNG`) random number generator +- `seed` -- (optional, default: `nothing`) seed for reseeding + +### Output + +A raw random ball (i.e., a center and a radius). + +### Algorithm + +All numbers are normally distributed with mean 0 and standard deviation 1. +Additionally, the radius is nonnegative. +""" +function rand_ball(N::Type{<:Real}=Float64, + dim::Int=2, + rng::AbstractRNG=Base.GLOBAL_RNG, + seed::Union{Int, Nothing}=nothing + )::Tuple{Vector{N}, N} + rng = reseed(rng, seed) + center = randn(rng, N, dim) + radius = abs(randn(rng, N)) + return (center, radius) +end + """ @neutral(SET, NEUT) diff --git a/test/unit_Ball1.jl b/test/unit_Ball1.jl index 79954503ff..5e7660d9cc 100644 --- a/test/unit_Ball1.jl +++ b/test/unit_Ball1.jl @@ -1,4 +1,7 @@ for N in [Float64, Rational{Int}, Float32] + # random ball + rand(Ball1) + # 1D Ball1 b = Ball1(N[0], N(1)) # dimension diff --git a/test/unit_Ball2.jl b/test/unit_Ball2.jl index 28de0808d0..a62eb34d63 100644 --- a/test/unit_Ball2.jl +++ b/test/unit_Ball2.jl @@ -1,4 +1,7 @@ for N in [Float64, Float32] + # random ball + rand(Ball2) + # 1D Ball2 b = Ball2(N[0], N(1)) # Test Dimension diff --git a/test/unit_BallInf.jl b/test/unit_BallInf.jl index 771c85d382..be055d2f9c 100644 --- a/test/unit_BallInf.jl +++ b/test/unit_BallInf.jl @@ -1,4 +1,7 @@ for N in [Float64, Rational{Int}, Float32] + # random ball + rand(BallInf) + # 1D BallInf b = BallInf(N[0], N(1)) # Test Dimension diff --git a/test/unit_Ballp.jl b/test/unit_Ballp.jl index 80d6b445a7..e68a50501e 100644 --- a/test/unit_Ballp.jl +++ b/test/unit_Ballp.jl @@ -1,4 +1,7 @@ for N in [Float64, Float32] + # random ball + rand(Ballp) + # 1D Ball3 b = Ballp(N(3), N[0], N(1)) # dimension