Eu tenho escrito uma caixa de ferramentas do sistema de controle a partir do zero e puramente em Python3 (plug descarado:) harold
. Nas minhas pesquisas anteriores, sempre tenho reclamações sobre o solucionador de Riccati care.m
por motivos técnicos / irrelevantes.
Por isso, tenho escrito meu próprio conjunto de rotinas. Uma coisa que não consigo encontrar é uma maneira de obter um algoritmo de balanceamento de alto desempenho, pelo menos tão bom quanto balance.m
. Antes de mencionar, a xGEBAL
família é exposta no Scipy e você pode basicamente ligar do Scipy da seguinte maneira, suponha que você tenha uma matriz 2D do tipo float A
:
import scipy as sp
gebal = sp.linalg.get_lapack_funcs(('gebal'),(A,)) # this picks up DGEBAL
Ab, lo, hi, scaling , info = gebal(A, scale=1 , permute=1 , overwrite_a=0 )
Agora, se eu usar a seguinte matriz de teste
array([[ 6. , 0. , 0. , 0. , 0.000002],
[ 0. , 8. , 0. , 0. , 0. ],
[ 2. , 2. , 6. , 0. , 0. ],
[ 2. , 2. , 0. , 8. , 0. ],
[ 0. , 0. , 0.000002, 0. , 2. ]])
eu recebo
array([[ 8. , 0. , 0. , 2. , 2. ],
[ 0. , 2. , 0.000002, 0. , 0. ],
[ 0. , 0. , 6. , 2. , 2. ],
[ 0. , 0.000002, 0. , 6. , 0. ],
[ 0. , 0. , 0. , 0. , 8. ]])
No entanto, se eu passar isso para balance.m
, recebo
>> balance(A)
ans =
8.0000 0 0 0.0625 2.0000
0 2.0000 0.0001 0 0
0 0 6.0000 0.0002 0.0078
0 0.0003 0 6.0000 0
0 0 0 0 8.0000
Se você verificar os padrões de permutação, eles são os mesmos, porém a escala está desativada. gebal
dá escaladas unidade enquanto Matlab dá as seguintes potências de 2: [-5,0,8,0,2]
.
Então, aparentemente, eles não estão usando a mesma maquinaria. Eu tentei várias opções, como Lemonnier, Van Dooren, escala de dois lados, Parlett-Reinsch original e também alguns outros métodos menos conhecidos na literatura, como a versão densa SPBALANCE
.
Um ponto que talvez eu deva enfatizar é que estou ciente do trabalho de Benner; em particular o balanceamento simplético das matrizes hamiltonianas especificamente para esse fim. No entanto, observe que esse tipo de tratamento é feito dentro gcare.m
(solucionador de Riccati generalizado) e o equilíbrio é feito diretamente via balance.m
. Por isso, eu apreciaria se alguém pudesse me indicar a implementação real.
Divulgação: Eu realmente não estou tentando fazer engenharia reversa do código do mathworks: eu realmente quero me afastar dele devido a várias razões, incluindo a motivação desta pergunta, ou seja, eu não sei o que está fazendo, o que me custou muito de tempo no dia. Minha intenção é obter um algoritmo de balanceamento satisfatório que me permita passar exemplos CAREX para que eu possa implementar métodos de iteração de Newton sobre o solucionador regular.
fonte