Top Banner
Modelling Examples Jens Bendisposto;Joy Clark;Michael Leuschel
112

Modelling Examples

Feb 03, 2023

Download

Documents

Khang Minh
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Modelling Examples

Modelling ExamplesJens Bendisposto;Joy Clark;Michael Leuschel

Page 2: Modelling Examples

Table of ContentsModelling Examples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  1

Apples and Oranges. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  1

Argumentation Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  3

Blocks World (Directed Model Checking). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  12

Bridges Puzzle (Hashiwokakero) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  17

Cheryl’s Birthday . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  22

Die Hard Jugs Puzzle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  25

Euler Problem 67 - Maximum Path Sum II . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  31

Fibonacci Numbers with Automatic Dynamic Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  40

Game of Life . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  41

Gilbreath Card Trick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  44

Mutual Exclusion (Fairness) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  51

N-Bishops Puzzle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  53

N-Queens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  54

Nine Prisoners . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  56

Peaceable Armies of Queens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  59

Proving Theorems in ProB REPL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  66

Rush Hour Puzzle. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  69

Rush Hour XTL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  85

SEND-MORE-MONEY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  93

ProB Validation for Siemens SAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  96

Sudoku Solved in the ProB REPL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  98

TrainSwitchingPuzzle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  109

Page 3: Modelling Examples

Modelling Examples

Apples and OrangesThis puzzle is apparently an Interview question at Apple. Quoting from 1 we have the followinginformation:

• (1) There are three boxes, one contains only apples, one contains only oranges, and one containsboth apples and oranges.

• (2) The boxes have been incorrectly labeled such that no label identifies the actual contents ofthe box it labels.

• (3) Opening just one box, and without looking in the box, you take out one piece of fruit.

• (4) By looking at the fruit, how can you immediately label all of the boxes correctly?

Here is one encoding of this puzzle in B:

MACHINE ApplesOrangesSETS Fruit={apple,orange}; // possible content for the boxes Label={A,O,Both} // labels for the boxesCONSTANTS a,o,b, // a,o,b are the three boxes  Take, // which box should we open (the label of that box)  DecisionFunction // given the fruit we pick from Take: what are the contentsof the boxes labeled A,O,BothPROPERTIES  a = {apple} & o={orange} & b={apple,orange} // (1)  &  Take : Label //3  &  DecisionFunction : Fruit --> (Label >->> {a,o,b}) & //4  !label. ( // the decision function has to work for all allowed labelings  ( label : {a,o,b} >->> Label &  label(a) /= A & label(o) /= O & label(b) /= Both // (2)  )  =>  !f.(f: label~(Take)  => DecisionFunction(f)=label~ // the function should tell us what is behindlabel A,O,Both  )  )END

We have abstracted the box of apples a by the set containing apple. Ditto for o and b, which areabstracted by {orange} and {apple,orange} respectively.

1

Page 4: Modelling Examples

NOTEYou need a recent version of ProB 1.5.1-beta3 or newer to load the above modelwith its one-line comments. If you have an older version of ProB, simply use thenormal comments /* … */.

Loading this model with ProB gives you just one solution (after less than 10 ms):

As we can see, the only solution is to open the box labelled with "Both". We can inspect the decisionfunction by using the B REPL (e.g., double click on the State Properties pane to open it):

>>>> DecisionFunction(apple)  {(A|->{orange}),(O|->{apple,orange}),(Both|->{apple})}

>>>> DecisionFunction(orange)  {(A|->{apple,orange}),(O|->{apple}),(Both|->{orange})}

In other words, when we pick an apple out of the box labelled with "Both", then it contains onlyapples and the box labelled "O"ranges contains both apples and oranges. The box labelled "A"pplescontains just oranges. Similarly, if we pick up an orange out of the box labelled with "Both", then itcontains only oranges and the box labelled with "A"pples contains contains both apples andoranges. The box labelled "O"ranges contains just apples.

2

Page 5: Modelling Examples

NOTEYou can inspect values or expressions in a tabular form, using the command"Expression as Table…" in the Visualize→Formulas menu. If you enter"DecisionFunction" as expression you will see the following tabular representation:

Argumentation TheoryBelow we try to model some concepts of argumentation theory in B. The examples try to show thatclassical (monotonic) logic with set theory can be used to model some aspects of argumentationtheory quite naturally, and that ProB can solve and visualise some problems in argumentationtheory. Alternative solutions are encoding arguments as normal logic programs (with non-monotonic negation) and using answer set solvers for problem solving.

The following model was inspired by a talk given by Claudia Schulz.

The model below represents the labelling of the arguments as a total function from arguments to itsstatus, which can either be in (the argument is accepted), out (the argument is rejected), or undec(the argument is undecided). The relation between the arguments is given in the binary attacksrelation.

In case you are new to B, you probably need to know the following operators to understand thespecification below (we als have a summary page about the B syntax):

• x : S specifies that x is an element of S

• a|→b represents the pair (a,b); note that a relation and function in B is a set of pairs.

• x|→y : R hence specifies that x is mapped to y in relation R

• !x.(P ⇒ Q) denotes universal quantification over variable x

• #x.(P & Q) denotes existential quantification over variable x

• A ←→ B denotes the set of relations from A to B

• A -→ B denotes the set of total functions from A to B

• block comments are of the form /* … */ and line comments start with // (be sure to useversion 1.5.1 of ProB, e.g., from the Nightly download site as line comments were added recentlyto B)

3

Page 6: Modelling Examples

MACHINE ArgumentationTotFunSETS ARGUMENTS={A,B,C,D,E}; STATUS = {in,out,undec}CONSTANTS attacks, labelPROPERTIES  attacks : ARGUMENTS <-> ARGUMENTS /* which argument attacks which other argument */  &  label: ARGUMENTS --> {in,out,undec} & /* the labeling function */

  // if an argument y is in any attacker must be out:  !(x,y).(x|->y:attacks => (label(y)=in => label(x)=out)) &  // if an argument x is in anything it attacks must be out:  !(x,y).(x|->y:attacks => (label(x)=in => label(y)=out)) &  //if an argument y is out it must be attacked by a valid argument:  !(y).(y:ARGUMENTS => (label(y)=out => #x.(x|->y:attacks & label(x)=in))) &  // if an argument y is undecided it must be attacked by an undecided argument:  !(y).(y:ARGUMENTS => (label(y)=undec => #x.(x|->y:attacks & label(x)=undec))) &  // here we model one particular argumentation graph  // A = the sun will shine to day, B = we are in the UK, C = it is summer, D = thereare only 10 days of sunshine per year, E = the BBC has forecast sun  attacks = {B|->A, C|->B, D|->C, E |-> B, E|->D}END

Here is a screenshot of ProB Tcl/Tk after loading the model.

4

Page 7: Modelling Examples

You can see that there is only a single solution (solving time 10 ms), as only a singleSETUP_CONSTANTS line is available in the "Enabled Operations" pane. Double-click onSETUP_CONSTANTS and then INITIALISATION will give you the following result, where you can seethe solution in the "State Properties" pane:

If you want to inspect the solution visually, you can select the "Current State as Graph" command inthe "States" submenu of the "Visualize" menu:

5

Page 8: Modelling Examples

This results in the following picture being displayed:

You can try and experiment with various attack graphs by editing the file. E.g., with

attacks = {B|→A, C|→B, D|→C, E |→ B, E|→D, D|→E}

you now get three possible labelling, the last one assigns undec to all arguments.

6

Page 9: Modelling Examples

7

Page 10: Modelling Examples

8

Page 11: Modelling Examples

A more elegant encoding

The following is a slightly more elegant encoding, where we represent the labelling as a partition ofthe arguments. This enables to use the relational image operator to express some constraints morecompactly. This model is particularly well suited if you wish to use our Kodkod backend whichtranslates the constraints to SAT. However, even the standard ProB solver can solve this instance in10 ms (Kodkod requires 70 ms), so this would only be worthwhile for larger problem instances.

In case you are new to B, you probably need to know the following additional operators tounderstand the specification below (we als have a summary page about the B syntax):

• r~ is the inverse of a function or relation r

• r[S] is the relational image of a relation r for a set of domain values S

9

Page 12: Modelling Examples

MACHINE ArgumentationAsSetsSETS ARGUMENTS={A,B,C,D,E}CONSTANTS attacks, in,out,undecPROPERTIES  attacks : ARGUMENTS <-> ARGUMENTS /* which argument attacks which other argument */  &  // we partition the arguments into three sets  ARGUMENTS = in \/ out \/ undec &  in /\ out = {} & in /\ undec = {} & out /\ undec = {} &

  // if an argument is in, any attacker must be out:  attacks~[in] <: out &  // if an argument is in, anything it attacks must be out:  attacks[in] <: out &  //if an argument y is out, it must be attacked by a valid argument:  !y.(y:out => #x.(x|->y:attacks & x:in)) &  // if an argument y is undecided, it must be attacked by an undecided argument:  !y.(y:undec => #x.(x|->y:attacks & x:undec))

 &  // here we model one particular argumentation graph  // A = the sun will shine to day, B = we are in the UK, C = it is summer, D = thereare only 10 days of sunshine per year, E = the BBC has forecast sun  attacks = {B|->A, C|->B, D|->C, E |-> B, E|->D}END

Influencing the Graphical Rendering

One can influence the graphical representation of the current state in various ways. The user candirectly define nodes and edges of the graph to be rendered. One way to do this is by adding thefollowing lines after the MACHINE section:

DEFINITIONS CUSTOM_GRAPH_NODES == (in * {"green"}) \/ (out * {"red"}) \/ (undec * {"orange"}); CUSTOM_GRAPH_EDGES == attacks

These lines do not influence the meaning of the model; they are just used by ProB. Indeed, one canthen use the "Current State as Custom Graph" command in the "States" submenu of the "Visualise"menu to obtain the following rendering of the very first example above:

10

Page 13: Modelling Examples

An Event-B Version of the Model

Instead of using ProB Tcl/Tk you can also encode this model in Rodin, the Eclipse-based platform forEvent-B.

Here we have split the model into two contexts. The first one encodes the general rules for labelling(we use Camille syntax):

11

Page 14: Modelling Examples

context ArgumentsAsSetssets ARGUMENTSconstants attacks in out undecaxioms  @axm1 attacks ∈ ARGUMENTS ↔ ARGUMENTS // which argument attacks which other argument  @axm2 partition(ARGUMENTS,in,out,undec) // we partition the arguments into threesets  @axm3 attacks∼[in] ⊆ out // if an argument is in, any attacker must be out  @axm4 attacks[in] ⊆ out // if an argument is in, anything it attacks must be out  @axm5 ∀y·(y∈out ⇒ ∃x·(x↦y∈attacks ∧ x∈in)) //if an argument y is out, it must beattacked by a valid argument  @axm6 ∀y·(y∈undec ⇒ ∃x·(x↦y∈attacks ∧ x∈undec)) // if an argument y is undecided, itmust be attacked by an undecided argumentend

A second context then extends the above one, and encodes our particular problem instance:

context Arguments_Example extends ArgumentsAsSetsconstants A B C D Eaxioms  @part partition(ARGUMENTS,{A},{B},{C},{D},{E})  @example attacks = {B↦A, C↦B, D↦C, E ↦ B, E↦D}  /* A = the sun will shine to day, B = we are in the UK  C = it is summer, D = there are only 10 days of sunshine per year, E = the BBChas forecast sun */end

If you load this model with ProB for Rodin, you can see the solution in the State view:

Blocks World (Directed Model Checking)In this example we want to highlight the new directed model checking features of ProB (available

12

Page 15: Modelling Examples

as of version 1.5.1), which allow one to direct the model checker towards a desired goal. Technicallyspeaking, the model checker now maintains a weighted priority queue of unprocessed states,choosing states with minimal weights for processing. The user can influence how the weights forthe unprocessed states are to be computed. The techniques are also explained and evaluated in ascientific paper [1].

To illustrate the directed model checking feature, 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 noother block is on top of it) and either move it onto a table or onto another block (provided this blockhas no other block on top of it). The goal is, given a starting position, to find a plan for the robot toachieve a certain goal (here: block a is on top of b, which is on top of c, …). We want to use themodel checker to find such a plan, i.e., a counter-example found by the model checker is actually asolution to our planning problem.

In B we can model this task as follows. We have two operations, on to move a block onto the tableand one to move a block onto another one. The initial configuration is specified in theINITIALISATION; the target is specified by the GOAL definition (which the ProB model checkerrecognises).

MACHINE BlocksWorldGeneric6SETS Objects={a,b,c,d,e,f}DEFINITIONS  GOAL == (on = ongoal);  ongoal == {a|->b, b|->c, c|->d, d|->e, e|->f}VARIABLES onINVARIANT  on: Objects +-> ObjectsINITIALISATION  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  ENDEND

Adding a graphical visualization

Adding a graphical visualization is independent of the model checking, but helps visualising thetraces found by the model checker. For this we can add ANIMATION_FUNCTION andANIMATION_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:

13

Page 16: Modelling Examples

Finding the GOAL

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 (typically 0.5 to 3.5 seconds on a Mac Book Air 1.7GHz). 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). You canuse the -bf flag to force breadth-first search, thus obtaining shortest counter-examples (of length 7;model checking time about 3.3 seconds).

As of version 1.5.1 you can use the -mc_mode flag to provide other options to control the modelchecking (see also the tutorial page on directed model checking options).

One option is random, which gives every node (aka unprocesses state) a random weight. Thedifference over the mixed depth-first/breadth-first mode is that it completely disregards whennodes where generated. The mixed depth-first/breadth-first mode will try to do a mixture of depth-first and breadth-first traversal; the random mode here is "just" random:

probcli BlocksWorldGeneric6.mch -model_check -mc_mode random

14

Page 17: Modelling Examples

A variation of the above is the hash mode, which simply uses the state’s Prolog hash as the randomweight. The difference is that the result here is predictable, i.e., you will always get the same resultwhen you run the model checker:

probcli BlocksWorldGeneric6.mch -model_check -mc_mode hash

Possibly a more interesting mode is heuristic. It looks for a user-provided DEFINITION forHEURISTIC_FUNCTION and uses this a s priority for states to process next. For example, we can providethe 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):

$ 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: 12Transitions 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

In ProB Tcl/Tk you simply use the standard model checking dialog (in the Verify menu) and choosethe "Heuristic Function / Random" option in the "Search Strategy" pop-up menu:

15

Page 18: Modelling Examples

After that you can find the solution quickly by simply pressing the "Model Check" button:

When writing your own heuristic functions, keep in mind that internally the weights are stored as64-bit integers on 64-bit systems, and 32-bit integers on 32-bit systems; currently no overflowchecking is performed and larger values for the HEURISTIC_FUNCTION expression are silentlyconverted to the respective integer size.

The complete model for reference

16

Page 19: Modelling Examples

MACHINE BlocksWorldGeneric6SETS 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 onINVARIANT  on: Objects +-> ObjectsINITIALISATION  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  ENDEND

Bridges Puzzle (Hashiwokakero)The Hashiwokakero Puzzle is a logical puzzle where one has to build bridges between islands. Thepuzzle is also known under the name Ai-Ki-Ai. The puzzles can also be played online.

The requirements for this puzzle are as follows:

• the goal is to build bridges between islands so as to generate a connected graph

• every island has a number on it, indicating exactly how many bridges should be linked with theisland

• there is an upper bound (MAXBRIDGES) on the number of bridges that can be built-between

17

Page 20: Modelling Examples

two islands

• bridges cannot cross each other

A B model for this puzzle can be found below. The constants and sets of the model are as follows:

• N are the nodes (islands); we have added a constant ignore where one can stipulate whichislands should be ignored in this puzzle

• nl (number of links) stipulates for each island how many bridges it should be linked with

• xc, yc are the x- and y-coordinates for every island

A simple puzzle with four islands would be defined as follows, assuming the basic set N is definedas N = {a,b,c,d,e,f,g,h,i,j,k,l,m,n}:

 xc(a)=0 & xc(b)=1 & xc(c)=0 & xc(d) = 1 & yc(a)=0 & yc(b)=0 & yc(c)=1 & yc(d) = 1 & nl = {a|->2, b|->2, c|->2, d|->2} & ignore = {e,f,g,h,i,j,k,l,m,n}

Below we will use a more complicated puzzle to illustrate the B model.

The model then contains the following derived constants:

• plx,ply: the possible links between islands on the x- and y-axis respectively

• pl: the possible links both on the x- and y-axis combined

• cs: the conflict set of links which overlap, i.e., one cannot build bridges on both links (a,b) whenthe pair (a,b) is in cs

• connected: the set of links on which at least one bridge was built

The model also sets up the goal constant sol which maps every link in pl to a number indicatinghow many bridges are built on it. The model also stipulates that the graph set up by connectedgenerates a fully connected graph.

Here is the full model:

MACHINE BridgesDEFINITIONS MAXBRIDGES==2; LINKS == 1..(MAXBRIDGES*4); COORD == 0..10; p1 == prj1(nodes,nodes); p2 == prj2(nodes,nodes); p1i == prj1(nodes,INTEGER)SETS N = {a,b,c,d,e,f,g,h,i,j,k,l,m,n}CONSTANTS nodes, ignore, nl, xc,yc, plx,ply,pl, cs, sol, connectedPROPERTIES nodes = N \ ignore &

18

Page 21: Modelling Examples

 // target number of links per node: nl : nodes --> LINKS & /* number of links */

// coordinates of nodes xc: nodes --> COORD & yc: nodes --> COORD &

// possible links: pl : nodes <-> nodes & plx : nodes <-> nodes & ply : nodes <-> nodes &

 plx = {n1,n2 | xc(n1)=xc(n2) & n1 /= n2 & yc(n2)>yc(n1) &  !n3.(xc(n3)=xc(n1) => yc(n3) /: yc(n1)+1..yc(n2)-1) } & ply = {n1,n2 | yc(n1)=yc(n2) & n1 /= n2 & xc(n2)>xc(n1) &  !n3.(yc(n3)=yc(n1) => xc(n3) /: xc(n1)+1..xc(n2)-1)} & pl = plx \/ ply

&// compute conflict set (assumes xc,yc coordinates ordered in plx,ply)cs = {pl1,pl2 | pl1:plx & pl2:ply &  xc(p1(pl1)): xc(p1(pl2))+1..xc(p2(pl2))-1 &  yc(p1(pl2)): yc(p1(pl1))+1..yc(p2(pl1))-1}&

sol : pl --> 0..MAXBRIDGES &!nn.(nn:nodes => SIGMA(l).(l:pl &  (p1(l)=nn or p2(l)=nn)|sol(l))=nl(nn)) &

!(pl1,pl2).( (pl1,pl2):cs => sol(pl1)=0 or sol(pl2)=0) // no conflicts&

 // check graph connected connected = {pl|sol(pl)>0} & closure1(connected \/ connected~)[{a}] = {nn|nn:nodes & nl(nn)>0}

 // encoding of puzzle&

// A puzzle from bridges.png

 xc(a)=1 & yc(a)=1 & nl(a)=4 & xc(b)=1 & yc(b)=4 & nl(b)=6 & xc(c)=1 & yc(c)=6 & nl(c)=3 &

 xc(d)=2 & yc(d)=2 & nl(d)=1 & xc(e)=2 & yc(e)=5 & nl(e)=2 &

 xc(f)=3 & yc(f)=2 & nl(f)=4 & xc(g)=3 & yc(g)=4 & nl(g)=6 & xc(h)=3 & yc(h)=5 & nl(h)=4 &

19

Page 22: Modelling Examples

 xc(i)=4 & yc(i)=3 & nl(i)=3 & xc(j)=4 & yc(j)=6 & nl(j)=3 &

 xc(k)=5 & yc(k)=2 & nl(k)=1 &

 xc(l)=6 & yc(l)=1 & nl(l)=4 & xc(m)=6 & yc(m)=3 & nl(m)=5 & xc(n)=6 & yc(n)=5 & nl(n)=2 & ignore = {}

END

The puzzle encode above can be visualized as follows:

A solution for this puzzle is found by ProB in 0.08 seconds (on a MacBook Air 2.2GHz i7). Theconflict set is {d|→e),(b|→g, i|→j),(h|→n} and the value for sol is

{((a|->b)|->2),((a|->l)|->2),((b|->c)|->2),((b|->g)|->2),((c|->j)|->1), ((d|->e)|->0),((d|->f)|->1),((e|->h)|->2),((f|->g)|->2),((f|->k)|->1), ((g|->h)|->2),((h|->n)|->0),((i|->j)|->2),((i|->m)|->1),((l|->m)|->2),((m|->n)|->2)}

20

Page 23: Modelling Examples

Adding graphical visualization

To show the solution graphically, we can add the following to the DEFINITIONS clause in the model:

 CUSTOM_GRAPH_NODES == {n,w,w2|(n|->w):nl & w=w2}; // %n1.(n1:nodes|nl(n1)); CUSTOM_GRAPH_EDGES == {n1,w,n2|n1:nl & n2:nl & (p1i(n1),p1i(n2),w):sol}

One can then load the model, perform the initialisation (double clicking on INITIALISATION in theoperations pane) and the execute the command "Current State as Custom Graph" in the States sub-menu of the Visualize menu. This leads to the following picture:

One can load the Dot file generated by ProB into another tool (e.g., OmniGraffle) and then re-arrange the nodes to obtain the rectangular layout respecting the x- and y-coordinates:

21

Page 24: Modelling Examples

Cheryl’s BirthdayThis Puzzle is a variation of another Puzzle (Sum and Product) and has been described in a NewYork Times article.

Here is a first solution in B, where the text of the puzzle has been integrated as comments. Thereare almost certainly more elegant encodings of the problem in B. You can load this model using,e.g., ProB Tcl/Tk (see below). The model is also available as an example in our online ProB LogicCalculator.

In case you are new to B, you probably need to know the following operators to understand thespecification below (we als have a summary page about the B syntax):

• x : S specifies that x is an element of S

• dom(r) is the domain of a function or relation r

• r~ is the inverse of a function or relation r

• r[S] is the relational image of a relation r for a set of domain values S

• card(S) is the cardinality of a set S

• a|→b represents the pair (a,b); note that a relation and function in B is a set of pairs.

• !x.(P ⇒ Q) denotes universal quantification over variable x

22

Page 25: Modelling Examples

MACHINE CherylsBirthday/* A simplified version of the SumProduct Puzzle taken from http://www.nytimes.com/2015/04/15/science/a-math-problem-from-singapore-goes-viral-when-is-cheryls-birthday.html*/DEFINITIONS  DontKnowFromDay(PossDates,KDay) == card(PossDates~[{KDay}]) > 1;  KnowFromDay(PossDates,KDay) == card(PossDates~[{KDay}]) = 1CONSTANTS Month, Day, PD, PD2PROPERTIES  /* Albert and Bernard just met Cheryl. “When’s your birthday?” Albert asked Cheryl.*/  Month:STRING & Day:1..31 &

  /* Cheryl thought a second and said, “I’m not going to tell you, but I’ll give yousome clues.” She wrote down a list of 10 dates: */ PD = {("aug"|->14),("aug"|->15),("aug"|->17),  ("july"|->14),("july"|->16),("june"|->17),("june"|->18),  ("may"|->15),("may"|->16),("may"|->19)} & /*Then Cheryl whispered in Albert’s ear the month — and only the month — of herbirthday.To Bernard, she whispered the day, and only the day.*/  Month : dom(PD) &  Day : ran(PD) &  Month|->Day : PD &

 /* Albert: I don’t know when your birthday is, */ card(PD[{Month}]) > 1 & /* but I know Bernard doesn’t know, either. */ !x.(x:PD[{Month}] => DontKnowFromDay(PD,x) ) &

 /* Bernard: I didn’t know originally, */  DontKnowFromDay(PD,Day) & /* but now I do. */  PD2 = {m,d| (m|->d):PD & !x.(x:PD[{m}] => DontKnowFromDay(PD,x) ) } &  KnowFromDay(PD2,Day) &

  /* Albert: Well, now I know, too! */  card({d|Month|->d : PD2 & KnowFromDay(PD2,d)})=1

ASSERTIONS /* single solution found by ProB in 20-30 ms */  Month = "july";  Day = 16END

When loading this B machine in ProB, you will see that there is only a single solution (solving time20-30 ms) : Month = "july" and `Day = 16.

23

Page 26: Modelling Examples

Here is a screenshot of ProB Tcl/Tk after loading the model.

Using an enumerated set

It is possible to use an enumerated set for the Months. One simply has to add

SETS MONTHS = {may, june, july, aug, sep}

and then change the definition of the possible dates:

PD = {(aug|->14), (aug|->15), (aug|->17),  (july|->14),(july|->16),(june|->17),  (june|->18),  (may|->15),(may|->16),(may|->19)}

and also “july” in the ASSERTIONS clause into july. This makes constraint solving via ProBmarginally faster.

24

Page 27: Modelling Examples

Die Hard Jugs PuzzleThis is the B model of a puzzle from the movie "Die Hard with a Vengeance". This clip shows BruceWillis and Samuel Jackson having a go at the puzzle. A more detailed explanation can be foundhere. At start we have one 3 gallon and one 5 gallon jug, and we need to measure precisely 4 gallonsby filling, emptying or transferring water from the jugs.

MACHINE JarsDEFINITIONS  GOAL == (4 : ran(level));SETS Jars = {j3,j5}CONSTANTS maxfPROPERTIES maxf : Jars --> NATURAL &  maxf = {j3 |-> 3, j5 |-> 5} /* in this puzzle we have two jars, withcapacities 3 and 5 */VARIABLES levelINVARIANT  level: Jars --> NATURALINITIALISATION level := Jars * {0} /* all jars start out empty */OPERATIONS  FillJar(j) = /* we can completely fill a jar j */  PRE j:Jars & level(j)<maxf(j) THEN  level(j) := maxf(j)  END;  EmptyJar(j) = /* we can completely empty a jar j */  PRE j:Jars & level(j)>0 THEN  level(j) := 0  END;  Transfer(j1,amount,j2) = /* we can transfer from jar j1 to j2 until either j2 isfull or j1 is empty */  PRE j1:Jars & j2:Jars & j1 /= j2 & amount>0 &  amount = min({level(j1), maxf(j2)-level(j2)}) THEN  level := level <+ { j1|-> level(j1)-amount, j2 |-> level(j2)+amount }  ENDEND

After opening the file in ProB, choose the Model Check command in the Verify menu and thencheck the "Find Define GOAL" check box. This instructs ProB to search for states satisfying theGOAL predicate (4:ran(level)) defined above.

25

Page 28: Modelling Examples

Now press the model check button and you should now obtain the following message:

The main window of ProB now contains the following information:

You can see that the second jug contains exactly 4 gallons. The steps required to reach this state canbe found in the history pane on the right (in reverse order).

Graphical Animation

This machine above is actually included in the ProB distribution (inside theexamples/B/GraphicalAnimation/ directory). It also contains the following lines in the DEFINITIONSsection, which defines a quick-and-dirty graphical visualisation of the state. The images can befound in the subfolder images along the file Jars.mch.

  ANIMATION_IMG1 == "images/Filled.gif";  ANIMATION_IMG2 == "images/Empty.gif";  ANIMATION_IMG3 == "images/Void.gif";  gmax == max(ran(maxf));  ANIMATION_FUNCTION_DEFAULT == {r,c,i | c:Jars & r:1..gmax & i=3};  ri == (gmax+1-r);  ANIMATION_FUNCTION == {r,c,i | c:Jars & ri:1..maxf(c) &  (ri<=level(c) => i=1 ) & (ri>level(c) => i=2)}

Here is a screenshot of ProB Tcl/Tk after loading the model and having found the goal:

26

Page 29: Modelling Examples

Using probcli (command-line version)

To find the solution using probcli you just need to type:

probcli -model_check Jars.mch

The output will be as follows:

27

Page 30: Modelling Examples

$ probcli -model_check Jars.mch% found_enumeration_of_constants(30,40)% backtrack(found_enumeration_of_constants(30,40))

ALL OPERATIONS COVERED

found_error(goal_found,10)finding_trace_from_to(root).Model Checking Time: 60 ms (60 ms walltime)States analysed: 10Transitions fired: 36*** COUNTER EXAMPLE FOUND ***

goal_found*** TRACE: 1: SETUP_CONSTANTS({(j3|->3),(j5|->5)}): 2: INITIALISATION({(j3|->0),(j5|->0)}): 3: FillJar(j5): 4: Transfer(j5,3,j3): 5: EmptyJar(j3): 6: Transfer(j5,2,j3): 7: FillJar(j5): 8: Transfer(j5,1,j3):! *** error occurred ***! goal_found

TLA+ Version

A TLA+ version of the puzzle is also included with ProB (inside the examples/TLA+/ directory). Thespecification was developed by Leslie Lamport. It is possible to load TLA+ specifications with ProBas shown on the TLA wiki page.

------------------------------ MODULE DieHard -------------------------------(***************************************************************************)(* In the movie Die Hard 3, the heros must obtain exactly 4 gallons of *)(* water using a 5 gallon jug, a 3 gallon jug, and a water faucet. Our *)(* goal: to get TLC to solve the problem for us. *)(* *)(* First, we write a spec that describes all allowable behaviors of our *)(* heros. *)(***************************************************************************)EXTENDS Naturals  (*************************************************************************)  (* This statement imports the definitions of the ordinary operators on *)  (* natural numbers, such as +. *)  (*************************************************************************)

(***************************************************************************)

28

Page 31: Modelling Examples

(* We next declare the specification's variables. *)(***************************************************************************)VARIABLES big, \* The number of gallons of water in the 5 gallon jug.  small \* The number of gallons of water in the 3 gallon jug.

(***************************************************************************)(* We now define TypeOK to be the type invariant, asserting that the value *)(* of each variable is an element of the appropriate set. A type *)(* invariant like this is not part of the specification, but it's *)(* generally a good idea to include it because it helps the reader *)(* understand the spec. Moreover, having TLC check that it is an *)(* invariant of the spec catches errors that, in a typed language, are *)(* caught by type checking. *)(* *)(* Note: TLA+ uses the convention that a list of formulas bulleted by /\ *)(* or \/ denotes the conjunction or disjunction of those formulas. *)(* Indentation of subitems is significant, allowing one to eliminate lots *)(* of parentheses. This makes a large formula much easier to read. *)(* However, it does mean that you have to be careful with your indentation.*)(***************************************************************************)TypeOK == /\ small \in 0..3  /\ big \in 0..5

(***************************************************************************)(* Now we define of the initial predicate, that specifies the initial *)(* values of the variables. I like to name this predicate Init, but the *)(* name doesn't matter. *)(***************************************************************************)Init == /\ big = 0  /\ small = 0

(***************************************************************************)(* Now we define the actions that our hero can perform. There are three *)(* things they can do: *)(* *)(* - Pour water from the faucet into a jug. *)(* *)(* - Pour water from a jug onto the ground. *)(* *)(* - Pour water from one jug into another *)(* *)(* We now consider the first two. Since the jugs are not calibrated, *)(* partially filling or partially emptying a jug accomplishes nothing. *)(* So, the first two possibilities yield the following four possible *)(* actions. *)(***************************************************************************)FillSmallJug == /\ small' = 3  /\ big' = big

29

Page 32: Modelling Examples

FillBigJug == /\ big' = 5  /\ small' = small

EmptySmallJug == /\ small' = 0  /\ big' = big

EmptyBigJug == /\ big' = 0  /\ small' = small

(***************************************************************************)(* We now consider pouring water from one jug into another. Again, since *)(* the jugs are not callibrated, when pouring from jug A to jug B, it *)(* makes sense only to either fill B or empty A. And there's no point in *)(* emptying A if this will cause B to overflow, since that could be *)(* accomplished by the two actions of first filling B and then emptying A. *)(* So, pouring water from A to B leaves B with the lesser of (i) the water *)(* contained in both jugs and (ii) the volume of B. To express this *)(* mathematically, we first define Min(m,n) to equal the minimum of the *)(* numbers m and n. *)(***************************************************************************)Min(m,n) == IF m < n THEN m ELSE n

(***************************************************************************)(* Now we define the last two pouring actions. From the observation *)(* above, these definitions should be clear. *)(***************************************************************************)SmallToBig == /\ big' = Min(big + small, 5)  /\ small' = small - (big' - big)

BigToSmall == /\ small' = Min(big + small, 3)  /\ big' = big - (small' - small)

(***************************************************************************)(* We define the next-state relation, which I like to call Next. A Next *)(* step is a step of one of the six actions defined above. Hence, Next is *)(* the disjunction of those actions. *)(***************************************************************************)Next == \/ FillSmallJug  \/ FillBigJug  \/ EmptySmallJug  \/ EmptyBigJug  \/ SmallToBig  \/ BigToSmall

-----------------------------------------------------------------------------

(***************************************************************************)(* Remember that our heros must measure out 4 gallons of water. *)(* Obviously, those 4 gallons must be in the 5 gallon jug. So, they have *)(* solved their problem when they reach a state with big = 4. So, we *)(* define NotSolved to be the predicate asserting that big # 4. *)

30

Page 33: Modelling Examples

(***************************************************************************)NotSolved == big # 4

(***************************************************************************)(* We find a solution by having TLC check if NotSolved is an invariant, *)(* which will cause it to print out an "error trace" consisting of a *)(* behavior ending in a states where NotSolved is false. Such a *)(* behavior is the desired solution. (Because TLC uses a breadth-first *)(* search, it will find the shortest solution.) *)(***************************************************************************)=============================================================================

Z Version

A Z version of the puzzle is also included with ProB (inside the examples/Z/GraphicalAnimation/directory) and shown on the ProZ wiki page.

Here is how the animation of the Z specification should look like:

Euler Problem 67 - Maximum Path Sum IIHere we give a solution to the Euler Problem 67. The purpose is to show:

31

Page 34: Modelling Examples

• that the encoding in B is compact and hopefully readable

• that by using ProB we get dynamic programming automatically.

The Euler Problem 67 Description

For convenience,here is the description from the official site of the Euler Problem 67:

By starting at the top of the triangle below and moving to adjacent numbers on the row below, themaximum total from top to bottom is 23.

37 42 4 68 5 9 3

That is, 3 + 7 + 4 + 9 = 23.

Find the maximum total from top to bottom in triangle.txt (right click and 'Save Link/Target As…'), a15K text file containing a triangle with one-hundred rows.

NOTE

This is a much more difficult version of Problem 18. It is not possible to try everyroute to solve this problem, as there are 299 altogether! If you could check onetrillion (1012) routes every second it would take over twenty billion years to checkthem all. There is an efficient algorithm to solve it. ;o)

The solution in B

A solution in B is as follows, where the data for the triangle is held in the file triangle_Euler67.def:

32

Page 35: Modelling Examples

MACHINE Euler_Problem_067DEFINITIONS "triangle_Euler67.def"; SET_PREF_TIME_OUT == 5000CONSTANTS n, Sol, OptimalSolution, TriangleCPROPERTIES TriangleC = Triangle &n = size (TriangleC) &

Sol : 1..n --> seq(INTEGER) &Sol(n) = TriangleC(n) /* Initialisation */&! i. (i:1..(n-1) =>  (size(Sol(i)) = size(TriangleC(i))  & !j.(j: 1..size(TriangleC(i)) => Sol(i)(j) =TriangleC(i)(j)+max({Sol(i+1)(j),Sol(i+1)(j+1)}))  )  ) & OptimalSolution = Sol(1)(1)ASSERTIONS OptimalSolution = 7273; n = 100END

This problem was solved on a MacBook Air 1.7 GHz using ProB 1.4.0rc2 in under 2.5 seconds:

$ probcli Euler_Problem_067.mch -init% set_pref(TIME_OUT,time_out,5000)% found_enumeration_of_constants(1990,2260)% backtrack(found_enumeration_of_constants(1990,2260))

You can also check the assertions using the command probcli Euler_Problem_067.mch -init-assertions in the same time:

33

Page 36: Modelling Examples

$ probcliEuler_Problem_067.mch -init -assertions% set_pref(TIME_OUT,time_out,5000)% found_enumeration_of_constants(2060,2350)% backtrack(found_enumeration_of_constants(2060,2350))% Checking ASSERTIONS:Checking Static Assertions

==> OptimalSolution = 7273TRUETRUE (0 ms + 0 ms = 0 ms)

==> n = 100TRUETRUE (0 ms + 0 ms = 0 ms)=======SUMMARY=======2 predicates: 2 TRUE, 0 FALSE, 0 UNKNOWN (0 timeouts)0 ms to analyseChecking Dynamic Assertions=======SUMMARY=======0 predicates: 0 TRUE, 0 FALSE, 0 UNKNOWN (0 timeouts)0 ms to analyse[total/2,total_after_expansion/2,true/2,true_after_expansion/2,false/0,false_after_expansion/0,unknown/0,unknown_after_expansion/0,timeout/0,runtime/0,enum_warning/0]% Finished checking ASSERTIONS

An interesting fact is the that dynamic programming is done automatically by ProB’s constraintsolving. In the Fibonacci Numbers with Automatic Dynamic Programming page we explain this facton a simpler example.

A picat solution is also available. Compared to our solution, in the Picat solution the order ofcomputation is directly encoded in the Picat program. Here, ProB has to infer the order ofcomputation itself; this obviously comes at a performance price compared to a more imperativeencoding of the problem.

The runtimes could be improved by enforcing the proper order of computation explicitly inside themodel (e.g., by putting the computation of rows into B operations and use model checking oranimation to solve the problem).

The data file for the Euler Problem 67

Contents of the definition file triangle_Euler67.def are:

DEFINITIONSTriangle == [[59],

34

Page 37: Modelling Examples

[73, 41],[52, 40, 09],[26, 53, 06, 34],[10, 51, 87, 86, 81],[61, 95, 66, 57, 25, 68],[90, 81, 80, 38, 92, 67, 73],[30, 28, 51, 76, 81, 18, 75, 44],[84, 14, 95, 87, 62, 81, 17, 78, 58],[21, 46, 71, 58, 02, 79, 62, 39, 31, 09],[56, 34, 35, 53, 78, 31, 81, 18, 90, 93, 15],[78, 53, 04, 21, 84, 93, 32, 13, 97, 11, 37, 51],[45, 03, 81, 79, 05, 18, 78, 86, 13, 30, 63, 99, 95],[39, 87, 96, 28, 03, 38, 42, 17, 82, 87, 58, 07, 22, 57],[06, 17, 51, 17, 07, 93, 09, 07, 75, 97, 95, 78, 87, 08, 53],[67, 66, 59, 60, 88, 99, 94, 65, 55, 77, 55, 34, 27, 53, 78, 28],[76, 40, 41, 04, 87, 16, 09, 42, 75, 69, 23, 97, 30, 60, 10, 79, 87],[12, 10, 44, 26, 21, 36, 32, 84, 98, 60, 13, 12, 36, 16, 63, 31, 91, 35],[70, 39, 06, 05, 55, 27, 38, 48, 28, 22, 34, 35, 62, 62, 15, 14, 94, 89, 86],[66, 56, 68, 84, 96, 21, 34, 34, 34, 81, 62, 40, 65, 54, 62, 05, 98, 03, 02, 60],[38, 89, 46, 37, 99, 54, 34, 53, 36, 14, 70, 26, 02, 90, 45, 13, 31, 61, 83, 73, 47],[36, 10, 63, 96, 60, 49, 41, 05, 37, 42, 14, 58, 84, 93, 96, 17, 09, 43, 05, 43, 06,59],[66, 57, 87, 57, 61, 28, 37, 51, 84, 73, 79, 15, 39, 95, 88, 87, 43, 39, 11, 86, 77,74, 18],[54, 42, 05, 79, 30, 49, 99, 73, 46, 37, 50, 02, 45, 09, 54, 52, 27, 95, 27, 65, 19,45, 26, 45],[71, 39, 17, 78, 76, 29, 52, 90, 18, 99, 78, 19, 35, 62, 71, 19, 23, 65, 93, 85, 49,33, 75, 09, 02],[33, 24, 47, 61, 60, 55, 32, 88, 57, 55, 91, 54, 46, 57, 07, 77, 98, 52, 80, 99, 24,25, 46, 78, 79, 05],[92, 09, 13, 55, 10, 67, 26, 78, 76, 82, 63, 49, 51, 31, 24, 68, 05, 57, 07, 54, 69,21, 67, 43, 17, 63, 12],[24, 59, 06, 08, 98, 74, 66, 26, 61, 60, 13, 03, 09, 09, 24, 30, 71, 08, 88, 70, 72,70, 29, 90, 11, 82, 41, 34],[66, 82, 67, 04, 36, 60, 92, 77, 91, 85, 62, 49, 59, 61, 30, 90, 29, 94, 26, 41, 89,04, 53, 22, 83, 41, 09, 74, 90],[48, 28, 26, 37, 28, 52, 77, 26, 51, 32, 18, 98, 79, 36, 62, 13, 17, 08, 19, 54, 89,29, 73, 68, 42, 14, 08, 16, 70, 37],[37, 60, 69, 70, 72, 71, 09, 59, 13, 60, 38, 13, 57, 36, 09, 30, 43, 89, 30, 39, 15,02, 44, 73, 05, 73, 26, 63, 56, 86, 12],[55, 55, 85, 50, 62, 99, 84, 77, 28, 85, 03, 21, 27, 22, 19, 26, 82, 69, 54, 04, 13,07, 85, 14, 01, 15, 70, 59, 89, 95, 10, 19],[04, 09, 31, 92, 91, 38, 92, 86, 98, 75, 21, 05, 64, 42, 62, 84, 36, 20, 73, 42, 21,23, 22, 51, 51, 79, 25, 45, 85, 53, 03, 43, 22],[75, 63, 02, 49, 14, 12, 89, 14, 60, 78, 92, 16, 44, 82, 38, 30, 72, 11, 46, 52, 90,27, 08, 65, 78, 03, 85, 41, 57, 79, 39, 52, 33, 48],[78, 27, 56, 56, 39, 13, 19, 43, 86, 72, 58, 95, 39, 07, 04, 34, 21, 98, 39, 15, 39,84, 89, 69, 84, 46, 37, 57, 59, 35, 59, 50, 26, 15, 93],[42, 89, 36, 27, 78, 91, 24, 11, 17, 41, 05, 94, 07, 69, 51, 96, 03, 96, 47, 90, 90,45, 91, 20, 50, 56, 10, 32, 36, 49, 04, 53, 85, 92, 25, 65],[52, 09, 61, 30, 61, 97, 66, 21, 96, 92, 98, 90, 06, 34, 96, 60, 32, 69, 68, 33, 75,

35

Page 38: Modelling Examples

84, 18, 31, 71, 50, 84, 63, 03, 03, 19, 11, 28, 42, 75, 45, 45],[61, 31, 61, 68, 96, 34, 49, 39, 05, 71, 76, 59, 62, 67, 06, 47, 96, 99, 34, 21, 32,47, 52, 07, 71, 60, 42, 72, 94, 56, 82, 83, 84, 40, 94, 87, 82, 46],[01, 20, 60, 14, 17, 38, 26, 78, 66, 81, 45, 95, 18, 51, 98, 81, 48, 16, 53, 88, 37,52, 69, 95, 72, 93, 22, 34, 98, 20, 54, 27, 73, 61, 56, 63, 60, 34, 63],[93, 42, 94, 83, 47, 61, 27, 51, 79, 79, 45, 01, 44, 73, 31, 70, 83, 42, 88, 25, 53,51, 30, 15, 65, 94, 80, 44, 61, 84, 12, 77, 02, 62, 02, 65, 94, 42, 14, 94],[32, 73, 09, 67, 68, 29, 74, 98, 10, 19, 85, 48, 38, 31, 85, 67, 53, 93, 93, 77, 47,67, 39, 72, 94, 53, 18, 43, 77, 40, 78, 32, 29, 59, 24, 06, 02, 83, 50, 60, 66],[32, 01, 44, 30, 16, 51, 15, 81, 98, 15, 10, 62, 86, 79, 50, 62, 45, 60, 70, 38, 31,85, 65, 61, 64, 06, 69, 84, 14, 22, 56, 43, 09, 48, 66, 69, 83, 91, 60, 40, 36, 61],[92, 48, 22, 99, 15, 95, 64, 43, 01, 16, 94, 02, 99, 19, 17, 69, 11, 58, 97, 56, 89,31, 77, 45, 67, 96, 12, 73, 08, 20, 36, 47, 81, 44, 50, 64, 68, 85, 40, 81, 85, 52,09],[91, 35, 92, 45, 32, 84, 62, 15, 19, 64, 21, 66, 06, 01, 52, 80, 62, 59, 12, 25, 88,28, 91, 50, 40, 16, 22, 99, 92, 79, 87, 51, 21, 77, 74, 77, 07, 42, 38, 42, 74, 83,02, 05],[46, 19, 77, 66, 24, 18, 05, 32, 02, 84, 31, 99, 92, 58, 96, 72, 91, 36, 62, 99, 55,29, 53, 42, 12, 37, 26, 58, 89, 50, 66, 19, 82, 75, 12, 48, 24, 87, 91, 85, 02, 07,03, 76, 86],[99, 98, 84, 93, 07, 17, 33, 61, 92, 20, 66, 60, 24, 66, 40, 30, 67, 05, 37, 29, 24,96, 03, 27, 70, 62, 13, 04, 45, 47, 59, 88, 43, 20, 66, 15, 46, 92, 30, 04, 71, 66,78, 70, 53, 99],[67, 60, 38, 06, 88, 04, 17, 72, 10, 99, 71, 07, 42, 25, 54, 05, 26, 64, 91, 50, 45,71, 06, 30, 67, 48, 69, 82, 08, 56, 80, 67, 18, 46, 66, 63, 01, 20, 08, 80, 47, 07,91, 16, 03, 79, 87],[18, 54, 78, 49, 80, 48, 77, 40, 68, 23, 60, 88, 58, 80, 33, 57, 11, 69, 55, 53, 64,02, 94, 49, 60, 92, 16, 35, 81, 21, 82, 96, 25, 24, 96, 18, 02, 05, 49, 03, 50, 77,06, 32, 84, 27, 18, 38],[68, 01, 50, 04, 03, 21, 42, 94, 53, 24, 89, 05, 92, 26, 52, 36, 68, 11, 85, 01, 04,42, 02, 45, 15, 06, 50, 04, 53, 73, 25, 74, 81, 88, 98, 21, 67, 84, 79, 97, 99, 20,95, 04, 40, 46, 02, 58, 87],[94, 10, 02, 78, 88, 52, 21, 03, 88, 60, 06, 53, 49, 71, 20, 91, 12, 65, 07, 49, 21,22, 11, 41, 58, 99, 36, 16, 09, 48, 17, 24, 52, 36, 23, 15, 72, 16, 84, 56, 02, 99,43, 76, 81, 71, 29, 39, 49, 17],[64, 39, 59, 84, 86, 16, 17, 66, 03, 09, 43, 06, 64, 18, 63, 29, 68, 06, 23, 07, 87,14, 26, 35, 17, 12, 98, 41, 53, 64, 78, 18, 98, 27, 28, 84, 80, 67, 75, 62, 10, 11,76, 90, 54, 10, 05, 54, 41, 39, 66],[43, 83, 18, 37, 32, 31, 52, 29, 95, 47, 08, 76, 35, 11, 04, 53, 35, 43, 34, 10, 52,57, 12, 36, 20, 39, 40, 55, 78, 44, 07, 31, 38, 26, 08, 15, 56, 88, 86, 01, 52, 62,10, 24, 32, 05, 60, 65, 53, 28, 57, 99],[03, 50, 03, 52, 07, 73, 49, 92, 66, 80, 01, 46, 08, 67, 25, 36, 73, 93, 07, 42, 25,53, 13, 96, 76, 83, 87, 90, 54, 89, 78, 22, 78, 91, 73, 51, 69, 09, 79, 94, 83, 53,09, 40, 69, 62, 10, 79, 49, 47, 03, 81, 30],[71, 54, 73, 33, 51, 76, 59, 54, 79, 37, 56, 45, 84, 17, 62, 21, 98, 69, 41, 95, 65,24, 39, 37, 62, 03, 24, 48, 54, 64, 46, 82, 71, 78, 33, 67, 09, 16, 96, 68, 52, 74,79, 68, 32, 21, 13, 78, 96, 60, 09, 69, 20, 36],[73, 26, 21, 44, 46, 38, 17, 83, 65, 98, 07, 23, 52, 46, 61, 97, 33, 13, 60, 31, 70,15, 36, 77, 31, 58, 56, 93, 75, 68, 21, 36, 69, 53, 90, 75, 25, 82, 39, 50, 65, 94,29, 30, 11, 33, 11, 13, 96, 02, 56, 47, 07, 49, 02],[76, 46, 73, 30, 10, 20, 60, 70, 14, 56, 34, 26, 37, 39, 48, 24, 55, 76, 84, 91, 39,

36

Page 39: Modelling Examples

86, 95, 61, 50, 14, 53, 93, 64, 67, 37, 31, 10, 84, 42, 70, 48, 20, 10, 72, 60, 61,84, 79, 69, 65, 99, 73, 89, 25, 85, 48, 92, 56, 97, 16],[03, 14, 80, 27, 22, 30, 44, 27, 67, 75, 79, 32, 51, 54, 81, 29, 65, 14, 19, 04, 13,82, 04, 91, 43, 40, 12, 52, 29, 99, 07, 76, 60, 25, 01, 07, 61, 71, 37, 92, 40, 47,99, 66, 57, 01, 43, 44, 22, 40, 53, 53, 09, 69, 26, 81, 07],[49, 80, 56, 90, 93, 87, 47, 13, 75, 28, 87, 23, 72, 79, 32, 18, 27, 20, 28, 10, 37,59, 21, 18, 70, 04, 79, 96, 03, 31, 45, 71, 81, 06, 14, 18, 17, 05, 31, 50, 92, 79,23, 47, 09, 39, 47, 91, 43, 54, 69, 47, 42, 95, 62, 46, 32, 85],[37, 18, 62, 85, 87, 28, 64, 05, 77, 51, 47, 26, 30, 65, 05, 70, 65, 75, 59, 80, 42,52, 25, 20, 44, 10, 92, 17, 71, 95, 52, 14, 77, 13, 24, 55, 11, 65, 26, 91, 01, 30,63, 15, 49, 48, 41, 17, 67, 47, 03, 68, 20, 90, 98, 32, 04, 40, 68],[90, 51, 58, 60, 06, 55, 23, 68, 05, 19, 76, 94, 82, 36, 96, 43, 38, 90, 87, 28, 33,83, 05, 17, 70, 83, 96, 93, 06, 04, 78, 47, 80, 06, 23, 84, 75, 23, 87, 72, 99, 14,50, 98, 92, 38, 90, 64, 61, 58, 76, 94, 36, 66, 87, 80, 51, 35, 61, 38],[57, 95, 64, 06, 53, 36, 82, 51, 40, 33, 47, 14, 07, 98, 78, 65, 39, 58, 53, 06, 50,53, 04, 69, 40, 68, 36, 69, 75, 78, 75, 60, 03, 32, 39, 24, 74, 47, 26, 90, 13, 40,44, 71, 90, 76, 51, 24, 36, 50, 25, 45, 70, 80, 61, 80, 61, 43, 90, 64, 11],[18, 29, 86, 56, 68, 42, 79, 10, 42, 44, 30, 12, 96, 18, 23, 18, 52, 59, 02, 99, 67,46, 60, 86, 43, 38, 55, 17, 44, 93, 42, 21, 55, 14, 47, 34, 55, 16, 49, 24, 23, 29,96, 51, 55, 10, 46, 53, 27, 92, 27, 46, 63, 57, 30, 65, 43, 27, 21, 20, 24, 83],[81, 72, 93, 19, 69, 52, 48, 01, 13, 83, 92, 69, 20, 48, 69, 59, 20, 62, 05, 42, 28,89, 90, 99, 32, 72, 84, 17, 08, 87, 36, 03, 60, 31, 36, 36, 81, 26, 97, 36, 48, 54,56, 56, 27, 16, 91, 08, 23, 11, 87, 99, 33, 47, 02, 14, 44, 73, 70, 99, 43, 35, 33],[90, 56, 61, 86, 56, 12, 70, 59, 63, 32, 01, 15, 81, 47, 71, 76, 95, 32, 65, 80, 54,70, 34, 51, 40, 45, 33, 04, 64, 55, 78, 68, 88, 47, 31, 47, 68, 87, 03, 84, 23, 44,89, 72, 35, 08, 31, 76, 63, 26, 90, 85, 96, 67, 65, 91, 19, 14, 17, 86, 04, 71, 32,95],[37, 13, 04, 22, 64, 37, 37, 28, 56, 62, 86, 33, 07, 37, 10, 44, 52, 82, 52, 06, 19,52, 57, 75, 90, 26, 91, 24, 06, 21, 14, 67, 76, 30, 46, 14, 35, 89, 89, 41, 03, 64,56, 97, 87, 63, 22, 34, 03, 79, 17, 45, 11, 53, 25, 56, 96, 61, 23, 18, 63, 31, 37,37, 47],[77, 23, 26, 70, 72, 76, 77, 04, 28, 64, 71, 69, 14, 85, 96, 54, 95, 48, 06, 62, 99,83, 86, 77, 97, 75, 71, 66, 30, 19, 57, 90, 33, 01, 60, 61, 14, 12, 90, 99, 32, 77,56, 41, 18, 14, 87, 49, 10, 14, 90, 64, 18, 50, 21, 74, 14, 16, 88, 05, 45, 73, 82,47, 74, 44],[22, 97, 41, 13, 34, 31, 54, 61, 56, 94, 03, 24, 59, 27, 98, 77, 04, 09, 37, 40, 12,26, 87, 09, 71, 70, 07, 18, 64, 57, 80, 21, 12, 71, 83, 94, 60, 39, 73, 79, 73, 19,97, 32, 64, 29, 41, 07, 48, 84, 85, 67, 12, 74, 95, 20, 24, 52, 41, 67, 56, 61, 29,93, 35, 72, 69],[72, 23, 63, 66, 01, 11, 07, 30, 52, 56, 95, 16, 65, 26, 83, 90, 50, 74, 60, 18, 16,48, 43, 77, 37, 11, 99, 98, 30, 94, 91, 26, 62, 73, 45, 12, 87, 73, 47, 27, 01, 88,66, 99, 21, 41, 95, 80, 02, 53, 23, 32, 61, 48, 32, 43, 43, 83, 14, 66, 95, 91, 19,81, 80, 67, 25, 88],[08, 62, 32, 18, 92, 14, 83, 71, 37, 96, 11, 83, 39, 99, 05, 16, 23, 27, 10, 67, 02,25, 44, 11, 55, 31, 46, 64, 41, 56, 44, 74, 26, 81, 51, 31, 45, 85, 87, 09, 81, 95,22, 28, 76, 69, 46, 48, 64, 87, 67, 76, 27, 89, 31, 11, 74, 16, 62, 03, 60, 94, 42,47, 09, 34, 94, 93, 72],[56, 18, 90, 18, 42, 17, 42, 32, 14, 86, 06, 53, 33, 95, 99, 35, 29, 15, 44, 20, 49,59, 25, 54, 34, 59, 84, 21, 23, 54, 35, 90, 78, 16, 93, 13, 37, 88, 54, 19, 86, 67,68, 55, 66, 84, 65, 42, 98, 37, 87, 56, 33, 28, 58, 38, 28, 38, 66, 27, 52, 21, 81,15, 08, 22, 97, 32, 85, 27],

37

Page 40: Modelling Examples

[91, 53, 40, 28, 13, 34, 91, 25, 01, 63, 50, 37, 22, 49, 71, 58, 32, 28, 30, 18, 68,94, 23, 83, 63, 62, 94, 76, 80, 41, 90, 22, 82, 52, 29, 12, 18, 56, 10, 08, 35, 14,37, 57, 23, 65, 67, 40, 72, 39, 93, 39, 70, 89, 40, 34, 07, 46, 94, 22, 20, 05, 53,64, 56, 30, 05, 56, 61, 88, 27],[23, 95, 11, 12, 37, 69, 68, 24, 66, 10, 87, 70, 43, 50, 75, 07, 62, 41, 83, 58, 95,93, 89, 79, 45, 39, 02, 22, 05, 22, 95, 43, 62, 11, 68, 29, 17, 40, 26, 44, 25, 71,87, 16, 70, 85, 19, 25, 59, 94, 90, 41, 41, 80, 61, 70, 55, 60, 84, 33, 95, 76, 42,63, 15, 09, 03, 40, 38, 12, 03, 32],[09, 84, 56, 80, 61, 55, 85, 97, 16, 94, 82, 94, 98, 57, 84, 30, 84, 48, 93, 90, 71,05, 95, 90, 73, 17, 30, 98, 40, 64, 65, 89, 07, 79, 09, 19, 56, 36, 42, 30, 23, 69,73, 72, 07, 05, 27, 61, 24, 31, 43, 48, 71, 84, 21, 28, 26, 65, 65, 59, 65, 74, 77,20, 10, 81, 61, 84, 95, 08, 52, 23, 70],[47, 81, 28, 09, 98, 51, 67, 64, 35, 51, 59, 36, 92, 82, 77, 65, 80, 24, 72, 53, 22,07, 27, 10, 21, 28, 30, 22, 48, 82, 80, 48, 56, 20, 14, 43, 18, 25, 50, 95, 90, 31,77, 08, 09, 48, 44, 80, 90, 22, 93, 45, 82, 17, 13, 96, 25, 26, 08, 73, 34, 99, 06,49, 24, 06, 83, 51, 40, 14, 15, 10, 25, 01],[54, 25, 10, 81, 30, 64, 24, 74, 75, 80, 36, 75, 82, 60, 22, 69, 72, 91, 45, 67, 03,62, 79, 54, 89, 74, 44, 83, 64, 96, 66, 73, 44, 30, 74, 50, 37, 05, 09, 97, 70, 01,60, 46, 37, 91, 39, 75, 75, 18, 58, 52, 72, 78, 51, 81, 86, 52, 08, 97, 01, 46, 43,66, 98, 62, 81, 18, 70, 93, 73, 08, 32, 46, 34],[96, 80, 82, 07, 59, 71, 92, 53, 19, 20, 88, 66, 03, 26, 26, 10, 24, 27, 50, 82, 94,73, 63, 08, 51, 33, 22, 45, 19, 13, 58, 33, 90, 15, 22, 50, 36, 13, 55, 06, 35, 47,82, 52, 33, 61, 36, 27, 28, 46, 98, 14, 73, 20, 73, 32, 16, 26, 80, 53, 47, 66, 76,38, 94, 45, 02, 01, 22, 52, 47, 96, 64, 58, 52, 39],[88, 46, 23, 39, 74, 63, 81, 64, 20, 90, 33, 33, 76, 55, 58, 26, 10, 46, 42, 26, 74,74, 12, 83, 32, 43, 09, 02, 73, 55, 86, 54, 85, 34, 28, 23, 29, 79, 91, 62, 47, 41,82, 87, 99, 22, 48, 90, 20, 05, 96, 75, 95, 04, 43, 28, 81, 39, 81, 01, 28, 42, 78,25, 39, 77, 90, 57, 58, 98, 17, 36, 73, 22, 63, 74, 51],[29, 39, 74, 94, 95, 78, 64, 24, 38, 86, 63, 87, 93, 06, 70, 92, 22, 16, 80, 64, 29,52, 20, 27, 23, 50, 14, 13, 87, 15, 72, 96, 81, 22, 08, 49, 72, 30, 70, 24, 79, 31,16, 64, 59, 21, 89, 34, 96, 91, 48, 76, 43, 53, 88, 01, 57, 80, 23, 81, 90, 79, 58,01, 80, 87, 17, 99, 86, 90, 72, 63, 32, 69, 14, 28, 88, 69],[37, 17, 71, 95, 56, 93, 71, 35, 43, 45, 04, 98, 92, 94, 84, 96, 11, 30, 31, 27, 31,60, 92, 03, 48, 05, 98, 91, 86, 94, 35, 90, 90, 08, 48, 19, 33, 28, 68, 37, 59, 26,65, 96, 50, 68, 22, 07, 09, 49, 34, 31, 77, 49, 43, 06, 75, 17, 81, 87, 61, 79, 52,26, 27, 72, 29, 50, 07, 98, 86, 01, 17, 10, 46, 64, 24, 18, 56],[51, 30, 25, 94, 88, 85, 79, 91, 40, 33, 63, 84, 49, 67, 98, 92, 15, 26, 75, 19, 82,05, 18, 78, 65, 93, 61, 48, 91, 43, 59, 41, 70, 51, 22, 15, 92, 81, 67, 91, 46, 98,11, 11, 65, 31, 66, 10, 98, 65, 83, 21, 05, 56, 05, 98, 73, 67, 46, 74, 69, 34, 08,30, 05, 52, 07, 98, 32, 95, 30, 94, 65, 50, 24, 63, 28, 81, 99, 57],[19, 23, 61, 36, 09, 89, 71, 98, 65, 17, 30, 29, 89, 26, 79, 74, 94, 11, 44, 48, 97,54, 81, 55, 39, 66, 69, 45, 28, 47, 13, 86, 15, 76, 74, 70, 84, 32, 36, 33, 79, 20,78, 14, 41, 47, 89, 28, 81, 05, 99, 66, 81, 86, 38, 26, 06, 25, 13, 60, 54, 55, 23,53, 27, 05, 89, 25, 23, 11, 13, 54, 59, 54, 56, 34, 16, 24, 53, 44, 06],[13, 40, 57, 72, 21, 15, 60, 08, 04, 19, 11, 98, 34, 45, 09, 97, 86, 71, 03, 15, 56,19, 15, 44, 97, 31, 90, 04, 87, 87, 76, 08, 12, 30, 24, 62, 84, 28, 12, 85, 82, 53,99, 52, 13, 94, 06, 65, 97, 86, 09, 50, 94, 68, 69, 74, 30, 67, 87, 94, 63, 07, 78,27, 80, 36, 69, 41, 06, 92, 32, 78, 37, 82, 30, 05, 18, 87, 99, 72, 19, 99],[44, 20, 55, 77, 69, 91, 27, 31, 28, 81, 80, 27, 02, 07, 97, 23, 95, 98, 12, 25, 75,29, 47, 71, 07, 47, 78, 39, 41, 59, 27, 76, 13, 15, 66, 61, 68, 35, 69, 86, 16, 53,67, 63, 99, 85, 41, 56, 08, 28, 33, 40, 94, 76, 90, 85, 31, 70, 24, 65, 84, 65, 99,

38

Page 41: Modelling Examples

82, 19, 25, 54, 37, 21, 46, 33, 02, 52, 99, 51, 33, 26, 04, 87, 02, 08, 18, 96],[54, 42, 61, 45, 91, 06, 64, 79, 80, 82, 32, 16, 83, 63, 42, 49, 19, 78, 65, 97, 40,42, 14, 61, 49, 34, 04, 18, 25, 98, 59, 30, 82, 72, 26, 88, 54, 36, 21, 75, 03, 88,99, 53, 46, 51, 55, 78, 22, 94, 34, 40, 68, 87, 84, 25, 30, 76, 25, 08, 92, 84, 42,61, 40, 38, 09, 99, 40, 23, 29, 39, 46, 55, 10, 90, 35, 84, 56, 70, 63, 23, 91, 39],[52, 92, 03, 71, 89, 07, 09, 37, 68, 66, 58, 20, 44, 92, 51, 56, 13, 71, 79, 99, 26,37, 02, 06, 16, 67, 36, 52, 58, 16, 79, 73, 56, 60, 59, 27, 44, 77, 94, 82, 20, 50,98, 33, 09, 87, 94, 37, 40, 83, 64, 83, 58, 85, 17, 76, 53, 02, 83, 52, 22, 27, 39,20, 48, 92, 45, 21, 09, 42, 24, 23, 12, 37, 52, 28, 50, 78, 79, 20, 86, 62, 73, 20,59],[54, 96, 80, 15, 91, 90, 99, 70, 10, 09, 58, 90, 93, 50, 81, 99, 54, 38, 36, 10, 30,11, 35, 84, 16, 45, 82, 18, 11, 97, 36, 43, 96, 79, 97, 65, 40, 48, 23, 19, 17, 31,64, 52, 65, 65, 37, 32, 65, 76, 99, 79, 34, 65, 79, 27, 55, 33, 03, 01, 33, 27, 61,28, 66, 08, 04, 70, 49, 46, 48, 83, 01, 45, 19, 96, 13, 81, 14, 21, 31, 79, 93, 85,50, 05],[92, 92, 48, 84, 59, 98, 31, 53, 23, 27, 15, 22, 79, 95, 24, 76, 05, 79, 16, 93, 97,89, 38, 89, 42, 83, 02, 88, 94, 95, 82, 21, 01, 97, 48, 39, 31, 78, 09, 65, 50, 56,97, 61, 01, 07, 65, 27, 21, 23, 14, 15, 80, 97, 44, 78, 49, 35, 33, 45, 81, 74, 34,05, 31, 57, 09, 38, 94, 07, 69, 54, 69, 32, 65, 68, 46, 68, 78, 90, 24, 28, 49, 51,45, 86, 35],[41, 63, 89, 76, 87, 31, 86, 09, 46, 14, 87, 82, 22, 29, 47, 16, 13, 10, 70, 72, 82,95, 48, 64, 58, 43, 13, 75, 42, 69, 21, 12, 67, 13, 64, 85, 58, 23, 98, 09, 37, 76,05, 22, 31, 12, 66, 50, 29, 99, 86, 72, 45, 25, 10, 28, 19, 06, 90, 43, 29, 31, 67,79, 46, 25, 74, 14, 97, 35, 76, 37, 65, 46, 23, 82, 06, 22, 30, 76, 93, 66, 94, 17,96, 13, 20, 72],[63, 40, 78, 08, 52, 09, 90, 41, 70, 28, 36, 14, 46, 44, 85, 96, 24, 52, 58, 15, 87,37, 05, 98, 99, 39, 13, 61, 76, 38, 44, 99, 83, 74, 90, 22, 53, 80, 56, 98, 30, 51,63, 39, 44, 30, 91, 91, 04, 22, 27, 73, 17, 35, 53, 18, 35, 45, 54, 56, 27, 78, 48,13, 69, 36, 44, 38, 71, 25, 30, 56, 15, 22, 73, 43, 32, 69, 59, 25, 93, 83, 45, 11,34, 94, 44, 39, 92],[12, 36, 56, 88, 13, 96, 16, 12, 55, 54, 11, 47, 19, 78, 17, 17, 68, 81, 77, 51, 42,55, 99, 85, 66, 27, 81, 79, 93, 42, 65, 61, 69, 74, 14, 01, 18, 56, 12, 01, 58, 37,91, 22, 42, 66, 83, 25, 19, 04, 96, 41, 25, 45, 18, 69, 96, 88, 36, 93, 10, 12, 98,32, 44, 83, 83, 04, 72, 91, 04, 27, 73, 07, 34, 37, 71, 60, 59, 31, 01, 54, 54, 44,96, 93, 83, 36, 04, 45],[30, 18, 22, 20, 42, 96, 65, 79, 17, 41, 55, 69, 94, 81, 29, 80, 91, 31, 85, 25, 47,26, 43, 49, 02, 99, 34, 67, 99, 76, 16, 14, 15, 93, 08, 32, 99, 44, 61, 77, 67, 50,43, 55, 87, 55, 53, 72, 17, 46, 62, 25, 50, 99, 73, 05, 93, 48, 17, 31, 70, 80, 59,09, 44, 59, 45, 13, 74, 66, 58, 94, 87, 73, 16, 14, 85, 38, 74, 99, 64, 23, 79, 28,71, 42, 20, 37, 82, 31, 23],[51, 96, 39, 65, 46, 71, 56, 13, 29, 68, 53, 86, 45, 33, 51, 49, 12, 91, 21, 21, 76,85, 02, 17, 98, 15, 46, 12, 60, 21, 88, 30, 92, 83, 44, 59, 42, 50, 27, 88, 46, 86,94, 73, 45, 54, 23, 24, 14, 10, 94, 21, 20, 34, 23, 51, 04, 83, 99, 75, 90, 63, 60,16, 22, 33, 83, 70, 11, 32, 10, 50, 29, 30, 83, 46, 11, 05, 31, 17, 86, 42, 49, 01,44, 63, 28, 60, 07, 78, 95, 40],[44, 61, 89, 59, 04, 49, 51, 27, 69, 71, 46, 76, 44, 04, 09, 34, 56, 39, 15, 06, 94,91, 75, 90, 65, 27, 56, 23, 74, 06, 23, 33, 36, 69, 14, 39, 05, 34, 35, 57, 33, 22,76, 46, 56, 10, 61, 65, 98, 09, 16, 69, 04, 62, 65, 18, 99, 76, 49, 18, 72, 66, 73,83, 82, 40, 76, 31, 89, 91, 27, 88, 17, 35, 41, 35, 32, 51, 32, 67, 52, 68, 74, 85,80, 57, 07, 11, 62, 66, 47, 22, 67],[65, 37, 19, 97, 26, 17, 16, 24, 24, 17, 50, 37, 64, 82, 24, 36, 32, 11, 68, 34, 69,

39

Page 42: Modelling Examples

31, 32, 89, 79, 93, 96, 68, 49, 90, 14, 23, 04, 04, 67, 99, 81, 74, 70, 74, 36, 96,68, 09, 64, 39, 88, 35, 54, 89, 96, 58, 66, 27, 88, 97, 32, 14, 06, 35, 78, 20, 71,06, 85, 66, 57, 02, 58, 91, 72, 05, 29, 56, 73, 48, 86, 52, 09, 93, 22, 57, 79, 42,12, 01, 31, 68, 17, 59, 63, 76, 07, 77],[73, 81, 14, 13, 17, 20, 11, 09, 01, 83, 08, 85, 91, 70, 84, 63, 62, 77, 37, 07, 47,01, 59, 95, 39, 69, 39, 21, 99, 09, 87, 02, 97, 16, 92, 36, 74, 71, 90, 66, 33, 73,73, 75, 52, 91, 11, 12, 26, 53, 05, 26, 26, 48, 61, 50, 90, 65, 01, 87, 42, 47, 74,35, 22, 73, 24, 26, 56, 70, 52, 05, 48, 41, 31, 18, 83, 27, 21, 39, 80, 85, 26, 08,44, 02, 71, 07, 63, 22, 05, 52, 19, 08, 20],[17, 25, 21, 11, 72, 93, 33, 49, 64, 23, 53, 82, 03, 13, 91, 65, 85, 02, 40, 05, 42,31, 77, 42, 05, 36, 06, 54, 04, 58, 07, 76, 87, 83, 25, 57, 66, 12, 74, 33, 85, 37,74, 32, 20, 69, 03, 97, 91, 68, 82, 44, 19, 14, 89, 28, 85, 85, 80, 53, 34, 87, 58,98, 88, 78, 48, 65, 98, 40, 11, 57, 10, 67, 70, 81, 60, 79, 74, 72, 97, 59, 79, 47,30, 20, 54, 80, 89, 91, 14, 05, 33, 36, 79, 39],[60, 85, 59, 39, 60, 07, 57, 76, 77, 92, 06, 35, 15, 72, 23, 41, 45, 52, 95, 18, 64,79, 86, 53, 56, 31, 69, 11, 91, 31, 84, 50, 44, 82, 22, 81, 41, 40, 30, 42, 30, 91,48, 94, 74, 76, 64, 58, 74, 25, 96, 57, 14, 19, 03, 99, 28, 83, 15, 75, 99, 01, 89,85, 79, 50, 03, 95, 32, 67, 44, 08, 07, 41, 62, 64, 29, 20, 14, 76, 26, 55, 48, 71,69, 66, 19, 72, 44, 25, 14, 01, 48, 74, 12, 98, 07],[64, 66, 84, 24, 18, 16, 27, 48, 20, 14, 47, 69, 30, 86, 48, 40, 23, 16, 61, 21, 51,50, 26, 47, 35, 33, 91, 28, 78, 64, 43, 68, 04, 79, 51, 08, 19, 60, 52, 95, 06, 68,46, 86, 35, 97, 27, 58, 04, 65, 30, 58, 99, 12, 12, 75, 91, 39, 50, 31, 42, 64, 70,04, 46, 07, 98, 73, 98, 93, 37, 89, 77, 91, 64, 71, 64, 65, 66, 21, 78, 62, 81, 74,42, 20, 83, 70, 73, 95, 78, 45, 92, 27, 34, 53, 71, 15],[30, 11, 85, 31, 34, 71, 13, 48, 05, 14, 44, 03, 19, 67, 23, 73, 19, 57, 06, 90, 94,72, 57, 69, 81, 62, 59, 68, 88, 57, 55, 69, 49, 13, 07, 87, 97, 80, 89, 05, 71, 05,05, 26, 38, 40, 16, 62, 45, 99, 18, 38, 98, 24, 21, 26, 62, 74, 69, 04, 85, 57, 77,35, 58, 67, 91, 79, 79, 57, 86, 28, 66, 34, 72, 51, 76, 78, 36, 95, 63, 90, 08, 78,47, 63, 45, 31, 22, 70, 52, 48, 79, 94, 15, 77, 61, 67, 68],[23, 33, 44, 81, 80, 92, 93, 75, 94, 88, 23, 61, 39, 76, 22, 03, 28, 94, 32, 06, 49,65, 41, 34, 18, 23, 08, 47, 62, 60, 03, 63, 33, 13, 80, 52, 31, 54, 73, 43, 70, 26,16, 69, 57, 87, 83, 31, 03, 93, 70, 81, 47, 95, 77, 44, 29, 68, 39, 51, 56, 59, 63,07, 25, 70, 07, 77, 43, 53, 64, 03, 94, 42, 95, 39, 18, 01, 66, 21, 16, 97, 20, 50,90, 16, 70, 10, 95, 69, 29, 06, 25, 61, 41, 26, 15, 59, 63, 35]]

Fibonacci Numbers with Automatic DynamicProgrammingIn this example we show how one can encode the Fibonacci problem in such a way that you getdynamic programming automatically when using ProB to solve the encoding:

40

Page 43: Modelling Examples

MACHINE Fibonacci_Dynamic_Programming/* an encoding of Fibonacci where we get dynamic programming for free from ProB */DEFINITIONS  DOM == INTEGER; /* INTEGER : For ProB no restriction necessary; for Kodkod yes */CONSTANTS n, fib, solPROPERTIES  fib : 0..n --> DOM &  fib(0) = 1 & fib(1) = 1 &  !x.(x:2..n => fib(x) = fib(x-1) + fib(x-2))

  & n = 200 & sol = fib(n)END

Runtimes on a 1.7 GHz i7 Mac Book Air with ProB 1.4.0-rc2, where we have also used our Kodkodbackend with minSAT for comparison. For Kodkod to be applicable, we had to constrain the domainDOM of possible Fibonacci numbers as indicated below:

 n DOM ProB Kodkod -> Result Fib(n) 10 1..100 0.01 1.93 sec 11 1..200 0.01 5.15 sec

 10 INTEGER 0.01 impossible 20 INTEGER 0.01 impossible -> 10946 40 INTEGER 0.01 impossible -> 165580141100 INTEGER 0.02 impossible -> 573147844013817084101200 INTEGER 0.06 impossible -> 453973694165307953197296969697410619233826

How does it work

Game of LifeThis is a simple model of Conway’s Game of Life. It was written for animation with ProB. Oneinteresting aspect is that the simulation is unbounded, i.e., not restricted to some pre-determinedarea of the grid.

41

Page 44: Modelling Examples

MACHINE gol/* A simple B model of the Game of Life *//* by Jens Bendisposto and Michael Leuschel */ABSTRACT_CONSTANTS ncPROPERTIES  /* neighbour count function: */  nc = %(a,b,alive).(a:INTEGER&b:INTEGER & alive <: INTEGER*INTEGER  | card({(xn,yn)| (xn,yn) : alive & neighbour(xn,yn,a,b)}))VARIABLES aliveDEFINITIONS  neighbour(x,y,a,b) == (max({x-a,a-x}) : {0,1} & max({y-b,b-y}) : {0,1} &(x,y)/=(a,b));INVARIANT alive <: INTEGER * INTEGER & alive /= {}INITIALISATION  alive := {(2,1),(2,2),(2,3)} /* blinker */OPERATIONS step = alive := {(u1,v1) | (u1,v1):alive & nc(u1,v1,alive) : {2,3} } \/  {(u2,v2) | #(a2,b2).((a2,b2):alive & neighbour(u2,v2,a2,b2)) & /*restrict enumeration to neighbours of alive */  (u2,v2)/:alive & nc(u2,v2,alive)=3 }END

We believe this to be quite compact. In the future we hope to be able to remove the need to add thepredicate #(a2,b2).a2,b2):alive & neighbour(u2,v2,a2,b2 by improving ProB’s constraint solver forcardinality constraints on set comprehensions. You may want to compare this to an ASMspecification found here and described on pages 39-40 in Egon Börger and Robert Stärk, AbstractState Machines, A Method for High-Level System Design and Analysis, Springer-Verlag 2003, (ISBN3-540-00702-4).

If you want to visualize the simulation using ProB’s Tk graphical viewer one needs to add adefinition for the animation function. This leads to the following B model (where we have alsoadded an alternate definition of the neighbourhood relationship):

42

Page 45: Modelling Examples

MACHINE gol/* A simple B model of the Game of Life *//* by Jens Bendisposto and Michael Leuschel */ABSTRACT_CONSTANTS ncPROPERTIES  /* neighbour count function: */  nc = %(a,b,alive).(a:INTEGER&b:INTEGER & alive <: INTEGER*INTEGER  | card({(xn,yn)| (xn,yn) : alive & neighbour(xn,yn,a,b)}))VARIABLES aliveDEFINITIONS  /* two alternate definitions of neighbour relationship; both work */  neighbour1(x,y,a,b) == (max({x-a,a-x}) : {0,1} & max({y-b,b-y}) : {0,1} &(x,y)/=(a,b));  neighbour(x,y,a,b) == ((x-a)**2 <= 1 & (y-b)**2 <=1 & (x,y)/=(a,b));  /* some simple patterns : */  blinker == {(2,1),(2,2),(2,3)} ; glider == {(1,2),(2,3),(3,1),(3,2),(3,3)} ;  SET_PREF_CLPFD == TRUE;  /* describing the animation function for the graphical visualization : */  wmin == min(dom(alive)\/{1}); wmax == max(dom(alive)\/{1});  hmin == min(ran(alive)\/{1}); hmax == max(ran(alive)\/{1});  ANIMATION_FUNCTION_DEFAULT == ( (wmin..wmax)*(hmin..hmax)*{0} );  ANIMATION_FUNCTION == ( alive * {1} );  ANIMATION_IMG0 == "images/sm_empty_box.gif";  ANIMATION_IMG1 == "images/sm_gray_box.gif"INVARIANT alive <: INTEGER * INTEGER & alive /= {}INITIALISATION  alive := gliderOPERATIONS step = alive := {(u1,v1) | (u1,v1):alive & nc(u1,v1,alive) : {2,3} } \/  {(u2,v2) | #(a2,b2).((a2,b2):alive & neighbour(u2,v2,a2,b2)) & /*restrict enumeration to neighbours of alive */  (u2,v2)/:alive & nc(u2,v2,alive)=3 }END

The following is a screenshot of ProB Tcl/Tk animating the above model:

43

Page 46: Modelling Examples

Gilbreath Card TrickMy belief is that B is a very expressive language, which can be very convenient for modelling manyproblems. Hence, when in the Dagstuhl library I stumbled upon a nice short article by Tony Hoareand Natarajan Shankar in memory of Amir Pnueli, I decided to model the problem and time howlong it would take me to solve the problem using ProB. The article unravels a card trick byGilbreath. The card trick has several phases:

• first you arrange 16 cards into a sequence of quartets with one card from each suit (Spade, Club,Heart, Diamond) in the same order. The example in the article is as follows: ⟨5♠⟩,⟨3♡⟩,⟨Q♣⟩,⟨8♢⟩,⟨K♠⟩,⟨2♡⟩,⟨7♣⟩,⟨4♢⟩, ⟨8♠⟩,⟨J♡⟩,⟨9♣⟩,⟨A♢⟩

• you split the cards into two sequences. The example in the article is: ⟨5♠⟩,⟨3♡⟩,⟨Q♣⟩,⟨8♢⟩,⟨K♠⟩and ⟨2♡⟩,⟨7♣⟩,⟨4♢⟩,⟨8♠⟩,⟨J♡⟩,⟨9♣⟩,⟨A♢⟩ .

• you reverse one of the sequences

• you perform a (not necessarily perfect) riffle shuffle of the two sequences

• the resulting final sequence is guaranteed to consist of a sequence of four quartets with onecard from each suite.

I attempted to model this problem in B and wanted to use model checking to validate the property

44

Page 47: Modelling Examples

on the final sequence. As I wanted to measure the time spent modeling I used a stopwatch. It took13 minutes (starting from an empty B specification) to produce a first model that could be modelchecked by ProB. Full validation was finished after 19 minutes from the start. The model checkingitself generated 150,183 states and 179,158 transitions and took 2 minutes and 17 seconds on a MacBook Air (1.8 GHz i7). (Further below on this page I also describe ways to reduce the modelchecking time.) I am very interested in seeing how much combined modelling and verification timeis required to solve this task in other formalisms and with other model checking tools (e.g., Promelawith Spin, CSP with FDR, TLA+ with TLC).

Here is the specification

45

Page 48: Modelling Examples

MACHINE CardTrick/* Translation by Michael Leuschel of Example in "Unraveling a Card Trick" by Tony Hoare and Natarajan Shankar  in LNCS 6200, pp. 195-201, 2010.  DOI: 10.1007/978-3-642-13754-9_10  https://link.springer.com/chapter/10.1007%2F978-3-642-13754-9_10  */SETS SUIT={spade,club,heart,diamond}DEFINITIONS  all == [spade,club,heart,diamond]; /* an arbitrary permutation of the suits */

  /* check that in dst we can partition the deck into quartets where every suit occursonce: */  ok(dst) == #(a,b,c,d).(dst = a^b^c^d & size(a)=4 & size(b)=4 & size(c)=4 & size(d)=4&  a : perm(SUIT) & b:perm(SUIT) & c:perm(SUIT) & d:perm(SUIT))CONSTANTS initialPROPERTIES initial = all^all^all^all /* we fix the sequence; i.e., we perform symmetry reductionby hand; it should be possible to achieve this by ProB's symmetry reduction itselfusing a deferred set */VARIABLES x,y,dest,reversedINVARIANT x:seq(SUIT) & y:seq(SUIT) & dest:seq(SUIT) & reversed:BOOL & ((x=<> & y=<>) => ok(dest)) /* the property we are interested in: after the riffleshuffle the sequence consists of four quartets, each containing every suit */INITIALISATION  x,y : (x^y = initial) /* split the initial sequence into two: x and y */ || dest := <> || reversed := FALSEOPERATIONS

  /* reverse one of the two decks */  Reverse = PRE reversed=FALSE THEN CHOICE x := rev(x) OR y := rev(y) END || reversed:= TRUE END;

  /* perform the riffle shuffle: transfer one card from either x or y to dest */  Shuffle1 = PRE x/=<> & reversed=TRUE THEN dest := dest<-last(x) || x:= front(x) END;  Shuffle2 = PRE y/=<> & reversed=TRUE THEN dest := dest<-last(y) || y:= front(y) ENDEND

Some observations:

• in the above model I perform symmetry reduction by hand, by forcing a particular order of thecards initially

• a version of the model which does not do this can be found below; it requires symmetryreduction to be enabled for efficient model checking

• I have tried to translate this example to TLA+ and use TLC (using our new B-TLC translator), but

46

Page 49: Modelling Examples

TLC cannot deal with the initialisation x,y : (x^y = initial). Later Domink Hansen producedan adapted (more low-level) version of my B machine which can be run by TLC; see below.

• A (longer) Why3 encoding can be found here.

• Arguably model checking gives less insight into why the trick works than proof. However, byadding a graphical visualization, a different kind of insight can be gained. This is shown below.

Adding graphical visualization

To add a simple graphical visualization one needs to generate four pictures (in GIF format). I tookpictures from Wikimedia Commons. In the DEFINITIONS section of the B machine above, you thensimply have to add the following:

  ANIMATION_FUNCTION_DEFAULT == {(1,0,"x"),(2,0,"y"),(3,0,"dest")};  ANIMATION_FUNCTION == ( {r,c,i| r=1 & c|->i:x} \/ {r,c,i| r=2 & c|->i:y} \/{r,c,i| r=3 & c|->i:dest} );  ANIMATION_IMG1 == "images/French_suits_Spade.gif";  ANIMATION_IMG2 == "images/French_suits_Club.gif";  ANIMATION_IMG3 == "images/French_suits_Heart.gif";  ANIMATION_IMG4 == "images/French_suits_Diamond.gif";

Details about the use of this feature can be found in the Graphical_Visualization page of themanual. With the above, ProB will display the variables x, y and dist in a graphical way, and byanimation one can gain insights into why it is impossible not to generate four quartets.

47

Page 50: Modelling Examples

A version requiring symmetry reduction

48

Page 51: Modelling Examples

MACHINE CardTrickSym /* a version to be used with ProB's symmetry reduction *//* see comments in machine CardTrick for more details about the modeling effort *//* Translation by Michael Leuschel of Example in "Unraveling a Card Trick" by TonyHoare and Natarajan Shankar in LNCS 6200, pp. 195-201, 2010.  DOI: 10.1007/978-3-642-13754-9_10  https://link.springer.com/chapter/10.1007%2F978-3-642-13754-9_10  *//* Model checking with hash symmetry taking 161.9 seconds to traverse  150,183 states and 179,181 transitions (on a MacBook Air 1.8Ghz i7) */SETS SUIT /* ={spade,club,heart,diamond} */DEFINITIONS  /* check that in dst we can partition the deck into quartets where every suit occursonce */  ok(dst) == #(a,b,c,d).(dst = a^b^c^d & size(a)=4 & size(b)=4 & size(c)=4 & size(d)=4&  a : perm(SUIT) & b:perm(SUIT) & c:perm(SUIT) & d:perm(SUIT))CONSTANTS  allPROPERTIES  card(SUIT)=4 &  all : perm(SUIT) /* a sequence of all suits in any order */VARIABLES x,y,dest,reversedINVARIANT x:seq(SUIT) & y:seq(SUIT) & dest:seq(SUIT) & reversed:BOOL & ((x=<> & y=<>) => ok(dest))INITIALISATION x,y : (x^y = all^all^all^all ) || dest := <> || reversed := FALSEOPERATIONS  Reverse = PRE reversed=FALSE THEN CHOICE x := rev(x) OR y := rev(y) END || reversed:= TRUE END;  Shuffle1 = PRE x/=<> & reversed=TRUE THEN dest := dest<-last(x) || x:= front(x) END;  Shuffle2 = PRE y/=<> & reversed=TRUE THEN dest := dest<-last(y) || y:= front(y) ENDEND

A more low-level version for use with TLC

We later adapted the above model (without symmetry) to make it somewhat more low-level and toenable the translation to TLA+ for use with TLC (this is a new feature inside ProB Tcl/Tk). Themachine is shown below. The model checking time with ProB is now reduced to 75 seconds. Withthe command "Verify → External Tools → Model Check with TLC…" you can use TLC as a backend.The model checking time is then approximately 15 seconds (including the translation time from Bto TLA+).

49

Page 52: Modelling Examples

MACHINE CardTrick_TLC/* A version of the machine (adapted by Domink Hansen) which is a bit more low-level;  this improves model checking performance and now allows translation to TLC *//* Translation by Michael Leuschel of Example in "Unraveling a Card Trick" by TonyHoare and Natarajan Shankar in LNCS 6200, pp. 195-201, 2010.  DOI: 10.1007/978-3-642-13754-9_10  https://link.springer.com/chapter/10.1007%2F978-3-642-13754-9_10  */SETS SUIT={spade,club,heart,diamond}DEFINITIONS  all == [spade,club,heart,diamond];

  /* check that in dst we can partition the deck into quartets where every suit occursonce */ subseq(s,m,n) == (s/|\n)\|/m-1;

 ok(dst) == subseq(dst,1,4) : perm(SUIT)  & subseq(dst,5,8) : perm(SUIT)  & subseq(dst,9,12) : perm(SUIT)  & subseq(dst,13,16) : perm(SUIT);/*#(a,b,c,d).(dst = a^b^c^d & size(a)=4 & size(b)=4 & size(c)=4 & size(d)=4 &  a : perm(SUIT) & b:perm(SUIT) & c:perm(SUIT) & d:perm(SUIT));*/

 initial == all^all^all^all/* we fix the sequence; i.e., we perform symmetry reduction by hand; it should bepossible to achieve this by ProB's symmetry reduction itself using a deferred set */VARIABLES x,y,dest,reversedINVARIANT x:seq(SUIT) & y:seq(SUIT) & dest:seq(SUIT) & reversed:BOOL & ((x=<> & y=<>) => ok(dest))INITIALISATION x,y :(#n.(n : 0..size(initial) & x = initial /|\ n & y = initial \|/ n& x^y = initial)) || dest := <> || reversed := FALSEOPERATIONS  Reverse = PRE reversed=FALSE THEN CHOICE x := rev(x) OR y := rev(y) END || reversed:= TRUE END;  Shuffle1 = PRE x/=<> & reversed=TRUE THEN dest := dest<-last(x) || x:= front(x) END;  Shuffle2 = PRE y/=<> & reversed=TRUE THEN dest := dest<-last(y) || y:= front(y) ENDEND

The TLA+ translation generated by B-TLC is as follows:

50

Page 53: Modelling Examples

---- MODULE CardTrick_TLC ----EXTENDS Naturals, Sequences, SequencesExtendedCONSTANTS spade, club, heart, diamondVARIABLES x, y, dest, reversedSUIT == {spade, club, heart, diamond}all == <<spade, club, heart, diamond>>subseq(s, m, n) == DropFirstElements(TakeFirstElements(s, n), m - 1)ok(dst) == subseq(dst, 1, 4) \in Perm(SUIT) /\ subseq(dst, 5, 8) \in Perm(SUIT) /\subseq(dst, 9, 12) \in Perm(SUIT) /\ subseq(dst, 13, 16) \in Perm(SUIT)initial == all \o all \o all \o allInvariant == x \in Seq(SUIT) /\ y \in Seq(SUIT) /\ dest \in Seq(SUIT) /\ reversed \inBOOLEAN /\ (x = <<>> /\ y = <<>> => ok(dest))Init == \E n \in (0 .. Len(initial)) : n \in (0 .. Len(initial)) /\ x =TakeFirstElements(initial, n) /\ y = DropFirstElements(initial, n) /\ x \o y = initial  /\ dest = <<>>  /\ reversed = FALSEReverse == reversed = FALSE  /\ ((x' = Rev(x) /\ UNCHANGED <<y>>) \/ (y' = Rev(y) /\ UNCHANGED <<x>>))  /\ reversed' = TRUE /\ UNCHANGED <<dest>>

Shuffle1 == (x # <<>> /\ reversed = TRUE)  /\ dest' = Append(dest, Last(x))  /\ x' = Front(x) /\ UNCHANGED <<y, reversed>>

Shuffle2 == (y # <<>> /\ reversed = TRUE)  /\ dest' = Append(dest, Last(y))  /\ y' = Front(y) /\ UNCHANGED <<x, reversed>>

Next == \/ Reverse  \/ Shuffle1  \/ Shuffle2====

Mutual Exclusion (Fairness)Consider an Event-B model formalizing an algorithm for mutual exclusion with semaphores for twoconcurrent processes P_1 and P_2. Each process has been simplified to perform three types ofevents: request (for entering in the critical section), enter (entering the critical section), and release(exiting the critical section). (For more information on the algorithm and the design of the modelsee [2]).

Each of the actions of a process are represented by a respective event:

51

Page 54: Modelling Examples

Each process P_i has three possible states that are denoted by the constants noncrit_{i} (the state inwhich P_i performs noncritical actions), wait_{i} (the state in which P_{i} waits to enter the criticalsection), and crit_{i} (representing the state in which P_{i} is in the critical section). Bothprocesses share the binary semaphore y where y=1 indicates that the semaphore is free and y=0that the semaphore is currently processed by one of the processes.

There are several requirements that the mutual exclusion algorithm should satisfy. The mostimportant one is the mutual exclusion property that says always at most one process is in its criticalsection. This can be simply expressed, for example, as an invariant of the respective Event-B model:not(p1 = crit1 & p2 = crit2). However, there are other properties that can be easily expressed bymeans of LTL formulas and automatically checked on the model. For example, the requirementeach process will enter infinitely often its critical section can be specified by the LTL formula GF \{p1= crit1} & GF \{p2 = crit2} or the starvation freedom property that states each waiting processwill eventually enter its critical section:

G ({p1 = wait1} ⇒ F {p1 = crit1}) & G ({p2 = wait2} ⇒ F {p2=crit2})

Running the LTL model checker of ProB will provide for the last two properties above acounterexample since the model permits that a process may perform infinitely often consecutivelythe events request, enter and release, and in this way to ignore the other process infinitely. Anexample trace that describes this behavior could be \langleReq2,Req1,Enter1,Rel1,Req1,Enter1,\ldots\rangle.

On the other hand, such behaviors can be considered as unrealistic computations for the eventualimplementation of the algorithm. Therefore fairness constraints can be set in order to discard suchbehaviors. For example, checking the property process P_1 will enter its critical section infinitelyoften (as LTL property: GF \{p1 = crit1}) can be checked by restricting that the event Req1 will notbe continuously ignored and that the event Enter1 will not be ignored infinitely often. Bothconditions for the property can be given by means of an LTL[e] formula on the left side of thefollowing implication:

(FG e(Req1) ⇒ GF [Req1]) & (GF e(Enter1) ⇒ GF [Enter1]) ⇒ GF {p1 = crit1}

For checking the formula the LTL model checker generates 13312 atoms<a

52

Page 55: Modelling Examples

id="_footnoteref_3">�</a><sup>[<a anchor="_footnotedef_3">3</a>]</sup></sup> formula times thenumber of states of the model.] and 7515 transitions and needs overall 509 ms to prove theproperty (the model has 8 states and 15 transitions in total). On the other hand, using the extensionof the LTL model checker for checking fairness (by entering the formula <code>WF(Req1) &amp;SF(Enter1) &#8658; GF \{p1=crit1}</code>), the model checker generates 32 atoms and 39 transitions(the atoms and transitions generated just for <code>GF \{p1 = crit1}</code>) and an overall time of50 ms.

For checking the requirement each process will enter infinitely often its critical section the LTLformula ` GF \{p1 = crit1} & GF \{p2 = crit2}` should be checked with the following fairnessconstraints:

(WF(Req1) & WF(Req2)) & (SF(Enter1) & SF(Enter2))

Encoding these fairness conditions as an LTL[e] formula will blow up exponentially the number ofatoms and the transitions in regard to the number of temporal operators (in this case G (globally)and F(finally)) and thus make practically impossible to check the above property in a reasonabletime.

N-Bishops PuzzleThis puzzle is a variation of the N-Queens puzzle: we try to place as many bishops as possible on a nby n chess board. In contrast to the N-Queens puzzle, one can place more than one bishop per row.As such, we can now longer represent the positions of the bishops as an total function 1..n >→ 1..n.There are two encodings we show below. The first represents the bishops as a subset of theCartesian product (1..n)*(1..n), i.e., a set of positions (aka a binary relation on 1..n).

MACHINE NBishopsSetsCONSTANTS n, nbishops, hasbishopPROPERTIES n=8 & hasbishop <: (1..n)*(1..n) & !(i,j).(i:1..n & j:1..n  =>  ( (i,j): hasbishop  =>  (!k.(k:(i+1)..n =>  (k,j+k-i) /: hasbishop &  (k,j-k+i) /: hasbishop  ))  )) & nbishops = card(hasbishop) & nbishops >13END

One can try and find the maximum number of bishops by gradually increasing the lower limit fornbishops in the last line of the model before the final END. The maximum number of bishops thatcan be placed is 2*n - 2; see here.

53

Page 56: Modelling Examples

ProB 1.5.1 can solve this puzzle with nbishops >13 in about half a second.

One can use graphical visualisation features to display the solution, by declaring the ANIMATIONFUNCTION inside the DEFINITIONS section as follows:

DEFINITIONS  BWOFFSET(x,y) == (x+y) mod 2;  ANIMATION_FUNCTION_DEFAULT == ( {r,c,i|r:1..n & c:1..n & i=(r+c) mod 2 } );  ANIMATION_FUNCTION == {r,c,i|(r,c):hasbishop & i= 2+BWOFFSET(r,c)} ;  ANIMATION_IMG0 == "ChessPieces/Chess_emptyl45.gif";  ANIMATION_IMG1 == "ChessPieces/Chess_emptyd45.gif";  ANIMATION_IMG2 == "ChessPieces/Chess_bll45.gif";  ANIMATION_IMG3 == "ChessPieces/Chess_bld45.gif";  SET_PREF_TK_CUSTOM_STATE_VIEW_PADDING == 1;END

This will lead to ProB to show the solution graphically, as follows:

For the chess pieces we have used the images available at this site. These images are availableunder the Creative Commons Attribution-Share Alike 3.0 Unported license. The same applies to thescreenshots shown here.

N-QueensThe N-Queens is a famous constraint solving benchmark puzzle. It is a generalisation of the originaleight queens puzzle, where the goal is to place eight queens on a 8*8 chessboard so that no twoqueens attach each other.

54

Page 57: Modelling Examples

Here is one way to encode the N-Queens puzzle in B.

MACHINE NQueensCONSTANTS n,queensPROPERTIES n = 40 & queens : 1..n >-> 1..n /* for each column the row in which the queen is in */ & !(q1,q2).(q1:1..n & q2:2..n & q2>q1  => queens(q1)+q2-q1 /= queens(q2) & queens(q1)-q2+q1 /= queens(q2))END

ProB 1.3.7 can solve this puzzle in about 0.150 seconds (for n=40, on a 1.7 GHz Mac Book Air).

One can use graphical visualisation features to display the solution, by declaring the ANIMATIONFUNCTION as follows:

MACHINE NQueens40CONSTANTS n,queensPROPERTIES n = 40 & queens : 1..n >-> 1..n /* for each column the row in which the queen is in */ & !(q1,q2).(q1:1..n & q2:2..n & q2>q1  => queens(q1)+q2-q1 /= queens(q2) & queens(q1)-q2+q1 /= queens(q2))DEFINITIONS  ANIMATION_FUNCTION_DEFAULT == ( {r,c,i|r:1..n & c:1..n & i=(r+c) mod 2 } );  ANIMATION_FUNCTION == ( {r,c,i|c:1..n & r=queens(c) & i=2+((r+c) mod 2) } );  ANIMATION_IMG0 == "images/sm_empty_box.gif";  ANIMATION_IMG1 == "images/sm_gray_box.gif";  ANIMATION_IMG2 == "images/sm_queen_white.gif";  ANIMATION_IMG3 == "images/sm_queen_black.gif";  SET_PREF_CLPFD == TRUE;END

This will lead to ProB to show the solution graphically, as follows (the screenshot is unfortunatelycropped and does not show all rows):

55

Page 58: Modelling Examples

Instead of using ProB’s standard constraint-solving backend, you can also use our Kodkod backendto solve this puzzle. To do this, either "Enable Kodkod for Properties" in the ProB Tcl/Tk"Preferences" menu or add the following to the DEFINITIONS in the machine file above:

  SET_PREF_KODKOD == TRUE

However, using the MiniSat backend solving the N-queens puzzle for n=40 takes 57.1 seconds (onthe same hardware as above).

Nine PrisonersAn article in Quanta magazine mentions the following puzzle by Dudeney and popularized byMartin Gardner:

"So in the spirit of Kirkman, we will leave the gentle reader with another brainteaser, a slightvariation on the schoolgirl puzzle devised in 1917 by the British puzzle aficionado Henry ErnestDudeney and later popularized by Martin Gardner: Nine prisoners are taken outdoors for exercisein rows of three, with each adjacent pair of prisoners linked by handcuffs, on each of the sixweekdays (back in Dudeney’s less enlightened times, Saturday was still a weekday). Can theprisoners be arranged over the course of the six days so that each pair of prisoners shareshandcuffs exactly once?"

56

Page 59: Modelling Examples

An encoding of this puzzle in B is relatively straightforward, thanks to the use of sets, sequencesand permutations and universal quantification. To improve the performance, symmetry reductionswere added by hand in the model below. The constant arrange contains the solution to our puzzle:the arrangement of the prisoners for every working day from 1 to Days.

MACHINE NinePrisonersDEFINITIONS Prisoners == 1..9; Days == 6; Cuffs == {1,2, 4,5, 7,8 }; share(day,cuff) == {arrange(day)(cuff),arrange(day)(cuff+1)}CONSTANTS arrangePROPERTIES /* typing + permutation requirement */  arrange : (1..Days) --> perm(Prisoners) &

 /* symmetry breaking */  arrange(1) = %i.(i:Prisoners|i) &  !d.(d:1..Days =>  !c.(c:Prisoners & c mod 3 = 1 => arrange(d)(c) < arrange(d)(c+2))) &  !d.(d:1..Days =>  !c.(c:{1,3} => arrange(d)(c) < arrange(d)(c+3))) &

/* the constraint proper */  !(c,d).(c:Cuffs & d:2..Days =>  !(c1,d1).(d1<d & d1>0 & c1:Cuffs =>  share(d,c) /= share(d1,c1))  )END

The solving time using ProB on a MacBook Air is as follows: for Days == 4: 0.08 seconds, forDays==5: 0.20 seconds, for Days == 6: 80 seconds (i.e., the complete puzzle).

Simple Graphical Visualization

To generate a simple graphical visualization of the solutions found by ProB, one needs to add adefinition for the animation function, e.g., as follows:

 ANIMATION_FUNCTION ==  {r,c,i| r:1..Days & c:1..3 & i = arrange(r)(c) } \/  {r,c,i| r:1..Days & c:5..7 & i = arrange(r)(c-1) } \/  {r,c,i| r:1..Days & c:9..11 & i = arrange(r)(c-2) }; ANIMATION_FUNCTION_DEFAULT == {r,c,i| r:1..Days & c:1..11 & i = " " }

This gives rise to the following visualisation:

57

Page 60: Modelling Examples

As can be seen in the screenshot, we have also added an operation to inspect the solution computedby ProB:

OPERATIONS  r <-- Neighbours(i) = PRE i:Prisoners THEN /* compute for every day the neighboursof i */  r := %d.(d:1..Days |  UNION(x,c).( x:Prisoners & c:Cuffs & i: share(d,c)| share(d,c) \ {i})  ) END

Adding graphical visualization

To add a better graphical visualization one needs to generate 10 pictures (in GIF format). I generatethese using OmniGraffle. In the DEFINITIONS section of the B machine above, you then simply haveto add the following (and remove the definition of ANIMATION_FUNCTION_DEFAULT from above):

58

Page 61: Modelling Examples

 ANIMATION_FUNCTION_DEFAULT == {r,c,i| r:1..Days & c:1..11 & i = 0 }; ANIMATION_IMG0 == "images/Prisoner_0.gif"; ANIMATION_IMG1 == "images/Prisoner_1.gif"; ANIMATION_IMG2 == "images/Prisoner_2.gif"; ANIMATION_IMG3 == "images/Prisoner_3.gif"; ANIMATION_IMG4 == "images/Prisoner_4.gif"; ANIMATION_IMG5 == "images/Prisoner_5.gif"; ANIMATION_IMG6 == "images/Prisoner_6.gif"; ANIMATION_IMG7 == "images/Prisoner_7.gif"; ANIMATION_IMG8 == "images/Prisoner_8.gif"; ANIMATION_IMG9 == "images/Prisoner_9.gif"

This gives rise to the following graphical visualization of the first solution found by ProB:

Details about the use of this visualization feature can be found in the Graphical_Visualization pageof the manual.

Peaceable Armies of QueensI found this challenging constraint programming problem in the following paper:

• B. M. Smith, K. E. Petrie, and I. P. Gent. Models and symmetry breaking for peaceable armies ofqueens. In Integration of AI and OR Techniques in Constraint Programming for CombinatorialOptimization Problems, pages 271–286. Springer Berlin Heidelberg, 2004.

59

Page 62: Modelling Examples

A variation of the problem can be found on page 329 of the Handbook on Constraint Programming.

The challenge is to place two equal-sized armies of white and black queens onto a chessboard. Wecan distinguish between two problems:

• checking whether two armies of n queens can be placed on a dim*dim chessboard,

• for a given board of size dim*dim find the maximal size n of armies that can be placed onto theboard, i.e., solving an optimisation problem.

Checking

Here is a B model for the checking problem. The problem is quite straightforward to encode in B.Many lines below (in the DEFINITIONS) just define the animation function to graphically representsolutions.

60

Page 63: Modelling Examples

MACHINE JustQueensDEFINITIONS  SET_PREF_TIME_OUT == 1000000;  SET_PREF_MAX_INITIALISATIONS == 1;  ANIMATION_IMG0 == "images/sm_empty_box.gif";  ANIMATION_IMG1 == "images/sm_gray_box.gif";  ANIMATION_IMG2 == "images/sm_queen_white.gif";  ANIMATION_IMG3 == "images/sm_queen_black.gif";  ANIMATION_IMG4 == "images/sm_knight_white.gif";  ANIMATION_IMG5 == "images/sm_knight_black.gif";  ANIMATION_IMG6 == "images/sm_white_queen_white.gif";  ANIMATION_IMG7 == "images/sm_white_queen_black.gif";  BWOFFSET(xx,yy) == (xx+yy) mod 2;  ANIMATION_FUNCTION_DEFAULT == ( {r,c,i|r:1..dim & c:1..dim & i=(r+c) mod 2 } );  ANIMATION_FUNCTION == ( UNION(k).(k:1..n|{(blackc(k),blackr(k),2+BWOFFSET(blackc(k),blackr(k)))}) \/  UNION(k).(k:1..n|{(whitec(k),whiter(k),6+BWOFFSET(whitec(k),whiter(k)))}) );  ORDERED(c,r) == (!i.(i:1..(n-1) => c(i) <= c(i+1)) &  !i.(i:1..(n-1) => (c(i)=c(i+1) => r(i) < r(i+1))))CONSTANTS n, dim, blackc, blackr, whitec, whiterPROPERTIES n = 8 & dim = 8 & blackc : 1..n --> 1..dim & whitec : 1..n --> 1..dim & blackr : 1..n --> 1..dim & whiter : 1..n --> 1..dim & ORDERED(blackc,blackr) & /* ensures proper ordering + that we do not place twoqueens on same square */ ORDERED(whitec,whiter) &

 !(i,j).(i:1..n & j:1..n => blackc(i) /= whitec(j)) & !(i,j).(i:1..n & j:1..n => blackr(i) /= whiter(j)) & !(i,j).(i:1..n & j:1..n => blackr(i) /= whiter(j) + (blackc(i)-whitec(j))) & !(i,j).(i:1..n & j:1..n => blackr(i) /= whiter(j) - (blackc(i)-whitec(j))) &

  whitec(1) < blackc(1) /* symmetry breaking */END

Here are some running times on my MacBook Air 1.7 GHz i7, also comparing to using Kodkod asProB’s backend and using an Alloy model (see below).

61

Page 64: Modelling Examples

 dim=7, n=7 : solved in 0.3 secs dim=7, n=8 : unsat in 20 secs dim=8, n=6 : solved in 0.02 secs (1.12 secs with Kodkod) dim=8, n=7 : solved in 0.06 secs (2.66 secs with Kodkod) dim=8, n=8 : solved in 0.53 secs (8.44 secs with Kodkod; 7.03 secs second run; +/-8.5 with Alloy & miniSat; 9.3 seconds if we avoid overflows) dim=8, n=9 : solved in 12.96 secs (128.07 secs with Kodkod ; +/- 84 secs with Alloy& miniSat) dim=8, n=10 : unsat in 728 secs (Alloy & miniSat still running after over fourhours)

The first solution found for dim=8 and n=9 is as follows:

The Alloy model for comparison

Here is the Alloy model we have used. Initially, the model gave us wrong solutions as we were using+ instead of sum; this was correct for previous versions of Alloy but not for Alloy 4.2 which we wereusing.

62

Page 65: Modelling Examples

abstract sig Queens {  row : one Int,  col: one Int,} { row >= 0 and row < 8 and col >= 0 and col < 8}sig BQueens extends Queens {} {}sig WQueens extends Queens {} {}

pred nothreat(q1,q2 : Queens) {q1.row != q2.rowand q1.col != q2.coland plus[ int[q1.row] , int[q1.col]] != plus[ int[q2.col] , int[q2.row]]  and plus [int[q1.row] , int[q2.col]] != plus[ int[q1.col] , int[q2.row]]}

pred nothreats { all q1:BQueens, q2:WQueens |  nothreat[q1, q2]}

pred alldiffB { all q1:BQueens, q2:BQueens |  q1=q2 or q1.row != q2.row or q1.col != q2.col}pred alldiffW { all q1:WQueens, q2:WQueens |  q1=q2 or q1.row != q2.row or q1.col != q2.col}

pred equalnum {  #(WQueens) = #(BQueens)}

pred valid {  nothreats and equalnum and alldiffB and alldiffW}

fact {  #Queens = 16}

run valid for 16 Queens, 7 int

Optimization

One can obviously use the above models to try and manually find a maximal value of n for a givenboard size dim. Below, we have encoded this process as B constraints, by setting up the problemtwice: once for the army size n and a second time for army size n+1. The second encoding iswrapped into a negated existential quantification. (This model can no longer be translated intoKodkod because of this.)

63

Page 66: Modelling Examples

ProB solves this optimisation problem in about 780 seconds for a board size of 8. This is verycompetitive with the timings reported in the above mentioned constraint solving paper using newsymmetry breaking techniques and much more low-level encoding on state of the art constraintsolving libraries such as ILOG.

MACHINE JustQueens_FindOptimal_CBCDEFINITIONS  SET_PREF_TIME_OUT == 1000000;  SET_PREF_MAX_INITIALISATIONS == 1;  ANIMATION_IMG0 == "images/sm_empty_box.gif";  ANIMATION_IMG1 == "images/sm_gray_box.gif";  ANIMATION_IMG2 == "images/sm_queen_white.gif";  ANIMATION_IMG3 == "images/sm_queen_black.gif";  ANIMATION_IMG4 == "images/sm_knight_white.gif";  ANIMATION_IMG5 == "images/sm_knight_black.gif";  ANIMATION_IMG6 == "images/sm_white_queen_white.gif";  ANIMATION_IMG7 == "images/sm_white_queen_black.gif";  BWOFFSET(xx,yy) == (xx+yy) mod 2;  ANIMATION_FUNCTION_DEFAULT == ( {r,c,i|r:1..dim & c:1..dim & i=(r+c) mod 2 } );  ANIMATION_FUNCTION == ( UNION(k).(k:1..n|{(blackc(k),blackr(k),2+BWOFFSET(blackc(k),blackr(k)))}) \/  UNION(k).(k:1..n|{(whitec(k),whiter(k),6+BWOFFSET(whitec(k),whiter(k)))}) );  ORDERED(c,r,nn) == (!i.(i:1..(nn-1) => c(i) <= c(i+1)) &  !i.(i:1..(nn-1) => (c(i)=c(i+1) => r(i) < r(i+1))));  CHECK_TYPE(bc,br,wc,wr,nn) == (  bc : 1..nn --> 1..dim &  wc : 1..nn --> 1..dim &  br : 1..nn --> 1..dim &  wr : 1..nn --> 1..dim );  CHECK_DIAGONALS(bc,br,wc,wr,nn) == (  !(i,j).(i:1..nn & j:1..nn => bc(i) /= wc(j)) &  !(i,j).(i:1..nn & j:1..nn => br(i) /= wr(j)) &  !(i,j).(i:1..nn & j:1..nn => br(i) /= wr(j) + (bc(i)-wc(j))) &  !(i,j).(i:1..nn & j:1..nn => br(i) /= wr(j) - (bc(i)-wc(j)))  )CONSTANTS n, dim, blackc, blackr, whitec, whiterPROPERTIES n : 1..16 & dim = 8 &

 CHECK_TYPE(blackc, blackr, whitec, whiter, n) & ORDERED(blackc,blackr,n) & /* ensures proper ordering + that we do not place twoqueens on same square */ ORDERED(whitec,whiter,n) & CHECK_DIAGONALS(blackc, blackr, whitec, whiter, n) & whitec(1) < blackc(1) /* symmetry breaking */ &

 /* Repeat constraints for n+1 and assert that it cannot be solved */  not( #(n1,blackc1, blackr1, whitec1, whiter1).  (n1=n+1 & /* n1:2..17 & */

64

Page 67: Modelling Examples

  CHECK_TYPE(blackc1, blackr1, whitec1, whiter1, n1) &  ORDERED(blackc1,blackr1,n1) & /* ensures proper ordering + that we do notplace two queens on same square */  ORDERED(whitec1,whiter1,n1) &  CHECK_DIAGONALS(blackc1, blackr1, whitec1, whiter1, n1) &  whitec1(1) < blackc1(1) /* symmetry breaking */  )  )END

Here are the solving times for various board sizes on my MacBook Air:

 dim=5 --> optimum n=4 found in 0.18 secs dim=6 --> optimum n=5 found in 1.16 secs dim=7 --> optimum n=7 found in 21.174 secs dim=8 --> optimum n=9 found in 780.130 secs

The first solution found for dim=8 is as follows:

65

Page 68: Modelling Examples

Proving Theorems in ProB REPLFor this example we try and use the REPL (Read-Eval-Print-Loop) of ProB to prove theorems. TheREPL can either be started using probcli’s command -repl or by starting the Eval Console in ProBTcl/Tk.

See the beginning of Sudoku Solved in the ProB REPL for more details about how to start the REPL.

The general principle for proving a sequent Hyp |- Goal is to state the hypotheses Hyp and negatethe goal. If ProB finds a solution, a counter example to the sequent exists and it cannot be proven. IfProB finds no solution, then under certain circumstances the sequent is proven, as no counterexample exists. (This mechanism is used by the ProB Disprover in Rodin.)

Let us prove that from x:1..100 it follows that the equation x*x+2*x+2 = 1 has no solution:

>>> x:1..100 & not(x*x+2*x+2/=1)Existentially Quantified Predicate over x is FALSE

In this case, ProB has not generated an "enumeration warning", i.e., all cases where considered: wehave a proof. In general when all variables are restricted to a finite set of values in the hypotheses,ProB can be used as a prover.

Let us now lift the finiteness restriction on x and prove the theorem for all integer values:

>>> x:INTEGER & not(x*x+2*x+2/=1)### Warning: enumerating x : INTEGER : inf: -1 ---> -1: -1Existentially Quantified Predicate over x is TRUESolution:  x = -1

Here ProB has found a counter example and the sequent is not valid. As you can see, anenumeration warning occurred; meaning that not all of the infinitely many values for x will betried. But this warning is not relevant here as a solution was found.

Let us try and restrict x to positive values; the number of values are infinite (NATURAL is the set ofmathematical natural numbers, not restricted by MAXINT):

>>> x:NATURAL & not(x*x+2*x+2/=1)Existentially Quantified Predicate over x is FALSE

Here ProB has found no solution and generated no enumeration warning: the sequent is proven.

Now let us try and prove that x>=y follows from x>y:

66

Page 69: Modelling Examples

>>> x>y & not(x>=y)% Timeout when posting constraint:% kernel_objects:(_15735#>0)### Warning: enumerating x : INTEGER : inf:sup ---> -1:3% Timeout when posting constraint:% kernel_objects:(_15735#<0)Existentially Quantified Predicate over x,y is UNKNOWN [FALSE with ** ENUMERATIONWARNING **]

As you can see, here the solver was not able to detect the inconsistency and prove the sequent overthe unbounded integers x and y. There are two things one can try. First, one can enable someadditional constraint propagation rules (implemented using the Constraint Handling Rules libraryof Prolog) in the standard ProB kernel by setting the CHR preference to TRUE:

>>> -p CHR TRUEExecuting probcli command: [set_pref(CHR,TRUE)]>>> x>y & not(x>=y)Existentially Quantified Predicate over x,y is FALSE

This has enabled us to prove the sequent. (The ProB Disprover automatically sets this preferencefor you.) Another solution is again to use the Z3 backend:

>>> :z3 x>y & not(x>=y)PREDICATE is FALSE

User-Defined Sets

Suppose we want to prove a property not over a specific set such as the integers but over anarbitrary set. If you want to use additional basic types in the ProB REPL you need to define them ina B machine, they cannot (yet) be added in the REPL. For example, let us create a file DefSets.mch:

MACHINE DefSetsSETS D;E = {e1,e2,e3,e4,e5} // we just define two sets to be used in the REPL, D isdeferred, E is enumeratedEND

Then you can load the file and start the REPL:

rlwrap probcli DefSets.mch -repl

Let us try and prove that A={a,b} & B={c,d} implies A /\ B = {}. We can state this as follows. Notethat in B we need to type A and B. Here we first use the enumerated set E for that purpose.

67

Page 70: Modelling Examples

>>> A <: E & B<: E & A={a,b} & B={c,d} & not( A /\ B = {} )Existentially Quantified Predicate over A,B,a,b,c,d is TRUESolution:  A = {e1} &  B = {e1} &  a = e1 &  b = e1 &  c = e1 &  d = e1

As you can see, the goal A /\ B = {} cannot be proven, a counter-example is provided. If we addhypotheses that a,b,c,d are all pair-wise distinct we can prove the assertion:

>>> A <: E & B<: E & A={a,b} & B={c,d} & a/=b & a/=c & a/=d & b/=c & b/=d & c/=d &not( A /\ B = {} )Existentially Quantified Predicate over A,B,a,b,c,d is FALSE

This has used ProB’s Prolog-CLPFD solver. You can use ProB’s translation to Z3 (see Using ProB withZ3) by prefixing the formula with z3:

>>> :z3 A <: E & B<: E & A={a,b} & B={c,d} & not( A /\ B = {} ) & a/=b & a/=c & a/=d& b/=c & b/=d & c/=dPREDICATE is FALSE

You can also translate the query to SAT via the Kodkod library (see Using ProB with KODKOD) using:

>>> :kodkod A <: E & B<: E & A={a,b} & B={c,d} & not( A /\ B = {} ) & a/=b & a/=c &a/=d & b/=c & b/=d & c/=dkodkod ok: A = {a,b} & B = {c,d} & not(A /\ B = {}) & a /= b ... ints: none,intatoms: noneKodkod module started up successfully (SAT solver SAT4J with timeout of 1500 ms).Times for computing solutions: []Existentially Quantified Predicate over A,B,a,b,c,d is FALSE

Note that ProB’s Prolog-CLPFD solver and Kodkod cannot provide proofs when you use deferredsets whose cardinality is not specified and finite. For example, let us use the deferred set D insteadof E to type A and B:

>>> A <: D & B<: D & A={a,b} & B={c,d} & not( A /\ B = {} ) & a/=b & a/=c & a/=d &b/=c & b/=d & c/=dExistentially Quantified Predicate over A,B,a,b,c,d is FALSE>>> DExpression Value ={D1,D2}

68

Page 71: Modelling Examples

As you can see, ProB has set the size of the set D to two (see Deferrred_Sets). You can see this also byasking ProB to find four different Values:

>>> A <: D & B<: D & A={a,b} & B={c,d} & a/=b & a/=c & a/=d & b/=c & b/=d & c/=dExistentially Quantified Predicate over A,B,a,b,c,d is FALSE

So, in the presence of deferred sets, ProB’s default solver and the Kodkod-based solver cannot beused to prove theorems; they can only be used to find counter-examples. The Z3 backend howeverdoes not fix the size of D:

>>> :z3 A <: D & B<: D & A={a,b} & B={c,d} & a/=b & a/=c & a/=d & b/=c & b/=d & c/=dPREDICATE is TRUESolution:  A = {D1,D2}  B = {}  a = D1  b = D2  c = D3  d = D4

Rush Hour PuzzleThis case studies tackles encoding the rush hour board game in which cars are packed on a 6-by-6grid and can either move horizontally or vertically. The goal is to move the red car to the exit. Inthis particular instance we try to solve the hardest puzzle of the original game Nr. 40.

Inspired by discussions with Neng-Fa Zhou at ICLP'14 in Vienna, we now have a new version of theB model for this puzzle.

The old version can still be found below. There is also a Prolog XTL encoding of the same problemavailable, where ProB finds the example in one second or less. Explanations and comparison withthe Picat solution will follow soon.

As we show below, the shortest solution can be found very quickly using our new feature to useTLC for model checking B specifications] (about 1 second model checking time; rest of time neededto replay counter example).

First, here is the B model of the Rush Hour puzzle:

MACHINE RushHour/* a more elegant encoding of the Rush Hour puzzle *//* Michael Leuschel, July 2014 *//* ProB finds solution in about 10.5 secs (turning invariant checking off) *//* This version has been slightly adapted for TLC by adding the c:1..red guards:  it finds a solution in 3 seconds  (most of this time is spent replaying the counter ; the model checking seems lessthan a

69

Page 72: Modelling Examples

  second) */SETS DIR = {h,v}CONSTANTS sze, dir, red, dim, free_initialPROPERTIES sze = [2,2,2,2,2, 2,2,2,2, 3,3,3, 2] & /* the sizes of the cars */ dir = [v,v,v,v,v, h,h,h,h, v,v,h, h] & /* indicating whether the cars movevertically or horizontally */ red = size(sze) & /* the last car is the red one */ dim = 5 & /* the grid goes from 0..dim */ free_initial = {(0,3),(1,3), (0,5), (3,4),(4,0),(4,1),(5,5)}DEFINITIONS  GOAL == (col(red) = 4); /* The target : move red car to the right */  ANIMATION_STR_JUSTIFY_RIGHT == TRUE;  ANIMATION_FUNCTION_DEFAULT == (0..dim)*(0..dim)*{-1};  ANIMATION_FUNCTION ==  {r,c,i| i:1..red & dir(i)=h & row(i)=r & c:col(i)..col(i)+sze(i)-1} \/  {r,c,i| i:1..red & dir(i)=v & col(i)=c & r:row(i)..row(i)+sze(i)-1} \/  free * {0}VARIABLES free, row, colINVARIANT  free <: (0..dim)*(0..dim) & /* the currently free blocks */  card(free) = card(free_initial) &  row : 1..red --> 0..dim & /* the row of each car */  col : 1..red --> 0..dim /* the column for each car */INITIALISATION free := free_initial ||  col := [(1),(2),(2),(3),(4), /* vertical 2-size cars */  (0),(1),(3),(4), /* horiz. 2-size cars */  (0),(5), /* vertical 3-size cars */  (0), /* horiz. 3-size cars */  (3)] /* red car */ ||  row := [(1),(1),(4),(3),(0),  (5),(0),(5),(4),  (0),(1),  (3),  (2)] /* red car */OPERATIONS  mv_down(c,F) = PRE c:1..red & c |-> v : dir & F = row(c)+sze(c)|->col(c) &  F : free THEN  free := free - {F} \/ {row(c)|->col(c)} ||  row(c) := row(c)+1  END;  mv_up(c,F) = PRE c:1..red & c |-> v : dir & F = row(c)-1|->col(c) &  F : free THEN  free := free - {F} \/ {row(c)+sze(c)-1|->col(c)} ||  row(c) := row(c)-1  END;  mv_right(c,F) = PRE c:1..red & c |-> h : dir & F = row(c)|->col(c)+sze(c) &  F : free THEN

70

Page 73: Modelling Examples

  free := free - {F} \/ {row(c)|->col(c)} ||  col(c) := col(c)+1  END;  mv_left(c,F) = PRE c:1..red & c |-> h : dir & F = row(c)|->col(c)-1 &  F : free THEN  free := free - {F} \/ {row(c)|->col(c)+sze(c)-1} ||  col(c) := col(c)-1  ENDEND

Finding a Solution with ProB

To find a solution you need to run the ProB "Model Check" command in the "Verify" menu. Be sureto enable the "Find GOAL (from DEFINITIONS)" checkbox, as above we have specified the targetstate col(red) = 4 inside the GOAL definition.

Here is a screenshot of ProB after finding the shortest solution using model checking. As you cansee there is also a (simple) graphical visualisation of the state of the model. We have also openedthe Evaluation View.

Exporting a Solution Trace

You can inspect or export the solution trace found by ProB in various ways:

71

Page 74: Modelling Examples

• using the command "History to Current State" in the "Traces" submenu of the "Visualize" menu

• using various commands in the "Trace Checking" submenu of the "Verify" menu, e.g.:

◦ "Save History to Trace File": this generates a Prolog trace file that can be replayed later usingthe "Check Trace from Trace File" command

◦ "Save History to B File…": this saves the trace in B format and it can be parsed by a B parser

Note: you can also find the solution from the command line using probcli: probcli -mc 10000RushHour.mch. The command line version probcli will output the trace on the console, but alsoprovides various commands to save the history to file.

Finding the shortest solution using the TLC backend

If you want to find the shortest solution with ProB you should set the "Search Strategy" in the ProB"Model Check" command to "Breadth First". The shortest solution has 81 moves (if one allows a carto move multiple spaces in one move then the shortest solution has 51 moves).

You can also use ou It was found in 3 seconds (about 1 second model checking time) using our TLCmodel checking backend on a Mac Book Air 1.7 GHz i7:

Note; without invariant checking the overall TLC runtime goes down to 2 seconds. Note that we hadto add the predicates c:1..red to the guards, as otherwise TLC cannot reduce the domain c to afinite domain. ProB itself has no issue with this, but ProB is slower (about 10 seconds to find asolution trace).

Here is the solution as obtained when saving the trace to a B file (Save History to B File… commandin the Verify → Trace Checking submenu):

/* Constants

72

Page 75: Modelling Examples

  sze = [2,2,2,2,2,2,2,2,2,3,3,3,2] & dir = [v,v,v,v,v,h,h,h,h,v,v,h,h] & red = 13 & dim = 5 & free_initial = {(0|->3),(0|->5),(1|->3),(3|->4),(4|->0),(4|->1),(5|->5)}*//* Initialisation *//* Variables  free = {(0|->3),(0|->5),(1|->3),(3|->4),(4|->0),(4|->1),(5|->5)} & col = [1,2,2,3,4,0,1,3,4,0,5,0,3] & row = [1,1,4,3,0,5,0,5,4,0,1,3,2]*/mv_up(11,(0|->5));mv_right(8,(5|->5));mv_down(4,(5|->3));mv_right(12,(3|->3));mv_down(10,(3|->0));mv_down(10,(4|->0));mv_right(12,(3|->4));mv_down(1,(3|->1));mv_down(1,(4|->1));mv_right(12,(3|->5));mv_up(3,(3|->2));mv_right(6,(5|->2));mv_down(10,(5|->0));mv_left(7,(0|->0));mv_up(2,(0|->2));mv_left(13,(2|->2));mv_left(13,(2|->1));mv_left(13,(2|->0));mv_down(2,(2|->2));mv_right(7,(0|->2));mv_right(7,(0|->3));mv_down(5,(2|->4));mv_right(7,(0|->4));mv_up(2,(0|->2));mv_right(13,(2|->2));mv_up(10,(2|->0));mv_up(10,(1|->0));mv_up(10,(0|->0));mv_right(13,(2|->3));mv_up(1,(2|->1));mv_up(1,(1|->1));mv_up(1,(0|->1));mv_left(13,(2|->1));mv_left(6,(5|->0));mv_down(3,(5|->2));mv_left(12,(3|->2));mv_down(11,(3|->5));mv_right(7,(0|->5));mv_left(12,(3|->1));

73

Page 76: Modelling Examples

mv_left(12,(3|->0));mv_up(4,(3|->3));mv_up(4,(2|->3));mv_up(4,(1|->3));mv_up(4,(0|->3));mv_right(13,(2|->3));mv_down(1,(2|->1));mv_right(12,(3|->3));mv_down(10,(3|->0));mv_right(12,(3|->4));mv_down(1,(3|->1));mv_down(10,(4|->0));mv_left(9,(4|->3));mv_down(1,(4|->1));mv_left(13,(2|->1));mv_down(4,(2|->3));mv_left(7,(0|->3));mv_left(8,(5|->3));mv_up(11,(0|->5));mv_right(12,(3|->5));mv_up(3,(3|->2));mv_right(6,(5|->2));mv_down(10,(5|->0));mv_left(13,(2|->0));mv_down(2,(2|->2));mv_left(7,(0|->2));mv_up(5,(0|->4));mv_left(7,(0|->1));mv_up(4,(0|->3));mv_left(7,(0|->0));mv_up(2,(0|->2));mv_right(13,(2|->2));mv_up(10,(2|->0));mv_right(13,(2|->3));mv_right(13,(2|->4));mv_left(6,(5|->0));mv_down(3,(5|->2));mv_left(12,(3|->2));mv_down(11,(3|->5));mv_down(11,(4|->5));mv_down(11,(5|->5));mv_right(13,(2|->5))

The full state space has 4782 states (including the root node and the set-up-constants node) and29890 transitions, as indicated by ProB’s coverage info (after doing full model checking withoutlooking for states satisfying the GOAL predicate):

74

Page 77: Modelling Examples

STATESdeadlocked:0invariant_violated:0invariant_not_checked:0open:0live:4782total:4782TOTAL_OPERATIONS29890COVERED_OPERATIONSINITIALISATION:1SETUP_CONSTANTS:1mv_down:8461mv_left:6483mv_right:6483mv_up:8461UNCOVERED_OPERATIONS

For reference, here are the statistics as output by TLC (when not looking for states satisfying thegoal predicate):

TLC2 Version 2.05 of 23 July 2013Running in Model-Checking mode.Parsing file/Users/leuschel/git_root/prob_examples/public_examples/B/Puzzles/RushHour_v2_TLC.tla...Semantic processing of module RushHour_v2_TLCStarting... (2014-07-23 12:28:17)Computing initial states...Finished computing initial states: 1 distinct state generated.Model checking completed. No error has been found.  Estimates of the probability that TLC did not check all reachable states  because two distinct states had the same fingerprint:  calculated (optimistic): val = 6.5E-12  based on the actual fingerprints: val = 8.0E-1329889 states generated, 4780 distinct states found, 0 states left on queue.The depth of the complete state graph search is 123.== Finished. (2014-07-23 12:28:21)Parsing time: 644 msTranslation time: 107 msModel checking time: 3 secStates analysed: 4780Transitions fired: 29889Result: NoError

Old Solution

This is my old solution to the Rush hour puzzle. It is not very elegant, but does work. It has a more

75

Page 78: Modelling Examples

sophisticated animation function for visualisation.

MACHINE RushHour/* not a very elegant model; but it seems to work *//* ProB finds a solution for the hardest puzzle (no. 40) */DEFINITIONS  SET_PREF_MAXINT == 8;  /*"RushHour/Puzzle10.def"; */  "RushHour/Puzzle40.def";  INDEX == (1..dim);  GOAL == (pos_hcar(red_hcar) >= dim-size_hcar(red_hcar)+1);  HEURISTIC_FUNCTION == dim-size_hcar(red_hcar) - pos_hcar(red_hcar) ; /* not a veryinteresting heuristic function; as red_car can only be moved at very last step */  ANIMATION_IMG0 == "images/sm_empty_box.gif";  ANIMATION_IMG1 == "images/sm_vcar.gif";  ANIMATION_IMG2 == "images/sm_vcar_front.gif";  ANIMATION_IMG3 == "images/sm_hcar.gif";  ANIMATION_IMG4 == "images/sm_red_hcar.gif";  ANIMATION_FUNCTION == ( {r,c,i|r:1..dim & c:1..dim & i=0} <+  {r,c,i|r:1..dim & c:1..dim & i=1 &  #j.(j:dom(col_vcar) & c=col_vcar(j) &  r>pos_vcar(j) & r<pos_vcar(j)+size_vcar(j)) } <+  {r,c,i|r:1..dim & c:1..dim & i=2 &  #j.(j:dom(col_vcar) & c=col_vcar(j) & r=pos_vcar(j)) } <+  {r,c,i|r:1..dim & c:1..dim & i:3..4 &  #j.(j:dom(row_hcar) & r=row_hcar(j) &  c>=pos_hcar(j) & c<pos_hcar(j)+size_hcar(j) &  ((j=red_hcar & i=4) or (j/=red_hcar & i=3)) ) }  );

  POSs_VCAR(vc) == {c,r|c=col_vcar(vc) & r>=pos_vcar(vc) &r<pos_vcar(vc)+size_vcar(vc)};  POSs_HCAR(hc) == {c,r|r=row_hcar(hc) & c>=pos_hcar(hc) &c<pos_hcar(hc)+size_hcar(hc)}CONSTANTS vcars,hcars,dim, col_vcar, row_hcar, size_vcar, size_hcar, red_hcar

PROPERTIES

 /* The particular puzzle */ STATIC_PROPS &

 dim = 6 & vcars : NATURAL1 & hcars: NATURAL1 & col_vcar: 1..vcars --> INDEX & row_hcar: 1..hcars --> INDEX & size_vcar: 1..vcars --> INDEX & size_hcar: 1..hcars --> INDEX &

76

Page 79: Modelling Examples

 red_hcar : 1..hcars &

 /* vcars are in ascending in row order */ !r.(r:1..(vcars-1) => col_vcar(r)<=col_vcar(r+1)) & /* hcars are in ascending in col order */ !c.(c:1..(hcars-1) => row_hcar(c)<=row_hcar(c+1))

VARIABLES  pos_vcar,  pos_hcarINVARIANT  pos_vcar: 1..vcars --> INDEX &  pos_hcar: 1..hcars --> INDEXASSERTIONS  !(vc,hc).(vc:1..vcars & hc:1..hcars => POSs_VCAR(vc) /\ POSs_HCAR(hc) = {});  !(vc1,vc2).(vc1:1..(vcars-1) & vc2:2..vcars & vc1<vc2 => POSs_VCAR(vc1) /\POSs_VCAR(vc2) = {});  !(hc1,hc2).(hc1:1..(hcars-1) & hc2:2..hcars & hc1<hc2 => POSs_HCAR(hc1) /\POSs_HCAR(hc2) = {})

INITIALISATION  pos_vcar := INIT_VCAR ||  pos_hcar := INIT_HCAROPERATIONS  move_hcar_right(car) =  PRE car:1..hcars &  pos_hcar(car)<=dim - size_hcar(car) & /* car not at extreme right */  (car<hcars => (row_hcar(car) /= row_hcar(car+1) or  pos_hcar(car+1) > pos_hcar(car)+size_hcar(car))) &  !cv.(cv:1..vcars & col_vcar(cv)=pos_hcar(car)+size_hcar(car) =>  row_hcar(car) /: pos_vcar(cv)..pos_vcar(cv)+size_vcar(cv)-1)  THEN  pos_hcar(car) := pos_hcar(car)+1  END;

  move_hcar_left(car) =  PRE car:1..hcars &  pos_hcar(car)> 1 & /* car not at extreme left */  (car>1 => (row_hcar(car) /= row_hcar(car-1) or  pos_hcar(car-1)+size_hcar(car-1) <= pos_hcar(car)-1))&  !cv.(cv:1..vcars & col_vcar(cv)=pos_hcar(car)-1 =>  row_hcar(car) /: pos_vcar(cv)..pos_vcar(cv)+size_vcar(cv)-1)  THEN  pos_hcar(car) := pos_hcar(car)-1  END;

  move_vcar_down(car) =  PRE car:1..vcars &  pos_vcar(car)<=dim - size_vcar(car) & /* car not at extreme bottom */

77

Page 80: Modelling Examples

  (car<vcars => (col_vcar(car) /= col_vcar(car+1) or  pos_vcar(car+1) > pos_vcar(car)+size_vcar(car))) &  !cv.(cv:1..hcars & row_hcar(cv)=pos_vcar(car)+size_vcar(car) =>  col_vcar(car) /: pos_hcar(cv)..pos_hcar(cv)+size_hcar(cv)-1)  THEN  pos_vcar(car) := pos_vcar(car)+1  END;

  move_vcar_up(car) =  PRE car:1..vcars &  pos_vcar(car)> 1 & /* car not at extreme top */  (car>1 => (col_vcar(car) /= col_vcar(car-1) or  pos_vcar(car-1)+size_vcar(car-1) <= pos_vcar(car)-1)) &  !cv.(cv:1..hcars & row_hcar(cv)=pos_vcar(car)-1 =>  col_vcar(car) /: pos_hcar(cv)..pos_hcar(cv)+size_hcar(cv)-1)  THEN  pos_vcar(car) := pos_vcar(car)-1  ENDEND

The encoding of hardest puzzle Nr 40 in the file RushHour/Puzzle40.def is as follows:

DEFINITIONS/* The particular puzzle (nr. 40) */ STATIC_PROPS == (vcars=7 & hcars = 6 & col_vcar = {1|->1, 2|->2, 3|->3, 4|->3, 5|->4, 6|->5, 7|->6} & size_vcar = {1|->3, 2|->2, 3|->2, 4|->2, 5|->2, 6|->2, 7|->3} & row_hcar = {1|->1, 2|->3, 3|->4, 4|->5, 5|->6, 6|->6} & size_hcar = {1|->2, 2|->2, 3|->3, 4|->2, 5|->2, 6|->2} & red_hcar = 2); /* red hcar */ INIT_VCAR == {1|->1, 2|->2, 3|->2, 4|->5, 5|->4, 6|->1, 7|->2 }; INIT_HCAR == {1|->2, 2|->4, 3|->1, 4|->5, 5|->1, 6|->4}

ProB 1.3.7 took about 26 seconds to solve this puzzle (on my Mac Book Air 1.8 GHz i7; runtimes mayvary as ProB uses a randomized depth-first/breadth-first search):

78

Page 81: Modelling Examples

The solution found has 125 steps:

SETUP_CONSTANTS(6,7,6,[1,2,3,3,4,5,6],[1,3,4,5,6,6],[3,2,2,2,2,2,3],[2,2,3,2,2,2],2)INITIALISATION([1,2,2,5,4,1,2],[2,4,1,5,1,4])move_hcar_right(6)move_vcar_down(5)move_hcar_right(3)move_vcar_down(1)move_vcar_up(7)move_hcar_left(1)move_vcar_down(1)move_hcar_right(3)move_vcar_down(2)move_hcar_right(3)move_vcar_down(2)move_vcar_up(4)move_vcar_up(3)move_hcar_right(5)move_vcar_down(1)move_hcar_left(2)move_vcar_down(6)move_hcar_left(2)

79

Page 82: Modelling Examples

move_hcar_left(2)move_vcar_down(3)move_hcar_right(1)move_hcar_right(1)move_hcar_right(1)move_vcar_up(3)move_hcar_right(2)move_vcar_up(1)move_vcar_up(1)move_vcar_up(1)move_hcar_right(2)move_vcar_up(2)move_vcar_up(2)move_hcar_left(5)move_vcar_down(4)move_vcar_up(2)move_hcar_left(3)move_hcar_left(3)move_hcar_left(3)move_hcar_left(2)move_vcar_up(5)move_vcar_up(5)move_vcar_up(5)move_vcar_down(7)move_hcar_right(1)move_hcar_right(3)move_vcar_up(5)move_hcar_right(2)move_vcar_down(1)move_vcar_down(2)move_hcar_right(3)move_vcar_down(2)move_vcar_down(2)move_hcar_left(2)move_vcar_down(5)move_vcar_down(1)move_hcar_left(1)move_vcar_up(7)move_hcar_right(3)move_vcar_up(4)move_hcar_right(5)move_vcar_down(1)move_hcar_left(2)move_vcar_down(3)move_hcar_left(1)move_hcar_left(1)move_hcar_left(1)move_vcar_up(3)move_hcar_right(2)move_vcar_up(1)move_hcar_left(5)

80

Page 83: Modelling Examples

move_hcar_left(4)move_vcar_up(5)move_vcar_down(4)move_hcar_right(2)move_vcar_up(2)move_vcar_up(6)move_hcar_right(2)move_vcar_up(1)move_vcar_up(4)move_vcar_up(4)move_vcar_down(2)move_vcar_down(1)move_vcar_down(4)move_vcar_down(3)move_vcar_up(2)move_vcar_up(2)move_hcar_left(6)move_hcar_right(1)move_vcar_up(1)move_vcar_up(1)move_vcar_down(4)move_vcar_down(3)move_vcar_down(2)move_vcar_down(2)move_vcar_up(3)move_vcar_up(4)move_vcar_down(1)move_vcar_down(1)move_vcar_down(4)move_vcar_up(2)move_vcar_up(1)move_hcar_left(3)move_vcar_up(2)move_vcar_down(7)move_vcar_up(1)move_vcar_down(7)move_vcar_down(7)move_vcar_down(2)move_vcar_down(2)move_vcar_up(7)move_vcar_up(7)move_hcar_right(6)move_vcar_up(7)move_vcar_up(2)move_vcar_up(2)move_hcar_left(3)move_vcar_down(7)move_vcar_down(7)move_vcar_down(1)move_vcar_down(1)move_hcar_left(6)

81

Page 84: Modelling Examples

move_vcar_down(7)move_vcar_up(1)move_hcar_right(2)

Adapted version for TLC

Using our translator to TLA+ we can solve an adapted version of the above model in 11 secondsplus the time for the translation and starting up the translator and TLC (a few seconds). (The modelhas to be rewritten slightly for TLC, as it’s enumeration and constraint solving capabilities are morelimited.)

Here is the slightly rewritten version which works with TLC (in addition to ProB):

MACHINE RushHour_TLC/* not a very elegant model; but it seems to work *//* ProB finds a solution for the hardest puzzle (no. 40) */DEFINITIONS  SET_PREF_MAXINT == 8;

  /*"RushHour/Puzzle40.def"; */  STATIC_PROPS ==  (vcars=7 & hcars = 6 &

82

Page 85: Modelling Examples

  col_vcar = {1|->1, 2|->2, 3|->3, 4|->3, 5|->4, 6|->5, 7|->6} &  size_vcar = {1|->3, 2|->2, 3|->2, 4|->2, 5|->2, 6|->2, 7|->3} &  row_hcar = {1|->1, 2|->3, 3|->4, 4|->5, 5|->6, 6|->6} &  size_hcar = {1|->2, 2|->2, 3|->3, 4|->2, 5|->2, 6|->2} &  red_hcar = 2); /* red hcar */  INIT_VCAR == {1|->1, 2|->2, 3|->2, 4|->5, 5|->4, 6|->1, 7|->2 };  INIT_HCAR == {1|->2, 2|->4, 3|->1, 4|->5, 5|->1, 6|->4};

  INDEX == (1..dim);  GOAL == (pos_hcar(red_hcar) >= dim-size_hcar(red_hcar)+1);  HEURISTIC_FUNCTION == dim-size_hcar(red_hcar) - pos_hcar(red_hcar) ; /* not a veryinteresting heuristic function; as red_car can only be moved at very last step */  ANIMATION_IMG0 == "images/sm_empty_box.gif";  ANIMATION_IMG1 == "images/sm_vcar.gif";  ANIMATION_IMG2 == "images/sm_vcar_front.gif";  ANIMATION_IMG3 == "images/sm_hcar.gif";  ANIMATION_IMG4 == "images/sm_red_hcar.gif";  ANIMATION_FUNCTION == ( {r,c,i|r:1..dim & c:1..dim & i=0} <+  {r,c,i|r:1..dim & c:1..dim & i=1 &  #j.(j:dom(col_vcar) & c=col_vcar(j) &  r>pos_vcar(j) & r<pos_vcar(j)+size_vcar(j)) } <+  {r,c,i|r:1..dim & c:1..dim & i=2 &  #j.(j:dom(col_vcar) & c=col_vcar(j) & r=pos_vcar(j)) } <+  {r,c,i|r:1..dim & c:1..dim & i:3..4 &  #j.(j:dom(row_hcar) & r=row_hcar(j) &  c>=pos_hcar(j) & c<pos_hcar(j)+size_hcar(j) &  ((j=red_hcar & i=4) or (j/=red_hcar & i=3)) ) }  );

  POSs_VCAR(vc) == {c,r|c=col_vcar(vc) & r :pos_vcar(vc)..(pos_vcar(vc)+size_vcar(vc))-1}; /* r>=pos_vcar(vc) &r<pos_vcar(vc)+size_vcar(vc) */  POSs_HCAR(hc) == {c,r|r=row_hcar(hc) & c : pos_hcar(hc)..(pos_hcar(hc)+size_hcar(hc))-1} /* c>=pos_hcar(hc) & c<pos_hcar(hc)+size_hcar(hc)*/CONSTANTS vcars,hcars,dim, col_vcar, row_hcar, size_vcar, size_hcar, red_hcar

PROPERTIES

 /* The particular puzzle */ STATIC_PROPS &

 dim = 6 & vcars : NATURAL1 & hcars: NATURAL1 & col_vcar: 1..vcars --> INDEX & row_hcar: 1..hcars --> INDEX & size_vcar: 1..vcars --> INDEX & size_hcar: 1..hcars --> INDEX &

83

Page 86: Modelling Examples

 red_hcar : 1..hcars &

 /* vcars are in ascending in row order */ !r.(r:1..(vcars-1) => col_vcar(r)<=col_vcar(r+1)) & /* hcars are in ascending in col order */ !c.(c:1..(hcars-1) => row_hcar(c)<=row_hcar(c+1))

VARIABLES  pos_vcar,  pos_hcarINVARIANT  pos_vcar: 1..vcars --> INDEX &  pos_hcar: 1..hcars --> INDEXASSERTIONS  !(vc,hc).(vc:1..vcars & hc:1..hcars => POSs_VCAR(vc) /\ POSs_HCAR(hc) = {});  !(vc1,vc2).(vc1:1..(vcars-1) & vc2:2..vcars & vc1<vc2 => POSs_VCAR(vc1) /\POSs_VCAR(vc2) = {});  !(hc1,hc2).(hc1:1..(hcars-1) & hc2:2..hcars & hc1<hc2 => POSs_HCAR(hc1) /\POSs_HCAR(hc2) = {})

INITIALISATION  pos_vcar := INIT_VCAR ||  pos_hcar := INIT_HCAROPERATIONS  move_hcar_right(car) =  PRE car:1..hcars &  pos_hcar(car)<=dim - size_hcar(car) & /* car not at extreme right */  (car<hcars => (row_hcar(car) /= row_hcar(car+1) or  pos_hcar(car+1) > pos_hcar(car)+size_hcar(car))) &  !cv.(cv:1..vcars & col_vcar(cv)=pos_hcar(car)+size_hcar(car) =>  row_hcar(car) /: pos_vcar(cv)..pos_vcar(cv)+size_vcar(cv)-1)  THEN  pos_hcar(car) := pos_hcar(car)+1  END;

  move_hcar_left(car) =  PRE car:1..hcars &  pos_hcar(car)> 1 & /* car not at extreme left */  (car>1 => (row_hcar(car) /= row_hcar(car-1) or  pos_hcar(car-1)+size_hcar(car-1) <= pos_hcar(car)-1))&  !cv.(cv:1..vcars & col_vcar(cv)=pos_hcar(car)-1 =>  row_hcar(car) /: pos_vcar(cv)..pos_vcar(cv)+size_vcar(cv)-1)  THEN  pos_hcar(car) := pos_hcar(car)-1  END;

  move_vcar_down(car) =  PRE car:1..vcars &  pos_vcar(car)<=dim - size_vcar(car) & /* car not at extreme bottom */

84

Page 87: Modelling Examples

  (car<vcars => (col_vcar(car) /= col_vcar(car+1) or  pos_vcar(car+1) > pos_vcar(car)+size_vcar(car))) &  !cv.(cv:1..hcars & row_hcar(cv)=pos_vcar(car)+size_vcar(car) =>  col_vcar(car) /: pos_hcar(cv)..pos_hcar(cv)+size_hcar(cv)-1)  THEN  pos_vcar(car) := pos_vcar(car)+1  END;

  move_vcar_up(car) =  PRE car:1..vcars &  pos_vcar(car)> 1 & /* car not at extreme top */  (car>1 => (col_vcar(car) /= col_vcar(car-1) or  pos_vcar(car-1)+size_vcar(car-1) <= pos_vcar(car)-1)) &  !cv.(cv:1..hcars & row_hcar(cv)=pos_vcar(car)-1 =>  col_vcar(car) /: pos_hcar(cv)..pos_hcar(cv)+size_hcar(cv)-1)  THEN  pos_vcar(car) := pos_vcar(car)-1  ENDEND

Rush Hour XTLThis case studies tackles encoding the rush hour board game in which cars are packed on a 6-by-6grid and can either move horizontally or vertically. The goal is to move the red car to the exit. Inthis particular instance we try to solve the hardest puzzle of the original game Nr. 40.

This is a Prolog XTL encoding of the B solution which is also available. On the Prolog XTL encodingpresented here ProB finds the example in one second (on a Mac Book Air, 1.7 GHz i7), on the Bversion it takes ProB about 10 seconds (but the TLC backend is faster). Part of the B models areshown in comments for reference below. This file needs to be saved with a .P extension so that itcan be loaded by ProB Tcl/Tk or probcli.

Observe how we use sort and ord_add_element to avoid multiple versions of the same state. Theimportant predicates that ProB uses are start/1, trans/3 and prop/2.

/* a Prolog XTL translation of the more elegant encoding of the Rush Hour puzzle *//* Michael Leuschel, July 2014 *//* ProB finds solution in about 0.5 - 1 second *using mixed DF/BF search *//* Using BF search it takes 1.3 seconds *//* This shows the potential of compiling the ProB B interpreter down to Prolog *//* The Prolog could still be optimized further (e.g. run through a partial evaluator )*/

%:- use_module(library(lists)). % not needed when run from ProB%:- use_module(library(ordsets)). % not needed when run from ProB

 sze([2,2,2,2,2, 2,2,2,2, 3,3,3, 2]). /* the sizes of the cars */ dir([v,v,v,v,v, h,h,h,h, v,v,h, h]). /* indicating whether the cars move

85

Page 88: Modelling Examples

vertically or horizontally */

red(Len) :- sze(S), length(S,Len). /* the last car is the red one */dim(5). /* the grid goes from 0..dim */free_initial([(0,3),(1,3), (0,5), (3,4),(4,0),(4,1),(5,5)]).

col_initial([(1),(2),(2),(3),(4), /* vertical 2-size cars */  (0),(1),(3),(4), /* horiz. 2-size cars */  (0),(5), /* vertical 3-size cars */  (0), /* horiz. 3-size cars */  (3)] /* red car */  ).row_initial([(1),(1),(4),(3),(0),  (5),(0),(5),(4),  (0),(1),  (3),  (2)]).

init(S) :- start(S).start(rcf(Rows,Cols,SFree)) :- free_initial(Free),  sort(Free,SFree),  row_initial(Rows),  col_initial(Cols).

prop(rcf(_,_,Free),free(I,J)) :- member((I,J),Free).prop(rcf(Rows,Cols,_),car(Car,Row,Col)) :- nth1(Car,Rows,Row),nth1(Car,Cols,Col)./*prop(rcf(_,_,Free),unsafe) :- member((N,M),Free), (N>5 ; N<0 ; M>5 ; M<0).prop(rcf(Rows,_,_),unsafe) :- member(N,Rows), (N>5 ; N<0).prop(rcf(_,Cols,_),unsafe) :- member(N,Cols), (N>5 ; N<0).*/prop(rcf(_Rows,Cols,_Free),unsafe) :- last(Cols,4). /* The target : move red car tothe right */

% utility for updating lists of columns/rows:replace([_|T],1,New,Res) :- !, Res=[New|T].replace([H|T],N,New,[H|TR]) :- N1 is N-1, replace(T,N1,New,TR).

trans(mv_down(Car,F),rcf(Rows,Cols,Free),rcf(Rows1,Cols,SFree1)) :-  dir(Dir),  nth1(Car,Dir,v),  nth1(Car,Rows,RC),  nth1(Car,Cols,CC),  sze(Sze),  nth1(Car,Sze,SC),  FR is RC+SC, F = (FR,CC),  select(F,Free,Free0),  ord_add_element(Free0,(RC,CC),SFree1),  RC1 is RC+1,

86

Page 89: Modelling Examples

  replace(Rows,Car,RC1,Rows1).

/*  mv_down(c,F) = PRE c:1..red & c |-> v : dir & F = row(c)+sze(c)|->col(c) &  F : free THEN  free := free - {F} \/ {row(c)|->col(c)} ||  row(c) := row(c)+1  END;*/

trans(mv_up(Car,F),rcf(Rows,Cols,Free),rcf(Rows1,Cols,SFree1)) :-  dir(Dir),  nth1(Car,Dir,v),  nth1(Car,Rows,RC),  nth1(Car,Cols,CC),  FR is RC-1, F = (FR,CC),  select(F,Free,Free0),  sze(Sze),  nth1(Car,Sze,SC),  RSC1 is RC+SC-1,  ord_add_element(Free0,(RSC1,CC),SFree1),  replace(Rows,Car,FR,Rows1).

/*  mv_up(c,F) = PRE c:1..red & c |-> v : dir & F = row(c)-1|->col(c) &  F : free THEN  free := free - {F} \/ {row(c)+sze(c)-1|->col(c)} ||  row(c) := row(c)-1  END; */

trans(mv_right(Car,F),rcf(Rows,Cols,Free),rcf(Rows,Cols1,SFree1)) :-  dir(Dir),  nth1(Car,Dir,h),  nth1(Car,Rows,RC),  nth1(Car,Cols,CC),  sze(Sze),  nth1(Car,Sze,SC),  CCS is CC+SC, F = (RC,CCS),  select(F,Free,Free0),  ord_add_element(Free0,(RC,CC),SFree1),  CC1 is CC+1,  replace(Cols,Car,CC1,Cols1).

/*  mv_right(c,F) = PRE c:1..red & c |-> h : dir & F = row(c)|->col(c)+sze(c) &  F : free THEN  free := free - {F} \/ {row(c)|->col(c)} ||  col(c) := col(c)+1

87

Page 90: Modelling Examples

  END; */

trans(mv_left(Car,F,RC,CC,SC,CCS),rcf(Rows,Cols,Free),rcf(Rows,Cols1,SFree1)) :-  dir(Dir),  nth1(Car,Dir,h),  nth1(Car,Rows,RC),  nth1(Car,Cols,CC),  CC1 is CC-1, F = (RC,CC1),  select(F,Free,Free0),  sze(Sze),  nth1(Car,Sze,SC),  CCS is CC1+SC,  ord_add_element(Free0,(RC,CCS),SFree1),  replace(Cols,Car,CC1,Cols1).

/*  mv_left(c,F) = PRE c:1..red & c |-> h : dir & F = row(c)|->col(c)-1 &  F : free THEN  free := free - {F} \/ {row(c)|->col(c)+sze(c)-1} ||  col(c) := col(c)-1  ENDEND*/

We can also add a simple graphical visualisation by including the following in the XTL file (usingthe animation_function_result predicate recognised by ProB as of version 1.4.0-rc3):

88

Page 91: Modelling Examples

% Graphical Visualization Animation Function:

is_index(I,I).is_index(I,Res) :- dim(N), I<N, I1 is I+1, is_index(I1,Res).

animation_function_result(State,Matrix) :-  findall(((RowNr,ColNr),Cell), (is_index(0,RowNr),is_index(0,ColNr),  cell_content(State,RowNr,ColNr,Cell)),Matrix).cell_content(rcf(Rows,Cols,Free),Row,Col,'--') :- member((Row,Col),Free).cell_content(rcf(Rows,Cols,Free),Row,Col,Car) :- nth1(Car,Rows,Row),nth1(Car,Cols,Col).cell_content(rcf(Rows,Cols,Free),Row1,Col,Car) :- dir(Dir),  sze(Sze),  nth1(Car,Dir,v),  nth1(Car,Sze,SC),  nth1(Car,Rows,Row), nth1(Car,Cols,Col),  (Row1 is Row+1 ; SC>2, Row1 is Row+2).cell_content(rcf(Rows,Cols,Free),Row,Col1,Car) :- dir(Dir),  sze(Sze),  nth1(Car,Dir,h),  nth1(Car,Sze,SC),  nth1(Car,Rows,Row), nth1(Car,Cols,Col),  (Col1 is Col+1 ; SC>2, Col1 is Col+2).

Here is a screenshot of ProB after finding the shortest solution using model checking. You can seethe (simple) graphical visualisation of the state of the model.

89

Page 92: Modelling Examples

Running using probcli

Here is how you can find the solution using probcli (run on a Mac Book Air, 1.7 GHz i7):

$ probcli -mc 100000 RushHour_Prolog.P -bftcltk_open_xtl_file(/Users/leuschel/git_root/prob_examples/public_examples/B/Puzzles/RushHour/RushHour_Prolog.P)new_xtl_file(/Users/leuschel/git_root/prob_examples/public_examples/B/Puzzles/RushHour/RushHour_Prolog.P)found_error(xtl_error,3026)finding_trace_from_to(root)....................Model Checking Time: 1310 msStates analysed: 3026Transitions fired: 19821*** COUNTER EXAMPLE FOUND ***

xtl_error*** TRACE: 1: start_xtl_system: 2: mv_right(8,(5,5)): 3: mv_down(4,(5,3)): 4: mv_up(11,(0,5)):

90

Page 93: Modelling Examples

 5: mv_right(12,(3,3)): 6: mv_down(10,(3,0)): 7: mv_left(7,(0,0),0,1,2,2): 8: mv_right(12,(3,4)): 9: mv_up(2,(0,2)): 10: mv_down(1,(3,1)): 11: mv_down(10,(4,0)): 12: mv_right(12,(3,5)): 13: mv_left(13,(2,2),2,3,2,4): 14: mv_down(1,(4,1)): 15: mv_up(3,(3,2)): 16: mv_right(6,(5,2)): 17: mv_left(13,(2,1),2,2,2,3): 18: mv_down(10,(5,0)): 19: mv_left(13,(2,0),2,1,2,2): 20: mv_down(2,(2,2)): 21: mv_right(7,(0,2)): 22: mv_down(5,(2,4)): 23: mv_right(7,(0,3)): 24: mv_right(7,(0,4)): 25: mv_up(2,(0,2)): 26: mv_right(13,(2,2)): 27: mv_up(10,(2,0)): 28: mv_left(6,(5,0),5,1,2,2): 29: mv_down(3,(5,2)): 30: mv_left(12,(3,2),3,3,3,5): 31: mv_right(13,(2,3)): 32: mv_up(1,(2,1)): 33: mv_up(1,(1,1)): 34: mv_left(12,(3,1),3,2,3,4): 35: mv_up(10,(1,0)): 36: mv_up(10,(0,0)): 37: mv_up(1,(0,1)): 38: mv_left(12,(3,0),3,1,3,3): 39: mv_up(4,(3,3)): 40: mv_left(13,(2,1),2,2,2,3): 41: mv_up(4,(2,3)): 42: mv_up(4,(1,3)): 43: mv_right(12,(3,3)): 44: mv_down(10,(3,0)): 45: mv_down(11,(3,5)): 46: mv_right(7,(0,5)): 47: mv_up(4,(0,3)): 48: mv_right(13,(2,3)): 49: mv_right(12,(3,4)): 50: mv_down(1,(2,1)): 51: mv_down(1,(3,1)): 52: mv_down(1,(4,1)): 53: mv_left(13,(2,1),2,2,2,3): 54: mv_down(4,(2,3)): 55: mv_left(7,(0,3),0,4,2,5):

91

Page 94: Modelling Examples

 56: mv_up(11,(0,5)): 57: mv_right(12,(3,5)): 58: mv_up(3,(3,2)): 59: mv_right(6,(5,2)): 60: mv_down(10,(4,0)): 61: mv_down(10,(5,0)): 62: mv_left(13,(2,0),2,1,2,2): 63: mv_down(2,(2,2)): 64: mv_left(7,(0,2),0,3,2,4): 65: mv_left(7,(0,1),0,2,2,3): 66: mv_left(7,(0,0),0,1,2,2): 67: mv_up(2,(0,2)): 68: mv_right(13,(2,2)): 69: mv_left(9,(4,3),4,4,2,5): 70: mv_up(10,(2,0)): 71: mv_left(6,(5,0),5,1,2,2): 72: mv_up(4,(0,3)): 73: mv_right(13,(2,3)): 74: mv_left(8,(5,3),5,4,2,5): 75: mv_down(3,(5,2)): 76: mv_left(12,(3,2),3,3,3,5): 77: mv_down(11,(3,5)): 78: mv_down(11,(4,5)): 79: mv_up(5,(0,4)): 80: mv_right(13,(2,4)): 81: mv_down(11,(5,5)): 82: mv_right(13,(2,5)):! *** error occurred ***! xtl_error

The full states has 4781 states (including the root node) and 29889 transitions. This is the output ofProB’s coverage statistics:

STATESdeadlocked:0open:0live:4781total:4781TOTAL_OPERATIONS29889COVERED_OPERATIONSmv_down:8461mv_left:6483mv_right:6483mv_up:8461start_xtl_system:1UNCOVERED_OPERATIONS

Complete model checking, without looking for goal states, takes 1.6 seconds (on a Mac Book Air, 1.7

92

Page 95: Modelling Examples

GHz i7):

$ probcli -mc 100000 RushHour_Prolog.P -noinv --coveragetcltk_open_xtl_file(/Users/leuschel/git_root/prob_examples/public_examples/B/Puzzles/RushHour/RushHour_Prolog.P)new_xtl_file(/Users/leuschel/git_root/prob_examples/public_examples/B/Puzzles/RushHour/RushHour_Prolog.P)% All open nodes visitedModel Checking Time: 1610 msStates analysed: 4780Transitions fired: 29889No Counter Example found. ALL nodes visited.Coverage:

[STATES,deadlocked:0,open:0,live:4781,total:4781,TOTAL_OPERATIONS,29889,COVERED_OPERATIONS,mv_down:8461,mv_left:6483,mv_right:6483,mv_up:8461,start_xtl_system:1,UNCOVERED_OPERATIONS]

SEND-MORE-MONEYIn this entry we study how to solve the famous verbal arithmetic SEND-MORE-MONEY puzzle. Thetask is to find the digits S,E,N,D,M,O,R,Y such that the addition of SEND to MORE leads the decimalnumber MONEY. There are various ways to solve this problem in B using ProB. The quickest isprobably to fire up the probcli REPL and then type the problem into the console. To start up theREPL type the following into your shell or terminal:

probcli -repl

This should give you the following output:

ProB Interactive Expression and Predicate EvaluatorType ":help"for more information.>>>

Note, you can also use the Eval Console in ProB Tcl/Tk or the online Logic Calculator. We can nowencode the puzzle as a predicate as follows:

>>> {S,E,N,D, M,O,R, Y} <: 0..9 & S>0 & M>0 & card({S,E,N,D, M,O,R, Y})=8 & S*1000 + E*100 +N*10 + D + M*1000 + O*100 + R*10 + E = M*10000 + O*1000 + N*100 + E*10 + Y

After hitting return, ProB will output the following immediately:Existentially Quantified Predicate over S,E,N,D,M,O,R,Y is TRUESolution:S = 9 &E = 5 &N = 6 &D = 7 &M = 1 &O = 0 &

93

Page 96: Modelling Examples

R = 8 &Y = 2

Let us review the individual conjuncts of the B encoding of the puzzle: The following specifies thatS,E,N,D,M,O,R,Y are all digits. Note that <: is the subset operator in B:

{S,E,N,D, M,O,R, Y} <: 0..9

An alternative, slightly longer, encoding would have been to write:

S:0..9 & E:0..9 & N:0..9 & D:0..9 & M:0..9 & O:0..9 & R:0..9 & Y:0..9

The following conjunct specifies that the S and M cannot be 0:

S>0 & M>0

The next conjunct specifies that all digits are distinct:

card({S,E,N,D, M,O,R, Y})=8

Note that an alternative, but much longer encoding would have been to specify inequalities

S /= E & S /= N & S /= D & … & R/=Y

Finally, the last conjunct expresses the sum constraint:

S*1000 + E*100 + N*10 + D + M*1000 + O*100 + R*10 + E = M*10000 + O*1000 + N*100 + E*10 + Y

We are still not sure if this is the only solution. One way to ensure this is to compute a setcomprehension with all solutions:

>>> {S,E,N,D,M,O,R,Y|{S,E,N,D, M,O,R, Y} <: 0..9 & S>0 & M>0 & card({S,E,N,D, M,O,R, Y})=8 &S*1000 + E*100 + N*10 + D + M*1000 + O*100 + R*10 + E = M*10000 + O*1000 + N*100 + E*10 + Y}Expression Value ={(((((((9|→5)|→6)|→7)|→1)|→0)|→8)|→2)}

As you can see, only one solution tuple was found.

Instead of solving the puzzle within ProB’s console, you can also save the above predicate into a fileSendMoreMoney.eval and then issue the command:

probcli -eval_file SendMoreMoney.eval

Existentially Quantified Predicate over S,E,N,D,M,O,R,Y is TRUESolution:S = 9 &E = 5 &N = 6 &D = 7 &M = 1 &O = 0 &R = 8 &Y = 2

94

Page 97: Modelling Examples

Another alternative is to wrap the predicate into a full B machine, e.g., as PROPERTIES, e.g., into afile SendMoreMoney.mch with the following content:

MACHINE SendMoreMoneyCONSTANTS S,E,N,D, M,O,R, YPROPERTIES  {S,E,N,D, M,O,R, Y} <: 0..9 & S >0 & M >0 &  card({S,E,N,D, M,O,R, Y}) = 8 &  S*1000 + E*100 + N*10 + D +  M*1000 + O*100 + R*10 + E =  M*10000 + O*1000 + N*100 + E*10 + YEND

This machine can then be loaded, e.g., into the ProB Tcl/Tk animator, which should give you apicture like this:

Alternatively you can load the B machine from the command-line using, e.g.:

probcli SendMoreMoney.mch -init -repl

This command will solve the properties and then start the REPL, where you can query the values ofthe solutions found.

95

Page 98: Modelling Examples

KISS*KISS = PASSION

A similar puzzle, this times involving multiplication is the KISS*KISS=PASSION puzzle. Here weagain have distinct digits K, I, S, P, A, O, N such that the square of KISS equals the decimal numberpassion. The puzzle can be described and solved in a fashion very similar to the problem above:

>>> {K,P} <: 1..9 & {I,S,A,O,N} <: 0..9 & (1000*K+100*I+10*S+S) * (1000*K+100*I+10*S+S) =1000000*P+100000*A+10000*S+1000*S+100*I+10*O+N & card({K, I, S, P, A, O, N}) = 7Existentially Quantified Predicate over K,P,I,S,A,O,N is TRUESolution:K = 2 &P = 4 &I = 0 &S = 3 &A = 1 &O = 8 &N = 9

ProB Validation for Siemens SAS

Situation

During the course of the European FP7 project Deploy, Siemens deployed the ProB software tocheck if it was feasible to use ProB to automatically check B models. These models were alreadyused in a production environment and related to the track topology and signal data. At that point intime, the properties in question took Siemens several weeks to manually check (about a man monthof effort).

Challenge

The challenge facing the STUPS team (Softwaretechnik und Programmiersprachen) at theUniversity of Düsseldorf is described in the Deploy Deliverable D41. Siemens sent the STUPS teamthe models for the San Juan case study on 8 July 2008. There were 23,000 lines of B spread over 79files, two of which were to be analysed: a simpler model and a hard model. It then took STUPS awhile to understand the models and get them through the new parser, the development of whichwas being finalised at the time.

Solution

ProB was able to analyse the simple model right away. One error in the assertions was discovered.Then ProB was improved so that the analysis of the difficult model was possible. The improvementsthat were made were not specific to the model in question, but were rather general improvementsthat benefited all ProB users. The results of the analysis were conclusive.

On 8 December 2008 the STUPS team were finally able to animate and validate the complicatedmodel. This revealed four errors. Note that the STUPS team were not told about the presence oferrors in the models (they were not even hinted at by Siemens), and initially STUPS believed thatthere was still a bug in ProB. In fact, the errors were genuine and they were exactly the same errors

96

Page 99: Modelling Examples

that Siemens had uncovered themselves by manual inspection.

Results

The results shows that ProB was a great success. Instead of taking several weeks to inspect theproperties manually, ProB was able to check the properties in 4.15 seconds and the assertions in1017.7 seconds (around 17 minutes) using ProB 1.3.0. Performance tuning for the ProB software hascontinued. The assertion checking for the above model now takes less than one minute using thecurrent version of ProB.

Papers

More details can be found in these papers:

• FAC'2011

• FM'2009

• Formally Checking Large Data Sets in the Railways, 2012

Complicated Formula

Below we show the graphical visualisation of a complicated property by ProB’s graphical formulaviewer. The graphics are also available as pdf The property is the following one:

!iti_ztr.(iti_ztr: t_iti_ztr_pas =>  !(cv_ztr1,cv_ztr2).(cv_ztr1: t_cv_ztr & cv_ztr2: t_cv_ztr &  cv_ztr1: {aa,bb | aa: t_iti_ztr_pas & bb: t_cv_ztr &  bb:inv_iti_ztr_cv_liste_i[inv_iti_ztr_cv_deb(aa)..inv_iti_ztr_cv_fin(aa)]}[{iti_ztr}] &  cv_ztr2: {aa,bb | aa: t_iti_ztr_pas & bb: t_cv_ztr &  bb:inv_iti_ztr_cv_liste_i[inv_iti_ztr_cv_deb(aa)..inv_iti_ztr_cv_fin(aa)]}[{iti_ztr}] &  not(cv_ztr1 = cv_ztr2)  =>  inv_ztr_cv_pas_i(inv_iti_ztr_pas_i(iti_ztr)|->cv_ztr1)  |->inv_ztr_cv_pas_i(inv_iti_ztr_pas_i(iti_ztr)|->cv_ztr2)  :  dom(inv_cv_sens_orientation)))

It stems from a Siemens model for the automatic controller for Line 9 of Sao Paulo. The propertydefied validation using Atelier B or alternate methods.

Indeed, the property is related to routes from one zone controller to another one: each route isdecomposed into virtual blocks, each virtual block is linked with another virtual block by afunction, and each couple of blocks has a direction. This property checks the coherence of all theseitems. This property involves several large functions, with images of images of functions, and has adouble universal quantifier. All this lead to a proof tree and a goal size that is beyond thecapabilities of Atelier B.

97

Page 100: Modelling Examples

Sudoku Solved in the ProB REPLFor this example we try and solve a Sudoku using the REPL (Read-Eval-Print-Loop) of ProB only,without constructing any B machine. The REPL can either be started using probcli’s command -replor by starting the Eval Console in ProB Tcl/Tk.

We will use the new feature of the REPL (available in ProB 1.4) to introduce local variables with thelet construct. Below we have started the REPL using probcli -repl and also using the preference -pREPL_UNICODE TRUE to display the formula again using Unicode operators (warning: this can slowdown certain terminal applications). We also recommend you use the rlwrap tool available underUnix and Linux to start probcli, so that you have a command history. Every character following the>>> until the end of the line is typed by the user. The next line, starting with ⇝, shows the Unicoderendering of the ASCII expression or predicate typed by the user. The lines below then show theoutput computed by ProB; the responses are immediate (80 ms or less for all queries below on aMac Book Air).

probcli -repl -p REPL_UNICODE TRUEProB Interactive Expression and Predicate EvaluatorType ":help" for more information.

First let us define two useful values: the domain DOM for the numbers to be put inside the Sudokuand the group of indices SUBSQ which can be used to construct the 3x3 sub-squares:

>>> let DOM = 1..9 ⇝ 1 ‥ 9Expression Value ={1,2,3,4,5,6,7,8,9}>>> let SUBSQ = { {1,2,3}, {4,5,6}, {7,8,9} } ⇝ {{1,2,3},{4,5,6},{7,8,9}}Expression Value ={{1,2,3},{4,5,6},{7,8,9}}

Now let us encode in Diff1 and Diff2 sets of pairs of coordinates at which the values on the Sudoku

98

Page 101: Modelling Examples

board have to be different (because they lie on the same column or row respectively):

>>> let Diff1 = {x1,x2,y1,y2| y1:DOM & y2:DOM & x1:DOM & x2:DOM & x1<x2 & y1=y2} ⇝ {x1,x2,y1,y2|((((y1 ∈ DOM ∧ y2 ∈ DOM) ∧ x1 ∈ DOM) ∧ x2 ∈ DOM) ∧ x1 < x2) ∧ y1 = y2}Expression Value =#324:{(((1|->2)|->1)|->1),(((1|->2)|->2)|->2),...,(((8|->9)|->8)|->8),(((8|->9)|->9)|->9)}>>> let Diff2 = {x1,x2,y1,y2| y1:DOM & y2:DOM & x1:DOM & x2:DOM & x1=x2 & y1<y2} ⇝ {x1,x2,y1,y2|((((y1 ∈ DOM ∧ y2 ∈ DOM) ∧ x1 ∈ DOM) ∧ x2 ∈ DOM) ∧ x1 = x2) ∧ y1 < y2}Expression Value =#324:{(((1|->1)|->1)|->2),(((1|->1)|->1)|->3),...,(((9|->9)|->7)|->9),(((9|->9)|->8)|->9)}

We have not yet encoded that in each sub-square the values must also all be distinct. Nonetheless,let us try and solve the puzzle as it stands, by looking for a full board (of type DOM -→ (DOM -→ DOM))which has distinct values on each row and column:

>>> Board : DOM --> (DOM --> DOM) & !(x1,x2,y1,y2).((x1,x2,y1,y2):Diff1\/Diff2 =>Board(x1)(y1) /= Board(x2)(y2)) ⇝ ∃(Board).(Board ∈ DOM → (DOM → DOM) ∧ ∀(x1,x2,y1,y2).((((x1 ∈ ℤ ∧ x2 ∈ ℤ) ∧ y1 ∈ ℤ) ∧y2 ∈ ℤ) ∧ ((x1 ↦ x2) ↦ y1) ↦ y2 ∈ Diff1 ∪ Diff2 ⇒ Board(x1)(y1) ≠ Board(x2)(y2)))Existentially Quantified Predicate over Board is TRUESolution:  Board = {(1|->{(1|->1),(2|->2),(3|->3),(4|->4),(5|->5),(6|->6),(7|->7),(8|->8),(9|->9)}),(2|->{(1|->2),(2|->1),(3|->4),(4|->3),(5|->6),(6|->5),(7|->8),(8|->9),(9|->7)}),(3|->{(1|->3),(2|->4),(3|->1),(4|->2),(5|->7),(6|->8),(7|->9),(8|->5),(9|->6)}),(4|->{(1|->4),(2|->3),(3|->2),(4|->1),(5|->8),(6|->9),(7|->6),(8|->7),(9|->5)}),(5|->{(1|->5),(2|->6),(3|->7),(4|->8),(5|->9),(6|->1),(7|->2),(8|->3),(9|->4)}),(6|->{(1|->6),(2|->5),(3|->8),(4|->9),(5|->1),(6|->7),(7|->3),(8|->4),(9|->2)}),(7|->{(1|->7),(2|->8),(3|->9),(4|->5),(5|->2),(6|->3),(7|->4),(8|->6),(9|->1)}),(8|->{(1|->8),(2|->9),(3|->6),(4|->7),(5|->4),(6|->2),(7|->5),(8|->1),(9|->3)}),(9|->{(1|->9),(2|->7),(3|->5),(4|->6),(5|->3),(6|->4),(7|->1),(8|->2),(9|->8)})}

Now, we will try and complete the constraints and put pairs of co-ordinates within each sub-squareinto the variable Diff3, and computing the union of Diff1, Diff2 and Diff3:

99

Page 102: Modelling Examples

>>> let Diff3 = {x1,x2,y1,y2|#(s1,s2).(s1:SUBSQ & s2:SUBSQ & x1:s1 & x2:s1 & x1>=x2 &(x1=x2 => y1>y2) & y1:s2 & y2:s2 & (x1,y1) /= (x2,y2))} ⇝ {x1,x2,y1,y2|(((x1 ∈ ℤ ∧ x2 ∈ ℤ) ∧ y1 ∈ ℤ) ∧ y2 ∈ ℤ) ∧ (((x1 ≥ x2 ∧ (x1 = x2 ⇒ y1 >y2)) ∧ (x1 ↦ y1) ≠ (x2 ↦ y2)) ∧ ∃(s1,s2).(((((s1 ∈ SUBSQ ∧ s2 ∈ SUBSQ) ∧ x1 ∈ s1) ∧ x2 ∈s1) ∧ y1 ∈ s2) ∧ y2 ∈ s2))}Expression Value =#324:{(((1|->1)|->2)|->1),(((1|->1)|->3)|->1),...,(((9|->9)|->9)|->7),(((9|->9)|->9)|->8)}>>> let Diff = Diff1 \/ Diff2 \/ Diff3 ⇝ (Diff1 ∪ Diff2) ∪ Diff3Expression Value =#972:{(((1|->1)|->1)|->2),(((1|->1)|->1)|->3),...,(((9|->9)|->9)|->7),(((9|->9)|->9)|->8)}

A full Sudoku solution, with distinct values in each row, column and sub-square, can now be foundas follows:

>>> Board : DOM --> (DOM --> DOM) & !(x1,x2,y1,y2).((x1,x2,y1,y2):Diff =>Board(x1)(y1) /= Board(x2)(y2)) ⇝ ∃(Board).(Board ∈ DOM → (DOM → DOM) ∧ ∀(x1,x2,y1,y2).((((x1 ∈ ℤ ∧ x2 ∈ ℤ) ∧ y1 ∈ ℤ) ∧y2 ∈ ℤ) ∧ ((x1 ↦ x2) ↦ y1) ↦ y2 ∈ Diff ⇒ Board(x1)(y1) ≠ Board(x2)(y2)))Existentially Quantified Predicate over Board is TRUESolution:  Board = {(1|->{(1|->1),(2|->2),(3|->3),(4|->4),(5|->5),(6|->6),(7|->7),(8|->8),(9|->9)}),(2|->{(1|->4),(2|->5),(3|->6),(4|->7),(5|->8),(6|->9),(7|->1),(8|->2),(9|->3)}),(3|->{(1|->7),(2|->8),(3|->9),(4|->1),(5|->2),(6|->3),(7|->4),(8|->5),(9|->6)}),(4|->{(1|->2),(2|->1),(3|->4),(4|->3),(5|->6),(6|->5),(7|->8),(8|->9),(9|->7)}),(5|->{(1|->3),(2|->6),(3|->5),(4|->8),(5|->9),(6|->7),(7|->2),(8|->1),(9|->4)}),(6|->{(1|->8),(2|->9),(3|->7),(4|->2),(5|->1),(6|->4),(7|->3),(8|->6),(9|->5)}),(7|->{(1|->5),(2|->3),(3|->1),(4|->6),(5|->4),(6|->2),(7|->9),(8|->7),(9|->8)}),(8|->{(1|->6),(2|->4),(3|->2),(4|->9),(5|->7),(6|->8),(7|->5),(8|->3),(9|->1)}),(9|->{(1|->9),(2|->7),(3|->8),(4|->5),(5|->3),(6|->1),(7|->6),(8|->4),(9|->2)})}

Let us now try and add some additional constraints for certain pre-established positions on theboard, and put those into the variable P and require that the solution Board contains those values:

100

Page 103: Modelling Examples

>>> let P = {(1,1,7), (1,2,8), (1,3,1), (2,1,9)} ⇝ {((1↦1)↦7),((1↦2)↦8),((1↦3)↦1),((2↦1)↦9)}Expression Value ={((1|->1)|->7),((1|->2)|->8),((1|->3)|->1),((2|->1)|->9)}>>> Board : DOM --> (DOM --> DOM) & !(x1,x2,y1,y2).((x1,x2,y1,y2):Diff =>Board(x1)(y1) /= Board(x2)(y2)) & !(x,y,z).((x,y,z):P => Board(x)(y)=z) ⇝ ∃(Board).((Board ∈ DOM → (DOM → DOM) ∧ ∀(x1,x2,y1,y2).((((x1 ∈ ℤ ∧ x2 ∈ ℤ) ∧ y1 ∈ ℤ) ∧y2 ∈ ℤ) ∧ ((x1 ↦ x2) ↦ y1) ↦ y2 ∈ Diff ⇒ Board(x1)(y1) ≠ Board(x2)(y2))) ∧ ∀(x,y,z).(((x∈ ℤ ∧ y ∈ ℤ) ∧ z ∈ ℤ) ∧ (x ↦ y) ↦ z ∈ P ⇒ Board(x)(y) = z))Existentially Quantified Predicate over Board is TRUESolution:  Board = {(1|->{(1|->7),(2|->8),(3|->1),(4|->2),(5|->3),(6|->4),(7|->5),(8|->6),(9|->9)}),(2|->{(1|->9),(2|->2),(3|->3),(4|->1),(5|->5),(6|->6),(7|->4),(8|->7),(9|->8)}),(3|->{(1|->4),(2|->5),(3|->6),(4|->7),(5|->8),(6|->9),(7|->1),(8|->2),(9|->3)}),(4|->{(1|->1),(2|->3),(3|->2),(4|->4),(5|->6),(6|->5),(7|->8),(8|->9),(9|->7)}),(5|->{(1|->5),(2|->4),(3|->7),(4|->8),(5|->9),(6|->2),(7|->3),(8|->1),(9|->6)}),(6|->{(1|->6),(2|->9),(3|->8),(4|->3),(5|->1),(6|->7),(7|->2),(8|->4),(9|->5)}),(7|->{(1|->2),(2|->1),(3|->5),(4|->6),(5|->7),(6|->3),(7|->9),(8|->8),(9|->4)}),(8|->{(1|->3),(2|->6),(3|->4),(4|->9),(5|->2),(6|->8),(7|->7),(8|->5),(9|->1)}),(9|->{(1|->8),(2|->7),(3|->9),(4|->5),(5|->4),(6|->1),(7|->6),(8|->3),(9|->2)})}

You can visualise the solution using the show command of the REPL:

>>> :showNr prj1 prj21 1 [7,8,1,2,3,4,5,6,9]2 2 [9,2,3,1,5,6,4,7,8]3 3 [4,5,6,7,8,9,1,2,3]4 4 [1,3,2,4,6,5,8,9,7]5 5 [5,4,7,8,9,2,3,1,6]6 6 [6,9,8,3,1,7,2,4,5]7 7 [2,1,5,6,7,3,9,8,4]8 8 [3,6,4,9,2,8,7,5,1]9 9 [8,7,9,5,4,1,6,3,2]

Let us now check that inconsistencies are detected by our tool:

101

Page 104: Modelling Examples

>>> let P = {(1,1,7), (1,2,8), (1,3,1), (2,1,9), (2,2,9)} ⇝ {((1↦1)↦7),((1↦2)↦8),((1↦3)↦1),((2↦1)↦9),((2↦2)↦9)}Expression Value ={((1|->1)|->7),((1|->2)|->8),((1|->3)|->1),((2|->1)|->9),((2|->2)|->9)}>>> Board : DOM --> (DOM --> DOM) & !(x1,x2,y1,y2).((x1,x2,y1,y2):Diff =>Board(x1)(y1) /= Board(x2)(y2)) & !(x,y,z).((x,y,z):P => Board(x)(y)=z) ⇝ ∃(Board).((Board ∈ DOM → (DOM → DOM) ∧ ∀(x1,x2,y1,y2).((((x1 ∈ ℤ ∧ x2 ∈ ℤ) ∧ y1 ∈ ℤ) ∧y2 ∈ ℤ) ∧ ((x1 ↦ x2) ↦ y1) ↦ y2 ∈ Diff ⇒ Board(x1)(y1) ≠ Board(x2)(y2))) ∧ ∀(x,y,z).(((x∈ ℤ ∧ y ∈ ℤ) ∧ z ∈ ℤ) ∧ (x ↦ y) ↦ z ∈ P ⇒ Board(x)(y) = z))Existentially Quantified Predicate over Board is FALSE

Note, you can use the browse command :b to show the let definitions, and any other identifieravailable (in our case none, as we have not loaded any pre-existing B specification):

>>> :bAvailable SETS:Available CONSTANTS: []Available VARIABLES: []Available let definitions:  DOM = {1,2,3,4,5,6,7,8,9}  SUBSQ = {{1,2,3},{4,5,6},{7,8,9}}  Diff1 = #324:{(((1|->2)|->1)|->1),(((1|->2)|->2)|->2),...,...  Diff2 = #324:{(((1|->1)|->1)|->2),(((1|->1)|->1)|->3),...,...  Diff3 = #324:{(((1|->1)|->2)|->1),(((1|->1)|->3)|->1),...,...  Diff = #972:{(((1|->1)|->1)|->2),(((1|->1)|->1)|->3),...,...  P = {((1|->1)|->7),((1|->2)|->8),((1|->3)|->1),((2|->1...

Other useful REPL commands are:

• :t EXPR to display the type of an expression,

• :r to reload a previously loaded B specification (above we did not load any specification), and

• :q to quit the REPL.

Also, many commands available for probcli also work inside the REPL:

• -p PREF VALUE to set preference values, e.g., -p MAX_DISPLAY_SET 999 if you want the prettyprinter to display sets up until size 999 in full (above the sets Diff1,… were truncated as thedefault value is 100,

• -init to intialise a previously loaded specification,

• -animate Nr to animate a certain number of steps,

• -mc Nr to model check the specification, exploring at most Nr states.

= The Jobs Puzzle

Based on Michael Leuschel, David Schneider. Towards B as a High-Level Constraint ModelingLanguage. In Yamine Ait Amer, Klaus-Dieter Schewe (ed.): Abstract State Machines, Alloy, B, TLA,

102

Page 105: Modelling Examples

VDM, and Z, Springer Berlin Heidelberg, 8477: 101-116, 2014.

This puzzle was originally published in 1984 by Wos et al. [4] as part of a collection of puzzles forautomatic reasoners. A reference implementation of the puzzle, by one of the authors of the book,using OTTER[5].

The puzzle consists of eight statements that describe the problem domain and provide someconstraints on the elements of the domain. The problem is about a set of people and a set of jobs;the question posed by the puzzle is: who holds which job? The text of the puzzle as presented in"The jobs puzzle: A challenge for logical expressibility and automated reasoning."[6] is as follows:

• There are four people: Roberta, Thelma, Steve, and Pete.

• Among them, they hold eight different jobs.

• Each holds exactly two jobs.

• The jobs are: chef, guard, nurse, clerk, police officer (gender not implied), teacher, actor, andboxer.

• The job of nurse is held by a male.

• The husband of the chef is the clerk.

• Roberta is not a boxer.

• Pete has no education past the ninth grade.

• Roberta, the chef, and the police officer went golfing together.

What makes this puzzle interesting for automatic reasoners, is that not all the information requiredto solve the puzzle is provided explicitly in the text.

The puzzle can only be solved if certain implicit assumptions about the world are taken intoaccount, such as: the names in the puzzle denote gender or that some of the job names imply thegender of the person that holds it.

Shapiro’s Challenge

Shapiro[multiblock footnote omitted], following the original authors’ remarks, that formalizing thepuzzle was at times hard and tedious, identified three challenges posed by the puzzle with regard toautomatic reasoners. According to Shapiro, the challenges posed by the jobs puzzle are to:

• formalize it in a non-difficult, non-tedious way

• formalize it in a way that adheres closely to the English statement of the puzzle

• have an automated general-purpose commonsense reasoner that can accept that formalizationand solve the puzzle quickly.

Any formalization also needs to encode the implicit knowledge used to solve the puzzle for theautomatic reasoners while still trying to satisfy the aspects mentioned above. Addressing thischallenge makes this puzzle a good case-study for the expressiveness of B to formalize such aproblem.

103

Page 106: Modelling Examples

A Solution to the Jobs Puzzle using B

The B encoding of the puzzle uses plain predicate logic, combined with set theory and arithmetic.We will show how this enables a very concise encoding of the problem, staying very close to thenatural language requirements. Moreover, the puzzle can be quickly solved using the constraintsolving capabilities of ProB. Following the order of the sentences in the puzzle we will discuss oneor more possibilities to formalize them using B.

To express "There are four people: Roberta, Thelma, Steve, and Pete” we define a set of people, thatholds the list of names:

PEOPLE={"Roberta", "Thelma", "Steve", "Pete"}

We are using strings here to describe the elements of the set. This has the advantage, that theelements of the set are implicitly different.[7] Alternatively, we could use enumerated or deferredsets defined in the SETS section of a B machine. As stated above we need some additionalinformation that is not included in the puzzle to solve it. The first bit of information is that thenames used in the puzzle imply the gender. In order to express this information we create two sets,MALE and FEMALE which are subsets of PEOPLE and contain the corresponding names.

FEMALE={"Roberta", "Thelma"} & MALE={"Steve", "Pete"}

The next statement of the puzzle is: “among them, they hold eight different jobs”. This can beformalized in B using a function that maps from a job to the corresponding person that holds thisjob using a total surjection from JOBS to PEOPLE:

HoldsJob : JOBS -->> PEOPLE

Although redundant, as we will see below, to express “Among them, they hold eight different jobs”we can add the assertion that the cardinality of HoldsJob is 8. This is possible, because in Bfunctions and relations can be treated as sets of pairs, where each pair consists of an element of thedomain and the corresponding element from the range of the relation.

card(HoldsJob) = 8

Constraining the jobs each person holds, the puzzle states: “Each holds exactly two jobs”. To expressthis we use the inverse relation of HoldsJob, it maps a PERSON to the JOBS associated to her. Theinverse function or relation is expressed in B using the ~ operator. For readability we assign theinverse of HoldsJob to a variable called JobsOf. JobsOf is in this case is a relation, because, as statedabove, each person holds two jobs.

JobsOf = HoldsJob~

Because JobsOf is a relation and not a function, in order to read the values, we need to use B’s

104

Page 107: Modelling Examples

relational image operator. This operator maps a subset of the domain to a subset of the range,instead of a single value. To read the jobs Steve holds, the relational image of JobsOf is used asshown below:

JobsOf[{"Steve"}]

Using the JobsOf relation we can express the third sentence of the puzzle using a universallyquantified expression over the set PEOPLE. The Universal quantification operator (∀) is expressedin B using the ! symbol followed by the name of the variable that is quantified. This way ofexpressing the constraint is close to the original text of the puzzle, saying that the set of jobs eachperson holds has a cardinality of two.

!x.(x : PEOPLE => card(JobsOf[{x}]) = 2)

The fourth sentence assigns the set of job names to the identifier JOBS. This statement alsoconstraints the cardinality of HoldsJob to 8.

JOBS = {"chef", "guard", "nurse", "clerk", "police", "teacher", "actor", "boxer"}

The following statements further constrain the solution. First “The job of nurse is held by a male”,which we can express using the HoldsJob function and the set MALE by stating that the element ofPEOPLE that HoldsJob("nurse") points to is also an element of the set MALE.

HoldsJob("nurse") : MALE

Additionally, we add the next bit of implicit information, which is that typically a distinction ismade between actress and actor, and therefore the job name actor implies that it is held by a male.This information is formalized, similarly as above.

HoldsJob("actor") : MALE

The next sentence: “The husband of the chef is the clerk” contains two relevant bits of information,based on another implicit assumption, which is that marriage usually is between one female andone male. With this in mind, we know that the chef is female and the clerk is male. One possibilityis to do the inference step manually and encode this as:

HoldsJob("chef") : FEMALE & HoldsJob("clerk") : MALE

Alternatively, and in order to stay closer to the text of the puzzle we can add a function Husbandthat maps from the set FEMALE to the set MALE as a partial injection. We use a partial function,because we do not assume that all elements of FEMALE map to an element of MALE.

105

Page 108: Modelling Examples

Husband : FEMALE >+> MALE

To add the constraint using this function we state that the tuple of the person that holds the job aschef and the person that holds the job as clerk are an element of this function when treated as a setof tuples.

(HoldsJob("chef"), HoldsJob("clerk")) : Husband

The next piece of information is that “Roberta is not a boxer”. Using the JobsOf relation we canexpress this close to the original sentence, by stating: boxer is not one of Roberta’s jobs. This can beexpressed using the relational image of the JobsOf relation:

"boxer" /: JobsOf[{"Roberta"}]

The next sentence provides the information that “Pete has no education past the ninth grade”. Thisagain needs some contextual information to be useful in order to find a solution for thepuzzle[multiblock footnote omitted]. To interpret this sentence we need to know that the jobs ofpolice officer, teacher and nurse require an education of more than 9 years. Hence the informationwe get is that Pete does not hold any of these jobs. Doing this inference step we could, as above,state something along the lines of HoldsJob("police") /= "Pete", etc. for each of the jobs. The solutionused here, tries to avoid doing the manual inference step. Although we still need to provide theinformation needed to draw the conclusion that Pete does not hold any of these three jobs. Wecreate a set of those jobs that need higher education:

QualifiedJobs = {"police", "teacher", "nurse"}

Using the relational image operator we can now say that Pete is not among the ones that hold anyof these jobs. The relational image can be used to get the set of items in the range of function orrelation for all elements of a subset of the domain.

"Pete" /: HoldsJob[QualifiedJobs]

Finally, the last piece of information is that “Roberta, the chef, and the police officer went golfingtogether”, from this we can infer that Roberta, the chef, and the police officer are all differentpersons. We write this in B stating that the set of Roberta, the person that holds the job as chef, andthe person that is the police officer has cardinality 3, using a variable for the set for readability.

Golfers = {"Roberta", HoldsJob("chef"), HoldsJob("police")} & card(Golfers) = 3

By building the conjunction of all these statements, ProB searches for a valid assignment to thevariables introduced that satisfies all constraints, generating a valid solution that answers thequestion posed by the puzzle “who holds which job? ” in form of the HoldsJob function. The

106

Page 109: Modelling Examples

solution found by ProB is depicted below.

This satisfies, in our eyes, the challenges identified by Shapiro. In the sense that the formalization,is not difficult, although it uses a formal language. The elements of this language are familiar tomost programmers or mathematicians and it builds upon well understood and widely knownconcepts. The brevity of the solution shows that using an expressive high-level language it ispossible to encode the puzzle without having tedious tasks in order to be able to solve the puzzle atall. The encoding of the sentences follows the structure of the English statements very closely. Weavoid the use of quantification wherever possible and use set based expressions that relate closelyto the puzzle. We are able to encode the additional knowledge needed to solve puzzle in a straightforward way, that is also close to how this would be expressed as statements in English. Lastly it isworth to note that the formalization of “Each holds exactly two jobs” is the one furthest away fromthe English expression, using quantifications and set cardinality expressions.

Related Work

In his paper Shapiro discusses several formalizations of the puzzle with regard to the identifiedchallenges. A further formalization using controlled natural language and answer set programming(ASP) was presented in "The jobs puzzle: Taking on the challenge via controlled natural languageprocessing" by Schwitter et al.[8]

The first of the solutions discussed by Shapiro is a solution from the TPTP website, encoded as a setof clauses and translated to FOL. The main disadvantages of this encoding is that it requires 64clauses to encode the problem and many of them are needed to define equality among jobs andnames. This is in contrast to our B encoding using either enumerated sets or strings, where allelements are implicitly assumed to be different. Thus the user does not have to define the conceptof equality for simple atoms.

The second solution discussed by Shapiro uses SNePS[9], a common sense and natural languagereasoning system designed with the goal to “have a formal logical language that captured theexpressibility of the English language”[multiblock footnote omitted]. The language has a uniquename assumption and set arguments making the encoding simpler and less tedious. On the otherhand the lack of support for modus tolens requires rewriting some of the statements in order tosolve the puzzle.

The last formalization discussed by Shapiro uses Lparse and Smodles[10] which uses stable modelsemantics with an extended logic programming syntax. According to Shapiro several features ofLparse/Smodels are simmilar to those of SNePS. This formalization also simplifies the encoding ofthe puzzle, but according to Schwitter et al. both solutions still present a “considerable conceptualgap between the formal notations and the English statements of the puzzle”[multiblock footnoteomitted].

Schwitter et al. in their paper “The jobs puzzle: Taking on the challenge via controlled naturallanguage processing”[multiblock footnote omitted] present a solution to the jobs puzzle usingcontrolled natural language and a translation to ASP to solve the jobs puzzle in a novel way thatstays very close to the English statements of the puzzle and satisfying the challenges posed byShapiro. To avoid the mismatch between natural and controlled natural languages Schwitter et al.

107

Page 110: Modelling Examples

describe the use of a development environment that supports the user to input valid statementsaccording to the rules of the controlled language. A solution using a mathematical, but high levellanguage like B avoids this problems by having a formal and, for most, familiar language used toformalize the problem.

MACHINE JobsPuzzleSETS  P = {Roberta, Thelma, Steve, Pete};  J = {chef, guard, nurse, clerk, police, teacher, actor, boxer}

CONSTANTS PEOPLE, JOBS, MALE, FEMALE, HoldsJob, Husband, QualifiedJobs, GolfersPROPERTIES /* There are four people: Roberta, Thelma, Steve, and Pete. */ PEOPLE={Roberta, Thelma, Steve, Pete} & /* Implicit assumption, names denote gender */ FEMALE={Roberta, Thelma} & MALE={Steve, Pete} /* Among them, they hold eight different jobs. */ & HoldsJob : JOBS -->> PEOPLE /* Each holds exactly two jobs. */ & !x.(x : PEOPLE => card(HoldsJob|>{x}) = 2) & JOBS = {chef, guard, nurse, clerk, police, teacher, actor, boxer} /* The job of nurse is held by a male. */ & HoldsJob(nurse) : MALE /* Implicit assumption -> see slides (gender specific job-name (actor vs. actress?)*/ & HoldsJob(actor) : MALE /* The husband of the chef is the clerk. */ & Husband : FEMALE >+> MALE & (HoldsJob(chef), HoldsJob(clerk)) : Husband /* Roberta is not a boxer. */ & HoldsJob(boxer) /= Roberta /* Pete has no education past the ninth grade. */ & /* Implicit assumption, these jobs require higher education */ QualifiedJobs = {police, teacher, nurse} & Pete /: HoldsJob[QualifiedJobs] /* Roberta, the chef, and the police officer went golfing together. */ & Golfers = {Roberta, HoldsJob(chef), HoldsJob(police)} & card(Golfers) = 3END

108

Page 111: Modelling Examples

TrainSwitchingPuzzleThis model was developed to solve Puzzle Nr 40 from the book "My best mathematical and logicalpuzzles" by Martin Gardner. Using breadth-first, ProB takes about 5 seconds to find the shortestsolution leading to a state satisfying the GOAL predicate. The trace consists of 22 steps. Avisualisation of this trace can be found on YouTube.

MACHINE GardnerSwitchingPuzzle_v2/* v2 without a special PassThroughTunnel operation *//* Puzzle Nr 40 from My best mathematical and logical puzzles, Martin Gardner *//* written by Michael Leuschel, 2010 *//*We have ENGINE + two wagons A, BOnly ENGINE can go through tunnelLayout: ==ENGINE ======+======A======\  / |  | TUN  | NEL  | |  \ / ======================B======Task: move A to B's position and vice versa and return ENGINE to original position*/SETS TRAINS={engine,A,B}; TRACKS = {topleft,top_middle,bot_left,bot_middle,leftlink}DEFINITIONS GOAL == occ(topleft) = [engine] & occ(top_middle)=[B] & occ(bot_middle)=[A]CONSTANTS  link, restrictPROPERTIES  link = {topleft |->top_middle, leftlink |->top_middle,  top_middle |-> bot_middle, /* Tunnel */  bot_middle|-> bot_left, bot_middle |-> leftlink} &  restrict = (link*{{}}) <+  { (top_middle|->bot_middle) |-> {A,B} } /* A,B are not allowed to take thetunnel */VARIABLES occINVARIANT occ: TRACKS --> iseq(TRAINS) & !(t1,t2).(t1:TRACKS & t1/=t2 => ran(occ(t1)) /\ ran(occ(t2)) = {} ) & UNION(t).(t:TRACKS|ran(occ(t))) = TRAINS/* Sequence Order on Track Sections: ====1=2=3======+====1=2=3====\  / |  3 TUN  2 NEL  1 |

109

Page 112: Modelling Examples

  \ / ====3=2=1===========3=2=1====*/INITIALISATION occ := {topleft |-> [engine], top_middle |-> [A], bot_middle |->[B],  leftlink |-> <>, bot_left |-> <> }OPERATIONS  Move(Seq,T1,T2,Rest) = PRE Seq : iseq1(TRAINS) & Rest : iseq(TRAINS) &  occ(T1)= Rest^Seq & engine:ran(Seq) & T1|->T2 : link &  restrict((T1,T2)) /\ ran(Seq) = {} THEN  occ := occ <+ {T1 |-> Rest, T2 |-> (Seq^occ(T2))}  END;  MoveRev(Seq,T1,T2,Rest) = PRE Seq : iseq1(TRAINS) & Rest : iseq(TRAINS) &  occ(T1)= Seq^Rest & engine:ran(Seq) & T2|->T1 : link &  restrict((T2,T1)) /\ ran(Seq) = {} THEN  occ := occ <+ {T1 |-> Rest, T2 |-> (occ(T2)^Seq)}  ENDEND

[1] M. Leuschel and J. Bendisposto: Directed Model Checking for B: An Evaluation and New Techniques. In Proceedings SBMF'2010,LNCS 6527. Springer-Verlag, 2010 https://www3.hhu.de/stups/downloads/pdf/LeBe2010.pdf

[2] C.Baier and J.-P. Katoen. “Principles of Model Checking”, The MIT Press, 2008, pages 43-45.

<a id="_footnotedef_3">�</a>[<a anchor="_footnoteref_3">3</a>] The number of atoms generated for the search graph correspondsto the number of valuations of the respective LTL<sup>[e

[4] L. Wos, R. Overbeek, E. Lusk, and J. Boyle. Automated Reasoning: Introduction and Applications. Prentice-Hall, Englewood Cliffs,NJ, 1984.

[5] W. Mccune. Otter 3.3 reference manual, 2003.

[6] S. C. Shapiro. The jobs puzzle: A challenge for logical expressibility and automated reasoning. In AAAI Spring Symposium:Logical Formalizations of Commonsense Reasoning, 2011.

[7] This encoding allows us to input the puzzle directly into the ProB Logic Calculator.

[8] R. Schwitter. The jobs puzzle: Taking on the challenge via controlled natural language processing. Theory and Practice of LogicProgramming, 13:487–501, 7 2013.

[9] S. C. Shapiro and The SNePS Implementation Group. SNePS 2.7.1 User’s Manual. Department of Computer Science andEngineering University at Buffalo, The State University of New York, Dec. 2010.

[10] I. Niemelä, P. Simons, and T. Syrjänen. Smodels: A system for answer set programming. CoRR, cs.AI/0003033, 2000.

110