247247
248248"""
249249 overapproximate(P::AbstractSparsePolynomialZonotope, ::Type{<:Zonotope},
250- dom::IntervalBox )
250+ dom::AbstractVector{<:IA.Interval} )
251251
252252Overapproximate a sparse polynomial zonotope over the parameter domain `dom`
253253with a zonotope.
@@ -264,9 +264,10 @@ with a zonotope.
264264A zonotope.
265265"""
266266function overapproximate (P:: AbstractSparsePolynomialZonotope , :: Type{<:Zonotope} ,
267- dom:: IA.IntervalBox )
268- @assert dom ⊆ IA. IntervalBox (IA. interval (- 1 , 1 ), nparams (P)) " dom should " *
269- " be a subset of [-1, 1]^q"
267+ dom:: AbstractVector{<:IA.Interval} )
268+ @assert length (dom) == nparams (P) &&
269+ all (IA. issubset_interval (vi, IA. interval (- 1 , 1 )) for vi in dom) " dom should be a " *
270+ " subset of [-1, 1]^q"
270271
271272 # handle dependent generators
272273 G = genmat_dep (P)
@@ -275,12 +276,11 @@ function overapproximate(P::AbstractSparsePolynomialZonotope, ::Type{<:Zonotope}
275276 Gnew = similar (G)
276277 @inbounds for (j, g) in enumerate (eachcol (G))
277278 # monomial value over the domain
278- # α = mapreduce(x -> _fast_interval_pow(x[1], x[2]), *, zip(dom, E[:, i]))
279279 α = IA. interval (1 , 1 )
280280 for (i, vi) in enumerate (dom)
281- α *= fast_interval_pow (vi, E[i, j])
281+ α *= vi ^ E[i, j]
282282 end
283- m, r = IA. midpoint_radius (α)
283+ m, r = IA. midradius (α)
284284 cnew .+ = m * g
285285 Gnew[:, j] .= r * g
286286 end
@@ -396,10 +396,10 @@ function load_taylormodels_overapproximation()
396396 [-0.5, 0.5]
397397
398398 julia> x₀ = IA.interval(0.0) # expansion point
399- [0, 0]
399+ [0.0, 0. 0]
400400
401401 julia> D = IA.interval(-3.0, 1.0)
402- [-3, 1]
402+ [-3.0 , 1.0 ]
403403
404404 julia> p1 = Taylor1([2.0, 1.0], 2) # define a linear polynomial
405405 2.0 + 1.0 t + 𝒪(t³)
@@ -440,11 +440,10 @@ function load_taylormodels_overapproximation()
440440 julia> X = box_approximation(Z)
441441 Hyperrectangle{Float64, Vector{Float64}, Vector{Float64}}([1.0, -2.1], [2.5, 6.5])
442442
443- julia> Y = evaluate(vTM[1], vTM[1].dom) × evaluate(vTM[2], vTM[2].dom)
444- [-1.5, 3.5] × [-8.60001, 4.40001]
445-
446- julia> H = convert(Hyperrectangle, Y) # this IntervalBox is the same as X
447- Hyperrectangle{Float64, StaticArraysCore.SVector{2, Float64}, StaticArraysCore.SVector{2, Float64}}([1.0, -2.1000000000000005], [2.5, 6.500000000000001])
443+ julia> Y = [evaluate(vTM[1], vTM[1].dom), evaluate(vTM[2], vTM[2].dom)]
444+ 2-element Vector{IntervalArithmetic.Interval{Float64}}:
445+ │ [-1.50001, 3.50001]
446+ [-8.60001, 4.40001]
448447 ```
449448 However, the zonotope returns better results if we want to approximate the
450449 Taylor model because it is not axis-aligned:
@@ -553,17 +552,21 @@ function load_taylormodels_overapproximation()
553552 1.0 x₁ + 𝒪(‖x‖⁹)
554553 1.0 x₂ + 𝒪(‖x‖⁹)
555554
556- julia> x₀ = IA.IntervalBox(0..0, 2) # expansion point
557- [0, 0]²
555+ julia> x₀ = fill(0..0, 2) # expansion point
556+ 2-element Vector{IntervalArithmetic.Interval{Float64}}:
557+ │ [0.0, 0.0]
558+ │ [0.0, 0.0]
558559
559560 julia> Dx₁ = IA.interval(0.0, 3.0) # domain for x₁
560- [0, 3]
561+ [0.0 , 3.0 ]
561562
562563 julia> Dx₂ = IA.interval(-1.0, 1.0) # domain for x₂
563- [-1, 1]
564+ [-1.0 , 1.0 ]
564565
565- julia> D = Dx₁ × Dx₂ # take the Cartesian product of the domain on each variable
566- [0, 3] × [-1, 1]
566+ julia> D = [Dx₁, Dx₂]
567+ 2-element Vector{IntervalArithmetic.Interval{Float64}}:
568+ │ [0.0, 3.0]
569+ │ [-1.0, 1.0]
567570
568571 julia> r = IA.interval(-0.5, 0.5) # interval remainder
569572 [-0.5, 0.5]
@@ -629,13 +632,17 @@ function load_taylormodels_overapproximation()
629632
630633 # build the generators
631634 α = mid (rem_nonlin)
632- c[i] = constant_term (pol_lin_norm) + α # constant terms
633- G[i, 1 : n] = get_linear_coeffs (pol_lin_norm) # linear terms
635+ cterm = constant_term (pol_lin_norm)
636+ @assert IA. isthin (cterm) " unexpected interval value"
637+ c[i] = mid (cterm) + α # constant terms
638+ lin_coeffs = get_linear_coeffs (pol_lin_norm)
639+ @assert all (IA. isthin, lin_coeffs) " unexpected interval value"
640+ G[i, 1 : n] = mid .(lin_coeffs) # linear terms
634641 # interval generator
635642 for j in (n + 1 ): (n + m)
636643 G[i, j] = zero (N)
637644 end
638- G[i, n + i] = abs (rem_nonlin . hi - α)
645+ G[i, n + i] = abs (IA . sup (rem_nonlin) - α)
639646 end
640647
641648 if remove_redundant_generators
@@ -1194,35 +1201,40 @@ end
11941201# - the resulting zonotope is G * D + c
11951202function _overapproximate_zonotope_halfspace_ICP (Z:: AbstractZonotope{N} ,
11961203 H:: HalfSpace{N,SingleEntryVector{N}} ) where {N}
1204+ require (@__MODULE__ , :IntervalConstraintProgramming ; fun_name= " overapproximate" )
1205+
11971206 c = center (Z)
11981207 G = genmat (Z)
11991208 p = size (G, 2 )
12001209 d = H. a. i
12011210
12021211 a = G[d, :]
12031212 io = IOBuffer ()
1204- first = true
12051213 v = H. a. v
12061214 negate = v < zero (N)
12071215 if negate
12081216 v = - v
12091217 end
1218+ vars = " "
1219+ first = true
12101220 for (i, ai) in enumerate (a)
12111221 if first
12121222 first = false
12131223 elseif ai >= 0
12141224 write (io, " +" )
1225+ vars *= " , "
12151226 end
12161227 write (io, " $(v * ai) *x$(i) " )
1228+ vars *= " x$(i) "
12171229 end
12181230 if negate
12191231 write (io, " >=$(- H. b + c[d]) " )
12201232 else
12211233 write (io, " <=$(H. b - c[d]) " )
12221234 end
12231235 e = Meta. parse (String (take! (io)))
1224- X = IA . IntervalBox (IA. interval (- 1 , 1 ), p)
1225- newD = _contract_zonotope_halfspace_ICP (e, X)
1236+ X = fill (IA. interval (- 1 , 1 ), p)
1237+ newD = _contract_zonotope_halfspace_ICP (e, X, vars )
12261238 if isempty (newD)
12271239 return EmptySet {N} (length (c))
12281240 end
@@ -1232,15 +1244,22 @@ end
12321244function load_overapproximate_ICP ()
12331245 return quote
12341246 import . IntervalConstraintProgramming as ICP
1235-
1236- function _contract_zonotope_halfspace_ICP (e, X)
1247+ import . IntervalConstraintProgramming. IntervalBoxes as IB
1248+
1249+ function _contract_zonotope_halfspace_ICP (e, X, vars_string)
1250+ n = length (X)
1251+ prefix = " IntervalConstraintProgramming.Symbolics.@variables "
1252+ sym = Meta. parse (prefix * vars_string)
1253+ vars = eval (quote
1254+ $ sym
1255+ end )
12371256 separator = eval (quote
1238- ICP. @constraint $ e
1257+ ICP. Separator ( $ e, $ vars)
12391258 end )
12401259 # smallest box containing all points in domain X satisfying constraint
12411260 # (`invokelatest` to avoid world-age issue; `Base.` for VERSION < v"1.9")
1242- out , _ = Base. invokelatest (separator, X )
1243- return out
1261+ boundary , _, _ = Base. invokelatest (separator, IB . IntervalBox (X ... ) )
1262+ return boundary
12441263 end
12451264 end
12461265end # load_overapproximate_ICP()
0 commit comments