【枚举的思想】模型检验

枚举的测试设计思想,强调的是“聪明的枚举”,也就是在枚举的同时尽可能压缩测试集的规模,以控制测试成本。控制测试成本的方法主要有两种,一种就像组合测试、分割测试那样,减少测试用例的数量;还有一种,是降低每个用例的执行成本。

第二种方法的常规实现方式,就是利用计算机仿真技术。比如在芯片领域,这种做法就非常普遍:

针对一个被测芯片,用形式验证驱动器来仿真所有可能的输入信号,然后用性质检查器,判断芯片的输出结果是不是和期望相符。如果在整个枚举测试过程中,性质检查器给出的fails( )信号始终是0,就说明被测芯片是正确的。

“模型检验”是另一种借助计算机仿真技术的枚举测试方法,也是现在最主流的形式化验证方法。为什么叫形式化验证方法呢?因为要借助计算机来做验证,我们就必须把被测对象的理想和现实,都表示成计算机能够理解的形式。什么形式是计算机最容易理解的呢?主要是结构化数据、算数或逻辑表达式。模型检验这种方法,就是用结构化数据的形式来描述被测对象的现实,一般叫做形式化模型;用逻辑表达式的形式来描述被测对象的理想,一般叫做形式化规约。

那么,什么样的被测对象比较适合用模型检验呢?目前主要是各种状态转换系统。比方说我们要测一个通信协议,它的形式化模型就是这样一个状态转换图:

我们想要证明,只要发送方发出了请求,就一定能收到回复。这个期望可以表示成这样一个形式化规约:

接下来,我们就可以跑一个模型检验的算法,让计算机去枚举形式化模型的所有状态,检查是不是在每一个状态下,形式化规约都成立。如果是,模型检验就通过了。

形式化模型

我们要注意,被测对象的形式化模型,并不等于被测对象本身。即使模型检验通过了,我们也并不能直接就断言被测对象就是正确的,而是要进一步考虑形式化模型和被测对象本身之间的差异。

实际上,形式化模型是从被测对象的实现机制中抽象出来的。这里就有一个抽象程度高低的问题。比方说,被测对象是一架飞机,模型的抽象程度可以很高,高到只具有飞机的外形轮廓:

用这样的模型来做模型检验的话,就会出现我们刚刚提到的问题:模型和被测对象差异太大,模型检验的正确性结论,不能代表被测对象的正确性结论。

但这并不等于说,模型的抽象程度越低越好。比如这种专业的航模:

上面有发动机、螺旋桨、油箱,工作方式跟真飞机几乎一样。对模型检验来说,这样的模型就太复杂了,分析起来很难,而且状态空间规模会非常庞大,要枚举它的所有状态,成本会很高。

下面我们就来介绍两种常用的、建立形式化模型的方法。第一种是迁移系统。迁移系统模型非常简单,里面只有两种要素,状态和迁移。状态指的是被测对象在某个时刻的行为特征或属性特征,比如交通信号灯有红灯、绿灯、黄灯3种状态;迁移指的是被测对象从一个状态转换为另一个状态,比如交通信号灯从绿灯变成黄灯,就是一个迁移。

下面这个有向图,表示的是自动售货机的迁移系统模型:

其中的节点表示状态,边表示迁移,边上面标注的是迁移发生的条件。这个模型很清楚地反映了自动售货机的工作机制:初始状态是“等待选择商品”,一旦有顾客选择了商品,就进入“等待支付”的状态;顾客支付完成后,进入“商品出货”状态,最后回到初始状态。

下面我们讨论一个稍微复杂的形式化模型,Petri网。很多时候,系统状态的变化,是因为系统里某些元素的位置发生了变化。比如说一扇门,当门锁里的弹子,从锁芯进入锁槽的时候,门也就从打开的状态,变成了上锁的状态。在Petri网模型里,我们把弹子这样的元素叫做系统的资源。资源可以是物质的,也可以是信息的。资源的位置表示系统的状态,资源的流动触发了状态的变迁。

Petri网里有这样几种要素:

  ① 圆形节点叫做“库所”,代表资源可能所处的位置;

  ② 库所中的黑点叫做“令牌”,代表系统中的资源。如果一个库所里有令牌,这个库所的令牌储量就是1,否则就是0。所有库所的令牌储量构成的向量,可以表示系统的当前状态。比如在下面这个Petri网里:

只有库所P1里有令牌,所以系统当前状态可以表示为(1,0,0,0)。

  ③ 箭头叫做“弧”,代表资源的流动方向;

  ④ 灰色小长条叫做“变迁”,代表资源的流动。当一个变迁的所有输入库所都拥有令牌的时候,这个变迁才会发生,变迁之后输入库所的令牌流动到输出库所里,系统状态就发生了变化。比如t1这个变迁发生之后,库所P1里的令牌就会流动到P2里,系统状态就会从(1,0,0,0)变成?(0,1,0,0)。

再举一个例子,给消防员救火的过程建一个Petri网模型(假设消防员只能用水桶救火。水和桶是这个模型里最主要的资源):

令牌现在在库所P1’里,说明变迁t1刚刚发生,这代表消防员刚刚把水泼到火场里,正在拎着空桶往水源地跑;等到消防员跑到水源地,打满一桶水,变迁t2就发生了,令牌会流动到P1里,这代表消防员又开始拎着一桶水往火场跑。

如果火势很大,只靠一位消防员肯定是不行的。下面这个Petri网模型,描述了5名消防员,在火场和水源地之间接力运水救火的过程:

  ① 变迁x1类似上个模型里的t1,表示离火场最近的一名消防员把一桶水泼到火场里;

  ② 变迁f4类似上个模型里的t2,表示离水源地最近的一名消防员从水源地接了一桶水;

  ③ 变迁y1~y4表示相邻的两名消防员交换一桶水和空桶的动作。比如现在这个状态,离火场最近的1号消防员手里是空桶,说明他刚刚把一桶水泼到火场里,拎着空桶往后跑;跟他相邻的2号消防员正拎着一桶水往前跑,他们俩一旦相遇,1号就接过2号手里的一桶水转身往前跑,2号就接过1号手里的空桶转身往后跑,这样变迁y1就发生了,库所P2里的令牌就会流动到P1里,P1’里的令牌就会流动到P2’里。

Petri网有一个特点,就是可以描述并发。比如1号和2号正在交换水桶的时候,5号可能正在运水,也可能正在运桶,他们的行为之间并没有时序关系,这就是并发。

形式化规约

下面我们讨论模型检验的理想,也就是形式化规约。古希腊哲学家赫拉克利特说:“人不能两次踏入同一条河流,因为无论是这条河还是这个人都已经不同”。

同样,被测对象的状态,也会随时间发生变化,状态变化的轨迹,就形成了一个状态序列。

很多时候,期望也会随时间变化,比如“在状态序列的某个时刻之后,应该怎样怎样”。但是,基本的命题逻辑没办法描述这种期望。这时候我们就需要用到“时序逻辑”。时序逻辑通过引入□/◇/U等一组时序算子,跟时间成为了朋友。我们来看几个最基本的时序逻辑公式:

(δ, j) ⊨ □f。□f指的是“命题f一直为真”。δ表示被测对象的一个状态序列,j表示其中第j个状态,符号⊨表示“满足、成立”。整个表达式的意思是:对状态序列δ来说,f在时刻j及其之后的任一时刻均成立。

(δ, j) ⊨ ◇f。◇f指的是“f终将为真”。整个表达式的意思是,对状态序列δ来说,f一定会在时刻j或其之后的某一时刻成立。

(δ, j)  ⊨ ◯f。◯f指的是“f即将为真”。整个表达式的意思是,对状态序列δ来说,f会在时刻j的下一个时刻成立。

(δ, j)  ⊨ f U g。意思是,对状态序列δ来说,从时刻j开始,到g成立为止,f都成立。而g一定会在时刻j或其之后的某一时刻成立。

我们来看一个线性时序逻辑的应用示例。这是一个弹簧的迁移系统模型:

初始是自然状态s1,从两头用力拉,可以让弹簧处于拉紧状态s2,释放之后弹簧会恢复自然状态,但如果拉的时候用力过猛,弹簧就会失去弹性,进入状态s3,而且没办法再恢复。e和m都是命题变项,e代表“弹簧伸长”,m代表“弹簧失去弹性”。显然,当弹簧处于s2状态的时候,e成立;当弹簧处于s3状态的时候,e和m都成立。

这个模型可能产生无穷多种状态序列。如果拉紧弹簧的力道一直都控制得很合适,s1和s2就会交替出现,这就是状态序列ξ0=s1s2s1s2s1s2s1...;如果拉第一次就用力过猛,弹簧崩了,那就会出现状态序列ξ1=s1s2s3s3s3s3s3...;如果拉两次之后崩了,那就会出现ξ2=s1s2s1s2s3s3s3...。

对于状态序列ξ2,有这样一组结论:

(ξ2, 1) ⊨ ◯ e(弹簧在下个时刻会伸长)

(ξ2, 1) !⊨ ◯◯ e(弹簧在下下个时刻会伸长)

(ξ2, 1) ⊨ ◇e(弹簧终将伸长)

(ξ2, 1) !⊨ □e(弹簧一直伸长)

(ξ2, 1) ⊨ ◇□e(弹簧最终会一直伸长)

(ξ2, 1) !⊨ (¬e) U m(弹簧直到失去弹性才能伸长)

这些,是针对ξ2这个状态序列的初始状态的结论。如果所有状态序列的初始状态,都满足某个形式化规约,我们就说模型满足这个规约。对于弹簧的迁移系统模型,有如下结论:

M ⊨ ◇ e(任何状态序列都会到达弹簧伸长的状态)

M ⊨ □(¬e→◯e)(在任何状态序列下,如果弹簧没有伸长,那么它一定会在下一状态伸长)

M !⊨ ◇□e(任意状态序列最终将会达到弹簧永远保持伸长的状态)

M !⊨ □(e→◯¬e)(弹簧一旦伸长,总会在下一个状态恢复自然)

可以看到,形式化模型不满足一个形式化规约,很多时候是因为只有部分状态序列满足,另一部分状态序列不满足。那么,如果我们实际想要的没有那么严格呢?如果只要一部分状态序列满足就够了呢?这时候我们就需要用“分支时序逻辑公式”,来表达这种相对宽松的形式化规约。

我们说过,被测对象的状态,会随时间发生变化,而且变化的轨迹还可能有很多条,每一条轨迹就是一个状态序列。如果把状态序列看做一条状态转换的路径,每一个状态就是这条路径上的结点。从初始状态出发,可能会产生不同的路径分支,最终形成一个树状结构。

在线性时序逻辑的基础上,分支时序逻辑里引入了两个路径量词,A表示“所有路径”,E表示“存在一条路径”。例如:

(M, s0) ⊨ A□f,意思是“对模型M来说,从s0出发的所有路径上的所有状态结点都满足f ”:

(M, s0) ⊨ E□f,意思是“对模型M来说,存在一条从s0出发的路径,使得该路径上的所有结点都满足f”:

(M, s0) ⊨  A◇f,意思是“对模型M来说,从s0出发的所有路径最终都存在一个结点满足f ”:

(M, s0) ⊨  E◇f,意思是“对模型M来说,存在一条从s0出发的路径,在该路径上会有一个结点满足f”:

(M, s0) ⊨  A◯f,意思是“对模型M来说,从s0出发的所有路径上的第二个结点都满足f”:

(M, s0) ⊨  E◯f,意思是“对模型M来说,存在从s0出发的一条路径,该路径上的第二个结点满足f”:

(M, s0) ⊨  A( f  U g ),意思是“对模型M来说,从s0出发的所有路径上,都存在一个结点满足g,并且在该结点之前所有的结点都满足f”:

(M, s0) ⊨  E( f  U g ),意思是“对模型M来说,存在一条从s0出发的路径,该路径上存在一个结点满足g,并且在该结点之前所有的结点都满足f”:

标记算法

我们已经讨论了适合计算机理解的形式化模型和形式化规约。接下来我们就来简单介绍一下,怎样让计算机去枚举形式化模型的所有可能状态,检查是不是符合形式化规约的要求。这里有一个主要的问题,就是形式化规约经常很复杂,要判断一个状态是不是符合规约,往往是很困难的。

怎么解决这个问题呢?一个典型的方法是标记算法。标记算法的基本思路是化整为零,也就是把复杂的规约公式拆解成一些比较简单的子公式,然后逐个击破。

因为所有分支时序逻辑公式都可以转换成如下一组完备算子的组合:

我们可以先把原始的规约拆解成用这组算子表示的子公式。针对每个算子,我们可以设计一种符合性判定的简单算法:

比如对A◇f来说,它的意思是“从某个状态节点出发的所有路径最终都存在一个结点满足f”,它的标记算法是这样的:“从路径树的叶节点出发,自底向上枚举所有状态,如果f在状态s成立,或者A◇f在s的所有直接后继状态上都成立,则将A◇f加入L(s)中”,L(s)是状态s的标记集合,把A◇f加进去的意思就是,状态s满足A◇f。

我们结合一个具体的例子,来看看标记算法的具体应用过程。假设被测系统的形式化模型是这样一个迁移系统:

系统有5种状态,在s0/s1/s2/s4状态下,命题p成立;在s3状态下,命题q成立。系统的形式化规约是这样一个分支时序逻辑公式:

可以看到这个公式还是有些复杂的,如果我们想直接去判断每个状态是不是满足这个公式,其实并不容易。

下面我们就用标记算法去做这个符合性判定。首先将原始公式转换成完备算子组合的形式:

然后由内而外定义子公式:

接下来我们根据标记算法,由内而外对各层子公式进行状态标记,结果如下:

这样我们就得到了所有状态对各层子公式的符合性判定结果:

可以看到,模型只在状态s3下满足原始规约g7,在初始状态s0下并不满足。最终结论是,被测对象的模型不满足规约。

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值