@@ -502,4 +502,139 @@ function IntervalArithmetic.Interval(d::δ{C}) where C <: Complex
502502 re = Interval (d. val. re- d. radius, d. val. re+ d. radius)
503503 im = Interval (d. val. im- d. radius, d. val. im+ d. radius)
504504 Complex (re, im)
505- end
505+ end
506+
507+
508+
509+ """
510+ block_structure(Δ)
511+
512+ Take a vector of uncertain elements and return a vector of vectors with the block
513+ structure of perturbation blocks as described expected my μ-tools, i.e.
514+ - `[-N, 0]` denots a repeated real block of size `N`
515+ - `[N, 0]` denots a repeated complex block of size `N`
516+ - `[ny, nu]` denots a full complex block of size `ny × nu`
517+ """
518+ function block_structure (D)
519+ perm = sortperm (D, by= d-> d. name)
520+ D = D[perm]
521+ blocks = Vector{Int}[]
522+ blockstart = 1
523+ for i in 2 : length (D)
524+ if D[i]. name == D[i- 1 ]. name
525+ if blockstart == 0
526+ blockstart = i- 1
527+ end
528+ else
529+ push! (blocks, makeblock (D[blockstart: i- 1 ]))
530+ blockstart = i
531+ end
532+ end
533+ push! (blocks, makeblock (D[blockstart: length (D)]))
534+ blocks, perm
535+ end
536+
537+ function makeblock (d) # TODO : full uncertain block that is not a dynamical system is not supported
538+ N = length (d)
539+ if N > 1 || (N== 1 && d[] isa δ) # Δ = δI -> μ(M) = ρ(M) 8.80
540+ if eltype (d[1 ]) <: Complex
541+ b = [N, 0 ] # complex*I
542+ else
543+ b = [- N, 0 ] # real*I
544+ end
545+ else
546+ b = [size (d[], 1 ), size (d[], 2 )]
547+ end
548+ end
549+
550+
551+ function blocksort (P:: UncertainSS )
552+ blocks, perm = block_structure (P. Δ)
553+ Poutinds = []
554+ Pininds = []
555+ # Build indices into M that corresponds to the Δ blocks and permute those indices with the same permutation as was applied to Δ
556+ for (i, d) in enumerate (P. Δ)
557+ if i == 1
558+ push! (Poutinds, 1 : size (d, 2 ))
559+ push! (Pininds, 1 : size (d, 1 ))
560+ else
561+ push! (Poutinds, (1 : size (d, 2 )) .+ Poutinds[i- 1 ][end ])
562+ push! (Pininds, (1 : size (d, 1 )) .+ Pininds[i- 1 ][end ])
563+ end
564+ end
565+ Poutinds = reduce (vcat, Poutinds[perm])
566+ Pininds = reduce (vcat, Pininds[perm])
567+ M = P. M[Poutinds, Pininds]
568+ blocks, M
569+ end
570+
571+ function getinds (blocks:: Vector{Vector{Int}} , d:: Int )
572+ lengths = [b[2 ] <= 1 ? 1 : b[d] for b in blocks]
573+ endinds = cumsum (lengths)
574+ startinds = [1 ; endinds[1 : end - 1 ] .+ 1 ]
575+ inds = UnitRange .(0 .+ startinds, lengths .+ startinds .- 1 )
576+ end
577+
578+ # function getinds(D::AbstractVector, d::Int)
579+ # lengths = size.(D, d)
580+ # endinds = cumsum(lengths)
581+ # startinds = [1; endinds[1:end-1] .+ 1]
582+ # inds = UnitRange.(0 .+ startinds, lengths .+ startinds .- 1)
583+ # end
584+
585+ # struct BlockDiag{T}
586+ # D::Vector{T}
587+ # rinds::Vector{UnitRange{Int}}
588+ # cinds::Vector{UnitRange{Int}}
589+ # end
590+ # BlockDiag(D::AbstractVector) = BlockDiag(D, getinds(D, 1), getinds(D, 2))
591+
592+ # Base.size(B::BlockDiag) = (B.rinds[end][end], B.cinds[end][end])
593+
594+ # function Base.:*(A, B::BlockDiag)
595+ # rinds = B.rinds
596+ # submats = map(enumerate(rinds)) do (i,inds)
597+ # A[:, inds] * B.D[i]
598+ # end
599+ # reduce(hcat, submats)
600+ # end
601+
602+ # function quadform_minus(Q::BlockDiag, M, b, op)
603+ # # con = M'Q*M - b^2*Q ⪯ I(n)
604+ # rinds = Q.rinds
605+ # cinds = Q.cinds
606+ # map(eachindex(rinds)) do i
607+ # r = rinds[i]
608+ # c = cinds[i]
609+ # q = Q.D[i]
610+ # op(M[r,:]'q*M[c,:] .- b^2*q, I(size(M,2)))
611+ # end
612+ # end
613+
614+
615+
616+ #=
617+ D_from_Delta: I-full, full-I, diag-diag
618+ Version that constructs from initial guess
619+ =#
620+
621+
622+ # See Skogestad 8.8.3
623+ # for complex δ:
624+ # Δ = δI -> μ(M) = ρ(M) 8.80
625+ # Full block complex -> μ(M) = σ̄(M) = opnorm(M)
626+ # In general ρ(M) <= μ(M) <= σ̄(M)
627+
628+ # function make_D(blocks)
629+ # D = []
630+ # for b in blocks
631+ # if b[2] == 0
632+ # n = abs(b[1])
633+ # T = b[1] > 0 ? ComplexF64 : Float64
634+ # push!(D, zeros(T, n, n))
635+ # else
636+ # push!(D, 0*I)
637+ # end
638+ # end
639+ # BlockDiagonal(D)
640+ # end
0 commit comments