What's the difference between [A,B] and [A;B] in MatLab? - matlab

% CAT(2,A,B) is the same as [A,B].
% CAT(1,A,B) is the same as [A;B].
Seems I need to know this to understand what cat does.

[A,B]
is a matrix formed by placing B to the right of A, while
[A;B]
is a matrix formed by placing B below A.
Learn also about horzcat and vertcat.

[A, B] does col cat
[A; B] does row cat
eg:
x = [1, 2, 3];
y = [7, 8, 9];
[x, y] == > [1, 2, 3, 7, 8, 9]
becomes a 1x6 array
[x; y] == > [1, 2, 3]
[7, 8, 9]
becomes a 2x3 array
Just try it in Matlab and open ans to see the difference

Related

Find values in 3d matrix

I would like to do the equivalent of
x = [1, 0, 3; 2, 3, 0; 0, 0, 3];
[yy, xx, vals] = find(x);
where I really need the vals variable. I need all three, but vals is important. Now consider the 3d case, and flip one, so it's more interesting.
x = repmat(x, [1, 1, 3]);
x(:, :, 2) = fliplr(x(:, :, 1));
I'd like to do the same as before. I found this in several places
[yy, xx, zz] = ind2sub(size(x), find(x));
but then I don't know how to extract vals properly... I also don't really care about zz, but I'm sure they somehow need to be used for indexing.
Any help would be appreciated.
find with one output argument, as you used in your last statement:
[yy, xx, zz] = ind2sub(size(x), find(x));
returns linear indices into the matrix. You can use these to index:
index = find(x);
vals = x(index);
[xx,yy,zz] = ind2sub(size(x), index);
I'm not sure I've understood what you want to achieve, nevertheless, considering your last matrix x
x = [1, 0, 3; 2, 3, 0; 0, 0, 3]
z = repmat(x, [1, 1, 3]);
x(:, :, 2) = fliplr(x(:, :, 1))
with
[yy, xx, vals] = find(x)
you have:
yy the indices of the rows of the found elements
xx the indices of the columns of the found elements
then you can use
lin_idx=sub2ind(size(x),yy,xx)
to get the linear indices of the values inside the matrix x
now you can use
[a,b,c]=ind2sub(size(x),lin_idx)
to get the 3D indices of the elements in the matrix
You can access the values using that indices:
for i=1:length(a)
k(i)=x(a(i),b(i),c(i))
end
Now the array k contains the values (as per the array vals returned by find).

Efficient way to compute a tensor

Suppose c is a d-dimensional vector. I want to compute the following third-order tensor
where e_i stands for the ith standard basis of the Euclidean space. Is there a efficient way to compute this? I am using the following for-loop and the Kruskal-tensor ktensor to compute it using the tensor toolbox managed by Sandia National Labs:
x=ktensor({c,c,c});
I=eye(d);
for i=1:d
x=x+2*c(i)*ktensor({I(:,i),I(:,i),I(:,i)}
end
for i=1:d
for j=1:d
x=x- c(i)*c(j)*(ktensor({I(:,i),I(:,i),I(:,j)})+ktensor({I(:,i),I(:,j),I(:,i)})+ktensor({I(:,i),I(:,j),I(:,j)}))
end
end
Here is a possibility.
I used an optimization for the second term, as it places values of c along the "diagonal" of the tensor.
For the first term, there isn't much room for optimization, as it is a dense multiplication, so bsxfun seems appropriate.
For the third term, I stick to bsxfun, but as the result is somewhat sparse, you may benefit from filling it "by hand" if the size of your matrix is large.
Here is the code:
dim = 10;
c = [1:dim]';
e = eye(dim);
x = zeros([dim, dim, dim]);
% initialize with second term
x(1:dim*(dim+1)+1:end) = 2 * c;
% add first term
x = x + bsxfun(#times, bsxfun(#times, c, shiftdim(c, -1)), shiftdim(c, -2));
% add third term
x = x - sum(sum(bsxfun(#times, shiftdim(c*c',-3), ...
bsxfun(#times, bsxfun(#times, permute(e, [1, 3, 4, 2, 5]), permute(e, [3, 1, 4, 2, 5])), permute(e, [3, 4, 1, 5, 2])) +...
bsxfun(#times, bsxfun(#times, permute(e, [1, 3, 4, 2, 5]), permute(e, [3, 1, 4, 5, 2])), permute(e, [3, 4, 1, 2, 5])) +...
bsxfun(#times, bsxfun(#times, permute(e, [1, 3, 4, 5, 2]), permute(e, [3, 1, 4, 2, 5])), permute(e, [3, 4, 1, 2, 5]))), 5), 4);
EDIT
A much more efficient (esp. memory-wise) computation of the third term:
ec = bsxfun(#times, e, c);
x = x - ...
bsxfun(#times, ec, shiftdim(c, -2)) -...
bsxfun(#times, c', reshape(ec, [dim, 1, dim])) -....
bsxfun(#times, c, reshape(ec, [1, dim, dim]));
You could try the Parallel Computing Toolbox that is namely parfor loops.
x=ktensor({c,c,c});
I=eye(d);
y = zeros(d,d,d, d);
parfor i=1:d
y(:,:,:, i) = 2*c(i)*ktensor({I(:,i),I(:,i),I(:,i)};
end
x = x + sum(y, 4);
z = zeros(d,d,d, d,d);
parfor i=1:d
for j=1:d % only one layer of parallelization is allowed
z(:,:,:, i,j) = c(i)*c(j)*(ktensor({I(:,i),I(:,i),I(:,j)})+ktensor({I(:,i),I(:,j),I(:,i)})+ktensor({I(:,i),I(:,j),I(:,j)}));
end
end
x = x - sum(sum(z, 5), 4);
x % is your result
It just runs the untouched ktensor commands but in separate threads, so the Toolbox takes care of running the code in parallel.
Because of the independence property of each iteration, which means, for example, c_{i+1, j+1} does not rely on c_{i, j}, this is possible.
Depending on the number of cores (and hyperthreading) of your system, there could be up to #-of-cores-times of speed-up.

Sorting the vectors in matlab

I have three vectors in matlab:
x=[2, 3, 2, 3, 3]
y=[1, 5, 1, 5, 5]
Q=[7, 8, 4, 6, 8]
The modified vectors should be
x=[2, 3]
y=[1, 5]
Q=[12, 22 ]
Here x,y represents coordinates and Q a value depending upon (x,y).
The coordinates are getting repeated, like (2,1) has come twice, then I need to modify the vectors x and y representing unique coordinates and summing the values of Q for the particular coordinates e.g. (2,1) has come twice and the values of Q at those coordinates are 7 and 5 then for modified vectors coordinate (2,1) has to come once and corresponding Q value 7+5=12 and similarly for (3,5) Q is 8+6+8=22.
[XY, ~, ic] = unique([x' y'],'rows')
xu = XY(:,1).'; % The unique x you want
yu = XY(:,2).'; % The unique y you want
Qu = accumarray(ic,Q').';

extracting vertices of a triangle which is in y-coordinate matrix format

I'm using the "fuzarith" function for division of two fuzzy numbers;
C = fuzarith(X, A, B, operator)
x is a row vector that defines the x coordinates of the points at which the operation(in this case a division) is carried out. I think the mathematical term is abcissa.
A and B are triangular fuzzy numbers defined by their 3 vertices using the function trimf(x,[a b c]), where a,b and c are the x-coordinates of the vertices as shown below:
for
x=0:0.1:10; and
P=trimf(x,[3 6 8]);
Now if I use the division operator, let's say I do [3 6 8]/[1 2 3],
the result,r, is mathematically [1 3 8] but matlab gives me an <101x1> column vector of the ordinates of the plot of r v/s x.
The question is how to extract the 3 vertices from the column vector.
For this or similar problem you can do:
y = fuzarith(x, A, B, 'div');
result = x([find(y ~= 0, 1, 'first') - 1, find(y == 1), find(y ~= 0, 1, 'last') + 1]);

Vector of lengths of all elements in a cell array?

I have a cell array containing matrices. I would like to get a 1-D row vector of the lengths of every element in the cell array. Example:
a = {[1, 2], [1, 8], [5, 2, 4]};
% b = ...?
b == [ 2, 2, 3 ]
Is this possible without using a for loop?
cellfun is your friend.
b = cellfun( #numel, a );