Programming in Prolog

What will be covered?

A logic programming language is a notational system for writing logical statements together with specified algorithms for implementing inference rules.

family.pl program
/* If mother( X ,Y ) then parent( X ,Y ) */
parent( X , Y ) :- mother( X , Y ).
parent( X , Y ) :- father( X , Y ).

/* if parent( X ,Y ) and parent(Y,Z ) then grandparent( X ,Z ). */
grandparent( X , Z ) :- parent( X , Y ),parent(Y, Z ).

grandparent(sue, ann).   

Logical Operators

parent( X , Y ) :- mother( X , Y );  father( X , Y ).
parent( X , Y ) :- mother( X , Y ).
parent( X , Y ) :- father( X , Y ).

Execution model :  Unification, pattern matching and backtracking

/* facts */
mother(mary, ann).
mother(mary, joe).
mother(sue, mary ).
father(mike, ann).
father(mike, joe).

/* rules */
parent( X , Y ) :- mother( X , Y ).
parent( X , Y ) :- father( X , Y ).


/* Query */
?- parent( X , joe).
X = mary
true .

binding


Review of Recursion -- Divide and Conquer

Example - What is the length of a list?

Converting to Prolog
length( [ ], 0 ).
length([H | T], Acc) :-
length(T,Nx), 
Acc is Nx + 1 .
(note: length is build in and this code will cause an error.)

Executing length--

?- length ([ 1, 59, 49], X).


?- length ( jim, X).


?- length ( Jim, X).


What will happen if we change the order of the rules?
length2([H | T], Acc) :-
            Acc is Nx + 1, length2(T,Nx).
length2( [ ], 0 ).


Another example  -- writing code to implement set operations

A break in the logical Model : write -- is extra logical to provide I/O

?-  X = [1, 2, 3],  write( X  ), nl,  mymember(a, X ).
[1, 2, 3] ;
false.


?- mymember(a, X ), write( X  ), nl,  X = [1, 2, 3].
[a| _3] ;
[ _5, a| _7] ;
[ _5, _8, a| _9] ;
[ _5, _8, _11, a| _12] ;
[_5, _8, _11, _14, a| _15] ;

intersect( SetA, SetB, Intersection)

union( SetA, SetB Union)

addToSet( E, SetA, Result )

r1:  addToSet( X,L,L ) :- member( X, L ).  
r2:  addToSet( X,L,[X|L] ).

execution of addToSet



Declarative Meaning vs Procedural Meaning

What does GCD mean?  What are the axioms that define GCD?

Converting to Prolog.

 gcd( A, 0, A ).
 
gcd( A, B, D ) :- (A<B), gcd( B, A, D ).
 gcd( A, B, D ) :- (A>B), (B>0),
R is A mod B, gcd( B, R, D ).
 
?- gcd( 24, 6, G).

Converting specification of  n!  to Prolog.

Recursive definition:
n! = n * ( n - 1)! 
0! = 1

factorial(0,1).
factorial(N, M):- N1 is N - 1,
factorial (N1, M1),
M is N*M1.

How does it work??  What is the binding?

Binding of values

Fibonacci Sequence

fibonacci_1( X , 1) :- X =< 2.
fibonacci_1( X , Y ) :- X > 2,
    X1 is X - 1,
    X2 is X - 2,     
    fibonacci_1( X 1, Y1),
    fibonacci_1( X 2, Y2),
    Y is Y1 + Y2.

Improvements for calculation speed.

fibonacci_2( 1, 1).
fibonacci_2( 2, 1).
fibonacci_2( X, Y ) :-  X > 2, X1 is X - 1, 
     X2 is X - 2,
     fibonacci_2( X1, Y1 ),
     fibonacci_2( X2, Y2 ),
     Y is Y1 + Y2,
     asserta(fibonacci_2( X,Y ))).
fibonacci_3( N, Fib):-  fib_aux( 2,  N, 1, 1, Fib ).
fib_aux ( N, N, F1, Fib, Fib ).
fib_aux ( M, N, F1, F2,  F )  :-  M < N,
    NextM is M + 1,           
    NextF2 is F1 + F2,
    fib_aux(NextM, N, F2, NextF2, F).

Cuts - used to control backtracking (procedural)

p( X ) :- q(X).
p( X) :- r( X, Y ), ! , s( Y ).
p( X ) :- t( X).
?- p(fred).

clause 2
 will be reach only if q(fred)  fails. If it reaches the cut symbol then it found the first solution to  r(fred,Y).  With the cut it will only solve s(Y) for the current instantiation of Y.  If s(Y) fails it will not try alternatives for r(fred,Y).  It will NOT even try the third clause!  Alternatives deviations that were created before the selection of the p(fred) literal are not discarded by the cut, the same for  alternatives created after the cut.

Red cuts and green cuts

f(N,0) :- N < 3.                                %rule 1
f(N,2) :- 3=< N, N < 6.                         %rule 2
f(N,4) :- 6 =< N.                               %rule 3
f(N,0) :- N < 3, !.                             %rule 1
f(N,2) :- 3=< N, N < 6,!.                       %rule 2
f(N,4) :- 6 =< N.                               %rule 3

f(N,0) :- N < 3, !.                             %rule 1 
f(N,2) :- N < 6, !.                             %rule 2
f(N,4) .                                        %rule 3


More on cuts
max(X, Y, Z) is true if Z is the maximum of X & Y

max(X,Y,X) :- X >= Y.
max(X,Y,Y) :- X < Y.

Green cuts, discards no solutions at all or discards only solutions of no interest.

maxGreen(X,Y,X) :- X >= Y, !.

maxGreen(X,Y,Y) :- X < Y.

Red cuts,  sometimes make it difficult to understand programs  but worse it may be incorrect in terms of the problem to be solved.

maxRed(X,Y,X) :- X >= Y, !.
maxRed(X,Y,Y).

Diagram of the effect of using cuts.

fragileZeros( [ ], 0).
fragileZeros([ 0 | T ], Z)  :- fragileZeros(T, Z1), Z is Z1 + 1.
fragileZeros( [ _ |T ], Z ) :- fragileZeros( T, Z ).


Fragile Zero example
Fragile Zero continued




zeros( [ ], 0).
zeros( [ 0 | T ], Z ) :�  zeros( T, Z1),  !,  Z is Z1 + 1.
zeros( [ _ | T ], Z ) :�  zeros( T, Z ).

Withcuts

Another example of cuts...  Beware of the order of subgoals!

haveCommonElts1( X ,Y ) :- mymember( E, X ),
   mymember( E, Y ).

haveCommonElts2( X ,Y ):- mymember( E, X ), 
  mymember( E,Y ), !.

? � haveCommonElts1( X , [1, 2, 3] ).
X = [1| _14];
X = [2| _14];
X = [3| _14];
X = [ _16, 1| _18];
X = [ _16, 2| _18];
X = [ _16, 3| _18];

? - haveCommonElts1( [1, 2, 3], Y ).
Y = [1| _33];
Y = [_35, 1 | _36];
Y = [_35, _39, 1 | _40]
...


Graphs in Prolog


Not!! Another break of the Logical Model

not(P) :- call(P), !, fail.
not(P).

alternatively:
not(P):� P, !, fail; true.

alternatively:
not(P):� P, !, fail.
not(P):-true.

test( S, T) :- S = T.

1?- test( 3, 5).


no


2?- test( 5, 5).


yes


3?- not( test( 5,5)).


no


4?- test( X,3), R is X+2.


X=3
R=5



5?- not( not( test( X,3))), R is X+2.


warning unbounded variable in arithmetic expression fail ...
/* When not(test(X,3)) fails the instantiation of X to 3 is released */
/* X instantiated to 0, then not( 0= 1) succeeds. */



6?-  X = 0, not( X=1).




/* X instantiated to 1, not( X=1) fails, the goal X = 0 is never reached */


8?- not( X=1 ),  X=0.





9. ?-
A=B, not(not(A=3)),B=5.

What do you think happens?




10?- A=3,not(not(A=3)), A=B, B=5

What do you think happens?


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

Findall

findall(+Template, :Goal, -Bag)                                   [ISO]
    Create  a list of the  instantiations Template gets successively  on
    backtracking  over Goal  and unify the  result with  Bag.   Succeeds
    with  an  empty  list  if Goal  has  no  solutions

Examples of uses:
?- findall(C, member(C,[1,2,3]), B).

?- findall(C, (member(C,[1,2,3,-4]),C>1), B).
B = [2, 3].

?- findall(I, (member(C,[10,2,13,5]), I is C+15, I>20), B).
B = [25, 28].
----------------------------------------

Other Extra-Logical Operators

Homoiconicity

is a property of some languages, in which the primary representation of programs is also a data structure of the language itself. This makes metaprogramming easier than in a language without this property.

?- D = (Exp is 44 // 7 ), call(D).
?- E = (Exp is 44 / 7), E.
?- L = (ten(X):-(X is 2*5)), write_canonical(L), assert(L), ten(A).  %% *1
?- listing(ten).
?- retract( (ten(X):-(X is 2*5))  ).
?- C = (newrule(E):-E is 44 // 7), assert(C).
?- newrule(X).


?- A=newrule, A(X).  #BAD
?-A =.. [newrule, X], A.
?- call(newrule, X).

*1) :- dynamic ten/1.  # must be at the top of the program file (OR put ten(A) in another query).

call/2
Append ExtraArg1, ExtraArg2, ... to the argument list of Goal and call the result. For example, call(plus(1), 2, X) will call plus(1, 2, X), binding X to 3.

?Term =.. ?List
List is a list whose head is the functor of Term and the remaining arguments are the arguments of the term. Either side of the predicate may be a variable, but not both. This predicate is called `Univ'.


Code related to these notes:
example.pl
intersect.pl
find.pl
sendMoreMoney.pl