SPIN verifier: cannot prove LTL formulae - verification

I have quite simpe sender-receiver protocol:
#define SZ 4
int sent = 0;
int received = 0;
chan ch = [SZ] of {int};
int varch;
init {
do
:: ((len(ch) < SZ) && (received != 1)) ->
d_step {
ch ! 1; sent = 1; printf("sent\n");
}
:: ((len(ch) == SZ) || ((received == 1) && (len(ch) > 0))) ->
d_step {
ch ? varch; received = 1; printf("received\n");
}
:: 1 -> /* simulates ramdomness */
atomic {
printf("timeout1\n");/*break; */
}
od;
}
which sends four packets and then receives them. Then I try to prove property: always send implies eventually receive:
ltl pr { [] ( (sent == 1) -> (<> (received == 1)) ) }
...and nothing happens: SPIN does not find both this property prove and its negation.
Why?

So, upon quick inspection, the LTL property cannot possibly be satisfied. The LTL property includes always but one viable execution is for the do::od statement to take the /* simulates randomness */ option forever. In that case, no queue will be 'received' and the LTL fails.
My SPIN run confirms the above (I put your code into a file 'sr.pml')
$ spin -a sr.pml
$ gcc -o pan pan.c
$ ./pan -a
pan:1: acceptance cycle (at depth 16)
pan: wrote sr.pml.trail
(Spin Version 6.3.2 -- 17 May 2014)
Warning: Search not completed
+ Partial Order Reduction
Full statespace search for:
never claim + (pr)
assertion violations + (if within scope of claim)
acceptance cycles + (fairness disabled)
invalid end states - (disabled by never claim)
State-vector 60 byte, depth reached 20, errors: 1
12 states, stored (14 visited)
0 states, matched
14 transitions (= visited+matched)
0 atomic steps
hash conflicts: 0 (resolved)
Stats on memory usage (in Megabytes):
0.001 equivalent memory usage for states (stored*(State-vector + overhead))
0.290 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
And then we can see the path with:
$ spin -p -t sr.pml
ltl pr: [] ((! ((sent==1))) || (<> ((received==1))))
starting claim 1
using statement merging
Never claim moves to line 4 [(1)]
2: proc 0 (:init::1) sr.pml:8 (state 1) [(((len(ch)<4)&&(received!=1)))]
4: proc 0 (:init::1) sr.pml:9 (state 5) [ch!1]
4: proc 0 (:init::1) sr.pml:10 (state 3) [sent = 1]
sent
4: proc 0 (:init::1) sr.pml:10 (state 4) [printf('sent\\n')]
Never claim moves to line 3 [((!(!((sent==1)))&&!((received==1))))]
6: proc 0 (:init::1) sr.pml:8 (state 1) [(((len(ch)<4)&&(received!=1)))]
Never claim moves to line 8 [(!((received==1)))]
8: proc 0 (:init::1) sr.pml:9 (state 5) [ch!1]
8: proc 0 (:init::1) sr.pml:10 (state 3) [sent = 1]
sent
8: proc 0 (:init::1) sr.pml:10 (state 4) [printf('sent\\n')]
10: proc 0 (:init::1) sr.pml:8 (state 1) [(((len(ch)<4)&&(received!=1)))]
12: proc 0 (:init::1) sr.pml:9 (state 5) [ch!1]
12: proc 0 (:init::1) sr.pml:10 (state 3) [sent = 1]
sent
12: proc 0 (:init::1) sr.pml:10 (state 4) [printf('sent\\n')]
14: proc 0 (:init::1) sr.pml:8 (state 1) [(((len(ch)<4)&&(received!=1)))]
16: proc 0 (:init::1) sr.pml:9 (state 5) [ch!1]
16: proc 0 (:init::1) sr.pml:10 (state 3) [sent = 1]
sent
16: proc 0 (:init::1) sr.pml:10 (state 4) [printf('sent\\n')]
<<<<<START OF CYCLE>>>>>
18: proc 0 (:init::1) sr.pml:16 (state 11) [(1)]
timeout1
20: proc 0 (:init::1) sr.pml:18 (state 12) [printf('timeout1\\n')]
spin: trail ends after 20 steps
#processes: 1
sent = 1
received = 0
queue 1 (ch): [1][1][1][1]
varch = 0
20: proc 0 (:init::1) sr.pml:7 (state 14)
20: proc - (pr:1) _spin_nvr.tmp:7 (state 10)
1 processes created
The <<<<<START OF CYCLE>>>> shows sr.pml at line 16 (:: 1 -> ...) executed forever. Also, there are other failures of the LTL. Run the SPIN search with './pan -a -i' to find the shortest trail; it indicates that your LTL isn't finding what you intend to find.

Related

Base 2 exponential of native int

Some algorithms (allocate a binary tree...) need to compute a base 2 exponential. How to compute it for this native type?
newtype {:nativeType "uint"} u32 =
x: nat | 0 <= x < 2147483648
This is an obvious try:
function pow2(n: u32): (r: u32)
requires n < 10
{
if n == 0 then 1 else 2 * pow2(n - 1)
}
It fails because Dafny doubts that the product stays below u32's max value. How to prove that it's value is below 2**10?
In this case, it is more convenient to first define the unbounded version of the function, and then prove a lemma showing that when n < 10 (or n < 32, even) it is in bounds.
function pow2(n: nat): int
{
if n == 0 then 1 else 2 * pow2(n - 1)
}
lemma pow2Bounds(n: nat)
requires n < 32
ensures 0 <= pow2(n) < 0x100000000
{ /* omitted here; two proofs given below */ }
function pow2u32(n: u32): u32
requires n < 32
{
pow2Bounds(n as nat);
pow2(n as nat) as u32
}
Intuitively, we might expect the lemma to go through automatically, because there are only a small number of cases to consider: n = 0, n = 1, ... n = 31. But Dafny will not perform such case analysis automatically. Instead, we have a couple of options.
First proof
First, we can prove a more general property, which, by the magic of inductive reasoning, is easier to prove, despite being stronger than what we need.
lemma pow2Monotone(a: nat, b: nat)
requires a < b
ensures pow2(a) < pow2(b)
{} // Dafny is able to prove this automatically by induction.
The lemma then follows.
lemma pow2Bounds(n: nat)
requires n < 32
ensures 0 <= pow2(n) < 0x100000000
{
pow2Monotone(n, 32);
}
Second proof
Another way to prove it is to tell Dafny it should unroll pow2 up to 32 times, using a :fuel attribute. These 32 unrollings are essentially the same as asking Dafny to do case analysis on each possible value. Dafny can then complete the proof without additional help.
lemma {:fuel pow2,31,32} pow2Bounds(n: nat)
requires n < 32
ensures 0 <= pow2(n) < 0x100000000
{}
The :fuel attribute is (lightly) documented in the Dafny Reference Manual in Section 24.
A bit of a cheat, but with so narrow a domain, this works very well.
const pow2: seq<u32> :=
[0x1, 0x2, 0x4, 0x8, 0x10, 0x20];
lemma pow2_exponential(n: u32)
ensures n == 0 ==> pow2[n] == 1
ensures 0 < n < 6 ==> pow2[n] == 2 * pow2[n - 1]
{}

Spin random error, bakery lock

I've created a bakery lock using Spin
1 int n=3;
2 int choosing[4] ; // initially 0
3 int number[4]; // initially 0
4
5 active [3] proctype p()
6 {
7
8 choosing[_pid] = 1;
9 int max = 0;
10 int i=0;
11
12 do
13 ::(number[i] > max) -> max=number[i];
14 ::i++;
15 :: (i == n) -> break;
16 od;
17
18 number[_pid] = max + 1;
19 choosing[_pid] = 0;
20
21 int j=0;
22
23 do
24 ::(j==n) -> break;
25 :: do
26 ::(choosing[j] == 0)-> break;
27 od;
28 :: if
29 ::(number[j] ==0) -> j++;
30 ::(number[j] > number[_pid]) -> j++;
31 ::((number[j] == number[_pid]) && ( j> _pid)) -> j++;
32 fi;
33 od;
34
35 number[_pid]=0
36
37 }
when I test it I get an error: pan:1: assertion violated - invalid array index (at depth 5)
when I run the trail I get this back
1: proc 2 (p) Bakery_lock.pml:8 (state 1) [choosing[_pid] = 1]
2: proc 2 (p) Bakery_lock.pml:10 (state 2) [max = 0]
2: proc 2 (p) Bakery_lock.pml:12 (state 3) [i = 0]
3: proc 2 (p) Bakery_lock.pml:14 (state 6) [i = (i+1)]
4: proc 2 (p) Bakery_lock.pml:14 (state 6) [i = (i+1)]
5: proc 2 (p) Bakery_lock.pml:14 (state 6) [i = (i+1)]
spin: indexing number[3] - size is 3
spin: Bakery_lock.pml:13, Error: indexing array 'number'
6: proc 2 (p) Bakery_lock.pml:13 (state 4) [((number[i]>max))]
Can anyone tell me why it skips this line (i == n) -> break; ?
It doesn't 'skip' that line. Spin executes every line that is executable. In your do the line i++ is always executable and therefore, because Spin explores all possible executions, the i++ line will be executed even when (i == n). The fix is:
do
:: (number[i] > max) -> max=number[i];
:: (i < n) -> i++
:: (i == n) -> break;
od;

How to reduce the code space for a hexadecimal ASCII chars conversion using a _small_ code space?

How to reduce the code space for a hexadecimal ASCII chars conversion using a small code space?
In an embedded application, I have extraordinary limited space (note 1). I need to convert bytes, from serial I/O, with the ASCII values '0' to '9' and 'A' to 'F' to the usual hexadecimal values 0 to 15. Also, all the other 240 combinations, including 'a' to 'f', need to be detected (as an error).
Library functions such as scanf(), atoi(), strtol() are far too large to use.
Speed is not an issue. Code size is the the limiting factor.
My present method re-maps the 256 byte codes into 256 codes such that '0' to '9' and 'A' to 'Z' have the values 0 - 35. Any ideas on how to reduce or different approaches are appreciated.
unsigned char ch = GetData(); // Fetch 1 byte of incoming data;
if (!(--ch & 64)) { // decrement, then if in the '0' to '9' area ...
ch = (ch + 7) & (~64); // move 0-9 next to A-Z codes
}
ch -= 54; // -= 'A' - 10 - 1
if (ch > 15) {
; // handle error
}
Note 1: 256 instructions exist for code and constant data (1 byte data costs 1 instruction) in a PIC protected memory for a bootloader. This code costs ~10 instructions. Current ap needs a re-write & with only 1 spare instruction, reducing even 1 instruction is valuable. I'm going through it piece by piece. Also have looked at overall reconstruction.
Notes: PIC16. I prefer to code in 'C', but must do what ever it takes. Assembly code follows. A quick answer is not required.
if (!(--ch & 64)) {
002D:DECF 44,F 002E:BTFSC 44.6 002F:GOTO 034
ch = (ch + 7) & (~64);
0030:MOVLW 07 0031:ADDWF 44,W 0032:ANDLW BF 0033:MOVWF 44
}// endif
ch -= 54;
0034:MOVLW 36 0035:SUBWF 44,F
[edit best solution]
Optimizing existing solution as suggested by #GJ. In C, performing the ch += 7; ch &= (~64); instead of ch = (ch + 7) & (~64); saved 1 instruction. Going to assembly saved another by not having to reload ch within the if().
PIC16 family is RISC MCPU, so you can try to optimize your asm code.
This is your c compilers asm code...
decf ch, f
btfsc ch, 6
goto Skip
movlw 07
addwf ch, w
andlw 0xBF
movwf ch
Skip
movlw 0x36
subwf ch, f
This is my optimization of upper code...
decf ch, w //WREG = (--ch)
btfsc WREG, 6 //if (!(WREG & 64)) {
goto Skip
addlw 7 //WREG += 7
andlw 0xBF //WREG &= (~64)
Skip
addlw 0x100 - 0x36 //WREG -= 54;
movwf ch //ch = WREG
//
addlw 0x100 - 0x10 //if (WREG > 15) {
btfsc STATUS, 0 //Check carry
goto HandleError
...so only 7 opcodes (2 less) without range error check and 10 opcodes with range error check!
EDIT:
Try also this PIC16 c compiler optimized function, not sure if works...
WREG = (--ch);
if (!(WREG & 64)) { // decrement, then if in the '0' to '9' area ...
WREG = (WREG + 7) & (~64); // move 0-9 next to A-Z codes
}
ch = WREG - 54; // -= 'A' - 10 - 1
if (WREG > 15) {
; // handle error
}
EDIT II: added version which is compatible with older PIC16 MCPUs not made in XLP technology, but code size is one opcode longer.
decf ch, f ;//ch = (--ch)
movf ch, w ;//WREG = ch
btfsc ch, 6 ;//if (!(ch & 64)) {
goto Skip
addlw 7 ;//WREG += 7
andlw 0xBF ;//WREG &= (~64)
Skip
addlw 0x100 - 0x36 ;//WREG -= 54;
movwf ch ;//ch = WREG
//
addlw 0x100 - 0x10 ;//if (WREG > 15) {
btfsc STATUS, 0 ;//Check carry
goto HandleError
EDIT III: explanation
The 'D Kruegers' solution is also very good, but need some modification...
This code..
if (((ch += 0xC6) & 0x80) || !((ch += 0xF9) & 0x80)) {
ch += 0x0A;
}
...we can translate to...
if (((ch -= ('0' + 10)) < 0) || ((ch -= ('A' - '0' - 10)) >= 0)) {
ch += 10;
}
After that we can optimize in asembler...
call GetData
//if GetData return result in WREG then you do not need to store in ch and read it again!
// movwf ch
// movf ch, w
addlw 0x100 - '0' - 10 //if (((WREG -= ('0' + 10)) < 0) || ((WREG -= ('A' - '0' - 10)) >= 0)) {
btfss STATUS, 0
goto DoAddx
addlw 0x100 - ('A' - '0' - 10)
btfsc STATUS, 0
DoAddx
addlw 10 //WREG += 10; }
movwf ch //ch = WREG;
addlw 0x100 - 0x10 //if (WREG > 15) {
btfsc STATUS, 0 //Check carry
goto HandleError
With good compiler optimization, this may take less code space:
unsigned char ch = GetData(); // Fetch 1 byte of incoming data;
if (((ch += 0xC6) & 0x80) || !((ch += 0xF9) & 0x80)) {
ch += 0x0A;
}
if (ch > 15) {
; // handle error
}
Perhaps using ctype.h's isxdigit():
if( isxdigit( ch ) )
{
ch -= (ch >= 'A') ? ('A' - 10) : '0' ;
}
else
{
// handle error
}
Whether that is smaller or not will depend largely on the implementation of isxdigit and perhaps your compiler and processor architecture, but worth a try and far more readable. isxdigit() is normally a macro so there is no function call overhead.
An alternative is to perform the transformation unconditionally then check the range of the result:
ch -= (ch >= 'A') ? ('A' - 10) :
(ch >= '0') ? '0' : 0 ;
if( ch > 0xf )
{
// handle error
}
I suspect this latter will be smaller, but modification of ch on error may be unhelpful in some cases, such as error reporting the original value.

Whats causing timeout in Promela/SPIN?

I have the following promela code:
chan level = [0] of {int};
proctype Sensor (chan levelChan) {
int x;
do
:: true ->
levelChan ? x;
if
:: (x < 2) -> printf("low %d", x);
:: (x > 8) -> printf("high %d", x);
:: else -> printf("normal %d", x);
fi
od
}
init {
run Sensor(level);
int lvl = 5;
level ! lvl;
lvl = 0;
do
:: true ->
level ! lvl;
lvl++;
(lvl > 9) -> break;
od
}
I am expecting to send level (0-9) information into a channel and have the sensor output low|normal|high depending on this level. Its quite simple. But why SPIN saying its timeout all the time?
0: proc - (:root:) creates proc 0 (:init:)
Starting Sensor with pid 1
1: proc 0 (:init:) creates proc 1 (Sensor)
1: proc 0 (:init:) 1.pml:18 (state 1) [(run Sensor(level))]
2: proc 1 (Sensor) 1.pml:6 (state 11) [(1)]
3: proc 0 (:init:) 1.pml:20 (state 2) [lvl = 5]
4: proc 0 (:init:) 1.pml:20 (state 3) [level!lvl]
4: proc 1 (Sensor) 1.pml:8 (state 2) [levelChan?x]
5: proc 1 (Sensor) 1.pml:9 (state 9) [else]
6: proc 0 (:init:) 1.pml:21 (state 4) [lvl = 0]
normal 5 8: proc 1 (Sensor) 1.pml:12 (state 8) [printf('normal %d',x)]
9: proc 0 (:init:) 1.pml:22 (state 10) [(1)]
12: proc 1 (Sensor) 1.pml:6 (state 11) [(1)]
13: proc 0 (:init:) 1.pml:24 (state 6) [level!lvl]
13: proc 1 (Sensor) 1.pml:8 (state 2) [levelChan?x]
14: proc 1 (Sensor) 1.pml:9 (state 9) [((x<2))]
low 0 15: proc 1 (Sensor) 1.pml:10 (state 4) [printf('low %d',x)]
17: proc 0 (:init:) 1.pml:25 (state 7) [lvl = (lvl+1)]
19: proc 1 (Sensor) 1.pml:6 (state 11) [(1)]
timeout
#processes: 2
19: proc 1 (Sensor) 1.pml:8 (state 2)
19: proc 0 (:init:) 1.pml:26 (state 8)
2 processes created
It seem to only do 1 iteration of the do loop why?
The statements in the init process's do loop are run in sequence.
do
:: true ->
level ! lvl;
lvl++;
(lvl > 9) -> break;
od
The very first time the do loop is run it will send lvl over the level channel, increase the lvl (so it is now 1) and then test (lvl > 9). This is false so will block and causes the timeout.
To have multiple options in a do loop you need :: to define the start of each option:
do
:: true ->
level ! lvl;
lvl++;
:: (lvl > 9) -> break;
od
However this will still not perform as expected. When lvl is greater than 9 both options of the do loop are valid and either one can be chosen, so the loop will not necessarily break when lvl > 9 it could choose to continue to send the lvl over the level channel and increase lvl.
You need to have a condition on the first do option as well as the second:
do
:: (lvl <= 9) ->
level ! lvl;
lvl++;
:: (lvl > 9) -> break;
od
It might be nicer to use the for loop syntax for this example:
init {
run Sensor(level);
int lvl = 5;
level ! lvl;
for (lvl : 0..9){
level ! lvl;
}
}
Note that this example will still have a timeout error caused by Sensor's do loop, when the init process has finished Sensor will still try to read from the level channel and timeout.

Running Time Calculation/Complexity of an Algorithm

I have to calculate the time complexity or theoretical running time of an algorithm (given the psuedocode), line by line as T(n). I've given it a try, but there are a couple things confusing me. For example, what is the time complexity for an "if" statement? And how do I deal with nested loops? The code is below along with my attempt which is commented.
length[A] = n
for i = 0 to length[A] - 1 // n - 1
k = i + 1 // n - 2
for j = 1 + 2 to length[A] // (n - 1)(n - 3)
if A[k] > A[j] // 1(n - 1)(n - 3)
k = j // 1(n - 1)(n - 3)
if k != i + 1 // 1(n - 1)
temp = A[i + 1] // 1(n - 1)
A[i + 1] = A[k] // 1(n - 1)
A[k] = temp // 1(n - 1)
Blender is right, the result is O(n^2): two nested loops that each have an iteration count dependent on n.
A longer explanation:
The if, in this case, does not really matter: Since O-notation only looks at the worst-case execution time of an algorithm, you'd simply choose the execution path that's worse for the overall execution time. Since, in your example, both execution paths (k != i+ 1 is true or false) have no further implication for the runtime, you can disregard it. If there were a third nested loop, also running to n, inside the if, you'd end up with O(n^3).
A line-by-line overview:
for i = 0 to length[A] - 1 // n + 1 [1]
k = i + 1 // n
for j = 1 + 2 to length[A] // (n)(n - 3 + 1) [1]
if A[k] > A[j] // (n)(n - 3)
k = j // (n)(n - 3)*x [2]
if k != i + 1 // n
temp = A[i + 1] // n*y [2]
A[i + 1] = A[k] // n*y
A[k] = temp // n*y
[1] The for loop statement will be executed n+1 times with the following values for i: 0 (true, continue loop), 1 (true, continue loop), ..., length[A] - 1 (true, continue loop), length[A] (false, break loop)
[2] Without knowing the data, you have to guess how often the if's condition is true. This guess can be done mathematically by introducing a variable 0 <= x <= 1. This is in line with what I said before: x is independent of n and therefore influences the overall runtime complexity only as a constant factor: you need to take a look at the execution paths .