diff --git a/src/Interfaces/AbstractHyperrectangle.jl b/src/Interfaces/AbstractHyperrectangle.jl index 32115cf806..766856f2f3 100644 --- a/src/Interfaces/AbstractHyperrectangle.jl +++ b/src/Interfaces/AbstractHyperrectangle.jl @@ -57,7 +57,8 @@ Return the generator matrix of a hyperrectangular set. A matrix where each column represents one generator of `H`. """ function genmat(H::AbstractHyperrectangle) - return genmat_fallback(H) + gens = generators(H) + return genmat_fallback(H, gens=gens, ngens=length(gens)) end # iterator that wraps the generator matrix diff --git a/src/Interfaces/AbstractZonotope.jl b/src/Interfaces/AbstractZonotope.jl index 1934dfbe09..0ec4eaccf6 100644 --- a/src/Interfaces/AbstractZonotope.jl +++ b/src/Interfaces/AbstractZonotope.jl @@ -59,18 +59,51 @@ Fallback definition of `genmat` for zonotopic sets. ### Input -- `Z` -- zonotopic set +- `Z` -- zonotopic set +- `gens` -- (optional; default: `generators(Z)`) iterator over generators +- `ngens` -- (optional; default: `nothing`) number of generators or `nothing` if + unknown ### Output A matrix where each column represents one generator of `Z`. + +### Notes + +Passing the number of generators is much more efficient as otherwise the +generators have to be obtained from the iterator (`gens`) and stored in an +intermediate vector until the final result matrix can be allocated. """ -function genmat_fallback(Z::AbstractZonotope{N}) where {N<:Real} - gens = generators(Z) +function genmat_fallback(Z::AbstractZonotope{N}; + gens=generators(Z), + ngens=nothing) where {N<:Real} if isempty(gens) return Matrix{N}(undef, dim(Z), 0) + elseif ngens == nothing + return _genmat_fallback_generic(Z, gens) + else + return _genmat_fallback_ngens(Z, gens, ngens) + end +end + +function _genmat_fallback_generic(Z::AbstractZonotope{N}, gens) where {N<:Real} + Gv = Vector{Vector{N}}() + @inbounds for (i, g) in enumerate(gens) + push!(Gv, g) + end + G = Matrix{N}(undef, dim(Z), length(Gv)) + @inbounds for (i, g) in enumerate(Gv) + G[:, i] = g + end + return G +end + +function _genmat_fallback_ngens(Z::AbstractZonotope{N}, gens, ngens) where {N<:Real} + G = Matrix{N}(undef, dim(Z), ngens) + @inbounds for (i, g) in enumerate(gens) + G[:, i] = g end - return hcat(gens...) + return G end # iterator that wraps the generator matrix diff --git a/src/Sets/LineSegment.jl b/src/Sets/LineSegment.jl index 88d4670dbb..927a460ba5 100644 --- a/src/Sets/LineSegment.jl +++ b/src/Sets/LineSegment.jl @@ -210,7 +210,8 @@ Return the generator matrix of a line segment. A matrix with a single column representing the generator of `L`. """ function genmat(L::LineSegment) - return genmat_fallback(L) + ngens = L.p == L.q ? 0 : 1 + return genmat_fallback(L, ngens=ngens) end """