Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly express inequality in prolog?

TL;DR: sibling(a,X) succeeds with the answer X = a, but sibling(a,a) fails.


I have the following Prolog file:

children(a, c).
children(a, d).
children(b, c).
children(b, d).

sibling(X, Y) :-
   X \== Y, A \== B,
   children(X, A), children(X, B),
   children(Y, A), children(Y, B).

It seems clear enough to me, two person are siblings if their parents are the same. Also, a person is not their own sibling.

But when I tried to run some queries on GNU Prolog, I get some strange results:

| ?- sibling(a, b).

true ? a

true

true

yes

This is the intended behavior. a and b are siblings. There are three results, which is a bit weird, but I assume Prolog is binding A = c, B = d and A = d, B = c.

| ?- sibling(a, a).

no

I think this means a and a are not siblings.

| ?- sibling(a, X).

X = a ? a

X = b

X = a

X = b

X = a

X = b

X = a

X = b

(15 ms) yes

This is where I got stuck: It says X = a, which means sibling(a,a) is true, but sibling(a,a) failed in the previous query!

I feel that I'm not understanding what \== actually does in Prolog.

What is happening, and how do I fix this?

like image 624
parchment Avatar asked Oct 31 '15 04:10

parchment


2 Answers

TL;DR: Use prolog-dif—or iso_dif/2 (on iso-prolog conforming systems like gnu-prolog)!


Good question, +1!

In fact, it's a question I have asked myself, and the answer has to do with logical-purity: logical purity is a central aspect of what makes Prolog as a language so special, as it enables you to:

  • describe—not prescribe
  • write code that is relational—not just functional
  • think in terms of problems / solutions—not the individual steps of the search process itself
  • operate on a higher level—not get lost in nitty-gritty details

Unlike many other programming languages, Prolog programs have both procedural semantics (defining the execution steps and their order) and declarative semantics (allowing you to state relations that should hold and let the Prolog processor find a proper way of execution by itself).

But, beware: Prolog has some features that, when used, ruin declarative semantics. To prevent this, try to structure your application into two parts: an impure shell for dealing with side-effects (input/output) and a logically pure base which comprises pure monotonic Prolog code.

like image 124
repeat Avatar answered Sep 20 '22 14:09

repeat


Try moving the inequality to the end of the predicate. Maybe it gives you true because it's not instantiated already.

sibling(X,Y):- children(X, A), children(X, B),
               children(Y, A), children(Y, B),
               X \== Y, A \== B.
like image 40
leoxs Avatar answered Sep 21 '22 14:09

leoxs