Как найти левые собственные вектора?
Задача моя типичная – имею плотную действительную квадратную несимметричную матрицу, размером 100х100. Нужны собственные значения и собственные вектора. И побыстрее
.
Несимметричные матрицы имеют два разных набора собственных векторов – левые и правые, которые в отличие от симметричной (или эрмитовой) матрицы, не могут быть получены друг из друга простым транспонированием. И причина этого в том, что в данном случае наборы векторов (ни левых, ни правых) не являются унитарными. И мне нужны они оба.
На мое горе, понятные мне процедуры выдают только набор правых собственных векторов, полностью умалчивая про то, как можно получить набор левых. В частности я использовал связку процедур EISPACK: ortran.f + orthes.f + hqr2.f. Первая из них приводит исходную матрицу в верхней форме Хессенберга (почти треугольную) отражениями Хаусхолдера, вторая повторяет те же самые манипуляции над единичной матрицей, производя из нее заготовку для набора правых собственных векторов. А третья (hqr2.f) находит собственные значения, попутно доводя полуфабрикат из единичной матрицы до набора правых собственных векторов.
Отчего абсолютное большинство процедур больше любят правые векторы, чем левые, легко объяснимо. Действительно, если в процессе преобразования исходной матрицы к диагональному виду «параллельно» совершать те же самые преобразования с единичной матрицей, то в конце этой процедуры единичная матрица как раз «дойдет» до набора правых собственных векторов. Но вот каким образом можно получить набор левых собственных векторов я никак в толк взять не могу. По крайней мере, таким образом их получить видимо не удастся.
Какие вижу возможности лично я.
Первое, что приходит в голову – инвертировать матрицу правых векторов. Левые вектора получить так можно, но чтобы инвертировать
КОМПЛЕКСНУЮ матрицу мне даже подумать страшно – настолько это времязатратно. Обращаю внимание, что процедуры вычисления собственных значений и (правых) векторов не работают в комплексной арифметике, и даже мнимые части собственных векторов пакуют в действительную матрицу, пользуясь тем, что комплексные вектора получаются всегда комплексно-сопряженной парой, соответственно своим собственным значениям. Это и позволяет этой паре векторов «сообразить на двоих» - один хранит действительную часть, а другой мнимую. Опять же разделение на действительную и мнимую части происходит уже на самом последнем этапе алгоритма (работа с диагональными матрицами размером 2х2), что времени занимает мало. А вот если я стану инвертировать комплексную матрицу в лоб, то мне мало не покажется.
Второй способ я подсмотрел в интернете. Чтобы получить набор левых собственных векторов люди транспонируют свою исходную матрицу и повторяют с ней сызнова все (!) процедуры вычисления собственных значений и векторов. Затем полученные собственные вектора комплексно-сопрягаются (т.е. транспонируются с попутным изменением знака перед мнимыми частями). Так и получают левые вектора.
В самом деле, правые вектора для сопряженной матрицы (а для действительной матрицы это простое транспонирование) соответствуют по определению условию:
A’v = vD
комплексно-транспонируя, получаем:
v’A = D’v’
(D тут тоже приходится сопрягать, несмотря на то, что она диагональная)
после чего, сравнивая с определением левых собственных векторов
yA=Dy (я тут ничего не попутал?),
понимаем, что искомый левый вектор
y=v’, а собственные значения от этого получились сопряженными к старым. Но они нам второй раз и не нужны.
Тут вроде бы все чисто, но ведь двойная работа! Тут еще изрядно подумаешь, чего быстрее – комплексную матрицу обращать или заново диагонализацию делать.
Нутром чую, что, уже зная собственные значения и набор правых собственных векторов, найти левые должно быть проще (быстрее), но как это сделать ума не приложу. Возможно тут что-то такое простое, что и обращаться за помощью стыдно, но сам никак недопетрю.
P.S. Очень прошу не тыкать меня носом в функции LAPACK или подобных пакетов, которые согласно описанию выдают по требованию наборы правых, левых и обоих вместе векторов. Знать хочу, как их получают! А в LAPACK’е с ума сойдешь разбираться, это тебе не EISPACK, написанный по ясным алгоритмам Уилкинсона и Райша (да не померкнет их слава в веках!
.