Why some eigen vector signs from C++ Armadillo are

2020-05-07 04:42发布

问题:

I was wondering why the sign of the elements in the eigen vectors from Armadillo is the opposite from other languages like Python (i.e. numpy) and R.

For example:

C++

using namespace arma;

vec eigval;
mat eigvec;

// C++11 initialization
mat A = { 1, -1, 0, -1, 2, -1, 0, -1, 1};

eig_sym(eigval, eigvec, A);
eigvec.print("Eigen Vectors");

Output

Eigen Vectors
-5.7735e-01  -7.071068e-01  0.4082483
-5.7735e-01  9.714451e-e17  -0.8164966
-5.7735e-01  7.017068e-01   0.4082483

Python

import numpy as np
w,v = np.linalg.eig(np.array([[1,-1,0],[-1,2,-1],[0,-1,1]]))
v 

Output

array([[ -4.08248290e-01,  -7.07106781e-01,   5.77350269e-01],
       [  8.16496581e-01,   2.61214948e-16,   5.77350269e-01],
       [ -4.08248290e-01,   7.07106781e-01,   5.77350269e-01]])

R

eigen(matrix(c(1,-1,0,-1,2,-1,0,-1,1), 3, byrow=TRUE)$vectors

Output

-4.082483e-01  -7.071068e-01   5.773503e-01
 8.164966e-01   9.420555e-16   5.773503e-01
-4.082483e-01   7.071068e-01   5.773503e-01

You can see that Python and R provide the same eigen vectors (excluding rounding errors). The armadillo result does provide the same numbers (the order is a simple fix) but the sign on the first and third columns are opposite from the corresponding columns in Python and R. Am I overlooking something here?

回答1:

That is answered by help(eigen) in R:

Value:

     The spectral decomposition of ‘x’ is returned as components of a
     list with components

  values: a vector containing the p eigenvalues of ‘x’, sorted in
          _decreasing_ order, according to ‘Mod(values)’ in the
          asymmetric case when they might be complex (even for real
          matrices).  For real asymmetric matrices the vector will be
          complex only if complex conjugate pairs of eigenvalues are
          detected.

 vectors: either a p * p matrix whose columns contain the eigenvectors
          of ‘x’, or ‘NULL’ if ‘only.values’ is ‘TRUE’.  The vectors
          are normalized to unit length.

          Recall that the eigenvectors are only defined up to a
          constant: even when the length is specified they are still
          only defined up to a scalar of modulus one (the sign for real
          matrices).

So the sign is a 'free' parameter, and the result is truly equivalent. If it were me, I'd follow R and Python but Conrad generally knows what he is doing.



回答2:

you don't use the good fucntion (your function is for symetric Martix)

A << 1. << -1. << 0. <<endr
  << -1. << 2. << -1. <<endr
  <<  0. << -1. << 1. <<endr;

A.print("A :");
eig_gen(eigval, eigvec, A);
eigval.print("eigval");
eigvec.print("eigvec");

and the OutPut :

A :
   1.0000  -1.0000        0
  -1.0000   2.0000  -1.0000
        0  -1.0000   1.0000
eigval
    (+3.000e+00,+0.000e+00)
    (+1.000e+00,+0.000e+00)
    (-3.368e-17,+0.000e+00)
eigvec
   (-4.082e-01,+0.000e+00)    (-7.071e-01,+0.000e+00)    (+5.774e-01,+0.000e+00)
   (+8.165e-01,+0.000e+00)    (+2.612e-16,+0.000e+00)    (+5.774e-01,+0.000e+00)
   (-4.082e-01,+0.000e+00)    (+7.071e-01,+0.000e+00)    (+5.774e-01,+0.000e+00)