Question about assigning value in a matrix.

Hi, all, again, I want to do the work quickly: I have a large matrix A, and I want to assign value in some entry in each row.
For example:
A=zeros(4);
a=[1,2;
2,3;
3,2;
4,1];
I want (1,2), (2,3),(3,2), (4,1) of matrix A be 1. How shall I make it work in no more than 3 commands?
What I am doing now is using loops:
for i=1:4
A(a(i,1),a(i,2)=1;
end
However, as i is very large like 3^14, the program is very slow. So I wonder is there a way to speed the programming?
Thanks.

 Réponse acceptée

Walter Roberson
Walter Roberson le 6 Juin 2013
idx = sub2ind(size(A), [1 2 3 4], [2 3 2 1]);
A(idx) = 1;

3 commentaires

C Zeng
C Zeng le 6 Juin 2013
Thanks, Walter! So sub2ind can find the index of A quickly by loops, right? I will definitely try this code. I like it!
Sean de Wolski
Sean de Wolski le 6 Juin 2013
I've always found for-loops to be significantly faster than sub2ind and ind2sub. Especially as the number of indices gets large.
It's been a few years since I was timing it for my own work though...
C Zeng
C Zeng le 6 Juin 2013
Oh, really? I always found that MATLAB is not efficient for large loops. That is why I tried to avoid large loops.

Connectez-vous pour commenter.

Plus de réponses (2)

Azzi Abdelmalek
Azzi Abdelmalek le 6 Juin 2013
A=zeros(4);
a=[1,2;
2,3;
3,2;
4,1];
idx= sub2ind(size(A),a(:,1),a(:,2));
A(idx)=1
Sean de Wolski
Sean de Wolski le 6 Juin 2013

0 votes

I've always found for-loops to be significantly faster than sub2ind and ind2sub. Especially as the number of indices gets large.
It's been a few years since I was timing it for my own work though...

12 commentaires

C Zeng
C Zeng le 6 Juin 2013
Sean, let me do a simple experiment and let u know.
Azzi Abdelmalek
Azzi Abdelmalek le 6 Juin 2013
The for loop, in this case, is almost twice faster
Sean de Wolski
Sean de Wolski le 6 Juin 2013
Modifié(e) : Sean de Wolski le 6 Juin 2013
function testFORIND2SUB
n = 1000;
idx = ceil(rand(n,2)*n); %two dimensions
[t1,t2] = deal(0);
for ii = 1:100
A = magic(n);
tic
for jj = 1:n
A(idx(jj,1),idx(jj,2)) = 0;
end
t1=t1+toc;
A = magic(n);
%With SUB2IND
tic
idxLinear = sub2ind([n n],idx(:,1),idx(:,2));
A(idxLinear) = 0;
t2 = t2+toc;
end
t2./t1
So for 1000x2 I'm seeing a 60% speed up.
Sean de Wolski
Sean de Wolski le 6 Juin 2013
Now this might be somewhere that MEXing this with MATLAB Coder could buy you even more speedup. I'll try that tomorrow.
C Zeng
C Zeng le 6 Juin 2013
Oh, I see. Yes, you may be right. Interested in more speedup!
Sean de Wolski
Sean de Wolski le 7 Juin 2013
For longer idx I am seeing the sub2ind approach be faster.
C Zeng
C Zeng le 7 Juin 2013
Sean, yes, my test result also shows it. For 3^10 rows (I assume it is large): Using for loops takes ~565 seconds while sub2ind procedure takes ~446 seconds.
Do you think if there is room for improvement? Ideally I hope it can compute for 3^14.
Sean de Wolski
Sean de Wolski le 7 Juin 2013
How many times do you have to do this? I ran it yesterday with 3^14 and it took circa 25 seconds.
C Zeng
C Zeng le 7 Juin 2013
Modifié(e) : C Zeng le 7 Juin 2013
2 times each, Sean. My problem is complex, M is a matrix with 3^10 rows, and around 400 columns. Here is the sample code:
for i=1:M1
pr=(rR(i:i+M-1)-1)/10; %pr is the vector of probabilities
prMatrix=zeros(M2);
for j=1:M2
prMatrix(j,j)=pr(j);
end
x=Y*prMatrix; % x is sample yield for each polnicy
x=round(x); % only consider yield as integer
% matrix computation(faster!)
%
TotalCollect=sum(x,2); % total collection for each policy
TotalCollect=TotalCollect+1;
TempMatrix=zeros(3^M2, n);
%{
for j=1:3^M2 %---slow!
TempMatrix(j,TotalCollect(j))=1;
end
%}
%use sub2ind procedure
row=(1:1:3^M2)';
idx=sub2ind(size(TempMatrix),row,TotalCollect);
TempMatrix(idx)=1;
%}
Pr=Pr+TempMatrix;
end
Well a few things real quick:
prMatrix = diag(pr);
Skips the first for-loop and call to zeros()
Second, you migh twant to consider taking the outer for-loop and converting it to a parfor with the Parallel Computing Toolbox. This would allow this to work in Parallel, over a few workers and speed things up that way.
Alternatively, just run it over the weekend or overnight, at two times total and 556 seconds, that's still only 20 minutes...
C Zeng
C Zeng le 7 Juin 2013
Thanks, Sean!
Let me try it again. I have to run large data on server, because 3^12 is memory out here.
C Zeng
C Zeng le 13 Juin 2013
Sean, thanks for your advice. My program got speedup. sub2ind will be faster if the size is large.

Connectez-vous pour commenter.

Catégories

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by