2

I have following clauses:

num_parent(adam, X) :- !, X = 0.  
num_parent(eve, X) :- !, X = 0.  
num_parent(X, 2).  

When I typed the query:

num_parent(eve,X).

It only returns:

X = 0.  

which is what I want.

But when I typed this query:

num_parent(X,0).  

it only returns:

X = adam.

So how can I modify the clauses to make it return:

X = adam;
X = eve.

Thanks

repeat
  • 18,496
  • 4
  • 54
  • 166
  • 2
    Just remove the `!`? – DodgyCodeException Nov 23 '17 at 11:08
  • 2
    Actually cut can result in a lot of results you did not take into account. Since it is sometimes hard for people to reason multidirectional. – Willem Van Onsem Nov 23 '17 at 11:19
  • I'm sorry that I didn't explain the problem clearly, the original clauses didn't have any !, when I type num_parent(eve,X), because of the last clause, except for returning X = 0, it also returned X = 2, which is not what I want. To avoid getting X = 2, I add ! in first two clauses, when I type num_parent(X,0), it only returns X = adam now, but I want to get X = eve too. – Shaopeng Guo Nov 24 '17 at 09:14

2 Answers2

4

First, try to formulate what you want in plain English. You probably want to say:

Everyone has two parents except Adam and Eve who have none.

What about Lilith? Never mind, let's stick to your reading.

num_parent(Person, 2) :-
   dif(Person, adam),
   dif(Person, eve).
num_parent(adam, 0).
num_parent(eve, 0).

As you can see, it is a bit cumbersome to define this: You have to mention each exceptional person twice. Easy to make an error.

With if_/3 available in library(reif) for SICStus and SWI you can write more succinctly:

num_parent(Person, Num) :-
   if_( ( Person = adam ; Person = eve ), Num = 0, Num = 2 ).

And now some uses:

?- num_parent(eve, Num).
   Num = 0.
?- num_parent(X, 0).
   X = adam
;  X = eve
;  false.
?- num_parent(X, 2).
   dif(X, eve), dif(X, adam).
?- num_parent(lilith, 2).
   true.
false
  • 10,264
  • 13
  • 101
  • 209
0

The programs returns only X = adam because you inserted the cut !. The cut is used when you have found the right rules and you don't need to do further evaluations, but it cuts all the other solutions.

In your case

num_parent(adam, X) :- !, X = 0.  
num_parent(eve, X) :- !, X = 0.  
num_parent(_, 2). %replaced num_parent(X, 2) with num_parent(_, 2) to avoid singleton variable

num_parent(X, 0) returns only X = adam.

If you write

num_parent(adam, X) :- X = 0.  
num_parent(eve, X) :- !, X = 0.  
num_parent(_, 2). 

the solution will be X = adam and X = eve, and in this case:

num_parent(adam, X) :- X = 0.  
num_parent(eve, X) :- X = 0.  
num_parent(_, 2). 

the solution will be X = adam, X = eve and false because the query num_parent(X, 0) doesn't unify with num_parent(_, 2).

You can better see this behavior using the tracer.

damianodamiano
  • 2,528
  • 2
  • 13
  • 21