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 more and better operations for Interval #3533

Merged
merged 17 commits into from
Jul 2, 2024
Merged
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
57 changes: 49 additions & 8 deletions docs/src/lib/sets/Interval.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,9 @@ chebyshev_center_radius(::Interval)
constraints_list(::Interval)
diameter(::Interval, ::Real=Inf)
dim(::Interval)
high(::Interval)
∈(::AbstractVector, ::Interval)
isflat(::Interval)
linear_map(::AbstractMatrix, ::Interval)
low(::Interval)
min(::Interval)
max(::Interval)
ngens(::Interval)
radius_hyperrectangle(::Interval)
radius_hyperrectangle(::Interval{N}, ::Int) where {N}
Expand All @@ -52,6 +48,8 @@ isdisjoint(::Interval, ::Interval, ::Bool=false)
minkowski_difference(::Interval, ::Interval)
minkowski_sum(::Interval, ::Interval)
plot_recipe(::Interval{N}, ::Any=zero(N)) where {N}
min(::Interval)
max(::Interval)
-(::Interval, ::Interval)
*(::Interval, ::Interval)
```
Expand All @@ -61,21 +59,65 @@ CurrentModule = LazySets.API
```

Undocumented implementations:
* [`affine_map`](@ref affine_map(::AbstractMatrix, ::LazySet, ::AbstractVector))
* [`complement`](@ref complement(::LazySet))
* [`exponential_map`](@ref exponential_map(::AbstractMatrix, ::LazySet))
* [`extrema`](@ref extrema(::LazySet))
* [`extrema`](@ref extrema(::LazySet, ::Int))
* [`high`](@ref high(::LazySet, ::Int))
* [`high`](@ref high(::LazySet))
* [`isoperationtype`](@ref isoperationtype(::Type{<:LazySet}))
* [`low`](@ref low(::LazySet, ::Int))
* [`low`](@ref low(::LazySet))
* [`norm`](@ref norm(::LazySet, ::Real))
* [`permute`](@ref permute(::LazySet, ::AbstractVector{Int}))
* [`project`](@ref project(::LazySet, ::AbstractVector{Int}))
* [`radius`](@ref radius(::LazySet, ::Real))
* [`volume`](@ref volume(::LazySet))
* [`convex_hull`](@ref convex_hull(::LazySet, ::LazySet))
* [`distance`](@ref distance(::LazySet, ::LazySet))
* [`≈`](@ref ≈(::LazySet, ::LazySet))
* [`isequivalent`](@ref isequivalent(::LazySet, ::LazySet))
* [`⊂`](@ref ⊂(::LazySet, ::LazySet))

```@meta
CurrentModule = LazySets
```

Inherited from [`LazySet`](@ref):
* [`concretize`](@ref concretize(::LazySet))
* [`constraints`](@ref constraints(::LazySet))
* [`eltype`](@ref eltype(::Type{<:LazySet}))
* [`eltype`](@ref eltype(::LazySet))
* [`isoperation`](@ref isoperation(::LazySet))
* [`singleton_list`](@ref singleton_list(::LazySet))
* [`vertices`](@ref vertices(::LazySet))
* [`is_interior_point`](@ref is_interior_point(::AbstractVector, ::LazySet))
* [`sample`](@ref sample(::LazySet, ::Int))
* [`==`](@ref ==(::LazySet, ::LazySet))

Inherited from [`AbstractPolyhedron`](@ref):
* [`is_polyhedral`](@ref is_polyhedral(::AbstractPolyhedron))

Inherited from [`ConvexSet`](@ref):

```@meta
CurrentModule = LazySets.API
```

* [`linear_combination`](@ref linear_combination(::LazySet, ::LazySet))

```@meta
CurrentModule = LazySets
```

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

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

Inherited from [`AbstractZonotope`](@ref):
* [`order`](@ref order(::AbstractZonotope))
Expand All @@ -84,9 +126,8 @@ Inherited from [`AbstractZonotope`](@ref):
Inherited from [`AbstractHyperrectangle`](@ref):
* [`generators`](@ref generators(::AbstractHyperrectangle))
* [`genmat`](@ref genmat(::AbstractHyperrectangle))
* [`high`](@ref high(::AbstractHyperrectangle, ::Int))
* [`low`](@ref low(::AbstractHyperrectangle, ::Int))
* [`norm`](@ref norm(::AbstractHyperrectangle, ::Real))
* [`isconvextype`](@ref isconvextype(::Type{<:AbstractHyperrectangle}))
* [`cartesian_product`](@ref cartesian_product(::AbstractHyperrectangle, ::AbstractHyperrectangle))

Some additional functionality is available for `IntervalArithmetic.Interval`s:

Expand Down
2 changes: 2 additions & 0 deletions src/API/Binary/linear_combination.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,7 @@ The linear combination of two sets ``X`` and ``Y`` is defined as
```math
\\left\\{\\frac{1}{2}(1+λ)x + \\frac{1}{2}(1-λ)y \\mid x ∈ X, y ∈ Y, λ ∈ [-1, 1]\\right\\}.
```

If ``X`` and ``Y`` are convex, their linear combination is identical with their convex hull.
"""
function linear_combination(::LazySet, ::LazySet) end
4 changes: 4 additions & 0 deletions src/ConcreteOperations/linear_combination.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,7 @@ function linear_combination(P1::SimpleSparsePolynomialZonotope,

return SimpleSparsePolynomialZonotope(c, G, E)
end

function linear_combination(X::ConvexSet, Y::ConvexSet)
return convex_hull(X, Y)
end
3 changes: 3 additions & 0 deletions src/Interfaces/LazySet.jl
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,9 @@ end
The default implementation applies the functions `exp` and `linear_map`.
"""
function exponential_map(M::AbstractMatrix, X::LazySet)
n = dim(X)
@assert size(M) == (n, n) "cannot apply an exponential map of dimension " *
"$(size(M)) to an $n-dimensional set"
return linear_map(exp(M), X)
end

Expand Down
26 changes: 20 additions & 6 deletions src/Sets/Interval/IntervalModule.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ using ReachabilityBase.Comparison
using ReachabilityBase.Distribution: reseed!
import IntervalArithmetic as IA

@reexport import ..API: an_element, center, constraints_list, diameter, dim, high, ∈,
isoperationtype, linear_map, low, rand, rectify, reflect, scale, ρ, σ,
translate, vertices_list,
difference, intersection, isdisjoint, ⊆, minkowski_difference,
minkowski_sum
@reexport import ..API: affine_map, an_element, center, complement, constraints_list,
convex_hull, diameter, dim, exponential_map, extrema, high, ∈,
isoperationtype, linear_map, low, norm, permute, project, rand,
rectify, reflect, scale, ρ, σ, translate, vertices_list, volume,
difference, distance, intersection, ≈, isdisjoint, isequivalent,
⊂, ⊆, minkowski_difference, minkowski_sum
@reexport import ..LazySets: chebyshev_center_radius, isflat, ngens, plot_recipe,
radius_hyperrectangle, split
import Base: convert, -, *, min, max
Expand All @@ -25,20 +26,28 @@ export Interval

include("Interval.jl")

include("affine_map.jl")
include("an_element.jl")
include("center.jl")
include("chebyshev_center_radius.jl")
include("complement.jl")
include("constraints_list.jl")
include("convert.jl")
include("convex_hull.jl")
include("diameter.jl")
include("dim.jl")
include("exponential_map.jl")
include("extrema.jl")
include("high.jl")
include("in.jl")
include("isflat.jl")
include("isoperationtype.jl")
include("linear_map.jl")
include("low.jl")
include("isoperationtype.jl")
include("ngens.jl")
include("norm.jl")
include("permute.jl")
include("project.jl")
include("radius.jl")
include("radius_hyperrectangle.jl")
include("rand.jl")
Expand All @@ -50,10 +59,15 @@ include("support_vector.jl")
include("support_function.jl")
include("translate.jl")
include("vertices_list.jl")
include("volume.jl")

include("difference.jl")
include("distance.jl")
include("intersection.jl")
include("isapprox.jl")
include("isdisjoint.jl")
include("isequivalent.jl")
include("isstrictsubset.jl")
include("issubset.jl")
include("minkowski_difference.jl")
include("minkowski_sum.jl")
Expand Down
10 changes: 10 additions & 0 deletions src/Sets/Interval/affine_map.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
function affine_map(M, X::Interval, v::AbstractVector; kwargs...)
@assert size(M, 2) == 1 "cannot apply an affine map of dimension $(size(M, 2)) " *
"to an interval"
@assert size(M, 1) == length(v) "cannot apply an affine map of matrix dimension " *
"$(size(M, 1)) and translation dimension $(length(v))"
@inbounds if length(v) == 1
return Interval(M[1, 1] * X.dat + v[1])
end
return translate(linear_map(M, X; kwargs...), v)
end
6 changes: 6 additions & 0 deletions src/Sets/Interval/complement.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
function complement(X::Interval)
N = eltype(X)
L = HalfSpace(SingleEntryVector(1, 1, one(N)), min(X))
H = HalfSpace(SingleEntryVector(1, 1, -one(N)), -max(X))
return UnionSet(L, H)
end
3 changes: 3 additions & 0 deletions src/Sets/Interval/convex_hull.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function convex_hull(I1::Interval, I2::Interval)
return Interval(min(min(I1), min(I2)), max(max(I1), max(I2)))
end
7 changes: 7 additions & 0 deletions src/Sets/Interval/distance.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
function distance(X::Interval, Y::Interval; p::Real=2)
schillic marked this conversation as resolved.
Show resolved Hide resolved
d = max(min(X) - max(Y), min(Y) - max(X))
if d < 0
return zero(d)
end
return d
end
6 changes: 6 additions & 0 deletions src/Sets/Interval/exponential_map.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
function exponential_map(M::AbstractMatrix, X::Interval)
@assert size(M) == (1, 1) "cannot apply an exponential map of dimension " *
"$(size(M)) to an interval"
@inbounds e = exp(M[1, 1])
return Interval(e * X.dat)
end
12 changes: 12 additions & 0 deletions src/Sets/Interval/extrema.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# the implementations here are equivalent to the default implementation for
# `LazySet`, but more efficient than the more specific implementations for
# subtypes

function extrema(X::Interval, i::Int)
@assert i == 1 "an interval has dimension 1, but the index is $i"
return (min(X), max(X))
end

function extrema(X::Interval)
return ([min(X)], [max(X)])
end
20 changes: 6 additions & 14 deletions src/Sets/Interval/high.jl
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
"""
high(x::Interval)

Return the higher coordinate of an interval set.

### Input

- `x` -- interval

### Output
function high(X::Interval, i::Int)
@assert i == 1 "an interval has dimension 1, but the index is $i"
return max(X)
end

A vector with the higher coordinate of the interval.
"""
function high(x::Interval)
return [x.dat.hi]
function high(X::Interval)
return [max(X)]
end
3 changes: 3 additions & 0 deletions src/Sets/Interval/isapprox.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function ≈(I1::Interval, I2::Interval)
return _isapprox(min(I1), min(I2)) && _isapprox(max(I1), max(I2))
end
3 changes: 3 additions & 0 deletions src/Sets/Interval/isequivalent.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function isequivalent(I1::Interval, I2::Interval)
return I1 ≈ I2
end
11 changes: 11 additions & 0 deletions src/Sets/Interval/isstrictsubset.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function ⊂(X::Interval, Y::Interval, witness::Bool=false)
if min(X) < min(Y) || max(X) > max(Y)
return _witness_result_empty(witness, false, X, Y)
end
if min(X) > min(Y)
return witness ? (true, low(Y)) : true
elseif max(Y) > max(X)
return witness ? (true, high(Y)) : true
end
return _witness_result_empty(witness, false, X, Y)
end
20 changes: 6 additions & 14 deletions src/Sets/Interval/low.jl
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
"""
low(x::Interval)

Return the lower coordinate of an interval set.

### Input

- `x` -- interval

### Output
function low(X::Interval, i::Int)
@assert i == 1 "an interval has dimension 1, but the index is $i"
return min(X)
end

A vector with the lower coordinate of the interval.
"""
function low(x::Interval)
return [x.dat.lo]
function low(X::Interval)
return [min(X)]
end
3 changes: 3 additions & 0 deletions src/Sets/Interval/norm.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function norm(X::Interval, p::Real=Inf)
return max(abs(min(X)), abs(max(X)))
end
4 changes: 4 additions & 0 deletions src/Sets/Interval/permute.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
function permute(X::Interval, p::AbstractVector{Int})
@assert length(p) == 1 && p[1] == 1 "invalid permutation vector $p"
return X
end
4 changes: 4 additions & 0 deletions src/Sets/Interval/project.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
function project(X::Interval, block::AbstractVector{Int}; kwargs...)
@assert length(block) == 1 && block[1] == 1 "invalid permutation vector $block"
return X
end
3 changes: 3 additions & 0 deletions src/Sets/Interval/volume.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function volume(X::Interval)
return max(X) - min(X)
end
Loading
Loading