@@ -276,7 +276,7 @@ function tzeros(A::AbstractMatrix, B::AbstractMatrix, C::AbstractMatrix, D::Abst
276
276
tzeros (A2, B2, C2, D2)
277
277
end
278
278
279
- function tzeros (A:: AbstractMatrix{T} , B:: AbstractMatrix{T} , C:: AbstractMatrix{T} , D:: AbstractMatrix{T} ; extra:: Val{E} = Val {false} (), balance= true , kwargs... ) where {T <: BlasFloat , E}
279
+ function tzeros (A:: AbstractMatrix{T} , B:: AbstractMatrix{T} , C:: AbstractMatrix{T} , D:: AbstractMatrix{T} ; extra:: Val{E} = Val {false} (), balance= true , kwargs... ) where {T, E}
280
280
if balance
281
281
A, B, C = balance_statespace (A, B, C)
282
282
end
@@ -289,110 +289,110 @@ function tzeros(A::AbstractMatrix{T}, B::AbstractMatrix{T}, C::AbstractMatrix{T}
289
289
end
290
290
end
291
291
292
- function tzeros (A:: AbstractMatrix{T} , B:: AbstractMatrix{T} , C:: AbstractMatrix{T} , D:: AbstractMatrix{T} ; extra:: Val{E} = Val {false} (), kwargs... ) where {T <: Union{AbstractFloat,Complex{<:AbstractFloat}} , E}
293
- isempty (A) && return complex (T)[]
294
-
295
- # Balance the system
296
- A, B, C = balance_statespace (A, B, C; verbose= false )
297
-
298
- # Compute a good tolerance
299
- meps = 10 * eps (real (T))* norm ([A B; C D])
300
-
301
- # Step 1:
302
- A_r, B_r, C_r, D_r = reduce_sys (A, B, C, D, meps)
303
-
304
- # Step 2: (conjugate transpose should be avoided since single complex zeros get conjugated)
305
- A_rc, B_rc, C_rc, D_rc = reduce_sys (copy (transpose (A_r)), copy (transpose (C_r)), copy (transpose (B_r)), copy (transpose (D_r)), meps)
306
-
307
- # Step 3:
308
- # Compress cols of [C D] to [0 Df]
309
- mat = [C_rc D_rc]
310
- Wr = qr (mat' ). Q * I
311
- W = reverse (Wr, dims= 2 )
312
- mat = mat* W
313
- if fastrank (mat' , meps) > 0
314
- nf = size (A_rc, 1 )
315
- m = size (D_rc, 2 )
316
- Af = ([A_rc B_rc] * W)[1 : nf, 1 : nf]
317
- Bf = ([Matrix {T} (I, nf, nf) zeros (nf, m)] * W)[1 : nf, 1 : nf]
318
- Z = schur (complex .(Af), complex .(Bf)) # Schur instead of eigvals to handle BigFloat
319
- zs = Z. values
320
- ControlSystemsBase. _fix_conjugate_pairs! (zs) # Generalized eigvals does not return exact conj. pairs
321
- else
322
- zs = complex (T)[]
323
- end
324
- return zs
325
- end
326
-
327
- """
328
- reduce_sys(A::AbstractMatrix, B::AbstractMatrix, C::AbstractMatrix, D::AbstractMatrix, meps::AbstractFloat)
329
- Implements REDUCE in the Emami-Naeini & Van Dooren paper. Returns transformed
330
- A, B, C, D matrices. These are empty if there are no zeros.
331
- """
332
- function reduce_sys (A:: AbstractMatrix , B:: AbstractMatrix , C:: AbstractMatrix , D:: AbstractMatrix , meps:: AbstractFloat )
333
- T = promote_type (eltype (A), eltype (B), eltype (C), eltype (D))
334
- Cbar, Dbar = C, D
335
- if isempty (A)
336
- return A, B, C, D
337
- end
338
- while true
339
- # Compress rows of D
340
- U = qr (D). Q
341
- D = U' D
342
- C = U' C
343
- sigma = fastrank (D, meps)
344
- Cbar = C[1 : sigma, :]
345
- Dbar = D[1 : sigma, :]
346
- Ctilde = C[(1 + sigma): end , :]
347
- if sigma == size (D, 1 )
348
- break
349
- end
350
-
351
- # Compress columns of Ctilde
352
- V = reverse (qr (Ctilde' ). Q * I, dims= 2 )
353
- Sj = Ctilde* V
354
- rho = fastrank (Sj' , meps)
355
- nu = size (Sj, 2 ) - rho
356
-
357
- if rho == 0
358
- break
359
- elseif nu == 0
360
- # System has no zeros, return empty matrices
361
- A = B = Cbar = Dbar = Matrix {T} (undef, 0 ,0 )
362
- break
363
- end
364
- # Update System
365
- n, m = size (B)
366
- Vm = [V zeros (T, n, m); zeros (T, m, n) Matrix {T} (I, m, m)] # I(m) is not used for type stability reasons (as of julia v1.7)
367
- if sigma > 0
368
- M = [A B; Cbar Dbar]
369
- Vs = [copy (V' ) zeros (T, n, sigma) ; zeros (T, sigma, n) Matrix {T} (I, sigma, sigma)]
370
- else
371
- M = [A B]
372
- Vs = copy (V' )
373
- end
374
- sigma, rho, nu
375
- M = Vs * M * Vm
376
- A = M[1 : nu, 1 : nu]
377
- B = M[1 : nu, (nu + rho + 1 ): end ]
378
- C = M[(nu + 1 ): end , 1 : nu]
379
- D = M[(nu + 1 ): end , (nu + rho + 1 ): end ]
380
- end
381
- return A, B, Cbar, Dbar
382
- end
383
-
384
- # Determine the number of non-zero rows, with meps as a tolerance. For an
385
- # upper-triangular matrix, this is a good proxy for determining the row-rank.
386
- function fastrank (A:: AbstractMatrix , meps:: Real )
387
- n, m = size (A)
388
- if n* m == 0 return 0 end
389
- norms = Vector {real(eltype(A))} (undef, n)
390
- for i = 1 : n
391
- norms[i] = norm (A[i, :])
392
- end
393
- mrank = sum (norms .> meps)
394
- return mrank
395
- end
292
+ # function tzeros(A::AbstractMatrix{T}, B::AbstractMatrix{T}, C::AbstractMatrix{T}, D::AbstractMatrix{T}; extra::Val{E} = Val{false}(), kwargs...) where {T <: Union{AbstractFloat,Complex{<:AbstractFloat}}, E}
293
+ # isempty(A) && return complex(T)[]
294
+
295
+ # # Balance the system
296
+ # A, B, C = balance_statespace(A, B, C; verbose=false)
297
+
298
+ # # Compute a good tolerance
299
+ # meps = 10*eps(real(T))*norm([A B; C D])
300
+
301
+ # # Step 1:
302
+ # A_r, B_r, C_r, D_r = reduce_sys(A, B, C, D, meps)
303
+
304
+ # # Step 2: (conjugate transpose should be avoided since single complex zeros get conjugated)
305
+ # A_rc, B_rc, C_rc, D_rc = reduce_sys(copy(transpose(A_r)), copy(transpose(C_r)), copy(transpose(B_r)), copy(transpose(D_r)), meps)
306
+
307
+ # # Step 3:
308
+ # # Compress cols of [C D] to [0 Df]
309
+ # mat = [C_rc D_rc]
310
+ # Wr = qr(mat').Q * I
311
+ # W = reverse(Wr, dims=2)
312
+ # mat = mat*W
313
+ # if fastrank(mat', meps) > 0
314
+ # nf = size(A_rc, 1)
315
+ # m = size(D_rc, 2)
316
+ # Af = ([A_rc B_rc] * W)[1:nf, 1:nf]
317
+ # Bf = ([Matrix{T}(I, nf, nf) zeros(nf, m)] * W)[1:nf, 1:nf]
318
+ # Z = schur(complex.(Af), complex.(Bf)) # Schur instead of eigvals to handle BigFloat
319
+ # zs = Z.values
320
+ # ControlSystemsBase._fix_conjugate_pairs!(zs) # Generalized eigvals does not return exact conj. pairs
321
+ # else
322
+ # zs = complex(T)[]
323
+ # end
324
+ # return zs
325
+ # end
326
+
327
+ # """
328
+ # reduce_sys(A::AbstractMatrix, B::AbstractMatrix, C::AbstractMatrix, D::AbstractMatrix, meps::AbstractFloat)
329
+ # Implements REDUCE in the Emami-Naeini & Van Dooren paper. Returns transformed
330
+ # A, B, C, D matrices. These are empty if there are no zeros.
331
+ # """
332
+ # function reduce_sys(A::AbstractMatrix, B::AbstractMatrix, C::AbstractMatrix, D::AbstractMatrix, meps::AbstractFloat)
333
+ # T = promote_type(eltype(A), eltype(B), eltype(C), eltype(D))
334
+ # Cbar, Dbar = C, D
335
+ # if isempty(A)
336
+ # return A, B, C, D
337
+ # end
338
+ # while true
339
+ # # Compress rows of D
340
+ # U = qr(D).Q
341
+ # D = U'D
342
+ # C = U'C
343
+ # sigma = fastrank(D, meps)
344
+ # Cbar = C[1:sigma, :]
345
+ # Dbar = D[1:sigma, :]
346
+ # Ctilde = C[(1 + sigma):end, :]
347
+ # if sigma == size(D, 1)
348
+ # break
349
+ # end
350
+
351
+ # # Compress columns of Ctilde
352
+ # V = reverse(qr(Ctilde').Q * I, dims=2)
353
+ # Sj = Ctilde*V
354
+ # rho = fastrank(Sj', meps)
355
+ # nu = size(Sj, 2) - rho
356
+
357
+ # if rho == 0
358
+ # break
359
+ # elseif nu == 0
360
+ # # System has no zeros, return empty matrices
361
+ # A = B = Cbar = Dbar = Matrix{T}(undef, 0,0)
362
+ # break
363
+ # end
364
+ # # Update System
365
+ # n, m = size(B)
366
+ # Vm = [V zeros(T, n, m); zeros(T, m, n) Matrix{T}(I, m, m)] # I(m) is not used for type stability reasons (as of julia v1.7)
367
+ # if sigma > 0
368
+ # M = [A B; Cbar Dbar]
369
+ # Vs = [copy(V') zeros(T, n, sigma) ; zeros(T, sigma, n) Matrix{T}(I, sigma, sigma)]
370
+ # else
371
+ # M = [A B]
372
+ # Vs = copy(V')
373
+ # end
374
+ # sigma, rho, nu
375
+ # M = Vs * M * Vm
376
+ # A = M[1:nu, 1:nu]
377
+ # B = M[1:nu, (nu + rho + 1):end]
378
+ # C = M[(nu + 1):end, 1:nu]
379
+ # D = M[(nu + 1):end, (nu + rho + 1):end]
380
+ # end
381
+ # return A, B, Cbar, Dbar
382
+ # end
383
+
384
+ # # Determine the number of non-zero rows, with meps as a tolerance. For an
385
+ # # upper-triangular matrix, this is a good proxy for determining the row-rank.
386
+ # function fastrank(A::AbstractMatrix, meps::Real)
387
+ # n, m = size(A)
388
+ # if n*m == 0 return 0 end
389
+ # norms = Vector{real(eltype(A))}(undef, n)
390
+ # for i = 1:n
391
+ # norms[i] = norm(A[i, :])
392
+ # end
393
+ # mrank = sum(norms .> meps)
394
+ # return mrank
395
+ # end
396
396
397
397
"""
398
398
relative_gain_array(G, w::AbstractVector)
0 commit comments