Model Checking: why does LTL logic "<>" not produce correct counter-example in Spin - model-checking

Update
There are two problems in my previous attempt. By fixing them I successfully get the expected answer.
The LTL specified using the -f option from command line will be negated. Instead, I use the inline LTL by adding ltl { <> p} into the Promela program.
Second, when executing pan, seems that we need to use -a to "find acceptance cycles". I'm not completely sure what this means, my guess is that Spin will try to identify infinite schedules.
Original Question
I'm new to model checking and Spin. I am having trouble with the following example.
I specify the claim '<> p' that every schedule will eventually lead to p, in my case SUM > BOUND
In my understanding, if there exist an infinite schedule that p is always false, in my case SUM is always less than or equal to BOUND, spin will report that as a counter example.
However, when I run spin, the counter example I get is one that p is true.
Specifically, the commands, the Promela code and the trail are as follow.
In this trail, the result is that p is satisfied, as SUM is indeed bigger than BOUND. I could not understand why Spin give me an counter example that satisfies p?
./spin649_linux64 -f '<> p' -a sample.pml
gcc -o pan pan.c
./pan -i
./spin649_linux64 -p -t sample.pml
#define UPDATE(c) if :: ch[c]>sz[c] -> sz[c] = ch[c] :: else fi
#define PRODUCE(c, n) ch[c] = ch[c] + n; UPDATE(c)
#define CONSUME(c, n) ch[c] = ch[c] - n
#define WAIT(c, n) ch[c] >= n
int ch[2]; int sz[2];
#define BOUND 6
#define SUM (sz[0] + sz[1])
#define p (SUM > BOUND)
// Actor_a <==1==> Actor_b <==2==> Actor_c
// Actor_a produces 2 tokens to channel 1
// Actor_b consumes 3 tokens from channel 1 and produces 1 token to channel 2
// Actor_c consumes 2 tokens from channel 2
// sz[i] records the highest capacity seen for channel[i]
// There exist an infinite schedule that sz[0] + sz[1] is at most 6 at any moment
proctype Actor_a() {
do
:: atomic{ PRODUCE(0, 2); printf("a")}
od
}
proctype Actor_b() {
do :: atomic { WAIT(0,3) -> CONSUME(0, 3); PRODUCE(1, 1); printf("b") }
od
}
proctype Actor_c() {
do :: atomic {WAIT(1, 2) -> CONSUME(1, 2); printf("c")}
od
}
init {
atomic {
run Actor_a();
run Actor_b();
run Actor_c();
}
}
starting claim 4
spin: couldn't find claim 4 (ignored)
Starting Actor_a with pid 2
2: proc 0 (:init::1) sample.pml:30 (state 1) [(run Actor_a())]
Starting Actor_b with pid 3
3: proc 0 (:init::1) sample.pml:31 (state 2) [(run Actor_b())]
Starting Actor_c with pid 4
4: proc 0 (:init::1) sample.pml:32 (state 3) [(run Actor_c())]
6: proc 1 (Actor_a:1) sample.pml:14 (state 1) [ch[0] = (ch[0]+2)]
7: proc 1 (Actor_a:1) sample.pml:14 (state 2) [((ch[0]>sz[0]))]
7: proc 1 (Actor_a:1) sample.pml:14 (state 3) [sz[0] = ch[0]]
a 7: proc 1 (Actor_a:1) sample.pml:14 (state 7) [printf('a')]
9: proc 1 (Actor_a:1) sample.pml:14 (state 1) [ch[0] = (ch[0]+2)]
10: proc 1 (Actor_a:1) sample.pml:14 (state 2) [((ch[0]>sz[0]))]
10: proc 1 (Actor_a:1) sample.pml:14 (state 3) [sz[0] = ch[0]]
a 10: proc 1 (Actor_a:1) sample.pml:14 (state 7) [printf('a')]
12: proc 1 (Actor_a:1) sample.pml:14 (state 1) [ch[0] = (ch[0]+2)]
13: proc 1 (Actor_a:1) sample.pml:14 (state 2) [((ch[0]>sz[0]))]
13: proc 1 (Actor_a:1) sample.pml:14 (state 3) [sz[0] = ch[0]]
a 13: proc 1 (Actor_a:1) sample.pml:14 (state 7) [printf('a')]
15: proc 1 (Actor_a:1) sample.pml:14 (state 1) [ch[0] = (ch[0]+2)]
16: proc 1 (Actor_a:1) sample.pml:14 (state 2) [((ch[0]>sz[0]))]
16: proc 1 (Actor_a:1) sample.pml:14 (state 3) [sz[0] = ch[0]]
a 16: proc 1 (Actor_a:1) sample.pml:14 (state 7) [printf('a')]
spin: trail ends after 17 steps
#processes: 4
ch[0] = 8
ch[1] = 0
sz[0] = 8
sz[1] = 0
17: proc 3 (Actor_c:1) sample.pml:24 (state 5)
17: proc 2 (Actor_b:1) sample.pml:19 (state 11)
17: proc 1 (Actor_a:1) sample.pml:13 (state 9)
17: proc 0 (:init::1) sample.pml:34 (state 5) <valid end state>
4 processes created
Thanks a lot if you can help!

There are two problems in the original attempt. By fixing them I successfully get the expected answer.
The LTL specified using the -f option from command line will be negated. Instead, I use the inline LTL by adding ltl { <> p} into the Promela program.
Second, when executing pan, seems that we need to use -a to "find acceptance cycles". I'm not completely sure what this means, my guess is that Spin will try to identify infinite schedules.

Related

Will the output always be greater than 0 ? PROMELA program

I'm a bit boggled by this question, when I ran this program I got results greater than 0 but I'm not sure if that would always be the case since the program could execute x++ or x-- first in theory. How can I definitively confirm that the results will always be bigger than 0 ?
proctype testcount(byte x)
{
do
:: (x != 0 ) ->
if
:: x ++
:: x --
:: break
fi
:: else -> break
od;
printf("counter = %d\n", x);
}
init {run testcount(1)}
This can be easily verified by extending the model with the property you want to verify:
ltl larger_or_equal { [] (testcount[1]:x >= 0) };
ltl strictly_larger { [] (testcount[1]:x > 0) };
larger_or_equal: ``It is always the case that x >= 0''
strictly_larger: ``It is always the case that x > 0''
Complete Model:
proctype testcount(byte x)
{
do
:: (x != 0 ) ->
if
:: x ++
:: x --
:: break
fi
:: else -> break
od;
printf("counter = %d\n", x);
}
init {
run testcount(1)
}
ltl larger_or_equal { [] (testcount[1]:x >= 0) };
ltl strictly_larger { [] (testcount[1]:x > 0) };
Generate a verifier, and run it:
~$ spin -a test.pml
~$ gcc pan.c -o run
~$ ./run -a -N larger_or_equal
pan: ltl formula larger_or_equal
...
Full statespace search for:
never claim + (larger_or_equal)
assertion violations + (if within scope of claim)
acceptance cycles + (fairness disabled)
invalid end states - (disabled by never claim)
State-vector 28 byte, depth reached 1031, errors: 0
...
~$ ./run -a -N strictly_larger
pan: ltl formula strictly_larger
pan:1: assertion violated !( !((testcount[0].x>0))) (at depth 1)
pan: wrote test.pml.trail
...
Full statespace search for:
never claim + (strictly_larger)
assertion violations + (if within scope of claim)
acceptance cycles + (fairness disabled)
invalid end states - (disabled by never claim)
State-vector 20 byte, depth reached 1, errors: 1
...
As witnessed by the result of the above verification, property larger_or_equal is always true whereas property strictly_larger can be false.

How does the syntax in a if/then/else within a do block work in Haskell

I'm trying to make the folowing function:
repcountIORIban :: IORef -> Int -> Int -> Int -> Int -> Lock -> IORef -> Lock -> Int -> Int -> IO ()
repcountIORIban count number lower modulus amountthreads lock done lock2 difference rest = do
if rest > number
then let extra = 1
else let extra = 0
if number + 1 < amountthreads
then
forkIO $ realcountIORIban(count lower (lower + difference + extra - 1) modulus lock done lock2)
repcountIORIban (count (number + 1) (lower + difference + extra) modulus amountthreads lock done lock2 difference rest)
else
forkIO $ realcountIORIban(count lower (lower + difference + extra - 1) modulus lock done lock2)
But I can't run the program from which this function is a part of. It gives me the error:
error: parse error on input `else'
|
113 | else let extra = 0
| ^^^^
I've got this error a lot of times withing my program but I don't know what I'm doing wrong.
This is incorrect, you can't let after then/else and expect those lets to define bindings which are visible below.
do if rest > number
then let extra = 1 -- wrong, needs a "do", or should be "let .. in .."
else let extra = 0
... -- In any case, extra is not visible here
Try this instead
do let extra = if rest > number
then 1
else 0
...
Further, you need then do if after that you need to perform two or more actions.
if number + 1 < amountthreads
then do
something
somethingElse
else -- use do here if you have two or more actions
...

SPIN assert not triggered

I am trying to understand why the assert in this model isn't triggered.
ltl { !A#wa U B#sb && !B#wb U A#sa }
byte p = 0
byte q = 0
int x = 0
inline signal(sem) { sem++ }
inline wait (sem) { atomic { sem > 0 ; sem-- } }
proctype A() {
x = 10*x + 1
signal(p)
sa: wait(q)
wa: x = 10*x + 2
}
proctype B() {
x = 10*x + 3
signal(q)
sb: wait(p)
wb: x = 10*x + 4
}
init {
atomic { run A(); run B() }
_nr_pr == 1
assert(x != 1324)
}
Clearly, there is an order of operations that produces the final value x = 1324:
Initially x = 0
A sets x = 10*0 + 1 = 1
B sets x = 10*1 + 3 = 13
A and B allow each other to proceed
A sets x = 10*13 + 2 = 132
B sets x = 10*132 + 4 = 1324
The assertion isn't triggered because it is "never reached" when the solver proves that the property
ltl { !A#wa U B#sb && !B#wb U A#sa }
is true.
Take a look at the output that is given by the solver, it clearly states that:
it is checking any assertion, but only if within the scope of the claim:
Full statespace search for:
never claim + (ltl_0)
assertion violations + (if within scope of claim)
the assertion isn't reached:
unreached in init
t.pml:27, state 5, "assert((x!=1324))"
t.pml:28, state 6, "-end-"
(2 of 6 states)
You can use the option -noclaim so to check the model only for the assertion, which is then easily proven false:
~$ spin -search -noclaim t.pml
ltl ltl_0: ((! ((A#wa))) U ((B#sb))) && ((! ((B#wb))) U ((A#sa)))
pan:1: assertion violated (x!=1324) (at depth 13)
pan: wrote t.pml.trail
(Spin Version 6.4.8 -- 2 March 2018)
Warning: Search not completed
+ Partial Order Reduction
Full statespace search for:
never claim - (not selected)
assertion violations +
cycle checks - (disabled by -DSAFETY)
invalid end states +
State-vector 36 byte, depth reached 15, errors: 1
48 states, stored
6 states, matched
54 transitions (= stored+matched)
1 atomic steps
hash conflicts: 0 (resolved)
Stats on memory usage (in Megabytes):
0.003 equivalent memory usage for states (stored*(State-vector + overhead))
0.286 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

Find non-unique characters in a given string in O(n) time with constant space i.e with no extra auxiliary array

Given a string s containing only lower case alphabets (a - z), find (i.e print) the characters that are repeated.
For ex, if string s = "aabcacdddec"
Output: a c d
3 approaches to this problem exists:
[brute force] Check every char of string (i.e s[i] with every other char and print if both are same)
Time complexity: O(n^2)
Space complexity: O(1)
[sort and then compare adjacent elements] After sorting (in O(n log(n) time), traverse the string and check if s[i] ans s[i + 1] are equal
Time complexity: O(n logn) + O(n) = O(n logn)
Space complexity: O(1)
[store the character count in an array] Create an array of size 26 (to keep track of a - z) and for every s[i], increment value stored at index = s[i] - 26 in the array. Finally traverse the array and print all elements (i.e 'a' + i) with value greater than 1
Time complexity: O(n)
Space complexity: O(1) but we have a separate array for storing the frequency of each element.
Is there a O(n) approach that DOES NOT use any array/hash table/map (etc)?
HINT: Use BIT Vectors
This is the element distinctness problem, so generally speaking - no there is no way to solve it in O(n) without extra space.
However, if you regard the alphabet as constant size (a-z characters only is pretty constant) you can either create a bitset of these characters, in O(1) space [ it is constant!] or check for each character in O(n) if it repeats more than once, it will be O(constant*n), which is still in O(n).
Pseudo code for 1st solution:
bit seen[] = new bit[SIZE_OF_ALPHABET] //contant!
bit printed[] = new bit[SIZE_OF_ALPHABET] //so is this!
for each i in seen.length: //init:
seen[i] = 0
printed[i] = 0
for each character c in string: //traverse the string:
i = intValue(c)
//already seen it and didn't print it? print it now!
if seen[i] == 1 and printed[i] == 0:
print c
printed[i] = 1
else:
seen[i] = 1
Pseudo code for 2nd solution:
for each character c from a-z: //constant number of repeats is O(1)
count = 0
for each character x in the string: //O(n)
if x==c:
count += 1
if count > 1
print count
Implementation in Java
public static void findDuplicate(String str) {
int checker = 0;
char c = 'a';
for (int i = 0; i < str.length(); ++i) {
int val = str.charAt(i) - c;
if ((checker & (1 << val)) > 0) {
System.out.println((char)(c+val));
}else{
checker |= (1 << val);
}
}
}
Uses as int as storage and performs bit wise operator to find the duplicates.
it is in O(n) .. explanation follows
Input as "abddc"
i==0
STEP #1 : val = 98 - 98 (0) str.charAt(0) is a and conversion char to int is 98 ( ascii of 'a')
STEP #2 : 1 << val equal to ( 1 << 0 ) equal to 1 finally 1 & 0 is 0
STEP #3 : checker = 0 | ( 1 << 0) equal to 0 | 1 equal to 1 checker is 1
i==1
STEP #1 : val = 99 - 98 (1) str.charAt(1) is b and conversion char to int is 99 ( ascii of 'b')
STEP #2 : 1 << val equal to ( 1 << 1 ) equal to 2 finally 1 & 2 is 0
STEP #3 : checker = 2 | ( 1 << 1) equal to 2 | 1 equal to 2 finally checker is 2
i==2
STEP #1 : val = 101 - 98 (3) str.charAt(2) is d and conversion char to int is 101 ( ascii of 'd')
STEP #2 : 1 << val equal to ( 1 << 3 ) equal to 8 finally 2 & 8 is 0
STEP #3 : checker = 2 | ( 1 << 3) equal to 2 | 8 equal to 8 checker is 8
i==3
STEP #1 : val = 101 - 98 (3) str.charAt(3) is d and conversion char to int is 101 ( ascii of 'd')
STEP #2 : 1 << val equal to ( 1 << 3 ) equal to 8 finally 8 & 8 is 8
Now print 'd' since the value > 0
You can also use the Bit Vector, depends upon the language it would space efficient. In java i would prefer to use int for this fixed ( just 26) constant case
The size of the character set is a constant, so you could scan the input 26 times. All you need is a counter to store the number of times you've seen the character corresponding to the current iteration. At the end of each iteration, print that character if your counter is greater than 1.
It's O(n) in runtime and O(1) in auxiliary space.
Implementation in C# (recursive solution)
static void getNonUniqueElements(string s, string nonUnique)
{
if (s.Count() > 0)
{
char ch = s[0];
s = s.Substring(1);
if (s.LastIndexOf(ch) > 0)
{
if (nonUnique.LastIndexOf(ch) < 0)
nonUnique += ch;
}
getNonUniqueElements(s, nonUnique);
}
else
{
Console.WriteLine(nonUnique);
return;
}
}
static void Main(string[] args)
{
getNonUniqueElements("aabcacdddec", "");
Console.ReadKey();
}

Is simulating race conditions with gdb/lldb feasible?

I'm wondering if it would be feasible to automatically test for race conditions using a debugger.
For example, imaging you want to test a multi-threaded queue. Amongst others you would want to test that you can concurrently call enqueue() and dequeue().
A simple unit-test could be able to start two threads, each calling enqueue() and dequeue() respectively in a loop and checking the results:
// thread A
for( int i=0; i<count; i+=1 ) {
enqueue( queue, i );
}
// thread B
for( int i=0; i<count; i+=1 ) {
ASSERT( i == dequeue( queue ) );
}
Now, a clever test-driver, running the unit-test in gdb or lldb, should be able to wait for breakpoints set inside both loops and then use the debuggers si (step instruction) command to simulate all possible interleavings of the two threads.
My question is not if this is technically possible (it is). What I want to know is this:
Assuming the enqueue() function has 10 instructions and the dequeue() function has 20 - how many different interleavings does the test have to try?
Let's see...
If we only have 2 instructions in each: a,b and A,B:
a,b,A,B
a,A,b,B
a,A,B,b
A,a,b,B
A,a,B,b
A,B,a,b
That's 6.
For a, b, C and A,B,C:
a,b,c,A,B,C
a,b,A,c,B,C
a,b,A,B,c,C
a,b,A,B,C,c
a,A,b,c,B,C
a,A,b,B,c,C
a,A,B,b,c,C
a,A,b,B,C,c
a,A,B,b,C,c
a,A,B,C,b,c
A,a,b,c,B,C
A,a,b,B,c,C
A,a,B,b,c,C
A,B,a,b,c,C
A,a,b,B,C,c
A,a,B,b,C,c
A,B,a,b,C,c
A,a,B,C,b,c
A,B,a,C,b,c
A,B,C,a,b,c
That's 20, unless I'm missing something.
If we generalize it to N instructions (say, N is 26) in each and start with a...zA...Z, then there will be 27 possible positions for z (from before A to after Z), at most 27 positions for y, at most 28 for x, at most 29 for w, etc. This suggest a factorial at worst. In reality, however, it's less than that, but I'm being a bit lazy, so I'm going to use the output from a simple program calculating the number of possible "interleavings" instead of deriving the exact formula:
1 & 1 -> 2
2 & 2 -> 6
3 & 3 -> 20
4 & 4 -> 70
5 & 5 -> 252
6 & 6 -> 924
7 & 7 -> 3432
8 & 8 -> 12870
9 & 9 -> 48620
10 & 10 -> 184756
11 & 11 -> 705432
12 & 12 -> 2704156
13 & 13 -> 10400600
14 & 14 -> 40116600
15 & 15 -> 155117520
16 & 16 -> 601080390
So, with these results you may conclude that while the idea is correct, it's going to take an unreasonable amount of time to use it for code validation.
Also, you should remember that you need to take into account not only the order of instruction execution, but also the state of the queue. That's going to increase the number of iterations.
Here's the program (in C):
#include <stdio.h>
unsigned long long interleavings(unsigned remaining1, unsigned remaining2)
{
switch (!!remaining1 * 2 + !!remaining2)
{
default: // remaining1 == 0 && remaining2 == 0
return 0;
case 1: // remaining1 == 0 && remaining2 != 0
case 2: // remaining1 != 0 && remaining2 == 0
return 1;
case 3: // remaining1 != 0 && remaining2 != 0
return interleavings(remaining1 - 1, remaining2) +
interleavings(remaining1, remaining2 - 1);
}
}
int main(void)
{
unsigned i;
for (i = 0; i <= 16; i++)
printf("%3u items can interleave with %3u items %llu times\n",
i, i, interleavings(i, i));
return 0;
}
BTW, you could also save an order of magnitude (or two) of the overhead due to interfacing with the debugger and due to the various context switches, if you simulate pseudo-code instead. See this answer to a somewhat related question for a sample implementation. This may also give you a more fine grained control over switching between the threads than direct execution.

Resources