FIFO

本例子是一个先进先出FIFO的Buffer。Sender向Buff发送数据,Buffer接收数据存储在Sequence中,然后,Buffer将Sequence中第一个数据取出发送给Receiver。可以理解为上一例子的复杂应用。

TLA+提供了 Sequences module可以直接使用,该module提供了 Append,Tail,Head,Len 等常见接口。

\* module使用之前要先Extend
EXTENDS Sequences\* 初始化一个seq
VARIABLE q
q = <<>>  \* q为空sequenceSeq(S) \* 集合S中所有元素序列的集合,例如<<3,7>>是Seq(<<3,7,9>>)的一个元素
Head(s) \* 取sequence s中的第一个元素,例如Head(<<3,7>>)等于3
Tail(s)  \* 取sequence s中的最后一个元素,例如Tail(<<3,7>>)等于7
Append(s,e) \* 将元素e添加到sequence s的最后,例如Append(<<3,7>>,9) 等于 <<3,7,9>>
s \o t    \* 连接两个sequence,例如<<3,7>> \o <<5,9>> 等于 <<3,7,5,9>>
Len(s) \* 返回sequence s的长度,例如 Len(<<3.7>>) 等于2

TLA+实现过程

本例子可以理解为上一例子Interface的复杂版本,在FIFO中,相当于,sender与buffer之间,buffer与receiver之间的两个interface。根据之前的例子可以看出,TLA+的实现过程通常分为以下几步:1、引入module,定义变量,2、定义变量合法范围,3、定义初始化状态,4、定义可操作动作,5、定义基于初始化状态的下一步动作

1、先导入需要打module,定义需要的变量

----------------------------- MODULE FIFO ------------------------------
EXTENDS Naturals,Sequences
CONSTANT Message   \* 集合Message为Sender发送的数据范围
VARIABLE inval,inrdy,inack  \* sender发送的数据和发送标识
VARIABLE outval,outrdy,outack \* receiver接收的数据与接收标识
VARIABLE q  \* q为sequence

2、定义上述变量的合法范围

InChannelTypeInvariant == inval \in Message /\ inrdy \in {0,1} /\ inack \in {0,1}
OutChannelTypeInvariant == outval \in Message /\ outrdy \in {0,1} /\ outack \in {0,1}
\* q 的合法范围为集合Message的元素序列的集合
TypeInvariant == InChannelTypeInvariant /\ OutChannelTypeInvariant /\ q \in Seq(Message)

3、定义初始化状态

\* Sender 初始化状态如下
InChannelInit == InChannelTypeInvariant /\ inrdy = inack \* Receiver 初始化状态如下
OutChannelInit == OutChannelTypeInvariant /\ outrdy = outack \* Buff 初始化状态如下
BufInit == q = <<>> \* 整体状态初始化如下
Init == InChannelInit /\ OutChannelInit /\ BufInit

4、定义可操作性动作

在Interface例子中,有Sender发送数据,Receiver接收数据两个动作,在本例子中,则会有以下动作:

\* sender发送数据给buff
CanInSend == inrdy = inack
Send(d) == CanInSend /\ inval' = d /\ inrdy' = 1 - inrdy /\ UNCHANGED <<inack,outval,outrdy,outack,q>>\* buff接收数据
CanBufRev == inrdy # inack
BufRev == CanBufRev /\ q' = Append(q,inval) /\ inack' = 1- inack /\ UNCHANGED <<inval,inrdy,outval,outrdy,outack>> \* buff发送数据给receiver
CanBufSend == outrdy = outack
BufSend == CanBufSend /\ q # <<>> /\ outval' = Head(q) /\ q' = Tail(q) /\ outrdy' = 1 - outrdy /\ UNCHANGED <<inval,inrdy,inack,outack>> \* eceiver接收数据
CanOutRev == outrdy # outack
Rev == CanOutRev /\ outack' = 1 - outack /\ UNCHANGED <<inval,inack,inrdy,outrdy,outval,q>> 

5、下一步动作

Next == \E d \in Message:Send(d)\/ BufRev\/ BufSend\/ Rev
=========================================================================

在上述第4步中,有很多的UNCHANGED 数据,在TLA+的代码中,如果有变量的状态未发生变更,一定要用UNCHANGED 进行标记,否则当前步骤执行完毕后,未使用UNCHANGED标记出来的变量的值将变更为NULL,这将影响到下一步操作的执行。

运行

按下图设置Init,Next,设置Message的范围,然后运行。
上述运行时间会很长,TLC检测到的状态也会很多,主要原因是上述TLA+代码是一个无边界限制的状态搜索,在无边界的状态下,q的值是不定的,在上述例子中,q的值可以是<<1>>,<<1,2>>,<<1,2,2>>,<<1,1,1,1,1,1,1>>等。
如果需要增加边界检查,可以增加q的长度检查,比如限制q的长度小于5。
在上图中TypeInvariant的检查项下面增加Len(q) < 5即可。

这样程序运行很快就会结束,并通过Error-trace打印出Len(q)==5的过程。

通过例子学TLA+(五)--FIFO Sequences相关推荐

  1. 通过例子学TLA+(十五)--时序属性

    时序属性 Termination 最简单的时序属性是Termination,Termination是算法终止的要求,如果算法崩溃或者死锁或者进入一个无限循环,那么久违反了Termination规范. ...

  2. 通过例子学TLA+(十四)--宏,过程与标签

    宏,过程与标签 TLA+在多进程之间复用代码,最简单的方法是使用宏和过程. 宏 宏是通用的代码内联器,格式为 nacro Name(var1,...) begin\* stuff end macro; ...

  3. 通过例子学TLA+(十三)--多进程与await

    多进程 之前使用的例子都是单进程的,现在用多进程来描述多个逻辑同时发生,TLA+中的多进程可以理解为其他高级语言中的多线程.为了方便理解,使用Pluscal语言来描述,TLA+ Toolbox可以将p ...

  4. 通过例子学TLA+(九)--元组和结构体

    元组 元组和其他语言中的数组类似,用<<>>表示,不同之处在于TLA+中元组下标是从1开始. x == <<4, 5, 6>>; x[1] + x[2] ...

  5. 通过例子学TLA+(一)-- HourClock

    前言 刚接触TLA+,将学习过程中的理解整理记录下来,用于加深理解和备忘.有对TLA+感兴趣的可以私信我,一起学习. TLA+简介 TLA+ 是一门形式规格说明语言(formal specificat ...

  6. 通过例子学TLA+(八)--表达式

    表达式 在之前的例子中,已经多次用到了表达式,常见的表达式中会用到 大于,小于,等于,不等于等这样条件判断.还有一些其他的用法,比如逻辑连接,IF-ELSE 等 逻辑连接 逻辑连接在之前的例子中是用过 ...

  7. 通过例子学TLA+(二) -- DieHard

    第二个例子DieHard 这是一个倒水的例子,初始一个3升容量的桶,一个5升容量的桶,水不限,如何倒出一个容量刚好是4升的水.在一部老电影DieHard中主角就面临这个问题,这里就将module名命名 ...

  8. 通过例子学TLA+(四)-- Send Rev Print

    Send & Rev 稍微复杂点的程序中都会涉及数据的发送与接收,本例子基于发送器Sender与接收器Receiver来实现数据的变更.假设Sender发送一个数据给Receiver,Rece ...

  9. 通过例子学TLA+(十二)-- 函数与实例

    函数和实例 函数 TLA+中除了 数字,字符串,布尔值,模型值 4种基本类型外,还有两种复杂类型,分别为集合和函数.函数构成了所有实用复杂类型的基础. 函数的形式看起来跟之前介绍过的操作符是一样的.函 ...

最新文章

  1. c语言dll注入,教大家写一个远程线程的DLL注入,其实还是蛮简单的……………………...
  2. Matlab 非线性规划问题模型代码
  3. python中删除字典中所有元素的函数_在python中,按值删除字典项的最佳方法是什么?...
  4. 惠普800g1支持什么内存_惠普黑白激光打印机哪种好 惠普黑白激光打印机推荐【图文详解】...
  5. python 程序停止打印日志_Python日志打印
  6. httpservletrequest_HttpServletResponse和HttpServletRequest取值的2个坑你知道吗?
  7. 使用Sklearn模型做分类并绘制机器学习模型的ROC曲线
  8. 剧情介绍:“遗愿清单”
  9. 实时帧数手机_小米部分高刷新率机型吃鸡强制开启120帧
  10. 诺顿误杀事件造成“疑似病毒大爆发”恐慌
  11. 旧手机利用(Android),当wifi,当mic,当ipcamera
  12. Vue动态加载并注册组件
  13. 机器学习之PCA原理入门
  14. python头像转卡通_用python将你的头像“卡通化”
  15. Elasticsearch开启安全认证详细步骤
  16. spring配置与监听mysql_spring boot (8)mybatis配置监听,
  17. 曲线之美(一)贝塞尔曲线
  18. 后端做app连续会员包月功能 -- IOS连续订阅 支付宝周期扣款
  19. VMware打开以后黑屏的解决办法
  20. 盘点 | 2020大数据十大关键词与趋势新鲜出炉

热门文章

  1. Springboot调度任务:动态管理
  2. 使用VMware Player在Ubuntu中运行Windows
  3. jcenter 到 maven
  4. element ui+echarts实现走马灯
  5. Ubuntu官方推荐U盘写入工具
  6. BeagleBoneBlack的U-Boot是如何引导系统的
  7. 大数据组件——Zookeeper配置文件解析
  8. 阿里云的云存储服务OSS可以支持哪些企业级存储需求?如何操作和管理?
  9. jquery validate highlight unhighlight,errorPlacement 合理使用
  10. 利用会议软件进行高效会议管理的四大优势