为什么犰狳中的“eigs_gen”在多次运行时会在最低特征值上给出不同的相位

问题描述 投票:0回答:1

我正在使用 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)
c++ armadillo eigenvector
1个回答
0
投票

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>
© www.soinside.com 2019 - 2024. All rights reserved.