You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:使用Spectra GenEigsSolver无法获取最小Eigenvalue问题排查

特征值计算问题:无法获取最小特征值
  • 程序可正常返回最大特征值,但无法获取最小特征值
  • 测试23×23矩阵时无此问题,官方文档示例运行正常
  • 代码运行耗时不到3秒,编译约10秒

完整代码

#include <iostream>
#include <random>
#include <Eigen/Sparse>
#include <Spectra/GenEigsSolver.h>
#include <Spectra/MatOp/SparseGenMatProd.h>
using namespace std;
using uint = unsigned int;

#define ALLOCATE_ARRAY(type, count) ((type*) malloc(sizeof(type) * (count)))
#define REALLOC_ARRAY(array, type, count) ((type*) realloc(array, sizeof(type) * count))
#define MATRIX(array, i,j) array[j+i*total_sites]


uint number_sites = 4;
uint total_sites = 0;
uint total_Hilbert_elements = 0;
uint number_spin_states = 2;
int* computational_base = 0;

default_random_engine ran_generator;

void inizialize_Hamiltonian_matrix (float trasverse_magnetic_field, float longitudinal_magnetic_field, uint boundary_conditions_flag, Eigen::MatrixXf& Hamiltonian_config_matrix);

int main(){

    float beta = 0.3;
    float trasverse_magnetic_field = 1;
    float longitudinal_magnetic_field = 1;

    uint dimensions = 1;
    uint initial_state = 1;
    uint boundary_conditions_flag = 1;
    uint number_eigenvalues = 1;
    total_sites = pow(number_sites, dimensions);

    total_Hilbert_elements = pow(number_spin_states, total_sites);
    computational_base =  ALLOCATE_ARRAY(int, total_Hilbert_elements*total_sites);

    for (int i=0; i<total_Hilbert_elements; ++i){
        uint i_holder = i;
        for (int j=0; j<total_sites; ++j){
            MATRIX(computational_base, i,j) = i_holder%2;
            i_holder = i_holder/2;
        }
    }

    // Build Matrix and print on shell
    Eigen::MatrixXf Hamiltonian_config_matrix(total_Hilbert_elements, total_Hilbert_elements);
    inizialize_Hamiltonian_matrix (trasverse_magnetic_field, longitudinal_magnetic_field, boundary_conditions_flag, Hamiltonian_config_matrix);

    for (int i=0; i<total_Hilbert_elements; ++i){
        for (int j=0; j<total_Hilbert_elements; ++j){
            if (Hamiltonian_config_matrix(i,j)>=0){
                cout << " " << Hamiltonian_config_matrix(i,j);
            }
            else{
                cout << Hamiltonian_config_matrix(i,j);
            }
        }
        cout << endl;
    }

    // Converting in Sparse Matrix and Spectra stuff
    Eigen::SparseMatrix<float> Sparse_Hamiltonian_config;
    Sparse_Hamiltonian_config = Hamiltonian_config_matrix.sparseView();
    Spectra::SparseGenMatProd<float> Operation_object_wrap(Sparse_Hamiltonian_config);

    // Initialize and Compute
    Spectra::GenEigsSolver<Spectra::SparseGenMatProd<float>> Ready_for_Lanczos(Operation_object_wrap, number_eigenvalues, 2*number_eigenvalues+1);
    Ready_for_Lanczos.init();

    uint which_eigenvalues = 0;
    cout << "Type 1 if Largest Eigenvalue, Type 0 if Smallest" << endl;
    cin >> which_eigenvalues;

    if (which_eigenvalues==0){
        int nconv = Ready_for_Lanczos.compute(Spectra::SortRule::SmallestMagn);
    }
    else{
        int nconv = Ready_for_Lanczos.compute(Spectra::SortRule::LargestMagn);
    }

    // Retrieve results
    Eigen::VectorXcf evalues;
    if(Ready_for_Lanczos.info() == Spectra::CompInfo::Successful)
        evalues = Ready_for_Lanczos.eigenvalues();
    cout << "Eigenvalues found:\n" << evalues << endl;

    return 0;
}

void inizialize_Hamiltonian_matrix (float trasverse_magnetic_field, float longitudinal_magnetic_field, uint boundary_conditions_flag, Eigen::MatrixXf& Hamiltonian_config_matrix){
    for (uint j=0; j<total_sites-1; ++j){
        for (uint i=0; i<total_Hilbert_elements; ++i){
            if (MATRIX(computational_base, i,j)==MATRIX(computational_base, i,j+1)){
                Hamiltonian_config_matrix(i,i) = Hamiltonian_config_matrix(i,i) -1.0;
            }
            else{
                Hamiltonian_config_matrix(i,i) = Hamiltonian_config_matrix(i,i) +1.0;
            }
        }
    }
    if (boundary_conditions_flag==1){
        uint j = total_sites-1;
        for (uint i=0; i<total_Hilbert_elements; ++i){
            if (MATRIX(computational_base, i,j)==MATRIX(computational_base, i,0)){
                    Hamiltonian_config_matrix(i,i) = Hamiltonian_config_matrix(i,i) -1.0;
            }
            else{
                Hamiltonian_config_matrix(i,i) = Hamiltonian_config_matrix(i,i) +1.0;
            }
        }
    }
    for (uint j=0; j<total_sites-1; ++j){
        for (uint i=0; i<total_Hilbert_elements; ++i){
            if (MATRIX(computational_base, i,j)==1){
                Hamiltonian_config_matrix(i,i) = Hamiltonian_config_matrix(i,i) -longitudinal_magnetic_field;
            }
            else{
                Hamiltonian_config_matrix(i,i) = Hamiltonian_config_matrix(i,i) +longitudinal_magnetic_field;
            }
        }
    }
    uint new_i_binary = 0;
    for (uint j=0; j<total_sites-1; ++j){
        for (uint i=0; i<total_Hilbert_elements; ++i){
            if (MATRIX(computational_base, i,j)==1){
                new_i_binary = i - pow(2, j);
            }
            else{
                new_i_binary = i + pow(2, j);
            }
            Hamiltonian_config_matrix(new_i_binary,i) = Hamiltonian_config_matrix(new_i_binary,i) -trasverse_magnetic_field;
        }
    }
}

问题修复建议

  1. 初始化矩阵时清零
    Eigen的MatrixXf默认不会将元素初始化为0,导致矩阵存在随机垃圾值,干扰特征值计算。在创建矩阵后添加清零操作:

    Eigen::MatrixXf Hamiltonian_config_matrix(total_Hilbert_elements, total_Hilbert_elements);
    Hamiltonian_config_matrix.setZero(); // 新增此行
    inizialize_Hamiltonian_matrix(trasverse_magnetic_field, longitudinal_magnetic_field, boundary_conditions_flag, Hamiltonian_config_matrix);
    
  2. 增大Lanczos子空间维度
    寻找最小模特征值时,当前设置的子空间维度2*number_eigenvalues+1(即3)过小,不足以让算法收敛。建议增大到更大的值,比如10:

    Spectra::GenEigsSolver<Spectra::SparseGenMatProd<float>> Ready_for_Lanczos(Operation_object_wrap, number_eigenvalues, 10);
    
  3. 替换pow为位运算避免精度问题
    pow(2,j)返回浮点数,赋值给uint可能因精度丢失导致索引错误,改用位运算翻转比特位:

    // 替换原new_i_binary计算部分
    new_i_binary = i ^ (1 << j);
    

内容的提问来源于stack exchange,提问作者Matteo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 05:01:33