以下内容对我有用。 (警告:我没有在官方文档中看到这一点。这可能意味着还有其他更好的方法可以做到这一点。或者我没有仔细寻找。)
我们想检查是否[] <> p && [] <> q
暗示<> (p && q)
。 (它不是。)
写一个简单的流程P
可以执行所有转换,并将声明写入 LTL 属性A
.
bool p; bool q;
active proctype P () {
do :: d_step { p = false; q = false }
:: d_step { p = false; q = true }
:: d_step { p = true; q = false }
:: d_step { p = true; q = true }
od
}
ltl A { (([] <> p) && ([] <> q)) -> <> (p && q) }
(编辑 2016 年 11 月 1 日:这可能不正确,因为由于隐藏的初始状态,我们可能会丢失一些转换,请参阅如何在 Spin 中创建未初始化的变量? https://stackoverflow.com/questions/40358915/how-to-make-a-non-initialised-variable-in-spin )
然后将其放入文件中check.pml
, and
spin -a check.pml
cc pan.c -o pan
./pan -a -n
./pan -r check.pml.trail -v
显示了否定声明的模型(最终的周期性轨迹,其中p
and q
无限频繁地为真,但是p && q
是从来没有)。
仔细检查:将权利要求中的结论更改为<> (p || q)
,则不存在反例,证明蕴涵成立。
就您而言,索赔是! (f && g)
(它们永远不应该同时为真)。
可能有一些聪明的方法可以使琐碎过程的代码更小。
另外,第三个命令实际上是./pan -a -i -n
(the -i
找到一个最短的例子)但它给出了一个警告。而且它确实找到了更短的周期。