LPN: reorg, split notes from exocortex page.
The exocortex page was getting unwieldy, this makes more sense.
This commit is contained in:
parent
36ed6df77f
commit
6d4fb673ef
|
@ -0,0 +1,97 @@
|
||||||
|
## Some basic syntax
|
||||||
|
|
||||||
|
```
|
||||||
|
property(name).
|
||||||
|
proposition.
|
||||||
|
/* rules */
|
||||||
|
head :- tail.
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
happy(yolanda).
|
||||||
|
listens2Music(mia).
|
||||||
|
listens2Music(yolanda):- happy(yolanda).
|
||||||
|
playsAirGuitar(mia):- listens2Music(mia).
|
||||||
|
playsAirGuitar(yolanda):- listens2Music(yolanda).
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rules
|
||||||
|
|
||||||
|
Conditional fact:
|
||||||
|
|
||||||
|
```
|
||||||
|
/* source */
|
||||||
|
listensToMusic(X) :- happy(X).
|
||||||
|
playsAirGuitar(X) :- listensToMusic(X).
|
||||||
|
happy(a).
|
||||||
|
/* interactive */
|
||||||
|
playsAirGuitar(a). /* true */
|
||||||
|
playsAirGuitar(b). /* false */
|
||||||
|
```
|
||||||
|
|
||||||
|
## KB5
|
||||||
|
|
||||||
|
```
|
||||||
|
loves(vincent,mia).
|
||||||
|
loves(marsellus,mia).
|
||||||
|
loves(pumpkin,honey_bunny).
|
||||||
|
loves(honey_bunny,pumpkin).
|
||||||
|
jealous(X,Y):- loves(X,Z), loves(Y,Z).
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that when you enter queries, sometimes it waits for you to enter something
|
||||||
|
(so far seems like a semi-colon finishes a query). For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
2 ?- jealous(vincent, W).
|
||||||
|
W = vincent
|
||||||
|
```
|
||||||
|
|
||||||
|
Output freezes there, waiting on input. Enter the semicolon:
|
||||||
|
|
||||||
|
```
|
||||||
|
2 ?- jealous(vincent, W).
|
||||||
|
W = vincent ;
|
||||||
|
W = marsellus.
|
||||||
|
```
|
||||||
|
|
||||||
|
Replacing both atoms with variable:
|
||||||
|
|
||||||
|
```
|
||||||
|
3 ?- jealous(A, B).
|
||||||
|
A = B, B = vincent ;
|
||||||
|
A = vincent,
|
||||||
|
B = marsellus ;
|
||||||
|
A = marsellus,
|
||||||
|
B = vincent ;
|
||||||
|
A = B, B = marsellus ;
|
||||||
|
A = B, B = pumpkin ;
|
||||||
|
A = B, B = honey_bunny.
|
||||||
|
```
|
||||||
|
|
||||||
|
This brings up something interesting: *jealous(A, A)* is always true:
|
||||||
|
|
||||||
|
```
|
||||||
|
4 ?- jealous(A, A).
|
||||||
|
A = vincent ;
|
||||||
|
A = marsellus ;
|
||||||
|
A = pumpkin ;
|
||||||
|
A = honey_bunny.
|
||||||
|
```
|
||||||
|
|
||||||
|
Can we fix that in the definitions?
|
||||||
|
|
||||||
|
```
|
||||||
|
jealous(X,Y):- loves(X,Z), loves(Y,Z), X \= Y.
|
||||||
|
```
|
||||||
|
|
||||||
|
Now:
|
||||||
|
|
||||||
|
```
|
||||||
|
9 ?- jealous(A, A).
|
||||||
|
false.
|
||||||
|
```
|
||||||
|
|
||||||
|
Re-reading a previous section, seems that ';' means "or".
|
|
@ -0,0 +1,50 @@
|
||||||
|
## Unification
|
||||||
|
|
||||||
|
Two terms unify if they are
|
||||||
|
1. The same term
|
||||||
|
2. They contain variables that can be uniformly instantiated such that the
|
||||||
|
resulting terms are equal.
|
||||||
|
|
||||||
|
Unification is foundational to Prolog.
|
||||||
|
|
||||||
|
`=/2` checks whether its two arguments unify:
|
||||||
|
|
||||||
|
```
|
||||||
|
12 ?- =(a, a).
|
||||||
|
true.
|
||||||
|
13 ?- =(a, b).
|
||||||
|
false.
|
||||||
|
```
|
||||||
|
|
||||||
|
*NB* variable assignment with `=`:
|
||||||
|
|
||||||
|
```
|
||||||
|
24 ?- vincent = X.
|
||||||
|
X = vincent.
|
||||||
|
25 ?- jealous(Y, X).
|
||||||
|
Y = vincent,
|
||||||
|
X = marsellus ;
|
||||||
|
Y = marsellus,
|
||||||
|
X = vincent ;
|
||||||
|
false.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lines
|
||||||
|
```
|
||||||
|
/* lines.pl */
|
||||||
|
vertical(line(point(X,Y),point(X,Z))).
|
||||||
|
horizontal(line(point(X,Y),point(Z,Y))).
|
||||||
|
```
|
||||||
|
|
||||||
|
Check this out:
|
||||||
|
|
||||||
|
```
|
||||||
|
39 ?- vertical(line(point(1, 7), P)).
|
||||||
|
P = point(1, _402).
|
||||||
|
```
|
||||||
|
|
||||||
|
The answer is structured: `_402` is a placeholder variable that means "any old
|
||||||
|
value of Y will do." This answer was derived solely through unification, and
|
||||||
|
didn't require logic (e.g. modus ponens) or any sort of mathematical
|
||||||
|
relationships. "Moreover, when a program is written that makes heavy use of
|
||||||
|
unification, it is likely to be extremely efficient."
|
|
@ -0,0 +1,24 @@
|
||||||
|
%% facts
|
||||||
|
child(anne,bridget).
|
||||||
|
child(bridget,caroline).
|
||||||
|
child(caroline,donna).
|
||||||
|
child(donna,emily).
|
||||||
|
|
||||||
|
%% rules
|
||||||
|
descend(X,Y) :- child(X,Y).
|
||||||
|
|
||||||
|
descend(X,Y) :- child(X,Z),
|
||||||
|
descend(Z,Y).
|
||||||
|
|
||||||
|
descend1(X,Y) :- child(X,Y).
|
||||||
|
descend1(X,Y) :- child(X,Z),
|
||||||
|
descend1(Z,Y).
|
||||||
|
|
||||||
|
descend2(X,Y) :- child(X,Y).
|
||||||
|
descend2(X,Y) :- descend2(Z,Y),
|
||||||
|
child(X,Z).
|
||||||
|
|
||||||
|
%% WARNING: non-terminating.
|
||||||
|
descend3(X,Y) :- child(X,Y).
|
||||||
|
descend3(X,Y) :- descend3(X,Z),
|
||||||
|
descend3(Z,Y).
|
|
@ -0,0 +1,2 @@
|
||||||
|
%% infinite recursion.
|
||||||
|
p :- p.
|
|
@ -0,0 +1,7 @@
|
||||||
|
directlyIn(natasha, irina).
|
||||||
|
directlyIn(olga, natasha).
|
||||||
|
directlyIn(katarina, olga).
|
||||||
|
|
||||||
|
in(X, Y) :- directlyIn(X, Y).
|
||||||
|
in(X, Y) :- directlyIn(X, Z),
|
||||||
|
in(Z, Y).
|
|
@ -0,0 +1,162 @@
|
||||||
|
## Recursion
|
||||||
|
|
||||||
|
Recursive definitions require that the recursive function isn't the first
|
||||||
|
clause, ex:
|
||||||
|
|
||||||
|
```
|
||||||
|
is_digesting(X,Y) :- just_ate(X,Y).
|
||||||
|
is_digesting(X,Y) :-
|
||||||
|
just_ate(X,Z),
|
||||||
|
is_digesting(Z,Y).
|
||||||
|
```
|
||||||
|
|
||||||
|
Recursive definition require a base ("escape") clause in addition to the
|
||||||
|
recursive clause.
|
||||||
|
|
||||||
|
### Rule ordering, goal ordering, and termination
|
||||||
|
|
||||||
|
Underlying vision for Prolog (and logic programming in general): the programmer
|
||||||
|
should be able to describe problems, and the computer derives the solution. The
|
||||||
|
programmer builds a knowledge base, then asks question of the computer.
|
||||||
|
|
||||||
|
Prolog's search order:
|
||||||
|
|
||||||
|
1. KB from top to bottom
|
||||||
|
2. Clauses from left to right
|
||||||
|
3. Backtracks on bad choices
|
||||||
|
|
||||||
|
This is somewhat of a procedural approach to declarative programming which may
|
||||||
|
affect the answer. Compare `descend1` with `descend2`:
|
||||||
|
|
||||||
|
```
|
||||||
|
child(anne,bridget).
|
||||||
|
child(bridget,caroline).
|
||||||
|
child(caroline,donna).
|
||||||
|
child(donna,emily).
|
||||||
|
|
||||||
|
descend1(X,Y) :- child(X,Y).
|
||||||
|
descend1(X,Y) :- child(X,Z),
|
||||||
|
descend1(Z,Y).
|
||||||
|
|
||||||
|
descend2(X,Y) :- descend2(Z,Y),
|
||||||
|
child(X,Z).
|
||||||
|
|
||||||
|
descend2(X,Y) :- child(X,Y).
|
||||||
|
```
|
||||||
|
|
||||||
|
Supposedly these give different answers, but `swipl` exploded on the latter...
|
||||||
|
and continuing reading, that's the point --- a warning to avoid left-recursive
|
||||||
|
rules.
|
||||||
|
|
||||||
|
The takeaway is that you can get the overall idea of how to write the program
|
||||||
|
by approaching the problem declaratively. Sensible goal orderings ensure
|
||||||
|
program / query termination: place the recursive definition last.
|
||||||
|
|
||||||
|
### Exercises
|
||||||
|
|
||||||
|
#### Exercise 3.1
|
||||||
|
|
||||||
|
In the text, we discussed the predicate
|
||||||
|
|
||||||
|
```
|
||||||
|
descend(X,Y) :- child(X,Y).
|
||||||
|
descend(X,Y) :- child(X,Z),
|
||||||
|
descend(Z,Y).
|
||||||
|
```
|
||||||
|
|
||||||
|
Suppose we reformulated this predicate as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
descend(X,Y) :- child(X,Y).
|
||||||
|
descend(X,Y) :- descend(X,Z),
|
||||||
|
descend(Z,Y).
|
||||||
|
```
|
||||||
|
|
||||||
|
Would this be problematic?
|
||||||
|
|
||||||
|
**A**: yes: there's no termination clause. See `descend3` in `descend.pl`.
|
||||||
|
|
||||||
|
#### Exercise 3.2
|
||||||
|
|
||||||
|
Do you know these wooden Russian dolls (Matryoshka dolls) where the smaller
|
||||||
|
ones are contained in bigger ones?
|
||||||
|
|
||||||
|
Ex katarina(olga(natasha(irina))).
|
||||||
|
|
||||||
|
First, write a knowledge base using the predicate `directlyIn/2` which encodes
|
||||||
|
which doll is directly contained in which other doll. Then, define a recursive
|
||||||
|
predicate `in/2`, that tells us which doll is (directly or indirectly)
|
||||||
|
contained in which other dolls. For example, the query `in(katarina,natasha)`
|
||||||
|
should evaluate to true, while `in(olga, katarina)` should fail.
|
||||||
|
|
||||||
|
```
|
||||||
|
directlyIn(natasha, irina).
|
||||||
|
directlyIn(olga, natasha).
|
||||||
|
directlyIn(katarina, olga).
|
||||||
|
|
||||||
|
in(X, Y) :- directlyIn(X, Y).
|
||||||
|
in(X, Y) :- directlyIn(X, Z),
|
||||||
|
in(Z, Y).
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Exercise 3.3
|
||||||
|
|
||||||
|
We have the following knowledge base:
|
||||||
|
|
||||||
|
```
|
||||||
|
directTrain(saarbruecken,dudweiler).
|
||||||
|
directTrain(forbach,saarbruecken).
|
||||||
|
directTrain(freyming,forbach).
|
||||||
|
directTrain(stAvold,freyming).
|
||||||
|
directTrain(fahlquemont,stAvold).
|
||||||
|
directTrain(metz,fahlquemont).
|
||||||
|
directTrain(nancy,metz).
|
||||||
|
```
|
||||||
|
|
||||||
|
That is, this knowledge base holds facts about towns it is possible to travel
|
||||||
|
between by taking a direct train. But of course, we can travel further by
|
||||||
|
chaining together direct train journeys. Write a recursive predicate
|
||||||
|
`travelFromTo/2` that tells us when we can travel by train between two towns.
|
||||||
|
For example, when given the query `travelFromTo(nancy,saarbruecken)` it should
|
||||||
|
reply yes.
|
||||||
|
|
||||||
|
```
|
||||||
|
travelFromTo(X, Y) :- directTrain(X, Y).
|
||||||
|
travelFromTo(X, Y) :- directTrain(X, Z),
|
||||||
|
travelFromTo(Z, Y).
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Exercise 3.4
|
||||||
|
|
||||||
|
Define a predicate `greater_than/2` that takes two numerals in the notation
|
||||||
|
that we introduced in the text (that is, `0`, `succ(0)`, `succ(succ(0))`, and
|
||||||
|
so on) as arguments and decides whether the first one is greater than the
|
||||||
|
second one. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
?- greater_than(succ(succ(succ(0))),succ(0)).
|
||||||
|
yes
|
||||||
|
?- greater_than(succ(succ(0)),succ(succ(succ(0)))).
|
||||||
|
no
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Exercise 3.5
|
||||||
|
|
||||||
|
Binary trees are trees where all internal nodes have exactly two children. The
|
||||||
|
smallest binary trees consist of only one leaf node. We will represent leaf
|
||||||
|
nodes as `leaf(Label)`. For instance, `leaf(3)` and `leaf(7)` are leaf nodes,
|
||||||
|
and therefore small binary trees. Given two binary trees B1 and B2 we can
|
||||||
|
combine them into one binary tree using the functor `tree/2` as follows:
|
||||||
|
`tree(B1,B2)`. So, from the leaves `leaf(1)` and `leaf(2)` we can build the
|
||||||
|
binary tree `tree(leaf(1),leaf(2))` . And from the binary trees
|
||||||
|
`tree(leaf(1),leaf(2))` and `leaf(4)` we can build the binary tree
|
||||||
|
`tree(tree(leaf(1), leaf(2)),leaf(4))`.
|
||||||
|
|
||||||
|
Now, define a predicate `swap/2`, which produces the mirror image of the binary
|
||||||
|
tree that is its first argument. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
?- swap(tree(tree(leaf(1), leaf(2)), leaf(4)),T).
|
||||||
|
T = tree(leaf(4), tree(leaf(2), leaf(1))).
|
||||||
|
yes
|
||||||
|
```
|
|
@ -0,0 +1,8 @@
|
||||||
|
numeral(0).
|
||||||
|
numeral(succ(X)) :- numeral(X).
|
||||||
|
|
||||||
|
%% add/3: add(X, Y, Z) -> X + Y = Z
|
||||||
|
add(0, X, X).
|
||||||
|
add(succ(X), Y, succ(Z)) :-
|
||||||
|
add(X, Y, Z).
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
%% Given facts.
|
||||||
|
directTrain(saarbruecken,dudweiler).
|
||||||
|
directTrain(forbach,saarbruecken).
|
||||||
|
directTrain(freyming,forbach).
|
||||||
|
directTrain(stAvold,freyming).
|
||||||
|
directTrain(fahlquemont,stAvold).
|
||||||
|
directTrain(metz,fahlquemont).
|
||||||
|
directTrain(nancy,metz).
|
||||||
|
|
||||||
|
%% Rules.
|
||||||
|
travelFromTo(X, Y) :- directTrain(X, Y).
|
||||||
|
travelFromTo(X, Y) :- directTrain(X, Z),
|
||||||
|
travelFromTo(Z, Y).
|
Loading…
Reference in New Issue