Multiplying a 3x3 matrix to 3nx1 array without using loops - matlab

In my code, I have to multiply a matrix A (dimensions 3x3) to a vector b1 (dimensions 3x1), resulting in C. So C = A*b1. Now, I need to repeat this process n times keeping A fixed and updating b to a different (3x1) vector each time. This can be done using loops but I want to avoid it to save computational cost. Instead I want to do it as matrix and vector product. Any ideas?

You need to build a matrix of b vectors, eg for n equal to 4:
bMat = [b1 b2 b3 b4];
Then:
C = A * bMat;
provides the solution of size 3x4 in this case. If you want the solution in the form of a vector of length 3n by 1, then do:
C = C(:);
Can we construct bMat for arbitrary n without a loop? That depends on what the form of all your b vectors is. If you let me know in a comment, I can update the answer.

Related

optimizing a matlab code involving for loop

I have a Matlab code that goes like this
s=[0.5 0.6 0.7];
u=[0.3618 0.9826 0.7237 0.0346 0.5525 0.0692 0.8949 0.1384
0.3418 0.9226 0.7213 0.0346 0.7525 0.0692 0.8949 0.1384
0.3318 0.9326 0.7237 0.0336 0.5575 0.0792 0.8949 0.1385]
A= u(1:2:7); % Here u is a 1-D vector and hence A
B=u(2:2:8); % Here u is a 1-D vector and hence B
C=mod(s(1)-(A+B),1);
I want to implement this code for the other two values of s also using next 8 values of u i.e now my code becomes
A=u(9:2:15);
B=u(10:2:16);
C=mod(s(2)-(A+B),1);
Similarly for last value of s. But each time i need the next 8 values of u. How do i code this so that it takes less time.
So you start with a 24 element array in u that you wish to perform this operation on in a vectorized fashion. I assume you have many more elements but that they all fit in memory. The way to do this is to reshape u to where you want the elements to be. You can do this via:
u1 = reshape(u1,[2,4,3]);
From there you also need to modify s to match it
s1 = permute(s,[1 3 2]);
Finally, you can calculate your C matrix in vectorized form
C1 = mod(s1-sum(u1),1);
For this problem, this gives a 1x4x3 matrix where the 3rd dimension represents each set of 8. From there you can then extract the problem set you want
C = squeeze(C1(1,:,1));

Multiply two vectors with dimensions increasing along time

I have two vectors (called A and B) with length N. Then I need to multiply both of them, but as an "integration" process. Which means I have to multiply first A(1)*B(1), then A(1:2)*B(1:2), until A(1:N)*B(1:N). The result of multiplying booth vector is a number, since B is a column vector. I've done it with a for loop:
for k = 1:N
C(k) = A(1:k) * B(1:k).';
end
But I wanted to ask you if this is the best solution or there is any other option more time-efficient, since N is very large (about 110,000)
C = cumsum(A.*B)
does the same thing without for loop. As EBH suggested in the comments if you are not sure whether A and B have same orientation, then use
C = cumsum(A(:).*B(:))

element by element matrix multiplication in Matlab

So I have the following matrices:
A = [1 2 3; 4 5 6];
B = [0.5 2 3];
I'm writing a function in MATLAB that will allow me to multiply a vector and a matrix by element as long as the number of elements in the vector matches the number of columns. In A there are 3 columns:
1 2 3
4 5 6
B also has 3 elements so this should work. I'm trying to produce the following output based on A and B:
0.5 4 9
2 10 18
My code is below. Does anyone know what I'm doing wrong?
function C = lab11(mat, vec)
C = zeros(2,3);
[a, b] = size(mat);
[c, d] = size(vec);
for i = 1:a
for k = 1:b
for j = 1
C(i,k) = C(i,k) + A(i,j) * B(j,k);
end
end
end
end
MATLAB already has functionality to do this in the bsxfun function. bsxfun will take two matrices and duplicate singleton dimensions until the matrices are the same size, then perform a binary operation on the two matrices. So, for your example, you would simply do the following:
C = bsxfun(#times,mat,vec);
Referencing MrAzzaman, bsxfun is the way to go with this. However, judging from your function name, this looks like it's homework, and so let's stick with what you have originally. As such, you need to only write two for loops. You would use the second for loop to index into both the vector and the columns of the matrix at the same time. The outer most for loop would access the rows of the matrix. In addition, you are referencing A and B, which are variables that don't exist in your code. You are also initializing the output matrix C to be 2 x 3 always. You want this to be the same size as mat. I also removed your checking of the length of the vector because you weren't doing anything with the result.
As such:
function C = lab11(mat, vec)
[a, b] = size(mat);
C = zeros(a,b);
for i = 1:a
for k = 1:b
C(i,k) = mat(i,k) * vec(k);
end
end
end
Take special note at what I did. The outer-most for loop accesses the rows of mat, while the inner-most loop accesses the columns of mat as well as the elements of vec. Bear in mind that the number of columns of mat need to be the same as the number of elements in vec. You should probably check for this in your code.
If you don't like using the bsxfun approach, one alternative is to take the vector vec and make a matrix out of this that is the same size as mat by stacking the vector vec on top of itself for as many times as we have rows in mat. After this, you can do element-by-element multiplication. You can do this stacking by using repmat which repeats a vector or matrices a given number of times in any dimension(s) you want. As such, your function would be simplified to:
function C = lab11(mat, vec)
rows = size(mat, 1);
vec_mat = repmat(vec, rows, 1);
C = mat .* vec_mat;
end
However, I would personally go with the bsxfun route. bsxfun basically does what the repmat paradigm does under the hood. Internally, it ensures that both of your inputs have the same size. If it doesn't, it replicates the smaller array / matrix until it is the same size as the larger array / matrix, then applies an element-by-element operation to the corresponding elements in both variables. bsxfun stands for Binary Singleton EXpansion FUNction, which is a fancy way of saying exactly what I just talked about.
Therefore, your function is further simplified to:
function C = lab11(mat, vec)
C = bsxfun(#times, mat, vec);
end
Good luck!

Maximum of a subset of array (MATLAB)

Suppose in MATLAB I have a real matrix A which is n x m and a binary matrix B of the same size. The latter matrix defines the optimization set (all indices for which the element of B equals one): over this set I would like to find the maximal element of A. How can I do this?
The first idea I had is that I consider C = A.*B and look for the maximal element of C. This works fine for all matrices A which have at least one positive element, however it does not work for matrices with all negative elements.
You can do
C = A(B==1);
to give you an array of just the values of A corresponding to a value of 1 in B. And
max( C )
will give you the maximum value of A where B is 1
With this method you don't run into a problem when all values of A are negative as the zeros don't appear in C.
Obviously you can condense this to
desiredValue = max(A(B(:)==1));
I am using the colon operator to make sure that the result of A(B(:)==1) is a column vector - if B is all ones I am not sure if Matlab would return a vector or a nxm matrix (and I can't confirm right now).
update to get the index of the value, you can do:
f = find(B==1);
[m mi] = max(A(f));
maxIndex = f(mi);
And to get that back to the 2D elements:
[i j] = ind2sub(size(A), maxIndex);

Efficient way of concatenating vectors

I have a n x 3 matrix E, a lot of means stocked in a d x 3 matrix M and a covariance matrix, say identity.
I want to compute, for each point in M, the mvnpdf(E[i,:],M(k,:),cov).
Basically, when I run mvnpdf(E,M(k,:),cov), I get a vector
[mvnpdf(E(1,:),M(k,:),cov)
mvnpdf(E(2,:),M(k,:),cov) etc]
I want to cat these vectors to get a matrix like:
[mvnpdf(E,M(1,:),cov), mvnpdf(E,M(2,:),cov), etc]
Is there any way to do that without a for loop?
This works on my machine, but see if it is what you are after:
Cov = eye(3);
C = arrayfun(#(x,y,z) mvnpdf(E,[x y z],Cov), M(1,:), M(2,:), M(3,:),'uni',false);
A = [C{:}]
Note: Consider not using cov as a variable because it is a MATLAB function.
EDIT: My original output M clobbered your input M. Please try again with original data!