how to get rid of loop for this scenario?

44 views
Skip to first unread message

Jin Tang

unread,
Feb 19, 2003, 9:31:53 PM2/19/03
to
I have to improve the speed of one Matlab program. To do this, I want
to get rid of the for-loop. But I don't know how to achieve it.


The simplified scenario is like this: I have a zero matrix A (let's
say 6 by 6). I want to change some consecutive elements in each
column to other numbers (known). I know the starting row index of
those elements I want to change for each column and these indexes for
different columns are different.


The most obvious way is to use for-loop for each column and replace
those elements in each column with target numbers. But is there any
way to avoid using for-loop? I cannot tolerate the speed using
for-loop. Or is there any way to improve the speed? Thanks a lot!

Brett Shoelson

unread,
Feb 19, 2003, 10:53:35 PM2/19/03
to


Your question is a bit vague, but if I follow, then sub2ind will help:


a = zeros(6);
b = floor(rand(36,1)*100);
[rows,cols] = meshgrid(1:6,1:6);
inds=sub2ind(size(a),rows,cols);
a(inds)=b;


Cheers,
Brett

Jin Tang

unread,
Feb 20, 2003, 1:21:37 PM2/20/03
to
Thank you very much for your help, Brett. I am sorry that I didn't
make it very clear on the question.


Let's say I have the matrix A as zeros (6 by 6):
0 0 0 0 0 0
0 0 0 0 0 0
A= 0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0


Also, I have another column vector B=[6 1 3]'
I want to replace three consecutive elements in each column of A by
the data vector B.


The positions of these three elements in each column are different.
But I know the starting index of these elements for each column,
which is expressed as a vector C=[2 4 1 3 2 1]. In other words, for
first column of A, the starting index for B is 2; for second column
of A, starting index for B is 4; for third column of A, the starting
index for B is 1; ... so on.


The final matrix A should look like this:
0 0 6 0 0 6
6 0 1 0 6 1
1 0 3 6 1 3
A= 3 6 0 1 3 0
0 1 0 3 0 0
0 3 0 0 0 0


I can use for-loop to finish this task. Is there any other ways to
avoid using for-loop?


Hope I am clear this time. Thanks!

Brett Shoelson

unread,
Feb 20, 2003, 2:28:31 PM2/20/03
to
SNIP

Again, use SUB2IND. You know the starting points for the the substitution,
in terms of their rows and columns. Use sub2ind to get the indices for these
starting points:

>> inds = sub2ind(size(A),C,[1:6])

inds =

2 10 13 21 26 31

Now the trick is to supplement each element with its next two neighbors. The
easiest way to do this is to download from MATLAB Central a function called
LINSPACEV (Duane Hanselman's extension into n-dimensions of my 2-D extension
of linspace).

>> inds1 = linspacev(inds,inds+2,3)

inds1 =

2 10 13 21 26 31
3 11 14 22 27 32
4 12 15 23 28 33


(There are other ways of creating these indices. You could use CUMSUM, for
instance):
>> inds2=cumsum([inds(:) ones(length(inds),2)],2)

inds2 =

2 3 4
10 11 12
13 14 15
21 22 23
26 27 28
31 32 33

Now use REPMAT to create copies of B (in a form appropriate for your
indices):
If you use linspacev:

>> vals1 = repmat(B,1,6)

vals1 =

6 6 6 6 6 6
1 1 1 1 1 1
3 3 3 3 3 3

Or if you use cumsum:
>> vals2 = repmat(B',6,1)

vals2 =

6 1 3
6 1 3
6 1 3
6 1 3
6 1 3
6 1 3

(Or, for either: inds = sort(inds(:)); vals = repmat(B,6,1);)

And substitute:

A(inds1) = vals1; (OR A(inds2) = vals2);
>> A(inds1) = vals1

A =

0 0 6 0 0 6
6 0 1 0 6 1
1 0 3 6 1 3

3 6 0 1 3 0
0 1 0 3 0 0
0 3 0 0 0 0

Cheers,
Brett


Brett Shoelson

unread,
Feb 20, 2003, 2:37:40 PM2/20/03
to
Followup comment:
that should be linspacen, not linspacev. (Linspacev was my 2-D version,
which would also have worked had I not withdrawn it when Duane extended to n
dimensions.)
Also, the content of my post might be more instructive for learning
vectorization than for avoiding a loop (particularly with the JIT
accelerator). You're probably not going to get much of a speed boost by
vectorizing a loop from 1:6 over a 6x6 matrix. Still, it's well worth
learning/practicing these things.
Cheers again,
Brett


Jin Tang

unread,
Feb 20, 2003, 8:19:30 PM2/20/03
to
Thank you so much for your warm help and detailed explaination,
Brett. They are really useful for my questions. Although the method
will not improve speed for 6 by 6 matrix, it helps me a lot when I
use it for 2000 by 2000 matrix. Besides, it is a new technique worth
studying for me. I can use the same idea to avoid using for-loop in
other similar situations. Thanks a lot!


Cheers,
Jin

Reply all
Reply to author
Forward
0 new messages