Получение списка решений в Прологе
Я изучаю пролог и читаю книгу под названием "Пролог программирования для искусственного интеллекта". В качестве практики я хочу научиться расширять один из примеров в этой книге. Может кто-нибудь, пожалуйста, помогите?
Скажем, у вас есть эти факты:
parent(pam, bob). %pam is a parent of bob
parent(george, bob). %george is a parent of bob
Как бы я написал предикат пролога, который бы дал мне список родителей Бобса? Например:
list_parents(bob, L).
L = [pam, george] ;
L = [george, pam] ;
true.
2 ответа
Предикат "все решения", как findall/3
может сделать трюк:
list_parents(P, L) :-
findall(Parent, parent(Parent, P), L).
Проще говоря, findall/3
находит все привязки для Parent
в "заднем ходу" цели parent(Parent, P)
и ставит все привязки Parent
в список L
, Обратите внимание, что это не удалит дубликаты, но вы можете сделать sort/2
в L
прежде чем вернуть его, чтобы создать набор. Выполнение этого:
?- list_parents(bob, L).
L = [pam, george].
Если у вас нет findall/3
в вашей реализации PROLOG вы можете сделать это вручную следующим образом:
list_parents(P, L) :-
list_parents(P, [], L).
list_parents(P, Acc, L) :-
parent(Parent, P),
\+ member(Parent, Acc), !,
list_parents(P, [Parent|Acc], L).
list_parents(_, L, L).
Эта версия отправляет звонки list_parents/2
от аккумуляторной версии, list_parents/3
, Последний пытается собрать Parent
привязки также, пока мы не видели их раньше (отсюда \+ member
проверить), и возвращает список, где нет новых Parent
привязки накапливаются в Acc
список можно найти. Выполнение этого дает нам тот же результат, что и первый вариант:
?- list_parents(bob, L).
L = [pam, george].
Попробуй это:
parent(pam, bob). %pam is a parent of bob
parent(george, bob). %george is a parent of bob
list_parents(A, Es, [X|Xs]) :- parent(X, A), \+ member(X, Es), list_parents(A, [X|Es], Xs).
list_parents(A, Es, []).
Это был неэффективный метод, более эффективный метод будет нуждаться в предикате высшего порядка "решения".
list_parents (X, Ys): - решения (родитель, [X, W], 1, Ys)