Finding the orthogonal basis of a symmetric matrix in c++ - c++

I want to find an eigendecomposition of a symmetric matrix, which looks for example like this:
0 2 2 0
2 0 0 2
2 0 0 2
0 2 2 0
It has a degenerate eigenspace in which you obviously have a certain freedom to chose the eigenvectors. Is there a library for c++ which I can force to find the Orthogonal Basis such that H = UDU^{T}?
Currently I'm using the Eigen::SelfAdjointEigenSolver. This gives the "wrong" result as then I have to use H = UDU^{-1}. The Matrices will have dimensions of 10000x10000 later on, because of this I want to omit the additional inversion of the matrix.
Does anyone know of such a thing?

OpenCV has support for this. Though, I don't know if you can use it on matrix 10000x10000 within suitable time/accuracy. I believe the best fit in OpenCV is eigen(...) method.
There is also BLAS C++ linear algebra library but I am not familiar with it.
Also, there is probably an implemetarion of an algorithm for this problem in the book Numerical Recipes.

Related

Reliability of the boost::numeric::ublas::matrix LU inversion method

My Problem : inverse squared matrices of doubles numbers of size 30*30 (or around this size).
I started coding in C++ a LU decomposition method, then I discovered the existence of the librairie boost::numeric::ublas::matrix. Therefore to spare me rewriting everything I used some functions of this librairie, namely in this very order lu_factorize() then lu_substitute() to retrieve the inverse.
I hand-checked the reliability of my inversing function (which again, only use the 2 aforementioned boost functions) comparing the results with simple squared matrices (size 3 or 4) and the results are satisfying so far.
Now taking a (30,30) matrix "A" and inversing it "A^-1", the product "A*A^-1" returns me a matrix with 1 on the diagonale and everywhere else some very small numbers, here's a snippet :
1 -1.5e-16 -5.1e-20 2.4e-19
0 1 0 -5.4e-20
1.1e-16 1.1e-16 1 -1.4e-19
6.9e-17 0 -3.3e-17 1
I cannot tell if these numbers (out of the main diagonale) are made up by the matrix librairie trying to approximate 0 or if they issued from the LU decomposition ...
My question : Have you ever used boost ublas with this issue ? Is this librairie still reliable or outdated ? Is there any way to access the source code of these algorithm ?
Thanks in advance
Using C++11, gcc/8.2.0 and boost/1.76.0.

Is there a fortran solver able to solve the following eigenvalue?

A is an N by N matrix. I is the unit matrix of (N-2) by (N-2). B is another N by N matrix which is defined as
B=[I 0 0;
0 0 0;
0 0 0]
. x is an array with N elements. How can I solve the eigenvalue of the following form
A x=cB x, where c is the eigenvalue,
by using an eigenvalue solver?
You can have a look at the Lapack library, which offers solutions for eigenvalues problems of generalized matrices. Depending on your data type and matrix type you will need to use different subroutines.
Have a look here on this regard. Also have a look here for the nomenclature used as type of matrix.
Finally, sometime ago I wrote this module to give an implementation example of a few Lapack functionalities, including eigenvalue problems. The one you can find there is for a single value generalized matrix (sgeev).

Paralize numpy.linalg.matrix_power do not increase performance

I need to paralize the function numpy.linalg.matrix_power and I use the following code to test how much fast can be the parallel version
def aux_matrix_arg3(A):
aaa=np.linalg.matrix_power(np.random.randn(199,199),100)
return 1
N=10000
processes=4
chunksize=N/processes
poolWorkers=mp.Pool(processes=processes)
ti=t.time()
A=poolWorkers.map(aux_matrix_arg3,range(N),chunksize=chunksize)
print 't_iteration 3',t.time()-ti
I have tried with 1 and 4 processes in my laptop. I got very similar performance
4 processes: t_iteration 3 40.7985408306
1 processes: t_iteration 3 40.6538720131
Any clue why I do not get any improvment with paralle processes?
The docs say:
For positive integers n, the power is computed by repeated matrix squarings and matrix multiplications. If n == 0, the identity matrix of the same shape as M is returned. If n < 0, the inverse is computed and then raised to the abs(n).
If your system is set up correctly, BLAS will be used to parallelize matrix-multiplications and LAPACK (maybe SuperLU, the latter probably only in the sparse-case) for solving systems of linear-equations (used to calculate the inverse). So with a very high probability, your naive code is already very very optimized!
Despite that, you should be careful as naive parallelization copies all the data, which can hurt. (Normaly one would use mmap-arrays to share data instead of copying).

Compute rank of Matrix

I need to calculate rank of 4096x4096 sparse matrix, and I use C/C++ code.
I found some libraries (like Armadillo) that do it but they're too slow (almost 5 minutes).
I've also tried two Open Source version of Matlab (Freemat and Octave) but both crashed when I tried to make a test with a script.
5 minutes isn't so much but I must get rank from something like a million of matrix so the faster the better.
Someone knows a fast library for rank computation?
The Eigen library supports sparse matrices, try it out.
Computing the algebraic rank is O(n^3), where n is the matrix size, so it's inherently slow. You need eg. to perform pivoting, and this is slow and inaccurate if your matrix is not well conditioned (for n = 4096, a typical matrix is very ill conditioned).
Now, what is the rank ? It is the dimension of the image. It is very difficult to compute when n is large and it'll be spoiled by any small numerical inaccuracy of the input. For n = 4096, unless you happen to have particularly well conditioned matrices, this will prevent you from doing anything useful with a pivoting algorithm.
The best way is in fact to fix a cutoff epsilon, compute the singular values s_1 > ... > s_n and take as the rank the lowest integer r such that sum(s_i^2, i > r) < epsilon^2 * sum(s_i^2).
You thus need a sparse SVD routine, eg. from there.
This may not be faster, but to the very least it will be correct.
You can ask for less singular values that you need to speed up things. This is a tough problem, and with no info on the background and how you got these matrices, there is nothing more we can do.
Try the following code (the documentation is here).
It is an example for calculating the rank of the matrix A with Eigen library:
MatrixXd A(2,2);
A << 1 , 0, 1, 0;
FullPivLU<MatrixXd> luA(A);
int rank = luA.rank();

Removing unsolvable equations from an underdetermined system

My program tries to solve a system of linear equations. In order to do that, it assembles matrix coeff_matrix and vector value_vector, and uses Eigen to solve them like:
Eigen::VectorXd sol_vector = coeff_matrix
.colPivHouseholderQr().solve(value_vector);
The problem is that the system can be both over- and under-determined. In the former case, Eigen either gives a correct or uncorrect solution, and I check the solution using coeff_matrix * sol_vector - value_vector.
However, please consider the following system of equations:
a + b - c = 0
c - d = 0
c = 11
- c + d = 0
In this particular case, Eigen solves the three latter equations correctly but also gives solutions for a and b.
What I would like to achieve is that only the equations which have only one solution would be solved, and the remaining ones (the first equation here) would be retained in the system.
In other words, I'm looking for a method to find out which equations can be solved in a given system of equations at the time, and which cannot because there will be more than one solution.
Could you suggest any good way of achieving that?
Edit: please note that in most cases the matrix won't be square. I've added one more row here just to note that over-determination can happen too.
I think what you want to is the singular value decomposition (SVD), which will give you exact what you want. After SVD, "the equations which have only one solution will be solved", and the solution is pseudoinverse. It will also give you the null space (where infinite solutions come from) and left null space (where inconsistency comes from, i.e. no solution).
Based on the SVD comment, I was able to do something like this:
Eigen::FullPivLU<Eigen::MatrixXd> lu = coeff_matrix.fullPivLu();
Eigen::VectorXd sol_vector = lu.solve(value_vector);
Eigen::VectorXd null_vector = lu.kernel().rowwise().sum();
AFAICS, the null_vector rows corresponding to single solutions are 0s while the ones corresponding to non-determinate solutions are 1s. I can reproduce this throughout all my examples with the default treshold Eigen has.
However, I'm not sure if I'm doing something correct or just noticed a random pattern.
What you need is to calculate the determinant of your system. If the determinant is 0, then you have an infinite number of solutions. If the determinant is very small, the solution exists, but I wouldn't trust the solution found by a computer (it will lead to numerical instabilities).
Here is a link to what is the determinant and how to calculate it: http://en.wikipedia.org/wiki/Determinant
Note that Gaussian elimination should also work: http://en.wikipedia.org/wiki/Gaussian_elimination
With this method, you end up with lines of 0s if there are an infinite number of solutions.
Edit
In case the matrix is not square, you first need to extract a square matrix. There are two cases:
You have more variables than equations: then you have either no solution, or an infinite number of them.
You have more equations than variables: in this case, find a square sub-matrix of non-null determinant. Solve for this matrix and check the solution. If the solution doesn't fit, it means you have no solution. If the solution fits, it means the extra equations were linearly-dependant on the extract ones.
In both case, before checking the dimension of the matrix, remove rows and columns with only 0s.
As for the gaussian elimination, it should work directly with non-square matrices. However, this time, you should check that the number of non-empty row (i.e. a row with some non-0 values) is equal to the number of variable. If it's less you have an infinite number of solution, and if it's more, you don't have any solutions.