Multiplication of two arrays with dimension=5 in a vectorize way - arrays

I have a three dimensional domain in MATLAB. For each point in the domain I have defined three arrays of size (NX,NY,NZ) at each point of the domain:
A1; % size(A1) = [NX NY NZ]
A2; % size(A2) = [NX NY NZ]
A3; % size(A3) = [NX NY NZ]
For each element, I am trying to construct an array which holds the value of A1, A2, and A3. Would the following be a good candidate for having a 1×3 vector at each point?
B = [A1(:) A2(:) A3(:)];
B = reshape(B, [size(A1) 1 3]);
If the 1×3 array is named C, I am trying to find C'*C at each point.
C = [A1(i,j,k) A2(i,j,k) A3(i,j,k)]; % size(C) = [1 3]
D = C'*C; % size(D) = [3 3]
My ultimate goal is to find the array D with size 3×3 for all the points in the domain in a vectorize fashion? In fact, the output which consists of array D for each point will have the size [NX NY NZ 3 3]. Could someone help me?

Basically we concatenate A1, A2 and A3 along the 4th and 5th dimensions separately that leaves singleton dimensions in the 5th and 4th dimensions respectively, which are then used by bsxfun [Apply element-by-element binary operation to two arrays with singleton expansion enable] to expand as 3x3 matrices along the 4th-5th dimensions for matrix multiplication result from each triplet of [A1(i,j,k),A2(i,j,k),A3(i,j,k)].
D = bsxfun(#times,cat(4,A1,A2,A3),cat(5,A1,A2,A3));

Related

How to create a matrix from product of all elements in two arrays?

I was reading the documentation for matlab on element-wise multiplication and I came across this example:
Create a row vector a and a column vector b, then multiply them. The
1-by-3 row vector and 6-by-1 column vector combine to produce a 6-by-3
matrix with all combinations of elements multiplied.
The documentation sure showed the output, but how did they get to that output matrix of size6,3? Which was obtained from multiplying a column vector b of size 6,1, and a row vector a of size 1,3 using the methods explained in the document.
This is called broadcasting. When one dimension is 1 while the other is bigger, the unit dimension is expanded, as if with repmat:
6 1 : column
1 3 : row
------
6 3 : result
Given
a = 1:3
b = [1:6]'
a .* b
is roughly equivalent to
a2 = repmat(a, 6, 1)
b2 = repmat(b, 1, 3)
a2 .* b2
But of course broadcasting is much more memory efficient.

Multiply each row of a matrix by another matrix

Say I have the following matrix
B = [1 2 3;4 5 6;7 8 9;10 11 12]
and another matrix
A = [a b c;d e f;g h i]
How do I multiply each row of matrix B by the matrix A (without using a for loop), i.e.
for i = 1:4
c(i) = B(i,:)*A*B(i,:)'
end
many thanks in advance.
You can use:
c = diag(B*A*B.');
However, this computes a whole 4×4 matrix only to extract its diagonal, so it's not very efficient.
A more efficient way that only computes the desired values is:
c = sum(bsxfun(#times, permute(sum(bsxfun(#times, B, permute(A, [3 1 2])), 2), [1 3 2]), B), 2);
Here is a breakdown of the above code:
c1 = sum(bsxfun(#times, B, permute(A, [3 1 2])), 2); % B(i,:)*A
c = sum(bsxfun(#times, permute(c1, [1 3 2]), B), 2); % (B(i,:)*A)*B(i,:)'
The first permute is used so that the number of columns in B matches the number of columns in A. Following the element-wise multiplication in bsxfun() each row is summed up (remember, permute shifted the rows into the 2nd-dimension), reproducing the effect of the vector-matrix multiplication B(i,:) * A occurring in the for loop.
Following the first sum, the 2nd-dimension is a singleton dimension. So, we use the second permute to move the 2nd-dimension into the 3rd-dimension and produce a 2-D matrix. Now, both c1 and B are the same size. Following element-wise multiplication in the second bsxfun() each column is summed up (remember, permute shifted columns back into the 2nd-dimension), reproducing the effect of B(i,:) * A * B(i,:)'.
Take note of a hidden advantage in this approach. Since we are using element-wise multiplication to replicate the results of matrix multiplication, order of the arguments doesn't matter in the bsxfun() calls. One less thing to worry about!
Or, from Matlab R2016b onwards, you can replace bsxfun(#times,...) by .*, thanks to implicit expansion:
c = sum(permute(sum(B.*permute(A, [3 1 2]), 2), [1 3 2]).*B, 2);

Matlab - Sort into deciles each column

Suppose I have a matrix A [m x 1], where m is not necessarily even. I to create a matrix B also [m x 1] which tells me the decile of the elements in A (i.e. matrix B has numbers from 1 to 10).
I know I can use the function sort(A) to get the position of the elements in A and from there I can manually get deciles. Is there another way of doing it?
I think one possibility would be B = ceil(10 * tiedrank(A) / length(A) . What do you think? Are there any issues with this?
Also, more generally, if I have a matrix A [m x n] and I want to create a matrix B also [m x n], in which each column of B should have the decile of the corresponding column in A , is there a way of doing it without a for loop through the columns?
Hope the problem at hand is clear. So far I have been doing it using the sort function and then manually assigning the deciles, but it is very inefficient.
This is how I would do it:
N = 10;
B = ceil(sum(bsxfun(#le, A(:), A(:).'))*N/numel(A));
This counts, for each element, how many elements are less than or equal to it; and then rounds the results to 10 values.
Depending on how you define deciles, you may want to change #le to #lt, or ceil to floor. For numel(A) multiple of N, the above definition gives exactly numel(A)/N values in each of the N quantiles. For example,
>> A = rand(1,8)
A =
0.4387 0.3816 0.7655 0.7952 0.1869 0.4898 0.4456 0.6463
>> N = 4;
>> B = ceil(sum(bsxfun(#le, A(:), A(:).'))*N/numel(A))
B =
2 1 4 4 1 3 2 3

array of matrices numpy

I need to make an array of matrices in numpy. This is so I can treat them as scalars and dot this with another array, like so:
a = [1,2,3]
b = [A,B,C] #A, B, and C are matrices
result = a.dot(b) #1A + 2B + 3C
Or similarly with a matrix M such that:
M.dot(b) -> another array of matrices
Is there a way of doing this? Currently, every array-like thing gets subsumed into the numpy array outside that allows .dot() in the first place. So, if A, B, and C were 3x3 matrices, a would be:
a.shape -> (3,3,3) #matrices absorbed into array
Thanks.
Solution:
import numpy as np
a = np.array([1,2,3])
X= np.ones((3,3))
Y= np.ones((3,3))
Z= np.ones((3,3))
b = np.array([X,Y,Z], dtype=object)
print a.dot(b)
results in:
[[6.0 6.0 6.0]
[6.0 6.0 6.0]
[6.0 6.0 6.0]]
Remember that the length of array of scalars must be of the same size of matrices (in this case matrices 3x3, so you need an array of length 3)

access last datapoint in matlab cell array

If I have data in a 1-D vector (Y) in matlab, I can access the last value by calling 'end', such as answer = Y(end). However, in my code, I am using a cell array to store a list of vectors of various lengths. Each vector is one cell in a 1D cell array. Is there some way in matlab to reference the last value of the vector stored in a specific cell array?
You can do this by writing y{k}(end) to grab the end of the kth item. Like this:
% Make some random vectors:
y1 = [ 1 2 3];
y2 = [ 1 5 9 12];
y3 = [9 48 2 1];
% create a cell array of them:
x = {y1, y2, y3};
% grab the end of the second vector:
k = 2;
x{k}(end)

Resources