Search code examples
c++matrixeigeneigen3eigenvector

How do I assign "Eigen::EigenSolver<MatrixXd> es(Matrix)" to a variable that I can use later?


I am successfully able to retrieve the eigenvalues and eigenvectors from the Eigen::EigenSolver command, however, I cannot assign them to a new Matrix. I need to assign the 3 eigenvectors to a new 3x3 Matrix so that I can perform a transpose then Matrix Multiplication against another 3x3 matrix.

I keep getting the following Error with a green carrot pointed to the "b" in the "{ a = b; }" part:

/Eigen/src/Core/functors/AssignmentFunctors.h:24:104: error: assigning to 'double' from incompatible type 'const std::__1::complex' EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(DstScalar& a, const SrcScalar& b) const { a = b; }

I have tried declaring the new variable I am trying to assign it to as MatrixXd or Vector3d and neither seem to work. I think the issue has to do with the Eigensolver returning each element as (Real, Complex) and I'm not manipulating this properly. This would not be a bad thing if I only needed to compute the values once. However, I am going to need to drop these calculations into a loop and the final calculations from this process will then be checked against some conditionals to determine if the random values used in the code result in valid results.

[EDIT 19April2020, 1152am]. I am only looking to use the Real parts for my current calculations. Thank you @stark for bringing this to my attention in the comments.

Any help would be greatly appreciated. Please keep in mind, I'm not a programmer by training, my areas of study are physics and mathematics, and I am used to working with symbolic software and python. '''

// Declare matrices for the up and down type quarks
MatrixXd MatrixYukawaUpQuark(3,3), MatrixYukawaDownQuark(3,3);

// Declare vectors for Up and Down Quark eigenvectors
Vector3d UpQVect, DownQVect;

Eigen::EigenSolver<MatrixXd> es1(MatrixYukawaUpQuark);
UpQVect = es1.eigenvectors(); // THE ERROR COMES FROM HERE, AND IF THIS IS COMMENTED OUT THE CODE WORKS FINE IN GENERATING THE EIGENVECTORS & VALUES IN THE PRINT STATEMENTS 

// Printing the Up Quark Matrice values for the Eigenvectors, and Eigenvalues to the screen
std::cout << "\nThe eigenvalues for the Yukawa Up Quark Matrix are: " << std::endl << es1.eigenvalues() << std::endl;
std::cout << "\nThe Up Quark eigenvectors are:" << std::endl << es1.eigenvectors() << std::endl;

Eigen::EigenSolver<MatrixXd> es2(MatrixYukawaDownQuark);
//DownQVect = es2.eigenvectors(); // THIS WILL ALSO PRODUCE AN ERROR AS IT IS THE SAME PROBLEM FROM ABOVE

// Printing the Up Quark Matrice values for the Eigenvectors, and Eigenvalues to the screen
std::cout << "\nThe eigenvalues of the Yukawa Down Quark Matrix are: " << std::endl << es2.eigenvalues() << std::endl;
std::cout << "\nThe Down Quark eigenvectors, V, is:" << std::endl << es2.eigenvectors() << std::endl;

'''

Below are the print statements that you see above:

The eigenvalues of the Yukawa Up Quark Matrix are:
(-1.00393,0)
(1.01004,0)
(1.00393,0)

The Up Quark eigenvectors are: (-0.707819,0) (0.57735,0) (-0.407013,0)
(0.706393,0) (0.57735,0) (-0.409483,0)
(0.00142613,0) (0.57735,0) (0.816495,0)

The eigenvalues of the Yukawa Down Quark Matrix are:
(-1.96316,0)
(2.07543,0)
(1.96316,0)

The Down Quark eigenvectors, V, are:
(-0.713131,0) (0.57735,0) (-0.397632,0)
(0.700925,0) (0.57735,0) (-0.418773,0)
(0.0122058,0) (0.57735,0) (0.816405,0)


Solution

  • You are trying to assign a 3x3 complex matrix to a 3x1 real vector. Changing the type of UpQVect to Matrix3cd should make your code compile:

    Matrix3cd UpQVect = es1.eigenvectors();
    

    If you want to extract the real parts and store them to a 3x3 matrix, you can write:

    Matrix3d UpQVect = es1.eigenvectors().real();
    

    Also note that accessing es1.eigenvectors() multiple times is essentially free. The expensive computation happens only when you construct es1 (or if you would later call es1.compute(newInput);.

    But your matrix appears to be selfadjoint (at least your eigenvector matrix is unitary), so you probably should prefer using the SelfAdjointEigenSolver. If your matrix also happens to be known at compile time to have size 3x3, you can even write the much more efficient:

    Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> es1;
    es1.computeDirect(MatrixYukawaUpQuark);