Spinroot

A forum for Spin users

You are not logged in.

#1 iSpin related (GUI) » duplicate -DMA option » 2012-12-07 17:45:35

eugen
Replies: 1

When I use the "Minimized automata" option, the command line looks like
  gcc -DMEMLIM=2048 -O2 -DMA=120 -DMA=100 -DXUSAFE -w -o pan pan.c
while it should be
  gcc -DMEMLIM=2048 -O2 -DMA=120 -DMA=100 -DXUSAFE -w -o pan pan.c

#2 Re: General » LTL and never-claims » 2011-12-22 21:49:39

My initial question was: "Is it safe to use a simple DFS to check safety LTL properties?" By this I meant that the formula specified as "ltl name {formula}" in a Promela model is a safety property.

I would be very surprised if when using the '-DSAFETY' option or when referring to safety properties in the man pages, it means that the negation of the desired property is safety, because then to check invariants one would need the -a option (because their negation is not a safety, but a liveness property)!

#3 Re: General » LTL and never-claims » 2011-12-22 21:20:26

But ([] p) || (p U q) is a safety property (the bad thing is if !p holds and before that q does not hold) and this is the property that I'd like to check. A similar situation is for the invariant []p: we search for a counter-example of []p, hence for words satisfying <>!p, although incidentally this is a liveness property.

#4 Re: General » LTL and never-claims » 2011-12-22 20:14:21

Well, for ltl prop {p W q} (or equivalently spin -f "! ( ([] p) || (p U q))"), SPIN generates a never-claim that has non-dummy accept labels, but I believe it doesn't need -a to fully verify, because all infinite accepted traces have a finite prefix for which the never-claim finishes.

#5 Re: General » LTL and never-claims » 2011-12-22 19:57:01

Said otherwise: say that I have an LTL to NBA translator that for the formula '[] true' generates the never claim N1. Then SPIN would not detect an error with a simple DFS, even though the translation is correct (the formula and the NBA/never-claim are equivalent). Hence the translation needs to have an additional property besides being correct in order to check safety LTL property with a simple DFS. And what I wonder is what is this property that makes SPIN work correctly (in case it indeed does).

#6 Re: General » LTL and never-claims » 2011-12-22 19:45:50

Actually my question is not whether the algorithms are correct, but rather which are the algorithms used. More precisely: never-claims are more powerful than Buchi automata, because they also accept finite traces, while Buchi automata only accept infinite traces. The papers I have seen only talk about how to generate Buchi automata, not never-claims. For instance, for ! (p W q), the Buchi automata could look (as a never-claim), like this:

never { 
T0_init :    /* init */
	if
	:: (!q) -> goto T0_init
	:: (!p && !q) -> goto accept_all
	fi;
accept_all :    /* 1 */
	if
	:: (1) -> goto accept_all
        fi
}

but SPIN generates a never-claim which looks like this:

never { /* ! ( ([] p) || (p U q)) */
T0_init :    /* init */
	if
	:: (!q) -> goto T0_init
	:: (!p && !q) -> goto accept_all
	fi;
accept_all :    /* 1 */
	skip
}

(I used here the ltl2ba tool just to keep the automaton smaller; I could have used SPIN instead to illustrate the same issue.)

Now, concerning correctness: if the only transformation from the (non-terminating) Buchi automata to (the possibly terminating) never-claims is the addition of jumps to the end of the never-claim, then I have reasons to believe that this is not sufficient: Kupferman and Vardi in "Model Checking of Safety Properties" (CAV'99) show that one needs to determinize the Buchi automaton obtained from the LTL formula, in order to obtain a finite automaton that detects all bad prefixes. (Unfortunately, they don't give the concrete LTL formula which shows this, they only give a similar one, which is complicated enough, see Theorem 3.3.) Without this determinization step, I think that there are safety LTL formulas for which SPIN's translation (and actually all translations) would generate a never-claim that never terminates and hence for which SPIN will not find errors only by doing a simple DFS.

#7 Re: General » LTL and never-claims » 2011-12-22 13:50:11

I try to explain my concern with some examples. Consider the model:

init {
  do
    :: (1) -> skip;
  od;
}

and the following three never-claims (N1, N2, N3):

never
{
accept_s:
  if
    :: (1) -> goto accept_s;
  fi;
}
never
{
accept_s:
  if
    :: (1) -> goto accept_s;
    :: (1) -> goto accept_all;
  fi;
accept_all:
  skip
}
never
{
accept_s1:
  if
    :: (1) -> goto accept_s2;
  fi;

accept_s2:
  if
    :: (1) -> goto accept_s1;
  fi;
}

As expected, with a simple DFS (ie. ./pan without the -a option), SPIN finds an error only for N2. With a nested DFS (./pan -a), it finds an error for all three never-claims. On infinite traces, the three never-claims are equivalent, and describe a safety property (the bad thing is the empty trace). Assume that there are 3 LTL formulas from which these never-claims are generated. (This assumption may or may not hold, I don't know.) To check them with a single DFS, the never-claims N1 and N3 would need to be further transformed into something similar to N2. To obtain N2 from N1 seems easy (for sink states, just add a goto to the end of the never-claim), but to obtain N2 from N3 seems harder.

So my question is how does SPIN make sure that never-claims like N3 are not generated from safety LTL properties?

#8 Re: General » LTL and never-claims » 2011-12-21 20:11:46

No. But I just imagine that further transformations are needed besides the theoretical LTL to NBA translation (and the above mentioned inverse of the stutter extension rule). So I am just curious how SPIN builds the never-claim. For instance, I know that one can transform a safety NBA into an NFA that accepts all good prefixes, by applying the powerset construction. Is this what is done?

Another reason for which I asked is that, besides the match between the names (safety option and safety property), I haven't seen a place where it is said that it is safe to do so.

#10 Re: General » LTL and never-claims » 2011-12-21 16:14:01

I refine my question: Is it safe to use a simple DFS (that is, the -DSAFETY option) to check safety LTL properties?

#11 General » LTL and never-claims » 2011-12-20 18:26:32

eugen
Replies: 18

My initial understanding was that never-claims generated from LTL formulas should never terminate as they encode Buchi automata, or equivalently, as the standard LTL semantics is on infinite words.

But for instance for pWq, the never claim can terminate. So how is a never-claim generated from an NBA? (I assume that the NBA is obtained from the LTL formula using the algorithm described in "Simple on-the-fly automatic verification of linear temporal logic".) Is it the case that all accepting "sink" states are transformed into the 'accept_all: skip' final statement of the never-claim? Or are there other transformations being done?

#12 Bug Reports » ispin error while displaying automata » 2011-12-06 13:19:23

eugen
Replies: 1

I have ispin 1.0.5 and spin 6.1.0. While trying to display the automaton for the receiver process of the following model I get the following error.

mtype = {msg0, msg1, ack0, ack1};

chan snd = [1] of {mtype};
chan rcv = [1] of {mtype};


active proctype lossy () {
  mtype drop;

  do
    :: snd?drop;
drop_snd:
       skip

    :: rcv?drop;
drop_rcv:
       skip
  od
}

active proctype sender () {
again:
  do
	:: snd!msg1; /* send message with bit=1 */
	   if
	     :: rcv?ack1 -> break/* receive acknowledge with bit=1 */
	     :: rcv?ack0 -> skip /* retransmission */
	     :: timeout -> skip /* retransmission */
	   fi
  od;
  do
    :: snd!msg0; /* send message with bit=0 */
       if
	 :: rcv?ack0 -> break/* receive acknowledge with bit=1 */
	 :: rcv?ack1 -> skip /* retransmission */
	 :: timeout -> skip /* retransmission */
       fi
  od;
  goto again
}

active proctype receiver () {
again:
  do /* expected bit is 1 */
    :: snd?msg1 -> /* receive msg1 from sender */
       rcv!ack1; /* acknowledge with ack1 */
       break /* alternate expected bit */
       
    :: snd?msg0 -> /* receive msg0 from sender */
       rcv!ack0; /* acknowledge with ack0 */
  od;
  
  do /* expected bit is 0 */
    :: snd?msg0 -> /* receive msg0 from sender */
       rcv!ack0; /* acknowledge with ack0 */
       break /* alternate expected bit */
       
    :: snd?msg1 -> /* receive msg1 from sender */
       rcv!ack1 /* acknowledge with ack1 */
  od;
  goto again
}
unexpected "," outside function argument list
in expression "50 * 1, height="
unexpected "," outside function argument list
in expression "50 * 1, height="
    (parsing expression "50 * 1, height=")
    invoked from within
"expr 50 * $mf"
    (procedure "find_field" line 10)
    invoked from within
"find_field "width="  $line"
    (procedure "display_graph" line 129)
    invoked from within
"display_graph p_receiver"
    (command bound to event)

#13 Re: General » acceptance cycles » 2011-11-30 08:47:23

I've used [ code ] ... [ \code ]. See http://spinroot.com/fluxbb/help.php#bbcode. But some of the other tags don't seem to work.

#14 Re: General » acceptance cycles » 2011-11-29 14:22:57

I think I've finally got it. Actually the same behavior is exhibited by the following program:

int x;
ltl p { <> (x == 1)}
init { 0; x = 1; }

which clearly deadlocks/blocks. As explained on page 130 of the SPIN book (Ch.6, The stutter extension rule), for finite traces, the last state is stuttered, in order to obtain an infinite trace. Then everything makes sense.

This explanation also appears at [url]http://spinroot.com/spin/Man/progress.html[/url]:
[quote]
The standard stutter-extension, to extend finite execution sequences into infinite ones by stuttering (repeating) the final state of the sequence, is applied in the detection of all standard types of acceptance properties, but it is not used for non-progress cycles.
[/quote]
But it does not appear on [url]http://spinroot.com/spin/Man/accept.html[/url] or [url]http://spinroot.com/spin/Man/ltl.html[/url]. Thus I would say that these pages are rather misleading with regard to the treatment of finite traces.

#15 Re: General » acceptance cycles » 2011-11-29 13:37:04

To be more clear, here is the model I have. (Sorry, it's quite long.)

#define N 3
#define C 1

byte nr_leaders;



ltl p0	{ <> (nr_leaders > 0) }
ltl p1	{ <>[] (nr_leaders == 1) }
ltl p2	{ [] (nr_leaders == 0 U nr_leaders == 1) }
ltl p3	{ ![] (nr_leaders == 0) }


mtype = {IN, OUT};

/* the type of messages: inbound(0)/outbound(1), id, hops */
chan ch1[N] = [C] of {mtype,byte,byte};
chan ch2[N] = [C] of {mtype,byte,byte};


inline send(ch, m, i, h, d) {
  atomic {
    ch ! m, i, h;
    if
      :: d -> printf ("[%d to right] ! %e, %d, %d\n", id, m, i, h);
      :: else -> printf ("[%d to left] ! %e, %d, %d\n", id, m, i, h);
    fi
  }
}

inline recv(ch, m, i, h, d) {
  atomic {
    ch ? m, i, h;
    if
      :: d -> printf ("[%d from right] ? %e, %d, %d\n", id, m, i, h);
      :: else -> printf ("[%d from left] ? %e, %d, %d\n", id, m, i, h);
    fi
  }
}

/* chb = backward channel, chf = forward channel */
/* d is true iff chb = left_snd */
inline comm(chb, chf, d)
{
  if
    :: type == OUT -> /* outbound message */
       if
	 :: ch_id == id ->
	    nr_leaders++;
	    assert(nr_leaders == 1);	    
	    
	 :: ch_id > id ->
	    if
	      :: hops > 1 -> /* forward message */
		 send(chf, OUT, ch_id, (hops-1), d);
	      :: else -> /* last hop, change direction */
		 send(chb, IN, ch_id, 0, !d);
	    fi
	 :: else -> /* discard message */
	    skip
       fi
       
    :: else -> /* all inbound messages are replayed */
       if 
	 :: ch_id == id ->
	    tokens++;
	 :: else ->
	    send(chf, IN, ch_id, 0, d)
       fi
  fi
}

proctype node (chan left_snd, left_rcv, right_snd, right_rcv; byte id)
{
  byte round;
  unsigned tokens : 2;
  byte ch_id;
  byte type;
  byte hops;

  xr left_rcv,right_rcv;
  xs left_snd,right_snd;

  printf ("[%d] started\n", id);

  send(left_snd, OUT, id, 1<<round, false);
  send(right_snd, OUT, id, 1<<round, true);
  
  do
    :: recv(left_rcv, type, ch_id, hops, false) -> 
       comm(left_snd, right_snd, true)

    :: recv(right_rcv, type, ch_id, hops, true) ->
       comm(right_snd, left_snd, false)

    :: tokens == 2 ->
       tokens = 0;
       round++;
       send(left_snd, OUT, id, 1<<round, false);
       send(right_snd, OUT, id, 1<<round, true);
  od;

  printf ("[%d] finished\n", id);
}



init
{  
  atomic {     
    byte uid[6];
    byte i;    
     
    /* randomly generate the _unique_ ids */
    for (i : 1 .. N)
    {
      if /* non-deterministic choice */
	:: uid[0] == 0 && N >= 1 -> uid[0] = i
	:: uid[1] == 0 && N >= 2 -> uid[1] = i
	:: uid[2] == 0 && N >= 3 -> uid[2] = i
	:: uid[3] == 0 && N >= 4 -> uid[3] = i
	:: uid[4] == 0 && N >= 5 -> uid[4] = i
	:: uid[5] == 0 && N >= 6 -> uid[5] = i	/* works for up to N=6 */
      fi;
    }

    /* start the processes */
    for (i : 0 .. N-1) {
      run node(ch1[i], ch2[i], ch2[(i+1)%N], ch1[(i+1)%N], uid[i]);
      printf ("neighbors of node %d:\n  node %d on the left\n  node %d on the right\n",
	      uid[i], uid[(N+i-1)%N], uid[(i+1)%N]);
    }
  }
}

The trail, obtained with spin -t -p leader-bi.pml, ends like this:
  <<<<<START OF CYCLE>>>>>
spin: trail ends after 103 steps
#processes: 4
                nr_leaders = 0
                queue 1 (ch1[0]):
                queue 2 (ch1[1]): [OUT,2,1]
                queue 3 (ch1[2]):
                queue 4 (ch2[0]):
                queue 5 (ch2[1]): [OUT,1,1]
                queue 6 (ch2[2]):
103:    proc  3 (node) leader-bi.pml:65 (state 60)
103:    proc  2 (node) leader-bi.pml:33 (state 36)
103:    proc  1 (node) leader-bi.pml:33 (state 10)
103:    proc  0 (:init:) leader-bi.pml:106 (state 33)

This doesn't look to me like a cycle, but rather like a deadlock.

#16 General » acceptance cycles » 2011-11-28 17:20:22

eugen
Replies: 5

I have troubles understanding the acceptance cycles. I have a model for which I want to check an LTL property (of the form <>p) specified within the model (using 'ltl'). SPIN complains that there is an acceptance cycle, however the trail seems to be a finite execution: there is a START OF CYCLE, but no END OF CYCLE. Hence, apparently there is no cycle. Second, my understanding is that the corresponding never claim matches a finite execution only when the claim reaches its final state. But the following claim corresponding to the checked LTL property can never reach its end. So I don't see why SPIN is complaining.

never  {    /* ! <> p */
accept_init:
T0_init:
        if
        :: (! ((p))) -> goto T0_init
        fi;
}

I'm using the following sequence of commands:
  spin -a model.pr
  cc -o pan pan.c
  ./pan -a

Board footer

Powered by FluxBB