120 likes | 265 Views
CIA2326 Week3: Prolog: List Processing. Lee McCluskey Email lee@hud.ac.uk First term: http://scom.hud.ac.uk/scomtlm/cia2326/. Resume. You should know Basic Prolog operation, matching, basic backtracking, variable instantiation (to end of section 2 in notes.tex) This week:
E N D
CIA2326 Week3:Prolog: List Processing Lee McCluskey Email lee@hud.ac.uk First term: http://scom.hud.ac.uk/scomtlm/cia2326/
Resume • You should know Basic Prolog operation, matching, basic backtracking, variable instantiation (to end of section 2 in notes.tex) This week: • The Cut, list processes, recursive functions (to end of notes - sections 3,4, and 5) • Also consult the “extendednotes” flie in the same link as notes.tex
Lists Lists are a high level data structure a. [ bank, moorgate, old_street ] b. [ john, [ X, mary] ] c. placing( red_rum, [ 1, 4, u, 2, 1, f, 3 ] ) d. [ [ [ x, y ], z ] ] • A List is a sequence of TERMS • It has a HEAD (the first term in the list) and a TAIL (the LIST without the first term) • In Prolog we use a MIXFIX op [ _ | _ ] to decompose lists • The empty list is an ODD list – [ ]
Recursion • Typical recursive procedures have the following form: • Base Case to stop recursion • Recursive Case: process data, and recursively call procedure with data nearer the Base Case descendant(X,Y) :- parent(X,Y). /* - X has descendant Y if X is the parent of Y */ descendant(X,Y) :- parent(X,Z), descendant(Z,Y). /* - X has descendant Y if X is the parent of someone who has decendant Y */
List Processing • Virtually all list processing carried out in prolog contains the following Recursive Case: 'Break the input list down into its head and tail with an expression of the form '[ X | Y ]' . Process the head X. Recursively call this procedure with input list = tail Y .‘ Example: arg2 is the list arg1 with its elements doubled.. double_list([],[]). double_list([Head|Tail], [HeadD|TailD):- HeadD is 2*Head, double_list(Tail, TailD).
List Processing common functions % Succeeds if arg1 is a member of arg2, otherwise fails: member(X, [X|T]). member(X, [_|T]) :- member(X,T). % concatenates two lists together, arg3 = arg1 ++ arg2 append([],L, L). append([H|T],L, [H|CL]) :- append(T,L,CL). “_” is the anonymous variable – it matches like a variable, but we don’t need to remember what it matches with!
The Cut The cut is written '!'. It is a predicate with the following properties: • It always succeeds the first time it is invoked in an activation of a rule. • If on backtracking the cut is re-invoked, it not only fails the current rule activation BUT ALSO FAILS THE GOAL THAT ACTIVATED THE RULE. • It may be placed anywhere (as a predicate) in the body of a rule.
The Cut Consider a program with rules of the form (where A, B, C, X, Y ,Z are arbitrary predicates): X :- ... Y, Z, ... /* rule 1 */ A :- ... B, !, C, ... /* rule 2 */ Assume the following takes place: rule 1 is activated and its sub-goals succeed up to Y; Z is invoked and matches A, thereby activating rule 2; rule 2's sub-goals succeed past B and the cut; C fails (or succeeds but subsequently fails on backtracking); then the cut will cause the goal that activated the rule it is in, i.e. Z, to fail. Control will next backtrack in rule 1 and re- invoke Y.
The Cut – main use The procedures factorial(N, Fact), double_list(L1,L2), member(X,L), append(L1,L2,L3) are FUNCTIONAL – not relational. So any procedure which calls them should NEVER backtrack within them => we use the CUT to make them functional. factorial(0,1) :- !. factorial(N,Fact) :- X is N-1, factorial(X,Fact1), Fact is N*Fact1,!. append([],L, L). append([H|T],L, [H|CL]) :- append(T,L,CL).!.
Assert and Retract “assert(X)” will assert term X as a clause at the end of the program. “retract(X)” will succeed once it has removed a clause that matches with X. Thus Prolog programs can change themselves ;-) Eg Assert all the terms in a list as facts.. assert_list([]). Assert_list([H|T) :- assert(H), assert_list(T).
Formative Assessment I would like to see everyone in class do the following exercises before we move on: 1. sort(L,SL): Write a prolog program to sort a list of numbers into ascending order 2. appendall(LL,L): Write a prolog program to join a list of lists into one big list NB do not get a solution from somewhere else – do it yourself!
Summary • List processing functions are very important in Prolog – a list is a special kind of term. • The Cut stops backtracking within a clause. It is particularly useful to make procedures only give out ONE answer. • Prolog programs can store/remove ‘global data’ using assert and retract. • PRACTICAL: finish the “notes”