2
woman(lisa).
woman(maggie).

parents(lisa  , homer, marge).
parents(maggie, homer, marge).

sister(X, Y) :-
   X \= Y,
   woman(X),
   parents(X, P, M),
   parents(Y, P, M).

When I ran the following query, I did not expect failure (but got it nonetheless).

?- sister(lisa, X).
false.                         % expected result: X = maggie

Why am I seeing this behavior?

repeat
  • 18,496
  • 4
  • 54
  • 166
Manuel W.
  • 65
  • 1
  • 6
  • `(\=)/2` is not a pure logical relation. Use the pure predicate `dif/2` instead. The problem with `(\=)/2` in a nutshell: `?- X \= Y, X = a, Y = b.` yields **false**, but `X = a, Y = b, X \= Y` **succeeds**. – mat Dec 21 '15 at 18:52

2 Answers2

1

Assuming that sister(X,Y) says that Y is a sister of X, you want woman(Y), not woman(X).

Re-arranging the rule makes it work (demo):

sister(X, Y):-
  woman(Y),
  parents(X, P, M),
  parents(Y, P, M),
  X \= Y.

The important thing in this re-arrangement is that the X \= Y term is moved to a point after both X and Y have been bound - X is given to the rule as input, and Y is bound through participation in woman(Y).

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • @ManuelW. It does not have to be the last one, it could be the second one (right after `woman(Y)` - [demo](http://ideone.com/P8v8Lg)). The important thing is that `Y` needs to be *bound* before the inequality check. – Sergey Kalinichenko Dec 21 '15 at 17:18
1

Stay pure! How? Use for expressing term inequality!

sister(X, Y) :-
   dif(X, Y),
   woman(X),
   parents(X, P, M),
   parents(Y, P, M).

Sample query:

?- sister(lisa, X).
X = maggie.

For more on dif/2 see also:

Community
  • 1
  • 1
repeat
  • 18,496
  • 4
  • 54
  • 166