Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
95 views

Prolog Programming Exercises1

The document provides 5 exercises for learning Prolog programming. It asks the reader to: 1) Define predicates for descendant, sibling, and uncle_or_aunt based on the genealogy code; 2) Analyze why reversing the order of clauses in the ancestor definition may cause non-termination; 3) Define a subsequence predicate; 4) Define an intersects predicate for lists with common elements; 5) Define a bfora predicate to replace all as with bs in nested lists. It also provides sample solutions for each exercise in Prolog code.

Uploaded by

atmroo9
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
95 views

Prolog Programming Exercises1

The document provides 5 exercises for learning Prolog programming. It asks the reader to: 1) Define predicates for descendant, sibling, and uncle_or_aunt based on the genealogy code; 2) Analyze why reversing the order of clauses in the ancestor definition may cause non-termination; 3) Define a subsequence predicate; 4) Define an intersects predicate for lists with common elements; 5) Define a bfora predicate to replace all as with bs in nested lists. It also provides sample solutions for each exercise in Prolog code.

Uploaded by

atmroo9
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 3

Prolog programming exercises

Exercise 1 Starting with the "genealogy" code, define new predicates for "descendant", "sibling" and "uncle_or_aunt". Add some more "parent" facts to the collection (perhaps from your own relatives) and test out the predicates you introduced. Exercise 2 Does the following definition of ancestor allow queries which fail to terminate? (Note that the order of the two clauses has been reversed from the original definition). You can of course experiment with prolog to get an answer, but try to understand why, independently of experiment.
ancestor(X,Y):-parent(X,Z),ancestor(Z,Y). ancestor(X,Y):-parent(X,Y).

(Note: this is a "trick question") Exercise 3 Define a predicate subsequence(L1,L2) which is satisfied by any pair of lists L1 and L2 which have the property that the elements of L1 occur in order in L2, but are not necessarily consecutive. For example subsequence([tues,wed,sat], [mon,tues,wed,thurs,fri,sat,sun]) should be true, but subsequence([thurs,wed],[mon,tues,wed,thurs,fri,sat,sun]) should fail. Exercise 4 Define a predicate intersects(L1,L2) which is satisfied by lists L1 and L2 provided that they have an element in common. Exercise 5 Define a predicate bfora(L1,L2) which is satisfied by lists L1 and L2 provided that L2 is obtained from L1 by replacing all occurrences of a in L1 by b, including occurrences in sub-lists, sub-sub-lists and so on. (It might be useful to use the built-in predicate atom, which is satisfied by an argument consisting of an atom, but not by a more complicated term such as a list.)

Solutions to prolog exercises

Sample solutions to first set of cs205 logic programming exercises Solution 1


descendant(X,Y):-ancestor(Y,X). sibling(X,Y):-parent(Z,X), parent(Z,Y), X\==Y. % uncle_or_aunt(X,Y) will be defined % to mean that X is the uncle or aunt of Y uncle_or_aunt(X,Y):-parent(Z,Y),sibling(Z,X).

Solution 2 A query may fail to terminate if some parent relationships are given which are cyclic (hence could not arise in reality). For example
parent(bob,ann). parent(ann,gaz). parent(gaz,bob). parent(hal,betty).

The query ancestor(bob,hal) causes an infinite loop. (It's a trick question because the original definition of "ancestor" also fails in this situation. So in a sense this reversal of the clauses does not make the definition any worse.) Under "normal circumstances" queries will terminate. To see this, you have to appreciate how prolog ever gets to apply the second clause in the definition of ancestor. (Since the first is recursive, only the second can allow computation to end.) What happens is that given the query such as
ancestor(bob,X).

prolog will in fact find all the descendants of bob using the first clause, without ever using the second to verify that they are all bob's descendants. Eventually the first clause will start to fail - when bob's youngest descendants are reached they fail the first subgoal of being parents. At that point, prolog can start backtracking, giving up on the use of the first clause and trying out the second, and it will eventually do so for all descendants of bob. Solution 3
subsequence([],L). % the empty list is a subsequence of anything subsequence([Head|Tail],[Head|Tail2]) :- subsequence(Tail,Tail2). % if the two lists have the same leading element % then the first is a subsequence of the second % provided that the first without its leading element % is a subsequence of the second without that leading % element subsequence(L1,[Head|Tail]) :- subsequence(L1,Tail). % L1 is a subsequence of L2 if it is a subsequence % of L2 minus its leading element

Solution 4 It is easy to do this by defining an auxiliary predicate intersect2 which is satisfied by two lists if the head of the first list belongs to the second.

intersect2([Head|Tail1],[Head|Tail2]). intersect2([Head|Tail1],[Head2|Tail2]) :intersect2([Head|Tail1],Tail2). intersects([Head|Tail],L) :- intersect2([Head|Tail],L). intersects([Head|Tail],L) :- intersect2(Tail,L).

Solution 5

bfora([],[]). bfora(a,b). bfora(X,X) :- atom(X). bfora([H1|T1],[H2|T2]) :- bfora(H1,H2), bfora(T1,T2).

The predicate also replaces the atom a by b (as well as just working on the contents of lists). The second and third clauses deal with atoms in particular, replacing a with b, or failing that replacing an arbitrary atom by itself. Note that if you reject the answer to a query such as
bfora([[q,a,w],[a,q,a],q,a,e],L).

which initially gives


L = [[q,b,w],[b,q,b],q,b,e] ? then you get offered alternatives in which the last a may not have been replaced by b. This is due to using the third clause instead of the second (where the first argument is a, so that the second should have been used.)

You might also like