查找与时间点重叠的一组目标

时间:2014-08-04 05:30:19

标签: algorithm matlab vectorization

在某个时间点,我需要找到所有具有早于及晚于该时间点的目标。

目前我正在做以下事情:

for current_time = sorted_set_of_times;
    target_set = find([Targets.First_Time] <= current_time ... 
        & [Targets.Last_Time] >= current_time);
    % Using target_set here. Targets are not modified within this loop
end

MATLAB探测器告诉我这条线需要大约40分钟,有40,000个电话。

有没有办法可以更有效地做到这一点?

current_time按顺序在for_loop中递增。我当时认为这种情况总是在增加,这可以用来简化一些测试。例如,Targets.First_Time <= current_time将是Targets.First_Time <= current_time+n的一个子集。

numel(sorted_set_of_times)约为40,000

numel(Targets)超过1000万

4 个答案:

答案 0 :(得分:1)

方法#1

带有bsxfun -

的矢量化解决方案
eqcond = bsxfun(@le,Targets.First_Time,sorted_set_of_times) & bsxfun(@ge,Targets.Last_Time,sorted_set_of_times);
[r,c] = find(eqcond);
for k =1:numel(sorted_set_of_times)
    target_set = r(c==k);
end

建议使用逻辑索引(如果适用):如果您使用target_set索引到名为target的某个变量的某个维度,这个维度很长与该维度的Targets.First_Time相同,然后您可以使用target_set直接索引到target的维度,而不是计算eqcond(:,ind),其中ind将是索引到该循环中的sorted_set_of_times。因此,举例来说,如果您使用原始代码target中的target_set索引target(target_set,..)行,那么您可以改为target(eqcond(:,ind),..)

方法#2

简化数据方法 -

vind = find(Targets.First_Time <= Targets.Last_Time); %//Indices to reduce Targets datasize
Targets.First_Time = Targets.First_Time(vind);
Targets.Last_Time = Targets.Last_Time(vind);
for current_time = sorted_set_of_times;
    target_set = vind([Targets.First_Time] <= current_time & [Targets.Last_Time] >= current_time);
end

方法#3(方法#1,2的混合)

vind = find(Targets.First_Time <= Targets.Last_Time);
Targets.First_Time = Targets.First_Time(vind);
Targets.Last_Time = Targets.Last_Time(vind);
eqcond = bsxfun(@le,Targets.First_Time,sorted_set_of_times) & bsxfun(@ge,Targets.Last_Time,sorted_set_of_times);
[r,c] = find(eqcond);
for k =1:numel(sorted_set_of_times)
    target_set = vind(r(c==k));
end

建议使用逻辑索引(如果适用):在类似于方法#1所述的类似讨论中,您也可以对此进行逻辑索引。因此,使用与该讨论相同的符号,而不是target(target_set,..),您可以执行target(vind(eqcond(:,ind)),..)

答案 1 :(得分:1)

我不知道具体的MATLAB指令,但您可以尝试关注,为CPU交易内存:

  1. 将所有目标作为TARGET迭代。
  2. 使用二进制搜索查找min_time >= TARGET.First_Timemax_time <= TARGET.Last_Time
  3. 每次在min_time和max_time之间添加TARGET到target_set。
  4. 像以前一样迭代次数,但使用预先计算的target_sets。

答案 2 :(得分:1)

我只是在查看问题描述,我认为使用Interval TreeKD Tree可能是您正在进行的查询类型的数据结构的更好选择。(基于搜索在范围内)。

同样地,假设您使用(startTime,EndTime)构建间隔树,然后您可以对范围执行查询。 关于此类范围查询数据结构,这是一个非常好的thread on Stackoverflow

我不知道matlab,但似乎确实支持KD-TREES。 我在matlab中找不到有关间隔树的信息,但这里有一个good tutorial

答案 3 :(得分:1)

我认为使用这些数字,蛮力方法永远不会快得多。 (不是通过取出结构或使用逻辑索引)。

如果你想要一个快速算法,我认为以下内容可以起作用:

  1. 排序current_time(已完成)
  2. First_Time
  3. 排序目标
  4. 查找所有目标的起点S
  5. Last_Time
  6. 排序
  7. 查找端点E
  8. 的所有目标

    如果您有两个已排序的列表,您只需要遍历每个列表以找到相关点,从而显着降低操作的复杂性。

    现在,您只需为每个目标调用您的函数,然后使用current_time(S:E)