0% found this document useful (0 votes)
115 views15 pages

Recursion Techniques in Prolog

The document discusses recursion, including: - Recursion involves defining something in terms of itself and allows clear algorithm statements. - Examples of recursive definitions include lists and sorting algorithms. - Recursive predicates in Prolog include testing if a term is a list, finding ancestors in a family tree, and sorting lists. - Recursion works on both explicit structures like lists and binary trees, and implicit structures defined by predicates. - Building recursive structures in Prolog involves both breaking terms apart and putting them together through unification.

Uploaded by

Manish
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
115 views15 pages

Recursion Techniques in Prolog

The document discusses recursion, including: - Recursion involves defining something in terms of itself and allows clear algorithm statements. - Examples of recursive definitions include lists and sorting algorithms. - Recursive predicates in Prolog include testing if a term is a list, finding ancestors in a family tree, and sorting lists. - Recursion works on both explicit structures like lists and binary trees, and implicit structures defined by predicates. - Building recursive structures in Prolog involves both breaking terms apart and putting them together through unification.

Uploaded by

Manish
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Recursion

Prof. Geraint A. Wiggins


Centre for Cognition, Computation and Culture
Goldsmiths College, University of London

Contents
• Recursion in general
• Recursion in Prolog
• Recursion on explicit structures
• Recursion on implicit structures
• Building recursive structures
Recursion in general

• Recursion is the idea of defining something in


terms of itself

• It is very closely bound up with the idea of


mathematical induction

• It allows us to make very clear statements of


algorithms. . .

• . . . because it is a very natural way to think

• Optimisations mean that programming recursively


can be efficient, too

“Recursion”, CIS335: Logic Programming,


Goldsmiths’ College, London 2
Some Recursive Definitions

• In Prolog, a list is either an empty list or a term


connected by ‘.’ to another list

• Someone’s ancestor can be one of their parents or


an ancestor of one of their parents

• We can sort a list of numbers into order by picking


out the smallest, and then sorting the rest

• We can sort a list of numbers into order by picking


one, say X, dividing the rest into two groups,
bigger and smaller than X, and sorting the two
groups

• We can reverse a list of terms by taking the first


element off, reversing the rest, and putting the first
element on the end
“Recursion”, CIS335: Logic Programming,
Goldsmiths’ College, London 3
Some Recursive Predicates

• Test if a term is a list


list( [] ).
list( [ |Tail] ) :- list( Tail ).

• Find an ancestor
ancestor( Old, Young ) :-
parent( Old, Young ).
ancestor( Old, Young ) :-
parent( Old, Middle ),
ancestor( Middle, Young ).

• Sort a list of numbers


sort( [], [] ).
sort( List, [Smallest|Sorted] ) :-
\+ List = [],
smallest( List, Smallest, Rest ),
sort( Rest, Sorted ).

“Recursion”, CIS335: Logic Programming,


Goldsmiths’ College, London 4
Some Recursive Predicates

• Sort a list of numbers


sort( [], [] ).
sort( [First|Rest], Ans ) :-
split( First, Rest, Small, Big ),
sort( Small, Front ),
sort( Big, Back ),
append( Front, [First|Back], Ans ).

• Reverse a list
reverse( [], [] ).
reverse( [Head|Tail], Answer ) :-
reverse( Tail, RevTail ),
append( RevTail, [Head], Answer ).

“Recursion”, CIS335: Logic Programming,


Goldsmiths’ College, London 5
Recursion in Prolog

• When we want to write recursive programs, we


need to think about two things:
1. How will the program terminate?
2. How will the program break up the data it
works on?

• Recursion is an example of a divide-and-conquer


strategy

“Recursion”, CIS335: Logic Programming,


Goldsmiths’ College, London 6
Recursion in Prolog (2)

• To ensure that a program terminates, we must have


at least one base case – a non-recursive clause

• We must also ensure that something gets (in some


sense) ”reduced” each time a recursive step
happens, so that we can say when we have got to
the end

• Example – testing if a term is a list:


– The base case is when we have an empty list –
the smallest list possible
– The recursive case breaks down a non-empty
list into a head and a tail. . .
– . . . and then tests the tail, so the thing being
tested gets smaller each time.

“Recursion”, CIS335: Logic Programming,


Goldsmiths’ College, London 7
Recursion on explicit structures

• Testing if a term is a list


list( [] ).
list( [ |Tail] ) :- list( Tail ).

?- list( [a,b,c] ).

Call: list( [a,b,c] ).


Unify: [ |Tail] = [a,b,c]

Call: list( [b,c] ).


Unify: [ |Tail’] = [b,c]

Call: list( [c] ).


Unify: [ |Tail’’] = [c]

Call: list( [] ).

“Recursion”, CIS335: Logic Programming,


Goldsmiths’ College, London 8
Recursion on explicit structures (2)

• Example: a binary tree datatype:


– Leaves are of form leaf( value )
– Branches are of form
branch( Left, Right )

• Testing if a term is a binary tree


tree( leaf( X )).
tree( branch( X, Y )) :-
tree( X ),
tree( Y ).

• Note that we normally put the base case first, so


that Prolog tests it first!

“Recursion”, CIS335: Logic Programming,


Goldsmiths’ College, London 9
Recursion on implicit structures

• An implicit datatype is one where there is no


visible term structure to control recursion

• Instead, the step along the datatype is defined by a


predicate, eg parent/2

• Example: parent/2
parent( john, mary ).
parent( anne, mary ).
parent( mary, dave ).
parent( tim, dave ).

• This forms an implicit binary tree, and we can use


it to control recursion just like an explicit one

“Recursion”, CIS335: Logic Programming,


Goldsmiths’ College, London 10
Recursion on implicit structures (2)

• Example: ancestor/2
parent( john, mary ).
parent( anne, mary ).
parent( mary, dave ).
parent( tim, dave ).

ancestor( Old, Young ) :-


parent( Old, Young ).
ancestor( Old, Young ) :-
parent( Old, Middle ),
ancestor( Middle, Young ).

“Recursion”, CIS335: Logic Programming,


Goldsmiths’ College, London 11
Recursion on implicit structures (3)

• Example run:
?- ancestor( john, dave ).

Call: ancestor( john, dave ).


Call: parent( john, dave ).
Fail.

Retry: ancestor( john, dave ).


Call: parent( john, Middle ).
Unify: Middle = mary.
Succeed: parent( john, mary ).

Call: ancestor( mary, dave ).


Call: parent( mary, dave ).
Succeed: parent( mary, dave ).
Succeed: ancestor( mary, dave ).
Succeed: ancestor( john, dave ).

“Recursion”, CIS335: Logic Programming,


Goldsmiths’ College, London 12
Building recursive structures

• In Prolog, taking terms apart and building them


are nearly always the same thing.

• For example, in append/3:


append( [], List, List ).
append( [H|T], List, [H|BigList] ) :-
append( T, List, BigList ).

• Arguments 1 and 3 are both “broken down” or


“built up” by unification; we don’t usually use
both as inputs

• Exercise 2 shows how append/3 can be used


both to split up a list and to join lists together

• This is one reason why it is better not to think of


predicates as having “outputs” at all
“Recursion”, CIS335: Logic Programming,
Goldsmiths’ College, London 13
Building recursive structures (2)

• In the examples so far, the answer has been built


up in reverse of the breakdown of the input (no
matter which way round they are)

• Alternatively, we can use an accumulator


argument to build up an answer as we break down
the input

• Example, reverse/3:
reverse( [], Answer, Answer ).
reverse( [H|T], SoFar, Answer ) :-
reverse( T, [H|SoFar], Answer ).

?- reverse( List, [], Answer ).

(This is an example of tail-recursive optimisation.)

“Recursion”, CIS335: Logic Programming,


Goldsmiths’ College, London 14
Building recursive structures (3)

• Example run of reverse/3:


?- reverse( [a,b,c], [], Ans ).

Call: reverse( [a,b,c], [], Ans ).


Unify: [a,b,c] = [H|T], SoFar = []

Call: reverse( [b,c], [a], Ans ).


Unify: [b,c] = [H’|T’], SoFar’ = [a]

Call: reverse( [c], [b,a], Ans ).


Unify: [c] = [H’’|T’’], SoFar’’ = [b,a]

Call: reverse( [], [c,b,a], Ans ).


Unify: Ans = Answer, Answer = [c,b,a]

“Recursion”, CIS335: Logic Programming,


Goldsmiths’ College, London 15

You might also like