¿Cómo obtengo vectores propios específicos de la factorización de Schur generalizada de un par de matrices usando LAPACK?

I am grad student trying to rewrite my MATLAB prototype code into C++ code using Eigen and LAPACK. Generalised eigenvalue solver (A*x=lamba*B*x) takes some part in this program. Because Eigen's generalised eigen solver could result in wrong eigenvalue (in my experience), I decided to go with LAPACK (using Accelerate framework in OS X)

The code below is the C++ translation of tgevc example http://www.nag.com/numeric/fl/manual/pdf/F08/f08ykf.pdf that I wrote. Everything looks fine unless I specify the eigenvalues for which right eigenvectors are calculated.

cuando me puse

char howmny = 'B';

It calculates every eigenvectors for every eigenvalues. And it works FINE. The values are correct also for larger problems.

Sin embargo, cuando establecí

char howmny = 'S';

The result just doesn't make sense. It looks like nothing.

The reason for doing this was for possible speed up in the first place. However, profiling shows that it has less than 4% of the entire process (for larger problems). So it won't change much. Anyway I am still wondering whether I understand something Wrong.

Aquí está mi código de muestra.

#include <iostream>
#include <cmath>
#include <Eigen/Core>
#include <Accelerate/Accelerate.h>

using namespace std;
using namespace Eigen;

int main(int argc, const char * argv[])
{
    // parameters
    int nmax = 5, lda = nmax, ldb = nmax, ldq = nmax, ldz = nmax, lwork=ldq*6, N=5, M;

    // Local scalars
    int ihi, ilo, info, irows, icols, jwork;
    char compq, compz, job, job1, job2, side;

    // Local arrays
    MatrixXd A(lda,nmax), B(ldb, nmax), Q(ldq,ldq), Z(ldz, ldz);
    VectorXd alphai(nmax), alphar(nmax), beta(nmax), lscale(nmax), rscale(nmax), tau(nmax), work(lwork);

    cout << " F08XEF Example Program Results " << endl;

    for (int i = 0; i < N ; i++) {
        A(i,0) = (i+1)*1.0;
    }
    for (int j = 1; j < N ; j++) {
        A.col(j) = A.col(0).array()*A.col(j-1).array();
    }

    B.block(0,0,N,N) = A.block(0, 0, N, N).transpose();
    cout << "Matrix A is" << endl;
    cout << A.block(0, 0, N, N) << endl;
    cout << "Matrix B is" << endl;
    cout << B.block(0,0,N,N) << endl;

    // Balance matrix pair (A, B)
    job = 'B';

    dggbal_(&job, &N, A.data(), &lda, B.data(), &ldb, &ilo, &ihi, lscale.data(), rscale.data(), work.data(), &info);
    cout << "Matrix A after balacing" << endl;
    cout << A.block(0, 0, N, N) << endl;
    cout << "Matrix B after balacing" << endl;
    cout << B.block(0,0,N,N) << endl;

    // Reduce B to triangular form using QR
    irows = ihi + 1 - ilo;
    icols = N + 1 - ilo;
    dgeqrf_(&irows, &icols, B.block(ilo-1,ilo-1,irows,icols).data(), &ldb, tau.data(), work.data(), &lwork, &info);

    // Apply the orthogonal transformation t matrix A
    job1 = 'L';
    job2 = 'T';
    dormqr_(&job1, &job2, &irows, &icols, &irows, B.block(ilo-1,ilo-1,irows,icols).data(), &ldb, tau.data(), A.block(ilo-1,ilo-1,irows,irows).data(), &lda, work.data(), &lwork, &info);
    Z.block(0, 0, N, N) = MatrixXd::Identity(N, N);
    // Compute the generalized Hassenberg form of (A, B)
    compq = 'V';
    compz = 'V';
    dgghrd_(&compq,&compz,&N,&ilo,&ihi,A.block(ilo-1,ilo-1,irows,irows).data(),&lda, B.block(ilo-1,ilo-1,irows,irows).data(),&ldb,Q.data(),&ldq,Z.data(),&ldz,&info);
    cout << "Matrix A in Hessenber form" << endl;
    cout << A.block(0, 0, N, N) << endl;
    cout << "Matrix B is triangular" << endl;
    cout << B.block(0, 0, N, N) << endl;

    // Routine dhgeqz
    // Worspace query : jwork = -1
    jwork = -1;
    job = 'S';
    dhgeqz_(&job, &compq, &compz, &N, &ilo, &ihi, A.data(), &lda, B.data(), &ldb, alphar.data(), alphai.data(), beta.data(), Q.data(), &ldq, Z.data(), &ldz, work.data(), &jwork, &info);
    cout << "Minimal required lwork = " << round(work(0)) << endl;
    cout << "Actual value of lwork = " << lwork << endl;
    // Compute the generalized Schur form if the workspace lwork is adequate
    if (round(work(0)) <= lwork)
    {
        dhgeqz_(&job, &compq, &compz, &N, &ilo, &ihi, A.data(), &lda, B.data(), &ldb, alphar.data(), alphai.data(), beta.data(), Q.data(), &ldq, Z.data(), &ldz, work.data(), &lwork, &info);
    }

    // Print the generalized eigenvalue

    for (int i = 0; i < N ; i++) {
        if (beta(i) != 0.0)
        {
            cout << alphar(i)/beta(i) << "," << alphai(i)/beta(i)<< endl;
        }
    }


    // Compute right generalized eigenvectors of the balaced matrix

    // !This is where the problem shows up!
    char howmny = 'S';
    side = 'R';
    __CLPK_logical select[5]; // int selec[5] works same.

    select[0]=false;
    select[1]=false;
    select[2]=false;
    select[3]=false;
    select[4]=false;


    dtgevc_(&side, &howmny, select, &N, A.data(), &lda, B.data(), &ldb, Q.data(), &ldq, Z.data(), &ldz, &N, &M, work.data(), &info);

    job = 'B';
    dggbak_(&job, &side, &N, &ilo, &ihi, lscale.data(), rscale.data(), &N, Z.data(), &ldz, &info);

    cout << "Right eigenvectors" << endl;
    cout << Z << endl;

    return 0;
}

preguntado el 28 de mayo de 14 a las 13:05

¿Afecta la regulación de la info signal back any problems? -

On a related not, I would recommend you take a look at Boost numeric bindings, which have Eigen/Lapack interface: ci.boost.org/svn-trac/browser/sandbox/numeric_bindings -

@Anycorn 'info' gives just '0' for dtgevc and dggbak which means it is correct. And thanks for the link! -

I just noticed that you set all select to false, - it seems your N is 5 - so nothing would be computed -

@Anycorn Oh that is just an example. Of course I tried 'true' , but there was nothing meaningful. -

0 Respuestas

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.