Loop erasing random walk
Show older comments
Hi, I'm trying to find a fast way to detect loops in a vector. By loop I mean repetition of an integer and by loop erasing remove all integers between two occurrence of any integer For instance,
v=[3 1 4 6 7 9 1 22 87 33 35 36 37 35 34] should be equal to [3 1 22 87 33 35 34]
basically these are the nodes that I'm visiting in a graph and there may be loops. I just want to obtain a simple path (without loops). I found solutions but require "for" loops and I need this to be performant since it will be applied to every walk (100'000 walk of length up to 2'000 ). If anyone could help it will be greatly appreciated.
4 Comments
Jan
on 25 May 2011
What do you want as output for v=[1, 2, 3, 2, 3]?
It would be much easier to find an equivalent vectorized solution, if you post your working FOR-loop approach - then we have a chance to knwo, what "equivalent" exactly means.
Mehmet Candemir
on 25 May 2011
Jan
on 25 May 2011
In the example in the question, the both 1's are deleted. Here you keep the first (or last) value of the loop. Which behaviour is wanted?
Mehmet Candemir
on 25 May 2011
Accepted Answer
More Answers (1)
Jan
on 25 May 2011
A FOR-loop approach, which might be fast already due to Matlab's JIT acceleration:
v = [3 1 4 6 7 9 1 22 87 33 35 36 37 35 34];
off = false; % Faster to call function FALSE once
n = length(v);
use = true(1, n);
for i = 1:n
if use(i)
multi = find(v((i + 1):n) == v(i), 1, 'last');
if isempty(multi) == 0
use((i + 1):(i + multi)) = off;
end
end
end
v = v(use);
If you expect long loops, a WHILE method can be faster:
off = false; % Faster to call function FALSE once
n = length(v);
use = true(1, n);
i = 1;
while i <= n
multi = find(v((i + 1):n) == v(i), 1, 'last');
if isempty(multi)
i = i + 1;
else
use((i + 1):(i + multi)) = off;
i = i + multi + 1;
end
end
v = v(use);
Using the smallest possible integer type for v will reduce the processing time:
v = int16(v);
5 Comments
Mehmet Candemir
on 25 May 2011
Mehmet Candemir
on 25 May 2011
Mehmet Candemir
on 25 May 2011
Jan
on 25 May 2011
I get the same [98 17 21 57 1 49 99 54 62 76 85 68 66] with both versions. And 80 appears inside [49 80 49], such that it should *not* be there. Please check this again.
For your small test-vector of length 169 I get these timings (Matlab 2009a, 1.5GHz PentiumM):
tic; for i=1:20000, r = Andrei(v); end, toc % 4.39 sec
tic; for i=1:20000, r = JanFor(v); end, toc % 1.50 sec
tic; for i=1:20000, r = JanWhile(v); end, toc % 0.85 sec
I've constructed a longer testvector by [v,v+500,v+1000,...]. For a vector of length 13520 the WHILE method is 5 times faster than the 2*UNIQUE method.
Mehmet Candemir
on 25 May 2011
Categories
Find more on Loops and Conditional Statements in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!