Related
I am doing a program for tic-tac-toe and i have a line with
for ( count = 1; count < 10 && winner == 0; count++ );
I referred to other programs and came up with this.
And I'm not very sure of what the entire line means. I have searched up online but I dont understand the meaning of initialization statement ( count = 1 ) and the test expression. And also want to clarify, count++ means increase count right?
Let's have a look at the structure of a for loop:
for ( init-statement; condition; iteration_expression) statement;
From cppreference, a for loop does the following:
Executes init-statement once, then executes statement and iteration_expression repeatedly, until the value of condition becomes false. The test takes place before each iteration.
For your case:
init statement: at the beginning count is initialized to 1
condition: check if count is less than 10 and you don't have a winner yet
iteration_expression: cout++ increases count by 1
statement: you haven't provided that, but it will be executed until the condition is false.
Syntax of for loop is
for(initialization; condition; increment/decrement){
statement;
}
initialization:
Before we start looping, we will initialize the variable to certain value.
In this case, you are initializing 'count' variable to 1
Condition:
In condition part, To stop the loop at certain point you have to provide some conditions.
In this case, condition is 'count<10 && winner==0'. Note that, you are using And(&&) operation so, loop will stop only after both of the conditions are satisfied.
increment/decrement:
Based on the problem, you can choose to increment or decrement the loop variable('count'). In this case, count++ means you are incrementing the count by 1 after each iteration.
for (initialize;condition;increment/decrement)
for loop means
you initialize the variable
you apply a condition to stop the for loop
you execute a single time the loop body (if the condition satisfied)
then you increase or decrease the value of that variable and go to step 2
According to the man pages,
Progress labels are used to define correctness claims. A progress label states the requirement that the labeled global state must be visited infinitely often in any infinite system execution. Any violation of this requirement can be reported by the verifier as a non-progress cycle.
and
Spin has a special mode to prove absence of non-progress cycles. It does so with the predefined LTL formula:
(<>[] np_)
which formalizes non-progress as a standard Buchi acceptance property.
But let's take a look at the very primitive promela specification
bool initialised = 0;
init{
progress:
initialised++;
assert(initialised == 1);
}
In my understanding, the assert should hold but verification fail because initialised++ is executed exactly once whereas the progress label claims it should be possible to execute it arbitrarily often.
However, even with the above LTL formula, this verifies just fine in ispin (see below).
How do I correctly test whether a statement can be executed arbitrarily often (e.g. for a locking scheme)?
(Spin Version 6.4.7 -- 19 August 2017)
+ Partial Order Reduction
Full statespace search for:
never claim + (:np_:)
assertion violations + (if within scope of claim)
non-progress cycles + (fairness disabled)
invalid end states - (disabled by never claim)
State-vector 28 byte, depth reached 7, errors: 0
6 states, stored (8 visited)
3 states, matched
11 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.293 actual memory usage for states
64.000 memory used for hash table (-w24)
0.343 memory used for DFS stack (-m10000)
64.539 total actual memory usage
unreached in init
(0 of 3 states)
pan: elapsed time 0.001 seconds
No errors found -- did you verify all claims?
UPDATE
Still not sure how to use this ...
bool initialised = 0;
init{
initialised = 1;
}
active [2] proctype reader()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
progress_reader:
assert(true);
od
}
active [2] proctype writer()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
(initialised == 0)
progress_writer:
assert(true);
od
}
And let's select testing for non-progress cycles. Then ispin runs this as
spin -a test.pml
gcc -DMEMLIM=1024 -O2 -DXUSAFE -DNP -DNOCLAIM -w -o pan pan.c
./pan -m10000 -l
Which verifies without error.
So let's instead try this with ltl properties ...
/*pid: 0 = init, 1-2 = reader, 3-4 = writer*/
ltl progress_reader1{ []<> reader[1]#progress_reader }
ltl progress_reader2{ []<> reader[2]#progress_reader }
ltl progress_writer1{ []<> writer[3]#progress_writer }
ltl progress_writer2{ []<> writer[4]#progress_writer }
bool initialised = 0;
init{
initialised = 1;
}
active [2] proctype reader()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
progress_reader:
assert(true);
od
}
active [2] proctype writer()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
(initialised == 0)
progress_writer:
assert(true);
od
}
Now, first of all,
the model contains 4 never claims: progress_writer2, progress_writer1, progress_reader2, progress_reader1
only one claim is used in a verification run
choose which one with ./pan -a -N name (defaults to -N progress_reader1)
or use e.g.: spin -search -ltl progress_reader1 test.pml
Fine, I don't care, I just want this to finally run, so let's just keep progress_writer1 and worry about how to stitch it all together later:
/*pid: 0 = init, 1-2 = reader, 3-4 = writer*/
/*ltl progress_reader1{ []<> reader[1]#progress_reader }*/
/*ltl progress_reader2{ []<> reader[2]#progress_reader }*/
ltl progress_writer1{ []<> writer[3]#progress_writer }
/*ltl progress_writer2{ []<> writer[4]#progress_writer }*/
bool initialised = 0;
init{
initialised = 1;
}
active [2] proctype reader()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
progress_reader:
assert(true);
od
}
active [2] proctype writer()
{
assert(_pid >= 1);
(initialised == 1)
do
:: else ->
(initialised == 0)
progress_writer:
assert(true);
od
}
ispin runs this with
spin -a test.pml
ltl progress_writer1: [] (<> ((writer[3]#progress_writer)))
gcc -DMEMLIM=1024 -O2 -DXUSAFE -DSAFETY -DNOCLAIM -w -o pan pan.c
./pan -m10000
Which does not yield an error, but instead reports
unreached in claim progress_writer1
_spin_nvr.tmp:3, state 5, "(!((writer[3]._p==progress_writer)))"
_spin_nvr.tmp:3, state 5, "(1)"
_spin_nvr.tmp:8, state 10, "(!((writer[3]._p==progress_writer)))"
_spin_nvr.tmp:10, state 13, "-end-"
(3 of 13 states)
Yeah? Splendid! I have absolutely no idea what to do about this.
How do I get this to run?
The problem with your code example is that it does not have any infinite system execution.
Progress labels are used to define correctness claims. A progress
label states the requirement that the labeled global state must be
visited infinitely often in any infinite system execution. Any
violation of this requirement can be reported by the verifier as a
non-progress cycle.
Try this example instead:
short val = 0;
init {
do
:: val == 0 ->
val = 1;
// ...
val = 0;
:: else ->
progress:
// super-important progress state
printf("progress-state\n");
assert(val != 0);
od;
};
A normal check does not find any error:
~$ spin -search test.pml
(Spin Version 6.4.3 -- 16 December 2014)
+ Partial Order Reduction
Full statespace search for:
never claim - (none specified)
assertion violations +
cycle checks - (disabled by -DSAFETY)
invalid end states +
State-vector 12 byte, depth reached 2, errors: 0
3 states, stored
1 states, matched
4 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.292 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:12, state 5, "printf('progress-state\n')"
test.pml:13, state 6, "assert((val!=0))"
test.pml:15, state 10, "-end-"
(3 of 10 states)
pan: elapsed time 0 seconds
whereas, checking for progress yields the error:
~$ spin -search -l test.pml
pan:1: non-progress cycle (at depth 2)
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 + (:np_:)
assertion violations + (if within scope of claim)
non-progress cycles + (fairness disabled)
invalid end states - (disabled by never claim)
State-vector 20 byte, depth reached 7, errors: 1
4 states, stored
0 states, matched
4 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.292 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
WARNING: ensure to write -l after option -search, otherwise it is not handed over to the verifier.
You ask:
How do I correctly test whether a statement can be executed arbitrarily often (e.g. for a locking scheme)?
Simply write a liveness property:
ltl prop { [] <> proc[0]#label };
This checks that process with name proc and pid 0 executes infinitely often the statement corresponding to label.
Since your edit substantially changes the question, I write a new answer to avoid confusion. This answer addresses only the new content. Next time, consider creating a new, separate, question instead.
This is one of those cases in which paying attention to the unreached in ... warning message is really important, because it affects the outcome of the verification process.
The warning message:
unreached in claim progress_writer1
_spin_nvr.tmp:3, state 5, "(!((writer[3]._p==progress_writer)))"
_spin_nvr.tmp:3, state 5, "(1)"
_spin_nvr.tmp:8, state 10, "(!((writer[3]._p==progress_writer)))"
_spin_nvr.tmp:10, state 13, "-end-"
(3 of 13 states)
relates to the content of file _spin_nvr.tmp that is created during the compilation process:
...
never progress_writer1 { /* !([] (<> ((writer[3]#progress_writer)))) */
T0_init:
do
:: (! (((writer[3]#progress_writer)))) -> goto accept_S4 // state 5
:: (1) -> goto T0_init
od;
accept_S4:
do
:: (! (((writer[3]#progress_writer)))) -> goto accept_S4 // state 10
od;
} // state 13 '-end-'
...
Roughly speaking, you can view this as the specification of a Buchi Automaton which accepts executions of your writer process with _pid equal to 3 in which it does not reach the statement with label progress_writer infinitely often, i.e. it does so only a finite number of times.
To understand this you should know that, to verify an ltl property φ, spin builds an automaton containing all paths in the original Promela model that do not satisfy φ. This is done by computing the synchronous product of the automaton modeling the original system with the automaton representing the negation of the property φ you want to verify. In your example, the negation of φ is given by the excerpt of code above taken from _spin_nvr.tmp and labeled with never progress_writer1. Then, Spin checks if there is any possible execution of this automaton:
if there is, then property φ is violated and such execution trace is a witness (aka counter-example) of your property
otherwise, property φ is verified.
The warning tells you that in the resulting synchronous product none of those states is ever reachable. Why is this the case?
Consider this:
active [2] proctype writer()
{
1: assert(_pid >= 1);
2: (initialised == 1)
3: do
4: :: else ->
5: (initialised == 0);
6: progress_writer:
7: assert(true);
8: od
}
At line 2:, you check that initialised == 1. This statement forces writer to block at line 2: until when initialised is set to 1. Luckily, this is done by the init process.
At line 5:, you check that initialised == 0. This statement forces writer to block at line 5: until when initialised is set to 0. However, no process ever sets initialised to 0 anywhere in the code. Therefore, the line of code labeled with progress_writer: is effectively unreachable.
See the documentation:
(1) /* always executable */
(0) /* never executable */
skip /* always executable, same as (1) */
true /* always executable, same as skip */
false /* always blocks, same as (0) */
a == b /* executable only when a equals b */
A condition statement can only be executed (passed) if it holds. [...]
import math
def is_prime(num):
if num < 2:
return False
for i in range(2, int(math.sqrt(num))+ 1):
if num % i == 0:
return False
return True
Primes seems to be a popular topic but in the book in which I am learning Python, I am on chpt 6 out of 21 and in the iteration chapter which it teaches while loops. I have not learned for loops yet although I understand what they do. So, let's say I have not learned for loops yet and am given only if/elif/else statements and the while loops as my tools. How can I change the for line of code into something more simple using the above tools? While asking this question I quickly came up with this code:
def formula(num):
i = 2
while i >= 2:
return int(math.sqrt(num)+ 1)
def is_primetwo(num):
i = 2
if num < 2:
return False
formula(num)
if num % i == 0:
return False
return True
It works but would this be a simple version of the for loop or is there something even more simple where I do not have to wrap a function within a function?
Absolutely, you do not need a function to replace a for loop.
So you've got this
for i in range(2, int(math.sqrt(num))+ 1):
which is your for loop. Take a second to think what it's doing.
1.) It's taking the variable i, and it's starting it at a value of 2.
2.) It's checking whether to do the loop every time by checking if i is less than the (square root of num) plus 1
3.) Every time through the loop, it adds one to i.
We can do all of these things using a while loop.
Here's the original
for i in range(2, int(math.sqrt(num))+ 1):
if num % i == 0:
return False
let's rename the second and third lines loop contents just so we're focusing on the looping part, not what logic we're doing with the variables i and num.
for i in range(2, int(math.sqrt(num))+ 1):
loop contents
ok, now let's just rearrange it to be a while loop. We need to set i to 2 first.
i = 2
Now we want to check that i is in the range we want
i = 2
while i <= int(math.sqrt(num) + 1):
loop contents
Now we're almost set, we just need to make i actually change, instead of staying at a value of 2 forever.
i = 2
while i <= int(math.sqrt(num) + 1):
loop contents
i = i + 1
Your example seemed to do some of these elements, but this way is a simple way to do it, and no extra function is necessary. It could be the range() function that is confusing. Just remember, the for loop is doing three things; setting a variable to an initial value, checking a condition (one variable is less than another), and incrementing your variable to be one large than previously to run the loop again.
How about something like:
from math import sqrt
def is_prime(num):
if (num < 2):
return False
i = 2
limit = int(sqrt(num) + 1)
while (i <= limit):
if num % i == 0:
return False
i = i + 1
return True
Not sure if this is what you want, but the for loop:
for i in range(2, int(math.sqrt(num))+ 1):
if num % i == 0:
return False
return True
can be expressed as:
i = 2
while i < int(math.sqrt(num))+ 1):
if num % i == 0:
return False
i += 1
return True
Probably a good idea to determine int(math.sqrt(num))+ 1) once:
i = 2
n = int(math.sqrt(num))+ 1)
while i < n:
if num % i == 0:
return False
i += 1
return True
for (; cnt--; dp += sz)
{
pair_sanitize_struct(rec_id, ctx->api_mode, dp, FALSE);
}
Could some one explain how this for loop works? It belongs to a cpp file.
I dont understand the condition in the for loop and how it is being checked. (The function is being invoked)
The general form of for statement looks like this:
for (init-statement; condition; expression)
statement
init-statement is used to initialize or assign a starting value that is modified over the course of the loop. condition serves as the loop control. As long as condition evaluates as true, statement is executed. expression is evaluated for each iteration only if condition is true
Back to your code:
for (; cnt--; dp += sz)
init-statement here is a null statement that does nothing. condition is cnt-- which evaluates its value as cnt then decrements 1. If cnt is non-zero, condition is true, if cnt is zero, condition is false.
The condition is being interpreted as a true or false scenario.
If it's 0, then it will be false, else true.
This is equivalent to the following code -
for(; cnt-->0; dp += sz);
Because as long as a value is not equal to 0, it is considered to be true.
Remember that normal integers can be used as boolean values as well, where zero is false and everything non-zero is true.
This means that the loop will continue until cnt is zero, and then the loop will end. However that's not the whole story, since the post-decrement operator is used the value of cnt after the loop have ended will be -1.
It is similar to
while(cnt--)
{
pair_sanitize_struct(rec_id, ctx->api_mode, dp, FALSE);
dp += sz;
}
hope this is helpful.
So syntax for for loop is
for (<initialization(optional)>; <condition(Optional)>; <increment(Optional)>)
{
...
}
Say for cnt is 2 your loop works as follows,
for(; cnt--; dp+=size)
{
...
}
Execution flow is,
1. initialization statement will be executed once. Since you dont have one nothing will be executed
2. Next condition statement will be executed. In your case cnt-- which result in cnt value is considered as condition result. So, if cnt is 2 then value 2 is considered as condition result. Hence all non-zero are considered as TRUE and zero is considered as FALSE. After evaluating to TRUE it decrements cnt by 1
3. Once the condition results in TRUE then it executes the statement part say, pair_sanitize_struct(rec_id, ctx->api_mode, dp, FALSE);
4. At the last it executes the increment statement of for loop,in you case it is dp-=size;
5. It executes from 2 till condition evaluated to ZERO ie FALSE it comes out of loop.
In c++, the value for a condition being true or false is determined by being non 0 (true) or 0 (false).
The above loop would continue iterating as long as cnt is NOT 0. It will terminate when cnt becomes 0.
UPDATE:
To clear an important point here, it is the value 0 that terminates the loop. If for some reason, cnt already starts with a negative value, the loop will never terminate
so i want to know how a boolean acts in a condition statement in the following code
bool flag = true;
do {
d += data[i];
if (d > 15 || i == 3) {
flag = false;
}
i = i + 1;
} while (flag);
when will it exit the dowhile loop?
If either d > 15 or i == 3 evaluates to true, i will get incremented and the loop will stop.
In other words, flag is only checked at the end of each iteration, even though it might be set to false in the middle of one.
It will exit when (d > 15 || i == 3) which means (d > 15 or i == 3).
i is incremented at each iteration therefore if i is < 3 at the beginning of the program we are sure that at a certain point it will reach i == 3 and break the loop.
On d we can't tell much since we don't know it initial value nor its behavior inside the loop since we don't know anything about data.
Depends on your values of d and i...
As soon as d is greater than 15 or i is equal to 3, flag becomes false and the loop will end.
This might not happen in the same iteration, though. For example if i is incremented to 3 in a loop, it will be evaluated in the following loop first and flag might be set to false.
It will break the while when SUM of first 3 values in array Data[] be greater than "15", or break if does not be greater than 15 the SUM of first 3 values.
[It's depend on initial value of "i"]