How to make this loop faster?

Hello,
The following code takes 30 seconds to execute. I can't make it any faster.
Any suggestion?
Thanks!
function [ at] = obstacleAttenuation( Ant, Movel, Obstaculo,mapa )
tic
fprintf('\nInside obstacleAttenuation function!\n');
at = zeros(mapa.xlength, mapa.ylength);
for xi=1:mapa.xlength
for yi=1:mapa.ylength
att = 0;
[x, y] = bresenham(Ant.Antena_x, Ant.Antena_y, Movel.x(xi), Movel.y(yi));
for i = 1:length(x)
Obs = Obstaculo(x(i), y(i));
att = att + Obs;
end
at(xi, yi) = att;
% Obs = Obstaculo(x(1:length(x)), y(1:length(x)));
% att = sum(sum(Obs));
% at(xi, yi) = att;
end
end
fprintf('\nExit obstacleAttenuation function!\n');
toc
end
NOTE: I am using R2016a version.

Answers (1)

Is it possible to enter vectors as arguments in the function Obstaculo and get a vector as result? If so, then you could try replacing:
for i = 1:length(x)
Obs = Obstaculo(x(i), y(i));
att = att + Obs;
end
By:
i=1:length(x);
att = sum(Obstaculo(x(i), y(i)));

12 Comments

First of all, thanks for your reply!
The answer for "Is it possible to enter vectors as arguments in the function Obstaculo and get a vector as result?" is yes.
When I tried your suggestion I get the error
Assignment has more non-singleton rhs dimensions than non-singleton subscripts
in the line
at(xi, yi) = att
because att gets a vector instead of a value.
I've already tried
i=1:length(x);
att = sum(sum(Obstaculo(x(i), y(i))));
But it seems that doesn't stop running.
Apparently, Obstaculo returns a scalar when you say
Obstaculo(x(i), y(i));
and you sum them all so to get a new scalar to save in at(xi,yi), correct?
Then, make sure that when you execute
i=1:length(x);
att = sum(Obstaculo(x(i), y(i)));
you should get a row vector of partial results (first for i=1, then for i=2,...etc.). (Please, check this).
Then, when doing
sum(Obstaculo(x(i), y(i)))
you should get a new scalar again.
Hi,
The problem of that solution it seems to be that bresenham function returns a 793x793, not a 887x887 like "at" variable sholud apparently be.
Thanks a lot for you answer.
I see. Is it solved now? Always make sure of the dimensions each function returns when using them in your code.
Actually don't...
The difference between the two variables it's expected.
"at" gets 887x897 because it's the size of the image. Obstaculo gets the same dimension of the image because represents the obstacles of the map (image). Obstaculo function has the attenuation of each position of the map.
When I do
i=1:length(x);
att = sum(Obstaculo(x(i), y(i)));
I get a row vector like you said, and not a number.
But then, I should keep the attenuation in each part of the map.
In the following code, "att" gets just a number, not a row vector. I need that in order of at(xi, yi) = att; be possible. Because "att" is the sum of the obstacles on each path, and "Obstaculo" has the number of the attenuation in each part of the map. x and y are the path.
So, at the end of this function I need to have all the attenuations considering that bresenham each is a path.
function [ at] = obstacleAttenuation( Ant, Movel, Obstaculo,mapa )
at = zeros(mapa.xlength, mapa.ylength);
for xi=1:mapa.xlength
for yi=1:mapa.ylength
att = 0;
[x, y] = bresenham(Ant.Antena_x, Ant.Antena_y, Movel.x(xi), Movel.y(yi));
for i = 1:length(x)
Obs = Obstaculo(x(i), y(i));
att = att + Obs;
end
at(xi, yi) = att;
end
end
end
I am sorry for the long text.
OK, I´m not familiar with the process you are modeling, but if after executing
i=1:length(x);
att = sum(Obstaculo(x(i), y(i)));
you get att as a vector, then you have to do:
att = sum(Obstaculo(x(i), y(i)),'all');
because you need to save a scalar in each position of the matrix 'at' later on.
Jesús Zambrano
Jesús Zambrano on 28 Dec 2020
Edited: Jesús Zambrano on 28 Dec 2020
I suggest to upload the functions and dataset if the issue persists, so to clearly find out where the problem is.
It seems that isn't support by my version.
I get the error
Trailing string input must be 'double', 'native', 'default', 'omitnan' or 'includenan'.
Oh!, you are right, that option starts in 2018b, then go with
i=1:length(x);
att = sum(sum(Obstaculo(x(i), y(i))));
you said before that when trying it, it didn't stop running. Try with few points and see that everyything is working fine. Then, run it with more points, or include breakpoints so to debug it.
Make sure Obstaculo function is handling the incoming vectors correctly. If you have multiplications, divisions or powers in that function, they must be evecuted element-by-element, so it has to include dot (.) notation: .* or ./ or .^
If initially the function gives you a single value when executing Obstaculo(x(i), y(i)) every time in the i for-loop, it should gives you a vector if you remove the for-loop and gives i=1:length(x).
I was trying that right now. Strange as it may seem, it is slower than with the for loop, that's why I thought that keeps running.
Obstaculo has numbers like 14.3, 0, 23... Maybe I should just resize the image...
Thanks for your time!
you're welcome!

Sign in to comment.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Asked:

on 27 Dec 2020

Commented:

on 28 Dec 2020

Community Treasure Hunt

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

Start Hunting!