Diagonalizing Matrix in Matlab Gives "Wrong" Linear Combination of Eigenvectors - matlab

In Matlab, I'm trying to solve for the energies and eigenstates of a Hamiltonian matrix which has a highly degenerate set of eigenvectors. The matrix is a 55x55 hermitian matrix, and when I call either eig or schur to do the diagonalization I find that some (but not all) of the eigenvectors are the "wrong" linear combinations within each degenerate subspace. What I mean by "wrong" is that there are additional constraints in the problem. In this case, there is a good quantum number, M, which I want to preserve by not allowing states with different M values to be mixed--- but that mixing is exactly what I see when I run the code. Is there a way to tell Matlab to diagonalize the matrix while simultaneously maintaining the eigenvectors of another operator?

you can use diag to diagonalize a matrix and [eig_vect,eig_val] = eig(A) to give you eigenvectors.

I don't know matlab well enough to know whether there is a routine for this this, but here's how to do it algorithmically:
First diagonalise H, as you do now. Then for each degenerate eigen-space V, diagonalise the restriction of C to V, and use this diagonalisation to compute simulaneous diagonalisations of C and H
In more detail:
I assume you have an operator C that commutes with your Hamiltonian H. If V is the eigen-space of H for a particular (degenerate) eigen value, and you have a basis x[1] .. x[n] of V , then for each i, Cx[i] must be in V, and so we can expand Cx[i] in terms of the x[], and get a matrix representation C^ of the restriction of C to V, that is we compute
C^[k,j] = <x[k]|C*x[j]> k,j =1 .. n
Diagonalise the matrix C^, getting
C^ = U*D*U*
Then for each row (r1,..rn) of U* we can form
chi = Sum{ j | r[j]*x[j]}
A little algebra shows that this is an eigenvector of C, and also of H

Related

Simultaneous diagonalization in Matlab

Crossposted and answered on MathOverflow. The generalised diagonalisation of two matrices A and B can be done in Matlab via
[V,D] = eig(A,B);
where the columns of V are a the generalised eigenvectors for A and B, while D is a diagonal matrix containing the corresponding generalised eigenvalues (A,B).
Assuming that V are also standard eigenvectors for both A and B, my goal is to compute the respective eigenvalues (i.e. in the same order of the eigenvectors in V) of A and B. I could do this via
eigA = V\A*V;
eigB = V\B*V;
However, is there a simpler way to achieve this, i.e. without having to compute the inverse of V as in the snippet above?

how does Matlab normalize generalized eigenvectors?

I know that the eigenvectors produced by eig(A) have 2-norm 1. But what about the vectors produced in the generalized eigenvalue problem eig(A,B)? A natural conjecture is that such a vector v should satisfy v'Bv=1. When B is the identity matrix, then v'Bv is exactly the square of the 2-norm. I ran the following test for various matrices A and B:
[p,d]=eig(A,B);
v=p(:,1);
v'*B*v
I always choose B to be diagonal. I noticed that v'Bv is not always 1. However, it is indeed 1 when A is symmetric. Does anyone know the rule for the way that Matlab normalizes the generalized eigenvectors? I can't find it in the document.
According to the documentation (emphasis mine):
The form and normalization of V depends on the combination of input arguments:
[...]
[V,D] = eig(A,B) and [V,D] = eig(A,B,algorithm) returns V as a matrix whose columns are the generalized right eigenvectors that satisfy A*V = B*V*D. The 2-norm of each eigenvector is not necessarily 1. In this case, D contains the generalized eigenvalues of the pair, (A,B), along the main diagonal.
When eig uses the 'chol' algorithm with symmetric (Hermitian) A and symmetric (Hermitian) positive definite B, it normalizes the eigenvectors in V so that the B-norm of each is 1.
This means that, unless you are using the 'chol' algorithm, V is not normalized.
If I get you correctly, you are looking for a way to generalize a vector then given a vector you can divide it by its norm to obtain a secondary vector whose norm is 1.
If you are looking for the mathematical background, then Eigendecomposition of a matrix contains a good introduction.

How to solve A*X - X*A' = 0

I have an equation of the form A*X = X*A', where A and X are real, square matrices (3x3 in that case) and A is known and A' represent the transpose of A. How to solve for X using MATLAB? (up to a scale factor)
This is a Sylvester equation. However, it is singular because the eigenvalues of A and A' are the same. But you can use the formulae
[I⊗A-A'⊗I]X(:)=C(:):
m=kron(eye(3),a)+kron(-a,eye(3))
v=null(m)
x1=reshape(v(:,1),[3 3])
x2=reshape(v(:,2),[3 3])
x3=reshape(v(:,3),[3 3])
Now the solution is span{x1,x2,x2}, i.e. any matrix of the form
b x1 + c x2 +d x3, where b,c,d are any real numbers
I don't think Matlab has facilities for symbolic algebra.
If you expand A and X, and work through the expression, you obtain an 3x3 matrix with equation in several unknowns, all of which are zero. You then solve that.
But I don't think Matlab allows you to set a matrix to a symbol, rather than an value and expand it for you. For this simple case, you could easily write such a function, that multiples a string matrix by a numerical matrix. The snag is it's hard to scale it up to the general case without throwing the entire Maple / Mathematica engine at it.

fft matrix-vector multiplication

I have to solve in MATLAB a linear system of equations A*x=B where A is symmetric and its elements depend on the difference of the indices: Aij=f(i-j).
I use iterative solvers because the size of A is say 40000x40000. The iterative solvers require to determine the product A*x where x is the test solution. The evaluation of this product turns out to be a convolution and therefore can be done dy means of fast fourier transforms (cputime ~ Nlog(N) instead of N^2). I have the following questions to this problem:
is this convolution circular? Because if it is circular I think that I have to use a specific indexing for the new matrices to take the fft. Is that right?
I find difficult to program the routine for the fft because I cannot understand the indexing I should use. Is there any ready routine which I can use to evaluate by fft directly the product A*x and not the convolution? Actually, the matrix A is constructed of 3x3 blocks and is symmetric. A ready routine for the product A*x would be the best solution for me.
In case that there is no ready routine, could you give me an idea by example how I could construct this routine to evaluate a matrix-vector product by fft?
Thank you in advance,
Panos
Very good and interesting question! :)
For certain special matrix structures, the Ax = b problem can be solved very quickly.
Circulant matrices.
Matrices corresponding to cyclic convolution Ax = h*x (* - is convolution symbol) are diagonalized in
the Fourier domain, and can be solved by:
x = ifft(fft(b)./fft(h));
Triangular and banded.
Triangular matrices and diagonally-dominant banded matrices are solved
efficiently by sparse LU factorization:
[L,U] = lu(sparse(A)); x = U\(L\b);
Poisson problem.
If A is a finite difference approximation of the Laplacian, the problem is efficiently solved by multigrid methods (e.g., web search for "matlab multigrid").
Interesting question!
The convolution is not circular in your case, unless you impose additional conditions. For example, A(1,3) should equal A(2,1), etc.
You could do it with conv (retaining only the non-zero-padded part with option valid), which probably is also N*log(N). For example, let
A = [a b c d
e a b c
f e a b
g f e a];
Then A*x is the same as
conv(fliplr([g f e a b c d]),x,'valid').'
Or more generally, A*x is the same as
conv(fliplr([A(end,1:end-1) A(1,:)]),x,'valid').'
I'd like to add some comments on Pio_Koon's answer.
First of all, I wouldn't advise to follow the suggestion for triangular and banded matrices. The time taken by a call to Matlab's lu() procedure on a large sparse matrix massively overshadows any benefits gained by solving the linear system as x=U\(L\b).
Second, in the Poisson problem you end up with a circulant matrix, therefore you can solve it using the FFT as described. In this specific case, your convolution mask h is a Laplacian, i.e., h=[0 -0.25 0; -0.25 1 -0.25; 0 -0.25 0].

How do I draw samples from multivariate gaussian distribution parameterized by precision in matlab

I am wondering how to draw samples in matlab, where I have precision matrix and mean as the input argument.
I know mvnrnd is a typical way to do so, but it requires the covariance matrix (i.e inverse of precision)) as the argument.
I only have precision matrix, and due to the computational issue, I can't invert my precision matrix, since it will take too long (my dimension is about 2000*2000)
Good question. Note that you can generate samples from a multivariant normal distribution using samples from the standard normal distribution by way of the procedure described in the relevant Wikipedia article.
Basically, this boils down to evaluating A*z + mu where z is a vector of independent random variables sampled from the standard normal distribution, mu is a vector of means, and A*A' = Sigma is the covariance matrix. Since you have the inverse of the latter quantity, i.e. inv(Sigma), you can probably do a Cholesky decomposition (see chol) to determine the inverse of A. You then need to evaluate A * z. If you only know inv(A) this can still be done without performing a matrix inverse by instead solving a linear system (e.g. via the backslash operator).
The Cholesky decomposition might still be problematic for you, but I hope this helps.
If you want to sample from N(μ,Q-1) and only Q is available, you can take the Cholesky factorization of Q, L, such that LLT=Q. Next take the inverse of LT, L-T, and sample Z from a standard normal distribution N(0, I).
Considering that L-T is an upper triangular dxd matrix and Z is a d-dimensional column vector,
μ + L-TZ will be distributed as N(μ, Q-1).
If you wish to avoid taking the inverse of L, you can instead solve the triangular system of equations LTv=Z by back substitution. μ+v will then be distributed as N(μ, Q-1).
Some illustrative matlab code:
% make a 2x2 covariance matrix and a mean vector
covm = [3 0.4*(sqrt(3*7)); 0.4*(sqrt(3*7)) 7];
mu = [100; 2];
% Get the precision matrix
Q = inv(covm);
%take the Cholesky decomposition of Q (chol in matlab already returns the upper triangular factor)
L = chol(Q);
%draw 2000 samples from a standard bivariate normal distribution
Z = normrnd(0,1, [2, 2000]);
%solve the system and add the mean
X = repmat(mu, 1, 2000)+L\Z;
%check the result
mean(X')
var(X')
corrcoef(X')
% compare to the sampling from the covariance matrix
Y=mvnrnd(mu,covm, 2000)';
mean(Y')
var(Y')
corrcoef(Y')
scatter(X(1,:), X(2,:),'b')
hold on
scatter(Y(1,:), Y(2,:), 'r')
For more efficiency, I guess you can search for some package that efficiently solves triangular systems.