0
votes

For university exam revision, I came across a past paper question with a Prolog database with the following structures:

% The structure of a media production team takes the form
% team(Producer, Core_team, Production_assistant).
% Core_team is an arbitrarily long list of staff structures,
% but excludes the staff structures for Producer and
% and Production_assistant.
% staff structures represent employees and take the form
% staff(Surname,Initial,file(Speciality,Grade,CV)).
% CV is an arbitrarily long list of titles of media productions.

team(staff(lyttleton,h,file(music,3,[my_music,best_tunes,showtime])),
[staff(garden,g,file(musical_comedy,2,[on_the_town,my_music])),
staff(crier,b,file(musical_comedy,2,[on_the_town,best_tunes]))],
staff(brooke-taylor,t,file(music,2,[my_music,best_tunes]))).

team(staff(wise,e,file(science,3,[horizon,frontiers,insight])),
[staff(morcambe,e,file(science,3,[horizon,leading_edge]))],
staff(o_connor,d,file(documentary,2,[horizon,insight]))).

team(staff(merton,p,file(variety,2,[showtime,dance,circus])),
[staff(smith,p,file(variety,1,[showtime,dance,circus,my_music])),
staff(hamilton,a,file(variety,1,[dance,best_tunes]))],
staff(steaffel,s,file(comedy,2,[comedians,my_music]))).

team(staff(chaplin,c,file(economics,3,[business_review,stock_show])),
[staff(keaton,b,file(documentary,3,[business_review,insight])),
staff(hardy,o,file(news,3,[news_report,stock_show,target,now])),
staff(laurel,s,file(economics,3,[news_report,stock_show,now]))],
staff(senate,m,file(news,3,[business_review]))).

One of the rules I have to write is the following:

Return the initial and surname of any producer whose team includes 2 employees whose CVs include a production entitled ‘Now’.

This is my solution:

recurseTeam([],0).

recurseTeam[staff(_,_file(_,_,CV))|List],Sum):-
    member(now,CV),
    recurseTeam(List,Rest),
    Sum is Rest + 1.

query(Initial,Surname):-
    team(staff(Surname,Initial,file(Speciality,Grade,CV)),Core_team,Production_assistant),
    recurseTeam([staff(Surname,Initial,file(Speciality,Grade,CV)),Production_assistant|Core_team,Sum),
Sum >= 2.

The logic I have here is that I have a recursive predicate which takes each staff member in turn, and a match is found only if the CV list contains the production 'now', and as you can see it will return the Initial and Surname of a Producer if at least 2 employees CV contains the 'now' production.

So, at least as far as I can see, it should return the c,chaplin producer, right? Because this team has staff members who have CV's which contains the 'now' production.

But when I query it, e.g.

qii(Initial,Surname).

It returns 'false'.

When I remove the "member(now,CV)" predicate, it successfully returns all four producers. So it would seem the issues lies with this rule. Member is the built-in predicate for querying the contents of lists, and 'CV' is the list structure that is contained within the file structure of a staff structure.

Any ideas why this isn't working as I had expected?

Any suggestions on what else I could try here?

1

1 Answers

2
votes

You need one more clause for the recurseTeam predicate, namely for the case that the first argument is a non-empty list, but its first element is a file structure that does not contain now.

In the current version, recurseTeam simply fails as soon as it encounters such an element in the list.

One possible solution is to add the following third clause for recurseTeam:

recurseTeam([staff(_,_,file(_,_,CV))|List],Sum):-
    \+ member(now,CV),
    recurseTeam(List,Sum).

Alternatively, one can use a cut ! in the second recurseTeam clause after member(now,CV) and drop \+ member(now,CV) in the third clause. This is more efficient, since it avoids calling member(now,CV) twice. (Note, however, that this is a red cut – the declarative and the operational semantics of the program are no longer the same. Language purists may find this disturbing – "real programmers" don't care.)