-
Notifications
You must be signed in to change notification settings - Fork 89
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
minreal
works -- but gives "wrong" result
#835
Comments
I would encourage you to open this issue in MatrixPencils.jl where minreal is implemented. |
OK -- I can do that. (In MatrixPencils, the tolerance |
I have opened the issue in MatrixPencils.jl. |
You have two pole-zero cancellations in the origin and one in -7.27070, so it makes sense that minreal removes three state variables julia> poles(linsys)
6-element Vector{ComplexF64}:
-7.270709095526688 + 0.0im
-6.683187769600364 + 0.0im
-0.5184873504279723 + 0.9245137064074253im
-0.5184873504279723 - 0.9245137064074253im
1.7969420165981442e-17 + 0.0im
4.638847626343683e-16 + 0.0im
julia> tzeros(linsys)
3-element Vector{Float64}:
3.0660800180583606e-16
-7.270709095526687
-1.4243805976205752e-16 minreal does not really care about the physics, only the input-output mapping of the linear operator and this mapping is subject to the pole-zero cancellations This is our implementation of function minreal(sys::T, tol=nothing; fast=false, atol=0.0, kwargs...) where T <: AbstractStateSpace
A,B,C,D = ssdata(sys)
if tol !== nothing
atol == 0 || atol == tol || error("Both positional argument `tol` and keyword argument `atol` were set but were not equal. `tol` is provided for backwards compat and can not be set to another value than `atol`.")
atol = tol
end
Ar, Br, Cr = MatrixPencils.lsminreal(A,B,C; atol, fast, kwargs...)
basetype(T)(Ar,Br,Cr,D, ntuple(i->getfield(sys, i+4), fieldcount(T)-4)...)
end |
Hm... OK -- but the bode plots before and after minimal realization are very different. |
I think that's because your system is very poorly balanced, if you perform balancing, you notice that the reduced-order system has the same frequency response using ControlSystemsBase, Plots
A = [-6.537773175952662 0.0 0.0 0.0 -9.892378564622923e-9 0.0; 0.0 -6.537773175952662 0.0 0.0 0.0 -9.892378564622923e-9; 2.0163803998106024e8 2.0163803998106024e8 -0.006223894167415392 -1.551620418759878e8 0.002358202548321148 0.002358202548321148; 0.0 0.0 5.063545034365582e-9 -0.4479539754649166 0.0 0.0; -2.824060629317756e8 2.0198389074625736e8 -0.006234569427701143 -1.5542817673286995e8 -0.7305736722226711 0.0023622473513548576; 2.0198389074625736e8 -2.824060629317756e8 -0.006234569427701143 -1.5542817673286995e8 0.0023622473513548576 -0.7305736722226711]
B = [0.004019511633336128; 0.004019511633336128; 0.0; 0.0; 297809.51426114445; 297809.51426114445]
C = [0.0 0.0 0.0 1.0 0.0 0.0]
D = [0.0]
linsys = ss(A,B,C,D)
bsys, T = balance_statespace(linsys)
rsys = minreal(bsys)
w = exp10.(LinRange(-2, 2, 200))
bodeplot(linsys, w)
bodeplot!(bsys, w)
bodeplot!(rsys, w, l=(:dash, )) |
Maybe we should perform balancing by default in the plotting functions? |
If I do not do balancing, the original system has 2 real poles, 2 complex conjugate poles, and 2 stray poles. The original system has 1 real zero and 2 stray zeros. A correct minimal realization should cancel one of the real poles with the real zero, and lead to a minimal realization with 1 real pole and 2 complex conjugate poles. However, |
minreal on the balanced model, like in the example above, does the right thing julia> poles(rsys)
3-element Vector{ComplexF64}:
-6.683187769600371 + 0.0im
-0.5184873504279726 + 0.9245137064074256im
-0.5184873504279726 - 0.9245137064074256im in general, we do not perform automatic balancing everywhere since it's in some situations an expensive operation, and also changes the state representation, instead, we require the user to explicitly opt into the balancing when needed. |
I get an error message when I try to use |
I can't do much without more information, the function is exported so it should work if you have loaded CS or CSBase |
OK. Could it be that I generated the linear system using ControlSystemsMTK and that I'll check. |
The problem is that you have not loaded ControlSystemsBase. ControlSystemsMTK does not contain this functionality |
That is not the problem -- I loaded ControlSystemsBase, but still |
OK -- now it seems to work. Don't know what I did wrong "in the heat of the moment"... |
The problem persists, and I found the problem...
|
|
Hm... still doesn't work properly. I have updated the packages, and this time, function However, doing I know you don't have my # Linearization using ControlSystemsMTK
linsys = named_ss(sys_p, sys_in, sys_out; op=op_0)
# poles
poles(linsys)
6-element Vector{ComplexF64}:
-7.270709095526688 + 0.0im
-6.683187769600364 + 0.0im
-0.5184873504279723 + 0.9245137064074253im
-0.5184873504279723 - 0.9245137064074253im
1.7969420165981442e-17 + 0.0im
4.638847626343683e-16 + 0.0im
# minimal realization (unbalanced) + poles
linsys_m = minreal(linsys)
poles(linsys_m)
3-element Vector{Float64}:
-0.850985115940591
-6.546113999987366
-4.460027611772281
# doing balance_statespace on Named SS
linsys_b = balance_statespace(linsys)[1]
poles(linsys_b)
3-element Vector{Float64}:
-0.850985115940591
-6.546113999987366
-4.460027611772281
# The above shows that doing balance_statespace on
# *Named* statespace does not improve the accuracy
# Instead, build an unnamed SS:
linsys_unm = ss(linsys.A,linsys.B,linsys.C,linsys.D)
poles(linsys_unm)
6-element Vector{ComplexF64}:
-7.270709095526688 + 0.0im
-6.683187769600364 + 0.0im
-0.5184873504279723 + 0.9245137064074253im
-0.5184873504279723 - 0.9245137064074253im
1.7969420165981442e-17 + 0.0im
4.638847626343683e-16 + 0.0im
# Above is the same as original named SS
# Using balance_statespace on unnamed SS + minreal
balance_statespace(linsys_unm)[1] |> minreal |> poles
3-element Vector{ComplexF64}:
-6.683187769600371 + 0.0im
-0.5184873504279726 + 0.9245137064074256im
-0.5184873504279726 - 0.9245137064074256im
# Notice that *this time*, the balancing has an effect
|
The PR I linked above has not been merged yet 😉 |
A new release will be out in a few minutes |
Hm... I still have problems with "named statespace" structures. I'm on Julia v1.9.0, with packages: status `[C:\Users\Bernt\.julia\environments\v1.9\Project.toml](file:///C:/Users/Bernt/.julia/environments/v1.9/Project.toml)`
[a6e380b2] ControlSystems v1.7.2
[aaaaaaaa] ControlSystemsBase v1.4.4
[687d7614] ControlSystemsMTK v0.1.12
[0c46a032] DifferentialEquations v7.7.0
[31c24e10] Distributions v0.25.90
[b964fa9f] LaTeXStrings v1.3.0
[961ee093] ModelingToolkit v8.55.1
[91a5bcdd] Plots v1.38.11 Here is what does and doesn't work:
Perhaps I should send my code. I realize that it is difficult to debug/check when you don't have the named linsys structure available. My code is in a Jupyter notebook in VSCode. I guess you don't like to work with such notebooks. It will take me some effort to ,convert the code into a standard |
I notice that now, the original "named ss" converted to an unnamed ss ( |
Named systems will work after the merge of for the code posted above, and the same result if I additionally do using RobustAndOptimalControl
nss = named_ss(linsys)
bsys, T = balance_statespace(nss)
rsys = minreal(bsys)
w = exp10.(LinRange(-2, 2, 200))
bodeplot(nss, w)
bodeplot!(bsys, w)
bodeplot!(rsys, w, l=(:dash, )) |
Today,
minreal
works on Windows 11/ Julia v1.9. THANKS!The result from
minreal
is, however, "wrong" -- or perhaps extremely sensitive to tolerances...Here is my system eigenvalues -- I insert copyable matrices for the system below:

minreal
function to the system with default tolerances, the system is reduced to a 3 state ODE.rtol
, the system minimal realization has 3 states all the way tortol=1e-16
.rtol=1e-17
, the minimal realization gives 1 statertol
at 1e-18 and smaller, the minimal realization gives 6 statesThe text was updated successfully, but these errors were encountered: