| Computational Logic |
| A ``Hands-on'' 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''.
pp
, ..., p
![]()
pq
, ..., 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 ... |
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)) | 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 | ||
| f(X, g(T)) | f(m(H), g(M)) | f(m(a), g(b)) | |
| " | " | f(m(H), g(f(A))) |
| A | B | ||
| f(X, g(T)) | f(m(H), g(M)) |
|
f(m(H), g(M)) |
| p(X,X) | p(f(Z),f(W)) | ||
| X | f(Z) | ||
| f(Z) | f(W) | ||
| Z | W | ||
| p(X,f(Y)) | p(Z,X) | ||
| X | Z | ||
| f(Y) | Z | ||
| p(X,f(Y)) | p(a,g(b)) | ||
| X | a | ||
| f(Y) | g(b) | ||
| fail |
| p(X,f(X)) | p(Z,Z) | ||
| X | 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 C C |
|
C C C |
|
|
|
Clause | |
|---|---|---|---|
| pet(P) | pet(P) | C |
|
|
pet(X |
animal(X |
C |
|
| pet(barry) | meows(barry) | C |
|
| pet(barry) | -- | -- | -- |
|
C
: pet(X) <- animal(X), barks(X).
C
: pet(X) <- animal(X), meows(X).
|
C C C |
|
C C C |
|
|
|
Clause | |
|---|---|---|---|
| pet(P) | pet(P) | C |
|
|
pet(X |
animal(X |
C |
|
| pet(hobbes) | barks(hobbes) | ??? | failure |
|
|
|||
|
We take C |
|||
| pet(P) | pet(P) | C |
|
|
pet(X |
animal(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 |
|
|
pet(X |
animal(X |
C |
|
| 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(M-1,1) ackermann(M,N) = ackermann(M-1,ackermann(M,N-1))
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 |
[a,b] |
| .(a,.(b,.(c,[ ]))) | [a |
[a,b,c] |
| .(a,X) | [a |
[a |
| .(a,.(b,X)) | [a |
[a,b |
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,[X
Y]) <- 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,[Y
Z]) <- member(X,Z).
This is still infinite
we need to generalize more.
append([],Ys,Ys) <- list(Ys).
append([X|Xs],Ys,[X|Zs]) <- 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([X|Xs],Ys ) <-
reverse(Xs,Zs),
append(Zs,[X],Ys).
How can we stop?
reverse([],[]) <-.
reverse(Xs,Ys) <- reverse(Xs,[],Ys).
reverse([],Ys,Ys) <-.
reverse([X|Xs],Acc,Ys) <- reverse(Xs,[X|Acc],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([X|OrderLeft],OrderRight,Order).
|
|
lt_member(X,[X|Y]) <- 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 3-5!
polynomial(X,X) <-. polynomial(Term,X) <- pconstant(Term). polynomial(Term1+Term2,X) <- polynomial(Term1,X), polynomial(Term2,X). polynomial(Term1-Term2,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(U-V,X,DU-DV) <- 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*V-U*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([X|Xs],Q) <- delta(Q,X,NewQ), accept_from(Xs,NewQ).
accept(S) <- initial(Q), accept_from(S,Q,[]).
accept_from([],Q,[]) <- final(Q).
accept_from([X|Xs],Q,S) <- delta(Q,X,S,NewQ,NewS),
accept_from(Xs,NewQ,NewS).
initial(q0) <-.
final(q1) <-.
delta(q0,X,Xs,q0,[X|Xs]) <-.
delta(q0,X,Xs,q1,[X|Xs]) <-.
delta(q0,X,Xs,q1,Xs) <-.
delta(q1,X,[X|Xs],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).