我正在使用 C++ 库 Armadillo 中的函数
eigs_gen
来查找存储为复杂稀疏矩阵 sp_cx_mat H;
的量子物理哈密顿量的基态。它有效,但每次运行时结果都会因随机阶段而有所不同eigs_gen
。考虑这个例子,我计算了 H
的特征值两次:
#include<cstdint>
#include<vector>
#include<iostream>
#include<string>
#include<complex>
#include<iomanip>
#include <armadillo>
using namespace std;
using namespace arma;
int main()
{
std::cout << std::fixed << std::showpoint;
std::cout << std::setprecision(2);
uint64_t N_states;
sp_cx_mat H = generate(N_states,/*Some physical arguments, to generate H and N_states*/);
//H has been generated above
//PURELY FOR DEBUGGING
cout<<H<<endl;
double energy=0;
cx_vec eigvals1;
cx_mat eigvec1(N_states,1);
cx_vec eigvals0;
cx_mat eigvec0(N_states,1);
//These are run on the same H (And H is not modified, as it is treated as const!)
eigs_gen(eigvals0, eigvec0, H , 1, "sr");//The lowest eigenstate
eigs_gen(eigvals1, eigvec1, H, 1, "sr");//The lowest eigenstate
cout<<"Eigenvector: "<<endl;
for (uint i = 0; i < N_states; ++i)
{
cout<<'|'<<All_States[i]<<"> * "<<eigvec0[i]<<" OR "<<eigvec1[i]<<endl;
}
cout<<"Eigenvalue found with direct diagonalization"<<eigvals0<<" AND "<<eigvals1<<endl;
return 0;
}
这里我没有包含生成
H
的函数,因为它相当冗长,但是在特征向量下方打印了 H
,并且打印的值是:
Eigenvector:
|3> * (0.55,0.15) OR (0.39,-0.42)
|5> * (0.39,0.11) OR (0.28,-0.30)
|6> * (0.41,0.11) OR (0.29,-0.31)
|9> * (0.41,0.11) OR (0.29,-0.31)
|10> * (0.20,0.06) OR (0.14,-0.15)
|12> * (0.17,0.05) OR (0.12,-0.13)
|17> * (0.15,0.04) OR (0.11,-0.11)
|18> * (0.12,0.03) OR (0.09,-0.09)
|20> * (0.04,0.01) OR (0.03,-0.03)
|24> * (0.05,0.01) OR (0.03,-0.04)
|33> * (0.12,0.03) OR (0.09,-0.09)
|34> * (0.07,0.02) OR (0.05,-0.05)
|36> * (0.05,0.01) OR (0.03,-0.04)
|40> * (0.02,0.01) OR (0.01,-0.02)
|48> * (0.01,0.00) OR (0.01,-0.01)
Eigenvalue found with direct diagonalization (+1.511e+00,-1.342e-17)
AND (+1.511e+00,-1.825e-16)
需要澄清的是,这些答案没有任何问题!它们都具有最低的能量,并且它们仅相差一个常数相位(因此所有数字都乘以常数
exp(i*phi)
,以获得某个常数和实数phi
),这不会改变任何重要的东西。
但是有人可以解释为什么
eigs_gen
被调用一次会影响后续调用吗? H
在 eig_gen
中是恒定的,因此它不会改变,并且没有其他数据被共享。
上例中使用的H:
(0, 0) (+3.000e+00,+0.000e+00)
(2, 0) (-1.000e+00,+0.000e+00)
(3, 0) (-1.000e+00,+0.000e+00)
(1, 1) (+4.000e+00,+0.000e+00)
(2, 1) (-1.000e+00,+0.000e+00)
(3, 1) (-1.000e+00,+4.899e-16)
(6, 1) (-1.000e+00,+0.000e+00)
(0, 2) (-1.000e+00,+0.000e+00)
(1, 2) (-1.000e+00,+0.000e+00)
(2, 2) (+5.000e+00,+0.000e+00)
(4, 2) (-1.000e+00,+4.899e-16)
(5, 2) (-1.000e+00,+0.000e+00)
(7, 2) (-1.000e+00,+0.000e+00)
(0, 3) (-1.000e+00,+0.000e+00)
(1, 3) (-1.000e+00,-4.899e-16)
(3, 3) (+5.000e+00,+0.000e+00)
(4, 3) (-1.000e+00,+0.000e+00)
(5, 3) (-1.000e+00,+0.000e+00)
(10, 3) (-1.000e+00,+0.000e+00)
(2, 4) (-1.000e+00,-4.899e-16)
(3, 4) (-1.000e+00,+0.000e+00)
(4, 4) (+6.000e+00,+0.000e+00)
(11, 4) (-1.000e+00,+0.000e+00)
(2, 5) (-1.000e+00,+0.000e+00)
(3, 5) (-1.000e+00,+0.000e+00)
(5, 5) (+7.000e+00,+0.000e+00)
(9, 5) (-1.000e+00,+0.000e+00)
(12, 5) (-1.000e+00,+0.000e+00)
(1, 6) (-1.000e+00,+0.000e+00)
(6, 6) (+6.000e+00,+0.000e+00)
(7, 6) (-1.000e+00,+0.000e+00)
(8, 6) (-1.000e+00,+0.000e+00)
(10, 6) (-1.000e+00,+9.797e-16)
(2, 7) (-1.000e+00,+0.000e+00)
(6, 7) (-1.000e+00,+0.000e+00)
(7, 7) (+7.000e+00,+0.000e+00)
(9, 7) (-1.000e+00,+0.000e+00)
(11, 7) (-1.000e+00,+9.797e-16)
(6, 8) (-1.000e+00,+0.000e+00)
(8, 8) (+8.000e+00,+0.000e+00)
(9, 8) (-1.000e+00,+4.899e-16)
(12, 8) (-1.000e+00,+9.797e-16)
(5, 9) (-1.000e+00,+0.000e+00)
(7, 9) (-1.000e+00,+0.000e+00)
(8, 9) (-1.000e+00,-4.899e-16)
(9, 9) (+9.000e+00,+0.000e+00)
(13, 9) (-1.000e+00,+9.797e-16)
(14, 9) (-1.000e+00,+0.000e+00)
(3, 10) (-1.000e+00,+0.000e+00)
(6, 10) (-1.000e+00,-9.797e-16)
(10, 10) (+7.000e+00,+0.000e+00)
(11, 10) (-1.000e+00,+0.000e+00)
(12, 10) (-1.000e+00,+0.000e+00)
(4, 11) (-1.000e+00,+0.000e+00)
(7, 11) (-1.000e+00,-9.797e-16)
(10, 11) (-1.000e+00,+0.000e+00)
(11, 11) (+8.000e+00,+0.000e+00)
(13, 11) (-1.000e+00,+0.000e+00)
(5, 12) (-1.000e+00,+0.000e+00)
(8, 12) (-1.000e+00,-9.797e-16)
(10, 12) (-1.000e+00,+0.000e+00)
(12, 12) (+9.000e+00,+0.000e+00)
(13, 12) (-1.000e+00,+4.899e-16)
(14, 12) (-1.000e+00,+0.000e+00)
(9, 13) (-1.000e+00,-9.797e-16)
(11, 13) (-1.000e+00,+0.000e+00)
(12, 13) (-1.000e+00,-4.899e-16)
(13, 13) (+1.000e+01,+0.000e+00)
(9, 14) (-1.000e+00,+0.000e+00)
(12, 14) (-1.000e+00,+0.000e+00)
(14, 14) (+1.100e+01,+0.000e+00)
Armadillo 有两个用于稀疏矩阵特征分解的后端。一种是标准的 ARPACK 库。另一个是 ARPACK 的较新的 C++ 实现,称为 NEWARP,它包含在 Armadillo 中。
标准 ARPACK 是一个基于 Fortran 的旧软件库,不可重入,并使用随机起点进行 Arnoldi 迭代。 NEWARP 实现较新,但可能不支持所有稀疏矩阵类型。
使用哪个后端取决于Armadillo的版本和配置、系统配置和稀疏矩阵类型。所以有可能正在使用 ARPACK 而不是 NEWARP。
尝试升级到最新版本的犰狳。要强制使用 NEWARP,请在包含 Armadillo 标头之前定义以下配置宏:
#define ARMA_DONT_USE_ARPACK
#define ARMA_USE_NEWARP
#include <armadillo>