user1884905
user1884905

Reputation: 3137

Independently solving for rows with mrdivide (B/A)?

When I answered this question, my answer started with: "For starters, you can get rid of all the if-statements by storing all the names in a cell."

The "For starters" bit was because I thought that I could add an edit with a vectorized solution. But when I tried to do so I ran into trouble vectorizing the use of mrdivide (b/a).

My question (marked below in the code) is if it is possible to solve b(z,:)/a(z,:) without using a loop. In other words, to solve b/a independently for each row of the matrices.

person = [98   206    35   114;
          60   206    28    52;
         100   210    31   116;
          69   217    26    35;
          88   213    42   100];

person1 = [93 208 34 107];

allNames = {'Cameron'; 'David'; 'Mike'; 'Bill'; 'Joe'};

n = 5;
a = max(person,repmat(person1,n,1));
b = min(person,repmat(person1,n,1));

for z = 1:5
    percent_error = b(z,:)/a(z,:);          %// Here is my question
    if percent_error >= 0.85
        disp(['Match, its ', allNames{z} ,'!'])
    end
end

Upvotes: 0

Views: 109

Answers (2)

Eitan T
Eitan T

Reputation: 32930

You can indeed eliminate the loop by vectorizing the operation. The trick is working with diagonal block matrices. Each block is matrix with only one row (each time a different row). After you create such a block matrix for a and for b, you can use mrdivide:

% # Without loop
tic
A = zeros(size(a) * size(a, 1));
B = zeros(size(b) * size(b, 1));
V = ones(size(a, 2), 1) * (1:size(a, 1));
idx = (0:size(A, 1):numel(A) - 1) + (V(:)' - 1) * size(a, 1) + 1;
A(idx) = a';
B(idx) = b';
X = diag(B / A);
percent_error1 = X(1:size(a, 1):end);
toc

% # With loop
tic
percent_error2 = zeros(5, 1);
for z = 1:5
    percent_error2(z) = b(z,:) / a(z,:);
end
toc

The result is:

Elapsed time is 0.000160 seconds.
Elapsed time is 0.000048 seconds.

percent_error1 =
    0.9741
    0.8516
    0.9670
    0.8221
    0.9611

percent_error2 =
    0.9741
    0.8516
    0.9670
    0.8221
    0.9611

Note that this is one of those cases where matrix division of large arrays takes longer than a for loop.

Upvotes: 1

Barney Szabolcs
Barney Szabolcs

Reputation: 12544

I was thinking about this:

person/person1

But this would only give good result when every index in person is bigger than the corresponding index in person1.

Upvotes: 0

Related Questions