2

I am trying to define an ltl formula which uses the ne(X)t operator in SPIN. My problem is very similar to this question. I have a state machine and I want to verify that if some statement p is true in state0, then some statement q is true in the next state, state1. The ltl formula looks like this:

ltl p0 {p X q}

When I attempt to generate the verifier using spin -a test.pml I get the following error:

spin: test.pml:20, Error: syntax error saw 'X'

I compiled SPIN with the -DNXT flag (as this suggested). I know that the ne(X)t operator cannot be tested with partial order reduction enabled. The only way I have found to disable partial order reduction is with the -DNOREDUCE flag when compiling the verifier. However, I can't even generate the verifier (pan.c) in the first place.

Patrick Trentin
  • 7,126
  • 3
  • 23
  • 40
cmoses
  • 196
  • 1
  • 2
  • 16

1 Answers1

4

The general structure of an LTL formula for which

if some statement p is true in statei, then some statement q is true in the next state, statei+1

is the following one:

ltl p0 { [] (p -> X q) }

The formula p -> X q is verified by

  • any state Si s.t. p is false in Si
  • any state Si s.t. p is true in Si and q is true in Si+1, where Si+1 is the successor of Si in the execution path currently being evaluated

The globally operator [] is required to make the Model Checker verify that the condition p -> X q holds for any state in the execution path. If you omit it, then the property p -> X q is only be checked for the initial state, which in the 99.99% of cases is not what you want.


EXAMPLE

In the following model, if cc is even then process counter increases it by one, otherwise the process either terminates or decreases cc by one in a non-deterministic fashion.

The property that we want to check is that, whenever counter reaches a given checkpoint state and cc is even, after exactly 2 transitions cc is odd.

byte cc = 0;

active proctype counter()
{
checkpoint:
    do
        :: cc % 2 == 0 -> cc++;
        :: else ->
            if
                :: cc--;
                :: break;
            fi;
    od;
}

#define even ( cc % 2 == 0 )
#define odd  ( cc % 2 == 1 )

ltl p0 { [] ( (counter[0]@checkpoint & even) -> X X odd) }

The ltl property p0 is verified:

~$ spin -a test.pml
~$ gcc -DNXT -DNOREDUCE -o run pan.c
~$ ./run -a

(Spin Version 6.4.3 -- 16 December 2014)

Full statespace search for:
    never claim             + (p0)
    assertion violations    + (if within scope of claim)
    acceptance   cycles     + (fairness disabled)
    invalid end states  - (disabled by never claim)

State-vector 28 byte, depth reached 11, errors: 0
        8 states, stored (10 visited)
        2 states, matched
       12 transitions (= visited+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.289   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 proctype counter
    (0 of 11 states)
unreached in claim p0
    _spin_nvr.tmp:16, state 20, "-end-"
    (1 of 20 states)

pan: elapsed time 0 seconds

Things to note:

  • in this example, the use of the label checkpoint: is completely optional. The same result could have been obtained using the ltl formula { [] ( even -> X X odd) }. However, labels are quite frequently used in the context of formulas with the structure [] (p -> X g), so I thought it would be useful to push one inside my example with some empty pretext.

  • I would normally prefer the weaker F odd condition to the stronger statement X X odd, unless that isn't possible/advisable due to the nature of the property being verified. In fact, with Spin it is not easy to guess with a single glance how many transitions occur from one statement to the other, since AFAIK the model normally undergoes a number of optimisations to remove/merge states with one another.

Patrick Trentin
  • 7,126
  • 3
  • 23
  • 40
  • I am having some trouble understand what exactly constitutes a transition. Is it only when the state changes? If so, then wouldn't X X (2 transitions) include the option of cc = 0 -> cc++ -> cc-- resulting in state cc = 0, which would violate (X X odd)? Or, is it any executable statement, in which case the only 2 transitions from checkpoint are cc = 0 -> (cc% 2 == 0) -> cc++? – cmoses Aug 01 '17 at 09:26
  • 1
    @cmoses *no*, because a state *loosely* corresponds to a **statement** in your *Promela* code (that is, the state information includes a reference to the statement *"being executed"*), so you have to take that into account too; it takes 4 transitions to make `cc` again even, you can test it by playing with the *ltl formula* in the example. You should use option `-o3` to prevent statement merging in the verifier, this might help matching states with statements in the model. – Patrick Trentin Aug 01 '17 at 09:51