Use a rule if a fact doesn't exist in prolog? - prolog

I'm new to prolog.
The idea of my project is to say "The room X is free if none is a guest of X, while X is taken if a family lives in X".
I use a predicate
guest(FamilySurname,RoomTaken)
So this mean that a family has taken that room.
taken(X) :- guest(_,X).
So if a family lives in room X, then X is taken.
My problem is how could i say that the room X is free? I should use a kind of NOT, like:
free(X) :- "NOT EXIST" guest(_,X).
How could i translate that "NOT EXIST" in prolog?
I have tried with ! but it doesn't work properly... maybe I'm placing it in the wrong way.
Sorry for my english.

Check the following code:
taken(X, Y) :- guest(Y,X).
free(X) :- \+ guest(_,X).
I made the a little change to taken, now it shows you who is on that room.
guest(albert, 123).
?- taken(123, R).
R = albert.
And the free() predicate it's pretty straightforward, I used the negation operator, you can check How to negate in Prolog

The code in the first answer does not seem to be a solution, i.e. the query ?- free(X) will not give an answer, where as the query ?- free(foo) will be successful. One needs to consider query floundering in Prolog into account, i.e. all variables
Consider the following code in which two alternatives for presenting the free predicate.
room(123).
room(124).
guest(albert, 123).
taken(Room) :- guest(_, Room).
free2(Room) :- room(Room),
\+ taken(Room).
free(Room) :- room(Room),
forall(guest(_, RoomTaken),
RoomTaken \= Room).

Related

Prolog taking inverse of a predicate

I got a database that looks like
hasChild(person1, person2).
hasChild(person1, person3).
hasChild(person4, person5).
Which means that (for example) person1 has child named person2.
I then create a predicate that identifies if the person is a parent
parent(A):- hasChild(A,_).
Which identifies if the person is a parent, i.e. has any children
Then I try to create a predicate childless(A) that should return true if the user doesn't have any children which is basically an inverse of parent(A).
So I have 2 questions here:
a) is it possible to somehow take an "inverse" of a predicate, like childless(A):-not(parent(A)). or in any other way bypass this using the hasChild or any other method?
b) parent(A) will return true multiple times if the person has multiple children. Is it possible to make it return true only once?
For problem 1, yes. Prolog is not entirely magically delicious to some because it conflates negation and failure, but you can definitely write:
childless(X) :- \+ hasChild(X, _).
and you will see "true" for people that do not have children. You will also see "true" for vegetables, minerals, ideologies, procedures, shoeboxes, beer recipes and unfeathered bipeds. If this is a problem for you, a simple solution is to improve your data model, but complaining about Prolog is a very popular alternative. :)
For problem 2, the simplest solution is to use once:
parent(A) :- once(hasChild(A, _)).
This is a safer alternative to using the cut operator, which would look like this:
parent(A) :- hasChild(A, _), !.
This has a fairly significant cost: parent/1 will only generate a single valid solution, though it will verify other correct solutions. To wit:
?- parent(X).
X = person1.
Notice it did not suggest person4. However,
?- childless(person4).
true.
This asymmetry is certainly a "code smell" to most any intermediate Prolog programmer such as myself. It's as though Prolog has some sort of amnesia or selective hearing depending on the query. This is no way to get invited to high society events!
I would suggest that the best solution here (which handles the mineral/vegetable problem above as well) is to add some more facts about people. After all, a person exists before they have kids (or do they?) so they are not "defined" by that relationship. But continuing to play the game, you may be able to circumvent the problem using setof/3 to construct a list of all the people:
parent(Person) :-
setof(X, C^hasChild(X, C), People),
member(Person, People).
The odd expression C^hasChild(X, C) tells Prolog that C is a free variable; this ensures that we get the set of all things in the first argument of hasChild/2 bound to the list People. This is not first-order logic anymore folks! And the advantage here is that member/2 will generate for us as well as check:
?- parent(person4).
true.
?- parent(X).
X = person1 ;
X = person4.
Is this efficient? No. Is it smart? Probably not. Is it a solution to your question that also generates? Yes, it seems to be. Well, one out of three ain't bad. :)
As a final remark, some Prolog implementations treat not/1 as an alias for \+/1; if you happen to be using one of them, I recommend you not mistake compatibility with pre-ISO conventions for a jovial tolerance for variety: correct the spelling of not(X) to \+ X. :)
Here's another way you could do it!
Define everything you know for a fact as a Prolog fact, no matter if it is positive or negative.
In your sample, we define "positives" like person/1 and "negatives" like childless/1. Of course, we also define the predicates child_of/2, male/1, female/1, spouse_husband/2, and so on.
Note that we have introduced quite a bit of redundancy into the database.
In return, we got a clearer line of knowns/unknowns without resorting to higher-order constructs.
We need to define the right data consistency constraints:
% There is no person which is neither male nor female.
:- \+ (person(X), \+ (male(X) ; female(X))).
% Nobody is male and female (at once).
:- \+ (male(X), female(X)).
% Nobody is childless and parental (at once).
:- \+ (childless(X), child_of(_,X)).
% There is no person which is neither childless nor parental.
:- \+ (person(X), \+ (childless(X) ; child_of(_,X))).
% There is no child which is not a person.
:- \+ (child_of(X,_), \+ person(X)).
% There is no parent which is not a person.
:- \+ (child_of(_,X), \+ person(X)).
% (...plus, quite likely, a lot more integrity constraints...)
This is just a rough sketch... Depending on your use-cases you could do the modeling differently, e.g. using relations like parental/1 together with suitable integrity constraints. YMMY! HTH

Make a predicate reversible

I'm new to prolog; I'm coming from a structured programming background, as will become obvious :)
I am building up a prolog query that involves reversing a number; eg. reverse_num(123,X) results in X = 321. I came up with the following definition, but it only works when I provide a number as the first parameter.
reverse_num(Num, Revnum) :-
number_chars(Num, Atoms),
reverse(Revatoms, Atoms),
number_chars(Reversed, Revatoms),
Reversed = Revnum.
the number_chars/2 predicate doesn't like an unsubstantiated variable if I do: reverse_num(X,123) (where I'm expecting X to be 321).
Am I trying too hard to make reverse_num do something it shouldn't (should it be understood to work only with a number as the first parameter and variable as the second)?
Or is there an easy / straight-forward way to handle a variable as the first parameter?
Relational naming
Before jumping into coding, let's take a step back. After all, the idea in Prolog is to define relations. Your name reverse_num/2 rather suggests some actions, num_reversed/2 might be a better name.
Determine the relation
Your definition is not that bad, let me rewrite it to1:
num_reversed(Num, Reversed) :-
number_chars(Num, Chars),
reverse(Chars, Revchars),
number_chars(Reversed, Revchars).
?- num_reversed(123,X).
X = 321.
?- num_reversed(1230,X).
X = 321.
?- num_reversed(12300,X).
X = 321.
Do you see the pattern? All numbers N*10^I have the same result!
Now, let's ask some more:
?- num_reversed(Num, 321).
error(instantiation_error,number_chars/2).
Hm, what did we expect? Actually, we wanted all 123*10^I to be printed. That's infinitely many solutions. So above query, if correctly answered, would require infinitely many solutions to be printed. If we print them directly, that will take all our universe's lifetime, and more!
It is for this reason, that Prolog produces an instantiation error instead. By this, Prolog essentially states:
This goal is too general that I can make a good answer. Maybe there are infinitely many solutions, maybe not. I know not. But at least I indicate this by issuing an error. To remove this error you need to instantiate the arguments a bit more.
So the answer Prolog produced was not that bad at all! In fact, it is much better to produce a clean error than to, say, fail incorrectly. In general, Prolog's errors are often a very useful hint to what semantic problems you might have. See all error classes how.
Coroutining
As have other answers suggested, coroutining, using when/2 might solve this problem. However, coroutining itself has many semantic problems. Not without reason, systems like XSB do not offer it, due to the many problems related to subsumption checking. An implementation that would be compatible to it would be unexpectedly inefficient.
But for the sake of the point, we could make our definition more versatile by querying it like
?- when(nonvar(Num), num_reversed(Num, Reversed)).
when(nonvar(Num), num_reversed(Num, Reversed)).
Now we get back as an answer exactly the query we entered. This is also known as floundering. So there is a way to represent infinitely may solutions in a compact manner! However, this comes at a rather high price: You no longer know whether a solution exists or not. Think of:
?- when(nonvar(Num), num_reversed(Num, -1)).
when(nonvar(Num), num_reversed(Num, -1)).
Others have suggested to wait also for nonvar(Reversed) which would only be correct if we would produce infinitely many answers - but, as we have seen - this just takes too much time.
Coroutining looked as a very promising road at the beginning of the 1980s. However, it has never really caught on as a general programming methodology. Most of the time you get much too much floundering which is just a pain and even more difficult to handle than, say instantiation errors.
However, a more promising offspring of this development are constraints. There, the mechanisms are much cleaner defined. For practical purposes, programmers will only use existing libraries, like CLPFD, CLPQ, or CHR. Implementing your own library is an extremely non-trivial project in its own right. In fact it might even be possible to provide an implementation of num_reversed/2 using library(clpfd) that is, restricting the relation to the integer case.
Mode dependent conditionals
Traditionally, many such problems are solved by testing for instantiations explicitly. It is good style to perform this exclusively with nonvar/1 and ground/1 like the condition in when/2- other type test predicates lead easily to errors as exemplified by another answer.
num_reversed(Num, Reversed) :-
( nonvar(Num)
-> original_num_reversed(Num, Reversed)
; original_num_reversed(Reversed, Base),
( Base =:= 0
-> Num is 0
; length(_, I),
Num is Base*10^I
)
).
Above code breaks very soon for floats using base 2 and somewhat later for base 10. In fact, with classical base 2 floats, the relation itself does not make much sense.
As for the definition of number_chars/2, ISO/IEC 13211-1:1995 has the following template and mode subclause:
8.16.7.2 Template and modes
number_chars(+number, ?character_list)
number_chars(-number, +character_list)
The first case is when the first argument is instantiated (thus nonvar). The second case, when the first argument is not instantiated. In that case, the second argument has to be instantiated.
Note, however, that due to very similar problems, number_chars/2 is not a relation. As example, Chs = ['0','0'], number_chars(0, Chs) succeeds, whereas number_chars(0, Chs), Chs = ['0','0'] fails.
Very fine print
1 This rewrite is necessary, because in many Prologs reverse/2 only terminates if the first argument is known. And in SWI this rewrite is necessary due to some idiosyncratic inefficiencies.
The number_chars/2 predicate has the signature:
number_chars(?Number, ?CharList)
But although not fully specified by the signature, at least Number or CharList have to be instantiated. That's where the error occurs from.
If you call:
reverse_num(Num,123)
You will call number_chars/2 with both uninstatiated at that time so the predicate will error.
A not very nice solution to the problem is to ask whether Num or RevNum are number/2s. You can do this by writing two versions. It will furthermore filter other calls like reverse_num(f(a),b), etc.:
reverse_num(Num,Revnum) :-
\+ number(Num),
\+ number(Revnum),
throw(error(instantiation_error, _)).
reverse_num(Num, Revnum) :-
ground(Num),
number(Num),
!,
number_chars(Num, Atoms),
reverse(Revatoms, Atoms),
number_chars(Revnum, Revatoms).
reverse_num(Num, Revnum) :-
ground(Revnum),
number(Revnum),
reverse_num(Revnum,Num).
Or you can in case you use two nongrounds (e.g. reverse_num(X,Y).) an instantiation error instead of false as #false says:
reverse_num(Num,Revnum) :-
\+ number(Num),
\+ number(Revnum),
!,
throw(error(instantiation_error, _)).
reverse_num(Num, Revnum) :-
number(Num),
!,
number_chars(Num, Atoms),
reverse(Revatoms, Atoms),
number_chars(Revnum, Revatoms).
reverse_num(Num, Revnum) :-
reverse_num(Revnum,Num).
The cut (!) is not behaviorally necessary, but will increase performance a bit. I'm not really a fan of this implementation, but Prolog cannot always fully make predicates reversible since (a) reversibility is an undecidable property because Prolog is Turing complete; and (b) one of the characteristics of Prolog is that the body atoms are evaluated left-to-right. otherwise it will take ages to evaluate some programs. There are logic engines that can do this in an arbitrary order and thus will succeed for this task.
If the predicate/2 is commutative, a solution that can be generalized is the following pattern:
predicate(X,Y) :-
predicate1(X,A),
predicate2(A,B),
% ...
predicaten(C,Y).
predicate(X,Y) :-
predicate(Y,X).
But you cannot simply add the last clause to the theory, because it can loop infinitely.
Nice to see someone is also worried about define flexible rules with no restrictions in the set of bound arguments.
If using a Prolog system that supports coroutining and the when/2 built-in predicate (e.g. SICStus Prolog, SWI-Prolog, or YAP), try as:
reverse_num(Num, Reversed) :-
when( ( ground(Num); ground(Atoms) ), number_chars(Num, Atoms) ),
when( ( ground(Reversed); ground(Revatoms) ), number_chars(Reversed, Revatoms) ),
reverse(Atoms , Revatoms).
that gives:
?- reverse_num( 123, X ).
X = 321.
?- reverse_num( X, 123 ).
X = 321 .
( thanks to persons who provided theses answers: Prolog: missing feature? )
This SWISH session shows my effort to answer.
Then I've come back here, where I found I was on #PasabaPorAqui' mood (+1), but I didn't get it right.
But, such an interesting topic: notice how regular is the join pattern.
reverse_num(X, Y) :-
when((nonvar(Xs);nonvar(Ys)), reverse(Xs, Ys)),
when((nonvar(X) ;nonvar(Xs)), atomic_chars(X, Xs)),
when((nonvar(Y) ;nonvar(Ys)), atomic_chars(Y, Ys)).
So, we can generalize in a simple way (after accounting for PasabaPorAqui correction, ground/1 it's the key):
% generalized... thanks Pasaba Por Aqui
:- meta_predicate when_2(0).
when_2(P) :-
strip_module(P,_,Q),
Q =.. [_,A0,A1],
when((ground(A0);ground(A1)), P).
reverse_num(X, Y) :-
maplist(when_2, [reverse(Xs, Ys), atomic_chars(X, Xs), atomic_chars(Y, Ys)]).
I think I understand why nonvar/1 was problematic: the list bound for reverse get 'fired' too early, when just the head get bound... too fast !
maplist/2 is not really necessary: by hand we can write
reverse_num(X, Y) :-
when_2(reverse(Xs, Ys)),
when_2(atomic_chars(X, Xs)),
when_2(atomic_chars(Y, Ys)).
this seems an ideal application of term rewriting... what do you think about -:- ? Implementing that we could write bidirectional code like
reverse_num(X, Y) -:-
reverse(Xs, Ys),
atomic_chars(X, Xs),
atomic_chars(Y, Ys).
edit SWISH maybe is not 'term_rewrite' friendly... so here is a lower level approach:
:- op(900, xfy, ++).
A ++ B ++ C :- when_2(A), B ++ C.
A ++ B :- when_2(A), when_2(B).
reverse_num(X, Y) :-
reverse(Xs, Ys) ++ atomic_chars(X, Xs) ++ atomic_chars(Y, Ys).
Setting aside the problem of trailing zeroes turning into leading zeroes, it doesn't seem like it should be much more complicated than something like this (made somewhat more complicated by dealing with negative numbers):
reverse_number(X,Y) :- number(X) , ! , rev(X,Y) .
reverse_number(X,Y) :- number(Y) , ! , rev(Y,X) .
rev(N,R) :-
N < 0 ,
! ,
A is abs(N) ,
rev(A,T) ,
R is - T
.
rev(N,R) :-
number_chars(N,Ns) ,
reverse(Ns,Rs) ,
number_chars(R,Rs)
.
Note that this does require at least one of the arguments to reverse_number/2 to be instantiated.

evaluating possible situations using prolog

I am trying to see the possible situations for the following facts.
don likes cain
bob does not like don
cain does not like aron
nobody likes someone who does not like him
aron likes everyone who likes bob
don likes everyone bob likes
everybody likes somebody
I have just started learning prolog and I am trying to implement this in prolog and see how many possible situations arise. I scanned through few prolog threads here and I am also using the book "Learn prolog now" . So here is my best attempt to come up with the code.
likes(don, cain).
likes(aron,W):- likes(W,bob).
likes(don,M):- likes(bob,M).
(likes(aron,aron);likes(aron,bob));(likes(aron,cain);likes(aron,don)).
(likes(bob,aron);likes(bob,bob));(likes(bob,cain);likes(bob,don)).
(likes(cain,aron);likes(cain,bob));(likes(cain,cain);likes(cain,don)).
(likes(don,aron);likes(don,bob));(likes(don,cain);likes(don,don)).
not(likes(bob,don)).
not(likes(cain,aron)).
not(likes(Y,X)) :- not(likes(X,Y)).
When I run this in swipl compiler in Ubuntu Linux (which is in VirtualBox inside winxp), I get following errors
?- [test].
ERROR: /home/test.pl:11:
'$record_clause'/2: No permission to modify static_procedure `(;)/2'
ERROR: /home/test.pl:13:
'$record_clause'/2: No permission to modify static_procedure `(;)/2'
ERROR: /home/test.pl:15:
'$record_clause'/2: No permission to modify static_procedure `(;)/2'
ERROR: /home/test.pl:17:
'$record_clause'/2: No permission to modify static_procedure `(;)/2'
% test compiled 0.00 sec, 1,616 bytes
true.
So can you help me with this...... I have made use of not as a predicate here, some threads on the net seem to mention it.
In Prolog we have a fairly natural representation of what's true, but when faced with negative information (say negation), we must adapt our intuition to the restricted computation model that Prolog offer.
In particular, Prolog semantic being based on closed world assumption, we could be tempted to omit as irrelevant proposition like bob does not like don, because this just states the absence of the positive clause 'bob likes don'. Such absence is indeed 'absorbed' in Prolog proof search, and formalized by a 'procedural' definition of not (the only available in Prolog, but with an operator less reminiscent of 'human' interpretation, i.e. \+ means not):
\+ X :- call(X), !, fail.
\+ X.
See this page for further explanation about.
All this introductory to say that I would introduce a not_like/2 to represent explicitly the 'negative' knowledge. Syntactically we get:
likes(don, cain).
not_likes(bob, don).
not_likes(cain, aron).
not_likes(X, Y) :- \+ likes(Y, X).
likes(aron, X) :- likes(X, bob).
likes(don, X) :- likes(bob, X).
likes(_, _).
Now those statements make sense? Prolog takes the viewpoint of a practical approach to logic programming, and it run queries against such knowledge, that make perfectly sense for some programming task...
edit suggested by comment, I think that instead of likes(_,_)., a better code for everybody likes somebody should be
likes(X, Y) :- \+ not_likes(X, Y).
This is justified by the last fact, but standalone it not allows to infer not_likes(cain, aron).

Why does Prolog crash in this simple example?

likes(tom,jerry).
likes(mary,john).
likes(mary,mary).
likes(tom,mouse).
likes(jerry,jerry).
likes(jerry,cheese).
likes(mary,fruit).
likes(john,book).
likes(mary,book).
likes(tom,john).
likes(john,X):-likes(X,john), X\=john.
Hi there, above is a very simple prolog file, with some facts and only one rule: John likes anyone who likes him.
But after loading this file and ask Prolog the following query:
likes(john,X).
The program crashes. The reason is somehow prolog gets stuck at likes(john,john) even though the rule states that X\=john.
Any advice?
Ironically, given the site we're on, you're getting a stack overflow.
It does this because of the order of execution that prolog uses, it's going to go into an infinite recursion at likes(X,john) in your rule, it activates the rule again - not a fact - never getting to the X\=john bit.
One way to fix this is to have your rule named differently from your fact like this:
kindoflikes(tom,jerry).
kindoflikes(mary,john).
kindoflikes(mary,mary).
kindoflikes(tom,mouse).
kindoflikes(jerry,jerry).
kindoflikes(jerry,cheese).
kindoflikes(mary,fruit).
kindoflikes(john,book).
kindoflikes(mary,book).
kindoflikes(tom,john).
likes(Y,X):- kindoflikes(X,Y), X\=Y.
likex(Y,X):- kindoflikes(Y,X), X\=Y.
Note the reversal of X and Y in the kindoflikes in the two rule definitions.
So you get:
?- likes(john,X).
X = mary ;
X = tom ;
X = book.
But you're not locked into finding what john likes, and you can do:
?- likes(jerry,X).
X = tom ;
X = cheese.
Your first question was why your program crashes. I am not sure what kind of Prolog system you are using, but many systems produce a clean "resource error" which can be handled from within Prolog.
Your actual problem is that your program does not terminate for the query likes(john, X). It gives you the expected answers and only then it loops.
?- likes(john,X).
X = book
; X = mary
; X = tom
; resource_error(local_stack). % ERROR: Out of local stack
You have been pretty lucky that you detected that problem so rapidly. Imagine more answers, and it would have not been that evident that you have the patience to go through all answers. But there is a shortcut for that. Ask instead:
?- likes(john, X), false.
This false goal is never true. So it readily prevents any answer. At best, a query with false at the end terminates. Currently this is not the case. The reason for this non-termination is best seen when considering the following failure-slice (look up other answers for more details):
?- likes(john,X), false.
loops.
likes(tom,jerry) :- false.
likes(mary,john) :- false.
likes(mary,mary) :- false.
likes(tom,mouse) :- false.
likes(jerry,jerry) :- false.
likes(jerry,cheese) :- false.
likes(mary,fruit) :- false.
likes(john,book) :- false.
likes(mary,book) :- false.
likes(tom,john) :- false.
likes(john,X) :-
likes(X,john), false,
X\=john.
So it is this tiny little part of your program that is responsible for the stack overflow. To fix the problem we have to do something in that tiny little part. Here is one: add a goal dif(X, john) such that the rule now reads:
likes(john,X) :-
dif(X, john),
likes(X,john).
dif/2 is available in many Prolog systems like: SICStus, SWI, YAP, B, IF.

Problem with `\+` in Prolog queries with variables

I'm reading "Seven languages in seven weeks" atm, and I'm stumped over some Prolog query that I don't understand the 'no' response to.
The friends.pl file looks like this:
likes(wallace, cheese).
likes(grommit, cheese).
likes(wendolene, sheep).
friend(X, Y) :- \+(X = Y), likes(X, Z), likes(Y, Z).
I can do some trivial queries on it, such as:
| ?- ['friends'].
compiling /home/marc/btlang-code/code/prolog/friends.pl for byte code...
/home/marc/btlang-code/code/prolog/friends.pl compiled, 12 lines read - 994 bytes written, 8 ms
yes
| ?- friend(wallace,grommit).
yes
| ?- friend(wallace,wendolene).
no
This is all as expected. Now, I want to introduce a variable in the query. My intent being that Prolog will give me a list of all of Wallace's friends. I'm expecting X = grommit, but I'm getting no:
| ?- trace.
The debugger will first creep -- showing everything (trace)
yes
{trace}
| ?- friend(wallace,X).
1 1 Call: friend(wallace,_16) ?
2 2 Call: \+wallace=_16 ?
3 3 Call: wallace=_16 ?
3 3 Exit: wallace=wallace ?
2 2 Fail: \+wallace=_16 ?
1 1 Fail: friend(wallace,_16) ?
no
{trace}
It doesn't even try to unify X (_16) with grommit. Why?
It is the definition of friend:
friend(X, Y) :- \+(X = Y), likes(X, Z), likes(Y, Z).
The important thing here is that you start with \+(X = Y) which is normally defined as:
\+ Goal :- Goal,!,fail
Note that this means that if goal succeeds, you are sure to fail. Free variables (ones that havent been assigned) will always unify, and thus be equal, so you will always fail with a free variable. It will thus never assign a value to X or Y if it doesn't already have one.
Instead
friend(X, Y) :- likes(X, Z), likes(Y, Z), \+(X = Y)
will behave more as you expect.
The problem here is that prolog gives you powerful ways to control the flow of programs, but those dont really fit nicely with its more logic oriented design. It should be possible to express "negation as failure" type constraints in a way that does not produce these problems. I'm not a huge prolog fan for this reason.
Regarding Philip JF's comment above:
It should be possible to express
"negation as failure" type constraints
in a way that does not produce these
problems.
This is possible: The modern solution for such problems are constraints. In this case, use for example dif/2, available in all serious Prolog systems.
The first subgoal of friend/2 is \+(X = Y). This is executed by first trying to find a solution for X = Y, then negating that result. The predicate =/2 is roughly the equivalent of unify/2, that is it tries to unify the left operand with the right operand. Now, when you are asking queries using e.g. friend(wallace, gromit), the two atoms wallace and gromit do not unify; but when a free variable is thrown into the mix, it always unifies with whatever term is given, so X = Y is always successful, therefore \+(X = Y) always fails, and the execution never gets past that first subgoal.
Another issue with having the inequality constraint first is: It is uncapable to find a binding for the unbound X (excluding the trivial case of unifying it with grommit for the moment). Prolog finds bindings by running through its database, trying to unify the unbound variable. That is why likes(grommit, Z) will find some binding for Z which can then be further processed, because there are likes clauses in the database. But there are no such clauses for the inequality of grommit with something, so Prolog cannot produce any bindings. As things stand, the friend predicate has to make sure that all variables are bound before the inequality can be tested.

Resources