Model checking 如何在Spin中生成非初始化变量?
Promela似乎初始化了每个变量(默认情况下,为0或声明中给定的值) 如何声明由未知值初始化的变量 文档建议Model checking 如何在Spin中生成非初始化变量?,model-checking,spin,promela,Model Checking,Spin,Promela,Promela似乎初始化了每个变量(默认情况下,为0或声明中给定的值) 如何声明由未知值初始化的变量 文档建议if::p=0::p=1fi,但我不这么认为 它是有效的:Spin仍然证实了这一说法 bit p init { if :: p = 0 :: p = 1 fi } ltl { ! p } (和伪造p) 那么,init的语义到底是什么呢?还有一些 “初始前”状态?我如何才能解决这个问题,而不让我的学生感到困惑 这是一个有趣的问题 表示每个变量都初始化为0,除非模型另有规定 与
if::p=0::p=1fi
,但我不这么认为
它是有效的:Spin仍然证实了这一说法
bit p
init { if :: p = 0 :: p = 1 fi }
ltl { ! p }
(和伪造p
)
那么,init
的语义到底是什么呢?还有一些
“初始前”状态?我如何才能解决这个问题,而不让我的学生感到困惑 这是一个有趣的问题 表示每个变量都初始化为0,除非模型另有规定 与所有变量声明一样,显式初始化字段是可选的。所有变量的默认初始值为零。这适用于标量变量和数组变量,也适用于全局变量和局部变量 在您的模型中,声明变量时不初始化变量,因此随后会在初始状态下将其赋值给值0,该值位于赋值之前:
bit p
init {
// THE INITIAL STATE IS HERE
if
:: p = 0
:: p = 1
fi
}
ltl { ! p }
一些实验。 为了避免这种限制,一个“幼稚”的想法是在调用
~$spin-A test.pml
时修改由spin生成的pan.c的c源代码,以便随机初始化变量
代替此初始化功能:
void
iniglobals(int calling_pid)
{
now.p = 0;
#ifdef VAR_RANGES
logval("p", now.p);
#endif
}
你可以试着这样写:
void
iniglobals(int calling_pid)
{
srand(time(NULL));
now.p = rand() % 2;
#ifdef VAR_RANGES
logval("p", now.p);
#endif
}
并在标题部分添加一个#include
但是,一旦您使用gcc pan.c
将其编译成一个验证器,并尝试运行它,您将根据变量p的初始化值获得非确定性行为
它可以确定是否违反了该属性:
~$ ./a.out -a
pan:1: assertion violated !( !( !(p))) (at depth 0)
pan: wrote test.pml.trail
(Spin Version 6.4.3 -- 16 December 2014)
Warning: Search not completed
+ Partial Order Reduction
Full statespace search for:
never claim + (ltl_0)
assertion violations + (if within scope of claim)
acceptance cycles + (fairness disabled)
invalid end states - (disabled by never claim)
State-vector 28 byte, depth reached 0, errors: 1
1 states, stored
0 states, matched
1 transitions (= stored+matched)
0 atomic steps
hash conflicts: 0 (resolved)
Stats on memory usage (in Megabytes):
0.000 equivalent memory usage for states (stored*(State-vector + overhead))
0.291 actual memory usage for states
128.000 memory used for hash table (-w24)
0.534 memory used for DFS stack (-m10000)
128.730 total actual memory usage
pan: elapsed time 0 seconds
或打印属性满足以下条件:
~$ ./a.out -a
(Spin Version 6.4.3 -- 16 December 2014)
+ Partial Order Reduction
Full statespace search for:
never claim + (ltl_0)
assertion violations + (if within scope of claim)
acceptance cycles + (fairness disabled)
invalid end states - (disabled by never claim)
State-vector 28 byte, depth reached 0, errors: 0
1 states, stored
0 states, matched
1 transitions (= stored+matched)
0 atomic steps
hash conflicts: 0 (resolved)
Stats on memory usage (in Megabytes):
0.000 equivalent memory usage for states (stored*(State-vector + overhead))
0.291 actual memory usage for states
128.000 memory used for hash table (-w24)
0.534 memory used for DFS stack (-m10000)
128.730 total actual memory usage
unreached in init
test.pml:8, state 5, "-end-"
(1 of 5 states)
unreached in claim ltl_0
_spin_nvr.tmp:8, state 8, "-end-"
(1 of 8 states)
pan: elapsed time 0 seconds
显然,假设由自旋验证的promela模型的初始状态是唯一的。毕竟,这是一个合理的假设,因为它会不必要地使事情复杂化:你总是可以用一个初始状态s.t.s替换N个不同的初始状态s_i。s允许通过ε转换到达每个s_i。在这种情况下,你得到的不是真正的ε转换,但在实践中,它几乎没有什么区别
编辑(来自评论):
原则上,可以通过进一步修改pan.c来实现这一点:
- 将初始状态初始化器转换为初始状态的生成器
- 修改验证例程,以考虑可能存在多个初始状态,并且属性必须为每个初始状态保留
解决方法。 如果您想声明某些内容在初始状态下为真,或从初始状态开始,并考虑某些非确定性行为,则应编写如下内容:
bit p
bool init_state = false
init {
if
:: p = 0
:: p = 1
fi
init_state = true // TARGET STATE
init_state = false
}
ltl { init_state & ! p }
您可以从中获得:
~$ ./a.out -a
pan:1: assertion violated !( !((initialised& !(p)))) (at depth 0)
pan: wrote 2.pml.trail
(Spin Version 6.4.3 -- 16 December 2014)
Warning: Search not completed
+ Partial Order Reduction
Full statespace search for:
never claim + (ltl_0)
assertion violations + (if within scope of claim)
acceptance cycles + (fairness disabled)
invalid end states - (disabled by never claim)
State-vector 28 byte, depth reached 0, errors: 1
1 states, stored
0 states, matched
1 transitions (= stored+matched)
0 atomic steps
hash conflicts: 0 (resolved)
Stats on memory usage (in Megabytes):
0.000 equivalent memory usage for states (stored*(State-vector + overhead))
0.291 actual memory usage for states
128.000 memory used for hash table (-w24)
0.534 memory used for DFS stack (-m10000)
128.730 total actual memory usage
pan: elapsed time 0 seconds
Init语义。 Init仅保证是第一个生成的进程,并用于生成其他进程,例如,当其他例程将某些参数(例如,共享某些资源)作为输入时。更多信息 我认为这段文字有点误导: 初始化过程最常用于初始化全局变量, 以及通过使用run来实例化其他流程 操作员,在系统执行开始之前。任何过程,而不仅仅是 不过,init进程可以这样做
由于可以使用
原子{}
语句保证init进程在任何其他进程之前执行其所有代码,因此从编程的角度来看,可以说它可以用于在其他进程使用变量之前初始化变量。但这只是一个粗略的近似值,因为init进程并不对应于执行模型中的唯一状态,而是对应于根的状态树,根本身只由全局环境给出,就像任何进程开始之前一样。是的,这种解决方法看起来是合理的。在我的应用程序中,我在主进程中有do::p=0::p=1 od
(请参阅),因此我还可以在声明中放置X
操作符。我仍然认为Promela应该有不确定的初始化(比如位p=?
)。我不知道在哪里需要init确定性来进行模拟或验证。我同意你的观点,支持非确定性初始化不会有技术困难,尽管在处理可能值范围非常大的数据类型时会出现性能问题,除非也提供了限制范围的方法。但是我真的说不出他们为什么要这样设计语言,除了可能是为了简化一些事情。原则上,你可以修改pan.c,使它使用一个初始状态生成器而不是一个初始化器,并考虑到存在多个初始状态的可能性。除此之外,任何事情都不会改变,验证者将报告正确的结果。但在这一点上,最好是简单地修补spin以支持这种行为,即使它不是Promela规范语言的标准。