2
votes

I have a matrix A in Matlab of dimension m x 3, e.g. m=18

A=[ 2| 1 1;
    3| 1 2;
   -8| 1 3;
   -------
   -5| 1 1;
    2| 1 2;
    6| 1 3;
   -------
    7| 2 1;
    3| 2 2;
    1| 2 3;
    5| 2 4;
   -------
    3| 2 1;
   -8| 2 2;
    1| 2 3;
    0| 2 4;
   -------
    1| 2 1;
    2| 2 2;
    7| 2 3;
    9| 2 4]

The characteristics of A are the following:

  1. It is composed by t submatrices. In the example t=5.

  2. Each submatrix t has dimension b x 3 with b<=m and b can take any value in {3,4,5,...,m} (clearly, in a way such that the sum of all rows is m). In the example, the first and the second submatrices have dimension 3 x 3, the last three submatrices have dimension 4 x 3.

  3. All submatrices of the same dimension are stacked one after the other. In the example, firstly we have the submatrices 3 x 3 and then the submatrices 4 x 3.

Then I have a matrix B of dimension f x 3 where f=size(unique(A(:,2:end),'rows','stable'),1) where the last two columns reproduce the elements in unique(A(:,2:end),'rows','stable'), e.g. in the eample above f=7 and

B=[2| 1 1;
   3| 1 2;
   1| 1 3;
   7| 2 1;
   8| 2 2;
  10| 2 3;
   2| 2 4]

I want to construct (possible without loops) a matrix C of dimension f x t such that C(:,i) is computed by

1) take the i-th sub-matrix of A and call it H. The number of rows of H is <f. The number of columns of H is 3. E.g. if i=1 in the example,

H=[2| 1 1;
   3| 1 2;
  -8| 1 3]

2) compute D=ismember(B(:,2:3),H(:,2:3),'rows') of dimension f x 1. When i=1 in the example, D=[1 1 1 0 0 0 0]';

3) Generate E(f,1)=0, i.e. in the example E=[0 0 0 0 0 0 0]'.

4) Replace E(D)=H(:,i), i.e. in the example with i=1, E=[2 3 -8 0 0 0 0]

5) Compute C(:,i)=E-B(:,1), i.e. in the example with i=1,

C(:,1)=[2-2;
        3-3;
       -8-1; 
        0-7;
        0-8;
        0-10;
        0-2]

In the example above summarising for all i

C=[ 2-2 | -5-2 | 0-2 | 0-2 | 0-2 ;
    3-3 |  2-3 | 0-3 | 0-3 | 0-3 ;
   -8-1 |  6-1 | 0-1 | 0-1 | 0-1 ;
    0-7 |  0-7 | 7-7 | 3-7 | 1-7 ;
    0-8 |  0-8 | 3-8 |-8-8 | 2-8 ;
   0-10 | 0-10 |1-10 |1-10 | 7-10;
    0-2 |  0-2 | 5-2 | 0-2 | 9-2;]

I have a rough idea on how to construct C using a loop; I would appreciate any suggestion that does not require looping and is possibly fast given that the actual matrices I'm working with have huge dimensions. One idea (that I don't know how to implement) could be: creating a cell variable of dimension tx1 in which in each cell I put a sub-matrix of A, then applying steps 2),3),4),5) to each cell and re-assembling.

1
I get lost while reading your computation steps. Would it be possible to show what the resulting calculations are at each step you're describing? It goes a longer way if you can pictorially show what each step does. - rayryeng
I can't see how this can be done without loops. Each submatrix may potentially be a different size, so it would be difficult to get this done vectorized. - rayryeng
Could you suggest the most efficient loop that you have in mind for doing this? - TEX
@rayryeng One idea (that I don't know how to implement) could be: creating a cell variable of dimension tx1 in which in each cell I put a sub-matrix of A, then applying steps 2),3),4),5) to each cell and re-assembling. What do you think? - TEX
That sounds very suitable... but that will require a loop over each submatrix. Is that what you want? - rayryeng

1 Answers

0
votes

Ok, I hope I got what you wanted, as your example and code were not easy to follow. Regarding loops you just need one, and as one level loop is compiled it shouldn't be a problem.

First your input data, I transposed just for readability, and I added an index column that corresponds to your lines.

 A = [1   1   1   2   2   2   3   3   3   3   4   4   4   4   5   5   5   5
      2   3  -8  -5   2   6   7   3   1   5   3  -8   1   0   1   2   7   9
      1   1   1   1   1   1   2   2   2   2   2   2   2   2   2   2   2   2
      1   2   3   1   2   3   1   2   3   4   1   2   3   4   1   2   3   4]';

 B = [2  3  1  7  8 10  2
      1  1  1  2  2  2  2
      1  2  3  1  2  3  4]';

t = length(unique(A(:,1)));
C = zeros(f,t);

for ii=1:length(unique(A(:,1)))
  C(ismember(B(:,2:3),A(A(:,1)==ii,3:4),'rows'),ii) = A(A(:,1)==ii,2);
  C(:,ii) = C(:,ii)-B(:,1);
end

The output will be what you wanted

 C = [0    -7    -2    -2    -2
      0    -1    -3    -3    -3
     -9     5    -1    -1    -1
     -7    -7     0    -4    -6
     -8    -8    -5   -16    -6
    -10   -10    -9    -9    -3
     -2    -2     3    -2     7];

enjoy