Пролог: список фактов - PullRequest
       7

Пролог: список фактов

0 голосов
/ 14 ноября 2018

Допустим, я ищу кого-то из друзей.

friend(mary, peter).
friend(mary, paul).
friend(mary, john).
friend(mary, justin).

friend(chris, peter).
friend(chris, paul).
friend(chris, conner).
friend(chris, louis).

friend(tyler, justin).
friend(tyler, lindsey).
friend(tyler, frank).
friend(tyler, paul).

friend(dan, justin).
friend(dan, conner).
friend(dan, frank).
friend(dan, peter).

В приведенном выше примере я знаю, что могу сделать что-то вроде

friend(X, paul).

, что скажет мне, что каждый Полдрузья с

или также

findall(X, friend(X, paul), L).

, который вернет список всех, с кем Павел дружит.

Допустим, я хочу немного углубиться в мойпоиск и уточнение.Итак, скажем, что я должен был сделать

findall(X, friend(X, paul), A).

, чтобы получить список А [Мэри, Крис, Тайлер].Но затем я хотел еще больше уточнить этот поиск.Я хочу иметь возможность поместить список в функцию (я знаю, что это недопустимо, но это мой шаблон мышления для того, что я хочу сделать) для чего-то вроде

findall(A, friend(A, peter), B).

Вернуть только [Мэри,Крис] на этот раз.А потом даже ДАЛЕЕ уточни это, чтобы сказать

findall(B, friend(B, conner), C).

Чтобы наконец завершить мой поиск, чтобы найти [chris]

Возможно ли это?Есть ли лучший или даже возможный способ сделать это?

1 Ответ

0 голосов
/ 14 ноября 2018

Условия цепочки

Если я правильно понял, вы хотите создать список людей, которые дружат с paul, peter и connor. Мы можем сделать это, «построив» цель, которая направлена ​​на удовлетворение трех условий:

findall(F, <b>(friend(F, paul), friend(F, peter), friend(F, conner))</b>, L).

или другое сочетание условий. Затем они дают:

?- findall(F, (friend(F, paul)), L).
L = [mary, chris, tyler].

?- findall(F, (friend(F, paul), friend(F, peter)), L).
L = [mary, chris].

?- findall(F, (friend(F, paul), friend(F, peter), friend(F, conner)), L).
L = [chris].

Отфильтруйте существующий список с помощью member/2 в цели

Или мы также можем использовать два вызова и использовать member/2 для «эмуляции» пересечения, например:

findall(F, friend(F, paul), L1),
findall(F, <b>(member(F, L1),</b> friend(F, peter)<b>)</b>, L2).

здесь мы, таким образом, используем member/2 таким образом, что F2 принимает значения только от L1 (результат начального findall/3), но я думаю, что первый способ чище и более самоочевиден: мы хотим после всех список F с друзьями paul, peter и conner.

Использование maplist/2 для получения людей, которые дружат со всеми в списке

Мы также можем найти людей, которые дружат со списком людей, используя maplist/2 здесь:

findall(F, <b>maplist(friend(F),</b> [paul, peter, conner]<b>)</b>, L).

Постобработка с пересечением

Мы также можем сделать два отдельных вызова findall/3, а затем рассчитать пересечение:

findall(F, friend(F, paul), L1),
findall(F, friend(F, paul), L2),
intersection(L1, L2, M).

Здесь M будет содержать элементы, которые находятся как в L1, так и L2. Но потенциальная проблема здесь заключается в том, что второй предикат может генерировать много результатов, которые были бы невозможны, если мы отфильтровали значения первого предиката.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...