Собственные значения не следуют порядку при изменении параметра в Python - PullRequest
0 голосов
/ 03 октября 2019

У меня есть 6x6 матрица H, из которых два собственных значения становятся сложными при определенных значениях параметра l (для лямбды). По-видимому, они являются первыми двумя элементами массива собственных значений E мы после диагонализации H (вызывая модуль np.linalg.eig). Однако эта последовательность не сохраняется, когда они становятся реальными (в моем случае, когда l находится между -1 и 1). Я могу отследить их, сравнив их с точными аналитическими выражениями.

См. Мой код ниже:

import numpy as np
import matplotlib.pyplot as plt
import cmath

dim=6; t=1.0; eps=0.5; U = 2.0

# Initialize H
H=np.zeros((dim,dim),float)

# Vary parameter l
for l in np.linspace(-2,2,3):

    # Construct H-matrix (size: 6 x 6)
    tm=t-l; tp=t+l

    H[0][0]=H[2][2]=H[3][3]=H[5][5]=2.0*eps
    H[1][1]=H[4][4]=2.0*eps+U
    H[1][2]=H[2][4]=tm
    H[2][1]=H[4][2]=tp
    H[1][3]=H[3][4]=-tm
    H[3][1]=H[4][3]=-tp

    # Diagonalize H 
    E,psi=np.linalg.eig(H)

    # Print all the eigenvalues 
    print('lambda=',l,'===>')
    print()
    print('First two eigenvalues: E0=',E[0], 'E1=',E[1] )
    print('Always real eigenvalues: E2=',E[2], 'E3=',E[3], 'E4=',E[4], 'E5=',E[5] )
    print()


    print("Expected sometimes complex eigenvalues:")
    print("2\eps+[U+\srqt{16(t^2-\lambda^2)+U^2}]/2=",2.0*eps+(U+cmath.sqrt(16*tp*tm+U**2) )*0.5,"degeneracy=1")
    print("2\eps+[U-\srqt{16(t^2-\lambda^2)}+U^2]/2=",2.0*eps+(U-cmath.sqrt(16*tp*tm+U**2) )*0.5,"degeneracy=1")


    print("Expected always real eigenvalues:")
    print("2\eps=",2.0*eps,"degeneracy=3")
    print("2\eps+U=",2.0*eps+U,"degeneracy=1")
    print('---------------------')
    print()

Как я могу поддерживать последовательность так, чтобы я мог строить только «иногда сложные»пара собственных значений против l (или лямбда)?

Вывод:

lambda= -2.0 ===>

First two eigenvalues: E0= (2.0000000000000058+3.3166247903554043j) E1= (2.0000000000000058-3.3166247903554043j)
Always real eigenvalues: E2= (2.9999999999999982+0j) E3= (0.9999999999999999+0j) E4= (1+0j) E5= (1+0j)

Expected sometimes complex eigenvalues:
2\eps+[U+\srqt{16(t^2-\lambda^2)+U^2}]/2= (2+3.3166247903554j) degeneracy=1
2\eps+[U-\srqt{16(t^2-\lambda^2)}+U^2]/2= (2-3.3166247903554j) degeneracy=1
Expected always real eigenvalues:
2\eps= 1.0 degeneracy=3
2\eps+U= 3.0 degeneracy=1
---------------------

lambda= 0.0 ===>

First two eigenvalues: E0= -0.23606797749979025 E1= 2.9999999999999996
Always real eigenvalues: E2= 4.236067977499788 E3= 1.0 E4= 1.0 E5= 1.0

Expected sometimes complex eigenvalues:
2\eps+[U+\srqt{16(t^2-\lambda^2)+U^2}]/2= (4.23606797749979+0j) degeneracy=1
2\eps+[U-\srqt{16(t^2-\lambda^2)}+U^2]/2= (-0.2360679774997898+0j) degeneracy=1
Expected always real eigenvalues:
2\eps= 1.0 degeneracy=3
2\eps+U= 3.0 degeneracy=1
---------------------

lambda= 2.0 ===>

First two eigenvalues: E0= (2.000000000000008+3.3166247903554043j) E1= (2.000000000000008-3.3166247903554043j)
Always real eigenvalues: E2= (2.999999999999997+0j) E3= (1+0j) E4= (1+0j) E5= (1+0j)

Expected sometimes complex eigenvalues:
2\eps+[U+\srqt{16(t^2-\lambda^2)+U^2}]/2= (2+3.3166247903554j) degeneracy=1
2\eps+[U-\srqt{16(t^2-\lambda^2)}+U^2]/2= (2-3.3166247903554j) degeneracy=1
Expected always real eigenvalues:
2\eps= 1.0 degeneracy=3
2\eps+U= 3.0 degeneracy=1
---------------------

PS: Пожалуйста, дайте мне знать, если мой вопрос не ясен или его нужно реорганизовать.

1 Ответ

0 голосов
/ 04 октября 2019

Ответ находится в документации: https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.linalg.eig.html

Я цитирую:

... Собственные значения не обязательно упорядочены. Полученный массив будет сложного типа, если только мнимая часть не равна нулю, и в этом случае он будет приведен к реальному типу. Когда a является действительным, результирующие собственные значения будут действительными (0 мнимая часть) или встречаются в сопряженных парах

Поэтому, если вы хотите сохранить порядок и знаете, что существует постоянное изменение реальногочасть собственных значений по отношению к параметрам, то, что вам нужно сделать, это отсортировать собственные векторы по ключу, где ключ просто задается действительной частью собственных значений:

vals, eigs = np.linalg.eig(H);
eigs = eigs[ np.argsort( np.real(vals) ) ]

должен сделать свое дело.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...