Skip to content

Commit

Permalink
Merge pull request #779 from JuliaReach/rip_upper_bound
Browse files Browse the repository at this point in the history
RIP upper_bound
  • Loading branch information
mforets authored Oct 13, 2018
2 parents d291c74 + 67327e7 commit 239022a
Show file tree
Hide file tree
Showing 9 changed files with 278 additions and 471 deletions.
6 changes: 0 additions & 6 deletions docs/src/lib/approximations.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,3 @@ BoxDiagDirections
```

See also `overapproximate(X::LazySet, dir::AbstractDirections)::HPolytope`.

## Upper bounds

```@docs
ρ_upper_bound
```
1 change: 0 additions & 1 deletion src/Approximations/Approximations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,5 @@ include("box_approximations.jl")
include("template_directions.jl")
include("overapproximate.jl")
include("decompositions.jl")
include("upper_bounds.jl")

end # module
46 changes: 16 additions & 30 deletions src/Approximations/box_approximations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
# ===================================

"""
box_approximation(S::LazySet; upper_bound::Bool=false)::Hyperrectangle
box_approximation(S::LazySet)::Hyperrectangle
Overapproximate a convex set by a tight hyperrectangle.
### Input
- `S` -- convex set
- `upper_bound` -- (optional, default: `false`) use overapproximation in support
function computation?
### Output
Expand All @@ -24,20 +22,19 @@ of the given set in the canonical directions, and the lengths of the sides can
be recovered from the distance among support functions in the same directions.
"""
function box_approximation(S::LazySet{N};
upper_bound::Bool=false
)::Union{Hyperrectangle{N}, EmptySet{N}} where N<:Real
(c, r) = box_approximation_helper(S; upper_bound=upper_bound)
if upper_bound && r[1] < 0
(c, r) = box_approximation_helper(S)
if r[1] < 0
return EmptySet{N}()
end
return Hyperrectangle(c, r)
end

# special case: Hyperrectangle
box_approximation(S::Hyperrectangle; upper_bound::Bool=false) = S
box_approximation(S::Hyperrectangle) = S

# special case: other rectangle
box_approximation(S::AbstractHyperrectangle; upper_bound::Bool=false) =
box_approximation(S::AbstractHyperrectangle) =
Hyperrectangle(center(S), radius_hyperrectangle(S))

"""
Expand All @@ -48,7 +45,7 @@ Alias for `box_approximation`.
interval_hull = box_approximation

"""
box_approximation_symmetric(S::LazySet{N}; upper_bound::Bool=false
box_approximation_symmetric(S::LazySet{N}
)::Union{Hyperrectangle{N}, EmptySet{N}}
where {N<:Real}
Expand All @@ -57,8 +54,6 @@ Overapproximate a convex set by a tight hyperrectangle centered in the origin.
### Input
- `S` -- convex set
- `upper_bound` -- (optional, default: `false`) use overapproximation in support
function computation?
### Output
Expand All @@ -70,11 +65,10 @@ The center of the box is the origin, and the radius is obtained by computing the
maximum value of the support function evaluated at the canonical directions.
"""
function box_approximation_symmetric(S::LazySet{N};
upper_bound::Bool=false
)::Union{Hyperrectangle{N},
EmptySet{N}} where {N<:Real}
(c, r) = box_approximation_helper(S; upper_bound=upper_bound)
if upper_bound && r[1] < 0
(c, r) = box_approximation_helper(S)
if r[1] < 0
return EmptySet{N}()
end
return Hyperrectangle(zeros(N, length(c)), abs.(c) .+ r)
Expand All @@ -88,16 +82,14 @@ Alias for `box_approximation_symmetric`.
symmetric_interval_hull = box_approximation_symmetric

"""
box_approximation_helper(S::LazySet{N}; upper_bound::Bool=false
box_approximation_helper(S::LazySet{N};
) where {N<:Real}
Common code of `box_approximation` and `box_approximation_symmetric`.
### Input
- `S` -- convex set
- `upper_bound` -- (optional, default: `false`) use overapproximation in support
function computation?
### Output
Expand All @@ -115,24 +107,22 @@ The lengths of the sides can be recovered from the distance among support
functions in the same directions.
"""
@inline function box_approximation_helper(S::LazySet{N};
upper_bound::Bool=false
) where {N<:Real}
zero_N = zero(N)
one_N = one(N)
ρ_rec = upper_bound ? ρ_upper_bound : ρ
n = dim(S)
c = Vector{N}(undef, n)
r = Vector{N}(undef, n)
d = zeros(N, n)
@inbounds for i in 1:n
d[i] = one_N
htop = ρ_rec(d, S)
htop = ρ(d, S)
d[i] = -one_N
hbottom = -ρ_rec(d, S)
hbottom = -ρ(d, S)
d[i] = zero_N
c[i] = (htop + hbottom) / 2
r[i] = (htop - hbottom) / 2
if upper_bound && r[i] < 0
if r[i] < 0
# contradicting bounds => set is empty
# terminate with first radius entry being negative
r[1] = r[i]
Expand All @@ -143,16 +133,14 @@ functions in the same directions.
end

"""
ballinf_approximation(S::LazySet{N}; upper_bound::Bool=false
ballinf_approximation(S::LazySet{N};
)::BallInf{N} where {N<:Real}
Overapproximate a convex set by a tight ball in the infinity norm.
### Input
- `S` -- convex set
- `upper_bound` -- (optional, default: `false`) use overapproximation in support
function computation?
### Output
Expand All @@ -164,26 +152,24 @@ The center and radius of the box are obtained by evaluating the support function
of the given convex set along the canonical directions.
"""
function ballinf_approximation(S::LazySet{N};
upper_bound::Bool=false
)::Union{BallInf{N}, EmptySet{N}} where {N<:Real}
zero_N = zero(N)
one_N = one(N)
ρ_rec = upper_bound ? ρ_upper_bound : ρ
n = dim(S)
c = Vector{N}(undef, n)
r = zero_N
d = zeros(N, n)
@inbounds for i in 1:n
d[i] = one_N
htop = ρ_rec(d, S)
htop = ρ(d, S)
d[i] = -one_N
hbottom = -ρ_rec(d, S)
hbottom = -ρ(d, S)
d[i] = zero_N
c[i] = (htop + hbottom) / 2
rcur = (htop - hbottom) / 2
if (rcur > r)
r = rcur
elseif upper_bound && rcur < 0
elseif rcur < 0
# contradicting bounds => set is empty
return EmptySet{N}()
end
Expand Down
51 changes: 14 additions & 37 deletions src/Approximations/overapproximate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,14 @@ Otherwise the result is an ε-close approximation as a polygon.
- `S` -- convex set, assumed to be two-dimensional
- `HPolygon` -- type for dispatch
- `ε` -- (optional, default: `Inf`) error bound
- `upper_bound` -- (optional, default: `false`) currently ignored
### Output
A polygon in constraint representation.
"""
function overapproximate(S::LazySet{N},
::Type{<:HPolygon},
ε::Real=Inf;
upper_bound::Bool=false
ε::Real=Inf
)::HPolygon where {N<:Real}
@assert dim(S) == 2
if ε == Inf
Expand All @@ -59,15 +57,14 @@ function overapproximate(S::LazySet{N},
end

"""
overapproximate(S::LazySet, ε::Real; [upper_bound]::Bool=false)::HPolygon
overapproximate(S::LazySet, ε::Real)::HPolygon
Alias for `overapproximate(S, HPolygon, ε, upper_bound=upper_bound)`.
Alias for `overapproximate(S, HPolygon, ε)`.
"""
function overapproximate(S::LazySet,
ε::Real;
upper_bound::Bool=false
)::HPolygon
return overapproximate(S, HPolygon, ε; upper_bound=upper_bound)
return overapproximate(S, HPolygon, ε)
end

"""
Expand All @@ -80,18 +77,15 @@ Return an approximation of a given set as a hyperrectangle.
- `S` -- set
- `Hyperrectangle` -- type for dispatch
- `upper_bound` -- (optional, default: `false`) use overapproximation in
support function computation?
### Output
A hyperrectangle.
"""
function overapproximate(S::LazySet,
::Type{<:Hyperrectangle};
upper_bound::Bool=false
)::Union{Hyperrectangle, EmptySet}
box_approximation(S; upper_bound=upper_bound)
box_approximation(S)
end

"""
Expand All @@ -100,22 +94,19 @@ end
Alias for `overapproximate(S, Hyperrectangle)`.
"""
overapproximate(S::LazySet;
upper_bound::Bool=false
)::Union{Hyperrectangle, EmptySet} =
overapproximate(S, Hyperrectangle; upper_bound=upper_bound)
overapproximate(S, Hyperrectangle)

"""
overapproximate(S::ConvexHull{N, Zonotope{N}, Zonotope{N}},
::Type{<:Zonotope};
[upper_bound]::Bool=false)::Zonotope where {N<:Real}
::Type{<:Zonotope})::Zonotope where {N<:Real}
Overapproximate the convex hull of two zonotopes.
### Input
- `S` -- convex hull of two zonotopes of the same order
- `Zonotope` -- type for dispatch
- `upper_bound` -- (optional, default: `false`) currently ignored
### Algorithm
Expand All @@ -134,8 +125,7 @@ zonotope, which is in general expensive in high dimensions. This is further inve
in: *Zonotopes as bounding volumes, L. J. Guibas et al, Proc. of Symposium on Discrete Algorithms, pp. 803-812*.
"""
function overapproximate(S::ConvexHull{N, Zonotope{N}, Zonotope{N}},
::Type{<:Zonotope};
upper_bound::Bool=false)::Zonotope where {N<:Real}
::Type{<:Zonotope})::Zonotope where {N<:Real}
Z1, Z2 = S.X, S.Y
@assert order(Z1) == order(Z2)
center = (Z1.center+Z2.center)/2
Expand All @@ -145,8 +135,7 @@ end

"""
overapproximate(X::LazySet,
dir::AbstractDirections;
[upper_bound]::Bool=false
dir::AbstractDirections
)::HPolytope
Overapproximating a set with template directions.
Expand All @@ -155,31 +144,26 @@ Overapproximating a set with template directions.
- `X` -- set
- `dir` -- direction representation
- `upper_bound` -- (optional, default: `false`) use overapproximation in support
function computation?
### Output
A `HPolytope` overapproximating the set `X` with the directions from `dir`.
"""
function overapproximate(X::LazySet{N},
dir::AbstractDirections{N};
upper_bound::Bool=false
)::HPolytope{N} where N
ρ_rec = upper_bound ? ρ_upper_bound : ρ
halfspaces = Vector{LinearConstraint{N}}()
sizehint!(halfspaces, length(dir))
H = HPolytope(halfspaces)
for d in dir
addconstraint!(H, LinearConstraint(d, ρ_rec(d, X)))
addconstraint!(H, LinearConstraint(d, ρ(d, X)))
end
return H
end

"""
overapproximate(S::LazySet{N},
::Type{Interval};
[upper_bound]::Bool=false
::Type{Interval}
) where {N<:Real}
Return the overapproximation of a real unidimensional set with an interval.
Expand All @@ -188,15 +172,13 @@ Return the overapproximation of a real unidimensional set with an interval.
- `S` -- one-dimensional set
- `Interval` -- type for dispatch
- `upper_bound` -- (optional, default: `false`) currently ignored
### Output
An interval.
"""
function overapproximate(S::LazySet{N},
::Type{Interval};
upper_bound::Bool=false
::Type{Interval}
) where {N<:Real}
@assert dim(S) == 1
lo = σ([-one(N)], S)[1]
Expand All @@ -207,7 +189,6 @@ end
"""
overapproximate(cap::Intersection{N, <:LazySet, S},
dir::AbstractDirections{N};
[upper_bound]::Bool=false,
kwargs...
) where {N<:Real, S<:AbstractPolytope{N}}
Expand All @@ -218,8 +199,6 @@ polytope given a set of template directions.
- `cap` -- intersection of a compact set and a polytope
- `dir` -- template directions
- `upper_bound` -- (optional, default: `false`) use overapproximation in support
function computation?
- `kwargs` -- additional arguments that are passed to the support function
algorithm
Expand Down Expand Up @@ -253,7 +232,6 @@ intersection is empty.
"""
function overapproximate(cap::Intersection{N, <:LazySet, S},
dir::AbstractDirections{N};
upper_bound::Bool=false,
kwargs...
) where {N<:Real, S<:AbstractPolytope{N}}

Expand All @@ -263,12 +241,11 @@ function overapproximate(cap::Intersection{N, <:LazySet, S},
Hi = constraints_list(P)
m = length(Hi)
Q = HPolytope{N}()
ρ_rec = upper_bound ? ρ_upper_bound : ρ

for di in dir
ρ_X_Hi_min = ρ_rec(di, X Hi[1], kwargs...)
ρ_X_Hi_min = ρ(di, X Hi[1], kwargs...)
for i in 2:m
ρ_X_Hi = ρ_rec(di, X Hi[i], kwargs...)
ρ_X_Hi = ρ(di, X Hi[i], kwargs...)
if ρ_X_Hi < ρ_X_Hi_min
ρ_X_Hi_min = ρ_X_Hi
end
Expand Down
Loading

0 comments on commit 239022a

Please sign in to comment.