how to make a non-initialised variable in Spin?

╄→гoц情女王★ 提交于 2019-12-11 01:59:27

问题


It seems that Promela initialises each variable (by default, to 0, or to the value that is given in the declaration).

How can I declare a variable that is initialised by an unknown value?

The documentation suggests if :: p = 0 :: p = 1 fi but I don't think that it works: Spin still verifies this claim

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

(and falsifies p)

So what exactly is the semantics of init? There still is some "pre-initial" state? How can I work around this - and not confuse my students?


回答1:


This is an interesting question.

The documentation says that each and every variable is initialised to 0, unless the model specifies otherwise.

As with all variable declarations, an explicit initialization field is optional. The default initial value for all variables is zero. This applies both to scalar variables and to array variables, and it applies to both global and to local variables.

In your model, you don't initialise the variable when you declare it, therefore it is subsequently assigned to the value 0 in the initial state, which is located before your assignment:

bit p

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

ltl {  ! p  }

Some Experiment.

A "naive" idea for dodging this limitation would be to modify the c source code of pan.c that is generated by spin when you invoke ~$ spin -a test.pml, so that the variable is initialised at random.

Instead of this initialisation function:

void
iniglobals(int calling_pid)
{
        now.p = 0;
#ifdef VAR_RANGES
        logval("p", now.p);
#endif
}

one could try writing this:

void
iniglobals(int calling_pid)
{
        srand(time(NULL));
        now.p = rand() % 2;
#ifdef VAR_RANGES
        logval("p", now.p);
#endif
}

and adding an #include <time.h> in the header part.

However, once you compile that into a verifier with gcc pan.c, and you attempt to run it, you obtain non-deterministic behaviour depending on the initialization value of the variable p.

It can both determine that the property is violated:

~$ ./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

or print that the property is satisfied:

~$ ./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

Clearly, the initial state of a promela model verified by spin is assumed to be unique. Afterall, that's a reasonable assumption, since it would needlessly complicate things: you can always replace N different initial states S_i with an initial state S s.t. S allows to reach each S_i with an epsilon-transition. In this context, what you get is not truly an epsilon-transition, but in practice it makes little difference.

EDIT (from comments): In principle, it is possible to make this work by modifying pan.c a little bit further:

  • transform the initial state initialiser into a generator of initial states
  • modify the verification routine to take into account that more than one initial state might exist, and that the property must hold for each initial state

Having said this, it is likely not worth the hassle, unless this is done by patching Spin's source code.


Workaround.

If you want to state that something is true in the initial state, or starting from the initial state, and take into account some non-deterministic behaviour, then you should write something as follows:

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  }

with which you get:

~$ ./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.

Init is simply guaranteed to be the first process to spawn, and is meant to be used for spawning other processes when, for-example, the other routines take as input some parameters, e.g. some resources are shared. More info here.

I believe that this fragment of documentation is a bit misleading:

The init process is most commonly used to initialize global variables, and to instantiate other processes, through the use of the run operator, before system execution starts. Any process, not just the init process, can do so, though

Since it is possible to guarantee that the init process executes all of its code before any other process using the atomic { } statement, one could say that it can be used to initialize variables before they are used by other processes from the programming point of view. But that is just a rough approximation, because the init process does not correspond to a unique state in the execution model, but rather to the tree of states at the root and the root itself is given only by the global environment as it is before any process starts.



来源:https://stackoverflow.com/questions/40358915/how-to-make-a-non-initialised-variable-in-spin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!