准备工作
给定您的示例案例,您希望区分与基本项相关的测试条目间隔,因为在算法的结果中不应该分割测试条目间隔。在
我将首先描述一个在更一般的设置中的解决方案,其中基本间隔和测试条目间隔是相同的。然后将对该解决方案进行补充,以满足保留的测试条目。在
此补充假设测试输入间隔不重叠。第二个修改确保在运行算法之前,重叠的测试条目间隔在概念上被折叠成一个单独的间隔。在
注意事项
此解决方案不提供压缩包装的python实现,而是提供伪代码。不过,将其转换为有效的python应该很简单。在
大纲
最初的时间间隔覆盖了一天的某一部分p。p是这些间隔的并集。请注意,此并集是一组有序的非重叠间隔集。在
基本思想是通过满足3个条件的不同时间间隔来覆盖p:间隔精确地覆盖p
间隔不重叠
原始集合的任何区间边界都不能是新集合的区间内部元素。在
考虑原始区间集的边界时间集。此集合中的元素按规范顺序排列。从这个集合建立由相邻时间点定义的间隔序列。结果是包含p的非空区间的无间隙并置。在
由于p可能是非连续的,因此构造的序列必须与p相交才能得到最终结果。此交叉口不
改变计算集中的任何间隔;但是,它可以消除一些。在
算法(通用)收集列表中的所有时间间隔边界tl_ta。tl_ta的元素应该是实际时间的对和一个标志,该标志指示元素是间隔的开始还是结束。此标志将用于跟踪p中的间隙。
按元素对的第一个组件对列表进行排序
迭代经过排序的时间点列表,构造非重叠间隔的结果列表。在
为了达到这个目的,你需要。。。在结果列表tl_cover(最初为空)。在
当前和上一个迭代元素ta_current,ta_previous。在
一个计数器cnt_active,指示当前时间点包含的间隔时间(最初为0)。在
在迭代的每个步骤中,将执行以下操作:如果当前时间间隔中的某个时间点和当前时间间隔中存在新的结果,则推送列表中的某个时间点和结果不同:
if (ta_previous[0] != ta_current[0]) && cnt_active > 0 then
tl_cover.push ( [ta_previous[0], ta_current[0]] );
end if
如果当前时间是间隔开始,则增加活动间隔的计数器:
if ta_current[1] then cnt_active++; end if;
如果当前时间是间隔结束,则减少活动间隔的计数器:
if !ta_current[1] then cnt_active ; end if;
更新当前和上一个时间点:
ta_previous = ta_current; ta_current = shift tl_ta;
算法(补码1-稳定的测试输入间隔)
为了保持测试条目间隔的完整性,在迭代过程中维护一个标志b_preserve,该标志指示测试条目间隔当前是否处于活动状态。在此期间,不得终止新的间隔。在
因此,来自tl_ta的元组变为三元组,第三个组件指示这个时间点是否来自测试条目。处理测试项的开始/结束时间设置/重置b_preserve。在
tl_ta应该按字典顺序对元组进行排序(tl_ta[_][0], !tl_ta[_][1], tl_ta[_][1] ? tl_ta[_][2] : !tl_ta[_][2]),这样在相同的时间。。。在。。。上面的首先处理区间界限
。。。在较低的区间界限中,首先处理测试入口边界
。。。在区间上限中,最后处理测试入口边界
此约定防止具有公共边界的多个测试和基本输入间隔之间的干扰。在
每个迭代的第一步现在还检查测试入口包含:if (ta_previous[0] != ta_current[0]) && (cnt_active > 0) && !b_preserve then
tl_cover.push ( [ta_previous[0], ta_current[0]] );
end if
新变量与活动间隔计数器一起维护:
^{pr2}$
算法(补码2-重叠测试输入间隔)
使用初始化为0的计数器cnt_active_te来处理重叠,而不是使用布尔值b_preserve。每个迭代的第一步中的新检查:if (ta_previous[0] != ta_current[0]) && (cnt_active > 0) && (cnt_active_te == 0) then
tl_cover.push ( [ta_previous[0], ta_current[0]] );
end if
维护cnt_active_te而不是{}:if ta_current[2] then
cnt_active_te += ta_current[1] ? 1 : -1;
end if;