From 464da43f50513b05a8b28d186b657c0486129872 Mon Sep 17 00:00:00 2001 From: mforets Date: Mon, 24 Jun 2019 23:09:59 -0300 Subject: [PATCH 1/4] write non-sorting functions for two points convex hull --- src/concrete_convex_hull.jl | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/concrete_convex_hull.jl b/src/concrete_convex_hull.jl index bef36e422b..9a782763bc 100644 --- a/src/concrete_convex_hull.jl +++ b/src/concrete_convex_hull.jl @@ -103,7 +103,7 @@ function convex_hull!(points::Vector{VN}; if n == 1 # dimensional check if m == 2 # two points case in 1d - return _two_points_1d!(points) + return _two_points_1d!(points, false) else # general case in 1d return _convex_hull_1d!(points) @@ -111,7 +111,7 @@ function convex_hull!(points::Vector{VN}; elseif n == 2 if m == 2 # two points case in 2d - return _two_points_2d!(points) + return _two_points_2d!(points, false) elseif m == 3 # three points case in 2d return _three_points_2d!(points) @@ -128,10 +128,9 @@ function convex_hull!(points::Vector{VN}; end end -function _two_points_1d!(points) +function _two_points_1d!(points, sort=Val(true)) p1, p2 = points[1], points[2] - if p1 == p2 - # check for redundancy + if _isapprox(p1, p2) # check for redundancy pop!(points) elseif p1[1] > p2[1] points[1], points[2] = p2, p1 @@ -139,11 +138,17 @@ function _two_points_1d!(points) return points end -function _two_points_2d!(points) - # special case, see #876 +function _two_points_1d!(points, sort=Val(false)) + p1, p2 = points[1], points[2] + if _isapprox(p1, p2) # check for redundancy + pop!(points) + end + return points +end + +function _two_points_2d!(points, sort=Val(true)) p1, p2 = points[1], points[2] - if p1 == p2 - # check for redundancy + if isapprox(p1[1], p2[1]) && _isapprox(p1[2], p2[2]) # check for redundancy pop!(points) elseif p1 <= p2 nothing @@ -153,6 +158,14 @@ function _two_points_2d!(points) return points end +function _two_points_2d!(points, sort=Val(false)) + p1, p2 = points[1], points[2] + if _isapprox(p1[1], p2[1]) && _isapprox(p1[2], p2[2]) # check for redundancy + pop!(points) + end + return points +end + function _three_points_2d!(points::AbstractVector{<:AbstractVector{N}}) where {N<:Real} # Algorithm: the function takes three points and uses the formula # from here: https://stackoverflow.com/questions/2122305/convex-hull-of-4-points/2122620#2122620 From 6ed1ec5db8a1ca76dbbf12a8f1d8aa8516b1606d Mon Sep 17 00:00:00 2001 From: mforets Date: Mon, 24 Jun 2019 23:30:46 -0300 Subject: [PATCH 2/4] remove code that sorts --- src/concrete_convex_hull.jl | 32 +++++--------------------------- test/unit_convex_hull.jl | 4 ++-- 2 files changed, 7 insertions(+), 29 deletions(-) diff --git a/src/concrete_convex_hull.jl b/src/concrete_convex_hull.jl index 9a782763bc..9ebab74310 100644 --- a/src/concrete_convex_hull.jl +++ b/src/concrete_convex_hull.jl @@ -103,7 +103,7 @@ function convex_hull!(points::Vector{VN}; if n == 1 # dimensional check if m == 2 # two points case in 1d - return _two_points_1d!(points, false) + return _two_points_1d!(points) else # general case in 1d return _convex_hull_1d!(points) @@ -111,7 +111,7 @@ function convex_hull!(points::Vector{VN}; elseif n == 2 if m == 2 # two points case in 2d - return _two_points_2d!(points, false) + return _two_points_2d!(points) elseif m == 3 # three points case in 2d return _three_points_2d!(points) @@ -128,37 +128,15 @@ function convex_hull!(points::Vector{VN}; end end -function _two_points_1d!(points, sort=Val(true)) - p1, p2 = points[1], points[2] - if _isapprox(p1, p2) # check for redundancy - pop!(points) - elseif p1[1] > p2[1] - points[1], points[2] = p2, p1 - end - return points -end - -function _two_points_1d!(points, sort=Val(false)) - p1, p2 = points[1], points[2] - if _isapprox(p1, p2) # check for redundancy - pop!(points) - end - return points -end - -function _two_points_2d!(points, sort=Val(true)) +function _two_points_1d!(points) p1, p2 = points[1], points[2] - if isapprox(p1[1], p2[1]) && _isapprox(p1[2], p2[2]) # check for redundancy + if _isapprox(p1[1], p2[1]) # check for redundancy pop!(points) - elseif p1 <= p2 - nothing - else - points[1], points[2] = p2, p1 end return points end -function _two_points_2d!(points, sort=Val(false)) +function _two_points_2d!(points) p1, p2 = points[1], points[2] if _isapprox(p1[1], p2[1]) && _isapprox(p1[2], p2[2]) # check for redundancy pop!(points) diff --git a/test/unit_convex_hull.jl b/test/unit_convex_hull.jl index 98fa97220e..d4cee54d5c 100644 --- a/test/unit_convex_hull.jl +++ b/test/unit_convex_hull.jl @@ -6,7 +6,7 @@ for N in [Float64, Rational{Int}] # corner cases in dimension 1 @test convex_hull([Vector{N}(undef, 0)]) == [Vector{N}(undef, 0)] @test convex_hull([[N(0)]]) == [[N(0)]] - @test convex_hull([[N(2)], [N(1)]]) == [[N(1)], [N(2)]] + @test convex_hull([[N(2)], [N(1)]]) == [[N(2)], [N(1)]] @test convex_hull([[N(2)], [N(2)]]) == [[N(2)]] # corner cases in dimension 2 @@ -19,7 +19,7 @@ for N in [Float64, Rational{Int}] p2 = [1., 3.] @test convex_hull([p1]) == [p1] @test convex_hull([p1, p2]) == [p1, p2] - @test convex_hull([p2, p1]) == [p1, p2] + @test convex_hull([p2, p1]) == [p2, p1] # no sorting # corner cases in higher dimension @test convex_hull([[N(0), N(0), N(0)]]) == [[N(0), N(0), N(0)]] From 8417b431bfee9583f780f109c8931ab1aa2bfa1d Mon Sep 17 00:00:00 2001 From: mforets Date: Wed, 26 Jun 2019 11:20:18 -0300 Subject: [PATCH 3/4] use ispermutation (needs 1439) --- test/unit_Zonotope.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit_Zonotope.jl b/test/unit_Zonotope.jl index 57cdfcb89a..48d6d5fb62 100644 --- a/test/unit_Zonotope.jl +++ b/test/unit_Zonotope.jl @@ -219,6 +219,6 @@ for N in [Float64] # constraints_list for generator matrix with a zero row Z = Zonotope(N[0, 0], N[2 3; 0 0]) P = tovrep(HPolygon(constraints_list(Z))) - @test vertices_list(P) ≈ [N[5, 0], [-5, 0]] + @test ispermutation(vertices_list(P), [N[5, 0], [-5, 0]]) end end From 0a701b1fa573c9dba0341e43b3543d9ef88c2e94 Mon Sep 17 00:00:00 2001 From: mforets Date: Sat, 29 Jun 2019 21:54:43 -0300 Subject: [PATCH 4/4] fix test --- test/unit_convex_hull.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/unit_convex_hull.jl b/test/unit_convex_hull.jl index d4cee54d5c..50d23b51cf 100644 --- a/test/unit_convex_hull.jl +++ b/test/unit_convex_hull.jl @@ -6,7 +6,7 @@ for N in [Float64, Rational{Int}] # corner cases in dimension 1 @test convex_hull([Vector{N}(undef, 0)]) == [Vector{N}(undef, 0)] @test convex_hull([[N(0)]]) == [[N(0)]] - @test convex_hull([[N(2)], [N(1)]]) == [[N(2)], [N(1)]] + @test ispermutation(convex_hull([N[2], N[1]]), [N[2], N[1]]) @test convex_hull([[N(2)], [N(2)]]) == [[N(2)]] # corner cases in dimension 2 @@ -18,8 +18,7 @@ for N in [Float64, Rational{Int}] p1 = [1., 2.] p2 = [1., 3.] @test convex_hull([p1]) == [p1] - @test convex_hull([p1, p2]) == [p1, p2] - @test convex_hull([p2, p1]) == [p2, p1] # no sorting + @test ispermutation(convex_hull([p1, p2]), [p1, p2]) # corner cases in higher dimension @test convex_hull([[N(0), N(0), N(0)]]) == [[N(0), N(0), N(0)]]