No edit summary |
No edit summary |
||
Line 35: | Line 35: | ||
The initial state of our model then looks as follows, when loaded using ProB Tcl/Tk: | The initial state of our model then looks as follows, when loaded using ProB Tcl/Tk: | ||
[[File:ProB_BlockInit_Screenshot.png|600px|center]] | [[File:ProB_BlockInit_Screenshot.png|600px|center]] | ||
<h3>Finding the GOAL</h3> | |||
To use the default mixed depth-first/breadth-first search you can type: | |||
$ probcli BlocksWorldGeneric6.mch -model_check | |||
As it has a random component, runtimes vary (up to 4 seconds). It finds reasonably short counter examples. | |||
You can use depth-first search using the -df flag: | |||
$ probcli BlocksWorldGeneric6.mch -model_check -df | |||
This finds a counter-example of length 48 relatively quickly (120 ms model checking time). | |||
As of version 1.5.1 you can use the <tt>-mc_mode</tt> flag to provide other options to control the model checking. | |||
probcli BlocksWorldGeneric6.mch -model_check -mc_mode random | |||
An interesting mode is <tt>heuristic</tt>. It looks for a user-provided DEFINITION for <tt>HEURISTIC_FUNCTION</tt> and uses this a s priority for states to process next. | |||
For example, we can provide the following definition to measure the distance to our target goal: | |||
<pre> | |||
DIFF(A,TARGET) == (card(A-TARGET) - card(TARGET /\ A)); | |||
HEURISTIC_FUNCTION == DIFF(on,ongoal); | |||
</pre> | |||
Now we get very good model checking time and short counter-examples (aka solution traces): | |||
<pre> | |||
$ time probcli BlocksWorldGeneric6.mch -model_check -mc_mode heuristic | |||
ALL OPERATIONS COVERED | |||
found_error(goal_found,62) | |||
finding_trace_from_to(root) | |||
. | |||
Model Checking Time: 80 ms (80 ms walltime) | |||
States analysed: 12 | |||
Transitions fired: 99 | |||
*** COUNTER EXAMPLE FOUND *** | |||
goal_found | |||
*** TRACE: | |||
1: INITIALISATION({(a|->b),(c|->a)}): | |||
2: move_on_object(c,d): | |||
3: move_on_object(e,f): | |||
4: move_on_table(c): | |||
5: move_on_object(d,e): | |||
6: move_on_object(c,d): | |||
7: move_on_table(a): | |||
8: move_on_object(b,c): | |||
9: move_on_object(a,b): | |||
! *** error occurred *** | |||
! goal_found | |||
real 0m1.232s | |||
user 0m1.120s | |||
sys 0m0.130s | |||
</pre> | |||
<h3> The complete model for reference </h3> | <h3> The complete model for reference </h3> |
In this example we want to highlight the new directed model checking features of ProB (available as of version 1.5.1).
For this we use the following model of Blocks-World, where we manipulate a given set of blocks (a,b,c,d,e,f). A robot arm can pick of blocks (provided no other block is on top of it) and either move it onto a table or onto another block (provided this block has no other block on top of it). The goal is, given a starting position, to find a plan for the robot to achieve a certain goal (here: block a is on top of b, which is on top of c, ...).
In B we can model this task as follows. We have two operations, on to move a block onto the table and one to move a block onto another one. The initial configuration is specified in the INITIALISATION; the target is specified by the GOAL definition (which the ProB model checker recognises).
MACHINE BlocksWorldGeneric6 SETS Objects={a,b,c,d,e,f} DEFINITIONS GOAL == (on = ongoal); ongoal == {a|->b, b|->c, c|->d, d|->e, e|->f} VARIABLES on INVARIANT on: Objects +-> Objects INITIALISATION on := {a|->b, c|->a} OPERATIONS move_on_table(obj) = PRE obj /: ran(on) & obj : dom(on) THEN on := {obj} <<| on END; move_on_object(obj,onobj) = PRE obj/:ran(on) & onobj /:ran(on) & obj /= onobj THEN on(obj) := onobj END END
Adding a graphical visualization is independent of the model checking, but helps visualising the traces found by the model checker. For this we can add ANIMATION_FUNCTION and ANIMATION_FUNCTION_DEFAULT definition, as specified in the complete model at the end of this page.
The initial state of our model then looks as follows, when loaded using ProB Tcl/Tk:
To use the default mixed depth-first/breadth-first search you can type:
$ probcli BlocksWorldGeneric6.mch -model_check
As it has a random component, runtimes vary (up to 4 seconds). It finds reasonably short counter examples.
You can use depth-first search using the -df flag:
$ probcli BlocksWorldGeneric6.mch -model_check -df
This finds a counter-example of length 48 relatively quickly (120 ms model checking time).
As of version 1.5.1 you can use the -mc_mode flag to provide other options to control the model checking.
probcli BlocksWorldGeneric6.mch -model_check -mc_mode random
An interesting mode is heuristic. It looks for a user-provided DEFINITION for HEURISTIC_FUNCTION and uses this a s priority for states to process next. For example, we can provide the following definition to measure the distance to our target goal:
DIFF(A,TARGET) == (card(A-TARGET) - card(TARGET /\ A)); HEURISTIC_FUNCTION == DIFF(on,ongoal);
Now we get very good model checking time and short counter-examples (aka solution traces):
$ time probcli BlocksWorldGeneric6.mch -model_check -mc_mode heuristic ALL OPERATIONS COVERED found_error(goal_found,62) finding_trace_from_to(root) . Model Checking Time: 80 ms (80 ms walltime) States analysed: 12 Transitions fired: 99 *** COUNTER EXAMPLE FOUND *** goal_found *** TRACE: 1: INITIALISATION({(a|->b),(c|->a)}): 2: move_on_object(c,d): 3: move_on_object(e,f): 4: move_on_table(c): 5: move_on_object(d,e): 6: move_on_object(c,d): 7: move_on_table(a): 8: move_on_object(b,c): 9: move_on_object(a,b): ! *** error occurred *** ! goal_found real 0m1.232s user 0m1.120s sys 0m0.130s
MACHINE BlocksWorldGeneric6 SETS Objects={a,b,c,d,e,f} DEFINITIONS ANIMATION_FUNCTION_DEFAULT == {r,c,img|r:1..card(Objects) & img=0 & c:1..card(Objects)}; ANIMATION_FUNCTION == ( {r,c,i| r=card(Objects) & i:Objects & c:Objects & c=i & i/:dom(on)} \/ {r,c,i| r:1..(card(Objects)-1) & i:Objects & c:Objects & i|->c:iterate(on,card(Objects)-r) & c/:dom(on)} ); ANIMATION_IMG0 == "images/empty_box_white.gif"; ANIMATION_IMG1 == "images/A.gif"; ANIMATION_IMG2 == "images/B.gif"; ANIMATION_IMG3 == "images/C.gif"; ANIMATION_IMG4 == "images/D.gif"; ANIMATION_IMG5 == "images/E.gif"; ANIMATION_IMG6 == "images/F.gif"; GOAL == (on = ongoal); ongoal == {a|->b, b|->c, c|->d, d|->e, e|->f}; DIFF(A,TARGET) == (card(A-TARGET) - card(TARGET /\ A)); HEURISTIC_FUNCTION == DIFF(on,ongoal); VARIABLES on INVARIANT on: Objects +-> Objects INITIALISATION on := {a|->b, c|->a} OPERATIONS move_on_table(obj) = PRE obj /: ran(on) & obj : dom(on) THEN on := {obj} <<| on END; move_on_object(obj,onobj) = PRE obj/:ran(on) & onobj /:ran(on) & obj /= onobj THEN on(obj) := onobj END END