Create diagonal matrix without using MATLAB built-in functions - matlab

I know the answer to this question as shown below.
function a = reverse_diag(n)
b = zeros(n);
b(1:n+1:end) = 1;
a(1:n, n:-1:1) = b(1:n, 1:n);
end
But why does it look like that? What does this mean?
b(1:n+1:end) = 1;

I seem to recall seeing something similar to this in MATLAB answers very recently, hence I will be brief.
MATLAB arrays can be indexed in 2 relevant ways:
Like A(x,y) using the actual coordinates in the matrix.
Like A(index), no matter how many dimensions the matrix A actually has. This is called linear indexing and will go through the matrix column by column. So for a 10x10 matrix, A(11) is actually A(2,1).
Read up on ind2sub and sub2ind to get a sense of how these work. You should now be able to figure out why that line works.

Related

Matrix multiplication and differences

I need to compute this equation with MATLAB:
where Sn can be both matrices or scalar and I tried to do it with
S_A = S_3*S_5*((ones-(S_1*S_5)).^(-1))*S_2+S_4
The problem is it doesn't give me the right result and the problem it seems to be with the difference but I cannot figure why is giving me wrong results.
The result is supposed to be this one
but the MATLAB result is
I don't understand why the two results are not the same.
The only way that I figured is through this
diff = ones-(S_1*S_5);
if S_1*S_5 == zeros %Perchè senza non funziona?
diff = ones;
else
diff = (ones-(S_1*S_5)).^(-1)
end
S_A = S_3*S_5*diff*S_2+S_4;
But I don't think it's a smart solution. Anyone knows why I'm not getting the correct results?
"I tried to do it with S_A = S_3*S_5*((ones-(S_1*S_5)).^(-1))*S_2+S_4"
The problem here is that A^(-1) in mathematical notation means "take the inverse", whereas you used A. ^(-1), note the dot, which in MATLAB's notation means "take the each matrix element to the power -1". Taking the inverse of a matrix is not smart in MATLAB anyway, be it via inv() or ^(-1), instead, use mldivide:
S_A = S_3*S_5*(eye(size(S_1*S_5,1))-(S_1*S_5))\S_2+S_4
Also, as mentioned in Brice's answer use eye, not ones to create an identity matrix, and feed it a size argument as opposed to nothing. All in all it looks to me like you do not have a firm grasp of basic MATLAB functionality, so I'd like to point you to The MathWorks own tutorial on MATLAB.
ones outputs a matrix filled with ones, not the identitiy matrix which is given by function eye.
You also need to specify the size of ones or eye, otherwise it will simply output a scalar 1 (i.e. a 1-by-1 matrix filled with ones, or the 1-by-1 identity matrix).
Try (assuming all matrices have the same size):
siz=length(S_1);
S_A = S_3*S_5*((eye(siz)-(S_1*S_5))^(-1))*S_2+S_4

How to vectorize nested for loop for operations on different indices of the same matrix/array?

I've been trying to vectorize a for loop in Matlab because it bottlenecks the whole program but I have no clue about how to do it when iterating on different rows or columns of a single matrix inside of the loop. Here's the code :
// X is an n*k matrix, W is n*n
// W(i,j) stores the norm of the vector resulting from subtracting
// the j-th line of X from its i-th line.
for i = 1:n
for j = 1:n
W(i,j) = norm(X(i,:) - X(j,:))
end
end
Edit :
I chose Luis Mendo's answer as it was the most convenient for me and the one that's closer to the mathematical concept behind my algorithm, yet all three answers were correct and I'd advise to use the one that's the most convenient depending on which Matlab Toolboxes you have or the way you want to code.
I also noticed that the common point of all answers was to use a different format, for example : using an array that would store the indices, reshaping current arrays, using one more dimension...
So I think that's the right thing to explore if you have a similar problem.
Using combinatory:
% sample data
X = randi(9,5,4);
n = size(X,1);
% row index combinations
combIdx = combvec(1:n,1:n);
% difference between row combinations
D = X(combIdx(1,:),:)-X(combIdx(2,:),:);
% norm of each row
W = diag(sqrt(D*D'));
% reshape
W = reshape(W,n,[]);
Here is another solution that may be more efficient for big matrices.
For Matlab >=R2016 you can simple use
W = sqrt(sum(abs(reshape(X,n,1,k) - reshape(X,1,n,k)).^2,3))
(if your array is real-valued you can also skip the abs). For earlier versions of Matlab you need to add some repmat magic, namely:
W = sqrt(sum(abs(repmat(reshape(X,n,1,k),[1,n,1]) - repmat(reshape(X,1,n,k),[n,1,1])).^2,3));
P.S.: R2017b might make it even more convenient, at least the release notes mention a function called vecnorm that could replace the somewhat ugly sqrt(sum(abs(.).^2))) thing. But the documentation is not up yet so I don't know what exactly it will do. "
If you have the Statistics Toolbox, use pdist:
W = squareform(pdist(X));
No toolbox: good old bsxfun:
W = sqrt(sum(bsxfun(#minus, permute(X, [1 3 2]), permute(X, [3 1 2])).^2, 3));

"Desort" a matrix. Undo a sorting in Matlab

This question is basically an extension of that question.
I have a matrix A in Matlab and want to sort that matrix along one dimension:
A = rand(3,3,5);
[B idx] = sort(A,3);
Now idx is a matrix containing the "sorted" indices. How can i get back the matrix A using only B and idx?
The answer of the original question doesn't work for matrices, unfortunately.
You need to sort the indices idxto get back the original indices. Rest of the work would involve getting the formatted row and column indices corresponding to all those dim-3 indices. The implementation would look something like this -
[~,dim3idx] = sort(idx,3);
[m,n,r] = size(B);
[rowidx,colidx,~] = ndgrid(1:m,1:n,1:r);
Aout = B(sub2ind(size(B),rowidx,colidx,dim3idx))
Please note that for performance, one can get the linear indices generated by sub2ind alternatively with bsxfun directly from the size parameters and thus also avoid ndgrid, like so -
Aout = B(bsxfun(#plus,bsxfun(#plus,(1:m)',m*(0:n-1)),m*n*(dim3idx-1)))

Plotting from 3D matrix in Matlab

I have a matrix which is 1*1*10000, the slightly odd dimensions are the result of the matrix algebra used to calculate it.
I simply want to be able to plot the 10000 data points contained in it, but matlab seems unable to do it?
Can someone please tell me how I can plot the data?
Seems simple but I really can't figure out how to do it!
Baz
yes you need to reduce the dimensions to a vector:
A = zeros(1,1,100)
vector = squeeze(A(1,1,:))
as when you'd access the third dimension this would only return a 3D-Matrix again:
z = A(1,1,:)
would NOT work. So use squeeze() ;-) Then plot as usual.
Doc-Link: http://www.mathworks.de/de/help/matlab/ref/squeeze.html
And as Ander pointed out in comments, no need to give any dimensions, as it removes singleton-dimensions by itself. So just use vector = squeeze(A). MATLAB recognizes the way to go itself.

Creating a 3D function in Matlab using meshgrid

This should be a really simple question, but for some reason I'm getting unreasonably confused and the Matlab documentation isn't helping.
Given a uniform grid of coordinates (x_i,y_j,z_k), I want to make a 3-dimensional array F in Matlab such that F(i,j,k)=f(x_i,y_j,z_k). The following is obviously incorrect:
x=linspace(-1,1,100) % uniform mesh on [-1,1]^3
[X,Y,Z]=meshgrid(x);
f=X.*Y.*sin(pi*Y.*Z) % for example
Do I need to use permute somewhere? I know that I could simply make a triple loop, but as we know that is slow.
Thanks!
Use ndgrid instead of meshgrid to avoid the unwanted permutation between first and second dimensions.
From the documentation (see also here):
MESHGRID is like NDGRID except that the order of the first two input
and output arguments are switched (i.e., [X,Y,Z] = MESHGRID(x,y,z)
produces the same result as [Y,X,Z] = NDGRID(y,x,z))