Computational Logic 
A ``Handson'' Introduction to Pure Logic Programming 
Examples: X, Im4u, A_little_garden, _, _x, _22
Examples: a, dog, a_big_cat, 23, 'Hungry man', []
Example: date(monday, Month, 1994)
Arguments can in turn be variables, constants and structures.
Term  Type  Main functor: 
dad  constant  dad/0 
time(min, sec)  structure  time/2 
pair(Calvin, tiger(Hobbes))  structure  pair/2 
Tee(Alf, rob)  illegal   
A_good_time  variable   
a + b  is the term  '+'(a,b)  if +/2 declared infix 
 b  is the term  ''(b)  if /1 declared prefix 
a < b  is the term  '<'(a,b)  if </2 declared infix 
john father mary  is the term  father(john,mary)  if father/2 declared infix 
Example:
meal(soup, beef, coffee) < . meal(First, Second, Third) < appetizer(First), main_dish(Second), dessert(Third).
Examples:
pet(spot) < . animal(spot) < . pet(X) < animal(X), barks(X). animal(barry) < . pet(X) < animal(X), meows(X). animal(hobbes) < .
Predicate pet/1 has three clauses. Of those, one is a fact and two are rules. Predicate animal/1 has three clauses, all facts.
The declarative meaning is the corresponding one in first order logic, according to certain conventions:
Example: the fact
animal(spot) <.
can be read as ``spot is an animal''.
Example: the rule
pet(X) < animal(X), barks(X).
can be read as ``X is a pet if it is an animal and it
barks''.
p p, ..., p
p q, ..., q
...
Example: the rules
pet(X) < animal(X), barks(X). pet(X) < animal(X), meows(X).
< pet(spot). 
< pet(X). 

asks whether spot is a pet.  asks: ``Is there an X which is a pet?'' 
animal(spot) <. animal(barry) <. animal(hobbes) <. 
pet(X) < animal(X), barks(X).
pet(X) < animal(X), meows(X). barks(spot) <. meows(barry) <. roars(hobbes) <. 
Example: given the program above and
the query < pet(X).
the system will try to find a
``substitution'' for X which makes pet(X) true.
: module(_,_,[bf]). (or : module(_,_,['bf/af']).)or, for ``user'' files, i.e., files that are not modules: : use_package(bf).
: module(_,_,[bf]). + the pet example code as in previous slides. 
Ciao 1.13 #0: Mon Nov 7 09:48:51 MST 2005 ? use_module(pets). yes ? pet(spot). yes ? pet(X). X = spot ? ; X = barry ? ; no ?
p p, ..., p
p q, ..., q ... 
E.g.:
A  B  
dog  dog  dog  dog  
X  a  a  a  
X  Y  Y  Y  
f(X, g(t))  f(m(h), g(M))  Xm(h), Mt  f(m(h), g(t))  f(m(h), g(t)) 
f(X, g(t))  f(m(h), t(M))  Impossible (1)  
f(X, X)  f(Y, l(Y))  Impossible (2) 
A  B  and  
f(X, g(T))  f(m(H), g(M))  Xm(a), Ha, Mb, Tb  f(m(a), g(b)) 
"  "  Xm(H), Mf(A), Tf(A)  f(m(H), g(f(A))) 
A  B  and  
f(X, g(T))  f(m(H), g(M))  Xm(H), TM  f(m(H), g(M)) 
p(X,X)p(f(Z),f(W))  p(X,X)  p(f(Z),f(W))  
Xf(Z), Xf(W)  X  f(Z)  
Xf(Z)  f(Z)f(W)  f(Z)  f(W) 
Xf(Z)  ZW  Z  W 
Xf(W), ZW 
p(X,f(Y))p(Z,X)  p(X,f(Y))  p(Z,X)  
XZ, f(Y)X  X  Z  
XZ  f(Y)Z  f(Y)  Z 
Xf(Y), Zf(Y) 
p(X,f(Y))p(a,g(b))  p(X,f(Y))  p(a,g(b))  
Xa, f(Y)g(b)  X  a  
Xa  f(Y)g(b)  f(Y)  g(b) 
fail 
p(X,f(X))p(Z,Z)  p(X,f(X))  p(Z,Z)  
XZ, f(X)Z  X  Z  
XZ  f(Z)Z  f(Z)  Z 
fail 
Example (two valid executions):
? pet(X). ? pet(X). X = spot ? ; X = barry ? ; X = barry ? ; X = spot ? ; no no ? ?
C: pet(X) < animal(X), barks(X).
C: pet(X) < animal(X), meows(X).
C: animal(spot) <.
C: animal(barry) <. C: animal(hobbes) <. 
C: barks(spot) <.
C: meows(barry) <. C: roars(hobbes) <. 
Clause  

pet(P)  pet(P)  C*  
pet(X)  animal(X), meows(X)  C*  
pet(barry)  meows(barry)  C  
pet(barry)       

C: pet(X) < animal(X), barks(X).
C: pet(X) < animal(X), meows(X).
C: animal(spot) <.
C: animal(barry) <. C: animal(hobbes) <. 
C: barks(spot) <.
C: meows(barry) <. C: roars(hobbes) <. 
Clause  

pet(P)  pet(P)  C*  
pet(X)  animal(X), barks(X)  C*  
pet(hobbes)  barks(hobbes)  ???  failure 
explore another branch (different choice in C* or C*) to find a solution.  
We take C instead of C:  
pet(P)  pet(P)  C*  
pet(X)  animal(X), barks(X)  C*  
pet(spot)  barks(spot)  C  
pet(spot)       
Example: query pet(X) with the
previous program generates this search tree
(the boxes represent the ``and'' parts [except leaves]):
Example: Consider query < animal(A), named(A,Name).
with:
animal(dog(barry)) < . named(dog(Name),Name) < .
Clause  

pet(P)  pet(P)  C*  P=X 
pet(X)  animal(X), barks(X)  C*  X=spot 
pet(spot)  barks(spot)  C  
pet(spot)       
Example: Consider query < pet(spot).
vs.
< pet(X).
or < add(s(0),s(s(0)),Z).
vs.
< add(s(0),Y,s(s(s(0)))).





resistor(power,n1) <.
resistor(power,n2) <. transistor(n2,ground,n1) <. transistor(n3,n4,n2) <. transistor(n5,ground,n4) <. 
inverter(Input,Output) < transistor(Input,ground,Output), resistor(power,Output). nand_gate(Input1,Input2,Output) < transistor(Input1,X,Output), transistor(Input2,ground,X), resistor(power,Output). and_gate(Input1,Input2,Output) < nand_gate(Input1,Input2,X), inverter(X, Output).
course(complog,Time,Lecturer, Location) < Time = t(wed,18:30,20:30), Lecturer = lect('M.','Hermenegildo'), Location = loc(new,5102).
course(complog, t(wed,18:30,20:30), lect('M.','Hermenegildo'), loc(new,5102)) <.
course(complog,Time,Lecturer, Location) < Time = t(wed,18:30,20:30), Lecturer = lect('M.','Hermenegildo'), Location = loc(new,5102).
resistor(r1,power,n1) <. transistor(t1,n2,ground,n1) <. resistor(r2,power,n2) <. transistor(t2,n3,n4,n2) <. transistor(t3,n5,ground,n4) <. inverter(inv(T,R),Input,Output) < transistor(T,Input,ground,Output), resistor(R,power,Output). nand_gate(nand(T1,T2,R),Input1,Input2,Output) < transistor(T1,Input1,X,Output), transistor(T2,Input2,ground,X), resistor(R,power,Output). and_gate(and(N,I),Input1,Input2,Output) < nand_gate(N,Input1,Input2,X), inverter(I,X,Output).
Traditional  Codd's Relational Model  
File  Relation  Table 
Record  Tuple  Row 
Field  Attribute  Column 


Relational Database  Logic Programming  
Relation Name  Predicate symbol  
Relation  Procedure consisting of ground facts  
(facts without variables)  
Tuple  Ground fact  
Attribute  Argument of predicate 

r_meet_s(,,) r(,,), s(,,).
r_joinX2_s(,,) r(,,,,), s(,,,,).
parent(X,Y) < father(X,Y). parent(X,Y) < mother(X,Y). ancestor(X,Y) < parent(X,Y). ancestor(X,Y) < parent(X,Z), parent(Z,Y). ancestor(X,Y) < parent(X,Z), parent(Z,W), parent(W,Y). ancestor(X,Y) < parent(X,Z), parent(Z,W), parent(W,K), parent(K,Y). ...
parent(X,Y) < father(X,Y). parent(X,Y) < mother(X,Y). ancestor(X,Y) < parent(X,Y). ancestor(X,Y) < parent(X,Z), ancestor(Z,Y).
less_or_equal(0,X) < nat(X).
less_or_equal(s(X),s(Y)) < less_or_equal(X,Y).
plus(0,X,X) < nat(X).
plus(s(X),Y,s(Z)) < plus(X,Y,Z).
plus(X,0,X) < nat(X).
plus(X,s(Y),s(Z)) < plus(X,Y,Z).
( Q s.t. X = Y*Q + Z and Z Y):
mod(X,Y,Z) < less(Z, Y), times(Y,Q,W), plus(W,Z,X).
less(0,s(X)) < nat(X).
less(s(X),s(Y)) < less(X,Y).
mod(X,Y,X) < less(X, Y).
mod(X,Y,Z) < plus(X1,Y,X), mod(X1,Y,Z).
ackermann(0,N) = N+1 ackermann(M,0) = ackermann(M1,1) ackermann(M,N) = ackermann(M1,ackermann(M,N1))
ackermann(0,N) = s(N) ackermann(s(M),0) = ackermann(M,s(0)) ackermann(s(M),s(N)) = ackermann(M,ackermann(s(M),N))
ackermann(0,N,s(N)) < . ackermann(s(M),0,Val) < ackermann(M,s(0),Val). ackermann(s(M),s(N),Val) < ackermann(s(M),N,Val1), ackermann(M,Val1,Val).
Formal object  Cons pair syntax  Element syntax 
.(a,[ ])  [a[ ]]  [a] 
.(a,.(b,[ ]))  [a[b[ ]]]  [a,b] 
.(a,.(b,.(c,[ ])))  [a[b[c[ ]]]]  [a,b,c] 
.(a,X)  [aX]  [aX] 
.(a,.(b,X))  [a[bX]]  [a,bX] 
member(a,[a]) <. member(b,[b]) <. etc.
member(X,[X]) <.
member(a,[a,c]) <. member(b,[b,d]) <. etc.
member(X,[X,Y]) <.
member(a,[a,c,d]) <. member(b,[b,d,l]) <.etc.
member(X,[X,Y,Z]) <.
member(X,[XY]) < list(Y).
member(a,[c,a]), member(b,[d,b]). etc.
member(X,[Y,X]).
member(a,[c,d,a]). member(b,[s,t,b]). etc.
member(X,[Y,Z,X]).
member(X,[YZ]) < member(X,Z).
This is still infinite we need to generalize more.
append([],Ys,Ys) < list(Ys).
append([XXs],Ys,[XZs]) < append(Xs,Ys,Zs).
It is clear that we will need to traverse the list Xs
For each element X of Xs, we must put X at the end of the rest of the Xs list already reversed:
reverse([XXs],Ys ) < reverse(Xs,Zs), append(Zs,[X],Ys).
How can we stop?
reverse([],[]) <.
reverse(Xs,Ys) < reverse(Xs,[],Ys).
reverse([],Ys,Ys) <.
reverse([XXs],Acc,Ys) < reverse(Xs,[XAcc],Ys).
binary_tree(void) < . binary_tree(tree(Element,Left,Right)) < binary_tree(Left), binary_tree(Right).
tree_member(X,tree(X,Left,Right)) < binary_tree(Left), binary_tree(Right). tree_member(X,tree(Y,Left,Right)) < tree_member(X,Left). tree_member(X,tree(Y,Left,Right)) < tree_member(X,Right).
pre_order(void,[]) <. pre_order(tree(X,Left,Right),Order) < pre_order(Left,OrderLeft), pre_order(Right,OrderRight), append([XOrderLeft],OrderRight,Order).


lt_member(X,[XY]) < list(Y). lt_member(X,[_T]) < lt_member(X,T). lt_member(X,tree(X,L,R)) < binary_tree(L), binary_tree(R). lt_member(X,tree(Y,L,R)) < lt_member(X,L). lt_member(X,tree(Y,L,R)) < lt_member(X,R).Lists only unify with the first two clauses, trees with clauses 35!
polynomial(X,X) <. polynomial(Term,X) < pconstant(Term). polynomial(Term1+Term2,X) < polynomial(Term1,X), polynomial(Term2,X). polynomial(Term1Term2,X) < polynomial(Term1,X), polynomial(Term2,X). polynomial(Term1*Term2,X) < polynomial(Term1,X), polynomial(Term2,X). polynomial(Term1/Term2,X) < polynomial(Term1,X), pconstant(Term2). polynomial(Term1^N,X) < polynomial(Term1,X), nat(N).
deriv(X,X,s(0)) <. deriv(C,X,0) < pconstant(C). deriv(U+V,X,DU+DV) < deriv(U,X,DU), deriv(V,X,DV). deriv(UV,X,DUDV) < deriv(U,X,DU), deriv(V,X,DV). deriv(U*V,X,DU*V+U*DV) < deriv(U,X,DU), deriv(V,X,DV). deriv(U/V,X,(DU*VU*DV)/V^s(s(0))) < deriv(U,X,DU), deriv(V,X,DV). deriv(U^s(N),X,s(N)*U^N*DU) < deriv(U,X,DU), nat(N). deriv(log(U),X,DU/U) < deriv(U,X,DU). ...

initial(q0) <. delta(q0,a,q1) <. delta(q1,b,q0) <. final(q0) <. delta(q1,b,q1) <. accept(S) < initial(Q), accept_from(S,Q). accept_from([],Q) < final(Q). accept_from([XXs],Q) < delta(Q,X,NewQ), accept_from(Xs,NewQ).
accept(S) < initial(Q), accept_from(S,Q,[]). accept_from([],Q,[]) < final(Q). accept_from([XXs],Q,S) < delta(Q,X,S,NewQ,NewS), accept_from(Xs,NewQ,NewS). initial(q0) <. final(q1) <. delta(q0,X,Xs,q0,[XXs]) <. delta(q0,X,Xs,q1,[XXs]) <. delta(q0,X,Xs,q1,Xs) <. delta(q1,X,[XXs],q1,Xs) <.
is represented by:
hanoi_moves( s(s(s(0))), [ move(a,b), move(a,c), move(b,c), move(a,b), move(c,a), move(c,b), move(a,b) ])
hanoi(s(0),Orig,Dest,_Help,[move(Orig, Dest)]) < . hanoi(s(N),Orig,Dest,Help,Moves) < hanoi(N,Orig,Help,Dest,Moves1), hanoi(N,Help,Dest,Orig,Moves2), append(Moves1,[move(Orig, Dest)Moves2],Moves).
hanoi_moves(N,Moves) < hanoi(N,a,b,c,Moves).