Алгоритм Матрицы Балансировки


9

Я пишу набор инструментов системы управления с нуля и чисто на Python3 (бесстыдный плагин:) harold. Из моих прошлых исследований я всегда жаловался на решатель Riccati care.mпо техническим / неуместным причинам.

Следовательно, я писал свой собственный набор процедур. Одна вещь, которую я не могу найти, это получить высокопроизводительный алгоритм балансировки, по крайней мере, такой же, как и balance.m. Прежде чем упомянуть об этом, xGEBALв Scipy раскрывается семейство, и вы можете в основном позвонить из Scipy следующим образом. Предположим, у вас есть 2D-массив с плавающей точкой 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 )

Теперь, если я использую следующую тестовую матрицу

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.      ]])

я получил

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.      ]])

Однако, если я передам это balance.m, я получу

>> 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

Если вы проверяете шаблоны перестановок, они совпадают, однако масштабирование отключено. gebalдает единство отслоений , тогда как MATLAB дает следующие полномочия 2: [-5,0,8,0,2].

Очевидно, что они не используют один и тот же механизм. Я пробовал различные варианты, такие как Lemonnier, Van Dooren двустороннее масштабирование, оригинальный Parlett-Reinsch, а также некоторые другие менее известные в литературе методы, такие как плотная версия SPBALANCE.

Возможно, я бы хотел подчеркнуть один момент: я знаю о работе Беннера; в частности, симплектическая балансировка гамильтоновых матриц специально для этой цели. Тем не менее, обратите внимание, что этот тип обработки выполняется внутри gcare.m(обобщенный Riccati решатель), а балансировка выполняется напрямую через balance.m. Следовательно, я был бы признателен, если бы кто-то указал мне на фактическую реализацию.


Раскрытие информации: я действительно не пытаюсь перепроектировать математический код: я действительно хочу уйти от него по разным причинам, включая мотивацию этого вопроса, то есть я не знаю, что он делает, что стоило мне много времени назад в тот же день. Мое намерение состоит в том, чтобы получить удовлетворительный алгоритм балансировки, который позволил бы мне передавать примеры CAREX так, чтобы я мог реализовать итерационные методы Ньютона поверх обычного решателя.

Ответы:


7

Мне потребовалось некоторое время, чтобы понять это, и, как обычно, это становится очевидным после того, как вы найдете виновника.

После проверки проблемных случаев сообщили в Дэвид С. Уоткинс. Случай, когда балансировка вредна. Электрон. Сделка Numer. Anal, 23: 1–4, 2006, а также обсуждение здесь (оба цитируются в arXiv: 1401.5766v1 ), оказывается, что Matlab использует балансировку, сначала разделяя диагональные элементы.

Моей первоначальной мыслью было, согласно классической ограниченной документации по функциям LAPACK, GEBAL выполнил это автоматически. Тем не менее, я думаю, что авторы подразумевают, игнорируя диагональные элементы , а не удаляя их из сумм строк / столбцов.

На самом деле, если я вручную удаляю диагональ из массива, то оба результата совпадают, то есть

import scipy as sp
gebal = sp.linalg.get_lapack_funcs(('gebal'),(A,)) # this picks up DGEBAL
Ab, lo, hi, scaling , info = gebal(A - np.diag(np.diag(A)), scale=1 , permute=1 , overwrite_a=0 )  

дает тот же результат, что и balance.m(без диагональных записей, конечно).

Если кто-то из пользователей, владеющих Fortran, может подтвердить это, проверив dgebal.f , я был бы благодарен.

РЕДАКТИРОВАТЬ: Приведенный выше результат не означает, что это единственная разница. Я также построил разные матрицы, в которых GEBAL и balance.m дают разные результаты даже после разделения диагоналей.

Мне довольно любопытно, в чем может быть разница, но, кажется, нет никакого способа узнать, так как это встроенный в Matlab и, следовательно, закрытый код.

РЕДАКТИРОВАТЬ 2 : Оказывается, Matlab использовал более старую версию LAPACK (вероятно, до 3.5.0), и к 2016b они, похоже, будут обновлены до более новой версии. Теперь результаты согласуются, насколько я могу проверить. Так что я думаю, что это решает проблему. Я должен был проверить это с более старыми версиями LAPACK.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.