一阶逻辑公式转Kripke structure(KS)

将一段imp程序转Kripke structure(KS)。

这是系统分析与验证一门课的作业,需要将一段imp程序转为一阶逻辑公式,再由一阶逻辑公式转为 Kripke structure(KS)。并且老师要求是不能使用python.因为github上有python和t实现了完整的过程。

https://github.com/lypnol/impy

其实也有一个rust 版本

https://gitlab.com/davirain.yin/imp-interpeter

关于阶逻辑公式和Kripke structure的概念,可以参考

https://blog.youkuaiyun.com/qq_37400312/article/details/109157582

https://blog.youkuaiyun.com/Campsisgrandiflora/article/details/110505997

将Imp程序翻译为一阶逻辑公式,显然需要词法、语法解析器。在小组分工中,我负责将一阶逻辑公式转为KS.

我使用的是.net c#语言。以下就从代码实现的角度简单的总结一下这个转化过程。

一阶逻辑公式构造Kripke structure(KS)

假定对于一段这样的代码:

V= {x, y, z}, initial value: x=y=z=0

Program

 x=y+1; z=z+2;

for (y; y<=3; y++)

  if x<y then x++; else y++;

作了这样的标签化处理:

现在已经通过词法、语法分析生成了一以下这样的一阶逻辑公式:

D:{0,1,2,3,4}

V:{x,y,z}

S0(x,y,z):x=0⋀y=0⋀z=0

R:

(x=0⋀y=0⋀z=0⋀PC=M⋀PC'=L1)⋁

(x=y+1⋀SAME(V\{x})⋀PC=L1⋀PC'=L12)⋁

(z=z+2⋀SAME(V\{z})⋀PC=L12⋀PC'=L2)⋁

(SAME(ALL)⋀PC=L2⋀PC'=L22)⋁

((y<=3)⋀SAME(ALL)⋀PC=L22⋀PC'=L3)⋁

(!(y<=3)⋀SAME(ALL)⋀PC=L22⋀PC'=M')⋁

((x<y)⋀SAME(ALL)⋀PC=L3⋀PC'=L31)⋁

(!(x<y)⋀SAME(ALL)⋀PC=L3⋀PC'=L32)⋁

(x=x+1⋀SAME(V\{x})⋀PC=L31⋀PC'=L23)⋁

(y=y+1⋀SAME(V\{y})⋀PC=L32⋀PC'=L23)⋁

(y=y+1⋀SAME(V\{y})⋀PC=L23⋀PC'=L22)

一阶逻辑公式中的R过析取符号⋁将状态集连接起来。

每一状态中可能有赋值表达式、条件表达式。同时通过计数器PC、PC'指示着当前的位置以及下一个状态的位置。

使用代码处理时,可以使用这样的内存结构来保存一阶逻辑,对于每一步的转换状态 (TransitionState),使用PC标识自己,即SelfPC,PC'为找下一状态的依据,即NextPC。

R中包含着多个TransitionState.

将S0作为初始状态(或者是SelfPC=M时表达式的值)。遍历每一个TransitionState,得到新的状态。

(1)顺序状态集得更新KS状态

对于顺序语句来讲,这是显而易见的,

比如对于语句1,程序将读取到当前状态为 (x=0) (y=0) (z=0), 并且根据NextPC= L1,找一下个状态PC=L1的状态语句,即2,通过表达式 x=y+1, 可以得到新状态 (x=1) (y=0) (z=0)

(在这里,c#对于表达式 x=y+1来获取状态,需要通过反射来执行,如果是js或者python可能会有eval等函数)

条件/循环的处理

对于包含SAME(ALL)的TransitionState,状态不需要更新,这时NextPC会找到多个,意味着遇到条件分支的情况。

比如遍历到以下状态集时,NextPC=L22, 可以找到两个,那么需要结合当前状态和条件语句,判断下步的是找L3还是M'。(条件语句的判断与赋值语句一样,需要通过反射来执行,获得true/false的结果)

 

当第一次遍历到这里时,可以知道y<=3是成立,而NextPC=L3,依然是条件分支情况,状态7或者8

结合当前状态和条件语句,可以判断是下一步是L31还是L32。执行L31或者32,可以得到新的状态。然后再根据新状态回到条件语句继续作判定,直到条件不成立。

可以将以上过程归纳为如下流程:

使用Graphivz绘制KS的状态集,结果如下:

以上为简单程序一阶逻辑公式到KS。(这里的简单的指的是不考虑并发)。以下再探讨并发进程的处理。

附上示例中的代码

https://download.youkuaiyun.com/download/mochounv/19414680

并发程序一阶逻辑公式到KS

同样假定通过语法词法分析得到一阶逻辑公式如下:

我的实现基于这样的约定:

1 . 从 S0PC1=⊥∧PC2=⊥ 判定为程序为两个进程的并发的程序。且PC1和PC2为进程计数器标识。

结构的话,依然可以使用以上FirstOrderFormula 和 TransitionState的结构.

2. 以t为竞态变量(更为通用的处理方法应该是遍历了R集合为,如果一个条件没有出口,则应该是竞态条件)

内存结构与以上差不多

转为过程大致如下:

每对每一个状态条件:

      构建进程未初始化状态

      如构建 进程在入口状态

对于每一个进程:

   查找当前遍历进程的下一下状态

   判断是否到出口:

   如果是则查看其它进程

   如果不是则判断是否为等待状态

   如果是则置状态为自循环状态,且将另一进程置为进程i

   如果不是则生成新的状态

流程图如下:

以上FOL生成了这样的KS结构:

代码在这:

https://download.youkuaiyun.com/download/mochounv/19414680

以上两个示例的代码并不能非常通用,非并发和并发的状况也没处理为一个程序,实在时间限制。

程序中用于绘图的GraphViz,确实是一个非常方便的工具,既可以有c#(其它语言如java,python也行)接口,也可以基于dot的格式,生成文本,然后找个在线的GraphViz贴上文本就行。

http://www.graphviz.org/download GraphViz的下载地址。

https://github.com/remyzerems/GraphVizDotNetLib

GraphVizDotNetLib主要是通过P-invokde的方式,将GraphViz库中提供与绘制节点和和输出绘制相关的c++API封装成为c# API。并在GraphVizRenderer类中将调用这些API,实现通过传入dot 文本,输出 内存形式的图形数据。

在windows 10 中安装了graphviz时,选择把路径写到环境变量,则GraphVizDotNetLib会自动找到依赖的include和bin.

指定节点描述字符

http://cn.voidcc.com/question/p-cnrmzjdj-ms.html

节点带换行

https://www.it1352.com/1678876.html

在线绘图工具

Graphviz Visual Editor (magjac.com)

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值