Skip to content

Fix affine system corner case #223

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

Merged
merged 6 commits into from
Dec 8, 2020
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
19 changes: 12 additions & 7 deletions src/macros.jl
Original file line number Diff line number Diff line change
Expand Up @@ -280,14 +280,20 @@ function _parse_system(exprs::NTuple{N, Expr}) where {N}
dynamic_equation = stripped
state_var = subject
AT = abstract_system_type
# if the system has the structure x_ = A_*x_ + B_*u_ ,
# handle u_ as input variable
# if the stripped system has the structure x_ = A_*x_ + B_*u_ or
# one of the other patterns, handle u_ as input variable
if @capture(stripped, (x_ = A_*x_ + B_*u_) |
(x_ = x_ + B_*u_) |
(x_ = A_*x_ + B_*u_ + c_) |
(x_ = x_ + B_*u_ + c_) |
(x_ = f_(x_, u_)) )
input_var = u
if (f == :+) || (f == :-) || (f == :*)
# pattern x_ = f_(x_, u_) also catches the cases:
# x_ = x_ + u_, x_ = x_ - u_ and x_ = x_*u_
# where u_ doesn't necessarily need to be the input
else
input_var = u
end
end

elseif @capture(ex, (dim = (f_dims_)) | (dims = (f_dims_)))
Expand Down Expand Up @@ -407,14 +413,13 @@ function extract_dyn_equation_parameters(equation, state, input, noise, dim, AT)
rhs = rhscode
end

# if rhs is a sum, => affine system which is controlled, noisy or both
# if rhs is parsed as addition => affine system which is controlled, noisy or both
if @capture(rhs, A_ + B__)
# parse summands of rhs and add * if needed
summands = add_asterisk.([A, B...], Ref(state), Ref(input), Ref(noise))
push!(rhs_params, extract_sum(summands, state, input, noise)...)

# If rhs is function call => black-box system
elseif @capture(rhs, f_(a__)) && f != :(*) && f != :(-)
# if rhs is a function call except `*` or `-` => black-box system
elseif @capture(rhs, f_(a__)) && f != :(*) && f != :(-)
# the dimension argument needs to be a iterable
(dim == nothing) && throw(ArgumentError("for a blackbox system, the dimension has to be defined"))
dim_vec = [dim...]
Expand Down
4 changes: 3 additions & 1 deletion test/@system.jl
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,9 @@ end
end

@testset "@system for affine continuous systems" begin
@test @system(x' = A*x + c) == AffineContinuousSystem(A, c)
b = [1.0]
@test @system(x' = x + b) == AffineContinuousSystem(I(1), b)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just checked that the vector form doesn't work (i'll open an issue):

julia> b = rand(10); @system(x' = x + b)
ERROR: AssertionError: checksquare(A) == length(c)
Stacktrace:
 [1] AffineContinuousSystem(::IdentityMultiple{Float64}, ::Array{Float64,1}) at /home/mforets/.julia/dev/MathematicalSystems/src/systems.jl:189
 [2] top-level scope at REPL[4]:1

Copy link
Member

@mforets mforets Dec 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please note that in pple the transformation can be done (without manually specifying dim=10), because the code would generate I(n) wheren=length(b).

Copy link
Collaborator Author

@ueliwechsler ueliwechsler Dec 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took me too long to figure out, what you meant by pple 😅
Yes, but from my experience it is a bit akward to get the length from the input vector and return it again in a macro.

@test @system(x' = A*x + c) == AffineContinuousSystem(A, c)
sys = @system(z_1' = A*z_1 + B*v_1 + c1, z_1 ∈ X, v_1 ∈ U1, input:v_1)
@test sys == ConstrainedAffineControlContinuousSystem(A, B, c1, X, U1)
@test_throws ArgumentError @system(x' = Ax + Bu + c) # not a system type
Expand Down