所以我在Promela代码中使用了以下行。
select( cycles: 26..31 );
然而,它导致了国家爆炸。我用下面的if
语句替换了它,突然间状态爆炸问题消失了。上面显示的select
语句不应该等同于下面的if
语句吗?这是怎么回事?
if
:: cycles = 26;
:: cycles = 27;
:: cycles = 28;
:: cycles = 29;
:: cycles = 30;
:: cycles = 31;
fi;
答案 0 :(得分:4)
您的select语句由Spin转换为
cycles = 26;
do
:: cycles < 31 -> cycles++
:: break
od
这意味着在每个循环执行中有两种可供选择的可能性,即转换系统中的两种不同的后继状态。如果未选择break
,则必须进行比较和分配(两个状态),然后继续。如果你想达到值31,你之前已经进行了5次比较和5次分配,而在if版本中,只有一个非确定性的选择。
我使用spinspider将两个不同版本可视化,这应该可以使问题更容易理解。
下图描绘了一个带有“if”-version的程序生成的状态空间,其中显然只有6种可供选择:
int cycles;
active proctype testWithIf() {
if
:: cycles = 26;
:: cycles = 27;
:: cycles = 28;
:: cycles = 29;
:: cycles = 30;
:: cycles = 31;
fi;
assert(cycles >= 26 && cycles <= 31);
}
与此相比,将作为select语句转换为do-loop的程序生成的图像:
int cycles;
active proctype test1() {
cycles = 26;
do
:: cycles < 31 -> cycles++
:: break
od;
assert(cycles >= 26 && cycles <= 31);
}
你看到了差异吗?正如我所说,我认为主要的问题是,在if-version中你只需选择一个赋值,你必须在每个你不选择break的状态下做do-version中的多个事情:你必须做比较,递增计数器,然后继续。这显然会产生更大的状态空间。