Symbolic Mining of Temporal Specifications中文翻译.docx
《Symbolic Mining of Temporal Specifications中文翻译.docx》由会员分享,可在线阅读,更多相关《Symbolic Mining of Temporal Specifications中文翻译.docx(24页珍藏版)》请在冰豆网上搜索。
SymbolicMiningofTemporalSpecifications中文翻译
基于时序描述的符号挖掘
摘要:
项目说明书在软件开发过程的许多阶段中起着重要作用,但是它们却经常被省略或者是不完整的。
重要的一类说明书表现为具有时序特性的形式,规定了软件系统组成部分合适的用法。
近期的工作重点是程序在静态或运行时行为时序描述的自动推理。
很多技术匹配一种描述模式(以有限状态机为代表)到程序组成的所有可能匹配,并枚举了可能的匹配。
这些方法具有高的空间复杂度并且在两个字母的交换式(例如(ab)*)并没有实现简单化的要求。
在这篇文章中,我们精确地定义了这种形式的描述挖掘并且说明它通常的形式是NP完全的。
我们观察了大量出现的规律并追踪了系统组成的所有可能组合。
这激发我们引进一个符号算法,基于二进制的决策图(BDD)来利用这个规律。
我们的结果显示这个符号算法通过按照时间和空间的量级顺序使得这个问题更易处理。
它使得我们能够挖掘更多复杂的描述,例如常见的三字母的资源获取、作用,以及释放模式((ab+c)*)。
我们在实际工具上实现了我们的算法并利用它找到了真实系统中的重要描述,包括ApacheAnt和Hibernate。
我们利用这些描述去寻找之前未知的错误。
分类和主题描述符:
D.2.7[软件工程]:
分布,维护,以及增加——重建,逆向工程,以及再造;
F.3.1[程序逻辑和意义]:
程序的描述、证实和推理
一般用语:
语言,算法,证实
关键词:
符号挖掘,动态分析,正式描述
1.介绍
在软件开发过程中精确的计划书是无价之宝。
这些计划书往往表现为描述了时序特性的有限状态机的形式。
这些特性形式上详细说明了与具体的系统组成的合法交互模式。
包括交替特性这样权威的例子,像锁定捕获和释放,以及资源占有特性,像调用read(fd)的要求在open(fd)和close(fd)之间调用必须全部存在。
规范运用时,时序描述能够帮助廉价地预防未来程序错误的出现。
不规范使用时,这些计划书为证实模式检查和静态核实[3,9,12,24],轻度权值静态分析技术[7,14],或者人工检验提供后援。
这些特性也可以通过软件测试得到证实,在测试中它们可作为系统常量得到证实。
这些特性的特征能够为测试案例提供帮助。
这些计划书往往易丢失,不正确,或者是不完整的。
研究人员已经认识到这个问题并且试图为基于它们通常行为的系统推理计划书寻找方法。
目前的技术可以按照输入和输出的分别的算法来分类。
绝大部分算法采取输入一些程序或者跟踪程序来产生一个或多个有限状态机的时序描述。
更具体一点,一些技术[1,2,23]寻找产生一种基于已知初始态的单个的,具有反复复杂性的状态机。
例如,人们或许想学习一种语言套接字API的交互模式。
用户提供API函数的算法和程序描述(源代码或者动态分析),于是返回了一个描述可能是正确行为的有限状态机。
其他技术[10,18,21,25]把输入看成一个以描述模式形式的状态机。
用户提供了一个有大量输入符号的算法,通常代表了系统中的每个函数,跟踪过程中的事件,和程序实现。
算法枚举了赋给状态机初始态的系列值进而让状态机得交互模式来支持程序。
绝大多数先前的工作重点聚焦在交换模式。
例如,用户提供了一个可交换的模板,它代表了规则的表达式(ab)*,一个程序,和一个可能多个值的初始态。
算法返回了匹配这个表达式的一系列特性,包括锁定捕获和释放这样的特性。
对这种可交换模式的限制的原因是追踪输入状态机初始态所有可能值要付出的代价。
基本算法追踪每个可能程序执行值的状态。
这种方法有个大空间的要求:
对n路输入符号和一个大小为k的的模式初始态,这些算法要求空间大小为O(nk)。
因为在可交换模式中,只有两个关系者,计算可以以二次关系进行。
工作提供了一个新颖的符号技术来为这种符号推理服务,这种符号推理由于运用了二元决策图(BDD)[6]被高效地改进了。
由于运用了问题空间的规律性,我们的技术减少了空间和时间的要求来形成一个高效的符号表述。
在对大型系统的实际跟踪的经验评估下,我们观察到我们的算法能够进一步解决至少是三个字母作为初始态的描述模式。
更重要的是,这允许先前提到的常见的资源获取/使用/释放协议由类型(ab+c)*来描述。
我们已经应用我们的算法到实际系统的跟踪中,并且运用发现的特性来找到先前位置的程序错误。
这篇论文做出以下技术上的贡献:
(1)我们正式提出了基于种类的描述挖掘问题并且证明它的通常形式是NP完全的。
(2)我们提供了一个基于二元决策图(BDD)的符号算法,从而让此问题大大易于计算机化处理。
(3)我们对我们的算法提出了实际的修正进而允许对不完美的输入数据的要求范围和容忍度。
(4)我们执行了一个基于我们算法的描述挖掘工具并且评估了它的表现。
我们运用了这个工具挖掘了几项有趣的描述,我们用此在我们的实际系统中找到了先前未知的程序错误。
论文的剩下部分结构如下:
我们以对基于类型的描述挖掘问题给出形式上的定义开头,并且分析了它的计算复杂性(第二部分)。
接着描述了我们的符号算法(第三部分),它包括了关于BDD的必要背景信息。
然后讨论了我们的实现并且呈现了我们经验评估的结果(第四部分)。
最后,我们讨论了相关工作(第五部分)并且为未来的工作总结了一下想法(第六部分)。
2.正式分析
在这一部分,我们正式提出了基于种类的描述挖掘问题并且分析了它的计算复杂度。
我们也分析了它的表达来推进了我们的工作。
2.1描述挖掘问题
我们的工作聚焦在动态路径中的挖掘特性,这与Yangetal.的工作相关[25]。
我们首先给出这个问题的精确定义。
定义2.1(描述挖掘)假设我们有初始态为∑的状态机A和一个不相交的初始态∑’执行路径T,例如,∑∩∑’=∅。
基于类型的描述挖掘问题定义成枚举所有满足并且一一对应的映射ρ:
∑∑’,满足这样的条件,投射路径T在ρ上由ρ(A)接受,A是同样的道理,除了每个变换δ(s,a)=t由δ(s,ρ(a))=t代替。
考虑以下路径实例:
open,use,use,close,dispose,get,get,open,use,close,dispose
(打开,使用,使用,关闭,处理,获取,获取,打开,使用,关闭,处理)
假设我们通过路径挖掘图1中可交换的状态机类型。
在这个例子中,赋值(a=open,b=close),(a=open,b=dispose),和(a=close,b=dispose)在路径上是满足的。
为了阐述这个问题的复杂性,我们证明它的通常的决定问题部分是NP完全的。
图1:
一个表现了可交换类型的状态机
定义2.2(符号挖掘问题)给定初始态为∑的状态机A和一个不相交的初始态∑’执行路径T,例如,∑∩∑’=∅。
符号挖掘问题提出了是否存在一个完全的和一一对应的映射:
∑∑’,满足这样的条件,投射路径T在ρ上由ρ(A)接受,A是同样的道理,除了每个变换δ(s,a)=t由δ(s,ρ(a))=t代替。
有趣的是,很显然的是,|Σ|≤|Σ’|。
如何简化是哈密顿路径问题。
首先让我们回忆下这个问题的定义。
定义2.3(哈密顿路径)我们考虑问题的定向版本:
给定一个定向图G=(V,E),G有没有一个路径访问每个v∈V仅仅一次?
这个问题由于其NP完全性而广为人知[15]。
我们将给出从哈密顿路径问题到描述挖掘问题的多项式-时间简化法来证明描述挖掘问题是NP-困难的。
考虑哈密顿问题的一个实例:
G=(V,E)。
我们构建一个不具决定性的状态机A=(Σ,S,s0,δ,F)如下:
•Σ=V;
•S=∪v∈V{sv}∪{s0,s∗};
•S0是初始态;
•∀(u,v)∈E.δ(su,u)=sv;
•∀u∈V.δ(s0,e)=su;
•∀u∈V.δ(su,u)=s∗;
•F={s∗}.
令|V|=n,令∑’为任意的字母,∑和∑’有相同的基数(例如:
|Σ’|=|Σ|),并且不相交(∑∩∑’=∅)。
然后我们在∑’上构造一组路径T=T1…Tn,对于所有1≤i≠j≤n,Ti≠Tj。
引理2.4G=(V,E)有一个哈密顿路径当且仅当SpecMine(A,T).
证明:
(⇒)假定G=(V,E)有一个哈密顿路径p,我们构造一个映射ρ:
Σ→∑’如下:
ρ(p[i]=T[i])
这里,p[i]表示路径p上第i个顶点,T[i]表示路径T上的第i个字母(1≤i≤n)。
这个映射说明了通过考虑如下通过A的路径p,T由A来接受:
s0,sp[1],sp[2],...,sp[n],s∗
路径p引起A接受字符串
e.ρ(p[1]).ρ(p[2]).....ρ(p[n])
=ρ(p[1]).ρ(p[2]).....ρ(p[n])
=T[1].T[2].....T[n]
=T
(<==)假设SpecMine(A,T),存在一个映射ρ:
Σ→∑’,A有个路径p接受T。
由于ρ是可逆的,路径p必须有如下的形式:
s0,sψ(T[1]),...,sψ(T[n]),s∗
这里,ψ表示ρ-1,因而ψ(T[1]),...,ψ(T[n])是G的一个路径,它是哈密顿函数。
定理2.5(NP完全性)描述挖掘问题是NP完全的。
证明:
我们首先说明描述挖掘问题是NP的。
它的NP完全性遵守因为从哈密顿路径到描述挖掘问题的简化是多形式的简化是显而易见的。
描述挖掘问题是NP的,因为我们能够在多项式时间里产生一个映射ρ,并且可以检查是否投射路径由ρ(A)接受。
2.2大规模状态机的需求
考虑图2中的状态机。
它代表了类型(ab+c)*,它描述了获取一个资源并使用它,合适释放它的通用的编程任务,从程序中挖掘这个描述类型是令人满意的,但是用现有的技术要么是昂贵的(对于小规模的例子),要么是不可能的(中等大小的例子)。
在某些情况下,可能从小的特性开拓关系形成大的特性。
在我们早期的例子中,算法发现了特性(open,close)∗,(open,dispose)∗,和(close,dispose)∗。
从这3个两字母的特性和他们拓展出的关系中,我们可以推断3字母的特性:
(open,close,dispose)∗。
在他们初始态上的三种发现的语言的扩张的交集正是精确说明了推断的特性。
作为我们工作的又一动力,我们说明图2中的状态机没有两字母的分解。
图2:
一个表现了资源使用类型的状态机
定义2.6(扩张)带有初始态∑的状态机A在任意初始态∑’上的扩张,E∑‘(A),是一个状态机,A是一个和A等价的并且有一个循环变换δ(q,a)=q,增加了每一个状态q,每个字母a∈Σ’/Σ。
必要地扩张操作符是规划的反转。
例如,通常与表达式E{a,b,c}((ab)∗)一致的是c∗(ac∗bc∗)∗。
在描述挖掘的内容中,在所有可能追踪事件初始态基础上的特性扩张产生一个描述所有可能具有特性支持的程序追踪的语言。
定义2.7(分解)如果满足条件
,
具有初始态{∑1’,…,∑n’}状态机系列{A1’,…,An’}是一个初始态∑的有限状态机A。
定理2.8在图2中的资源使用状态机,R,由通常的表达式(ab+c)∗来表示,没有两个字母的分解。
证明:
令∑表示初始态R({a,b,c})。
不失一般性,我们假设分解严格地构成
的状态机,正如有相同状态子集的状态机能够联合在一起。
我们考虑这三个状态机R1,R2,R3具有代表性的初始态Σ1={a,b},Σ2={b,c},Σ3={a,c}。
从分解的定义中可以清楚地得到:
,
并遵守
,
在两边应用规划得到:
,
然后我们将这些规划转换成它们通常的表达:
,
R的每两个字母的分解的语言必须由这三种语言的扩张的交集包括。
然而,下面的追踪由交集接受却不被R接受:
a,b,b,c,b,b,a,b,b,c
它遵守R没有两个字母的分解。
2.3当下的解决方法
Yangetal.描述了一个基本的语法,Perracotta,来解决大小为2的输入带有输出带有初始态的描述挖掘问题。
算法构造了一个包括了每个可能的路径初始值赋值给状态机初始值的状态的n×n矩阵,其中n代表唯一的输入符号的个数。
每个在矩阵中的(i,j)输入最初被设置成状态机A的初始值。
算法在输入路径上循环往复。
每次输入符号s是可见的,指数i被重新取回。
然后它在每个组(根据所有(s,_)的赋值)和每个列(根据所有(_,s)的赋值),然后更新基于A的转移函数的状态。
在路径中每个符号被处理之后,它在可能在最后状态的赋值和输入中循环。
这个算法的空间要求接近为O(n2),时间复杂度是O(nL),其中L是输入路径的长度。
考虑这个算法,从三个方向作出假设的扩展。
为了追踪所有的赋值,需要大小O(n3)的空间。
另外,输入信号s的扫描现在需要更新所有的赋值(s,_,_),(_,s,_),和(_,_,s),总共的空间要求时O(n2),这把时间复杂度提高到了O(n2L)。
通常,这个方法需要O(nk)的空间复杂度和O(nk−1L),其中k是模板状态机的初始态的大小。
这对两个以上字母的初始态时间和空间消耗太大(第四部分)。
3算法描述
在这一部分,我们将细致地描述我们的算法。
我们首先给出一般的,高级的版本(3.1部分)。
然后提供一些二元决策图的背景信息(3.2部分),我们将使用一个基于图表的布尔函数描述来高效地完善我们的算法(3.3部分)。
3.1高级算法
考虑状态机(Q,∑,δ,q0,F)和在更大,不相交的路径状态∑’。
在一个高级别上,我们的算法构建了一个符号化的公式Φ:
(Σ→Σ’)→Q,代表了每项类型初始态中的路径符号赋值的当前状态机状态。
然后扫描输入路径中的每个字母,然后应用状态机的转移函数到初始公式中。
公式代表了将每个可能的赋值映射到初始状态机状态q0的初始配置。
我们成为这种符号公式为一个状态配置。
在我们的算法中,我们仅考虑Σ→Σ’的一对一的赋值;将两个相同的路径字母赋值进两个特有的状态机的字母不代表有趣的描述。
为在一个路径字母a∈Σ’上应用转移函数δ,我们更新所有受影响的赋值的状态。
考虑一个任意的状态配置Φ。
我们定义一个转移函数,trans(ϕ,a)=ϕ’,在字母a上将δ应用到ϕ上。
由以下符号公式给出:
第一个分离,ϕ∧¬(x=a∧s=q),表征了一个映射这些赋值的状态,它没有受转换(q,x)→q’的影响。
第二项,(∃s.ϕ∧(x=a∧s=q))∧s=q’,表征了受影响赋值的状态映射。
它首先设计了一个带有存在的定量的受影响的赋值,然后更新他们适合的状态到q’。
为完善这个算法,我们现在需要符号化公式的合适的表示。
我们利用二元决策图(BDD)因为它能简洁代表一个大的,规律的状态空间。
在呈现我们基于BDD的算法之前,我们首先介绍一些BDD的基本背景知识。
3.2BDD背景
一个二元决策图(BDD)[6]是一个有限系列有序的布尔变量上的布尔函数的树图的表示。
每个无终端的BDD节点和一个布尔变量相联系并且有精确的两个向外的端:
一个真值端和一个伪值端。
每个BDD有精确的两个终端节点:
一个值为0的节点和一个值为1的节点。
鉴于一个任意的真值赋给了这些变量,通过遍历一个决策树,我们能够决定布尔函数是否得到满足。
从根节点开始,依靠给联系的布尔变量的赋值,我们顺着真值和伪值边界,直到到达终节点。
如果最后的节点是一个值为1的节点,函数接受真值的赋值。
类似地,如果最后的节点是零节点,函数则拒绝真值的赋值。
BDD以一个简化的形式被使用,有时指的是ROBDD(简化的顺序BDD)。
代表了相同变量有相同继承者的节点能被融合,并且指向相同节点的带有两个继承边界的节点可以被完全移除。
ROBDD是权威的:
给定一个具体的变量排序,对给定的布尔公式至少有一个最小的BDD。
正是由于这个原因,BDD能够表现特别大的集合,只要他们表现出某种程度的规律性。
在编程语言和软件工程领域,BDD用来创建可称量的指针分析[4,22]并表现动态路径[26]。
给定一个高效的变量序列,BDD能够被足够压缩。
然而,找到一个最佳的变量序列通常上是问题独立的并且是NP完全的。
[5]
高效算法为执行在BDD上的基本布尔操作而存在,并且他们对节点数目成比例的运行。
更重要的是,BDD在算法的执行中以简化的形式获得。
考虑布尔公式(x⇒y)∧¬(z⇒y),这个公式(带有变量序列xyz)的决策树表示在图3a中体现。
(a)完整图(b)简化图
图3:
(x⇒y)∧¬(z⇒y)的BDD示例。
真值边界由立方体表示,伪值由点表示。
注意到有一些多余节点:
图表仅仅要求每种类型的一个终端节点,一些z水平面上的节点是同样的能够被联系。
当联系后,一些测试变得多余(由完全相同的真值和伪值表征)并且能够被完全删除。
当所有这些应用转换了,我们有图3b中权威的简化图。
3.3基于BDD的算法
我们用BDD完善通常的3.1部分描述的符号解决方法。
这部分描述了与BDD操作有关系的我们的算法的完善。
3.3.1运行示例
我们首先给出一个示例说明基于BDD算法的核心步骤。
假设我们想追踪初始态{a,b,c}到图1中两字母的,三状态的状态机的六种可能赋值的状态。
我们能够为总共六种布尔变量的每个字母和两个比特的状态编码。
把a编作01,b为10,c为11,图4a描述了一个代表了初始态赋值的BDD:
{(a,b,0),(b,a,0),(a,c,0),(c,a,0),(b,c,0),(c,b,0)}。
假设我们想更新所有在第一个位置包含a的赋值(a,_,_)至状态2,例如,我们应用变换δ(a,∗)=2。
我们能够在我们的一系列布尔操作上执行更新。
图4b是代表了所有第一个位置包含a的BDD。
注意到其他变量的省略:
这指示着一个“不关心”的赋值。
为取出一系列受影响的赋值,我们把这个BDD与我们的状态BDD相交,产生了图4c的BDD。
图4:
BDD状态追踪示例。
节点用它们相应的节点变量数字标出。
实线是真值边,虚线是伪值边。
为在我们主集合中移除我们分离出的集合,我们在图4b中为我们的BDD补充状态。
完整的操作包括交换本地边界到终端值为0的节点和值为1的节点中。
我们现在想要更新我们受影响的集合的状态。
我们首先通过在状态变量(图4d)上的存在的量化移除图4c中现在状态的赋值。
然后交叉BDD到一个新的状态2,(图4e),连接这个更新的集合到我们的主集合中。
最后的结果是,图4f示出了集合{(a,b,2),(b,a,0),(a,c,2),(c,a,0),(b,c,0),(c,b,0)}。
3.3.2基本算法
我们基于BDD的算法以算法1表现出来。
我们算法的输入是:
1)有限的符号的路径,2)一个总共的和路径的唯一符号到引用的一一映射,以及3)一个挖掘的状态机类型。
在第5行,我们在输入状态机的初始态中循环并且分配足够的布尔变量来编码唯一的路径符号(第6行)。
在第7行,我们建立所有可能赋值的笛卡尔积。
函数bddof(vars,values)返回一个BDD相当于在变量vars上编码values。
其他所有布尔变量被认为是“不关心”状态。
在第10行,我们在状态机的初始态的主集合中放置每个赋值。
在我们完善的版本中,我们添加一个额外的步骤。
因为复制符号的赋值不是很有趣,我们建立BDD与
一致的可能的相同的变量集合,例如,BDD中两个变量集合是相当的。
我们将这其中的每个否定相交到我们的主集合中。
然后我们在路径中循环并且重复运用转移函数。
第18行建立一个掩饰由以下组成:
1)在合适初始态位置的输入符号,2)合适的当前状态。
我们将这个掩饰与全局集合相交以便重新获取受转换影响的所有赋值。
为后来的移动将这个集合和“老”集合做并运算。
然后我们删除存在的量化中的旧有的状态(第22行)并且在新状态中相交(第23行)。
我们将更新的集合与“新”集合做并运算为后来的增加做准备。
在应用了所有的相关转换后,我们从主集合中分离出先前的赋值(第27行)并且假设更新的值(第28行)。
算法执行后,主集合包含路径最后每种可能值的状态。
在这点上,我们将这个集合与相应的最后状态的BDD相交,并且在令人满意的值中循环以获得潜在的描述。
这个算法的运行状态展示了一个高度的规律性:
算法由移动大量的任务到由状态机状态定义的比较少的部分。
实践中,BDD被证明是实现(第4部分)的一个合适的选择。
算法1基于类型的描述挖掘
3.3.3实际提高
算法1精确而高效地解决了2.1部分定义的基于类型的描述挖掘问题。
然而,为让结果对实时系统更加适用,必须提出一些实际的问题。
大小问题
尽管BDD的使用大大提高了问题的易处理性,然而一些路径仍然有许多要考虑所有赋值的唯一事件。
在我们的评估中,最大的路径由7000个唯一的事件,我们先前的算法完成了它的扫描在一个合理的时间段中。
然而,存在的问题由于太大而不能用这个方法解决是有可能的。
为减化状态空间,我们能够将原始问题分解成一系列小问题。
即便是一个非常粗糙的,保守的分解也能显著提高执行速度,实际上,当运用BDD时分解尤为高效。
因为我们能同时处理各个分解,BDD能够缓存并且与其他不相关的状态集合分享节点。
大的解决集合和不完美的路径
通常,通过匹配类型的挖掘描述产生大的结果集合。
先前的关于挖掘可交换的描述问题的工作[10,18,25]大程度上集中在开发高效排序和选择机制。
Weimer和Necula[21]集中研究关于异常的控制流路径问题,他们做了几个关于排序统计的实验。
Yangetal.[25]开发了一套探索式的滤波器大大简化和改善了解决方法的集合。
Yangetal.也改变他们的分析方法来处理潜在的不完美的路径。
路径上的不完美源于路径产生机制的瑕疵,缺乏像线程处理和对象身份的内容信息,或者仅仅是程序错误。
为满足这个问题,他们的工具排序候选描述基于一个具体的赋值传递最后状态的时间大小和它传递错误状态(一个错误的赋值被清成开始状态)的时间大小的比率。
这导致了从潜在的错误或其他的不完美路径频繁发生描述的发现。
可惜的是,我们不能直接运用这个技术到我们的分析中。
在BDD中存储不成熟的数量或者是浮点率是相当昂贵的:
集合变成多样化的,内存使用和计算时间逐步升高,导致计算分离。
我们用我们基本算法的扩展解决了这些问题。
算法2和算法1的不同在于它允许输入路径包含某种程度的不精确性,并且它仅仅返回经常发生的描述。
我们为全局状态增加一个额外集合的布尔变量。
这些变量为每个赋值编码一个令人满意的数值,路径被处理时,这些值能够递增和递减。
这些变量的声明出现在改进算法的第11行。
数量被初始化到一个特别的值,它比0大(第14行)。
如果它达到了0值,描述被丢弃(第35行)。
如果达到了临界值,我们认为它是令人满意的值并且保存下来(第24行)。
我们不必再在描述上执行转换函数,而这些描述要么是完全失败的要么是完全被接受的。
每次一个赋值进入了一个错误状态(第33行),我们减少这个数量。
每次它进入最后一个状态,我们以一个不肯定的可配置的概率增加数量。
在两种情况下,我们复位赋值的状态到状态机的初始态以便执行能够继续。
我们发现用一个临界值7(3比特),起始点2,一个可能的概率0.5能够运行的很好。
在第29行的不肯定性显著地扩大了数量,以一个概率0.5,我们能够期望一个接受的描述到达一个最后的状态是以概率1的两倍。
更重要的是,我们能够一个满足更加严格地要求—一个更大的描述界限——在没有增加额外布尔变量的情况下。