From 8b319486d1cb722aceb96830f44dc6d6114487c9 Mon Sep 17 00:00:00 2001 From: schillic Date: Thu, 10 Jan 2019 20:47:01 +0100 Subject: [PATCH 1/5] numeric conversion for HalfSpace --- src/HalfSpace.jl | 7 ++++++- test/unit_HalfSpace.jl | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/HalfSpace.jl b/src/HalfSpace.jl index 01ad3e23ac..0d4d889557 100644 --- a/src/HalfSpace.jl +++ b/src/HalfSpace.jl @@ -1,6 +1,7 @@ import Base: rand, ∈, - isempty + isempty, + convert export HalfSpace, LinearConstraint, an_element, @@ -31,6 +32,10 @@ struct HalfSpace{N<:Real} <: LazySet{N} b::N end +function convert(::Type{HalfSpace{N}}, hs::HalfSpace) where {N<:Real} + return HalfSpace{N}(hs.a, hs.b) +end + """ LinearConstraint diff --git a/test/unit_HalfSpace.jl b/test/unit_HalfSpace.jl index 71b74cc3d4..7f3eeb0abe 100644 --- a/test/unit_HalfSpace.jl +++ b/test/unit_HalfSpace.jl @@ -6,6 +6,11 @@ for N in [Float64, Rational{Int}, Float32] normal = ones(N, 3) hs = HalfSpace(normal, N(5)) + # numeric-type conversion preserves vector base type + hs1 = HalfSpace(spzeros(4), 1.) + hs2 = convert(HalfSpace{N}, hs1) + @test hs2.a isa SparseVector{N} + # dimension @test dim(hs) == 3 From 37422fcf00f501a0cbb7b8b29034039c5d84a31c Mon Sep 17 00:00:00 2001 From: schillic Date: Thu, 10 Jan 2019 20:48:35 +0100 Subject: [PATCH 2/5] make tohrep and tovrep preserve numeric type --- src/HPolyhedron.jl | 6 +++++- src/VPolytope.jl | 6 +++++- test/unit_Polytope.jl | 8 ++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/HPolyhedron.jl b/src/HPolyhedron.jl index 6e711a575a..7f89d1d3ff 100644 --- a/src/HPolyhedron.jl +++ b/src/HPolyhedron.jl @@ -601,7 +601,11 @@ function tovrep(P::HPoly{N}; @assert isdefined(@__MODULE__, :Polyhedra) "the function `tovrep` needs " * "the package 'Polyhedra' to be loaded" P = polyhedron(P; backend=backend) - return VPolytope(P) + Q = VPolytope(P) + if Q isa VPolytope{N} + return Q + end + return VPolytope{N}(vertices_list(Q)) end """ diff --git a/src/VPolytope.jl b/src/VPolytope.jl index 2f5e295179..3fd919886e 100644 --- a/src/VPolytope.jl +++ b/src/VPolytope.jl @@ -273,7 +273,11 @@ function tohrep(P::VPolytope{N}; backend=default_polyhedra_backend(P, N)) where {N<:Real} @assert isdefined(@__MODULE__, :Polyhedra) "the function `tohrep` needs the " * "package 'Polyhedra' to be loaded" - return HPolytope(polyhedron(P; backend=backend)) + Q = HPolytope(polyhedron(P; backend=backend)) + if Q isa HPolytope{N} + return Q + end + return HPolytope{N}(constraints_list(Q)) end """ diff --git a/test/unit_Polytope.jl b/test/unit_Polytope.jl index 79e1edafc8..6d30607208 100644 --- a/test/unit_Polytope.jl +++ b/test/unit_Polytope.jl @@ -190,8 +190,8 @@ if test_suite_polyhedra A = [N(0) N(-1); N(-1) N(0); N(1) N(1)] b = N[-0.25, -0.25, -0] P = HPolytope(A, b) - @test tovrep(P) isa VPolytope - @test tohrep(P) isa HPolytope # test no-op + @test tovrep(P) isa VPolytope{N} + @test tohrep(P) isa HPolytope{N} # no-op # checking for emptiness P = HPolytope([LinearConstraint(N[1, 0], N(0))]) # x <= 0 @@ -246,7 +246,7 @@ if test_suite_polyhedra # tohrep from VPolytope P = VPolytope([v1, v2, v3, v4, v5]) - @test tohrep(P) isa HPolytope - @test tovrep(P) isa VPolytope # no-op + @test tohrep(P) isa HPolytope{N} + @test tovrep(P) isa VPolytope{N} # no-op end end From d937f451a329b4b50d06d3c7a47d2ba262f900b4 Mon Sep 17 00:00:00 2001 From: schillic Date: Fri, 11 Jan 2019 17:51:33 +0100 Subject: [PATCH 3/5] undo manual type conversion --- src/HPolyhedron.jl | 15 +++++++-------- src/VPolytope.jl | 20 +++++++++++--------- test/unit_Polytope.jl | 34 ++++++++++++++++++++++------------ 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/HPolyhedron.jl b/src/HPolyhedron.jl index 7f89d1d3ff..6b3e6d55a9 100644 --- a/src/HPolyhedron.jl +++ b/src/HPolyhedron.jl @@ -582,9 +582,9 @@ Transform a polyhedron in H-representation to a polytope in V-representation. ### Input -- `P` -- polyhedron in constraint representation -- `backend` -- (optional, default: `default_polyhedra_backend(P, N)`) - the polyhedral computations backend +- `P` -- polyhedron in constraint representation +- `backend` -- (optional, default: `default_polyhedra_backend(P, N)`) the + backend for polyhedral computations ### Output @@ -594,7 +594,7 @@ in constraint representation. ### Notes For further information on the supported backends see -[Polyhedra's documentation](https://juliapolyhedra.github.io/Polyhedra.jl/). +[Polyhedra's documentation](https://juliapolyhedra.github.io/Polyhedra.jl/latest/installation.html#Getting-Libraries-1). """ function tovrep(P::HPoly{N}; backend=default_polyhedra_backend(P, N)) where {N<:Real} @@ -602,10 +602,9 @@ function tovrep(P::HPoly{N}; "the package 'Polyhedra' to be loaded" P = polyhedron(P; backend=backend) Q = VPolytope(P) - if Q isa VPolytope{N} - return Q - end - return VPolytope{N}(vertices_list(Q)) + @assert Q isa VPolytope{N} "'polyhedron' did not preserve the numeric " * + "type; consider using a different polyhedra backend" + return Q end """ diff --git a/src/VPolytope.jl b/src/VPolytope.jl index 3fd919886e..b395ade790 100644 --- a/src/VPolytope.jl +++ b/src/VPolytope.jl @@ -258,26 +258,28 @@ Transform a polytope in V-representation to a polytope in H-representation. ### Input -- `P` -- polytope in vertex representation -- `backend` -- (optional, default: `default_polyhedra_backend(P, N)`) the polyhedral - computations backend, - see [Polyhedra's documentation](https://juliapolyhedra.github.io/Polyhedra.jl/latest/installation.html#Getting-Libraries-1) - for further information +- `P` -- polytope in vertex representation +- `backend` -- (optional, default: `default_polyhedra_backend(P, N)`) the + backend for polyhedral computations ### Output The `HPolytope` which is the constraint representation of the given polytope in vertex representation. + +### Notes + +For further information on the supported backends see +[Polyhedra's documentation](https://juliapolyhedra.github.io/Polyhedra.jl/latest/installation.html#Getting-Libraries-1). """ function tohrep(P::VPolytope{N}; backend=default_polyhedra_backend(P, N)) where {N<:Real} @assert isdefined(@__MODULE__, :Polyhedra) "the function `tohrep` needs the " * "package 'Polyhedra' to be loaded" Q = HPolytope(polyhedron(P; backend=backend)) - if Q isa HPolytope{N} - return Q - end - return HPolytope{N}(constraints_list(Q)) + @assert Q isa HPolytope{N} "'polyhedron' did not preserve the numeric " * + "type; consider using a different polyhedra backend" + return Q end """ diff --git a/test/unit_Polytope.jl b/test/unit_Polytope.jl index 6d30607208..e6a7b8a120 100644 --- a/test/unit_Polytope.jl +++ b/test/unit_Polytope.jl @@ -135,6 +135,28 @@ end @test HPolytope() isa HPolytope{Float64} @test VPolytope() isa VPolytope{Float64} +# Polyhedra tests that do not work with Float32 +if test_suite_polyhedra + for N in [Float64, Rational{Int}] + # tovrep from HPolytope + A = [N(0) N(-1); N(-1) N(0); N(1) N(1)] + b = N[-0.25, -0.25, -0] + P = HPolytope(A, b) + @test tovrep(P) isa VPolytope{N} + @test tohrep(P) isa HPolytope{N} # no-op + + # tohrep from VPolytope + v1 = N[1, 0] + v2 = N[0, 1] + v3 = N[-1, 0] + v4 = N[0, -1] + v5 = N[0, 0] + P = VPolytope([v1, v2, v3, v4, v5]) + @test tohrep(P) isa HPolytope{N} + @test tovrep(P) isa VPolytope{N} # no-op + end +end + # Polyhedra tests that only work with Float64 if test_suite_polyhedra for N in [Float64] @@ -186,13 +208,6 @@ if test_suite_polyhedra vl = vertices_list(p) @test ispermutation(vl, [N[0], N[1]]) - # tovrep from HPolytope - A = [N(0) N(-1); N(-1) N(0); N(1) N(1)] - b = N[-0.25, -0.25, -0] - P = HPolytope(A, b) - @test tovrep(P) isa VPolytope{N} - @test tohrep(P) isa HPolytope{N} # no-op - # checking for emptiness P = HPolytope([LinearConstraint(N[1, 0], N(0))]) # x <= 0 @test !isempty(P) @@ -243,10 +258,5 @@ if test_suite_polyhedra cp = cartesian_product(p1, p2) vl = vertices_list(cp) @test ispermutation(vl, [N[0, 0, 2], N[1, 1, 2]]) - - # tohrep from VPolytope - P = VPolytope([v1, v2, v3, v4, v5]) - @test tohrep(P) isa HPolytope{N} - @test tovrep(P) isa VPolytope{N} # no-op end end From bbf85e81c76b235b08fa6ed49f76d0888b6dcd85 Mon Sep 17 00:00:00 2001 From: schillic Date: Sat, 12 Jan 2019 18:00:36 +0100 Subject: [PATCH 4/5] only warn about numeric-type conversion in docs --- src/HPolyhedron.jl | 7 +++---- src/VPolytope.jl | 7 +++---- test/unit_Polytope.jl | 35 +++++++++++++++++++---------------- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/HPolyhedron.jl b/src/HPolyhedron.jl index 6b3e6d55a9..91e98db08b 100644 --- a/src/HPolyhedron.jl +++ b/src/HPolyhedron.jl @@ -593,6 +593,8 @@ in constraint representation. ### Notes +The conversion may not preserve the numeric type (e.g., with `N == Float32`) +depending on the backend. For further information on the supported backends see [Polyhedra's documentation](https://juliapolyhedra.github.io/Polyhedra.jl/latest/installation.html#Getting-Libraries-1). """ @@ -601,10 +603,7 @@ function tovrep(P::HPoly{N}; @assert isdefined(@__MODULE__, :Polyhedra) "the function `tovrep` needs " * "the package 'Polyhedra' to be loaded" P = polyhedron(P; backend=backend) - Q = VPolytope(P) - @assert Q isa VPolytope{N} "'polyhedron' did not preserve the numeric " * - "type; consider using a different polyhedra backend" - return Q + return VPolytope(P) end """ diff --git a/src/VPolytope.jl b/src/VPolytope.jl index b395ade790..3b630ec0b4 100644 --- a/src/VPolytope.jl +++ b/src/VPolytope.jl @@ -269,6 +269,8 @@ in vertex representation. ### Notes +The conversion may not preserve the numeric type (e.g., with `N == Float32`) +depending on the backend. For further information on the supported backends see [Polyhedra's documentation](https://juliapolyhedra.github.io/Polyhedra.jl/latest/installation.html#Getting-Libraries-1). """ @@ -276,10 +278,7 @@ function tohrep(P::VPolytope{N}; backend=default_polyhedra_backend(P, N)) where {N<:Real} @assert isdefined(@__MODULE__, :Polyhedra) "the function `tohrep` needs the " * "package 'Polyhedra' to be loaded" - Q = HPolytope(polyhedron(P; backend=backend)) - @assert Q isa HPolytope{N} "'polyhedron' did not preserve the numeric " * - "type; consider using a different polyhedra backend" - return Q + return HPolytope(polyhedron(P; backend=backend)) end """ diff --git a/test/unit_Polytope.jl b/test/unit_Polytope.jl index e6a7b8a120..4be8d673b9 100644 --- a/test/unit_Polytope.jl +++ b/test/unit_Polytope.jl @@ -138,22 +138,25 @@ end # Polyhedra tests that do not work with Float32 if test_suite_polyhedra for N in [Float64, Rational{Int}] - # tovrep from HPolytope - A = [N(0) N(-1); N(-1) N(0); N(1) N(1)] - b = N[-0.25, -0.25, -0] - P = HPolytope(A, b) - @test tovrep(P) isa VPolytope{N} - @test tohrep(P) isa HPolytope{N} # no-op - - # tohrep from VPolytope - v1 = N[1, 0] - v2 = N[0, 1] - v3 = N[-1, 0] - v4 = N[0, -1] - v5 = N[0, 0] - P = VPolytope([v1, v2, v3, v4, v5]) - @test tohrep(P) isa HPolytope{N} - @test tovrep(P) isa VPolytope{N} # no-op + # CDDLib does not preserve the Rational{Int} type + if VERSION >= v"0.7" || N == Float64 + # tovrep from HPolytope + A = [N(0) N(-1); N(-1) N(0); N(1) N(1)] + b = N[-0.25, -0.25, -0] + P = HPolytope(A, b) + @test tovrep(P) isa VPolytope{N} + @test tohrep(P) isa HPolytope{N} # no-op + + # tohrep from VPolytope + v1 = N[1, 0] + v2 = N[0, 1] + v3 = N[-1, 0] + v4 = N[0, -1] + v5 = N[0, 0] + P = VPolytope([v1, v2, v3, v4, v5]) + @test tohrep(P) isa HPolytope{N} + @test tovrep(P) isa VPolytope{N} # no-op + end end end From 646daf37a5bc4be0010f421ab6caf999e3aa5b3e Mon Sep 17 00:00:00 2001 From: schillic Date: Sat, 12 Jan 2019 18:18:56 +0100 Subject: [PATCH 5/5] fix unit test (see #994) --- test/unit_Polytope.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit_Polytope.jl b/test/unit_Polytope.jl index 4be8d673b9..25debd5499 100644 --- a/test/unit_Polytope.jl +++ b/test/unit_Polytope.jl @@ -141,8 +141,8 @@ if test_suite_polyhedra # CDDLib does not preserve the Rational{Int} type if VERSION >= v"0.7" || N == Float64 # tovrep from HPolytope - A = [N(0) N(-1); N(-1) N(0); N(1) N(1)] - b = N[-0.25, -0.25, -0] + A = N[0 1; 1 0; -1 -1] + b = N[0.25, 0.25, -0] P = HPolytope(A, b) @test tovrep(P) isa VPolytope{N} @test tohrep(P) isa HPolytope{N} # no-op