Skip to content

Commit d13d27d

Browse files
committed
zonotope overapproximation of zonotope w/ axis-aligned half-space
1 parent 1b38377 commit d13d27d

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
eval(load_paving_overapproximation())
2+
eval(load_overapproximate_ICP())

Diff for: src/Approximations/overapproximate_zonotope.jl

+70
Original file line numberDiff line numberDiff line change
@@ -1215,3 +1215,73 @@ function _overapproximate_zonotope_hyperplane(Z::AbstractZonotope, H::Hyperplane
12151215
G_cap = G * Gs
12161216
return Zonotope(c_cap, G_cap)
12171217
end
1218+
1219+
function overapproximate(X::Intersection{N,<:AbstractZonotope,<:HalfSpace{N,<:SingleEntryVector}},
1220+
::Type{Zonotope}) where {N}
1221+
return _overapproximate_zonotope_halfspace_ICP(first(X), second(X))
1222+
end
1223+
1224+
# symmetric method
1225+
function overapproximate(X::Intersection{N,<:HalfSpace{N,<:SingleEntryVector},<:AbstractZonotope},
1226+
::Type{Zonotope}) where {N}
1227+
return _overapproximate_zonotope_halfspace_ICP(second(X), first(X))
1228+
end
1229+
1230+
# method for a single constraint of the form x_i <= b based on ICP
1231+
# - zonotope = G * []^p + c, where []^p is the p-dimensional unit cube
1232+
# - let G_i be the i-th row of G
1233+
# - build an ICP contractor for the constraint G_i^T x <= b - c
1234+
# - contract the domain of []^p under this constraint to D
1235+
# - the resulting zonotope is G * D + c
1236+
function _overapproximate_zonotope_halfspace_ICP(Z::AbstractZonotope{N},
1237+
H::HalfSpace{N,SingleEntryVector{N}}) where {N}
1238+
c = center(Z)
1239+
G = genmat(Z)
1240+
p = size(G, 2)
1241+
d = H.a.i
1242+
1243+
a = G[d, :]
1244+
io = IOBuffer()
1245+
first = true
1246+
v = H.a.v
1247+
negate = v < zero(N)
1248+
if negate
1249+
v = -v
1250+
end
1251+
for (i, ai) in enumerate(a)
1252+
if first
1253+
first = false
1254+
elseif ai >= 0
1255+
write(io, "+")
1256+
end
1257+
write(io, "$(v * ai)*x$(i)")
1258+
end
1259+
if negate
1260+
write(io, ">=$(-H.b + c[d])")
1261+
else
1262+
write(io, "<=$(H.b - c[d])")
1263+
end
1264+
e = Meta.parse(String(take!(io)))
1265+
X = IA.IntervalBox(IA.interval(-1, 1), p)
1266+
newD = _contract_zonotope_halfspace_ICP(e, X)
1267+
if isempty(newD)
1268+
return EmptySet{N}(length(c))
1269+
end
1270+
return affine_map(G, convert(Hyperrectangle, newD), c)
1271+
end
1272+
1273+
function load_overapproximate_ICP()
1274+
return quote
1275+
import .IntervalConstraintProgramming as ICP
1276+
1277+
function _contract_zonotope_halfspace_ICP(e, X)
1278+
separator = eval(quote
1279+
ICP.@constraint $e
1280+
end)
1281+
# smallest box containing all points in domain X satisfying constraint
1282+
# (`invokelatest` to avoid world-age issue; `Base.` for VERSION < v"1.9")
1283+
out, _ = Base.invokelatest(separator, X)
1284+
return out
1285+
end
1286+
end
1287+
end # load_overapproximate_ICP()

Diff for: test/Approximations/overapproximate.jl

+8
Original file line numberDiff line numberDiff line change
@@ -521,4 +521,12 @@ for N in [Float64]
521521
H = overapproximate(p, dirs)
522522
B2 = Ball2(N[0, 0], N(1))
523523
@test B2 H
524+
525+
# overapproximate the intersection of a zonotope with an axis-aligned
526+
# half-space by a zonotope using ICP
527+
Z = Zonotope(N[0, 2], N[1//2 1//2; 1 0])
528+
H = HalfSpace(SingleEntryVector(1, 2, N(1)), N(0))
529+
R = overapproximate(Z H, Zonotope)
530+
R_exact = intersection(Z, H)
531+
@test R Z && R_exact R
524532
end

0 commit comments

Comments
 (0)