1

Given facts such as:

  • Jake is smarter than Nik
  • Nik is smarter than Wes
  • Wes is smarter than Dik

Write a recursive program that will determine that Jake's is smarter than Dik's.

The solution that I have is:

smarter(jake, nik).
smarter(nik, wes).
smarter(wes, dik).
smarter(X, Y) :-
    smarter(X, Z),
    smarter(Z, Y).

The output:

?- smarter(jake, dik).
True

but when I swap it:

?- smarter(dik, jake)

The output will show "ERROR: Out of local stack" I need the output to show "False". How do I fix it?

Thanks

false
  • 10,264
  • 13
  • 101
  • 209
Cael
  • 556
  • 1
  • 10
  • 36
  • It's generally better to name your predicate differently than your facts. But you should run a `trace` and rerun your query and watch what happens. – lurker Feb 26 '15 at 11:16
  • shouldn't ?- smarter(dik, jake) shows false? I don't understand how it will goes on a loop. – Cael Feb 26 '15 at 11:42
  • Logically, if it's defined correctly, of course `smarter(dik, jake)` should show false. But you have a logic error. Your `smarter(X, Y)` is a circular definition. If you do a `trace`, like I suggested before, you'll see what happens. – lurker Feb 26 '15 at 11:58

1 Answers1

0

Your code can prove

        ?- smarter(jake, dik).

because using X = jake, Y = dik it founds a Z=nik such that smarter(jake,nik) (this is a fact) and then smarter(nik,dik), (this is proved considering X1=nik, Y1=dik, Z1=wes).

However, in order to prove

       ?- smarter(dik, jake).

with X =dik, Y=jake, prolog needs a Z such that smarter(dik, Z). However, there is no fact smarter(dik, Z). Then, the rule is applied again ... and you have the loop.

The idea to fix (at least this particular example) is to distinguish facts and rules:

isSmarter(jake, nik).
isSmarter(nik, wes).
isSmarter(wes, dik).

smarter(X, Y) :- isSmarter(X,Y).

smarter(X, Y) :-
    isSmarter(X, Z),
    smarter(Z, Y).

This should work.

RafaelCaballero
  • 1,555
  • 2
  • 17
  • 24
  • The most general goal `smarter(X, Y)` now fails. – false Feb 26 '15 at 14:46
  • 1
    Just need to add one more rule : smarter(X,Y):- isSmarter(X,Y). just after the facts. Then it works! – Cael Feb 26 '15 at 15:27
  • Be careful when explaining examples in Prolog not to get variables (start with capital letter) mixed up with atoms (start with lower case letter). So your `x = dik`, for example, should be `X = dik`, and `smarter(dik, z)` should be `smarter(dik, Z)`. We don't want to mislead the inquirers. ;) – lurker Feb 26 '15 at 21:13
  • Added the rule smarter(X, Y) :- isSmarter(X,Y). as Cael suggestes and changed the variable names to upper case as lurker indicates. – RafaelCaballero Feb 27 '15 at 12:04