300 likes | 420 Views
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:
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