Thread Subject: Simple matrix manipulation question

Subject: Simple matrix manipulation question

From: jcurr Curran

Date: 16 Jul, 2009 00:46:01

Message: 1 of 21

Hi all,

Suppose I have a n x k matrix A and a n x 1 column vector b. b contains integers between 1 and k. I want to produce a n x 1 column vector c, which is defined by c(i) = min {A(i,1),A(i,2),...,A(i,b(i)}. This would be easy with loops, but I want code which will run as fast as possible (the matrices are large, and the operation will be performed many times).

To clarify, if b were (k,...,k)' then c would contain the minimum elements in each row of A.

Subject: Simple matrix manipulation question

From: Darren Rowland

Date: 16 Jul, 2009 01:54:01

Message: 2 of 21


Maybe it's just early in the morning but I have trouble understanding what you want.
Is c(i) given by
c(i) = min([A(i,1),A(i,2),...,A(i,k),A(i,b(i))]) ??
because this would just be the minimum value in the row.
What exactly are the ... representing?

Subject: Simple matrix manipulation question

From: Darren Rowland

Date: 16 Jul, 2009 01:57:01

Message: 3 of 21

Ok, I see what you want now
c(i) = min( A(1:b(i)) );

Subject: Simple matrix manipulation question

From: jcurr Curran

Date: 16 Jul, 2009 16:13:18

Message: 4 of 21

Right, but that method involves looping over each i. Is there a way to do this without loops?

"Darren Rowland" <darrenjremovethisrowland@hotmail.com> wrote in message <h3m1dc$5gs$1@fred.mathworks.com>...
> Ok, I see what you want now
> c(i) = min( A(1:b(i)) );

Subject: Simple matrix manipulation question

From: Nathan

Date: 16 Jul, 2009 16:22:53

Message: 5 of 21

On Jul 16, 9:13 am, "jcurr Curran" <johncurra...@yahoo.com> wrote:
> Right, but that method involves looping over each i. Is there a way to do this without loops?
>
> "Darren Rowland" <darrenjremovethisrowl...@hotmail.com> wrote in message <h3m1dc$5g...@fred.mathworks.com>...
> > Ok, I see what you want now
> > c(i) = min( A(1:b(i)) );

A = magic(10);
b = [1:10]';
c = min(A(b,:)')';

c =

     1
     7
     4
     3
     2
    17
     5
     6
    10
    11

How about that one?
-Nathan

Subject: Simple matrix manipulation question

From: Alan B

Date: 16 Jul, 2009 16:29:02

Message: 6 of 21

"jcurr Curran" <johncurran20@yahoo.com> wrote in message <h3njiu$8m6$1@fred.mathworks.com>...
> Right, but that method involves looping over each i. Is there a way to do this without loops?
>
> "Darren Rowland" <darrenjremovethisrowland@hotmail.com> wrote in message <h3m1dc$5gs$1@fred.mathworks.com>...
> > Ok, I see what you want now
> > c(i) = min( A(1:b(i)) );

If I understand correctly, this should work:

z = meshgrid(1:k)>repmat(b',1,k); % use this to mask off the unwanted values with inf
A(z) = inf;
min(A,[],2);

I didn't check for timing, a loop might be faster.

Subject: Simple matrix manipulation question

From: jcurr Curran

Date: 16 Jul, 2009 17:15:20

Message: 7 of 21

This computes the minimum element in each row of A, it's not quite what I was looking for.

Nathan <ngreco32@gmail.com> wrote in message <f83d9ae3-79bf-4717-be07-cb7ac76d00a1@12g2000pri.googlegroups.com>...
> On Jul 16, 9:13?am, "jcurr Curran" <johncurra...@yahoo.com> wrote:
> > Right, but that method involves looping over each i. Is there a way to do this without loops?
> >
> > "Darren Rowland" <darrenjremovethisrowl...@hotmail.com> wrote in message <h3m1dc$5g...@fred.mathworks.com>...
> > > Ok, I see what you want now
> > > c(i) = min( A(1:b(i)) );
>
> A = magic(10);
> b = [1:10]';
> c = min(A(b,:)')';
>
> c =
>
> 1
> 7
> 4
> 3
> 2
> 17
> 5
> 6
> 10
> 11
>
> How about that one?
> -Nathan

Subject: Simple matrix manipulation question

From: someone

Date: 16 Jul, 2009 17:30:36

Message: 8 of 21

"jcurr Curran" <johncurran20@yahoo.com> wrote in message <h3lt89$b6e$1@fred.mathworks.com>...
> Hi all,
>
> Suppose I have a n x k matrix A and a n x 1 column vector b. b contains integers between 1 and k. I want to produce a n x 1 column vector c, which is defined by c(i) = min {A(i,1),A(i,2),...,A(i,b(i)}. This would be easy with loops, but I want code which will run as fast as possible (the matrices are large, and the operation will be performed many times).

Vectorized code MAY NOT NECESSARILY run as fast as code with loops, especially for large matricies.

>
> To clarify, if b were (k,...,k)' then c would contain the minimum elements in each row of A.

Subject: Simple matrix manipulation question

From: Nathan

Date: 16 Jul, 2009 18:47:46

Message: 9 of 21

On Jul 16, 10:15 am, "jcurr Curran" <johncurra...@yahoo.com> wrote:
> This computes the minimum element in each row of A, it's not quite what I was looking for.

Ah, I get what you mean now.
I haven't been able to come up with anything other than loops for this
problem.
What is so bad about having a loop anyways? It's not that slow.
How big is your matrix A?
With a basic for loop
for i = 1:size(A,1)
c(i) = min(A(i,1:b(i)));
end

computation times aren't too bad...
-Nathan

Subject: Simple matrix manipulation question

From: Matt Fig

Date: 16 Jul, 2009 19:42:02

Message: 10 of 21

http://www.mathworks.com/matlabcentral/newsreader/view_thread/256123#665287

Subject: Simple matrix manipulation question

From: Matt

Date: 16 Jul, 2009 20:23:01

Message: 11 of 21

"jcurr Curran" <johncurran20@yahoo.com> wrote in message <h3lt89$b6e$1@fred.mathworks.com>...
> Hi all,
>
> Suppose I have a n x k matrix A and a n x 1 column vector b. b contains integers between 1 and k. I want to produce a n x 1 column vector c, which is defined by c(i) = min {A(i,1),A(i,2),...,A(i,b(i)}. This would be easy with loops, but I want code which will run as fast as possible (the matrices are large, and the operation will be performed many times).
-------

Another option


Amod=A;
Amod( bsxfun(@lt,b,(1:k)) )=nan;
c=min(Amod,[],2);

Subject: Simple matrix manipulation question

From: Bruno Luong

Date: 16 Jul, 2009 20:32:03

Message: 12 of 21

>
>
> Amod=A;
> Amod( bsxfun(@lt,b,(1:k)) )=nan;
> c=min(Amod,[],2);

A remark: When it's possible use alternative number other than NaN. Operation with NaN is usually much slowest. In this specific thread, use Inf.

Bruno

Subject: Simple matrix manipulation question

From: Matt

Date: 16 Jul, 2009 20:57:01

Message: 13 of 21

"Bruno Luong" <b.luong@fogale.findmycountry> wrote in message <h3o2o3$7g4$1@fred.mathworks.com>...
> >
> >
> > Amod=A;
> > Amod( bsxfun(@lt,b,(1:k)) )=nan;
> > c=min(Amod,[],2);
>
> A remark: When it's possible use alternative number other than NaN. Operation with NaN is usually much slowest. In this specific thread, use Inf.
------

I'd be curious to know why this is true in this case. Surely min() bails out as soon as it sees either an Inf or a Nan. Is there a reason it takes longer to recognize a Nan than an Inf?

Subject: Simple matrix manipulation question

From: Matt Fig

Date: 16 Jul, 2009 21:13:03

Message: 14 of 21

I can see no difference in speed (nan vs. inf), but Matt's solution is incomplete as I understand the problem.


% Data
N = 1200;
A = round(rand(N)*20);
B = randperm(N);

% obvious engine.
tic
for ii = N:-1:1
   C(ii,1) = min(A(ii,1:B(ii))); % OP wants column vector.
end
toc

% faster engine for this data.
tic
for ii = N:-1:1
    m = A(ii);
    for jj = 1:B(ii)
        if A(ii,jj)<m
            m = A(ii,jj);
        end
    end
   C2(ii,1) = m;
end
toc

% Unfinished(?) engine.
tic
Amod = A;
Amod( bsxfun(@lt,B,(1:N)) ) = nan;
c = min(Amod,[],2);
toc

whos
isequal(C,C2) % Yes
isequal(C,c) % No

Subject: Simple matrix manipulation question

From: Matt

Date: 16 Jul, 2009 21:27:01

Message: 15 of 21

"Matt Fig" <spamanon@yahoo.com> wrote in message <h3o54v$hc9$1@fred.mathworks.com>...
> I can see no difference in speed (nan vs. inf), but Matt's solution is incomplete as I understand the problem.
>
>
> % Data
> N = 1200;
> A = round(rand(N)*20);
> B = randperm(N);

It's because randperm() produces a row vector, whereas I assume B is a column vector (as did the OP). When you insert

B=B(:);

all 3 methods come into agreement.

Subject: Simple matrix manipulation question

From: Nathan

Date: 16 Jul, 2009 21:31:03

Message: 16 of 21

On Jul 16, 2:13 pm, "Matt Fig" <spama...@yahoo.com> wrote:
> I can see no difference in speed (nan vs. inf), but Matt's solution is incomplete as I understand the problem.
>
> % Data
> N = 1200;
> A = round(rand(N)*20);
> B = randperm(N);
>
> % obvious engine.
> tic
> for ii = N:-1:1
>    C(ii,1) = min(A(ii,1:B(ii)));  % OP wants column vector.
> end
> toc
>
> % faster engine for this data.
> tic
> for ii = N:-1:1
>     m = A(ii);
>     for jj = 1:B(ii)
>         if A(ii,jj)<m
>             m = A(ii,jj);
>         end
>     end
>    C2(ii,1) = m;
> end
> toc
>
> % Unfinished(?) engine.
> tic
> Amod = A;
> Amod( bsxfun(@lt,B,(1:N)) ) = nan;
> c = min(Amod,[],2);
> toc
>
> whos
> isequal(C,C2)  % Yes
> isequal(C,c)  % No

The last engine does work. B is supposed to be nx1, not 1xn
: )
But yeah, your for loop is faster than the obvious one.
-Nathan

Subject: Simple matrix manipulation question

From: Bruno Luong

Date: 16 Jul, 2009 21:33:02

Message: 17 of 21

It's not the first time I observe much slower operation on NaN, and I did very careful timing in various development of codes. I know that by default Matlab NaN is a "quiet" NaN (as opposed) to signaled. So in principle it does not trigger any floating point handler. So I don't have any explanation.

Bruno

n = 1000;
k = 1000;
A = rand(n,k);
b = ceil(k*rand(n,1));

tic
Amod=A;
Amod( bsxfun(@lt,b,(1:k)) )=inf;
c2=min(Amod,[],2);
toc % Elapsed time is 0.028898 seconds.
clear Amod c1

tic
Amod=A;
Amod( bsxfun(@lt,b,(1:k)) )=nan;
c1=min(Amod,[],2);
toc % Elapsed time is 0.119306 seconds.

% Bruno

Subject: Simple matrix manipulation question

From: Matt Fig

Date: 16 Jul, 2009 21:34:01

Message: 18 of 21

"Matt " <xys@whatever.com> wrote in message <h3o5v5$d8c$1@fred.mathworks.com>...

> It's because randperm() produces a row vector, whereas I assume B is a column vector (as did the OP). When you insert
>
> B=B(:);
>
> all 3 methods come into agreement.

(or B = randperm(N)';)

D'oh. My stupid oversight. Sorry Matt.

Subject: Simple matrix manipulation question

From: Matt

Date: 16 Jul, 2009 21:38:01

Message: 19 of 21

"Matt " <xys@whatever.com> wrote in message <h3o5v5$d8c$1@fred.mathworks.com>...
> "Matt Fig" <spamanon@yahoo.com> wrote in message <h3o54v$hc9$1@fred.mathworks.com>...
> > I can see no difference in speed (nan vs. inf), but Matt's solution is incomplete as I understand the problem.
> >
> >
> > % Data
> > N = 1200;
> > A = round(rand(N)*20);
> > B = randperm(N);
>
> It's because randperm() produces a row vector, whereas I assume B is a column vector (as did the OP). When you insert
>
> B=B(:);
>
> all 3 methods come into agreement.

This also probably explains why you see no significant difference between nan's and inf's in my version. With B a row vector, Amod gets truncated to an Nx1 vector. It inadvertently reduces the complexity of the min() operation by a factor of N.

I definitely see a significant speed-up, when using Infs as Bruno suggested:


%data
k=2000;
A=rand(k); b=randperm(k)';

tic;
 
 Amod=A;
 Amod( bsxfun(@lt,b,(1:k)) )=nan;
 c=min(Amod,[],2);

 toc;
%Elapsed time is 0.708845 seconds.

 tic;
 
 Amod=A;
 Amod( bsxfun(@lt,b,(1:k)) )=inf;
 c=min(Amod,[],2);

 toc;
%Elapsed time is 0.236525 seconds.

Subject: Simple matrix manipulation question

From: Matt Fig

Date: 16 Jul, 2009 21:40:18

Message: 20 of 21

"Bruno Luong" <b.luong@fogale.findmycountry> wrote in message <h3o6ae$6rr$1@fred.mathworks.com>...
> It's not the first time I observe much slower operation on NaN, and I did very careful timing in various development of codes. I know that by default Matlab NaN is a "quiet" NaN (as opposed) to signaled. So in principle it does not trigger any floating point handler. So I don't have any explanation.


Now that people have corrected my error (thanks all :-)) I DO see the speed difference too. I have no reason for this either, but it is good to know for future reference.

Subject: Simple matrix manipulation question

From: Matt

Date: 17 Jul, 2009 15:10:21

Message: 21 of 21

"Matt Fig" <spamanon@yahoo.com> wrote in message <h3o6c9$ag5$1@fred.mathworks.com>...
> "Matt " <xys@whatever.com> wrote in message <h3o5v5$d8c$1@fred.mathworks.com>...
>
> > It's because randperm() produces a row vector, whereas I assume B is a column vector (as did the OP). When you insert
> >
> > B=B(:);
> >
> > all 3 methods come into agreement.
>
> (or B = randperm(N)';)
>
> D'oh. My stupid oversight. Sorry Matt.

Well, it's all moot. The obvious engine is the fastest, even in the most pessimistic case where B(:)=N.

Tags for this Thread

Everyone's Tags:

Add a New Tag:

Separated by commas
Ex.: root locus, bode

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Tag Activity for This Thread
Tag Applied By Date/Time
matrix Sprinceana 16 Jul, 2009 12:23:31
rssFeed for this Thread

Contact us at files@mathworks.com