# More Simply Logical lab exercises chapter 3

The Prolog file to be used for these lab exercises is labs3b.pl.

• Describe and explain the two differences in behaviour between the predicates powerset and powerset1.

• Make powerset tail-recursive by adding an accumulator as extra argument.

1. The well-known 8-puzzle consists of 8 tiles and an empty space, organised in a square. A move consists in sliding a tile to the empty space. The objective is to reach the following position:
```   1 2 3
8   4
7 6 5
```
Such a position will be represented by a list
```       [XE/YE,X1/Y1,X2/Y2,X3/Y3,X4/Y4,X5/Y5,X6/Y6,X7/Y7,X8/Y8]
```
with the first pair denoting the coordinates of the empty space, X1/Y1 denoting the coordinates of tile 1, and so on. Coordinates 1/1 refer to the lower left square. The position above is thus represented by the list
```       [2/2,1/3,2/3,3/3,3/2,3/1,2/1,1/1,1/2]
```
• The 'Manhattan distance' is the sum of the horizontal and vertical distance between two squares. Write a predicate mandist(X1/Y1,X2/Y2,D) for calculating this distance.

• Write a predicate move_p(P1,P2) indicating whether position P2 can be reached from position P1 in a single move. Use the predicate mandist.

2. The predicate prove_e(Goal,Explanation) returns an explanation with the answer to a query:
```| ?- prove_e(student_of(S,T),Explanation).

S = paul,
T = peter,
Explanation = student_of(paul,peter)because(follows(paul,computer_science)because given)and(teaches(peter,computer_science)because given) ? ;

S = paul,

S = maria,
T = peter,
Explanation = student_of(maria,peter)because(follows(maria,ai_techniques)because given)and(teaches(peter,ai_techniques)because given) ? ;

no
```
Notice that because and and are declared as infix functors. Also notice that any predicate on which we use clause(Head,Body) should be declared as dynamic.

• Explanations can become long-winded when for instance the append-predicate is involved. Modify prove_e such that only the top-level call to such predicates is included in the explanation:
```| ?- prove_e(sublist1(SL,[a,b]),Explanation).

SL = [],
Explanation = sublist1([],[a,b])because append([],[a,b],[a,b])and append([],[a,b],[a,b]) ? ;

SL = [a],
Explanation = sublist1([a],[a,b])because append([],[a,b],[a,b])and append([a],[b],[a,b]) ? ;

SL = [a,b],
Explanation = sublist1([a,b],[a,b])because append([],[a,b],[a,b])and append([a,b],[],[a,b]) ? ;

SL = [],
Explanation = sublist1([],[a,b])because append([a],[b],[a,b])and append([],[b],[b]) ? ;

SL = [b],
Explanation = sublist1([b],[a,b])because append([a],[b],[a,b])and append([b],[],[b]) ? ;

SL = [],
Explanation = sublist1([],[a,b])because append([a,b],[],[a,b])and append([],[],[]) ? ;

no
```
Make use of the built-in predicate call(Goal) to prove goals without explaining them.

• Modify prove_e such that it can handle negation:
```| ?- prove_e(bachelor(X),Explanation).
X = peter,
Explanation = bachelor(peter)because(man(peter)because given)and(not married(peter)) ?
```

Back / Peter Flach