diff --git a/src/Interfaces/AbstractZonotope.jl b/src/Interfaces/AbstractZonotope.jl index 00287cbe56..f6082b82d1 100644 --- a/src/Interfaces/AbstractZonotope.jl +++ b/src/Interfaces/AbstractZonotope.jl @@ -304,8 +304,8 @@ A `Zonotope`. We apply the linear map to the center and the generators. -If the map has outpu dimension 1, a specialized algorithm ensures that the -resulting zonotope only has a single generator. +If the map has output dimension 1, a specialized algorithm ensures that the +resulting zonotope only has a single generator (or none if the map is zero). """ function linear_map(M::AbstractMatrix, Z::AbstractZonotope) @assert dim(Z) == size(M, 2) "a linear map of size $(size(M)) cannot be " * @@ -326,7 +326,8 @@ function _linear_map_zonotope_1D(M::AbstractMatrix, Z::LazySet) @inbounds for g in generators(Z) gi += abs(sum(M[1, i] * g[i] for i in eachindex(g))) end - return Zonotope(c, hcat(gi)) + G = iszero(gi) ? Matrix{N}(undef, 1, 0) : hcat(gi) + return Zonotope(c, G) end function _linear_map_zonotope_nD(M::AbstractMatrix, Z::LazySet) diff --git a/test/Sets/Zonotope.jl b/test/Sets/Zonotope.jl index 8aee3bec40..1fb7afc7c3 100644 --- a/test/Sets/Zonotope.jl +++ b/test/Sets/Zonotope.jl @@ -112,6 +112,10 @@ for N in [Float64, Rational{Int}, Float32] M = N[-1 1;] Z6 = linear_map(M, Z3) @test ngens(Z6) == 1 && genmat(Z6) == hcat(N[4]) + # ... unless the map is zero + M = N[0 0;] + Z7 = linear_map(M, Z3) + @test ngens(Z7) == 0 && genmat(Z7) == Matrix{N}(undef, 1, 0) # in-place linear map Zin = convert(Zonotope, BallInf(zeros(N, 2), N(1)))