我的教授决定给我们数学学生一个改为NuSMV的代码,我似乎无法在其他任何地方找到帮助,我只读了6页的教科书,只描述了某些属性的作用。 Module main是NuSMV代码的一个例子,他说使用那个格式示例来编写伪代码。 我不知道怎么写while循环并设置什么是真的?并且flag1是一个州还是另一个州?
while(true) do
flag1 := true
while flag2 do
if turn=2
flag1 := false;
wait until turn = 1;
flag1 := true
Critical section
turn := 2
flag1 := false;
答案 0 :(得分:1)
您似乎正在尝试对 Dekker / Dijkstra的算法进行建模,以便在两个进程之间进行互斥。
根据您的问题,您感兴趣的步骤应该只有 1-4 。我添加了更多内容,以便更全面地了解 NuSMV 可以实现的目标。
我使用了相同算法的稍微不同版本,但基本想法是相同的。
IDEA:存在将伪代码转换为 NuSMV 模型的方法:
标记代码中每个语句的条目和退出点:
-- void p(iflag, turn, id) {
-- l0: while(true) do
-- l1: flag := true
-- l2: while iflag do
-- l3: if turn != id
-- l4: flag := false;
-- l5: wait until turn = id;
-- l6: flag := true
-- l7: // Critical section
-- l8: turn := 1 - id
-- l9: flag := false;
-- }
请注意一些陈述,例如while iflag do
,可能有多个退出点,具体取决于 guard 的值:如果iflag
为true,则退出点是 l3 ,否则退出点是 l7 。
创建相应的模块,它采用相同的输入并具有状态变量,该变量的计算结果为新引入的标签。
MODULE p(iflag, turn, id)
VAR
state : { l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, error };
flag : boolean;
请注意,我添加了特殊状态错误。这只是为了确保在定义 state 的过渡关系时,我们不会遗漏任何正确的过渡步骤。通常,它应该被省略,因为它不属于原始代码。
定义州的转换关系:
ASSIGN
init(state) := l0;
next(state) := case
state = l0 : l1;
state = l1 : l2;
state = l2 & iflag : l3;
state = l2 & !iflag : l7;
state = l3 & turn != id : l4;
state = l3 & turn = id : l2;
state = l4 : l5;
state = l5 & turn != id : l5;
state = l5 & turn = id : l6;
state = l6 : l2;
state = l7 : l8;
state = l8 : l9;
state = l9 : l0;
TRUE : error; -- if you match this then the above
-- description of transitions are incomplete
esac;
如您所见,我只是将每个入口点连接到相应的出口点。此外,如果为给定的入口点定义了多个出口点 ,我还添加了其他州条件以确定行< / em>接下来执行。
添加标志的转换关系:
init(flag) := FALSE;
next(flag) := case
state = l1 | state = l6 : TRUE;
state = l4 | state = l9 : FALSE;
TRUE : flag;
esac;
添加一些定义以确定进程正在执行的代码段:
DEFINE
critical_section := (state = l7);
trying_section := (state = l1 | state = l2 | state = l3 |
state = l4 | state = l5 | state = l6);
创建主模块,创建 p 的两个实例:
MODULE main ()
VAR
turn : {0, 1};
p1 : p(p2.flag, turn, 0);
p2 : p(p1.flag, turn, 1);
ASSIGN
init(turn) := 0;
next(turn) := case
p1.state = l8 : 1;
p2.state = l8 : 0;
TRUE : turn;
esac;
添加一些非常典型 互斥属性以供模型检查器验证:
--*-- PROPERTIES --*--
-- Safety: two processes are never in the critical section at the same time
CTLSPEC AG !(p1.critical_section & p2.critical_section);
-- Liveness: if a process is in the trying section, then sooner or later
-- it will access the critical section.
CTLSPEC AG (p1.trying_section -> AF p1.critical_section);
-- Absence of Starvation
CTLSPEC ! EF AG (p1.trying_section & p2.trying_section);
-- Never in Error State
CTLSPEC AG !(p1.state = error);
运行工具
~$ NuSMV -int
并检查所有属性是否已经过验证:
NuSMV > reset; read_model -i dekker.smv; go; check_property
-- specification AG !(p1.critical_section & p2.critical_section) is true
-- specification AG (p1.trying_section -> AF p1.critical_section) is true
-- specification !(EF (AG (p1.trying_section & p2.trying_section))) is true
-- specification AG !(p1.state = error) is true
注意:
如果仔细查看 1 和 3 步骤,有几个州看起来多余。例如,始终可以折叠只有一个入口和出口点的连续状态。我将此作为练习留给您。
请注意,为简单起见,我使用了模块的同步组合。实际上,通过让两个进程异步运行,验证会更有意义。但是,这需要使模型比您真正需要的问题更复杂,因此超出了我的答案范围。
如果您想了解有关 NuSMV 的更多信息,可以查看其documentation或查看此course的第二部分。< / p>