Skip to content

Commit 34137ac

Browse files
authored
overapproximation of SPZ to VPolytope (#3821)
* Added overapproximation of SPZ to VPolytope * N type for G_z * changes and use ispermutation in unit tests
1 parent 58ad370 commit 34137ac

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

src/Approximations/overapproximate.jl

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,84 @@ function overapproximate(P::VPolygon, ::Type{<:LinearMap{N,<:Hyperrectangle}}) w
603603
return LinearMap(R, min_rectangle)
604604
end
605605

606+
"""
607+
overapproximate(P::SparsePolynomialZonotope{N}, ::Type{<:VPolytope}) where {N}
608+
609+
610+
Overapproximate a sparse polynomial zonotope with a polytope in vertex representation.
611+
612+
### Input
613+
614+
- `P` -- sparse polynomial zonotope
615+
- `VPolytope` -- target type
616+
617+
### Output
618+
619+
A `VPolytope` that overapproximates the sparse polynomial zonotope.
620+
621+
### Algorithm
622+
623+
This method implements [Kochdumper21a; Proposition 3.1.15](@citet).
624+
The idea is to split `P` into a linear and nonlinear part (such that `P = P₁ ⊕ P₂`).
625+
The nonlinear part is enclosed by a zonotope. Then we combine the vertices
626+
of both sets and finally apply a convex-hull algorithm.
627+
"""
628+
function overapproximate(P::SparsePolynomialZonotope{N}, ::Type{<:VPolytope}) where {N}
629+
c = center(P)
630+
G = genmat_dep(P)
631+
GI = genmat_indep(P)
632+
E = expmat(P)
633+
idx = P.idx
634+
635+
H = [j for j in 1:size(E, 2) if any(E[:, j] .> 1)]
636+
K = setdiff(1:size(E, 2), H)
637+
638+
if !isempty(H)
639+
SPZ₂ = SparsePolynomialZonotope(c, G[:, H], zeros(N, length(c), 0), E[:, H], idx)
640+
Z = overapproximate(SPZ₂, Zonotope)
641+
c_z = center(Z)
642+
GI_mod = hcat(GI, genmat(Z))
643+
else
644+
c_z = c
645+
GI_mod = GI
646+
end
647+
648+
G_mod = G[:, K]
649+
E_mod = E[:, K]
650+
651+
# P̄ = SparsePolynomialZonotope(c_z, G_mod, GI_mod, E_mod, idx)
652+
# Compute vertices of a Z-representation
653+
p = size(E, 1)
654+
dep_params = Iterators.product(fill([-one(N), one(N)], p)...)
655+
indep_params = Iterators.product(fill([-one(N), one(N)], size(GI_mod, 2))...)
656+
657+
V = Vector{Vector{N}}()
658+
for α in dep_params
659+
dep_term = zeros(N, size(c))
660+
for j in axes(G_mod, 2)
661+
prod = one(N)
662+
for k in 1:p
663+
if E_mod[k, j] == 1
664+
prod *= α[k]
665+
end
666+
end
667+
dep_term += prod * G_mod[:, j]
668+
end
669+
for β in indep_params
670+
indep_term = zeros(N, size(c))
671+
for j in axes(GI_mod, 2)
672+
indep_term += β[j] * GI_mod[:, j]
673+
end
674+
point = c_z + dep_term + indep_term
675+
push!(V, point)
676+
end
677+
end
678+
679+
convex_hull!(V)
680+
681+
return VPolytope(V)
682+
end
683+
606684
# function to be loaded by Requires
607685
function load_paving_overapproximation()
608686
return quote

test/Approximations/overapproximate.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ for N in [Float64, Rational{Int}, Float32]
147147
if N <: AbstractFloat
148148
@test isequivalent(P, R)
149149
end
150+
151+
#overapproximate a SparsePolynomialZonotope with a VPolytope
152+
S = SparsePolynomialZonotope(N[-0.5, -0.5], N[1. 1 1 1;1 0 -1 1], zeros(N, 2, 0), [1 0 1 2;0 1 1 0])
153+
P = overapproximate(S, VPolytope)
154+
@test ispermutation([N[-1.5, -2.5], N[2.5, -0.5], N[3.5, 0.5], N[-0.5, 2.5], N[-1.5, 1.5]], vertices_list(P))
150155
end
151156

152157
# tests that do not work with Rational{Int}

0 commit comments

Comments
 (0)