diff --git a/src/Approximations/Approximations.jl b/src/Approximations/Approximations.jl index e4828f5930..a03bfdf985 100644 --- a/src/Approximations/Approximations.jl +++ b/src/Approximations/Approximations.jl @@ -40,6 +40,7 @@ include("box_approximations.jl") include("template_directions.jl") include("overapproximate.jl") include("underapproximate.jl") +include("approximate.jl") include("decompositions.jl") include("distance.jl") include("hausdorff_distance.jl") diff --git a/src/Approximations/approximate.jl b/src/Approximations/approximate.jl new file mode 100644 index 0000000000..50e4fb2cf9 --- /dev/null +++ b/src/Approximations/approximate.jl @@ -0,0 +1,42 @@ +""" + approximate(R::Rectification; apply_convex_hull::Bool=false) + +Approximate a rectification of a polytopic set with a convex polytope. + +### Input + +- `R` -- rectification +- `apply_convex_hull` -- (optional; default: `false`) option to remove redundant + vertices + +### Output + +A polytope in vertex representation. +There is no guarantee that the result over- or underapproximates `R`. + +### Algorithm + +Let ``X`` be the set that is rectified. +We compute the vertices of ``X``, rectify them, and return the convex hull of +the result. + +### Notes + +Let ``X`` be the set that is rectified and let ``p`` and ``q`` be two vertices +on a facet of ``X``. +Intuitively, an approximation may occur if the line segment connecting these +vertices crosses a coordinate hyperplane and if the line segment connecting the +rectified vertices has a different angle. + +As a corollary, the approximation is exact for the special cases that the +original set is contained in either the positive or negative orthant or +is axis-aligned. +""" +function approximate(R::Rectification; apply_convex_hull::Bool=false) + vlist = [rectify(v) for v in vertices_list(set(R))] + if apply_convex_hull + vlist = convex_hull(vlist) + end + T = dim(R) == 2 ? VPolygon : VPolytope + return T(vlist) +end diff --git a/test/unit_approximate.jl b/test/unit_approximate.jl new file mode 100644 index 0000000000..2f69db3d9a --- /dev/null +++ b/test/unit_approximate.jl @@ -0,0 +1,22 @@ +for N in [Float64, Rational{Int}, Float32] + # approximate rectification by rectifying the vertices + # - exact approximation + X = Ball1(N[1, 1], N(1)) + Y = approximate(Rectification(X)) + @test isequivalent(Y, X) + # - underapproximation + X = Ball1(N[2, 2], N(3)) + Y = approximate(Rectification(X)) + Z = VPolygon([N[5, 2], N[2, 5], N[2, 0], N[0, 2]]) + @test Y ⊆ Z && Z ⊆ Y + # - overapproximation + X = Ball1(N[-1, -1], N(2)) + Y = approximate(Rectification(X)) + Z = VPolygon([N[0, 0], N[0, 1], N[1, 0]]) + @test Y ⊆ Z && Z ⊆ Y + # - neither over- nor underapproximation + X = VPolygon([N[3, 2], N[1, -1], N[-1, 2], N[-1, 4]]) + Y = approximate(Rectification(X)) + Z = VPolygon([N[3, 2], N[1, 0], N[0, 2], N[0, 4]]) + @test Y ⊆ Z && Z ⊆ Y +end