Я имею дело с разреженной матрицей с очень маленькими элементами. Рассмотрим вектор:
vec=[-1.e-76 -1.e-72 -1.e-68 -1.e-64 -1.e-60 -1.e-56 -1.e-52 -1.e-48 -1.e-44
-1.e-40 -1.e-36 -1.e-32 -1.e-28 -1.e-24 -1.e-20 -1.e-16 -1.e-12 -1.e-08
-1.e-04 -1.e-02 -1.e-04 -1.e-08 -1.e-12 -1.e-16 -1.e-20 -1.e-24 -1.e-28
-1.e-32 -1.e-36 -1.e-40 -1.e-44 -1.e-48 -1.e-52 -1.e-56 -1.e-60 -1.e-64
-1.e-68 -1.e-72 -1.e-76]
Для тех, кто заинтересован, эти числа представляют собой амплитуды скачкообразного изменения одномерной системы. Они не равны нулю. Гамильтониан задается разреженной матрицей:
H=sps.diags([vec,vec],[-1,1],dtype='f8')
Меня интересуют собственные значения, но еще больше - собственные векторы.
, Насколько я знаю, есть два способа справиться с диагонализацией:
scipy.linalg
и numpy.linalg
и первый лучше.
denseHam=H.toarray()
Правильный спектр собственных значений задается всеми этими функциями:
import numpy as np
import scipy.linalg as la
s1= la.eigvalsh(denseHam)
s2= np.linalg.eigvalsh(denseHam)
s3= np.linalg.eigvals(denseHam) #I did not expect that!
Правильный спектр:
spectrum=[-3.16230928e-03 -3.16227766e-08 -3.16227766e-13 -3.16227766e-18
-3.16227766e-23 -3.16227766e-28 -3.16227766e-33 -3.16227766e-38
-3.16227766e-43 -3.16227766e-48 -3.16227766e-53 -3.16227766e-58
-3.16224604e-63 3.16224604e-63 3.16227766e-58 3.16227766e-53
3.16227766e-48 3.16227766e-43 3.16227766e-38 3.16227766e-33
3.16227766e-28 3.16227766e-23 3.16227766e-18 3.16227766e-13
3.16227766e-08 3.16230928e-03]
Тем не менее, другие функции (которые также включают вычисление собственных векторов) не работают, и я не могу продолжать, потому что мне нужны собственные векторы.
Я должен сказать, что C ++ способен правильно вычислять и собственные векторы.
Итак, у меня два вопроса:
- Почему функция
np.linalg.eigh(denseHam)
дает спектр, отличный от np.linalg.eigvalsh(denseHam)
?
- Есть ли способ правильно вычислить собственные векторы с помощью python?
Заранее большое спасибо!
--- ОБНОВЛЕНИЕ ------
Я привожу здесь минимальный полный пример. Обратите внимание на явное вырождение numpy.linalg.eigh
:
import numpy as np
import scipy.sparse as sps
vec=np.array([-1.e-76, -1.e-72, -1.e-68, -1.e-64, -1.e-60, -1.e-56, -1.e-52,
-1.e-48, -1.e-44, -1.e-40, -1.e-36, -1.e-32, -1.e-28, -1.e-24,
-1.e-20, -1.e-16, -1.e-12, -1.e-08, -1.e-04, -1.e-02, -1.e-04,
-1.e-08, -1.e-12, -1.e-16, -1.e-20, -1.e-24, -1.e-28, -1.e-32,
-1.e-36, -1.e-40, -1.e-44, -1.e-48, -1.e-52, -1.e-56, -1.e-60,
-1.e-64, -1.e-68, -1.e-72, -1.e-76])
H=sps.diags([vec,vec],[-1,1],dtype='f8')
denseHam=H.toarray()
s1=np.linalg.eigvalsh(denseHam)
(s2,basis)=np.linalg.eigh(denseHam)
print("Note the difference between the eigenvalues computed with eigvalsh (1stcolumn) and eigh (2nd column)")
for elem in range(len(s1)):
print (s1[elem]," ",s2[elem])