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

#964 - Check if polytope is bounded on construction #978

Merged
merged 5 commits into from
Jan 19, 2019
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
1 change: 1 addition & 0 deletions docs/src/lib/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ addconstraint!(::AbstractHPolygon{N}, ::LinearConstraint{N}) where {N<:Real}
addconstraint!(::Vector{LinearConstraint{N}}, ::LinearConstraint{N}) where {N<:Real}
constraints_list(::AbstractHPolygon{N}) where {N<:Real}
vertices_list(::AbstractHPolygon{N}, ::Bool=false, ::Bool=true) where {N<:Real}
isbounded(::AbstractHPolygon, ::Bool=true)
```

### Centrally symmetric polytope
Expand Down
6 changes: 3 additions & 3 deletions docs/src/lib/representations.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,6 @@ Inherited from [`LazySet`](@ref):
* [`diameter`](@ref diameter(::LazySet, ::Real))

Inherited from [`AbstractPolytope`](@ref):
* [`isbounded`](@ref isbounded(::AbstractPolytope))
* [`isempty`](@ref isempty(::AbstractPolytope))
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})
* [`linear_map`](@ref linear_map(::AbstractMatrix{N}, ::AbstractPolytope{N}) where {N<:Real})
Expand All @@ -342,6 +341,7 @@ Inherited from [`AbstractHPolygon`](@ref):
* [`vertices_list`](@ref vertices_list(::AbstractHPolygon{N}, ::Bool=false, ::Bool=true) where {N<:Real})
* [`tohrep`](@ref tohrep(::HPOLYGON) where {HPOLYGON<:AbstractHPolygon})
* [`tovrep`](@ref tovrep(::AbstractHPolygon{N}) where {N<:Real})
* [`isbounded`](@ref isbounded(::AbstractHPolygon, ::Bool=true))
* [`addconstraint!`](@ref addconstraint!(::AbstractHPolygon{N}, ::LinearConstraint{N}) where {N<:Real})
* [`constraints_list`](@ref constraints_list(::AbstractHPolygon{N}) where {N<:Real})

Expand All @@ -357,7 +357,6 @@ Inherited from [`LazySet`](@ref):
* [`diameter`](@ref diameter(::LazySet, ::Real))

Inherited from [`AbstractPolytope`](@ref):
* [`isbounded`](@ref isbounded(::AbstractPolytope))
* [`isempty`](@ref isempty(::AbstractPolytope))
* [`singleton_list`](@ref singleton_list(::AbstractPolytope{N}) where {N<:Real})
* [`linear_map`](@ref linear_map(::AbstractMatrix{N}, ::AbstractPolytope{N}) where {N<:Real})
Expand All @@ -371,6 +370,7 @@ Inherited from [`AbstractHPolygon`](@ref):
* [`vertices_list`](@ref vertices_list(::AbstractHPolygon{N}, ::Bool=false, ::Bool=true) where {N<:Real})
* [`tohrep`](@ref tohrep(::HPOLYGON) where {HPOLYGON<:AbstractHPolygon})
* [`tovrep`](@ref tovrep(::AbstractHPolygon{N}) where {N<:Real})
* [`isbounded`](@ref isbounded(::AbstractHPolygon, ::Bool=true))
* [`addconstraint!`](@ref addconstraint!(::AbstractHPolygon{N}, ::LinearConstraint{N}) where {N<:Real})
* [`constraints_list`](@ref constraints_list(::AbstractHPolygon{N}) where {N<:Real})

Expand Down Expand Up @@ -460,10 +460,10 @@ The following methods are specific for `HPolytope`.
```@docs
rand(::Type{HPolytope})
vertices_list(::HPolytope{N}) where {N<:Real}
isbounded(::HPolytope, ::Bool=true)
```

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

#### Polyhedra
Expand Down
31 changes: 30 additions & 1 deletion src/AbstractHPolygon.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ export AbstractHPolygon,
an_element,
addconstraint!,
vertices_list,
constraints_list
constraints_list,
isbounded

# This constant marks the threshold for the number of constraints of a polygon
# above which we use a binary search to find the relevant constraint in a
Expand Down Expand Up @@ -378,3 +379,31 @@ function binary_search_constraints(d::AbstractVector{N},
return upper
end
end

"""
isbounded(P::AbstractHPolygon, [use_type_assumption]::Bool=true)::Bool

Determine whether a polygon in constraint representation is bounded.

### Input

- `P` -- polygon in constraint representation
- `use_type_assumption` -- (optional, default: `true`) flag for ignoring the
type assumption that polygons are bounded

### Output

`true` if `use_type_assumption` is activated.
Otherwise, `true` iff `P` is bounded.

### Algorithm

If `!use_type_assumption`, we convert `P` to an `HPolyhedron` `P2` and then use
`isbounded(P2)`.
"""
function isbounded(P::AbstractHPolygon, use_type_assumption::Bool=true)::Bool
if use_type_assumption
return true
end
return isbounded(HPolyhedron(P.constraints))
end
29 changes: 19 additions & 10 deletions src/HPolygon.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ are sorted in counter-clockwise fashion with respect to their normal directions.

### Fields

- `constraints` -- list of linear constraints, sorted by the angle
- `constraints` -- list of linear constraints, sorted by the angle
- `sort_constraints` -- (optional, default: `true`) flag for sorting the
constraints (sortedness is a running assumption of this
type)
- `check_boundedness` -- (optional, default: `false`) flag for checking if the
constraints make the polygon bounded; (boundedness is a
running assumption of this type)

### Notes

Expand All @@ -22,41 +28,44 @@ Use `addconstraint!` to iteratively add the edges in a sorted way.
-- default constructor
- `HPolygon()`
-- constructor with no constraints
- `HPolygon(S::LazySet)` -- constructor from another set
"""
struct HPolygon{N<:Real} <: AbstractHPolygon{N}
constraints::Vector{LinearConstraint{N}}

# default constructor that applies sorting of the given constraints
function HPolygon{N}(constraints::Vector{LinearConstraint{N}};
sort_constraints::Bool=true) where {N<:Real}
sort_constraints::Bool=true,
schillic marked this conversation as resolved.
Show resolved Hide resolved
check_boundedness::Bool=false) where {N<:Real}
if sort_constraints
sorted_constraints = Vector{LinearConstraint{N}}()
sizehint!(sorted_constraints, length(constraints))
for ci in constraints
addconstraint!(sorted_constraints, ci)
end
return new{N}(sorted_constraints)
P = new{N}(sorted_constraints)
else
return new{N}(constraints)
P = new{N}(constraints)
end
@assert (!check_boundedness ||
isbounded(P, false)) "the polygon is not bounded"
return P
end
end

# convenience constructor without type parameter
HPolygon(constraints::Vector{LinearConstraint{N}};
sort_constraints::Bool=true) where {N<:Real} =
HPolygon{N}(constraints; sort_constraints=sort_constraints)
sort_constraints::Bool=true,
check_boundedness::Bool=false) where {N<:Real} =
HPolygon{N}(constraints;
sort_constraints=sort_constraints,
check_boundedness=check_boundedness)

# constructor for an HPolygon with no constraints
HPolygon{N}() where {N<:Real} = HPolygon{N}(Vector{LinearConstraint{N}}())

# constructor for an HPolygon with no constraints of type Float64
HPolygon() = HPolygon{Float64}()

# conversion constructor
HPolygon(S::LazySet) = convert(HPolygon, S)


# --- LazySet interface functions ---

Expand Down
49 changes: 29 additions & 20 deletions src/HPolygonOpt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ This is a refined version of `HPolygon`.

### Fields

- `constraints` -- list of linear constraints
- `ind` -- index in the list of constraints to begin the search to evaluate the
support function
- `constraints` -- list of linear constraints
- `ind` -- index in the list of constraints to begin the search
to evaluate the support function
- `sort_constraints` -- (optional, default: `true`) flag for sorting the
constraints (sortedness is a running assumption of this
type)
- `check_boundedness` -- (optional, default: `false`) flag for checking if the
constraints make the polygon bounded; (boundedness is a
running assumption of this type)

### Notes

Expand All @@ -26,9 +32,8 @@ The default constructor assumes that the given list of edges is sorted.
It *does not perform* any sorting.
Use `addconstraint!` to iteratively add the edges in a sorted way.

- `HPolygonOpt(constraints::Vector{LinearConstraint{<:Real}}, [ind]::Int)`
- `HPolygonOpt(constraints::Vector{LinearConstraint{<:Real}}, [ind]::Int=1)`
-- default constructor with optional index
- `HPolygonOpt(S::LazySet)` -- constructor from another set
"""
mutable struct HPolygonOpt{N<:Real} <: AbstractHPolygon{N}
constraints::Vector{LinearConstraint{N}}
Expand All @@ -37,36 +42,40 @@ mutable struct HPolygonOpt{N<:Real} <: AbstractHPolygon{N}
# default constructor that applies sorting of the given constraints
function HPolygonOpt{N}(constraints::Vector{LinearConstraint{N}},
ind::Int=1;
sort_constraints::Bool=true) where {N<:Real}
sort_constraints::Bool=true,
check_boundedness::Bool=false) where {N<:Real}
if sort_constraints
sorted_constraints = Vector{LinearConstraint{N}}()
sizehint!(sorted_constraints, length(constraints))
for ci in constraints
addconstraint!(sorted_constraints, ci)
end
return new{N}(sorted_constraints, ind)
P = new{N}(sorted_constraints, ind)
else
return new{N}(constraints, ind)
P = new{N}(constraints, ind)
end
@assert (!check_boundedness ||
isbounded(P, false)) "the polygon is not bounded"
return P
end
end

# convenience constructor without type parameter
HPolygonOpt(constraints::Vector{LinearConstraint{N}},
ind::Int=1) where {N<:Real} =
HPolygonOpt{N}(constraints, ind)

# constructor for an HPolygon with no constraints
HPolygonOpt{N}() where {N<:Real} =
HPolygonOpt{N}(Vector{LinearConstraint{N}}())

# constructor for an HPolygon with no constraints of type Float64
ind::Int=1;
sort_constraints::Bool=true,
check_boundedness::Bool=false) where {N<:Real} =
HPolygonOpt{N}(constraints,
ind;
sort_constraints=sort_constraints,
check_boundedness=check_boundedness)

# constructor for an HPolygonOpt with no constraints
HPolygonOpt{N}() where {N<:Real} = HPolygonOpt{N}(Vector{LinearConstraint{N}}())

# constructor for an HPolygonOpt with no constraints of type Float64
HPolygonOpt() = HPolygonOpt{Float64}()

# conversion constructor
HPolygonOpt(S::LazySet) = convert(HPolygonOpt, S)



# --- LazySet interface functions ---

Expand Down
64 changes: 56 additions & 8 deletions src/HPolytope.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import Base.rand

export HPolytope,
vertices_list
vertices_list,
isbounded

"""
HPolytope{N<:Real} <: AbstractPolytope{N}
Expand All @@ -10,7 +11,10 @@ Type that represents a convex polytope in H-representation.

### Fields

- `constraints` -- vector of linear constraints
- `constraints` -- vector of linear constraints
- `check_boundedness` -- (optional, default: `false`) flag for checking if the
constraints make the polytope bounded; (boundedness is
a running assumption of this type)

### Note

Expand All @@ -19,28 +23,43 @@ assumption in this type.
"""
struct HPolytope{N<:Real} <: AbstractPolytope{N}
constraints::Vector{LinearConstraint{N}}

function HPolytope{N}(constraints::Vector{LinearConstraint{N}};
check_boundedness::Bool=false
) where {N<:Real}
P = new{N}(constraints)
@assert (!check_boundedness ||
isbounded(P, false)) "the polytope is not bounded"
return P
end
end

# convenience constructor without type parameter
HPolytope(constraints::Vector{LinearConstraint{N}};
check_boundedness::Bool=false) where {N<:Real} =
HPolytope{N}(constraints; check_boundedness=check_boundedness)

# constructor for an HPolytope with no constraints
HPolytope{N}() where {N<:Real} = HPolytope{N}(Vector{LinearConstraint{N}}())

# constructor for an HPolytope with no constraints of type Float64
HPolytope() = HPolytope{Float64}()

# conversion constructor
HPolytope(S::LazySet) = convert(HPolytope, S)

# constructor for an HPolytope from a simple H-representation
function HPolytope(A::AbstractMatrix{N}, b::AbstractVector{N}) where {N<:Real}
function HPolytope(A::AbstractMatrix{N}, b::AbstractVector{N};
check_boundedness::Bool=false) where {N<:Real}
m = size(A, 1)
constraints = LinearConstraint{N}[]
@inbounds for i in 1:m
push!(constraints, LinearConstraint(A[i, :], b[i]))
end
return HPolytope(constraints)
return HPolytope(constraints; check_boundedness=check_boundedness)
end

HPolytope{N}(A::AbstractMatrix{N}, b::AbstractVector{N}) where {N<:Real} = HPolytope(A, b)
HPolytope{N}(A::AbstractMatrix{N}, b::AbstractVector{N};
check_boundedness::Bool=false) where {N<:Real} =
HPolytope(A, b; check_boundedness=check_boundedness)


# --- LazySet interface functions ---

Expand Down Expand Up @@ -87,6 +106,35 @@ function rand(::Type{HPolytope};
return convert(HPolytope, vpolytope)
end

"""
isbounded(P::HPolytope, [use_type_assumption]::Bool=true)::Bool

Determine whether a polytope in constraint representation is bounded.

### Input

- `P` -- polytope in constraint representation
- `use_type_assumption` -- (optional, default: `true`) flag for ignoring the
type assumption that polytopes are bounded

### Output

`true` if `use_type_assumption` is activated.
Otherwise, `true` iff `P` is bounded.

### Algorithm

If `!use_type_assumption`, we convert `P` to an `HPolyhedron` `P2` and then use
`isbounded(P2)`.
"""
function isbounded(P::HPolytope, use_type_assumption::Bool=true)::Bool
if use_type_assumption
return true
end
return isbounded(HPolyhedron(P.constraints))
end



# --- functions that use Polyhedra.jl ---

Expand Down
Loading