300 likes | 435 Vues
This document delves into the control of execution within Prolog, particularly focusing on backtracking mechanisms. It outlines the use of the trace predicate to display variable instantiations during goal satisfaction, enhancing debugging efforts. It introduces important tools such as the fail predicate for forcing backtracking and the cut operator for preventing it. Examples illustrate how to utilize these concepts effectively in Prolog. Additionally, it addresses the structure and manipulation of lists in Prolog, including recursive techniques and computational efficiency through tail recursion.
E N D
Control of Execution& Lists CS321 Spring 2008
Trace • Prolog has a built-in predicate named trace • Displays the instantiations of values to variables at each step during the attempt to satisfy a given goal • Used to understand and debut Prolog programs
Trace • Using trace in gprolog: • Turn on with the command trace. • Turn off with the command notrace.
Trace • The tracing model: four events • Call, occurs at the beginning of an attempt to satisfy a goal • Exit, occurs when a goal has been satisfied • Redo, occurs when backtrack causes an attempt to re-satisfy a goal • Fail, occurs when a goal fails
Trace everybody. 1 1 Call: everybody ? 2 2 Call: father(_77,_38) ? 2 2 Exit: father(leonard,katherine) ? 3 2 Call: display(user_output,leonard) ? leonard 3 2 Exit: display(user_output,leonard) ? 4 2 Call: fail ? 4 2 Fail: fail ? 2 2 Redo: father(leonard,katherine) ? 2 2 Exit: father(carl,jason) ? 3 2 Call: display(user_output,carl) ? carl 3 2 Exit: display(user_output,carl) ? 4 2 Call: fail ? 4 2 Fail: fail ? 2 2 Redo: father(carl,jason) ? 2 2 Exit: father(carl,marilyn) ? 3 2 Call: display(user_output,carl) ? carl 3 2 Exit: display(user_output,carl) ? 4 2 Call: fail ? 4 2 Fail: fail ? 1 1 Exit: everybody ?
Control • In a logic programming language, to control the flow of execution, you must control the backtracking mechanism • Two tools: • the fail predicate, which is used to force backtracking • the cut (signified by !), which is used to prevent backtracking.
Example: failExample1-2.pro Clauses: father(leonard,katherine). father(carl,jason). father(carl,marilyn). everybody:- father(X,Y), display(user_output,’\n’), display(user_output, X). Goal: everybody. This is how you write to the screen in GNU Prolog. user_input is the keyboard user_output is the monitor. As written, Prolog will stop when the goal is satisfied with the first pattern match. Does not continue until you enter a ';' at the prompt.
fail • Although Prolog has a built-in backtracking mechanism, it is helpful to be able to force backtracking when the goal is written in a general form. • fail is a keyword provided for such control
Revised to use fail • See run of failExample_withFail1-2.pro father(leonard,katherine). father(carl,jason). father(carl,marilyn). everybody:- father(X,Y), display(user_output,’\n’), display(user_output, X), fail. Since the display is before the fail, the successful match is output before Prolog searches again. The fail causes prolog to seek a new match even though a match has already been found! All names are output without the user entering a ';' at the prompt.
Waits for the user to enter a value, then binds that value to the variable X. The value of X is now fixed. Input • Can read a value into a term using the read built-in predicate: father(leonard,katherine). father(carl,jason). father(jim,debbie). father(carl,marilyn). everybody:- display(user_output, ‘Enter:\n’), read(user_input, X), father(X,Y), display(user_output,’\n’), display(user_output, X).
cut • When Prolog finds a cut (the ! symbol) as a sub-goal, • the call to cut immediately succeeds, and • the next sub-goal (if there is one) is called. • Once a cut has been passed, • Cannot backtrack to sub-goals before the cut • Thus, a cut prevents backtracking.
Example • see buy_car1-2.pro and buy_car_withCut1-2.pro
Tail Recursion • Note that the factorial rule discussed earlier is not tail-recursive. • Must multiply after have unified the recursive call. factorial(0, 1). factorial(N, F) :- N > 0, N1 is N-1, factorial(N1,F1), F is N*F1. Not Tail Recursive! Computation is done here
Tail Recursion • Tail-recursive version factorial2(N, F, I, F) :- I > N. factorial2(N, F, I, Temp) :- I =< N, Temp2 is Temp * I, I2 is I + 1, !, factorial(N, F, I2, Temp2). • Use a helper function: fact(N, F) :- factorial2(N, F, 1, 1). Last predicate is the recursion Why not use I is I + 1? What is I used for? The cut keeps Prolog from recalculating
Example 2: the towers of IC /* Towers of Hanoi problem. */ hanoi(N) :- move(N, source, destination, spare). % why aren't source, destination, spare % capitalized?? report(X, Y) :- display(user_output,'Move top disk from the '), write(user_output,X), write(' peg to the '), write(Y), write(' peg.'), nl. % puts a carriage return in the output stream. move(0,_,_,_) :- !. move(N, Source, Destination, Spare) :- M is N - 1, move( ), report( ), move( ) move(M, Source, Spare, Destination), report(Source, Destination), move(M,Spare, Destination, Source).
Lists in Prolog • Enclosing syntax is brackets [...] • The notation [X|Y] refers to a list whose first element is X and whose tail is Y. • A finite list can be explicitly enumerated [1,2,3,4]
Scheme-like Facts • We can write facts in Prolog to give a syntax similar to Scheme car([X|Y],X). cdr([X|Y],Y). cons(X,R,[X|R]). • but these are un-necessary… (see following slides)
member rule • A versatile rule for working with lists: member(X,[X|R]). member(X,[Y|R]) :- member(X,R). • which means: • X is a member of a list whose first element is X. • X is a member of a list whose tail is R if it can be shown that X is a member of R.
Uses of member rule • test membership: GOAL member(2,[1,2,3]). yes • generate members of a list: GOAL member(X,[1,2,3]). X = 1 X = 2 X = 3
Sample Program • see prog6-1.pro
usage of member (continued) GOAL member([3,Y], [[1,a],[2,m],[3,z],[4,v],[3,p]]). Y = z Y = p • ... search to find elements paired with a specified element.
usage of member (continued) • … finding elements of a list which satisfy some constraint: GOAL member(X,[23,45,67,12,222,19,9,6]), Y = X*X, Y < 100. X = 9 Y = 81 X = 6 Y = 36 Note that the ‘=‘ symbol can be used here because it is a test for equality.
takeout rule takeout(X, [X|R], R). takeout(X, [F|R], [F|S]) :- takeout(X,R,S). • which means • When X is taken out of [X|R], R results. • When X is taken out of the tail of [X|R], [X|S] results, where S is the result of taking X out of R.
Example GOAL takeout;(X,[1,2,3],L). X=1 L=[2,3] X=2 L=[1,3] X=3 L=[1,2] takeout(X, [X|R], R). takeout(X, [F|R], [F|S]) :- takeout(X,R,S).
A different interpretation • 'takeout(X,Z,W)' can also be interpreted as "insert X into W to produce Z" GOAL takeout(3,W,[a,b,c]). W = [3,a,b,c] W = [a,3,b,c] W = [a,b,3,c] W = [a,b,c,3] • Obviously, 'takeout' got its name from just one of its uses.
append append([X|Y], Z, [X|W]) :- append(Y,Z,W). append([ ], X, X).
Examples GOAL append([1,2,3],[4,5],[1,2,3,4,5]). Yes GOAL append([1,2,3],[4,5],A). A = [1,2,3,4,5] GOAL append([1,2,3],W,[1,2,3,4,5]). W = [4,5] append([X|Y], Z, [X|W]) :- append(Y,Z,W). append([ ], X, X).
Examples • See append.pro
Reversing a List reverse([X|Y],Z,W) :- reverse( Y, [X|Z], W). reverse([ ], X, X). Example: GOAL reverse([1,2,3],[ ],A). A = [3, 2, 1]
Reversing a List Example: see reverse.pro