diff --git a/src/Approximations/overapproximate.jl b/src/Approximations/overapproximate.jl index 52ccff7fb9..3dfbace713 100644 --- a/src/Approximations/overapproximate.jl +++ b/src/Approximations/overapproximate.jl @@ -137,7 +137,11 @@ end Alias for `overapproximate(S, HPolygon, ε)`. """ function overapproximate(S::LazySet, ε::Real) - return overapproximate(S, HPolygon, ε) + if dim(S) == 1 + return overapproximate(S, Interval) + else + return overapproximate(S, HPolygon, ε) + end end # special case: overapproximation of empty set diff --git a/src/LazyOperations/Intersection.jl b/src/LazyOperations/Intersection.jl index f6becba70a..7335557941 100644 --- a/src/LazyOperations/Intersection.jl +++ b/src/LazyOperations/Intersection.jl @@ -711,7 +711,7 @@ function plot_recipe(cap::Intersection{N}, ε::N=zero(N), if isempty(cap) return plot_recipe(EmptySet{N}(dim(cap)), ε) elseif dim(cap) == 1 - if !isconvextype(cap) + if !isconvextype(typeof(cap)) throw(ArgumentError("cannot plot a one-dimensional $(typeof(cap))")) end return plot_recipe(convert(Interval, cap), ε) diff --git a/src/Plotting/plot_recipes.jl b/src/Plotting/plot_recipes.jl index b4ccb9a251..6a4462b07a 100644 --- a/src/Plotting/plot_recipes.jl +++ b/src/Plotting/plot_recipes.jl @@ -193,6 +193,8 @@ function _plot_list_same_recipe(list::AbstractVector{VN}, ε::Real=N(PLOT_PRECIS for Xi in list if Xi isa Intersection res = plot_recipe(Xi, ε, Nφ) + elseif dim(Xi) == 1 + res = plot_recipe(Xi, ε) else # hard-code overapproximation here to avoid individual # compilations for mixed sets diff --git a/test/Utils/plot.jl b/test/Utils/plot.jl index d1de7821e9..0043869ca1 100644 --- a/test/Utils/plot.jl +++ b/test/Utils/plot.jl @@ -1,129 +1,186 @@ -using SparseArrays +using LinearAlgebra, SparseArrays +import Optim for N in [Float64, Float32, Rational{Int}] - p0 = zero(N) - p1 = one(N) - v0 = zeros(N, 2) - v1 = ones(N, 2) - - # --------------- - # set definitions - # --------------- - - # bounded basic set types - b1 = Ball1(v0, p1) - bi = BallInf(v0, p1) - hr = Hyperrectangle(v0, v1) - itv = Interval(p0, p1) - ls = LineSegment(v0, v1) - st = Singleton(v1) - zt = Zonotope(v0, Diagonal(N[1, 1])) - zs = ZeroSet{N}(2) - - # ------------------------------------------- - # plot polytopes - # ------------------------------------------- - plot(b1) - plot(bi) - plot(hr) - plot(itv) - plot(ls) - plot(st) - plot(zt) - plot(zs) - - if N == Rational{Int} - # rationals do not support epsilon-close approximation - continue - end - - # bounded basic set types which are not polytopes - b2 = Ball2(v0, p1) - bp = Ballp(N(1.5), v0, p1) - el = Ellipsoid(v0, Diagonal(N[1, 1])) - - # unary set operations - spI = SparseMatrixCSC{N}(2I, 2, 2) - smIe = SparseMatrixExp(spI) - em = ExponentialMap(smIe, b2) - psme = ProjectionSparseMatrixExp(spI, smIe, spI) - epm = ExponentialProjectionMap(psme, b2) - - # binary set operations - its = Intersection(b1, bi) - itsa = IntersectionArray([b1, bi]) - - # polygon/polytope types - constraints = [LinearConstraint([p1, p0], p1), - LinearConstraint([p0, p1], p1), - LinearConstraint([-p1, p0], p0), - LinearConstraint([p0, -p1], p0)] - hpg = HPolygon(constraints) - hpgo = HPolygonOpt(constraints) - hpt = HPolytope(constraints) - hpt_empty = HPolytope([HalfSpace(N[1, 0], N(0)), HalfSpace(N[-1, 0], N(-1)), - HalfSpace(N[0, 1], N(0)), HalfSpace(N[0, -1], N(0))]) - vertices = vertices_list(bi) - vpg = VPolygon(vertices) - vpt = VPolytope(vertices) - - # empty set - es = EmptySet{N}(2) - - # infinite sets - hs = HalfSpace(v1, p1) - hp = Hyperplane(v1, p1) - l = Line2D(v1, p1) - uni = Universe{N}(2) - - # unary set operations - sih = SymmetricIntervalHull(b1) - lm = LinearMap(N[2 1; 1 2], bi) - rm = ResetMap(bi, Dict(1 => N(1))) - - # binary set operations - ch = ConvexHull(b1, bi) - cha = ConvexHullArray([b1, bi]) - - ms = MinkowskiSum(b1, bi) - msa = MinkowskiSumArray([b1, bi]) - cms = CachedMinkowskiSumArray([b1, bi]) - cp = CartesianProduct(itv, itv) - cpa = CartesianProductArray([itv, itv]) - - # ------------------------------------------------------------------ - # plot using epsilon-close approximation (default threshold ε value) - # ------------------------------------------------------------------ - if N == Float64 # Float32 requires promotion see #1304 - plot(its) - end - plot(hpg) - plot(hpgo) - plot(hpt) - plot(hpt_empty) - plot(vpg) - plot(vpt) - plot(es) - plot(hs) - plot(hp) - plot(l) - plot(uni) - plot(ch) - plot(cha) - plot(sih) - plot(lm) - plot(rm) - plot(ms) - plot(msa) - plot(cms) - plot(cp) - plot(cpa) - - if N == Float64 - plot(itsa) + for n in [1, 2] + p0 = zero(N) + p1 = one(N) + v0 = zeros(N, n) + v1 = ones(N, n) + + # --------------- + # set definitions + # --------------- + + # bounded basic set types + b1 = Ball1(v0, p1) + bi = BallInf(v0, p1) + hr = Hyperrectangle(v0, v1) + st = Singleton(v1) + zt = Zonotope(v0, Diagonal(ones(N, n))) + zs = ZeroSet{N}(n) + itv = Interval(p0, p1) + if n == 2 + ls = LineSegment(v0, v1) + end + if N <: AbstractFloat # `convert` not available for non-float + hpa = convert(HParallelotope, hr) + end + + # ------------------------------------------- + # plot polytopes + # ------------------------------------------- + plot(b1) + plot(bi) + plot(hr) + plot(st) + plot(zt) + plot(zs) + if n == 1 + plot(itv) + elseif n == 2 + plot(ls) + end + if N <: AbstractFloat + plot(hpa) + end + + if N == Rational{Int} + # rationals do not support epsilon-close approximation + continue + end + + # bounded basic set types which are not polytopes + b2 = Ball2(v0, p1) + bp = Ballp(N(1.5), v0, p1) + el = Ellipsoid(v0, Diagonal(ones(N, n))) + # dpz = convert(DensePolynomialZonotope, zt) # TODO conversion currently missing + spz = convert(SparsePolynomialZonotope, zt) + sspz = convert(SimpleSparsePolynomialZonotope, zt) + if n == 2 + ncp = Polygon([v0, v1]) + end + + # unary set operations + spI = SparseMatrixCSC{N}(2I, n, n) + smIe = SparseMatrixExp(spI) + em = ExponentialMap(smIe, b2) + psme = ProjectionSparseMatrixExp(spI, smIe, spI) + epm = ExponentialProjectionMap(psme, b2) + + # binary set operations + its = Intersection(b1, bi) + itsa = IntersectionArray([b1, bi]) + + # polygon/polytope types + constraints = [LinearConstraint([p1, p0], p1), + LinearConstraint([p0, p1], p1), + LinearConstraint([-p1, p0], p0), + LinearConstraint([p0, -p1], p0)] + hpg = HPolygon(constraints) + hpgo = HPolygonOpt(constraints) + hpt = HPolytope(constraints) + hpt_empty = HPolytope([HalfSpace(N[1, 0], N(0)), HalfSpace(N[-1, 0], N(-1)), + HalfSpace(N[0, 1], N(0)), HalfSpace(N[0, -1], N(0))]) + vlist = vertices_list(bi) + if n == 2 + vpg = VPolygon(vlist) + end + vpt = VPolytope(vlist) + + # empty set + es = EmptySet{N}(n) + + # bounded sets + hs = HalfSpace(v1, p1) + hp = Hyperplane(v1, p1) + hph = HPolyhedron(constraints) + uni = Universe{N}(n) + l = Line(v0, v1) + if n == 2 + l2D = Line2D(v1, p1) + end + sta = convert(Star, bi) + + # unary set operations + sih = SymmetricIntervalHull(b1) + if n == 1 + lm = LinearMap(hcat(N[2]), bi) + elseif n == 2 + lm = LinearMap(N[2 1; 1 2], bi) + end + rm = ResetMap(bi, Dict(1 => N(1))) + + # binary set operations + ch = ConvexHull(b1, bi) + cha = ConvexHullArray([b1, bi]) + ms = MinkowskiSum(b1, bi) + msa = MinkowskiSumArray([b1, bi]) + cms = CachedMinkowskiSumArray([b1, bi]) + us = UnionSet(b1, bi) + usa = UnionSetArray([b1, bi]) + if n == 2 + cp = CartesianProduct(itv, itv) + cpa = CartesianProductArray([itv, itv]) + end + + # ------------------------------------------------------------------ + # plot using epsilon-close approximation (default threshold ε value) + # ------------------------------------------------------------------ + plot(b2) + plot(bp) + plot(el) + if n == 2 + plot(ncp) + end + if N == Float64 # Float32 requires promotion see #1304 + plot(its) + end + plot(hpg) + plot(hpgo) + plot(hpt) + plot(hpt_empty) + if n == 2 + plot(vpg) + end + plot(vpt) + plot(es) + plot(hs) + plot(hp) + plot(hph) + plot(uni) + plot(l) + if n == 2 + plot(l2D) + end + plot(sta) + plot(ch) + plot(cha) + plot(sih) + plot(lm) + plot(rm) + plot(ms) + plot(msa) + plot(cms) + if n == 2 + plot(cp) + plot(cpa) + end + if N == Float64 + plot(itsa) + end + + # recipes using kwargs are not supported with the workaround we use here + # @test_broken plot(dpz) + @test_broken plot(spz) + @test_broken plot(sspz) + @test_broken plot(us) + @test_broken plot(usa) end end +using StaticArrays + for N in [Float64] # test plot with static arrays input Z = Zonotope(SA[N(1), N(0)], SA[N(1) N(0); N(0) N(1)])