Bivariate mvncdf for a matrix with different covariance matrices (Matlab) - matlab

I want to do the following:
for i = 1:N
l(i) = mvncdf(x(i,:), mu, sigma(:,:,i))
end
Can I do it without a loop given that a covariance matrix is different for each row of x?

Sure. Try this:
func = #(i) mvncdf(x(i,:), mu, sigma(:,:,i));
l = arrayfun(func, 1:N)
This is a neat puzzle-type question, but I'd say that your code with a loop is much more readable and probably just as fast.

Related

Hessenberg matrix with householder transformation on Hermitian matrix

I have written a program to find a Hessenberg matrix who's orthogonal equivalent with a matrix A using householder transformations. The program works fine until I start using Hermitian matrices. Normally, when using hermitian matrices, the hessenberg matrix should be tridiagonal but mine only has zeros at some places of the first row (and of course below the subdiagonal). Can anyone help me?
My householder function is defined as:
function [H,Q]=householder(A)
[m,n] = size(A);
Q=eye(n);
for k = 1:n-2
x=A(k+1:n,k);
[sz,szz] = size(x);
e_k = zeros(sz,1);
e_k(1)=1;
u = (x+sign(x(1))*norm(x)*e_k)/(norm(x+sign(x(1))*norm(x)*e_k));
I=eye(sz);
P=I-2*(u)*(u');
Q_temp=blkdiag(eye(k),P);
Q=Q_temp*Q;
A=(Q_temp')*A*(Q_temp);
end
H=A;
end
I make a random Hermitian matrix:
function RHM=RandomHermitianMatrix(n)
A=complex(rand(n,n),(rand(n,n)*2)-1);
for k=1:n-1
vct=diag(A,k);
for l=1:n-k
A(l+k,l)=conj(vct(l));
end
end
RHM=A;
end
I test it using:
function message = test_householder_hermitian(n)
tic;
tst=RandomHermitianMatrix(n)
tstt=householder(tst)
toc
message='done';
end
Thanks a lot!

how to vectorze this kind of loop for array

I'm newbie to Matlab. I have some questions.
How can I vectorise this loop:
epsilon = 0.45;
t = -3.033;
n = 100;
I = ones(n,n);
%// diagonal block 1
DB1 = gallery('tridiag',ones(1,n-1),ones(1,n),ones(1,n-1));
for k = 1:n
DB1(k,k) = epsilon;
end
for k = 1:n-1
DB1(k,k+1) = t*heaviside((-1)^(k+1));
end
for k = 2:n
DB1(k,k-1) = t*heaviside((-1)^k);
and this loop with LRG, R2, R1 are 3D arrays
for k = 2:N
LRG(:,:,k) = inv(R(:,:,k) - R2(:,:,k-1)*LRG(:,:,k-1)*R1(:,:,k-1));
end
Is there any way to handle the third dimension of an array (page) without writing (:,:,...) many times?
You don't need to call gallery: this will just initialize DB1 to a specific sparse tridiagonal matrix, which you manually overwrite afterwards. With n=100, I suspect that you don't actually want to work on sparse matrices. Here's the solution:
epsilon = 0.45; t = -3.033;
n = 100;
DB1 = zeros(n); %initialize to 0
%diagonal indices
inds=sub2ind([n n],1:n,1:n);
DB1(inds) = epsilon;
%superdiagonal
inds=sub2ind([n n],1:n-1,2:n);
DB1(inds) = t*heaviside((-1).^(2:n));
%subdiagonal
inds=sub2ind([n n],2:n,1:n-1);
DB1(inds) = t*heaviside((-1).^(2:n));
Here sub2ind lets you compute linear indices from your matrix indices, allowing you to access "subvectors" in your matrix. Watch out for the exponentialization in the heaviside: you need .^ instead of ^ to perform an element-wise operation using the vector 2:n.
If you insist on getting a sparse matrix, you could either convert this matrix to sparse by calling
DB1=sparse(DB1);
which is the easiest option if your matrix is small. If n was larger and you would really need sparse matrices, then you could set up the sparse matrix itself by
DB1new=sparse([1:n 1:n-1 2:n],[1:n 2:n 1:n-1],...
[epsilon*ones(1,n) t*heaviside((-1).^(2:n)) t*heaviside((-1).^(2:n))],n,n);
This call sets the elements of DB1new one-by-one according to its vector arguments: it takes the first index from the first input argument, the seconf index from the second, and the corresponding element from the third vector (see help sparse in MATLAB).
As for your second question: I'm not sure I understand correctly. Like in my example, sub2ind can be used to transform the multidimensional indices into linear ones, see help sub2ind. But personally, I think using the array notation is far more transparent and less prone to typos. And I think you can't vectorize that loop: you have to explicitly calculate the inverse matrix for each k.

Evaluate all pairs of matrices

I have a function f which takes 2 matrices with the same number of rows and procudes a scalar value. A am now looking for a possibility to create a new function which takes two lists of matrices and calls f for all pairs.
I need a moore efficient implementation of this loop:
% X = cell of matrices
% Y = cell of matrices
for k=1:length(X)
for l=1:length(Y)
M(k,l) = f(X{k},Y{l});
end
end
(It is not a requirement that X and Y are cells)
For example f could be the mean of squared distances
f = #(X,Y) mean(mean(bsxfun(#plus,dot(X,X,1)',dot(Y,Y,1))-2*(X'*Y)));
but don't question f, it is just an example of a much more complicated problem.
Firstly you should be pre-allocating M. Then you can cut out one loop quite easily by using meshgrid to generate a list of all pairs of elements in X and Y:
[K, L] = meshgrid(1:length(X), 1:length(Y));
M = zeros(size(K)); %//This preallocation alone should give you a significant speed up
for ii = 1:numel(K)
M(ii) = f(X{K(ii)},Y{L(ii)});
end
However, if you can implement f so that it is properly vectorized, you might be able to pass it two 3D matrices, i.e. the entire list of X and Y pairs and do it without a loop at all. But this depends entirely on what it is that your f does.
On possible solution that works is using cellfun
fy = #(x,Y) cellfun(#(y) f(x,y), Y);
fx = #(X,Y) cellfun(#(x) fy(x,Y), X, 'UniformOutput', false);
newF = #(X,Y) cell2mat(fx(X,Y)')';
however I suppose there is a better way to do this.

Calculating the covariance of a 1000 5x5 matrices in matlab

I have a 1000 5x5 matrices (Xm) like this:
Each $(x_ij)m$ is a point estimate drawn from a distribution. I'd like to calculate the covariance cov of each $x{ij}$, where i=1..n, and j=1..n in the direction of the red arrow.
For example the variance of $X_m$ is `var(X,0,3) which gives a 5x5 matrix of variances. Can I calculate the covariance in the same way?
Attempt at answer
So far I've done this:
for m=1:1000
Xm_new(m,:)=reshape(Xm(:,:,m)',25,1);
end
cov(Xm_new)
spy(Xm_new) gives me this unusual looking sparse matrix:
If you look at cov (edit cov in the command window) you might see why it doesn't support multi-dimensional arrays. It perform a transpose and a matrix multiplication of the input matrices: xc' * xc. Both operations don't support multi-dimensional arrays and I guess whoever wrote the function decided not to do the work to generalize it (it still might be good to contact the Mathworks however and make a feature request).
In your case, if we take the basic code from cov and make a few assumptions, we can write a covariance function M-file the supports 3-D arrays:
function x = cov3d(x)
% Based on Matlab's cov, version 5.16.4.10
[m,n,p] = size(x);
if m == 1
x = zeros(n,n,p,class(x));
else
x = bsxfun(#minus,x,sum(x,1)/m);
for i = 1:p
xi = x(:,:,i);
x(:,:,i) = xi'*xi;
end
x = x/(m-1);
end
Note that this simple code assumes that x is a series of 2-D matrices stacked up along the third dimension. And the normalization flag is 0, the default in cov. It could be exapnded to multiple dimensions like var with a bit of work. In my timings, it's over 10 times faster than a function that calls cov(x(:,:,i)) in a for loop.
Yes, I used a for loop. There may or may not be faster ways to do this, but in this case for loops are going to be faster than most schemes, especially when the size of your array is not known a priori.
The answer below also works for a rectangular matrix xi=x(:,:,i)
function xy = cov3d(x)
[m,n,p] = size(x);
if m == 1
x = zeros(n,n,p,class(x));
else
xc = bsxfun(#minus,x,sum(x,1)/m);
for i = 1:p
xci = xc(:,:,i);
xy(:,:,i) = xci'*xci;
end
xy = xy/(m-1);
end
My answer is very similar to horchler, however horchler's code does not work with rectangular matrices xi (whose dimensions are different from xi'*xi dimensions).

Matlab: determinant of a matrix of vectors

I have a 2x2 matrix, each element of which is a 1x5 vector. something like this:
x = 1:5;
A = [ x x.^2; x.^2 x];
Now I want to find the determinant, but this happens
B = det(A);
Error using det
Matrix must be square.
Now I can see why this happens, MATLAB sees A as a 2x10 matrix of doubles. I want to be able to treat x as an element, not a vector. What I'd like is det(A) = x^2 - x^4, then get B = det(A) as a 1x5 vector.
How do I achieve this?
While Matlab has symbolic facilities, they aren't great. Instead, you really want to vectorize your operation. This can be done in a loop, or you can use ARRAYFUN for the job. It sounds like ARRAYFUN would probably be easier for your problem.
The ARRAYFUN approach:
x = 1:5;
detFunc = #(x) det([ x x^2 ; x^2 x ]);
xDet = arrayfun(detFunc, x)
Which produces:
>> xDet = arrayfun(detFunc, x)
xDet =
0 -12 -72 -240 -600
For a more complex determinant, like your 4x4 case, I would create a separate M-file for the actual function (instead of an anonymous function as I did above), and pass it to ARRAYFUN using a function handle:
xDet = arrayfun(#mFileFunc, x);
Well mathematically a Determinant is only defined for a square matrix. So unless you can provide a square matrix you're not going to be able to use the determinant.
Note I know wikipedia isn't the end all resource. I'm simply providing it as I can't readily provide a print out from my college calculus book.
Update: Possible solution?
x = zeros(2,2,5);
x(1,1,:) = 1:5;
x(1,2,:) = 5:-1:1;
x(2,1,:) = 5:-1:1;
x(2,2,:) = 1:5;
for(n=1:5)
B(n) = det(x(:,:,n));
end
Would something like that work, or are you looking to account for each vector at the same time? This method treats each 'layer' as it's own, but I have a sneaky suspiscion that you're wanting to get a single value as a result.