Скажем, у меня есть следующий:Как проверить, существует ли какое-либо условие statforying в Prolog без возврата по всем различным путям?
parent(alice, charlie).
parent(bob, charlie).
parent(bob, diane).
parent(alice, diane).
parent(bob, eve).
parent(alice, eve).
% people are siblings of each other if they share a parent
% and aren't the same person.
sibling(A, B) :-
parent(X, A),
parent(X, B),
B \= A.
Теперь, если я задам для братий и сестер Дианы, я Чарли и Ева — дважды, один раз через Боб и один раз через Алису. Я хочу только каждый раз.
Я не думаю, что я могу использовать разрез здесь, так как это предотвратит полное отступление. Что я будет нравится, это способ проверить, есть ли любой.
Перефразируя
sibling(A, B) :-
∃(parent(X, A), parent(X, B)),
B \= A.
Я пытался несколько сокращений, но никто не работал.
Я попытался FindAll на (parent(X, A), parent(X, B))
и проверки, если результирующий список не пуст, но это не унифицировать А или В.
Использование setof/3, как предложено ниже работ, но я действительно хочу, чтобы найти способ включить его в определение брата/2, вместо того, чтобы использовать его в вопросе. Я бы очень хотел, чтобы быть в состоянии сделать следующее:
?- sibling(diane, X).
X = charlie ;
X = eve ;
false.
% or this
?sibling(X, Y).
X = charlie,
Y = diane ;
X = charlie,
Y = eve ;
X = diane,
Y = charlie ;
X = diane,
Y = eve ;
X = eve,
Y = charlie ;
X = eve,
Y = diane ;
false.
Как я уже говорил ниже, у меня есть решение для этого конкретного случая. То, что я хотел бы, и то, за что я подаю награду, - это общее решение.
Вместо
sibling(A, B) :-
setof(D, X^(parent(X, A), parent(X, D)), Ds),
member(B, Ds),
B \= A.
Я хотел бы сделать
sibling(A, B) :-
exists(X^(parent(X, A), parent(X, B))),
B \= A.
, объединяющим A
и B
.
Как определить exists/1
?
У меня был очень похожий случай, и я сделал то, что @false предложил с помощью 'setof'. Я также играл с несколькими методами, чтобы избежать лишних ответов в результатах, но они часто были более сложными, чем просто использование 'setof'. – lurker