diff --git a/src/ReachSets/reach.jl b/src/ReachSets/reach.jl index 9380166f..0b363b9c 100644 --- a/src/ReachSets/reach.jl +++ b/src/ReachSets/reach.jl @@ -41,11 +41,6 @@ Interface to reachability algorithms for an LTI system. A dictionary with available algorithms is available via `Reachability.available_algorithms`. - -WARNING: - -Only systems of even dimension are parsed; for odd dimension, manually add an -extra variable with no dynamics. """ function reach(S::AbstractSystem, N::Int; diff --git a/src/options.jl b/src/options.jl index 173c8e3e..431737f3 100644 --- a/src/options.jl +++ b/src/options.jl @@ -206,8 +206,8 @@ function validate_solver_options_and_add_default_values!(options::Options)::Opti elseif key == :partition expected_type = AbstractVector{<:AbstractVector{Int}} elseif key == :block_types - expected_type = - Dict{Type{<:LazySet}, AbstractVector{<:AbstractVector{Int}}} + expected_type = Union{Void, + Dict{Type{<:LazySet}, AbstractVector{<:AbstractVector{Int}}}} elseif key == :block_types_init expected_type = Dict{Type{<:LazySet}, AbstractVector{<:AbstractVector{Int}}} @@ -478,12 +478,18 @@ function check_and_add_partition_block_types!(dict::Dict{Symbol,Any}, error("need option :partition specified") end - block_types = haskey(dict, :block_types) ? dict[:block_types] : - haskey(dict, :set_type) ? - Dict{Type{<:LazySet}, AbstractVector{<:AbstractVector{Int}}}( - dict[:set_type] => copy(dict_copy[:partition]) - ) : nothing - check_aliases!(dict, dict_copy, [:block_types]) + block_types = nothing + if haskey(dict, :block_types) + for (key, value) in dict[:block_types] + @assert key <: LazySet "the keys of the `partition` dictionary should be lazy sets" + @assert typeof(value) <: AbstractVector{<:AbstractVector{Int}} "the keys of the `partition` dictionary should be vectors of vectors" + end + block_types = convert(Dict{Type{<:LazySet}, AbstractVector{<:AbstractVector{Int}}}, dict[:block_types]) + elseif haskey(dict, :set_type) + block_types = Dict{Type{<:LazySet}, AbstractVector{<:AbstractVector{Int}}}(dict[:set_type] => copy(dict_copy[:partition])) + end + check_aliases_and_add_default_value!(dict, dict_copy, [:block_types], block_types) + dict_copy[:block_types] = block_types block_types_init = haskey(dict, :block_types_init) ? dict[:block_types_init] : diff --git a/src/solve.jl b/src/solve.jl index 4705c212..100761f8 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -83,11 +83,8 @@ function solve(system::AbstractSystem, # ========== # Dimensions # ========== - dimension = statedim(system) - if isodd(dimension) - system = add_dimension(system) - end - options_input.dict[:n] = dimension + options_input.dict[:n] = statedim(system) + # ======= # Options # ======= diff --git a/test/Reachability/unit_solve.jl b/test/Reachability/unit_solve.jl index e13dc256..a2616f4d 100644 --- a/test/Reachability/unit_solve.jl +++ b/test/Reachability/unit_solve.jl @@ -47,3 +47,11 @@ s = solve(ContinuousSystem(sparse(A), X0), :T=>0.1, :partition=>[1:2, 3:4], s = solve(ContinuousSystem(sparse(A), X0), :T=>0.1, :partition=>[[i] for i in 1:4], :set_type=>Interval, :vars=>[1,3], :lazy_expm=>true); + +# =============================== +# System with an odd dimension +# =============================== +A = randn(5, 5); X0 = BallInf(ones(5), 0.1) +system = ContinuousSystem(A, X0) +options = Options(Dict(:T=>0.1, :partition=>[1:2, 3:4, [5]], :block_types=>Dict(HPolygon=>[1:2, 3:4], Interval=>[[5]]), :vars=>[1,3])) +s = solve(system, options)