How to compute the eigenvalues and the eigenvectors of a nonsymmetric matrix?

Motivation

The eigensystem of a real symmetric matrix is computed by using QR decomposition, for instance. However, we sometime need to compute the eigensystem of a real (complex) nonsymmetric matrix.

Solution

Use "eigen3/Eigen/Eigenvalues".

See also Eigenvalues module.

Details

Example 1

Let us compute a nonsymmetric matrix A:
(0 2)
(1 0)

eigensystem.cpp
  #include <eigen3/Eigen/Eigenvalues> // header file
  #include <iostream>

  int main(){
  Eigen::Matrix<double, 2, 2> A; // declare a real (double) 2x2 matrix
  A << 0, 2, 1, 0; // defined the matrix A

  Eigen::EigenSolver<Eigen::Matrix<double, 2,2> > s(A); // the instance s(A) includes the eigensystem
  std::cout << A << std::endl;
  std::cout << "eigenvalues:" << std::endl;
  std::cout << s.eigenvalues() << std::endl;
  std::cout << "eigenvectors=" << std::endl;
  std::cout << s.eigenvectors() << std::endl;

  return(0);
}

On Ubuntu 14.04, the header file should be included as <eigen3/Eigen/Eigenvalues>, but "eigen3" may be skipped in other platforms as <Eigen/Eigenvalues>.

The definition of the matrix A is also expressed as the normal matrix as

eigensystem.cpp
  #include <eigen3/Eigen/Eigenvalues> // header file
  #include <iostream>

  int main(){
  Eigen::Matrix<double, 2, 2> A; // declare a real (double) 2x2 matrix
  A(0,0) = 0.0;
  A(0,1) = 2.0;
  A(1,0) = 1.0;
  A(1,1) = 0.0;

  Eigen::EigenSolver<Eigen::Matrix<double, 2,2> > s(A);  // the instance s(A) includes the eigensystem
  std::cout << A << std::endl;
  std::cout << "eigenvalues:" << std::endl;
  std::cout << s.eigenvalues() << std::endl;
  std::cout << "eigenvectors=" << std::endl;
  std::cout << s.eigenvectors() << std::endl;
l;

  return(0);
}

Then, compile the source file and execute.

prompt> c++ eigensystem.cpp -o eigensystem
prompt> ./eigensystem
0 2
1 0
eigenvalues:
(1.41421,0)
(-1.41421,0)
eigenvectors:
(0.816497,0) (-0.816497,0)
(0.57735,0) (0.57735,0)

The 1st and 2nd arguments of each (.,.) are the real and imaginary parts. Thus, the eigenvalues and the corresponding eigenvectors are:
Eigenvalue Eigenvector
1.41421 (0.816497,0.57735)
-1.41421 (-0.816497,0.57735)

Note: The eigenvectors are neither (0.816497,-0.816497) nor (0.57735,0.57735) !

Example 2

Using the same source with a small modification, we can compute the eigensystem for a nonsymmetric complex-eigenvalued matrix A:
(0 1)
(-1 0)

prompt> c++ eigensystem.cpp -o eigensystem
prompt> ./eigensystem
0 1
-1 0
eigenvalues:
(0,1)
(0,-1)
eigenvectors:
(0.707107,0) (0.707107,0)
(0,0.707107) (0,-0.707107)

Eigenvalue Eigenvector
i (0.707107, i*0.707107) ~ (1,i)
-i (0.707107, -i*0.707107) ~ (1,-i)
where i=sqrt(-1) and we omitted the normalization of the eigenvectors.

Example 3

The eigensystem of a complex matrix is also computed, but with "ComplexEigenSolver". Let us compute a nonsymmetric matrix A:
(0 i)
(-i 0)

eigensystemC.cpp
  #include <eigen3/Eigen/Eigenvalues> // header file
  #include <complex>
  #include <iostream>

  int main(){
  std::complex<double> I(0.0, 1.0); // imaginary unit
  Eigen::Matrix<std::complex<double>, 2, 2> A; // declare a real (double) 2x2 matrix
  A << 0.0, I, -I, 0.0; // defined the matrix A

  Eigen::ComplexEigenSolver<Eigen::Matrix<std::complex<double>, 2,2> > s(A);  // the instance s(A) includes the eigensystem
  std::cout << A << std::endl;
  std::cout << "eigenvalues:" << std::endl;
  std::cout << s.eigenvalues() << std::endl;
  std::cout << "eigenvectors=" << std::endl;
  std::cout << s.eigenvectors() << std::endl;

  return(0);
}

prompt> c++ eigensystemC.cpp -o eigensystemC
prompt> ./eigensystemC
(0,0) (0,1)
(-0,-1) (0,0)
eigenvalues:
(1,0)
(-1,0)
eigenvectors:
(0.707107,0) (0.707107,0)
(0,-0.707107) (0,0.707107)

Eigenvalue Eigenvector
1 (0.707107,-i*0.707107) ~ (1,-i)
-1 (0.707107,i*0.707107) ~ (1,i)

Other manipulation

The real and imaginary parts can be extracted by using real() and imag().

eigensystemC.cpp
  #include <eigen3/Eigen/Eigenvalues> // header file
  #include <complex>
  #include <iostream>

  int main(){
  std::complex<double> I(0.0, 1.0); // imaginary unit
  Eigen::Matrix<std::complex<double>, 2, 2> A; // declare a real (double) 2x2 matrix
  A << 0.0, I, -I, 0.0; // defined the matrix A

  Eigen::ComplexEigenSolver<Eigen::Matrix<std::complex<double>, 2,2> > s(A);  // the instance s(A) includes the eigensystem
  std::cout << "The 1st eigenvalue and eigenvector" << std::endl;
  std::cout << real(s.eigenvalues()(0)) << " " << imag(s.eigenvalues()(0)) << std::endl;
  std::cout << real(s.eigenvectors()(0,0)) << " " << imag(s.eigenvectors()(0,0)) << std::endl;
  std::cout << real(s.eigenvectors()(1,0)) << " " << imag(s.eigenvectors()(1,0)) << std::endl;

  std::cout << "The 2nd eigenvalue and eigenvector" << std::endl;
  std::cout << real(s.eigenvalues()(1)) << " " << imag(s.eigenvalues()(1)) << std::endl;
  std::cout << real(s.eigenvectors()(0,1)) << " " << imag(s.eigenvectors()(0,1)) << std::endl;
  std::cout << real(s.eigenvectors()(1,1)) << " " << imag(s.eigenvectors()(1,1)) << std::endl;

  return(0);
}

The result is as follows:

prompt> c++ eigensystemC.cpp -o eigensystemC
prompt> ./eigensystemC
The 1st eigenvalue and eigenvector
1 0
0.707107 0
0 -0.707107
The 2nd eigenvalue and eigenvector
-1 0
0.707107 0
0 0.707107

Last modified: Thu Aug 17 16:20:35 JST 2017