【论文概述】delta debugging

这是Andreas Zeller 的一篇论文,原文,是北京大学本科生算法设计与分析2014年春季课程的选读论文之一。以下是其梗概。特别鸣谢小班课上做这篇论文pre的同学...仓促间写的,并且有些地方我都觉得我理解得不到位,欢迎提出疑问以及就疑问点和我讨论。


    这篇文章主要是在描述一种名为deltadebugging的方法。这种方法是用来处理编程过程中前一版本代码可以跑过但后一版本的代码却跑不过的情况。由于两个版本之间可以有上万处改动,所以需要一种自动的算法。

   传统的RegressionContainment所采用的线性方法在以下三个问题的处理上有不足:

1、Interference(干扰).错误可能是由几处单独没有问题的change共同作用导致的。

2、Inconsistency(不一致).若干change可能会导致不可测试文件(比如编译链接无法通过)。

3、Granularity(粒度).一处改动可能很大,涉及上千行代码,需要在改动内部进一步定位。

       这篇文章所讲的dd+算法就是在以上三个方面扩展了传统算法,在没有Interference时实现了O(log(n))的复杂度,在存在Interference时实现了O(n)的复杂度,在存在Inconsistency时还可以照顾到Granularity问题.

 

   为了能够更好地描述、处理这个问题,文中给出了如下定义:

   记C为所有change组成的集合,则称C的任一子集c为一个configuration,称空子集为baseline。(我们认为change是顺序无关的。)

    我们可以对一个configuration进行测试,产生的测设结果会是如下三种之一:PASS √;FAIL ×;UNRESOLVED ?。定义test为产生测试结果的定义在C的子集族上的函数。

   在我们的命题中,假设yesterday为baseline,today为C,有:test()=√test(C)=×

       定义failure-inducing change set满足所有包含它的configuration测试结果不为√。定义minimal failure-inducing set为一个failure-inducing change set但其任意真子集测试结果不为×。

    在上述定义下,我们的目标建模为寻找minimal failure-inducing set.

   我们定义一些configuration C的特征属性,这些属性的满足与否会影响我们的算法时间。

1、Monotony(单调性):对"C的子集c,若test(c)= ×,则包含c的集合的测试结果不为√。

(这使得若test(c)=√,则c的所有子集测试结果都是√或?。)

2、Unambiguity(无歧义):对"C的子集c1,c2,若其测试结果均为×则其交的测试结果不为√。

(这要求产生错误的change集是唯一的,不允许两个无交集的change集分别导致错误。)

3、Consistency(一致性):任何configuration的测试结果不为?。

    上面这些特征属性要求得非常苛刻,但是所有改变的全集C的很难满足并不妨碍C的很多子集满足。对于满足上述性质的子集通过更好地利用上述性质来简化我们对这个子集的处理从而简化对全集的处理是我们这个算法的核心思想。

 

    首先,对于Monotony&Unambiguity& Consistency的全集C,我们可以基于二分查找的方法,设计出如下的高效算法寻找minimal failure-inducing set。(dd算法)

    若|C|=1,则C为minimal failure-inducing set。

    若非,则将C分割成c1和c2,分别测试。由Unambiguity与Consistency,测试结果为如下三种:test(c1)= ×,test(c2)= ×,test(c1)=test(c2)=√.对于前两种情况,我们分治地继续下去。

    对于第三种情况,我们将baseline设置为c2,然后将c1视为全体change的集合,进行测试,我们会在其中找到一个minimal failure-inducing set:α∪c2,再以c1为baseline,将c2视为全体change的集合进行测试,再在其中找到一个minimal failure-inducing set:β∪c1。由Unambiguity,其交集α∪β也是failure-inducing change set.

    若α∪β不是minimal failure-inducing set,则不妨α’∪β为failure-inducing change set, α’为α的真子集。由Monotony, α’∪c2也是failure-inducing change set, α’在c2为baseline的情况下为failure-inducing change set,与α的minimal failure-inducing set矛盾!故α∪β就是我们的目标。

    根据分治策略可以算出,上述dd算法平均是O(log(n))的。其最好情况是log(n)的,在minimal failure-inducing set只有一个元素时取到。最坏情况是2n的,在minimal failure-inducing set等于C的时候取到。

    将上面这个算法不加修改的运用到不满足这些性质的情况依然有收效。

    对于Ambiguity的情况,dd算法会输出其中的一个导致错误的地方。我们可以通过逐一发现逐一修改的方式来解决问题。

    对于not monotone的情况,如果a错但是包含a的b对的话,严格来讲,a就已经不是failure-inducingchange set了,我们的dd算法找不到a也是正常的。并且由于b对,包含b的C错,所以C-b中一定还有failure-inducingchange set(有可能有来自b的Interference),这样我们的dd算法就会去寻找那个错误。

 

    很多情况会导致Inconsistency,而这种情况下,我们必须对dd算法进行扩展得到如下的dd+算法。

    扩展方式是我们先定义一个展开程度量n,初始为2.将C划分为子集c1,c2….cn,`ci表示ci的补集。我们对ci及其补集进行逐一检测。若对其中的某一个test(ci)= ×,则我们分治地将问题规模转化为ci(Cà ci).若存在一组ci,`ci的测试结果均为√,则视为interference进行处理,以分别以ci和`ci为baseline,在另一边中寻找minimal failure-inducing set,类似于上面的dd算法,我们可以证明其交为我们的目标。若存在一组ci,`ci的测试结果为√和?,我们以√的那个集合为baseline,对?的那部分集合进行分治处理,这样可以有效缩小我们所认定的failure-inducing change set的大小。(我觉得如果需要的话还可以在这个结果的基础上重新运用这个算法进一步尝试去缩小范围。)如果上述情况都不满足但n<|C|的话,我们将n变成2n(若大于了|C|,则取为|C|),重新做上面最初的检测。如果n已经是|C|了,则C就是我们所求出来的。

    在没有测试结果为?的时候,dd+算法会自动退化为dd算法。算法依然有着线性的时间。只要输出结果是安全的,dd+算法就能保证输出的结果是最小的。不过尽管如此,算法还是保证了所有安全且不包含错误的集合都被排除在结果之外了。(定义安全的改变集:无论加载在baseline上还是从today的情况中剔除,都是可测的。)【我对后面的这段分析的理解可能不太正确。】

 

    在实际中,我们会采用以下两种方法来尽量减少讨厌的?的出现。

1、提前对因关联导致分开不可测的change进行打包处理。(process criteria,打包在时间上和修改人上有共同点的改变。location criteria,打包文件或者文件目录上有共同点的改变。lexical criteria, syntactic criteria,对同一个函数或者模块的修改, semantic criteria等等…)

2、对某些可能会出现?的情况不错检测直接视为是?。在某些例子中如果我们明知道几个变化时相关联的(我觉得没有打包处理可能是不太确定或者其它什么原因吧。),对其测试结果预测为?,预测正确会大大减少测试,预测错误也不会产生过于严重的影响。

 

    【原文中的两个实例看看就好了,感觉没什么太大的理论价值,只是show一下而已。】

 

    目前对于这一类算法的研究还非常不够,这种方法在一些别的领域应该也会有用的。我们可以用很多临近领域的知识和理念来进一步优化我们的算法,比如检测实际未执行的代码段并在测试中将这部分的修改去除等。






疏漏很多。忘指教...O(∩_∩)O谢谢~

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值