I would like to report an issue which may be interesting in computational physics. Sometimes, to save time and memory, we use eigs()
to calculate the first several eigenvalues of a sparse matrix. However, I find that the eigenvectors calculated in this way is not always accurate, especially only few eigenvalues are calculated, which may lead to severe problem for later calculation. Any comment, suggestion and solution to this issue is highly appreciated.
Please consider the matrix produced by this code (this code is irrelavent, just copy and use it)
%% generate the Hamiltonian matrix of the Ising model.
X = sparse([0,1;1,0]);
Z = sparse([1,0;0,-1]);
XX = kron(X,X);
L = 12;
h = 0;
Hamiltonian = -kron(kron(X,speye(2^(L-2))),X);
for i = 1:L-1
Hamiltonian = Hamiltonian - kron(speye(2^(i-1)), kron(XX, speye(2^(L-1-i))));
end
for i = 1:L
Hamiltonian = Hamiltonian - kron(speye(2^(i-1)), kron(h*Z,speye(2^(L-i))));
end
I want to calculate the ground state energy, i.e. the minimal eigenvalue, and the corresponding eigenvector. To save time and memory, I use sparse matrix and eigs()
to calculate the only first six eigenvalues and eigenvectors. Here is the code
%% calculate the first several eigenvalues and eigenvectors by eigs()
Hamiltonian = sparse(Hamiltonian);
[eigv, eigd]= eigs(Hamiltonian, 6, 'smallestreal');
[~, idx] = sort(diag(eigd));
vg = eigv(:,idx(1));
eg = eigd(idx(1));
After a long time check and verify, I finally find that, the minimal eigenvalue is well caculated (it's $-12$ in this case), but the corresponding eigenvector is not well caculated (it's elements are $0.0217, -0.0041, -0.0041 \cdots$ in this case). Then I tried two other methods. Firstly, I use eig()
rather than eigs()
%% calculate the full eigenvalues and eigenvectors by eig()
Hamiltonian = full(Hamiltonian);
[eigv, eigd]= eig(Hamiltonian);
[~, idx] = sort(diag(eigd));
vg = eigv(:,idx(1));
eg = eigd(idx(1));
Secondly, I use eigs()
but with a coverage of all the full eigenvalues
%% calculate the full eigenvalues and eigenvectors by eigs()
Hamiltonian = sparse(Hamiltonian);
[eigv, eigd]= eigs(Hamiltonian, length(Hamiltonian), 'smallestreal');
[~, idx] = sort(diag(eigd));
vg = eigv(:,idx(1));
eg = eigd(idx(1));
The results of the two methods are the same. For the minimal eigen value, it's $-12$. For the corresponding eigenvector, it's $0, 0.0221, 0.0221 \cdots$, which is different from the previous one, and we should belive this results is more accurate. Is there any comment on why eigs()
is not that accurate when only several eigenvalues are included. And is there any suggestion that I can keep the eigs()
accurate while ultilizing its superiority in time and memory saving?
eig()
is more accurate since it includes all the eigenvalues. However, accroding to the answer by @helloworld922, I finally find it's about the degeneracy. Thanks for your comment. $\endgroup$