Почему вычисления собственных векторов в matlab и python не совпадают?

#python #numpy #matlab #scipy

Вопрос:

Matlab:

 m1 = [ 333.33333333  83.33333333   0. ;  83.33333333 333.33333333  83.33333333 ;  0.   3.33333333 166.66666667]
k1 = [ 800. -400.    0.; -400.  800. -400.;   0. -400.  400.]
[vec, val] = eig(m1, k1)

vec =

   -0.0106   -0.0289    0.0394
    0.0183   -0.0000    0.0683
   -0.0211    0.0289    0.0789
 

питон:

 import scipy
import numpy as np
m1 = np.array[[333.33333333,  83.33333333,  0.], [ 83.33333333, 333.33333333, 83.33333333], [0., 83.33333333, 166.66666667]]
k1 = np.array[[800., -400.,  0.], [-400.,  800., -400.], [0., -400.,  400.]]
val, vec = scipy.linalg.eig(m1, k1)

vec = 
[[ 3.53553391e-01, -7.07106781e-01,  3.53553391e-01], 
[ 6.12372436e-01,  1.88119544e-16, -6.12372436e-01], 
[ 7.07106781e-01,  7.07106781e-01,  7.07106781e-01]]
 

Таким образом, собственные векторы matlab и python vec не совпадают. В документе Matlab говорится

[V,D] = eig(A,B) возвращает диагональную матрицу D обобщенных собственных значений и полную матрицу V, столбцы которой являются соответствующими правыми собственными векторами, так что A*V = B*V*D .

и m1 * vec = k1 * vec * val удовлетворяет для вывода matlab, но не для вывода python. Как я могу получить аналогичные собственные векторы, заданные matlab, используя python, numpy?

Комментарии:

1. Я думаю, что эта разница обсуждалась в предыдущих статьях, хотя я не обращал на это особого внимания. Выглядит как векторы для обоих столбцов a, но является ли нормализация одинаковой? Как насчет порядка? np.linalg.eig похоже, у вас есть более полная документация.

Ответ №1:

Собственные векторы не уникальны; если x это собственный вектор, то a * x он по-прежнему является собственным вектором для любого ненулевого скаляра a .

Посмотрите на два результата из python и matlab; первый столбец vec из matlab выглядит как масштабированная версия третьего столбца vec из python. Второй столбец из matlab, по-видимому, является масштабированной версией второго столбца из python (отзыв 1.88119544e-16 почти равен нулю). Третий столбец соответствует первому столбцу. Поэтому я предполагаю, что val из matlab-это обратная версия val из python; Я не могу это проверить, потому что у меня сейчас нет matlab, но вы можете это проверить.

Также в python помните * , что это поэлементное умножение (т. Е. .* в matlab). Вы можете использовать @ для умножения матриц.

 import scipy.linalg
import numpy as np
m1 = np.array([[333.33333333,  83.33333333,  0.], [ 83.33333333, 333.33333333, 83.33333333], [0., 83.33333333, 166.66666667]])
k1 = np.array([[800., -400.,  0.], [-400.,  800., -400.], [0., -400.,  400.]])
val, vec = scipy.linalg.eig(m1, k1)

print(m1 @ vec)
print(k1 @ vec * val)
 

Как вы можете видеть в следующем выводе, у нас один и тот же вывод (мнимая часть есть 0.j , так что вы можете это игнорировать).

Выход:

 [[ 1.68882167e 02 -2.35702260e 02  6.68200939e 01]
 [ 2.92512493e 02 -3.14270210e-09 -1.15735798e 02]
 [ 1.68882167e 02  1.17851130e 02  6.68200939e 01]]
[[ 1.68882167e 02 0.j -2.35702260e 02 0.j  6.68200939e 01 0.j]
 [ 2.92512493e 02 0.j -3.14263578e-09 0.j -1.15735798e 02 0.j]
 [ 1.68882167e 02 0.j  1.17851130e 02 0.j  6.68200939e 01 0.j]]