Add ch04, start working on ch05.

This commit is contained in:
Kyle Isom 2018-01-18 16:30:58 -08:00
parent 50dbc5f0c0
commit 5f9633349c
11 changed files with 318 additions and 3 deletions

View File

@ -1,4 +1,4 @@
## Some basic syntax
## Chapter 1: Some basic syntax
```
property(name).

View File

@ -1,4 +1,4 @@
## Unification
## Chapter 2: Unification
Two terms unify if they are
1. The same term

View File

@ -1,4 +1,4 @@
## Recursion
## Chapter 3: Recursion
Recursive definitions require that the recursive function isn't the first
clause, ex:

60
lpn/ch04/exercises.pl Normal file
View File

@ -0,0 +1,60 @@
%% Exercises from chapter 4
%%
%% Exercise 4.3 Write a predicate second(X,List) which checks whether X is the
%% second element of List .
second(X, [_, X|_]).
%% Exercise 4.4 Write a predicate swap12(List1,List2) which checks whether
%% List1 is identical to List2 , except that the first two elements are
%% exchanged.
swap12([X,Y|T], [Y,X|T]).
%% Exercise 4.5 Suppose we are given a knowledge base with the following
%% facts:
tran(eins,one).
tran(zwei,two).
tran(drei,three).
tran(vier,four).
tran(fuenf,five).
tran(sechs,six).
tran(sieben,seven).
tran(acht,eight).
tran(neun,nine).
%% Write a predicate listtran(G,E) which translates a list of German number
%% words to the corresponding list of English number words. For example:
%% listtran([eins,neun,zwei],X).
%% should give:
%% X = [one,nine,two].
%% Your program should also work in the other direction. For example, if you give it the query
%% listtran(X,[one,seven,six,two]).
%% it should return:
%% X = [eins,sieben,sechs,zwei].
%% (Hint: to answer this question, first ask yourself How do I translate the
%% empty list of number words?. Thats the base case. For non-empty lists, first
%% translate the head of the list, then use recursion to translate the tail.)
listtran([], []).
listtran([X|TX], [Y|TY]) :-
tran(X, Y),
listtran(TX, TY).
%% Exercise 4.6 Write a predicate twice(In,Out) whose left argument is a list,
%% and whose right argument is a list consisting of every element in the left
%% list written twice. For example, the query
%% twice([a,4,buggle],X).
%% should return
%% X = [a,a,4,4,buggle,buggle]).
%% And the query
%% twice([1,2,1,1],X).
%% should return
%% X = [1,1,2,2,1,1,1,1].
%% (Hint: to answer this question, first ask yourself What should happen when
%% the first argument is the empty list?. Thats the base case. For non-empty
%% lists, think about what you should do with the head, and use recursion to
%% handle the tail.)
twice([], []).
twice([X|T1], [X,X|T2]) :-
twice(T1, T2).

13
lpn/ch04/list.pl Normal file
View File

@ -0,0 +1,13 @@
member(X, [X|_]).
member(X, [_|T]) :- member(X, T).
memberr(X, X).
memberr(X, [X|_]).
memberr(X, [[H|T1]|T2]) :-
memberr(X, H);
memberr(X, T1);
memberr(X, T2).
memberr(X, [_|T]) :- member(X, T).
sameLen([], []).
sameLen([_|TA], [_|TB]) :- sameLen(TA, TB).

30
lpn/ch04/notes.md Normal file
View File

@ -0,0 +1,30 @@
## Chapter 4: Lists
Lists are enclosed in square brackets, and are finite sequences of elements.
Elements can be anything: `[mia, robber(yolanda), X, 2, mia]` or `[mia,
[vincent, jules], [butch, girlfriend(butch)]]` --- a list can contain other
lists.
Prolog lists use the standard head/tail vocabulary, and the decomposition operator is `|`:
```
[Head|Tail] = [mia, [vincent, jules], [butch, girlfriend(butch)]]
```
Note that the empty list behaves as one would think.
```
?- [X|Y] = [].
no
````
Arguments can be chained, such as `[X, Y | Z]`.
### The `member` function
```
member(X, [X|_]).
member(X, [_|T]) :- member(X, T).
```

39
lpn/ch04/practical.pl Normal file
View File

@ -0,0 +1,39 @@
%% 1. Write a 3-place predicate combine1 which takes three lists as arguments
%% and combines the elements of the first two lists into the third as follows:
%%
%% ?- combine1([a,b,c],[1,2,3],X).
%%
%% X = [a,1,b,2,c,3]
%%
%% ?- combine1([f,b,yip,yup],[glu,gla,gli,glo],Result).
%%
%% Result = [f,glu,b,gla,yip,gli,yup,glo]
combine1([], [], []).
combine1([X|TX], [Y|TY], [X,Y|TXY]) :- combine1(TX, TY, TXY).
%% Now write a 3-place predicate combine2 which takes three lists as arguments
%% and combines the elements of the first two lists into the third as follows:
%%
%% ?- combine2([a,b,c],[1,2,3],X).
%%
%% X = [[a,1],[b,2],[c,3]]
%%
%% ?- combine2([f,b,yip,yup],[glu,gla,gli,glo],Result).
%%
%% Result = [[f,glu],[b,gla],[yip,gli],[yup,glo]]
combine2([], [], []).
combine2([X|TX], [Y|TY], [[X, Y]|TXY]) :- combine2(TX, TY, TXY).
%% Finally, write a 3-place predicate combine3 which takes three lists as
%% arguments and combines the elements of the first two lists into the third
%% as follows:
%%
%% ?- combine3([a,b,c],[1,2,3],X).
%%
%% X = [j(a,1),j(b,2),j(c,3)]
%%
%% ?- combine3([f,b,yip,yup],[glu,gla,gli,glo],R).
%%
%% R = [j(f,glu),j(b,gla),j(yip,gli),j(yup,glo)]
combine3([], [], []).
combine3([X|TX], [Y|TY], [j(X,Y)|TXY]) :- combine3(TX, TY, TXY).

21
lpn/ch05/arith.pl Normal file
View File

@ -0,0 +1,21 @@
len([], 0).
len([_|T], N) :-
len(T, X),
N is X+1.
alen_([], A, A).
alen_([_|H], A, L) :-
A2 is A+1,
alen_(H, A2, L).
alen(X, L) :- alen_(X, 0, L).
max([], N, N).
max([H|T], N, M) :-
H > N,
max(T, H, M).
max([H|T], N, M) :-
H =< N,
max(T, N, M).
max([H|T], N) :-
max(T, H, N).

24
lpn/ch05/exercises.pl Normal file
View File

@ -0,0 +1,24 @@
%% Exercise 5.2
%%
%% 1. Define a 2-place predicate increment that holds only when its second
%% argument is an integer one larger than its first argument. For example,
%% increment(4,5) should hold, but increment(4,6) should not.
increment(A, B) :- B is A+1.
%% 2. Define a 3-place predicate sum that holds only when its third argument is
%% the sum of the first two arguments. For example, sum(4,5,9) should hold, but
%% sum(4,6,12) should not.
sum(X, Y, Z) :- Z is X+Y.
%% Exercise 5.3
%%
%% Write a predicate addone/2 whose first argument is a list of integers, and
%% whose second argument is the list of integers obtained by adding 1 to each
%% integer in the first list. For example, the query
%% ?- addone([1,2,7,2],X).
%% should give
%% X = [2,3,8,3].
addone([], []).
addone([X|TX], [Y|TY]) :-
Y is X+1,
addone(TX, TY).

74
lpn/ch05/notes.md Normal file
View File

@ -0,0 +1,74 @@
## Chapter 5: Arithmetic in Prolog
Prolog provides basic arithmetic operators.
Ex.
```
?- 8 is 6+2.
yes
?- 12 is 6*2.
yes
?- -2 is 6-8.
yes
?- 3 is 6/2.
yes
?- 1 is mod(7,2).
yes
?- X is 12/4.
X = 3.
```
The operators don't actually do arithmetic:
```
?- X = 2 + 3.
X = 2+3.
```
The default is just to do unification; `is` must be used. The arithmetic
expression must be on the RHS. This part of Prolog is a black box that
handles this, and isn't part of the normal KB and unification parts.
### Arithmetic and lists
A recursive list length calculator:
```
len([], 0).
len([_|T], N) :-
len(T, X),
N is X+1.
```
A tail-recursive length calculator:
```
alen_([], A, A).
alen_([_|H], A, L) :-
A2 is A+1,
alen_(H, A2, L).
alen(X, L) :- alen_(X, 0, L).
```
Standard notes about tail recursion efficiency apply here.
### Comparing integers
* *x < y* &rarr; `X < Y.`
* *x ≤ y* &rarr; `X =< Y.`
* *x = y* &rarr; `X =:= Y.`
* *x ≠ y* &rarr; `X =\= Y.`
* *x ≥ y* &rarr; `X >= Y`
* *x > y* &rarr; `X > Y`
Note the difference between `=` and `=:=`.
Let's write a `max` function:
```

54
lpn/ch05/practical.pl Normal file
View File

@ -0,0 +1,54 @@
%% Chapter 5 practical session
%%
%% The purpose of Practical Session 5 is to help you get familiar with Prologs
%% arithmetic capabilities, and to give you some further practice in list
%% manipulation. To this end, we suggest the following programming exercises:
%%
%% 1. In the text we discussed the 3-place predicate accMax which returned the
%% maximum of a list of integers. By changing the code slightly, turn this into
%% a 3-place predicate accMin which returns the minimum of a list of integers.
min([], N, N).
min([H|T], N, M) :-
H < N,
min(T, H, M).
min([H|T], N, M) :-
H >= N,
min(T, N, M).
min([H|T], N) :-
min(T, H, N).
%% 2. In mathematics, an n-dimensional vector is a list of numbers of length n.
%% For example, [2,5,12] is a 3-dimensional vector, and [45,27,3,-4,6] is a
%% 5-dimensional vector. One of the basic operations on vectors is scalar
%% multiplication . In this operation, every element of a vector is multiplied
%% by some number. For example, if we scalar multiply the 3-dimensional vector
%% [2,7,4] by 3 the result is the 3-dimensional vector [6,21,12] .
%%
%% Write a 3-place predicate scalarMult whose first argument is an integer,
%% whose second argument is a list of integers, and whose third argument is the
%% result of scalar multiplying the second argument by the first. For example,
%% the query
%% ?- scalarMult(3,[2,7,4],Result).
%% should yield
%% Result = [6,21,12]
scalarMult(_, [], []).
scalarMult(K, [H|T], R) :-
V is K * H,
scalarMult(K, T, [R|V]).
%% 3. Another fundamental operation on vectors is the dot product. This
%% operation combines two vectors of the same dimension and yields a
%% number as a result. The operation is carried out as follows: the
%% corresponding elements of the two vectors are multiplied, and the
%% results added. For example, the dot product of [2,5,6] and [3,4,1] is
%% 6+20+6 , that is, 32 . Write a 3-place predicate dot whose first
%% argument is a list of integers, whose second argument is a list of
%% integers of the same length as the first, and whose third argument is
%% the dot product of the first argument with the second. For example,
%% the query
%% ?- dot([2,5,6],[3,4,1],Result).
%% should yield
%% Result = 32