Пролог, о том, как формировать лучшие предложения

У меня есть следующие пункты:

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

Когда я набрал запрос:

num_parent(eve,X).

Он возвращает только:

X = 0.  

чего я и хочу.

Но когда я набрал этот запрос:

num_parent(X,0).  

он возвращает только:

X = adam.

Итак, как я могу изменить предложения, чтобы они возвращались:

X = adam;
X = eve.

Спасибо


person Shaopeng Guo    schedule 23.11.2017    source источник
comment
Просто удалить !?   -  person DodgyCodeException    schedule 23.11.2017
comment
На самом деле сокращение может привести к большому количеству результатов, которые вы не приняли во внимание. Так как людям иногда тяжело рассуждать разнонаправленно.   -  person Willem Van Onsem    schedule 23.11.2017
comment
Извините, что я не объяснил проблему ясно, в исходных предложениях не было !, когда я набираю num_parent(eve,X), из-за последнего предложения, за исключением возврата X = 0, он также возвращал X = 2, а это не то, что я хочу. Чтобы не получить X = 2, я добавляю ! в первых двух предложениях, когда я набираю num_parent(X,0), теперь возвращается только X = adam, но я также хочу получить X = eve.   -  person Shaopeng Guo    schedule 24.11.2017


Ответы (2)


Во-первых, попробуйте сформулировать то, что вы хотите, на простом английском языке. Вы, наверное, хотите сказать:

У всех есть два родителя, кроме Адама и Евы, у которых их нет.

Что с Лилит? Неважно, давайте придерживаться вашего чтения.

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

Как видите, определить это немного громоздко: вы должны дважды упомянуть каждого исключительного человека. Легко совершить ошибку.

С if_/3, доступным в library(reif) для SICStus и SWI можно написать короче:

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

А теперь немного использования:

?- 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.
person false    schedule 23.11.2017
comment
Большое спасибо за перефразировку и решение моей проблемы! - person Shaopeng Guo; 24.11.2017

Программа возвращает только X = adam, потому что вы вставили разрез !. Отсечение используется, когда вы нашли правильные правила и вам не нужно проводить дальнейшие оценки, но оно отсекает все остальные решения.

В твоем случае

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) возвращает только X = adam.

Если вы пишете

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

решение будет X = adam и X = eve, и в этом случае:

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

решение будет X = adam, X = eve и false, поскольку запрос num_parent(X, 0) не унифицируется с num_parent(_, 2).

Вы можете лучше увидеть это поведение, используя трассировщик.

person damianodamiano    schedule 23.11.2017