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?
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.
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)