From 90bed96c3b0962c8109c5c0c5d43a89494b196ae Mon Sep 17 00:00:00 2001 From: alecarraro Date: Thu, 14 Aug 2025 19:22:52 +0200 Subject: [PATCH 1/6] add system type supporting matrix zonotope --- Project.toml | 2 + src/MathematicalSystems.jl | 1 + src/abstract.jl | 12 +++ src/macros.jl | 18 ++-- src/systems.jl | 178 +++++++++++++++++++++++++++++++++++++ 5 files changed, 199 insertions(+), 12 deletions(-) diff --git a/Project.toml b/Project.toml index de07344a..42740c2e 100644 --- a/Project.toml +++ b/Project.toml @@ -9,6 +9,7 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" MultivariatePolynomials = "102ac46a-7ee4-5c85-9060-abc95bfdeaa3" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" +Requires = "ae029012-a4dd-5104-9daa-d747884805df" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" [compat] @@ -18,5 +19,6 @@ LinearAlgebra = "<0.0.1, 1.4" MacroTools = "0.5" MultivariatePolynomials = "0.3, 0.4, 0.5" RecipesBase = "0.6, 0.7, 0.8, 1.0, 1.1, 1.2" +Requires = "1.3.1" SparseArrays = "<0.0.1, 1.4" julia = "1.5" diff --git a/src/MathematicalSystems.jl b/src/MathematicalSystems.jl index f620044f..c4640712 100644 --- a/src/MathematicalSystems.jl +++ b/src/MathematicalSystems.jl @@ -1,5 +1,6 @@ module MathematicalSystems +using Requires using LinearAlgebra, SparseArrays using LinearAlgebra: checksquare import RecipesBase diff --git a/src/abstract.jl b/src/abstract.jl index e27415a0..e6d3ae02 100644 --- a/src/abstract.jl +++ b/src/abstract.jl @@ -212,6 +212,18 @@ can also be applied to `typeof(s)`. """ function isconstrained(::AbstractSystem) end +""" + isparametric(s::AbstractSystem) + +Determines if the system `s` contains one or more symbolic parameters in its +dynamics (for example, matrix entries that can take values from a +specified set). + +The result of this function only depends on the +system type, not the value, and can also be applied to `typeof(s)`. +""" +function isparametric(::AbstractSystem) end + """ AbstractMap diff --git a/src/macros.jl b/src/macros.jl index 4ccdd6cf..fa860635 100644 --- a/src/macros.jl +++ b/src/macros.jl @@ -127,7 +127,7 @@ Return the system type whose field names match those in `fields`. ### Input - `AT` -- abstract system type, which can be either `AbstractContinuousSystem` - or `AbstractDiscreSystem` + or `AbstractDiscreteSystem` - `fields` -- tuple of field names ### Output @@ -757,15 +757,6 @@ function _sort(parameters::Vector{<:Tuple{Any,Symbol}}, order::NTuple{N,Symbol}) return order_parameters end -function _get_system_type(dyn_eq, AT, constr, state, input, noise, dim) - lhs, rhs = extract_dyn_equation_parameters(dyn_eq, state, input, noise, dim, AT) - ordered_rhs = _sort(rhs, (:A, :B, :c, :D, :f, :statedim, :inputdim, :noisedim)) - ordered_set = _sort(extract_set_parameter.(constr, state, input, noise), (:X, :U, :W)) - field_names, var_names = constructor_input(lhs, ordered_rhs, ordered_set) - sys_type = _corresponding_type(AT, field_names) - return sys_type, var_names -end - """ system(expr...) @@ -883,8 +874,11 @@ ConstrainedBlackBoxControlDiscreteSystem{typeof(f), BallInf{Float64, Vector{Floa macro system(expr...) try dyn_eq, AT, constr, state, input, noise, dim, x0 = _parse_system(expr) - sys_type, var_names = _get_system_type(dyn_eq, AT, constr, state, input, noise, dim) - sys = Expr(:call, :($sys_type), :($(var_names...))) + lhs, rhs = extract_dyn_equation_parameters(dyn_eq, state, input, noise, dim, AT) + ordered_rhs = _sort(rhs, (:A, :B, :c, :D, :f, :statedim, :inputdim, :noisedim)) + ordered_set = _sort(extract_set_parameter.(constr, state, input, noise), (:X, :U, :W)) + _, var_names = constructor_input(lhs, ordered_rhs, ordered_set) + sys = Expr(:call, :(_create_system), esc.(var_names)...) if isnothing(x0) return esc(sys) else diff --git a/src/systems.jl b/src/systems.jl index 8a26a705..a0efb268 100644 --- a/src/systems.jl +++ b/src/systems.jl @@ -18,6 +18,7 @@ for (Z, AZ) in ((:ContinuousIdentitySystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -73,6 +74,7 @@ for (Z, AZ) in ((:ConstrainedContinuousIdentitySystem, :AbstractContinuousSystem isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -137,6 +139,7 @@ for (Z, AZ) in ((:LinearContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -203,6 +206,7 @@ for (Z, AZ) in ((:AffineContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -271,6 +275,7 @@ for (Z, AZ) in ((:LinearControlContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = true isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -337,6 +342,7 @@ for (Z, AZ) in ((:ConstrainedLinearContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -408,6 +414,7 @@ for (Z, AZ) in ((:ConstrainedAffineContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -482,6 +489,7 @@ for (Z, AZ) in ((:AffineControlContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = true isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -561,6 +569,7 @@ for (Z, AZ) in ((:ConstrainedAffineControlContinuousSystem, :AbstractContinuousS isnoisy(::$T) = false iscontrolled(::$T) = true isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -640,6 +649,7 @@ for (Z, AZ) in ((:ConstrainedLinearControlContinuousSystem, :AbstractContinuousS isnoisy(::$T) = false iscontrolled(::$T) = true isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -710,6 +720,7 @@ for (Z, AZ) in ((:LinearDescriptorContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -780,6 +791,7 @@ for (Z, AZ) in ((:ConstrainedLinearDescriptorContinuousSystem, :AbstractContinuo isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -855,6 +867,7 @@ for (Z, AZ) in ((:PolynomialContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -929,6 +942,7 @@ for (Z, AZ) in ((:ConstrainedPolynomialContinuousSystem, :AbstractContinuousSyst isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -988,6 +1002,7 @@ for (Z, AZ) in ((:BlackBoxContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -1047,6 +1062,7 @@ for (Z, AZ) in ((:ConstrainedBlackBoxContinuousSystem, :AbstractContinuousSystem isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -1109,6 +1125,7 @@ for (Z, AZ) in ((:BlackBoxControlContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = true isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -1173,6 +1190,7 @@ for (Z, AZ) in ((:ConstrainedBlackBoxControlContinuousSystem, :AbstractContinuou isnoisy(::$T) = false iscontrolled(::$T) = true isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -1253,6 +1271,7 @@ for (Z, AZ) in ((:NoisyLinearContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = true iscontrolled(::$T) = false isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -1326,6 +1345,7 @@ for (Z, AZ) in ((:NoisyConstrainedLinearContinuousSystem, :AbstractContinuousSys isnoisy(::$T) = true iscontrolled(::$T) = false isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -1402,6 +1422,7 @@ for (Z, AZ) in ((:NoisyLinearControlContinuousSystem, :AbstractContinuousSystem) isnoisy(::$T) = true iscontrolled(::$T) = true isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -1485,6 +1506,7 @@ for (Z, AZ) in ((:NoisyConstrainedLinearControlContinuousSystem, :AbstractContin isnoisy(::$T) = true iscontrolled(::$T) = true isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -1572,6 +1594,7 @@ for (Z, AZ) in ((:NoisyAffineControlContinuousSystem, :AbstractContinuousSystem) isnoisy(::$T) = true iscontrolled(::$T) = true isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -1657,6 +1680,7 @@ for (Z, AZ) in ((:NoisyConstrainedAffineControlContinuousSystem, :AbstractContin isnoisy(::$T) = true iscontrolled(::$T) = true isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -1728,6 +1752,7 @@ for (Z, AZ) in ((:NoisyBlackBoxControlContinuousSystem, :AbstractContinuousSyste isnoisy(::$T) = true iscontrolled(::$T) = true isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -1799,6 +1824,7 @@ for (Z, AZ) in ((:NoisyConstrainedBlackBoxControlContinuousSystem, :AbstractCont isnoisy(::$T) = true iscontrolled(::$T) = true isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -1920,6 +1946,7 @@ for (Z, AZ) in ((:SecondOrderLinearContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -2000,6 +2027,7 @@ for (Z, AZ) in ((:SecondOrderAffineContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -2095,6 +2123,7 @@ for (Z, AZ) in ((:SecondOrderConstrainedLinearControlContinuousSystem, :Abstract isnoisy(::$T) = false iscontrolled(::$T) = true isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -2195,6 +2224,7 @@ for (Z, AZ) in ((:SecondOrderConstrainedAffineControlContinuousSystem, :Abstract isnoisy(::$T) = false iscontrolled(::$T) = true isconstrained(::$T) = true + isparametric(::$T) = false end end end @@ -2281,6 +2311,7 @@ for (Z, AZ) in ((:SecondOrderContinuousSystem, :AbstractContinuousSystem), isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = false + isparametric(::$T) = false end end end @@ -2368,6 +2399,153 @@ for (Z, AZ) in ((:SecondOrderConstrainedContinuousSystem, :AbstractContinuousSys isnoisy(::$T) = false iscontrolled(::$T) = false isconstrained(::$T) = true + isparametric(::$T) = false + end + end +end + +function __init__() + @require LazySets = "b4f0291d-fe17-52bc-9479-3d1a343d9043" begin + using .LazySets: MatrixZonotope + + export LinearUncertainParametricContinuousSystem, + LinearUncertainParametricDiscreteSystem, + LinearControlUncertainParametricContinuousSystem, + LinearControlUncertainParametricDiscreteSystem + + @doc """ + LinearUncertainParametricContinuousSystem + + Continuous-time linear uncertain parametric system of the form: + + ```math + x(t)' = A(\\theta) x(t), \\theta ∈ \\Theta \\; \\forall t + ``` + where ``A(θ)`` belongs to a continuous set of matrices, e.g., an interval + matrix, matrix zonotope, or other convex matrix sets. + + ### Fields + - `A` -- uncertain state matrix + """ + LinearUncertainParametricContinuousSystem + + @doc """ + LinearUncertainParametricDiscreteSystem + + Discrete-time linear uncertain parametric system of the form: + ```math + x_{k+1} = A(\\theta) x_k, \\theta ∈ \\Theta \\; \\forall k + ``` + where ``A(θ)`` belongs to a continuous set of matrices, e.g., an interval + matrix, matrix zonotope, or other convex matrix sets. + + ### Fields + - `A` -- uncertain state matrix + """ + LinearUncertainParametricDiscreteSystem + + for (Z, AZ) in ((:LinearUncertainParametricContinuousSystem, :AbstractContinuousSystem), + (:LinearUncertainParametricDiscreteSystem, :AbstractDiscreteSystem)) + + @eval begin + struct $(Z){T, MA<:MatrixZonotope{T}} <: $(AZ) + A::MA + end + + statedim(s::$Z) = size(s.A, 1) + inputdim(::$Z) = 0 + noisedim(::$Z) = 0 + state_matrix(s::$Z) = s.A + end + + for T in [Z, Type{<:eval(Z)}] + @eval begin + islinear(::$T) = true + isaffine(::$T) = false + ispolynomial(::$T) = false + isnoisy(::$T) = false + iscontrolled(::$T) = false + isconstrained(::$T) = false + isparametric(::$T) = true + end + end + end + + @doc """ + LinearControlUncertainParametricContinuousSystem + + Continuous-time linear uncertain parametric system of the form: + + ```math + x(t)' = A(θ) x(t) + B(θ) u(t), \\theta ∈ \\Theta \\; \\forall t + ``` + + where ``A(θ)`` and ``B(θ)`` belong to continuous sets of matrices, e.g., an interval + matrix, matrix zonotope, or other convex matrix sets. + + ### Fields + - `A` -- uncertain state matrix + - `B` -- uncertain input matrix + """ + LinearControlUncertainParametricContinuousSystem + + @doc """ + LinearControlUncertainParametricDiscreteSystem + + Discrete-time linear uncertain parametric system of the form: + + ```math + x_{k+1} = A(θ) x_k + B(θ) u_k, \\theta ∈ \\Theta \\; \\forall k + ``` + + where ``A(θ)`` and ``B(θ)`` belong to continuous sets of matrices, e.g., an interval + matrix, matrix zonotope, or other convex matrix sets. + + ### Fields + - `A` -- uncertain state matrix + - `B` -- uncertain input matrix + """ + LinearControlUncertainParametricDiscreteSystem + + for (Z, AZ) in + ((:LinearControlUncertainParametricContinuousSystem, :AbstractContinuousSystem), + (:LinearControlUncertainParametricDiscreteSystem, :AbstractDiscreteSystem)) + + @eval begin + struct $(Z){T, MTA<:MatrixZonotope{T}, MTB<:MatrixZonotope{T}} <: $(AZ) + A::MTA + B::MTB + function $(Z)(A::MTA, B::MTB) where {T, MTA<:MatrixZonotope{T}, MTB<:MatrixZonotope{T}} + if size(A, 1) != size(A, 2) || size(A, 1) != size(B, 1) + throw(DimensionMismatch("incompatible dimensions")) + end + return new{T, MTA, MTB}(A, B) + end + end + + function $(Z)(A::Number, B::Number) + return $(Z)(hcat(A), hcat(B)) + end + + statedim(s::$Z) = size(s.A, 1) + inputdim(s::$Z) = size(s.B, 2) + noisedim(::$Z) = 0 + state_matrix(s::$Z) = s.A + input_matrix(s::$Z) = s.B + end + + for T in [Z, Type{<:eval(Z)}] + @eval begin + islinear(::$T) = true + isaffine(::$T) = true + ispolynomial(::$T) = false + isblackbox(::$T) = false + isnoisy(::$T) = false + iscontrolled(::$T) = true + isconstrained(::$T) = false + isparametric(::$T) = true + end + end end end end From e4864410ef71c0590816e2bae532e7e30be90415 Mon Sep 17 00:00:00 2001 From: alecarraro Date: Tue, 19 Aug 2025 11:15:35 +0200 Subject: [PATCH 2/6] add documentation and fix tests --- docs/src/lib/methods.md | 1 + docs/src/lib/types.md | 4 ++ docs/src/man/systems.md | 4 ++ src/MathematicalSystems.jl | 3 +- src/macros.jl | 16 ++++-- src/systems.jl | 63 ++++++++++++--------- test/continuous.jl | 111 ++++++++++++++++++++++++++++--------- test/discrete.jl | 98 ++++++++++++++++++++++++-------- test/discretize.jl | 22 +++++--- test/runtests.jl | 7 +++ 10 files changed, 241 insertions(+), 88 deletions(-) diff --git a/docs/src/lib/methods.md b/docs/src/lib/methods.md index 109d87b2..3c4c9a96 100644 --- a/docs/src/lib/methods.md +++ b/docs/src/lib/methods.md @@ -55,6 +55,7 @@ isblackbox(::AbstractSystem) isnoisy(::AbstractSystem) iscontrolled(::AbstractSystem) isconstrained(::AbstractSystem) +isparametric(::AbstractSystem) state_matrix(::AbstractSystem) input_matrix(::AbstractSystem) noise_matrix(::AbstractSystem) diff --git a/docs/src/lib/types.md b/docs/src/lib/types.md index e7784b16..8ae0c445 100644 --- a/docs/src/lib/types.md +++ b/docs/src/lib/types.md @@ -57,6 +57,8 @@ SecondOrderConstrainedAffineControlContinuousSystem SecondOrderConstrainedLinearControlContinuousSystem SecondOrderContinuousSystem SecondOrderConstrainedContinuousSystem +LinearParametricContinuousSystem +LinearControlParametricContinuousSystem ``` ## Discrete Systems @@ -94,6 +96,8 @@ SecondOrderConstrainedAffineControlDiscreteSystem SecondOrderConstrainedLinearControlDiscreteSystem SecondOrderDiscreteSystem SecondOrderConstrainedDiscreteSystem +LinearParametricDiscreteSystem +LinearControlParametricDiscreteSystem ``` #### Discretization Algorithms diff --git a/docs/src/man/systems.md b/docs/src/man/systems.md index 9519dcbf..852e5866 100644 --- a/docs/src/man/systems.md +++ b/docs/src/man/systems.md @@ -99,6 +99,8 @@ However in this table we only included continuous system types for brevity. |SOACS|[`SecondOrderAffineContinuousSystem`](@ref)| |SOCACCS|[`SecondOrderConstrainedAffineControlContinuousSystem`](@ref)| |SOCLCCS|[`SecondOrderConstrainedLinearControlContinuousSystem`](@ref)| +|LPCS|[`LinearParametricContinuousSystem`](@ref)| +|LCPCS|[`LinearControlParametricContinuousSystem`](@ref)| The following table summarizes the equation represented by each system type (the names are given in abbreviated form). Again, discrete systems are not included. The column *Input constraints* is `yes` if the structure can model input or noise constraints (or both). @@ -137,3 +139,5 @@ The following table summarizes the equation represented by each system type |``Mx'' + Cx' + Kx = Bu, x ∈ X, u ∈ U``|yes|yes|SOCLCCS| |``Mx'' + Cx' + f_i(x) = f_e``|no|no|SOCS| |``Mx'' + Cx' + f_i(x) = f_e``, x ∈ X, u ∈ U``|yes|yes|SOCCS| +|``x' = A(θ)x, θ ∈ Θ``| no|no|LPCS| +|``x' = A(θ)x + B(θ)u, θ ∈ Θ``| no|no|LPCS| diff --git a/src/MathematicalSystems.jl b/src/MathematicalSystems.jl index c4640712..cee8b36e 100644 --- a/src/MathematicalSystems.jl +++ b/src/MathematicalSystems.jl @@ -56,7 +56,8 @@ export islinear, isblackbox, isnoisy, iscontrolled, - isconstrained + isconstrained, + isparametric #==================================== Concrete Types for Continuous Systems diff --git a/src/macros.jl b/src/macros.jl index fa860635..e89b496b 100644 --- a/src/macros.jl +++ b/src/macros.jl @@ -757,6 +757,15 @@ function _sort(parameters::Vector{<:Tuple{Any,Symbol}}, order::NTuple{N,Symbol}) return order_parameters end +function _get_system_type(dyn_eq, AT, constr, state, input, noise, dim) + lhs, rhs = extract_dyn_equation_parameters(dyn_eq, state, input, noise, dim, AT) + ordered_rhs = _sort(rhs, (:A, :B, :c, :D, :f, :statedim, :inputdim, :noisedim)) + ordered_set = _sort(extract_set_parameter.(constr, state, input, noise), (:X, :U, :W)) + field_names, var_names = constructor_input(lhs, ordered_rhs, ordered_set) + sys_type = _corresponding_type(AT, field_names) + return sys_type, var_names +end + """ system(expr...) @@ -874,11 +883,8 @@ ConstrainedBlackBoxControlDiscreteSystem{typeof(f), BallInf{Float64, Vector{Floa macro system(expr...) try dyn_eq, AT, constr, state, input, noise, dim, x0 = _parse_system(expr) - lhs, rhs = extract_dyn_equation_parameters(dyn_eq, state, input, noise, dim, AT) - ordered_rhs = _sort(rhs, (:A, :B, :c, :D, :f, :statedim, :inputdim, :noisedim)) - ordered_set = _sort(extract_set_parameter.(constr, state, input, noise), (:X, :U, :W)) - _, var_names = constructor_input(lhs, ordered_rhs, ordered_set) - sys = Expr(:call, :(_create_system), esc.(var_names)...) + sys_type, var_names = _get_system_type(dyn_eq, AT, constr, state, input, noise, dim) + sys = Expr(:call, :($sys_type), :($(var_names...))) if isnothing(x0) return esc(sys) else diff --git a/src/systems.jl b/src/systems.jl index a0efb268..3070655c 100644 --- a/src/systems.jl +++ b/src/systems.jl @@ -2408,15 +2408,15 @@ function __init__() @require LazySets = "b4f0291d-fe17-52bc-9479-3d1a343d9043" begin using .LazySets: MatrixZonotope - export LinearUncertainParametricContinuousSystem, - LinearUncertainParametricDiscreteSystem, - LinearControlUncertainParametricContinuousSystem, - LinearControlUncertainParametricDiscreteSystem + export LinearParametricContinuousSystem, + LinearParametricDiscreteSystem, + LinearControlParametricContinuousSystem, + LinearControlParametricDiscreteSystem @doc """ - LinearUncertainParametricContinuousSystem + LinearParametricContinuousSystem - Continuous-time linear uncertain parametric system of the form: + Continuous-time linear parametric system of the form: ```math x(t)' = A(\\theta) x(t), \\theta ∈ \\Theta \\; \\forall t @@ -2425,14 +2425,14 @@ function __init__() matrix, matrix zonotope, or other convex matrix sets. ### Fields - - `A` -- uncertain state matrix + - `A` -- parametric state matrix """ - LinearUncertainParametricContinuousSystem + LinearParametricContinuousSystem @doc """ - LinearUncertainParametricDiscreteSystem + LinearParametricDiscreteSystem - Discrete-time linear uncertain parametric system of the form: + Discrete-time linear parametric system of the form: ```math x_{k+1} = A(\\theta) x_k, \\theta ∈ \\Theta \\; \\forall k ``` @@ -2440,12 +2440,13 @@ function __init__() matrix, matrix zonotope, or other convex matrix sets. ### Fields - - `A` -- uncertain state matrix + - `A` -- parametric state matrix """ - LinearUncertainParametricDiscreteSystem + LinearParametricDiscreteSystem - for (Z, AZ) in ((:LinearUncertainParametricContinuousSystem, :AbstractContinuousSystem), - (:LinearUncertainParametricDiscreteSystem, :AbstractDiscreteSystem)) + for (Z, AZ) in ((:LinearParametricContinuousSystem, :AbstractContinuousSystem), + (:LinearParametricDiscreteSystem, :AbstractDiscreteSystem)) + BaseName = Symbol(replace(string(Z), "Parametric" => "")) @eval begin struct $(Z){T, MA<:MatrixZonotope{T}} <: $(AZ) @@ -2456,6 +2457,10 @@ function __init__() inputdim(::$Z) = 0 noisedim(::$Z) = 0 state_matrix(s::$Z) = s.A + + function $(BaseName)(M::MatrixZonotope) + return $Z(M) + end end for T in [Z, Type{<:eval(Z)}] @@ -2471,10 +2476,11 @@ function __init__() end end + @doc """ - LinearControlUncertainParametricContinuousSystem + LinearControlParametricContinuousSystem - Continuous-time linear uncertain parametric system of the form: + Continuous-time linear parametric system of the form: ```math x(t)' = A(θ) x(t) + B(θ) u(t), \\theta ∈ \\Theta \\; \\forall t @@ -2484,15 +2490,15 @@ function __init__() matrix, matrix zonotope, or other convex matrix sets. ### Fields - - `A` -- uncertain state matrix - - `B` -- uncertain input matrix + - `A` -- parametric state matrix + - `B` -- parametric input matrix """ - LinearControlUncertainParametricContinuousSystem + LinearControlParametricContinuousSystem @doc """ - LinearControlUncertainParametricDiscreteSystem + LinearControlParametricDiscreteSystem - Discrete-time linear uncertain parametric system of the form: + Discrete-time linear parametric system of the form: ```math x_{k+1} = A(θ) x_k + B(θ) u_k, \\theta ∈ \\Theta \\; \\forall k @@ -2502,14 +2508,15 @@ function __init__() matrix, matrix zonotope, or other convex matrix sets. ### Fields - - `A` -- uncertain state matrix - - `B` -- uncertain input matrix + - `A` -- parametric state matrix + - `B` -- parametric input matrix """ - LinearControlUncertainParametricDiscreteSystem + LinearControlParametricDiscreteSystem for (Z, AZ) in - ((:LinearControlUncertainParametricContinuousSystem, :AbstractContinuousSystem), - (:LinearControlUncertainParametricDiscreteSystem, :AbstractDiscreteSystem)) + ((:LinearControlParametricContinuousSystem, :AbstractContinuousSystem), + (:LinearControlParametricDiscreteSystem, :AbstractDiscreteSystem)) + BaseName = Symbol(replace(string(Z), "Parametric" => "")) @eval begin struct $(Z){T, MTA<:MatrixZonotope{T}, MTB<:MatrixZonotope{T}} <: $(AZ) @@ -2532,6 +2539,10 @@ function __init__() noisedim(::$Z) = 0 state_matrix(s::$Z) = s.A input_matrix(s::$Z) = s.B + + function $(BaseName)(MA::MatrixZonotope, MB::MatrixZonotope) + return $Z(MA, MB) + end end for T in [Z, Type{<:eval(Z)}] diff --git a/test/continuous.jl b/test/continuous.jl index cb6fa398..260dfbfa 100644 --- a/test/continuous.jl +++ b/test/continuous.jl @@ -55,7 +55,7 @@ Es = [e][:, :]; @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) && !isparametric(s) end end @@ -73,7 +73,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) && !isparametric(s) end end @@ -91,7 +91,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = LinearContinuousSystem(a) @@ -112,7 +112,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test !islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = AffineContinuousSystem(a, c) @@ -133,7 +133,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = LinearControlContinuousSystem(a, b) @@ -154,7 +154,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = ConstrainedLinearContinuousSystem(a, Xs) @@ -175,7 +175,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test !islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = ConstrainedAffineContinuousSystem(a, c, Xs) @@ -196,7 +196,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test !islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = ConstrainedAffineControlContinuousSystem(a, b, c, Xs, Us) @@ -216,7 +216,7 @@ end @test affine_term(s) == c for s in [s, typeof(s)] @test !islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System a = 1.0 @@ -243,7 +243,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && iscontrolled(s) && isconstrained(s) && !isparametric(s) end @testset "initial value problem composite type" begin @@ -300,7 +300,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = ConstrainedLinearDescriptorContinuousSystem(a, e, Xs) @@ -330,7 +330,7 @@ end @test mapping(s) == [p] for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) && !isparametric(s) end @test TypedPolynomials.nvariables(s) == 2 @@ -357,7 +357,7 @@ end @test mapping(s) == [p] for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) && !isparametric(s) end @test TypedPolynomials.nvariables(s) == 2 @@ -390,7 +390,7 @@ end for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && !ispolynomial(s) && isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) && !isparametric(s) end end @@ -415,7 +415,7 @@ end @test stateset(s) == H for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && !ispolynomial(s) && isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) && !isparametric(s) end end @@ -441,7 +441,7 @@ end @test mapping(s) == vanderpol_controlled! for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && !ispolynomial(s) && isblackbox(s) - @test !isnoisy(s) && iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && iscontrolled(s) && !isconstrained(s) && !isparametric(s) end end @@ -467,7 +467,7 @@ end @test dx ≈ [0.0, -1.0 + u[1]] for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && !ispolynomial(s) && isblackbox(s) - @test !isnoisy(s) && iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && iscontrolled(s) && isconstrained(s) && !isparametric(s) end end @@ -489,7 +489,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test isnoisy(s) && !iscontrolled(s) && !isconstrained(s) + @test isnoisy(s) && !iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = NoisyLinearContinuousSystem(a, d) @@ -510,7 +510,7 @@ end @test noiseset(s) == W for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test isnoisy(s) && !iscontrolled(s) && isconstrained(s) + @test isnoisy(s) && !iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = NoisyConstrainedLinearContinuousSystem(a, d, Xs, Ws) @@ -531,7 +531,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test isnoisy(s) && iscontrolled(s) && !isconstrained(s) + @test isnoisy(s) && iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = NoisyLinearControlContinuousSystem(a, b, d) @@ -552,7 +552,7 @@ end @test noiseset(s) == W for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test isnoisy(s) && iscontrolled(s) && isconstrained(s) + @test isnoisy(s) && iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = NoisyConstrainedLinearControlContinuousSystem(a, b, d, Xs, Us, Ws) @@ -573,7 +573,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test isaffine(s) && !islinear(s) && !ispolynomial(s) && !isblackbox(s) - @test isnoisy(s) && iscontrolled(s) && !isconstrained(s) + @test isnoisy(s) && iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = NoisyAffineControlContinuousSystem(a, b, c, d) @@ -594,7 +594,7 @@ end @test noiseset(s) == W for s in [s, typeof(s)] @test isaffine(s) && !islinear(s) && !ispolynomial(s) && !isblackbox(s) - @test isnoisy(s) && iscontrolled(s) && isconstrained(s) + @test isnoisy(s) && iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = NoisyConstrainedAffineControlContinuousSystem(a, b, c, d, Xs, Us, Ws) @@ -617,7 +617,7 @@ end @test mapping(s) == add_one for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && !ispolynomial(s) && isblackbox(s) - @test isnoisy(s) && iscontrolled(s) && !isconstrained(s) + @test isnoisy(s) && iscontrolled(s) && !isconstrained(s) && !isparametric(s) end end @@ -636,7 +636,7 @@ end @test noiseset(s) == W for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && !ispolynomial(s) && isblackbox(s) - @test isnoisy(s) && iscontrolled(s) && isconstrained(s) + @test isnoisy(s) && iscontrolled(s) && isconstrained(s) && !isparametric(s) end end @@ -664,6 +664,7 @@ end @test !isnoisy(s) @test !iscontrolled(s) @test !isconstrained(s) + @test !isparametric(s) s = SecondOrderLinearContinuousSystem(2, 3, 4) @test mass_matrix(s) == hcat(2) @@ -682,6 +683,7 @@ end @test !isnoisy(s) @test !iscontrolled(s) @test !isconstrained(s) + @test !isparametric(s) s = SecondOrderAffineContinuousSystem(2, 3, 4, 6) @test mass_matrix(s) == hcat(2) @@ -702,6 +704,7 @@ end @test !isnoisy(s) @test iscontrolled(s) @test isconstrained(s) + @test !isparametric(s) s = SecondOrderConstrainedLinearControlContinuousSystem(2, 3, 4, 5, X1, U1) @test mass_matrix(s) == hcat(2) @@ -724,6 +727,7 @@ end @test !isnoisy(s) @test iscontrolled(s) @test isconstrained(s) + @test !isparametric(s) s = SecondOrderConstrainedAffineControlContinuousSystem(2, 3, 4, 5, 6, X1, U1) @test mass_matrix(s) == hcat(2) @@ -751,6 +755,7 @@ end @test !isnoisy(s) @test !iscontrolled(s) @test !isconstrained(s) + @test !isparametric(s) s = SecondOrderContinuousSystem(2, 3, fi, fe) @test mass_matrix(s) == hcat(2) @@ -773,6 +778,7 @@ end @test !isnoisy(s) @test !iscontrolled(s) @test isconstrained(s) + @test !isparametric(s) s = SecondOrderConstrainedContinuousSystem(2, 3, fi, fe, X, U) @test mass_matrix(s) == hcat(2) @@ -780,3 +786,58 @@ end @test stateset(s) === X && inputset(s) === U @test s.fi == fi && s.fe == fe end + +# ================== +# Parametric systems +# ================== + +@testset "Linear parametric continuous systems" begin + @static if isdefined(@__MODULE__, :LazySets) + + Ac = [1.0 0.0; 0.0 1.0] + A1 = [0.1 0.0; 0.0 0.0] + A2 = [0.0 0.0; 0.0 0.2] + A = MatrixZonotope(Ac, [A1, A2]) + + s = LinearParametricContinuousSystem(A) + @test isa(s, LinearParametricContinuousSystem) + + # shortcut constructor + s = LinearContinuousSystem(A) + @test isa(s, LinearParametricContinuousSystem) + + @test statedim(s) == 2 + @test inputdim(s) == 0 + @test noisedim(s) == 0 + @test state_matrix(s) === A + @test islinear(s) + @test isparametric(s) + @test !isaffine(s) + @test !isnoisy(s) + @test !iscontrolled(s) + @test !isconstrained(s) + + # control case + Bc = hcat([1.0; 0.5]) + B1 = hcat([0.05; 0.0]) + B = MatrixZonotope(Bc, [B1]) + + sc = LinearControlParametricContinuousSystem(A, B) + @test isa(sc, LinearControlParametricContinuousSystem) + # shortcut constructor for control + sc = LinearControlContinuousSystem(A, B) + @test isa(sc, LinearControlParametricContinuousSystem) + + @test statedim(sc) == 2 + @test inputdim(sc) == size(B, 2) + @test noisedim(sc) == 0 + @test state_matrix(sc) === A + @test input_matrix(sc) === B + @test islinear(sc) + @test isparametric(sc) + @test isaffine(sc) + @test iscontrolled(sc) + @test !isnoisy(sc) + @test !isconstrained(sc) + end +end diff --git a/test/discrete.jl b/test/discrete.jl index 9bbc5dc8..24dd12fa 100644 --- a/test/discrete.jl +++ b/test/discrete.jl @@ -1,3 +1,5 @@ +using LazySets: MatrixZonotope + # linear systems E = [0.0 1; 1 0] A = [1.0 1; 1 -1] @@ -53,7 +55,7 @@ Es = [e][:, :]; @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) && !isparametric(s) end end @@ -71,7 +73,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) && !isparametric(s) end end @@ -89,7 +91,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = LinearDiscreteSystem(a) @@ -110,7 +112,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test !islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = AffineDiscreteSystem(a, c) @@ -131,7 +133,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = LinearControlDiscreteSystem(a, b) @@ -152,7 +154,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = ConstrainedLinearDiscreteSystem(a, Xs) @@ -173,7 +175,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test !islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = ConstrainedAffineDiscreteSystem(a, c, Xs) @@ -194,7 +196,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = ConstrainedLinearControlDiscreteSystem(a, b, Xs, Us) @@ -216,7 +218,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = LinearDescriptorDiscreteSystem(a, e) @@ -238,7 +240,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = ConstrainedLinearDescriptorDiscreteSystem(a, e, Xs) @@ -260,7 +262,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) && !isparametric(s) end end @@ -279,7 +281,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && ispolynomial(s) && !isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && isconstrained(s) && !isparametric(s) end end @@ -298,7 +300,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && !ispolynomial(s) && isblackbox(s) - @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && !iscontrolled(s) && !isconstrained(s) && !isparametric(s) end end @@ -317,7 +319,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && !ispolynomial(s) && isblackbox(s) - @test !isnoisy(s) && iscontrolled(s) && !isconstrained(s) + @test !isnoisy(s) && iscontrolled(s) && !isconstrained(s) && !isparametric(s) end end @@ -339,7 +341,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test isnoisy(s) && !iscontrolled(s) && !isconstrained(s) + @test isnoisy(s) && !iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = NoisyLinearDiscreteSystem(a, d) @@ -360,7 +362,7 @@ end @test noiseset(s) == W for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test isnoisy(s) && !iscontrolled(s) && isconstrained(s) + @test isnoisy(s) && !iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = NoisyConstrainedLinearDiscreteSystem(a, d, Xs, Ws) @@ -381,7 +383,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test isnoisy(s) && iscontrolled(s) && !isconstrained(s) + @test isnoisy(s) && iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = NoisyLinearControlDiscreteSystem(a, b, d) @@ -402,7 +404,7 @@ end @test noiseset(s) == W for s in [s, typeof(s)] @test islinear(s) && isaffine(s) && !ispolynomial(s) && !isblackbox(s) - @test isnoisy(s) && iscontrolled(s) && isconstrained(s) + @test isnoisy(s) && iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = NoisyConstrainedLinearControlDiscreteSystem(a, b, d, Xs, Us, Ws) @@ -423,7 +425,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test isaffine(s) && !islinear(s) && !ispolynomial(s) && !isblackbox(s) - @test isnoisy(s) && iscontrolled(s) && !isconstrained(s) + @test isnoisy(s) && iscontrolled(s) && !isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = NoisyAffineControlDiscreteSystem(a, b, c, d) @@ -444,7 +446,7 @@ end @test noiseset(s) == W for s in [s, typeof(s)] @test isaffine(s) && !islinear(s) && !ispolynomial(s) && !isblackbox(s) - @test isnoisy(s) && iscontrolled(s) && isconstrained(s) + @test isnoisy(s) && iscontrolled(s) && isconstrained(s) && !isparametric(s) end # Scalar System scalar_sys = NoisyConstrainedAffineControlDiscreteSystem(a, b, c, d, Xs, Us, Ws) @@ -466,7 +468,7 @@ end @test isnothing(noiseset(s)) for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && !ispolynomial(s) && isblackbox(s) - @test isnoisy(s) && iscontrolled(s) && !isconstrained(s) + @test isnoisy(s) && iscontrolled(s) && !isconstrained(s) && !isparametric(s) end end @@ -485,7 +487,7 @@ end @test noiseset(s) == W for s in [s, typeof(s)] @test !islinear(s) && !isaffine(s) && !ispolynomial(s) && isblackbox(s) - @test isnoisy(s) && iscontrolled(s) && isconstrained(s) + @test isnoisy(s) && iscontrolled(s) && isconstrained(s) && !isparametric(s) end end @@ -509,3 +511,55 @@ end @test ui isa Hyperrectangle end end + +# ================== +# Parametric systems +# ================== + +@testset "Linear parametric discrete systems" begin + @static if isdefined(@__MODULE__, :LazySets) + Ac = [1.0 0.0; 0.0 1.0] + A1 = [0.1 0.0; 0.0 0.0] + A2 = [0.0 0.0; 0.0 0.2] + A = MatrixZonotope(Ac, [A1, A2]) + + s = LinearParametricDiscreteSystem(A) + @test isa(s, LinearParametricDiscreteSystem) + # shortcut constructor + s = LinearDiscreteSystem(A) + @test isa(s, LinearParametricDiscreteSystem) + + @test statedim(s) == 2 + @test inputdim(s) == 0 + @test noisedim(s) == 0 + @test state_matrix(s) === A + @test islinear(s) + @test isparametric(s) + @test !isaffine(s) + @test !isnoisy(s) + @test !iscontrolled(s) + @test !isconstrained(s) + + Bc = hcat([1.0; 0.5]) + B1 = hcat([0.05; 0.0]) + B = MatrixZonotope(Bc, [B1]) + + sc = LinearControlParametricDiscreteSystem(A, B) + @test isa(sc, LinearControlParametricDiscreteSystem) + # shortcut constructor + sc = LinearControlDiscreteSystem(A, B) + @test isa(sc, LinearControlParametricDiscreteSystem) + + @test statedim(sc) == 2 + @test inputdim(sc) == size(B, 2) + @test noisedim(sc) == 0 + @test state_matrix(sc) === A + @test input_matrix(sc) === B + @test islinear(sc) + @test isparametric(sc) + @test isaffine(sc) + @test iscontrolled(sc) + @test !isnoisy(sc) + @test !isconstrained(sc) + end +end diff --git a/test/discretize.jl b/test/discretize.jl index e2a80ba3..4d522f62 100644 --- a/test/discretize.jl +++ b/test/discretize.jl @@ -1,15 +1,19 @@ @testset "Convert continuous to discrete type" begin for dtype in subtypes(AbstractDiscreteSystem) - ctype = eval.(Meta.parse.(replace(string(dtype), "Discrete" => "Continuous"))) - @test MathematicalSystems._complementary_type(dtype) == ctype - @inferred MathematicalSystems._complementary_type(dtype) + if dtype ∉ PARAMETRIC_DTYPES + ctype = eval.(Meta.parse.(replace(string(dtype), "Discrete" => "Continuous"))) + @test MathematicalSystems._complementary_type(dtype) == ctype + @inferred MathematicalSystems._complementary_type(dtype) + end end for ctype in subtypes(AbstractContinuousSystem) - dtype = eval.(Meta.parse.(replace(string(ctype), "Continuous" => "Discrete"))) - @test MathematicalSystems._complementary_type(ctype) == dtype - @inferred MathematicalSystems._complementary_type(ctype) + if ctype ∉ PARAMETRIC_CTYPES + dtype = eval.(Meta.parse.(replace(string(ctype), "Continuous" => "Discrete"))) + @test MathematicalSystems._complementary_type(ctype) == dtype + @inferred MathematicalSystems._complementary_type(ctype) + end end end @@ -38,7 +42,7 @@ end !occursin("Descriptor", string(x)), subtypes(AbstractContinuousSystem)) # this test doesn't apply for second order systems - filter!(x -> x ∉ SECOND_ORDER_CTYPES, CTYPES) + filter!(x -> x ∉ SECOND_ORDER_CTYPES && x ∉ PARAMETRIC_CTYPES, CTYPES) DTYPES = MathematicalSystems._complementary_type.(CTYPES) n_types = length(CTYPES) @@ -78,8 +82,8 @@ end CTYPES = filter(x -> (occursin("Linear", string(x)) || occursin("Affine", string(x))) && !occursin("Descriptor", string(x)), subtypes(AbstractContinuousSystem)) - # this test doesn't apply for second order systems - filter!(x -> x ∉ SECOND_ORDER_CTYPES, CTYPES) + # this test doesn't apply for second order systems and parametric systems + filter!(x -> x ∉ SECOND_ORDER_CTYPES && x ∉ PARAMETRIC_CTYPES, CTYPES) DTYPES = MathematicalSystems._complementary_type.(CTYPES) n_types = length(CTYPES) diff --git a/test/runtests.jl b/test/runtests.jl index 8f5ac25b..968ff7c1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -11,6 +11,13 @@ SECOND_ORDER_CTYPES = [SecondOrderAffineContinuousSystem, SecondOrderConstrainedLinearControlContinuousSystem, SecondOrderLinearContinuousSystem] +PARAMETRIC_CTYPES = [LinearParametricContinuousSystem, + LinearControlParametricContinuousSystem] + + +PARAMETRIC_DTYPES = [LinearParametricDiscreteSystem, + LinearControlParametricDiscreteSystem] + @testset "Utilities" begin include("utilities.jl") end From 466991e32035d4086509b54dc0a5bc2f49c5c800 Mon Sep 17 00:00:00 2001 From: alecarraro Date: Tue, 19 Aug 2025 12:05:54 +0200 Subject: [PATCH 3/6] fix indentation and tests --- src/systems.jl | 75 ++++++++++++++++++++++++++++++++-------------- test/@system.jl | 4 ++- test/continuous.jl | 2 +- test/discrete.jl | 2 +- 4 files changed, 57 insertions(+), 26 deletions(-) diff --git a/src/systems.jl b/src/systems.jl index c2cb5e02..56bee38a 100644 --- a/src/systems.jl +++ b/src/systems.jl @@ -42,6 +42,7 @@ for (Z, AZ) in ((:ContinuousIdentitySystem, :AbstractContinuousSystem), end function isparametric(::$T) return false + end end end end @@ -348,7 +349,8 @@ for (Z, AZ) in ((:LinearControlContinuousSystem, :AbstractContinuousSystem), struct $(Z){T,MTA<:AbstractMatrix{T},MTB<:AbstractMatrix{T}} <: $(AZ) A::MTA B::MTB - function $(Z)(A::MTA, B::MTB) where {T,MTA<:AbstractMatrix{T},MTB<:AbstractMatrix{T}} + function $(Z)(A::MTA, + B::MTB) where {T,MTA<:AbstractMatrix{T},MTB<:AbstractMatrix{T}} if checksquare(A) != size(B, 1) throw(DimensionMismatch("incompatible dimensions")) end @@ -635,7 +637,8 @@ ConstrainedAffineDiscreteSystem for (Z, AZ) in ((:AffineControlContinuousSystem, :AbstractContinuousSystem), (:AffineControlDiscreteSystem, :AbstractDiscreteSystem)) @eval begin - struct $(Z){T,MTA<:AbstractMatrix{T},MTB<:AbstractMatrix{T},VT<:AbstractVector{T}} <: $(AZ) + struct $(Z){T,MTA<:AbstractMatrix{T},MTB<:AbstractMatrix{T},VT<:AbstractVector{T}} <: + $(AZ) A::MTA B::MTB c::VT @@ -738,7 +741,8 @@ AffineControlDiscreteSystem for (Z, AZ) in ((:ConstrainedAffineControlContinuousSystem, :AbstractContinuousSystem), (:ConstrainedAffineControlDiscreteSystem, :AbstractDiscreteSystem)) @eval begin - struct $(Z){T,MTA<:AbstractMatrix{T},MTB<:AbstractMatrix{T},VT<:AbstractVector{T},ST,UT} <: + struct $(Z){T,MTA<:AbstractMatrix{T},MTB<:AbstractMatrix{T},VT<:AbstractVector{T},ST, + UT} <: $(AZ) A::MTA B::MTB @@ -964,7 +968,8 @@ for (Z, AZ) in ((:LinearDescriptorContinuousSystem, :AbstractContinuousSystem), struct $(Z){T,MTA<:AbstractMatrix{T},MTE<:AbstractMatrix{T}} <: $(AZ) A::MTA E::MTE - function $(Z)(A::MTA, E::MTE) where {T,MTA<:AbstractMatrix{T},MTE<:AbstractMatrix{T}} + function $(Z)(A::MTA, + E::MTE) where {T,MTA<:AbstractMatrix{T},MTE<:AbstractMatrix{T}} if size(A) != size(E) throw(DimensionMismatch("incompatible dimensions")) end @@ -1255,7 +1260,8 @@ for (Z, AZ) in ((:ConstrainedPolynomialContinuousSystem, :AbstractContinuousSyst statedim::Int X::ST function $(Z)(p::VPT, statedim::Int, - X::ST) where {T,PT<:AbstractPolynomialLike{T},VPT<:AbstractVector{PT},ST} + X::ST) where {T,PT<:AbstractPolynomialLike{T},VPT<:AbstractVector{PT}, + ST} if statedim != MultivariatePolynomials.nvariables(p) throw(DimensionMismatch("the state dimension $(statedim) does not match the number of state variables")) end @@ -1716,7 +1722,8 @@ for (Z, AZ) in ((:NoisyLinearContinuousSystem, :AbstractContinuousSystem), struct $(Z){T,MTA<:AbstractMatrix{T},MTD<:AbstractMatrix{T}} <: $(AZ) A::MTA D::MTD - function $(Z)(A::MTA, D::MTD) where {T,MTA<:AbstractMatrix{T},MTD<:AbstractMatrix{T}} + function $(Z)(A::MTA, + D::MTD) where {T,MTA<:AbstractMatrix{T},MTD<:AbstractMatrix{T}} if checksquare(A) != size(D, 1) throw(DimensionMismatch("incompatible dimensions")) end @@ -1916,7 +1923,8 @@ NoisyConstrainedLinearDiscreteSystem for (Z, AZ) in ((:NoisyLinearControlContinuousSystem, :AbstractContinuousSystem), (:NoisyLinearControlDiscreteSystem, :AbstractDiscreteSystem)) @eval begin - struct $(Z){T,MTA<:AbstractMatrix{T},MTB<:AbstractMatrix{T},MTD<:AbstractMatrix{T}} <: $(AZ) + struct $(Z){T,MTA<:AbstractMatrix{T},MTB<:AbstractMatrix{T},MTD<:AbstractMatrix{T}} <: + $(AZ) A::MTA B::MTB D::MTD @@ -2021,7 +2029,8 @@ NoisyLinearControlDiscreteSystem for (Z, AZ) in ((:NoisyConstrainedLinearControlContinuousSystem, :AbstractContinuousSystem), (:NoisyConstrainedLinearControlDiscreteSystem, :AbstractDiscreteSystem)) @eval begin - struct $(Z){T,MTA<:AbstractMatrix{T},MTB<:AbstractMatrix{T},MTD<:AbstractMatrix{T},ST,UT, + struct $(Z){T,MTA<:AbstractMatrix{T},MTB<:AbstractMatrix{T},MTD<:AbstractMatrix{T},ST, + UT, WT} <: $(AZ) A::MTA B::MTB @@ -2837,8 +2846,9 @@ Discrete-time second order constrained linear control system of the form: """ SecondOrderConstrainedLinearControlDiscreteSystem -for (Z, AZ) in ((:SecondOrderConstrainedLinearControlContinuousSystem, :AbstractContinuousSystem), - (:SecondOrderConstrainedLinearControlDiscreteSystem, :AbstractDiscreteSystem)) +for (Z, AZ) in + ((:SecondOrderConstrainedLinearControlContinuousSystem, :AbstractContinuousSystem), + (:SecondOrderConstrainedLinearControlDiscreteSystem, :AbstractDiscreteSystem)) @eval begin struct $(Z){T,MTM<:AbstractMatrix{T}, MTC<:AbstractMatrix{T}, @@ -2969,8 +2979,9 @@ Discrete-time second order constrained affine control system of the form: """ SecondOrderConstrainedAffineControlDiscreteSystem -for (Z, AZ) in ((:SecondOrderConstrainedAffineControlContinuousSystem, :AbstractContinuousSystem), - (:SecondOrderConstrainedAffineControlDiscreteSystem, :AbstractDiscreteSystem)) +for (Z, AZ) in + ((:SecondOrderConstrainedAffineControlContinuousSystem, :AbstractContinuousSystem), + (:SecondOrderConstrainedAffineControlDiscreteSystem, :AbstractDiscreteSystem)) @eval begin struct $(Z){T,MTM<:AbstractMatrix{T}, MTC<:AbstractMatrix{T}, @@ -2994,7 +3005,8 @@ for (Z, AZ) in ((:SecondOrderConstrainedAffineControlContinuousSystem, :Abstract VT<:AbstractVector{T}, ST, UT} - if !(checksquare(M) == checksquare(C) == checksquare(K) == size(B, 1) == length(d)) + if !(checksquare(M) == checksquare(C) == checksquare(K) == size(B, 1) == + length(d)) throw(DimensionMismatch("incompatible dimensions")) end return new{T,MTM,MTC,MTK,MTB,VT,ST,UT}(M, C, K, B, d, X, U) @@ -3228,7 +3240,8 @@ for (Z, AZ) in ((:SecondOrderConstrainedContinuousSystem, :AbstractContinuousSys U::UT function $(Z)(M::MTM, C::MTC, fi::FI, fe::FE, X::ST, - U::UT) where {T,MTM<:AbstractMatrix{T},MTC<:AbstractMatrix{T},FI,FE,ST,UT} + U::UT) where {T,MTM<:AbstractMatrix{T},MTC<:AbstractMatrix{T},FI,FE, + ST,UT} if checksquare(M) != checksquare(C) throw(DimensionMismatch("incompatible dimensions")) end @@ -3277,6 +3290,7 @@ for (Z, AZ) in ((:SecondOrderConstrainedContinuousSystem, :AbstractContinuousSys end function isconstrained(::$T) return true + end function isparametric(::$T) return false end @@ -3292,7 +3306,7 @@ function __init__() LinearParametricDiscreteSystem, LinearControlParametricContinuousSystem, LinearControlParametricDiscreteSystem - + @doc """ LinearParametricContinuousSystem @@ -3329,7 +3343,7 @@ function __init__() BaseName = Symbol(replace(string(Z), "Parametric" => "")) @eval begin - struct $(Z){T, MA<:MatrixZonotope{T}} <: $(AZ) + struct $(Z){T,MA<:MatrixZonotope{T}} <: $(AZ) A::MA end @@ -3347,23 +3361,29 @@ function __init__() @eval begin function islinear(::$T) return true + end function isaffine(::$T) - return false + return true + end function ispolynomial(::$T) return false + end function isnoisy(::$T) return false + end function iscontrolled(::$T) return false + end function isconstrained(::$T) return false + end function isparametric(::$T) return true + end end end end - @doc """ LinearControlParametricContinuousSystem @@ -3406,14 +3426,16 @@ function __init__() BaseName = Symbol(replace(string(Z), "Parametric" => "")) @eval begin - struct $(Z){T, MTA<:MatrixZonotope{T}, MTB<:MatrixZonotope{T}} <: $(AZ) + struct $(Z){T,MTA<:MatrixZonotope{T},MTB<:MatrixZonotope{T}} <: $(AZ) A::MTA B::MTB - function $(Z)(A::MTA, B::MTB) where {T, MTA<:MatrixZonotope{T}, MTB<:MatrixZonotope{T}} + function $(Z)(A::MTA, + B::MTB) where {T,MTA<:MatrixZonotope{T}, + MTB<:MatrixZonotope{T}} if size(A, 1) != size(A, 2) || size(A, 1) != size(B, 1) throw(DimensionMismatch("incompatible dimensions")) end - return new{T, MTA, MTB}(A, B) + return new{T,MTA,MTB}(A, B) end end @@ -3436,20 +3458,27 @@ function __init__() @eval begin function islinear(::$T) return true + end function isaffine(::$T) - return false + return true + end function ispolynomial(::$T) return false + end function isnoisy(::$T) return false + end function iscontrolled(::$T) return true + end function isconstrained(::$T) return false + end function isparametric(::$T) return true + end end end end end -end +end \ No newline at end of file diff --git a/test/@system.jl b/test/@system.jl index 4225ea6d..7ed991b3 100644 --- a/test/@system.jl +++ b/test/@system.jl @@ -1,7 +1,9 @@ @testset "_corresponding_type" begin for AS in [AbstractContinuousSystem, AbstractDiscreteSystem] for S in subtypes(AS) - @test MathematicalSystems._corresponding_type(AS, fieldnames.(S)) == S + if S ∉ vcat(PARAMETRIC_CTYPES, PARAMETRIC_DTYPES) #TODO refactor _corresponding_type + @test MathematicalSystems._corresponding_type(AS, fieldnames.(S)) == S + end end end end diff --git a/test/continuous.jl b/test/continuous.jl index 260dfbfa..890956c3 100644 --- a/test/continuous.jl +++ b/test/continuous.jl @@ -812,7 +812,7 @@ end @test state_matrix(s) === A @test islinear(s) @test isparametric(s) - @test !isaffine(s) + @test isaffine(s) @test !isnoisy(s) @test !iscontrolled(s) @test !isconstrained(s) diff --git a/test/discrete.jl b/test/discrete.jl index 24dd12fa..951d1b4c 100644 --- a/test/discrete.jl +++ b/test/discrete.jl @@ -535,7 +535,7 @@ end @test state_matrix(s) === A @test islinear(s) @test isparametric(s) - @test !isaffine(s) + @test isaffine(s) @test !isnoisy(s) @test !iscontrolled(s) @test !isconstrained(s) From f9de9ef5b848b73da56bb80b9c9ef9f8fd2ab026 Mon Sep 17 00:00:00 2001 From: alecarraro Date: Wed, 20 Aug 2025 14:53:42 +0200 Subject: [PATCH 4/6] restrict LazySets version to 5.0.0 --- docs/Project.toml | 2 +- test/Project.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index c25c14b6..5330a05c 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -6,4 +6,4 @@ LazySets = "b4f0291d-fe17-52bc-9479-3d1a343d9043" [compat] Documenter = "1" DocumenterCitations = "1.3" -LazySets = "2, 3, 4" +LazySets = "5" diff --git a/test/Project.toml b/test/Project.toml index d162affa..b2981b71 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -10,6 +10,6 @@ TypedPolynomials = "afbbf031-7a57-5f58-a1b9-b774a0fad08d" [compat] Aqua = "0.8.9" -LazySets = "1, 2, 3, 4" +LazySets = "5" RecipesBase = "1" TypedPolynomials = "0.3, 0.4" From 184b3486fc7140ac4d8874d4ba78b46dd6adab82 Mon Sep 17 00:00:00 2001 From: Alessandro Carraro <118743744+alecarraro@users.noreply.github.com> Date: Thu, 21 Aug 2025 13:42:17 +0200 Subject: [PATCH 5/6] Apply suggestions from code review Co-authored-by: Christian Schilling --- test/continuous.jl | 3 ++- test/discrete.jl | 6 +++--- test/discretize.jl | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/test/continuous.jl b/test/continuous.jl index 890956c3..fc9e9c4d 100644 --- a/test/continuous.jl +++ b/test/continuous.jl @@ -793,6 +793,7 @@ end @testset "Linear parametric continuous systems" begin @static if isdefined(@__MODULE__, :LazySets) + using LazySets: MatrixZonotope Ac = [1.0 0.0; 0.0 1.0] A1 = [0.1 0.0; 0.0 0.0] @@ -829,7 +830,7 @@ end @test isa(sc, LinearControlParametricContinuousSystem) @test statedim(sc) == 2 - @test inputdim(sc) == size(B, 2) + @test inputdim(sc) == 1 @test noisedim(sc) == 0 @test state_matrix(sc) === A @test input_matrix(sc) === B diff --git a/test/discrete.jl b/test/discrete.jl index 951d1b4c..27ccdb40 100644 --- a/test/discrete.jl +++ b/test/discrete.jl @@ -1,5 +1,3 @@ -using LazySets: MatrixZonotope - # linear systems E = [0.0 1; 1 0] A = [1.0 1; 1 -1] @@ -518,6 +516,8 @@ end @testset "Linear parametric discrete systems" begin @static if isdefined(@__MODULE__, :LazySets) + using LazySets: MatrixZonotope + Ac = [1.0 0.0; 0.0 1.0] A1 = [0.1 0.0; 0.0 0.0] A2 = [0.0 0.0; 0.0 0.2] @@ -551,7 +551,7 @@ end @test isa(sc, LinearControlParametricDiscreteSystem) @test statedim(sc) == 2 - @test inputdim(sc) == size(B, 2) + @test inputdim(sc) == 1 @test noisedim(sc) == 0 @test state_matrix(sc) === A @test input_matrix(sc) === B diff --git a/test/discretize.jl b/test/discretize.jl index 4d522f62..6973be0c 100644 --- a/test/discretize.jl +++ b/test/discretize.jl @@ -41,7 +41,7 @@ end CTYPES = filter(x -> (occursin("Linear", string(x)) || occursin("Affine", string(x))) && !occursin("Descriptor", string(x)), subtypes(AbstractContinuousSystem)) - # this test doesn't apply for second order systems + # this test doesn't apply for second order systems and parametric systems filter!(x -> x ∉ SECOND_ORDER_CTYPES && x ∉ PARAMETRIC_CTYPES, CTYPES) DTYPES = MathematicalSystems._complementary_type.(CTYPES) From c575ff82bd4fc8c382341c771dba4e4e28e55419 Mon Sep 17 00:00:00 2001 From: Alessandro Carraro <118743744+alecarraro@users.noreply.github.com> Date: Thu, 21 Aug 2025 13:45:38 +0200 Subject: [PATCH 6/6] Apply suggestions from code review Co-authored-by: Christian Schilling --- src/systems.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/systems.jl b/src/systems.jl index 56bee38a..60457c1a 100644 --- a/src/systems.jl +++ b/src/systems.jl @@ -3387,7 +3387,7 @@ function __init__() @doc """ LinearControlParametricContinuousSystem - Continuous-time linear parametric system of the form: + Continuous-time linear parametric control system of the form: ```math x(t)' = A(θ) x(t) + B(θ) u(t), \\theta ∈ \\Theta \\; \\forall t @@ -3405,7 +3405,7 @@ function __init__() @doc """ LinearControlParametricDiscreteSystem - Discrete-time linear parametric system of the form: + Discrete-time linear parametric control system of the form: ```math x_{k+1} = A(θ) x_k + B(θ) u_k, \\theta ∈ \\Theta \\; \\forall k @@ -3432,7 +3432,7 @@ function __init__() function $(Z)(A::MTA, B::MTB) where {T,MTA<:MatrixZonotope{T}, MTB<:MatrixZonotope{T}} - if size(A, 1) != size(A, 2) || size(A, 1) != size(B, 1) + if checksquare(A) != size(B, 1) throw(DimensionMismatch("incompatible dimensions")) end return new{T,MTA,MTB}(A, B)