Exploring Lists and Backtracking in Prolog and Scheme
This guide dives into list operations and backtracking functionality in Prolog, paralleling them with concepts from Scheme. It covers the implementation of basic list functions like `car`, `cdr`, and `cons`, alongside the creation of predicate functions. The document showcases how Prolog utilizes anonymous variables for efficient variable handling and details a family tree example to illustrate backtracking. With practical Prolog queries, it emphasizes the distinct behavior of cut operators in preventing backtracking, demonstrating how logic paradigms adapt across programming languages.
Exploring Lists and Backtracking in Prolog and Scheme
E N D
Presentation Transcript
Recall lists in Scheme: • '(a b c) = (cons 'a (cons 'b (cons c '()))) • ls = (cons (car ls) (cdr ls)) • Want the same operations in Prolog: • [a, b, c] = .(a, .(b, .(c, []))) • car([X|Tail], X). • cdr([X|Tail], Tail). • cons(X, Tail, [X|Tail]). Prolog: Lists lists.P
Prolog: Lists Try it out: | ?- consult(lists). | ?- car([1,2,3], H). H = 1 | ?- cdr([1,2,3], T). T = [2,3] | ?- cons(1, [2,3], L). L = [1,2,3]
Prolog: Anonymous Variables • What really happens: • | ?- consult(lists). • ++Warning[XSB]: [Compiler] ./lists: Singleton • variable Tail in a clause of car/2 • ++Warning[XSB]: [Compiler] ./lists: Singleton variable X in a clause of cdr/2 • Problem: We're not using some variables: • car([X|Tail], X). % Tail unused • cdr([X|Tail], Tail). % X unused
Prolog: Anonymous Variables Solution: Anonymous variables car([X|_], X). % _ = whatever cdr([_|Tail], Tail).
Recall member? function (predicate) in Scheme: • (define member? • (lambda (a ls) • (cond ((null? ls) #f) • ((equal? a (car ls)) #t) • (else (member? a (cdr ls)))))) Prolog: Lists • Can also write it in ML: • fun member(a, nil) = false | • member(a, x::t) = • if a = x then true else member(a, t); • How about Prolog? • member(X, [X|_]). • member(X, [_|T]) :- member(X, T).
Recall family tree example: • parent(linda, simon). • parent(sam, simon). • parent(linda, sharon). • parent(sam, sharon). • female(sharon). • sister(S,X) :- parent(P,S), parent(P,X), • female(S). • | ?- sister(Who, simon). • Who = sharon; • Who = sharon Prolog: Backtracking and Cut • Look under the hood using trace:
| ?- trace. yes [trace] | ?- sister(Who, simon). (0) Call: sister(_h81,simon) ? % sister(S, X=simon) (1) Call: parent(_h148,_h81) ? % parent(P, S) (1) Exit: parent(linda,simon) ? % parent(P=linda, S=simon) (2) Call: parent(linda,simon) ? % parent(P=linda, X=simon) (2) Exit: parent(linda,simon) ? (3) Call: female(simon) ? % female(S=simon) (3) Fail: female(simon) ? (2) Redo: parent(linda,simon) ? % parent(P=linda, X=simon) (2) Fail: parent(linda,simon) ? % fail on redo (1) Redo: parent(linda,simon) ? % parent(P=linda, S=simon) (1) Exit: parent(linda,sharon) ? % parent(P=linda, S=sharon) (4) Call: parent(linda,simon) ? % parent(P=linda, X=simon) (4) Exit: parent(linda,simon) ? (5) Call: female(sharon) ? % female(S=sharon) (5) Exit: female(sharon) ? (0) Exit: sister(sharon,simon) ? % P=linda, X=simon, S=sharon Who = sharon; Prolog: Backtracking and Cut sister(S, X) :- parent(P,S), parent(P,X), female(S).
(0) Redo: sister(sharon,simon) ? (5) Redo: female(sharon) ? % female(S=sharon) (5) Fail: female(sharon) ? % fail on redo (4) Redo: parent(linda,simon) ? % parent(P=linda, X=simon) (4) Fail: parent(linda,simon) ? % fail on redo (1) Redo: parent(linda,sharon) ? % parent(P=linda, S=sharon) (1) Exit: parent(sam,simon) ? % parent(P=sam, S=simon) (6) Call: parent(sam,simon) ? % parent(P=sam, X=simon) (6) Exit: parent(sam,simon) ? (7) Call: female(simon) ? % female(S=simon) (7) Fail: female(simon) ? (6) Redo: parent(sam,simon) ? % parent(P=sam, X=simon) (6) Fail: parent(sam,simon) ? % fail on redo (1) Redo: parent(sam,simon) ? % parent(P=sam, S=simon) (1) Exit: parent(sam,sharon) ? % parent(P=sam, S=sharon) (8) Call: parent(sam,simon) ? % parent(P=sam, X=simon) (8) Exit: parent(sam,simon) ? (9) Call: female(sharon) ? % female(S=sharon) (9) Exit: female(sharon) ? (0) Exit: sister(sharon,simon) ? % P=sam, X=simon, S=sharon Prolog: Backtracking and Cut sister(S, X) :- parent(P,S), parent(P,X), female(S).
Prolog: Backtracking and Cut • We can view this process as a tree, where each branch represents a binding choice:
Prolog: Backtracking and Cut • We can view this process as a tree, where each branch represents a binding choice: X simon
Prolog: Backtracking and Cut X simon P linda S
Prolog: Backtracking and Cut X simon P linda S simon FAIL
Prolog: Backtracking and Cut Backtrack to most recent success: X simon P linda S
Prolog: Backtracking and Cut X simon P linda S sharon Succeed
Prolog: Backtracking and Cut User asks for more answers X simon P linda S sharon Succeed
Prolog: Backtracking and Cut Backtrack: no more choices for S X simon P linda S
Prolog: Backtracking and Cut Backtrack X simon P
Prolog: Backtracking and Cut X simon P sam S
Prolog: Backtracking and Cut X simon P sam S sharon Succeed
Cut (!) prevents backtracking: • sister(S,X) :- parent(P,S), parent(P,X), • female(S), !. % don't backtrack! • | ?- sister(Who, simon). • Who = sharon; • no Prolog: Backtracking and Cut • No longer a “pure” logic paradigm: we are exploiting sequential order.