Search code examples
prologfailure-slice

Prolog - Rules are correct, but not outputting the way it's supposed to?


Clue

Four guests (Colonel Mustard, Professor Plum, Miss Scarlett, Ms. Green) attend a dinner party at the home of Mr. Boddy. Suddenly, the lights go out! When they come back, Mr Boddy lies dead in the middle of the table. Everyone is a suspect. Upon further examination, the following facts come to light:

  • Mr Boddy was having an affair with Ms. Green.
  • Professor Plum is married to Ms. Green.
  • Mr. Boddy was very rich.
  • Colonel Mustard is very greedy.
  • Miss Scarlett was also having an affair with Mr. Boddy.

There are two possible motives for the murder:

  • Hatred: Someone hates someone else if that other person is having an affair with his/her spouse.
  • Greed: Someone is willing to commit murder if they are greedy and not rich, and the victim is rich.

Part A: Write the above facts and rules in your Prolog program. Use the following names for the people: colMustard, profPlum, missScarlet, msGreen, mrBoddy. Be careful about how you encode (or don’t encode) symmetric relationships like marriage - you don’t want infinite loops! married(X,Y) :- married(Y,X) % INFINITE LOOP

?-suspect(Killer,mrBoddy)
Killer = suspect_name_1
Killer = suspect_name_2
etc.

Part B: Write a predicate, suspect/2, that determines who the suspects may be, i.e. who had a motive.

?-suspect(Killer,mrBoddy)
Killer = unique_suspect.

Part C: Add a single factto your database that will result in there being a unique suspect. Clearly indicate this line in your source comments so that it can be removed/added for grading.

?-suspect(Killer,mrBoddy)
Killer = unique_suspect.

Whenever I type in

suspect(Killer,mrBoddy).

I get

suspect(Killer,mrBoddy).
Killer = profPlum

I'm missing

Killer = colMustard.

Here's my source.

%8) Clue

%facts

affair(mrBoddy,msGreen).
affair(missScarlett, mrBoddy).
affair(X,Y) :- affair(X,Y), affair(Y,X).

married(profPlum, msGreen).
married(X,Y) :- married(X,Y), married(Y,X).

rich(mrBoddy).
greedy(colMustard).

%rules

hate(X,Y) :- married(X,Spouse), affair(Y,Spouse).
greed(X,Y) :- greedy(X), not(rich(X)), rich(Y).


%suspect

suspect(X,Y):- hate(X,Y).
suspect(X,Y):- greed(X,Y).

Solution

  • The problem is the recursive rules of the predicates affair/2 and married/2. Attempting to use them easily leads to an endless loop (i.e. until the stack memory is exhausted). You must use a different predicate in each case to represent that if X is having an affair with Y, then Y is having an affair with X. You also need to change your definition of the suspect/2 predicate to call those new predicates.

    To better understand why you get an endless loop, use the trace facilities of your Prolog system. Try:

    ?- trace, suspect(Killer, mrBoddy).
    

    and go step by step.