Minimize matrix-difference subject to block-diagonal constraints - matlab

I have a matrix W which is a block diagonal matrix with dimensions 2*4, and each of its two block diagonals is 1*2 vector. I want to find the values of its entries that minimize the difference between the following function:
( F = BH-AW )
Where: W is the required block diagonal matrix to be optimized, B is a 2*2 matrix, H is a given 2*4 matrix, and A is a 2*2 matrix. A and B are calculated using the functions used in the attached code.
I tried this attached code, but I think it is now in an infinite loop and I don't know what should I do?
%% My code is:
while ((B*H)-(A*W)~=zeros(2,4))
w1=randn(1,2);
% generate the first block diagonal vector with dimensions 1*2. The values of each entry of the block diagonal vector maybe not the same.
w2=randn(1,2);
% generate the second block diagonal vector with dimensions 1*2.
W=blkdiag(w1,w2);
% build the block diagonal matrix that I want to optimize with dimensions 2*4.
R=sqrtm(W*inv(inv(P)+(H'*inv(eye(2)+D)*H))*W');
% R is a 2*2 matrix that will be used to calculate matrix A using the LLL lattice reduction algorithm. The values of P (4*4 matrix), H (2*4 matrix) and D (2*2 matrix) are given. It's clear here that matrix R is a function of W.
A= LLL(R,3/4);
% I use here LLL lattice reduction algorithm to obtain 2*2 matrix A which is function of R.
B=A'*W*P*H'*inv(eye(2)+D+H*P*H');
% B is 2*2 matrix which is function of A and W. The values of P (4*4 matrix), H (2*4 matrix) and D (2*2 matrix) are given.
end

Numerical operations with floating point numbers are only approximate on a computer (any number is only ever represented with a finite number of bits, which means you cannot exactly represent Pi for example). For more info, see this link.
Consequently, it is extremely unlikely that the loop you wrote will ever terminate, because the difference between B*H and A*W will not be exactly zero. Instead, you need to use a tolerance factor to decide when you are satisfied with the similarity achieved.
Additionally, as suggested by others in comment, the "distance" between two matrices is typically measured using some sort of norm (e.g. the Frobenius norm). By default, the norm function in Matlab will give the 2-norm of an input matrix.
In your case, this would give something like:
tol = 1e-6;
while norm(B*H-A*W) > tol
% generate the first block diagonal vector with dimensions 1*2.
% The values of each entry of the block diagonal vector maybe not the same.
w1=randn(1,2);
% generate the second block diagonal vector with dimensions 1*2.
w2=randn(1,2);
% build the block diagonal matrix that I want to optimize with dimensions 2*4.
W=blkdiag(w1,w2);
% R is a 2*2 matrix that will be used to calculate matrix A using the LLL lattice reduction algorithm.
% The values of P (4*4 matrix), H (2*4 matrix) and D (2*2 matrix) are given.
% It's clear here that matrix R is a function of W.
R=sqrtm(W/(inv(P)+(H'/(eye(2)+D)*H))*W');
% I use here LLL lattice reduction algorithm to obtain 2*2 matrix A which is function of R.
A= LLL(R,3/4);
% B is 2*2 matrix which is function of A and W. The values of P (4*4 matrix),
% H (2*4 matrix) and D (2*2 matrix) are given.
B=A'*W*P*H'/(eye(2)+D+H*P*H');
end
Note that:
With regards to the actual algorithm, I am a little bit concerned that your loop never seems to update the value of W, but instead updates matrices A and B. This suggests that your description of the problem might be incorrect or incomplete, but that is beyond the scope of this forum anyway (ask on Maths.SE if you want to know more).
Using inv() directly is discouraged in many cases. This is because the algorithm to compute the inverse of a matrix is less reliable than the algorithm to solve systems of the type AX=B. Matlab should give you a warning to use / and \ where possible; I would advise following this recommendation unless you know what you are doing.

Related

How would you do this matrix operation in MATLAB?

Given two random variables X and Y, where X=(x1,..,xn) and Y=(y1,...,yn) in a nx2 matrix A, so A=[X Y], i need to perform the next operation:
median((x-median(x))(y-median(y)))
I'm trying to obtain an estimator of the covariance matrix using the median instead the mean, for a nxt matrix where t represents the number of random variables and n the length of the data set.
So far, I made the next code:
for i=1:n
for j=1:n
a1=median(A(:,i));
a2=median(A(:,j));
SMM(i,j)=median(((A(:,i)-a1(ones(t,1),:)).*(A(:,j)-a2(ones(t,1),:))));
end
end
However, theoretically I must obtain a semidefinite (positive or negative) symmetric matrix, however that's not the case with this code.
Am I making any mistake in the code formulation?
Various points:
For each of your columns of A (x, y), the median (a1, a2) doesn't change. You should compute these outside the loops.
The loops go over n, rather than t, which are the variables and the indices to the output matrix.
I would first subtract the median from each column, to avoid repeatedly doing the same computations:
A = A - median(A,1); % be explicit about which dimension to take the median over!
Next, we'd loop over the txt output elements of the covariance matrix, and compute each of the elements:
t = size(A,2);
SMM = zeros(t,t); % always preallocate output arrays before a loop
for j=1:t
for i=1:t
SMM(i,j) = median(A(:,i).*A(:,j));
end
end
The loop can likely be vectorized, but that leads to a large intermediate matrix, which slow down code also. So it might not be worth the effort to vectorize. Only try it if this code is too slow!
It should also be possible to run the inner loop from i=j:t, to skip computing the redundant half of the symmetric matrix, instead copying over the previously computed values.

How to simulate random point following multivariate t distribution?

If X is a multivariate t random variable with mean=[1,2,3,4,5] and a covariance matrix C, how to simulate points in matlab? I try mvtrnd in matlab, but clearly the sample mean does not give mean close to [1,2,3,4,5]. Also, when I test three simple examples, say X1 with mean 0 and C1=[1,0.3;0.3,1], X2 with mean 0 and C2=[0.5,0.15;0.15,0.5] and X3 with mean 0 and C3=[0.4,0.12;0.12,0.4] and use mvtrnd(C1,3,1000000), mvtrnd(C2,3,1000000) amd mvtrnd(C2,3,1000000) respectively, I find the sample points in each case give nearly the correlation matrix [1,0.3;0.3,1] but the sample covariance computed all give near [3,1;1,3]. Why and how to fix it?
The Mean
The t distribution has a zero mean unless you shift it. In the documentation for mvtrnd:
the distribution of t is that of a vector having a multivariate normal
distribution with mean 0, variance 1, and covariance matrix C, divided
by an independent chi-square random value having df degrees of
freedom.
Indeed, mean(X) will approach [0 0] for X = mvtrnd(C,df,n); as n gets larger.
The Correlation
Matching the correlation is straightforward as it addresses a part of the relationship between the two dimensions of X.
% MATLAB 2018b
df = 5; % degrees of freedom
C = [0.44 0.25; 0.25 0.44]; % covariance matrix
numSamples = 1000;
R = corrcov(C); % Convert covariance to correlation matrix
X = mvtrnd(R,df,numSamples); % X ~ multivariate t distribution
You can compare how well you matched the correlation matrix R using corrcoef or corr().
corrcoef(X) % Alternatively, use corr(X)
The Covariance
Matching the covariance is another matter. Admittedly, calling cov(X) will reveal that this is lacking. Recall that the diagonal of the covariance is the variance for the two components of X. My intuition is that we fixed the degrees of freedom df, so there is no way to match the desired variance (& covariance).
A useful function is corrcov which converts a covariance matrix into a correlation matrix.
Notice that this is unnecessary as the documentation for mvtrnd indicates
C must be a square, symmetric and positive definite matrix. If its
diagonal elements are not all 1 (that is, if C is a covariance matrix
rather than a correlation matrix), mvtrnd rescales C to transform it
to a correlation matrix before generating the random numbers.

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

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

Given LUP decomposition of a matrix, how to find determinant in MATLAB?

I want to compute the determinant of a matrix from its LUP decomposition in MATLAB. The determinant can be found from the formula:
P is a permutation matrix and S is the number of exchanges of rows needed to transform P into an identity matrix. How can I find S in the above formula in MATLAB? Does it have any pre-defined functions, etc.?
If you interpret P as an adjacency matrix, and the vector cycles contains the length of all cycles in the graph described by P, then S=sum(cycles) - length(cycles).
Now all is left is to find the length of all the cycles, for which there are several functions on the File Exchange, like this one.
BTW: [L, U, P] = lu(A), and det(A) = det(inv(P))*det(L)*det(U)

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.