matlabmatrixvectorizationindicespre-allocation

Preallocation in MATLAB


Problem

I have a matrix M which is the following:

   M =  [1, 1, 0, 1, 0, 0, 0;
         0, 1, 1, 0, 1, 0, 0;
         0, 0, 1, 1, 0, 1, 0;
         0, 0, 0, 1, 1, 0, 1;
         1, 0, 0, 0, 1, 1, 0;
         0, 1, 0, 0, 0, 1, 1;
         1, 0, 1, 0, 0, 0, 1];  

The total number of ones in all columns is 21:

 Total_ones_in_cols = 21; 

I am then preallocating memory to find the row indices of each column in M:

row_indices = zeros(1,Total_ones_in_cols); 

The next step is to find the row indices for all the columns:

for i = 1:7
     Temp = find(M(:,i)); 
     row_indices = [row_indices, Temp.'];
end 

Question

Despite doing preallocation to row_indices, MATLAB is still recommending within the loop to preallocate row_indices for speed. Could someone explain why this is so? My guess is that since I am continuously changing the size of row_indices within the loop the previous memory that I have preallocated is overwritten and is trashed away which inherently means that the preallocation I did is rendered useless.


Solution

  • You have allocated the memory correctly according to the final size of row_indices but then instead of storing your results from the loop at the preallocated indices, you are appending them at the end. Appending always kills the preallocation and hence MATLAB is telling you to do preallocation as the size of row_indices at the end of your loop is [1 42] (MATLAB assumes that you want this result) instead of [1 21] which you preallocated (and actually looking for).

    To fix your code, it would be:

    row_indices = zeros(1,Total_ones_in_cols); 
    for ii = 1:7 %i is for imaginary numbers; don't use i (and j) as variable name(s)
         Temp = find(M(:,ii)); 
         row_indices(3*ii-2 : 3*ii) = Temp;  %Storing results at their specific indices
    end 
    %This assumes that you already know that there are 3 ones in each column
    

    I see the tag in your question. Note that find is directly applicable on matrices, so you can avoid the loop (you should do this for a simpler task like this) with simply just this:

    [row_indices, ~] = find(M);