Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add discrete post for linear algorithms #887

Merged
merged 8 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 27 additions & 11 deletions src/Algorithms/A20/post.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
function post(alg::A20{N}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...) where {N}
@unpack δ, max_order = alg
# continuous post
function post(alg::A20, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...)
δ = alg.δ

NSTEPS = get(kwargs, :NSTEPS, compute_nsteps(δ, tspan))

# normalize system to canonical form
# x' = Ax, x in X, or
# x' = Ax + u, x in X, u in U
ivp_norm = _normalize(ivp)

# homogenize the initial-value problem
Expand All @@ -15,13 +14,30 @@ function post(alg::A20{N}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
end

# discretize system
ivp_discr = discretize(ivp_norm, δ, approx_model)
Φ = state_matrix(ivp_discr)
Ω0 = initial_state(ivp_discr)
X = stateset(ivp_discr)
ivp_discr = discretize(ivp_norm, δ, alg.approx_model)

return post(alg, ivp_discr, NSTEPS; Δt0=Δt0, kwargs...)
end

# discrete post
function post(alg::A20{N}, ivp::IVP{<:AbstractDiscreteSystem}, NSTEPS=nothing;
Δt0::TimeInterval=zeroI, kwargs...) where {N}
@unpack δ, max_order = alg

if isnothing(NSTEPS)
if haskey(kwargs, :NSTEPS)
NSTEPS = kwargs[:NSTEPS]
else
throw(ArgumentError("`NSTEPS` not specified"))
end
end

Φ = state_matrix(ivp)
Ω0 = initial_state(ivp)
X = stateset(ivp)

# true <=> there is no input, i.e. the system is of the form x' = Ax, x ∈ X
got_homogeneous = !hasinput(ivp_discr)
got_homogeneous = !hasinput(ivp)

# this algorithm requires Ω0 to be a zonotope
Ω0 = _convert_or_overapproximate(Zonotope, Ω0)
Expand Down Expand Up @@ -53,7 +69,7 @@ function post(alg::A20{N}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
disjointness_method)
else
# TODO: implement preallocate option for this scenario
U = inputset(ivp_discr)
U = inputset(ivp)
@assert isa(U, LazySet) "expected input of type `<:LazySet`, but got $(typeof(U))"
U = _convert_or_overapproximate(Zonotope, U)
reach_inhomog_GLGM06!(F, Ω0, Φ, NSTEPS, δ, max_order, X, U, reduction_method, Δt0,
Expand Down
38 changes: 27 additions & 11 deletions src/Algorithms/ASB07/post.jl
Original file line number Diff line number Diff line change
@@ -1,22 +1,38 @@
function post(alg::ASB07{N}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...) where {N}
@unpack δ, approx_model, max_order, reduction_method, static, recursive, dim, ngens = alg
# continuous post
function post(alg::ASB07, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...)
δ = alg.δ

NSTEPS = get(kwargs, :NSTEPS, compute_nsteps(δ, tspan))

# normalize system to canonical form
# x' = Ax, x in X, or
# x' = Ax + u, x in X, u in U
ivp_norm = _normalize(ivp)

# discretize system
ivp_discr = discretize(ivp_norm, δ, approx_model)
Φ = state_matrix(ivp_discr)
Ω0 = initial_state(ivp_discr)
X = stateset(ivp_discr)
ivp_discr = discretize(ivp_norm, δ, alg.approx_model)

return post(alg, ivp_discr, NSTEPS; Δt0=Δt0, kwargs...)
end

# discrete post
function post(alg::ASB07{N}, ivp::IVP{<:AbstractDiscreteSystem}, NSTEPS=nothing;
Δt0::TimeInterval=zeroI, kwargs...) where {N}
@unpack δ, approx_model, max_order, reduction_method, static, recursive, dim, ngens = alg

if isnothing(NSTEPS)
if haskey(kwargs, :NSTEPS)
NSTEPS = kwargs[:NSTEPS]
else
throw(ArgumentError("`NSTEPS` not specified"))
end
end

Φ = state_matrix(ivp)
Ω0 = initial_state(ivp)
X = stateset(ivp)

# true <=> there is no input, i.e. the system is of the form x' = Ax, x ∈ X
got_homogeneous = !hasinput(ivp_discr)
got_homogeneous = !hasinput(ivp)

# this algorithm requires Ω0 to be a zonotope
Ω0 = _convert_or_overapproximate(Zonotope, Ω0)
Expand All @@ -34,7 +50,7 @@ function post(alg::ASB07{N}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
if got_homogeneous
reach_homog_ASB07!(F, Ω0, Φ, NSTEPS, δ, max_order, X, recursive, reduction_method, Δt0)
else
U = inputset(ivp_discr)
U = inputset(ivp)
@assert isa(U, LazySet) "expected input of type `<:LazySet`, but got $(typeof(U))"
U = _convert_or_overapproximate(Zonotope, U)
reach_inhomog_ASB07!(F, Ω0, Φ, NSTEPS, δ, max_order, X, U, recursive, reduction_method, Δt0)
Expand Down
42 changes: 28 additions & 14 deletions src/Algorithms/BFFPSV18/post.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
function post(alg::BFFPSV18{N,ST}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...) where {N,ST}
@unpack δ, approx_model, vars, block_indices,
row_blocks, column_blocks = alg
# continuous post
function post(alg::BFFPSV18, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...)
δ = alg

NSTEPS = get(kwargs, :NSTEPS, compute_nsteps(δ, tspan))

# normalize system to canonical form
# x' = Ax, x in X, or
# x' = Ax + u, x in X, u in U
ivp_norm = _normalize(ivp)

# homogenize the initial-value problem
Expand All @@ -16,19 +14,35 @@ function post(alg::BFFPSV18{N,ST}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
end

# discretize system
ivp_discr = discretize(ivp_norm, δ, approx_model)
Φ = state_matrix(ivp_discr)
Ω0 = initial_state(ivp_discr)
X = stateset(ivp_discr)
ivp_discr = discretize(ivp_norm, δ, alg.approx_model)

return post(alg, ivp_discr, NSTEPS; Δt0=Δt0, kwargs...)
end

# discrete post
function post(alg::BFFPSV18{N,ST}, ivp::IVP{<:AbstractDiscreteSystem}, NSTEPS=nothing;
Δt0::TimeInterval=zeroI, kwargs...) where {N,ST}
@unpack δ, approx_model, vars, block_indices,
row_blocks, column_blocks = alg

if isnothing(NSTEPS)
if haskey(kwargs, :NSTEPS)
NSTEPS = kwargs[:NSTEPS]
else
throw(ArgumentError("`NSTEPS` not specified"))
end
end

Φ = state_matrix(ivp)
Ω0 = initial_state(ivp)
X = stateset(ivp)

# true <=> there is no input, i.e. the system is of the form x' = Ax, x ∈ X
got_homogeneous = !hasinput(ivp_discr)
got_homogeneous = !hasinput(ivp)

# decompose the initial states into a cartesian product
# TODO add option to do the lazy decomposition
Xhat0 = _decompose(Ω0, column_blocks, ST)
Φ = state_matrix(ivp_discr)
X = stateset(ivp_discr) # invariant

# force using sparse type for the matrix exponential
if alg.sparse
Expand All @@ -51,7 +65,7 @@ function post(alg::BFFPSV18{N,ST}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
row_blocks, column_blocks, Δt0, viewval)

else
U = inputset(ivp_discr)
U = inputset(ivp)
@assert isa(U, LazySet) "expected input of type `<:LazySet`, but got $(typeof(U))"
reach_inhomog_BFFPSV18!(F, Xhat0, Φ, NSTEPS, δ, X, U, ST,
vars, block_indices,
Expand Down
36 changes: 27 additions & 9 deletions src/Algorithms/BOX/post.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
function post(alg::BOX{N}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...) where {N}
@unpack δ, approx_model, static, dim, recursive = alg
# continuous post
function post(alg::BOX, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...)
δ = alg.δ

NSTEPS = get(kwargs, :NSTEPS, compute_nsteps(δ, tspan))

Expand All @@ -13,13 +14,30 @@ function post(alg::BOX{N}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
end

# discretize system
ivp_discr = discretize(ivp_norm, δ, approx_model)
Φ = state_matrix(ivp_discr)
Ω0 = initial_state(ivp_discr)
X = stateset(ivp_discr)
ivp_discr = discretize(ivp_norm, δ, alg.approx_model)

return post(alg, ivp_discr, NSTEPS; Δt0=Δt0, kwargs...)
end

# discrete post
function post(alg::BOX{N}, ivp::IVP{<:AbstractDiscreteSystem}, NSTEPS=nothing;
Δt0::TimeInterval=zeroI, kwargs...) where {N}
@unpack δ, approx_model, static, dim, recursive = alg

if isnothing(NSTEPS)
if haskey(kwargs, :NSTEPS)
NSTEPS = kwargs[:NSTEPS]
else
throw(ArgumentError("`NSTEPS` not specified"))
end
end

Φ = state_matrix(ivp)
Ω0 = initial_state(ivp)
X = stateset(ivp)

# true <=> there is no input, i.e. the system is of the form x' = Ax, x ∈ X
got_homogeneous = !hasinput(ivp_discr)
got_homogeneous = !hasinput(ivp)

# this algorithm requires Ω0 to be hyperrectangle
Ω0 = _overapproximate(Ω0, Hyperrectangle)
Expand All @@ -36,7 +54,7 @@ function post(alg::BOX{N}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
if got_homogeneous
reach_homog_BOX!(F, Ω0, Φ, NSTEPS, δ, X, recursive, Δt0)
else
U = inputset(ivp_discr)
U = inputset(ivp)
@assert isa(U, LazySet) "expected input of type `<:LazySet`, but got $(typeof(U))"
# TODO: can we use support function evaluations for the input set?
U = overapproximate(U, Hyperrectangle)
Expand Down
9 changes: 4 additions & 5 deletions src/Algorithms/GLGM06/post.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
# continuous post for GLGM06 using Zonotope set representation
function post(alg::GLGM06{N}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...) where {N}
# continuous post
function post(alg::GLGM06, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...)
δ = alg.δ

NSTEPS = get(kwargs, :NSTEPS, compute_nsteps(δ, tspan))

# normalize system to canonical form
# x' = Ax, x in X, or
# x' = Ax + u, x in X, u in U
ivp_norm = _normalize(ivp)

# homogenize the initial-value problem
Expand All @@ -21,6 +19,7 @@ function post(alg::GLGM06{N}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
return post(alg, ivp_discr, NSTEPS; Δt0=Δt0, kwargs...)
end

# discrete post
function post(alg::GLGM06{N}, ivp::IVP{<:AbstractDiscreteSystem}, NSTEPS=nothing;
Δt0::TimeInterval=zeroI, kwargs...) where {N}
@unpack δ, approx_model, max_order, static, dim, ngens,
Expand Down
37 changes: 27 additions & 10 deletions src/Algorithms/INT/post.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# this algorithms assumes that the initial-value problem is one-dimensional
function post(alg::INT{N}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...) where {N}
# continuous post
function post(alg::INT, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...)
n = statedim(ivp)
n == 1 || throw(ArgumentError("this algorithm applies to one-dimensional " *
"systems, but this initial-value problem is $n-dimensional"))

@unpack δ, approx_model = alg
δ = alg

NSTEPS = get(kwargs, :NSTEPS, compute_nsteps(δ, tspan))

Expand All @@ -18,16 +18,33 @@ function post(alg::INT{N}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
end

# discretize system
ivp_discr = discretize(ivp_norm, δ, approx_model)
Φ = state_matrix(ivp_discr)[1, 1]
Ω0 = initial_state(ivp_discr)
X = stateset(ivp_discr)
ivp_discr = discretize(ivp_norm, δ, alg.approx_model)

return post(alg, ivp_discr, NSTEPS; Δt0=Δt0, kwargs...)
end

# discrete post
function post(alg::INT{N}, ivp::IVP{<:AbstractDiscreteSystem}, NSTEPS=nothing;
Δt0::TimeInterval=zeroI, kwargs...) where {N}
@unpack δ, approx_model = alg

if isnothing(NSTEPS)
if haskey(kwargs, :NSTEPS)
NSTEPS = kwargs[:NSTEPS]
else
throw(ArgumentError("`NSTEPS` not specified"))
end
end

Φ = state_matrix(ivp)[1, 1]
Ω0 = initial_state(ivp)
X = stateset(ivp)

# this algorithm requires Ω0 to be an interval
Ω0 = overapproximate(Ω0, Interval)

# true <=> there is no input, i.e. the system is of the form x' = Ax, x ∈ X
got_homogeneous = !hasinput(ivp_discr)
got_homogeneous = !hasinput(ivp)

# preallocate output flowpipe
IT = typeof(Ω0)
Expand All @@ -37,7 +54,7 @@ function post(alg::INT{N}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
if got_homogeneous
reach_homog_INT!(F, Ω0, Φ, NSTEPS, δ, X, Δt0)
else
U = inputset(ivp_discr)
U = inputset(ivp)
@assert isa(U, LazySet)
U = overapproximate(U, Interval) # TODO guarantee this on the discretization?
reach_inhomog_INT!(F, Ω0, Φ, NSTEPS, δ, X, U, Δt0)
Expand Down
37 changes: 28 additions & 9 deletions src/Algorithms/LGG09/post.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
function post(alg::LGG09{N,AM,VN,TN}, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...) where {N,AM,VN,TN}
@unpack δ, approx_model, template, static, threaded, vars = alg
# continuous post
function post(alg::LGG09, ivp::IVP{<:AbstractContinuousSystem}, tspan;
Δt0::TimeInterval=zeroI, kwargs...)
δ = alg.δ

# dimension check
template = alg.template
@assert statedim(ivp) == dim(template) "the problems' dimension $(statedim(ivp)) " *
"doesn't match the dimension of the template directions, $(dim(template))"

Expand All @@ -17,10 +19,27 @@ function post(alg::LGG09{N,AM,VN,TN}, ivp::IVP{<:AbstractContinuousSystem}, tspa
end

# discretize system
ivp_discr = discretize(ivp_norm, δ, approx_model)
Φ = state_matrix(ivp_discr)
Ω₀ = initial_state(ivp_discr)
X = stateset(ivp_discr)
ivp_discr = discretize(ivp_norm, δ, alg.approx_model)

return post(alg, ivp_discr, NSTEPS; Δt0=Δt0, kwargs...)
end

# discrete post
function post(alg::LGG09{N,AM,VN,TN}, ivp::IVP{<:AbstractDiscreteSystem}, NSTEPS=nothing;
Δt0::TimeInterval=zeroI, kwargs...) where {N,AM,VN,TN}
@unpack δ, approx_model, template, static, threaded, vars = alg

if isnothing(NSTEPS)
if haskey(kwargs, :NSTEPS)
NSTEPS = kwargs[:NSTEPS]
else
throw(ArgumentError("`NSTEPS` not specified"))
end
end

Φ = state_matrix(ivp)
Ω₀ = initial_state(ivp)
X = stateset(ivp)

if alg.sparse # ad-hoc conversion of Φ to sparse representation
Φ = sparse(Φ)
Expand All @@ -29,7 +48,7 @@ function post(alg::LGG09{N,AM,VN,TN}, ivp::IVP{<:AbstractContinuousSystem}, tspa
cacheval = Val(alg.cache)

# true <=> there is no input, i.e. the system is of the form x' = Ax, x ∈ X
got_homogeneous = !hasinput(ivp_discr)
got_homogeneous = !hasinput(ivp)

# NOTE: option :static currently ignored!

Expand All @@ -41,7 +60,7 @@ function post(alg::LGG09{N,AM,VN,TN}, ivp::IVP{<:AbstractContinuousSystem}, tspa
if got_homogeneous
ρℓ = reach_homog_LGG09!(F, template, Ω₀, Φ, NSTEPS, δ, X, Δt0, cacheval, Val(alg.threaded))
else
U = inputset(ivp_discr)
U = inputset(ivp)
@assert isa(U, LazySet)
ρℓ = reach_inhomog_LGG09!(F, template, Ω₀, Φ, NSTEPS, δ, X, U, Δt0, cacheval,
Val(alg.threaded))
Expand Down
Loading
Loading