如何在Spin中创建一个非初始化变量?

时间:2016-11-01 11:12:46

标签: model-checking spin promela

似乎Promela初始化每个变量(默认情况下,为0,或者声明中给出的值)。

如何声明由未知值初始化的变量?

文档提示if :: p = 0 :: p = 1 fi,但我不这么认为 它的工作原理:Spin仍在验证此声明

bit p 
init {   if ::  p = 0 :: p = 1 fi }
ltl {  ! p  }

(并伪造p

那么init的语义到底是什么?还有一些 "预初始"州?我该如何解决这个问题 - 而不是混淆我的学生?

1 个答案:

答案 0 :(得分:3)

这是一个有趣的问题。

documentation表示每个变量都初始化为0,除非模型另有说明。

  

与所有变量声明一样,显式初始化字段是可选的。所有变量的默认初始值均为零。这适用于标量变量和数组变量,它适用于全局变量和局部变量。

在您的模型中,在声明变量时不要初始化变量,因此随后将其分配给初始状态中的值0,该状态位于分配之前:

bit p

init {
  // THE INITIAL STATE IS HERE
  if
    :: p = 0
    :: p = 1
  fi
}

ltl {  ! p  }

一些实验。

避免此限制的"天真" 想法是修改 pan.c c源代码当你调用~$ spin -a test.pml时由spin生成的,这样变量就会随机初始化。

而不是这个初始化函数:

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 <time.h>

但是,一旦将其编译为具有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

显然, spin 验证的 promela模型初始状态被认为是唯一的。 Afterall,这是一个合理的假设,因为它会不必要地使事情变得复杂:你总是可以用初始状态S s.t替换N个不同的初始状态S_i。 S允许通过epsilon转换到达每个S_i。在这种情况下,你得到的并不是真正的epsilon过渡,但在实践中它没什么区别。

编辑 (来自评论): 原则上,通过稍微修改 pan.c 可以使这项工作成为可能:

  • 将初始状态初始化转换为初始状态的生成器
  • 修改验证例程以考虑可能存在多个初始状态,并且该属性必须为每个初始状态保留

话虽如此,这可能不值得麻烦,除非通过修补 Spin 的源代码来完成。

解决方法。

如果你想在初始状态中说明某些事情是真的,或者从初始状态开始,并考虑到某些非确定性行为,那么你应该写下如下内容:

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 Semantics。

初始只是保证第一个产生过程,并且意味着用于产生其他过程例如,其他例程将输入一些参数,例如一些资源是共享的。更多信息here

我认为documentation的这个片段有点误导:

  

init进程最常用于初始化全局变量,   并通过使用run来实例化其他进程   运算符,在系统执行开始之前。任何过程,而不仅仅是   init进程,可以这样做,但

由于可以保证init进程在使用atomic { }语句的任何其他进程之前执行其所有代码,因此可以说它可以用于在之前初始化变量从编程的角度来看,它们被其他进程使用。但这只是一个粗略近似,因为init进程不对应于执行模型中的唯一状态,而是对应于根和状态树的状态。 root本身仅由全局环境给出,就像任何进程开始之前一样。