Skip to content

Commit 3a4e7b6

Browse files
authored
add find_similarity_transform (#1000)
* add `find_similarity_transform` this was previously implemented in ControlSystemIdentification * export * fix * up docstring * up docstring
1 parent dbe65e6 commit 3a4e7b6

File tree

4 files changed

+54
-2
lines changed

4 files changed

+54
-2
lines changed

lib/ControlSystemsBase/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name = "ControlSystemsBase"
22
uuid = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"
33
authors = ["Dept. Automatic Control, Lund University"]
44
repo = "https://github.com/JuliaControl/ControlSystems.jl.git"
5-
version = "1.16.1"
5+
version = "1.17.0"
66

77
[deps]
88
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"

lib/ControlSystemsBase/src/ControlSystemsBase.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export LTISystem,
4444
balreal,
4545
baltrunc,
4646
similarity_transform,
47+
find_similarity_transform,
4748
time_scale,
4849
innovation_form,
4950
observer_predictor,

lib/ControlSystemsBase/src/matrix_comps.jl

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ D̃ = D
710710
```
711711
712712
If `unitary=true`, `T` is assumed unitary and the matrix adjoint is used instead of the inverse.
713-
See also [`balance_statespace`](@ref).
713+
See also [`balance_statespace`](@ref), [`find_similarity_transform`](@ref).
714714
"""
715715
function similarity_transform(sys::ST, T; unitary=false) where ST <: AbstractStateSpace
716716
if unitary
@@ -726,6 +726,44 @@ function similarity_transform(sys::ST, T; unitary=false) where ST <: AbstractSta
726726
ST(A,B,C,D,sys.timeevol)
727727
end
728728

729+
"""
730+
find_similarity_transform(sys1, sys2, method = :obsv)
731+
732+
Find T such that `similarity_transform(sys1, T) == sys2`
733+
734+
Ref: Minimal state-space realization in linear system theory: an overview, B. De Schutter
735+
736+
If `method == :obsv`, the observability matrices of `sys1` and `sys2` are used to find `T`, whereas `method == :ctrb` uses the controllability matrices.
737+
738+
```jldoctest
739+
julia> using ControlSystemsBase
740+
741+
julia> T = randn(3,3);
742+
743+
julia> sys1 = ssrand(1,1,3);
744+
745+
julia> sys2 = similarity_transform(sys1, T);
746+
747+
julia> T2 = find_similarity_transform(sys1, sys2);
748+
749+
julia> T2 ≈ T
750+
true
751+
```
752+
"""
753+
function find_similarity_transform(sys1, sys2, method = :obsv)
754+
if method === :obsv
755+
O1 = obsv(sys1)
756+
O2 = obsv(sys2)
757+
return O1\O2
758+
elseif method === :ctrb
759+
C1 = ctrb(sys1)
760+
C2 = ctrb(sys2)
761+
return C1/C2
762+
else
763+
error("Unknown method $method")
764+
end
765+
end
766+
729767
"""
730768
time_scale(sys::AbstractStateSpace{Continuous}, a; balanced = false)
731769
time_scale(G::TransferFunction{Continuous}, a; balanced = true)

lib/ControlSystemsBase/test/test_matrix_comps.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@ sysdb, _ = balance_statespace(sysd)
3939

4040
@test ControlSystemsBase.balance_transform(A,B,C) ControlSystemsBase.balance_transform(sys)
4141

42+
@testset "similarity transform" begin
43+
@info "Testing similarity transform"
44+
T = randn(3,3)
45+
sys1 = ssrand(1,1,3)
46+
sys2 = ControlSystemsBase.similarity_transform(sys1, T)
47+
T2 = find_similarity_transform(sys1, sys2)
48+
@test T2 T atol=1e-8
49+
50+
T3 = find_similarity_transform(sys1, sys2, :ctrb)
51+
@test T3 T atol=1e-8
52+
53+
end
54+
4255
W = [1 0; 0 1]
4356
@test covar(sys, W) [0.002560975609756 0.002439024390244; 0.002439024390244 0.002560975609756]
4457
D2 = [1 0; 0 1]

0 commit comments

Comments
 (0)