地板+动作属性

2021-04-01 19:50:27

TLA +技术在那里没有全部很多:所有资源都是介绍或案例研究。对人们开始的好处,对过去的人不好。我认为我们需要编写更多的中级东西,本·库恩呼叫Blub研究。这是一个尝试。

大多数TLA +属性都是不变的,必须为行为中的每个状态都是如此的属性。如果我们有一个简单的柜台:

扩展整数变量x init == x = 1 next == / \ x< 3 / \ x' = x + 1 spec == init / \ [] [next] _x

然后这个规范的不变性是x \ In 1..3。一个不是不变的属性是x始终增加。从x = 2到x = 1将违反此,但这些都是有效的状态。它只是无效的过渡。转换中的此属性称为Action属性并编写[] [] [x' > x] _x。

(x'> x)是下一个状态(x')中的x值大于当前状态的x的值。 [](x'> x)会说这始终是真的:每个状态必须对x比之前的状态更大。

我们不能直接写一下,因为它将被口吃步骤侵犯。由于TLA +是口吃不变的,我们应该能够在不破坏属性的情况下在任何地方插入口吃。我们改为想要[](x'> x \ /不变的x),x是增加或不会改变。 tla +提供速记[] [a] _x语法,最后给我们[] [x' > x] _x。

在工具箱中,操作属性进入“时间属性”框。如果您从命令行运行,它们是配置文件中的属性。

使用=>,我们可以制作“条件”,如果前提条件是真的,只能持有“条件”属性。例如,如果我们的系统具有“kill switch”,我们可以说某些值不应在系统被禁用时更改:1

\ *如果x更改,y必须成为x [] [x' / = x => Y' = x] _

我们还可以使用作为不变性的前提条件的动作,在那里我们只需要在这些特定操作下保持不变性。如果我们将规范拆分为机器和世界动作,我们可能希望只有机器操作维护不变:

我们可以在条件的两侧使用行动,例如,如果发生某种变化,它必须是“因为”是“某种行动:

\ *所有者\在[Credit - >用户] \ *在子集中(用户\ x用户\ x信用)接受(从,到,信用)== \ *(用户,用户,信用)/ \<来自,信用>> \ in提供/ \优惠' =提供\ {<<来自,信用>> / \所有者' = [所有者除外![Credit] = to] \ *如果所有权从a从a从a变为b \ *它' s是因为b接受了来自vightchange(Credit)== Let Co ==所有者[信用]在CO中的报价/ = CO' =>接受(co,co',credit)\ *系统的所有变化都是有效的更改变更roopprop == [] [\ a c \在信用中:vightchange(c)] _所有者

服务器有三个州:脱机,引导和在线。我们可以说服务器无法直接从脱机到在线:

如果我们有许多不同的州过渡,我们可以摘要将有效转换到运营商中:

\ *状态== {a,b,c,d} \ *状态\在状态转换== {< a,b>> ,<< a,c>> << b,d>> ,<< c,a>> ,<< C,B>> } [] [<<国家,国家' >>在过渡时期] _state

t ==&lt;&lt;&lt;国家,国家&#39; &gt;&gt; [t = <&lt; a,b&gt;&gt; =&gt; X&#39; &gt; x] _ <&lt;&lt;&lt;国家,x&gt;&gt; [] [x&#39; &lt; x =&gt; t =&lt;&lt; a,c&gt;&gt; ] _ <&lt;国家,x&gt;&gt;

\ *机器== {M1,M2,M3} \ *状态\在[机器 - &gt;状态]变形符(m)==状态[m] / =状态&#39; [m]转换(m)==&lt;国家[M],状态&#39; [M]&gt;&gt; [] [\ a m \在机器中:epartstate(m)=&gt;转换过渡(m)\ [转换] _state

我们在线程之间共享锁。如果一个线程保存锁定,则必须在另一个线程获取它之前释放锁定:2

我们有一个仅追加的事件日志。日志的先前值永远不会改变。这意味着日志是日志&#39的前缀;:

如果我们从客户端处理邮件,并且仍然存在队列中的消息,我们不会切换到另一个客户端:

\ * curr = current_client \在[客户端 - &gt; seq(msg)] [] [队列[curr] / =&lt;&gt; =&gt;不变的Curr] _ <&lt;&lt; Curr,队列&gt;&gt;

在我的经验中,Action属性不太常见,而不是不变性,而不是生活属性。但是,对于对动作属性有效的规范,Livess属性通常是“更重要”。 3动作属性非常有用,但并不是同样的方式。

[a] _x中的x可以是任何状态谓词,而不仅仅是一个变量。通常人们添加辅助操作员vars ==&lt; x,y,z,...&gt;&gt;然后写[a] _vars。唯一的要求是,出现在a中的所有变量也必须出现在下标中。

行动属性只能描述一对状态。您无法自然地编写一个跨越三个州的属性而不添加辅助变量。

存在第二种动作语法:&lt;&gt;&gt; _x表示a / x&#39; / = x,或“A发生和X变化”。正如我们可以通过&lt; p,我们可以通过&lt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; _x。不幸的是,TLC无法检查一下。它只能检查形式[]&lt;&lt;&gt; _x,或“a”无限地发生“常常”。

TLC还可以检查表单的属性&lt; [] [] [a] _x或“最终,操作属性[] [] [a] _x始终保持。”我使用它在这篇文章中形成有条件的财产:

那种财产是“如果它最终是世界行动只在安全持有时发生的情况,那么即使世界突破安全,我们将永远最终返回安全持有。”

我认为我实际上没有使用&lt; [] [] [] [a] _x以真实的世界规范在一个例子中。

大多数规范都被写为init / \ [] [next] _vars。 TLC可以查看[] [下一步] _vars就像任何其他操作属性一样! 这是发射点进入细化,或者使用整个规范作为另一种规范的检查属性。 这将是另一个帖子的主题。 我可以刚刚写锁和#39; = null而不是锁定&#39; \在{lock,null}中。 [p] _lock意味着p \ /不变的锁定,这将隐式允许线程锁定不变。 但这将“卸载”对语法的规范逻辑,这对读者并不清楚。 [返回] 不变性和操作属性只涵盖不良状态和转换。 他们不会覆盖“系统实际上是你需要的事情。” 这是活跃的。 [返回]