How to Vectorize Dependent For-Loops in Matlab - performance

I was wondering if anyone could help me to vectorize this part of my code. Here, bin_pdf is binomial coefficient function. pb and pd are scalar parameters. Thank You!
for t=0:min(T,r)
for n=0:r-t
pp = (bin_pdf(n,pb,r-t) * bin_pdf(t,pd,min(T,r)));
pt = pt + t/r * pp;
pn = pn + n/r * pp;
pc = pc + (r-t-n)/r * pp;
end
end
where
function p = bin_pdf(x,rho,n)
if (x > n) || (n < 0)
p = 0;
else
p = Choosenk(n,x) * rho^x * (1-rho)^(n-x);
end
and
function C=Choosenk(n,k)
if k>n/2
k=n-k;
end;
C=1;
for i=0:k-1
C=C*(n-i)/(k-i);
end
end

This is the vectorized Choosenk. if you dont call it somewhere else you could integrate it into the bin_pdf.
function C=Choosenk(n,k)
if k>n/2
k=n-k;
end;
C=prod((n-k+1:n)./(1:k));
end

Related

I have a problem with a function in matlab

I'm depveloping a function in matlab, but I have the following problem.
When I assign the codigo variable to my function, matlab show me the next message
Error using ContLetrasTexto>shannon
Too many output arguments.
Error in ContLetrasTexto (line 111)
codigos = shannon(1, length(vectorprobabilidad), vectorprobabilidad, codigos);
My code is the following
% create the cell array of codes
codigos = cell(size(letra));
% call the recursive encoder function
codigos = shannon(1, length(vectorprobabilidad), vectorprobabilidad, codigos);
%Método shannon-Fano%
function shannon(inicio, fin, p, codes)
shannon_inicial = inicio;
shannon_final = fin;
suma_arriba = p(inicio);
suma_fin = p(fin);
while(shannon_inicial ~= shannon_final-1)
if (suma_arriba > suma_fin)
shannon_final = shannon_final - 1;
suma_fin = suma_fin + p(shannon_final);
else
shannon_inicial = shannon_inicial + 1;
suma_arriba = suma_arriba + p(shannon_inicial);
end;
end;
for i = inicio:shannon_inicial
p(i) = 0;
end;
for j = shannon_final:fin
p(j) = 1;
end;
if(shannon_inicial-inicio+1 > 1)
shannon(inicio,shannon_inicial,p,codes);
end;
if(fin-shannon_final+1 > 1)
shannon(shannon_final,fin,p,codes);
end;
end
I'll be grateful for your help

Solving Project Euler #12 with Matlab

I am trying to solve Problem #12 of Project Euler with Matlab and this is what I came up with to find the number of divisors of a given number:
function [Divisors] = ND(n)
p = primes(n); %returns a row vector containing all the prime numbers less than or equal to n
i = 1;
count = 0;
Divisors = 1;
while n ~= 1
while rem(n, p(i)) == 0 %rem(a, b) returns the remainder after division of a by b
count = count + 1;
n = n / p(i);
end
Divisors = Divisors * (count + 1);
i = i + 1;
count = 0;
end
end
After this, I created a function to evaluate the number of divisors of the product n * (n + 1) / 2 and when this product achieves a specific limit:
function [solution] = Solution(limit)
n = 1;
product = 0;
while(product < limit)
if rem(n, 2) == 0
product = ND(n / 2) * ND(n + 1);
else
product = ND(n) * ND((n + 1) / 2);
end
n = n + 1;
end
solution = n * (n + 1) / 2;
end
I already know the answer and it's not what comes back from the function Solution. Could someone help me find what's wrong with the coding.
When I run Solution(500) (500 is the limit specified in the problem), I get 76588876, but the correct answer should be:
76576500.
The trick is quite simple while it also bothering me for a while: The iteration in you while loop is misplaced, which would cause the solution a little bigger than the true answer.
function [solution] = Solution(limit)
n = 1;
product = 0;
while(product < limit)
n = n + 1; %%%But Here
if rem(n, 2) == 0
product = ND(n / 2) * ND(n + 1);
else
product = ND(n) * ND((n + 1) / 2);
end
%n = n + 1; %%%Not Here
end
solution = n * (n + 1) / 2;
end
The output of Matlab 2015b:
>> Solution(500)
ans =
76576500

Fast way to initialize a tensor in torch7

I need to initialize a 3D tensor with an index-dependent function in torch7, i.e.
func = function(i,j,k) --i, j is the index of an element in the tensor
return i*j*k --do operations within func which're dependent of i, j
end
then I initialize a 3D tensor A like this:
for i=1,A:size(1) do
for j=1,A:size(2) do
for k=1,A:size(3) do
A[{i,j,k}] = func(i,j,k)
end
end
end
But this code runs very slow, and I found it takes up 92% of total running time. Are there any more efficient ways to initialize a 3D tensor in torch7?
See the documentation for the Tensor:apply
These functions apply a function to each element of the tensor on
which the method is called (self). These methods are much faster than
using a for loop in Lua.
The example in the docs initializes a 2D array based on its index i (in memory). Below is an extended example for 3 dimensions and below that one for N-D tensors. Using the apply method is much, much faster on my machine:
require 'torch'
A = torch.Tensor(100, 100, 1000)
B = torch.Tensor(100, 100, 1000)
function func(i,j,k)
return i*j*k
end
t = os.clock()
for i=1,A:size(1) do
for j=1,A:size(2) do
for k=1,A:size(3) do
A[{i, j, k}] = i * j * k
end
end
end
print("Original time:", os.difftime(os.clock(), t))
t = os.clock()
function forindices(A, func)
local i = 1
local j = 1
local k = 0
local d3 = A:size(3)
local d2 = A:size(2)
return function()
k = k + 1
if k > d3 then
k = 1
j = j + 1
if j > d2 then
j = 1
i = i + 1
end
end
return func(i, j, k)
end
end
B:apply(forindices(A, func))
print("Apply method:", os.difftime(os.clock(), t))
EDIT
This will work for any Tensor object:
function tabulate(A, f)
local idx = {}
local ndims = A:dim()
local dim = A:size()
idx[ndims] = 0
for i=1, (ndims - 1) do
idx[i] = 1
end
return A:apply(function()
for i=ndims, 0, -1 do
idx[i] = idx[i] + 1
if idx[i] <= dim[i] then
break
end
idx[i] = 1
end
return f(unpack(idx))
end)
end
-- usage for 3D case.
tabulate(A, function(i, j, k) return i * j * k end)

How to remove the for loop in the following MATLAB code?

I need to perform the following computation in an image processing project. It is the logarthmic of the summation of H3. I've written the following code but this loop has a very high computation time. Is there any way to eliminate the for loop?
for k=1:i
for l=1:j
HA(i,j)=HA(i,j)+log2((H3(k,l)/probA).^q);
end;
end;
Thanks in advance!
EDIT:
for i=1:256
for j=1:240
probA = 0;
probC = 0;
subProbA = H3(1:i,1:j);
probA = sum(subProbA(:));
probC = 1-probA;
for k=1:i
for l=1:j
HA(i,j)=HA(i,j)+log2((H3(k,l)/probA).^q);
end;
end;
HA(i,j)=HA(i,j)/(1-q);
for k=i+1:256
for l=j+1:240
HC(i,j)=HC(i,j)+log2((H3(k,l)/probC).^q);
end;
end;
HC(i,j)=HC(i,j)/(1-q);
e1(i,j) = HA(i,j) + HC(i,j);
if e1(i) >= emax
emax = e1(i);
tt1 = i-1;
end;
end;
end;
Assuming the two loops are nested inside some other outer loops that are iterated with i and j (though using i and j as iterators are not the best practices) and also assuming that probA and q are scalars, try this -
HA(i,j) = sum(sum(log2((H3(1:i,1:j)./probA).^q)))
Using the above code snippet, yon can replace your actual code posted in the EDIT section with this -
for i=1:256
for j=1:240
subProbA = H3(1:i,1:j);
probA = sum(subProbA(:));
probC = 1-probA;
HA(i,j) = sum(sum(log2((subProbA./probA).^q)))./(1-q);
HC(i,j) = sum(sum(log2((subProbA./probC).^q)))./(1-q);
e1(i,j) = HA(i,j) + HC(i,j);
if e1(i) >= emax
emax = e1(i);
tt1 = i-1;
end
end
end
Note that in this code, probA = 0; and probC = 0; are removed as they are over-written anyway later in the original code.
Assuming that q is scalar value, this code removes all the four for loops. Also in your given code you are calculating the maximum value of e1 only along the first column. If that is so then you should put in out of the second loop
height = 256;
width = 240;
a = repmat((1:height)',1,width);
b = repmat(1:width,height,1);
probA = arrayfun(#(ii,jj)(sum(sum(H3(1:ii,1:jj)))),a,repmat(1:width,height,1));
probC = 1 - probA;
HA = arrayfun(#(ii,jj)(sum(sum(log2((H3(1:ii,1:jj)/probA(ii,jj)).^q)))/(1-q)),a,b);
HC = arrayfun(#(ii,jj)(sum(sum(log2((H3(ii+1:height,jj+1:width)/probC(ii,jj)).^q)))/(1-q)),a,b);
e1 = HA + HC;
[emax tt_temp] = max(e1(:,1));
tt1 = tt_temp - 1;

Simple Speed-up of code

It is known that MATLAB works slow with for loop. I have tried to vectorize the following code without success. Perhaps I am wrong with the implementation.
for I = NS2:-1:1
A = 0;
for J=1:8
A = A + KS2(J,I)*FA(J);
end
S2 = S2 + ( SS2(1,I)*sin(A) + SS2(2,I)*cos(A) );
end
where:
FA = matrix 1x8
KS2 = matrix 8x25
SS2 = matrix 2x25
A = scalar
S2 = scalar
I try to improve it in this way:
A = 0;
J = 1:8;
for I = NS2:-1:1
A = FA(1,J)*KS2(J,I);
S2 = S2 + ( SS2(1,I)*sin(A) + SS2(2,I)*cos(A) );
end
However, the runtime for this improvement is similar to the original code.
Try this instead (no loops):
A = (FA*KS2).'; %'# A is now 25-by-1
S2 = SS2(1,:)*sin(A) + SS2(2,:)*cos(A);

Resources