Skip to content

Commit

Permalink
Merge pull request #340 from JuliaReach/mforets/update_basics
Browse files Browse the repository at this point in the history
Add exponential LGG09 w/ time-varying input sets
  • Loading branch information
mforets authored Oct 20, 2020
2 parents 4d66f8b + 5dc8fe0 commit e94e9fd
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 55 deletions.
46 changes: 45 additions & 1 deletion docs/src/man/basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,58 @@ discrete modes that are compatible with the dynamics.

## Set representations

### Convex sets
### Representing sets with support functions

Support functions are one of the central tools in set-based reachability. The *support function* of a closed and bounded convex set $\mathcal{X} \subseteq \mathbb{R}^n$ attributes to a direction vector $d \in \mathbb{R}^n$ the real number

```math
ρ(d, \mathcal{X}) = \max \{ d^T x : x \in \mathcal{X} \},
```
where $d^T$ denotes the transpose of the (column) vector $d$.

TODO: example with triangle
A convex set can be represe

The

### Polyhedra

### Zonotopes

Zonotopes are a sub-class of polytopes defined as the image of a unit cube under


### Hausdorff distance



### LazySets


### Taylor models

## Taylor models


```@example
using ReachabilityAnalysis, Plots
f(x) = -6x^3 + (13/3)x^2 + (31/3)x
dom = -3.5 .. 3.5
plot(f, -3.5, 3.5, lab="f", xlab="x")
x = Taylor1(5)
set_taylor1_varname("x")
f(x)
rem = 0 .. 0
x0 = 0.0
dom = -3.5 .. 3.5
tm = TaylorModel1(f(x), rem, x0, dom)
```

## Reach-sets

We consider as a running example in this section the simple harmonic oscillator,
Expand Down
88 changes: 35 additions & 53 deletions src/Algorithms/LGG09/reach_homog.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,70 +115,52 @@ end
# Functionality that requires ExponentialUtilities.jl
# ------------------------------------------------------------

function load_exponential_utilities_LGG09()
function load_krylov_LGG09_homog()
return quote

# recursive version, default expv
function reach_homog_dir_LGG09_expv!(out, Ω₀, Aᵀ, ℓ, NSTEPS, recursive::Val{:true})
rᵢ = copy(ℓ)
rᵢ₊₁ = similar(rᵢ)

@inbounds for i in 1:NSTEPS
out[i] = ρ(rᵢ, Ω₀)

# update cache for the next iteration
rᵢ₊₁ = expv(1.0, Aᵀ, rᵢ) # computes exp(Aᵀ * 1.0) * rᵢ
copy!(rᵢ, rᵢ₊₁)
end
return out
end

# ρ(ℓ, Ω₀), ρ(exp(Aᵀ) * ℓ, Ω₀), ρ(exp(2Aᵀ) * ℓ, Ω₀)
function reach_homog_dir_LGG09_expv!(out, Ω₀, Aᵀ, ℓ, NSTEPS, recursive::Val{:false})
rᵢ = deepcopy(ℓ) # if ℓ is a sev => this is a sev

@inbounds for i in 1:NSTEPS
out[i] = ρ(rᵢ, Ω₀)

# update cache for the next iteration
rᵢ = expv(i*1.0, Aᵀ, ℓ)
end
return out
end

# non-recursive version using precomputed Krylov subspace
function reach_homog_dir_LGG09_expv_pk!(out, Ω₀, Aᵀ, ℓ, NSTEPS, recursive::Val{:false})
rᵢ = deepcopy(ℓ) # if ℓ is a sev => this is a sev
Ks = arnoldi(Aᵀ, ℓ, tol=1e-18)

@inbounds for i in 1:NSTEPS
out[i] = ρ(rᵢ, Ω₀)

# update cache for the next iteration
expv!(rᵢ, i*1.0, Ks)
end
return out
end

# this function computes the sequence
# ``ρ(ℓ, Ω₀)``, ``ρ(exp(Aᵀ) * ℓ, Ω₀)``, ``ρ(exp(2Aᵀ) * ℓ, Ω₀)`` until ``ρ(exp(NSTEPS * Aᵀ) * ℓ, Ω₀)``
function reach_homog_dir_LGG09_expv_pk2!(out, Ω₀, Aᵀ, ℓ, NSTEPS, recursive::Val{:false};
hermitian=false, m=min(30, size(Aᵀ, 1)), tol=1e-7)

TA, Tb = eltype(Aᵀ), eltype(ℓ)
# Compute the sequence:
#
# ρ(ℓ, Ω₀), ρ(ℓ, Φ Ω₀), ρ(ℓ, Φ^2 Ω₀), ρ(ℓ, Φ^3 Ω₀), ...
#
# Using Krylov subspace approximations to compute the action of Φ := exp(Aδ) over
# the direction ℓ.
#
# Method (see [1]):
#
# out[1] <- ρ(ℓ, Ω₀)
#
# out[2] <- ρ(ℓ, Φ Ω₀) = ρ(Φᵀ ℓ, Ω₀)
#
# out[3] <- ρ(ℓ, Φ^2 Ω₀) = ρ((Φᵀ)^2 ℓ, Ω₀)
#
# out[4] <- ρ(ℓ, Φ^3 Ω₀) = ρ((Φᵀ)^3 ℓ, Ω₀)
#
# and so on.
#
# [1] Reach Set Approximation through Decomposition with Low-dimensional Sets and
# High-dimensional Matrices. Sergiy Bogomolov, Marcelo Forets, Goran Frehse,
# Frédéric Viry, Andreas Podelski and Christian Schilling (2018) HSCC'18
# Proceedings of the 21st International Conference on Hybrid Systems: Computation
# and Control: 41–50.
#
function reach_homog_krylov_LGG09!(out, Ω₀::LazySet, Aᵀδ::AbstractMatrix,
::AbstractVector, NSTEPS;
hermitian=false, m=min(30, size(Aᵀδ, 1)), tol=1e-7)

# initialization of the krylov subspace
TA, Tb = eltype(Aᵀδ), eltype(ℓ)
T = promote_type(TA, Tb)
Ks = KrylovSubspace{T, real(T)}(length(ℓ), m)
arnoldi!(Ks, Aᵀ, ℓ; m=m, ishermitian=hermitian, tol=tol)
arnoldi!(Ks, Aᵀδ, ℓ; m=m, ishermitian=hermitian, tol=tol)

# rᵢ stores is the cache for each vector: (Φᵀ)^i ℓ
rᵢ = deepcopy(ℓ)

@inbounds for i in 1:NSTEPS
out[i] = ρ(rᵢ, Ω₀)

# update cache for the next iteration
expv!(rᵢ, i*1.0, Ks)
end
return out
end

end end # quote / load_exponential_utilities_LGG09()
end end # quote / load_krylov_LGG09_homog()
110 changes: 110 additions & 0 deletions src/Algorithms/LGG09/reach_inhomog.jl
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,113 @@ function reach_inhomog_LGG09!(F::Vector{RT},
return ρℓ
end
=#

# ------------------------------------------------------------
# Functionality that requires ExponentialUtilities.jl
# ------------------------------------------------------------

function load_krylov_LGG09_inhomog()
return quote

# Compute the sequence with constant input sets:
#
# ρ(ℓ, Ω₀), ρ(ℓ, Φ Ω₀ ⊕ V), ρ(ℓ, Φ^2 Ω₀ ⊕ Φ V ⊕ V), ρ(ℓ, Φ^3 Ω₀ ⊕ Φ^2 V ⊕ Φ V ⊕ V), ...
#
# Using Krylov subspace approximations to compute the action of Φ := exp(Aδ) over
# the direction ℓ.
#
# Method (see [1]):
#
# out[1] <- ρ(ℓ, Ω₀)
#
# out[2] <- ρ(ℓ, Φ Ω₀ ⊕ V) = ρ(ℓ, Φ Ω0) + ρ(ℓ, V) = ρ(Φᵀ ℓ, Ω₀) + ρ(ℓ, V)
#
# out[3] <- ρ(ℓ, Φ^2 Ω₀ ⊕ Φ V ⊕ V) = ρ((Φᵀ)^2 ℓ, Ω₀) + ρ(Φᵀ ℓ, V) + ρ(ℓ, V)
#
# out[4] <- ρ(ℓ, Φ^3 Ω₀ ⊕ Φ^2 V ⊕ Φ V ⊕ V) = ρ((Φᵀ)^3 ℓ, Ω₀) + ρ((Φᵀ)^2 ℓ, V) + ρ(Φᵀ ℓ, V) + ρ(ℓ, V)
#
# and so on.
#
# [1] Reach Set Approximation through Decomposition with Low-dimensional Sets and
# High-dimensional Matrices. Sergiy Bogomolov, Marcelo Forets, Goran Frehse,
# Frédéric Viry, Andreas Podelski and Christian Schilling (2018) HSCC'18
# Proceedings of the 21st International Conference on Hybrid Systems: Computation
# and Control: 41–50.
#
function reach_inhomog_krylov_LGG09!(out, Ω₀::LazySet, V::LazySet, Aᵀδ::AbstractMatrix,
::AbstractVector, NSTEPS;
hermitian=false, m=min(30, size(Aᵀδ, 1)), tol=1e-7)

# initialization of the krylov subspace
TA, Tb = eltype(Aᵀδ), eltype(ℓ)
T = promote_type(TA, Tb)
Ks = KrylovSubspace{T, real(T)}(length(ℓ), m)
arnoldi!(Ks, Aᵀδ, ℓ; m=m, ishermitian=hermitian, tol=tol)

# rᵢ stores is the cache for each vector: (Φᵀ)^i ℓ
rᵢ = deepcopy(ℓ)
out[1] = ρ(ℓ, Ω₀)

# accumulated support vector sum due to the inputs
s = zero(T)

@inbounds for i in 1:NSTEPS-1
s += ρ(rᵢ, V)
expv!(rᵢ, i*1.0, Ks)
out[i+1] = ρ(rᵢ, Ω₀) + s
end
return out
end

# Compute the sequence with time-varying input sets:
#
# ρ(ℓ, Ω₀), ρ(ℓ, Φ Ω₀ ⊕ V₀), ρ(ℓ, Φ^2 Ω₀ ⊕ Φ V₀ ⊕ V₁), ρ(ℓ, Φ^3 Ω₀ ⊕ Φ^2 V₀ ⊕ Φ V₁ ⊕ V₂), ...
#
# Using Krylov subspace approximations to compute the action of Φ := exp(Aδ) over
# the direction ℓ.
#
# Method (see [1]):
#
# out[1] <- ρ(ℓ, Ω₀)
#
# out[2] <- ρ(ℓ, Φ Ω₀ ⊕ V₀) = ρ(ℓ, Φ Ω0) + ρ(ℓ, V₀) = ρ(Φᵀ ℓ, Ω₀) + ρ(ℓ, V₀)
#
# out[3] <- ρ(ℓ, Φ^2 Ω₀ ⊕ Φ V₀ ⊕ V₁) = ρ((Φᵀ)^2 ℓ, Ω₀) + ρ(Φᵀ ℓ, V₀) + ρ(ℓ, V₁)
#
# out[4] <- ρ(ℓ, Φ^3 Ω₀ ⊕ Φ^2 V₀ ⊕ Φ V₁ ⊕ V₂) = ρ((Φᵀ)^3 ℓ, Ω₀) + ρ((Φᵀ)^2 ℓ, V₀) + ρ(Φᵀ ℓ, V₁) + ρ(ℓ, V₂)
#
# and so on.
#
# [1] Reach Set Approximation through Decomposition with Low-dimensional Sets and
# High-dimensional Matrices. Sergiy Bogomolov, Marcelo Forets, Goran Frehse,
# Frédéric Viry, Andreas Podelski and Christian Schilling (2018) HSCC'18
# Proceedings of the 21st International Conference on Hybrid Systems: Computation
# and Control: 41–50.
#
function reach_inhomog_krylov_LGG09!(out, Ω₀::LazySet, V::Vector{<:LazySet}, Aᵀδ::AbstractMatrix,
::AbstractVector, NSTEPS;
hermitian=false, m=min(30, size(Aᵀδ, 1)), tol=1e-7)

# initialization of the krylov subspace
TA, Tb = eltype(Aᵀδ), eltype(ℓ)
T = promote_type(TA, Tb)
Ks = KrylovSubspace{T, real(T)}(length(ℓ), m)
arnoldi!(Ks, Aᵀδ, ℓ; m=m, ishermitian=hermitian, tol=tol)

# rᵢ stores is the cache for each vector: (Φᵀ)^i ℓ
r = Vector{Vector{T}}(undef, NSTEPS)
r[1] = deepcopy(ℓ)
out[1] = ρ(ℓ, Ω₀)

@inbounds for i in 1:NSTEPS-1
s = zero(T)
for j in 1:i
s += ρ(r[i-j+1], V[j])
end
expv!(r[i+1], i*1.0, Ks)
out[i+1] = ρ(r[i+1], Ω₀) + s
end
return out
end

end end # quote / load_krylov_LGG09_inhomog()
1 change: 1 addition & 0 deletions src/Flowpipes/flowpipes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ function project(fp::Flowpipe, vars::NTuple{D, T}) where {D, T<:Integer}
end
end

project(fp::Flowpipe, vars::Int) = project(fp, (vars,))
project(fp::Flowpipe, vars::AbstractVector{<:Int}) = project(fp, Tuple(vars))
project(fp::Flowpipe; vars) = project(fp, Tuple(vars))
project(fp::Flowpipe, i::Int, vars) = project(fp[i], vars)
Expand Down
5 changes: 5 additions & 0 deletions src/Flowpipes/reachsets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,11 @@ end
vars_idx = indexin(variables, all_variables) |> Vector{Int}
end

# concrete projection onto a single variable
function project(R::AbstractLazyReachSet, variable::Int; check_vars::Bool=true)
return project(R, (variable,), check_vars=check_vars)
end

# lazy projection of a reach-set
function Projection(R::AbstractLazyReachSet, variables::NTuple{D, M},
check_vars::Bool=true) where {D, M<:Integer}
Expand Down
3 changes: 2 additions & 1 deletion src/Initialization/init_ExponentialUtilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ eval(quote
using .ExponentialUtilities: expv, expv!, arnoldi, arnoldi!, KrylovSubspace
end)

eval(load_exponential_utilities_LGG09())
eval(load_krylov_LGG09_homog())
eval(load_krylov_LGG09_inhomog())

0 comments on commit e94e9fd

Please sign in to comment.