gen
gen

Reputation: 10040

How to vectorize trace on an array of 2d matrices?

I am trying to set up some YALMIP constraints as follows:

for i=1:q 
    Constraints = [Constraints, trace(As(:, :, i)) == 1]
end

So I am essentially just trying to assert that all the (square) matrices in the first q pages of the 3d array As have trace 1.

How do I vectorize this so that I don't have to keep resizing my Constraints array?

Upvotes: 0

Views: 99

Answers (1)

Luis Mendo
Luis Mendo

Reputation: 112669

As Cris Luengo said, to avoid resizing you don't need to vectorize, it suffices to preallocate.

But if you want to vectorize, here's a way, using linear indexing:

As = randn(4,4,3); % example data
m = size(As, 1); % number of rows. The number of columns should be the same
q = size(As, 3); % number of pages
ind = (1:m+1:m^2).' + (0:q-1)*m^2; % linear index. Each diagonal is a column
Constraints = sum(As(ind), 1) == 1;

The linear indexing part works as follows. Consider a 4×4×3 example array ( As). Displaying its 3 pages (third-dimension slices) separately, the linear order of the entries is

 1     5     9    13
 2     6    10    14
 3     7    11    15
 4     8    12    16

17    21    25    29
18    22    26    30
19    23    27    31
20    24    28    32

33    37    41    45
34    38    42    46
35    39    43    47
36    40    44    48

The line lin = ... first builds the column vector

 1
 6
11
16

which corresponds to the diagonal of the first page. Then, the row vector [0 16 32] is added to that column vector. Thanks to implicit expansion, this produces the following matrix of linear indices (variable lin):

 1    17    33
 6    22    38
11    27    43
16    32    48

As can be seen, each column contains the indices of the diagonal of a page from the original array. The last line of the code applies this matrix as an index, computes the sum of each column and compares with 1.

Upvotes: 2

Related Questions