rauldg
rauldg

Reputation: 421

Build a matrix from a vector containing the maximum of each possible pair

Given a vector of size n

A=[2 2 5 1] % n=4

Build a matrix R of size nxn in which the value correspondent to the element (i,j) is the maximum between A(i) and A(j)

R = 
    2     2     5     2
    2     2     5     2
    5     5     5     5
    2     2     5     1 

I am doing this with a for loop. Is there a more efficient way?

 R = zeros(size(a,2))
 for i=1:size(R,1)
    for j=1:size(R,2)
        R(i,j) = max(A(i),A(j));
    end
 end

Thanks for your help :)

Upvotes: 1

Views: 90

Answers (4)

High Performance Mark
High Performance Mark

Reputation: 78306

This is an extended comment, not an answer ... I've lost connectivity to my development servers, so thought it appropriate to waste some time. I defined a script file containing the code:

A=1:1500; % bigger vector for stable timing
tStart = tic;
R = zeros(size(A,2));
 for i=1:size(R,1)
    for j=1:size(R,2)
        R(i,j) = max(A(i),A(j));
    end
end
tElapsed = toc(tStart)

another script containing:

A=1:1500;
tStart = tic;
B=ones(size(A))'*A;
R=max(B,B');
tElapsed = toc(tStart)

and a third containing:

A=1:1500;
tStart = tic;
r=size(A,2);
R=ones(r);
for i=1:r
   for j=(i+1):r
       R(i,j)=max(A(i),A(j));
       R(j,i)=R(i,j);
   end
R(i,i)=A(i);
end
tElapsed = toc(tStart)

and ran them each 5 times. The mean tElapseds were: 1.7674s, 0.0520s, 0.0645s, so @Johan Lundberg's answer takes the laurels for (time) efficiency.

For the sake of completeness, I timed @woodchips answer; mean time elapsed was 0.0206s. @Johan suffers the ignominy of having the laurels snatched from his brow.

Upvotes: 1

user85109
user85109

Reputation:

Well, to be honest, the true MATLAB way is not what Johan has suggested. It is not even the fastest way. Three times faster is to use bsxfun, in the true MATLAB way.

>> A= rand(1,1000);

>> tic,B=ones(size(A))'*A;R=max(B,B');toc
Elapsed time is 0.027081 seconds.

>> tic,R = bsxfun(@max,A',A);toc
Elapsed time is 0.006306 seconds.

Upvotes: 3

Ping Lu
Ping Lu

Reputation: 91

  1. Your matrix is always symmetric, since max {A(i), A(j)}= max {A(j),A(i)}. So you can reduce the checks by half.
  2. Your diagonal is always your input vector. diag(R) = A

So I suggest you check only once:

r=size(A,2)
R=ones(r)
for i=1:r
   for j=(i+1):r
       R(i,j)=max(A(i),A(j))
       R(j,i)=R(i,j)
   end
R(i,i)=A(i)
end

(save your size(A,2) since it won't change after input and otherwise matlab will compute it every time!)

Upvotes: 0

Johan Lundberg
Johan Lundberg

Reputation: 27038

This is at least a more matlaby way:

B=ones(size(A))'*A
R=max(B,B')

I would expect it's a lot faster.

Upvotes: 4

Related Questions