|
| 1 | +""" |
| 2 | + struct ZonotopeMD{N, VN<:AbstractVector{N}, MN<:AbstractMatrix{N}, DN<:AbstractVector{N}} <: AbstractZonotope{N} |
| 3 | +
|
| 4 | +Type that represents a zonotope of order `k` in normal form. |
| 5 | +
|
| 6 | +### Fields |
| 7 | +
|
| 8 | +- `center::VN` — the center of the zonotope |
| 9 | +- `M::MN` — matrix of general (non-axis-aligned) generators |
| 10 | +- `d::DN` — vector of axis-aligned (diagonal) generators |
| 11 | +
|
| 12 | +### Notes |
| 13 | +A zonotope is of order `k` if it has `n * k` generators in `ℝⁿ`, where `n` is the ambient dimension. |
| 14 | +
|
| 15 | +A zonotope of order `k` in *normal form* is defined as the set |
| 16 | +
|
| 17 | +```math |
| 18 | +Z = \\left\\{ x ∈ ℝ^n : x = c + Mξ + d ⊙ η, ~~ ξ ∈ [-1, 1]^m, ~~ η ∈ [-1, 1]^n \\right\\}, |
| 19 | +``` |
| 20 | +
|
| 21 | +where `M ∈ ℝ^{n×m}` is a matrix of general generators with `m = n*(k -1)` and `d ∈ ℝⁿ` is a vector of axis-aligned generators. |
| 22 | +Equivalently, this can be seen as a zonotope with generator matrix `[M D]`, where `D` is the diagonal matrix |
| 23 | +formed from the vector `d`. |
| 24 | +ZonotopeMD can be constructed in two ways: by passing the full generator matrix `[M D]` in normal form |
| 25 | +or by passing `M` and a vector `d` separately. |
| 26 | +
|
| 27 | +### Examples |
| 28 | +
|
| 29 | +Constructing a zonotope in normal form from a center, general generator matrix `M`, and diagonal vector `d`: |
| 30 | +
|
| 31 | +```jldoctest zonotopemd_label |
| 32 | +julia> c = [0.0, 0.0]; |
| 33 | +
|
| 34 | +julia> M = [1.0 2.0; 3.0 1.0]; |
| 35 | +
|
| 36 | +julia> d = [0.1, 0.2]; |
| 37 | +
|
| 38 | +julia> Z = ZonotopeMD(c, M, d) |
| 39 | +ZonotopeMD{Float64, Vector{Float64}, Matrix{Float64}, Vector{Float64}}([0.0, 0.0], [1.0 2.0; 3.0 1.0], [0.1, 0.2]) |
| 40 | +
|
| 41 | +julia> center(Z) |
| 42 | +2-element Vector{Float64}: |
| 43 | + 0.0 |
| 44 | + 0.0 |
| 45 | +
|
| 46 | +julia> genmat(Z) |
| 47 | +2×4 SparseArrays.SparseMatrixCSC{Float64, Int64} with 6 stored entries: |
| 48 | + 1.0 2.0 0.1 ⋅ |
| 49 | + 3.0 1.0 ⋅ 0.1 |
| 50 | +``` |
| 51 | +
|
| 52 | +The generator matrix returned by `genmat` is the concatenation `[M D]`, where `D` is the diagonal matrix formed from `d`. |
| 53 | +THe resulting matrix is stored as a sparse matrix. |
| 54 | +Constructing the same zonotope by passing the full generator matrix `[M D]` directly: |
| 55 | +
|
| 56 | +```jldoctest zonotopemd_label |
| 57 | +julia> G = [1.0 2.0 0.1 0.0; |
| 58 | + 3.0 1.0 0.0 0.2]; |
| 59 | +
|
| 60 | +julia> Z2 = ZonotopeMD([0.0, 0.0], G) |
| 61 | +ZonotopeMD{Float64, Vector{Float64}, Matrix{Float64}, Vector{Float64}}([0.0, 0.0], [1.0 2.0; 3.0 1.0], [0.1, 0.2]) |
| 62 | +
|
| 63 | +julia> genmat(Z2) == G |
| 64 | +true |
| 65 | +``` |
| 66 | +You can also convert back to a standard `Zonotope` if needed: |
| 67 | +
|
| 68 | +```jldoctest zonotopemd_label |
| 69 | +julia> Zstd = Zonotope(Z) |
| 70 | +Zonotope{Float64, Vector{Float64}, SparseArrays.SparseMatrixCSC{Float64, Int64}}([0.0, 0.0], sparse([1, 2, 1, 2, 1, 2], [1, 1, 2, 2, 3, 4], [1.0, 3.0, 2.0, 1.0, 0.1, 0.2], 2, 4)) |
| 71 | +``` |
| 72 | +
|
| 73 | +""" |
| 74 | +struct ZonotopeMD{N,VN<:AbstractVector{N},MN<:AbstractMatrix{N},DN<:AbstractVector{N}} <: |
| 75 | + AbstractZonotope{N} |
| 76 | + center::VN |
| 77 | + M::MN |
| 78 | + d::DN |
| 79 | + |
| 80 | + function ZonotopeMD(center::VN, M::MN, |
| 81 | + d::DN) where {N, |
| 82 | + VN<:AbstractVector{N}, |
| 83 | + MN<:AbstractMatrix{N}, |
| 84 | + DN<:AbstractVector{N}} |
| 85 | + @assert length(center) == size(M, 1) == length(d) "Dimensions must match" |
| 86 | + return new{N,VN,MN,DN}(center, M, d) |
| 87 | + end |
| 88 | +end |
| 89 | + |
| 90 | +# constructor from generator matrix |
| 91 | +function ZonotopeMD(center::VN, G::AbstractMatrix{N}) where {N,VN<:AbstractVector{N}} |
| 92 | + n, p = size(G) |
| 93 | + @assert p % n == 0 "The generator matrix must contain a multiple of n columns" |
| 94 | + @assert p >= 2n "Expected at least order 2 zonotope" |
| 95 | + |
| 96 | + M = G[:, 1:(p - n)] |
| 97 | + D = G[:, (end - n + 1):end] |
| 98 | + |
| 99 | + @assert isdiag(D) "The last n columns of the generator matrix must be diagonal" |
| 100 | + d = diag(D) |
| 101 | + return ZonotopeMD(center, M, d) |
| 102 | +end |
0 commit comments