Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 813
Marc Mutz - mmutz Avatar asked May 12 '11 00:05

Marc Mutz - mmutz


People also ask

How do you declare a variable in Prolog?

A variable in Prolog is a string of letters, digits, and underscores ( _ ) beginning either with a capital letter or with an underscore. Examples: X , Sister , _ , _thing , _y47 , First_name , Z2 The variable _ is used as a "don't-care" variable, when we don't mind what value the variable has.

How does Prolog solve a query?

The unique feature of Prolog is that it automatically chooses the facts and rules needed to solve a query. But how does it make its choice? It starts by trying to solve each goal in a query, left to right (recall goals are connected using “,” which is the and operator).

What does :- mean in Prolog?

body the last part of a Prolog rule. It is separated from the head by the neck symbol, written as :- . It has the form of a comma-separated list of goals, each of which is a the name part of a functor, possibly followed by a comma-separated list of arguments, in parentheses.

What are facts rules and queries in Prolog?

A Prolog program consists of a number of clauses. Each clause is either a fact or a rule. After a Prolog program is loaded (or consulted) in a Prolog interpreter, users can submit goals or queries, and the Prolog intepreter will give results (answers) according to the facts and rules.


1 Answers

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.

like image 99
Philip JF Avatar answered Oct 13 '22 10:10

Philip JF