question about vectorization using indexes
Mostrar comentarios más antiguos
Hello, I am trying to do the following operations in matlab but I have a problem with how to properly write my code using vectorization. This is just an example, m, n and the values of the vectors and matrices are just to illustrate my problem. In reality m and n can go up to 1000.
n=5; m=8;
a=4*ones(m,1); a(2)=2;a(n)=3;
b=2*ones(n,2);b(1,1)=5;b(3,1)=1;
ind=3*ones(n,2);
ind(1,2)=0;ind(3,2)=0; b(1,2)=0;b(3,2)=0;
non=zeros(1,n);c=zeros(1,n);
for i=1:n
non(i)=nnz(ind(i,:));
c(i)=prod(a(ind(i,1:non(i)))'.^b(i,1:non(i)),2);
end
I tried the following but it does not give correct results.
i=1:n;c=prod(a(ind(i,1:non(i))).^b(i,1:non(i)),2);
Thank you in advance
4 comentarios
Adam Danz
el 30 de Jul. de 2019
What's the goal with this line of code?
c(i)=prod(a(ind(i,1:non(i)))'.^b(i,1:non(i)),2);
I'm having a hard time guessing. The rest can easily be vectorized and cleaned up.
n=5;
m=8;
a=4*ones(m,1);
a([2,n])=[2,3];
b=2*ones(n,2);
b([1,3],1)=[5,1];
ind=3*ones(n,2);
ind([1,3],2)=0;
b([1,3],2)=0;
c=zeros(1,n);
non = sum(ind ~= 0,2)';
for i=1:n
c(i)=prod(a(ind(i,1:non(i)))'.^b(i,1:non(i)),2); % ????
end
AM
el 30 de Jul. de 2019
Note that :
non = nnz(ind(i,:));
x = a(ind(i,1:non);
can be written more simply as:
x = a(nonzeros(ind(i, :)));
which is a lot easier to understand (particularly given the poorly named variables).
--edit:--
I reiterate Adam's question, what is the intent of the line
c(i)=prod(a(ind(i,1:non(i)))'.^b(i,1:non(i)),2)
We now that it's what you want to vectorise. It'd be a lot easier to do if we knew what you're trying to do with it.
In particular, I'll point out that with the example given, the above will always pick element a(3), regardless of i.
Respuesta aceptada
Más respuestas (2)
Another option is to append a 0 (or any finite value) to the start of a and increase ind by 1, so a(ind+1) is always valid. Assuming that b is 0 when ind is 0 as in your example (if not, it's trivially fixed), then anything.^0 is 1 and multiplying by 1 doesn't affect the result, so:
apadded = [0; a];
c = prod(apadded(ind + 1) .^ b, 2)
As a bonus, c is a column vector matching the rows of b.
If b can be non-zero when ind is 0:
c = prod(apadded(ind + 1) . ^ (b .* (ind ~= 0)), 2)
to compensate.
edit: actually, if b can be non-zero when ind is 0, the easiest is to pad a with a 1 instead of a zero. Since 1.^anything is 1, it doesn't affect anything:
apadded = [1; a];
c = prod(apadded(ind + 1) .^b, 2) %b can be zero or non-zero where ind is 0. It'll result in 1.^something
1 comentario
Guillaume
el 31 de Jul. de 2019
Note: although both options are very fast even for very large inputs, this option is about twice as fast as the accepted answer. And much simpler and using less memory.
Andrei Bobrov
el 31 de Jul. de 2019
ind(ind == 0) = 1;
c = prod(a(ind).^b,2);
2 comentarios
Guillaume
el 31 de Jul. de 2019
Yes, that will also works as long as b is 0 when ind is 0, since a(1).^0 is 1.
Andrei Bobrov
el 31 de Jul. de 2019
lo = ind == 0;
ind(lo) = 1;
c = prod(a(ind).^(b.*~lo),2);
Categorías
Más información sobre Creating and Concatenating Matrices en Centro de ayuda y File Exchange.
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!