Understanding rules - false as answer

5.4k views Asked by At

I am new in Prolog and I was just thinking that why this rule giving me false result after one true.

likes(1,banana).
likes(1,mango).

test :- likes(1,banana),likes(1,mango).

?- test.  
true;  
false.

I want to know the reason behind this false.

1

There are 1 answers

2
aqua On BEST ANSWER

The way prolog works is by evaluating queries until a fail by negation.

Here, you've established two facts:

likes(1, banana). which says "1 likes banana"

likes(1, mango). which says "1 likes mango"

Then you have established a rule, which basically evaluates as:

left_hand_side :- right_hand_side. left_hand_side if right_hand_side

Evaluation of the rule as a query tries to match facts and returns true if it can, and false if it cannot match. One important thing to note is that, if specified, prolog will continue to match facts as long as rules evaluate to true.

So let's step through test :- likes(1,banana),likes(1,mango).

If test is run as a query, prolog first tries likes(1,banana) which is a previously established fact, and is true. Then, it moves on to likes(1,mango) which, again, is a fact, and is true. Prolog has then reached the end of the rule, and outputs true.

At this point, if you're not searching for more matches you can cut the query short and just have true. However, if you're looking for more (all) matches, prolog backtracks and tries to evaluate the rule again, searching for more matches.

However, since your rule is only matching "likes banana and likes mango" and we already matched likes(1,banana), when prolog backtracks and tries evaluating likes(1,banana) again, since we already matched it before, this time there is not another fact (in other words, 1 cannot "like" banana more than once, unless that has been defined) to match. So that's where the false comes from.

In your prolog interpreter you may be able to trace the execution of your program by typing trace. then running your query. My trace is given below:

| ?- trace
.
The debugger will first creep -- showing everything (trace)

(1 ms) yes
{trace}
| ?- test.
      1    1  Call: test ? 
      2    2  Call: likes(1,banana) ? 
      2    2  Exit: likes(1,banana) ? 
      3    2  Call: likes(1,mango) ? 
      3    2  Exit: likes(1,mango) ? 
      1    1  Exit: test ? 

true ? ;
      1    1  Redo: test ? 
      2    2  Redo: likes(1,banana) ? 
      2    2  Fail: likes(1,banana) ? 
      1    1  Fail: test ? 

(1 ms) no
{trace}
| ?-

One last thing to note: If, instead of pressing ; at the true ? prompt, had I pressed <ENTER>, the script would have finished with only the true.

I'm glad you asked this question 'cause it allowed me a tiny refresher on prolog, which I really like but haven't used in a long time.