Пролог Предок со Списком
Я искал вокруг и не мог найти ответ. У меня проблемы с составлением генеалогического списка.
Итак, у меня есть некоторые отношения is_a, например:
is_a(cow, animal).
is_a(calf, cow).
is_a(dog, animal).
.... etc.
Я хочу иметь процедуру, которая делает следующее:
toAnimal(cow, X).
that outputs
X= [calf, cow, animal].
По сути, если я дам ему вход (корова), то он перейдет от коровы до животного и добавит каждый шаг в список.
Пока у меня есть это:
toAnimal(A, B) :- is_a(A,B).
toAnimal(A, B) :- is_a(A, X), toAnimal(X, B).
Выход этого будет
X= cow;
X = animal;
false
Как бы я получить это, чтобы стать списком?
РЕДАКТИРОВАТЬ:
descend(X,Y) :- is_a(X,Y).
descend(X,Y) :- is_a(X,Z), descend(Z,Y).
toAnimal(X,Y):-
findall(X, descend('animal', X), Y).
Я обновил его до этого после просмотра предложения. Тем не менее, как я могу получить список для печати? Я все еще новичок в прологе. Страница findall сказала, что вернет список, но это не так для меня.
toAnimal(calf, Y)
outputs:
false.
РЕДАКТИРОВАТЬ:
Теперь он возвращает пустой список. Я не уверен, что проблема здесь. Я не изменил код вообще, поэтому вывод не должен измениться, но он изменился.
РЕДАКТИРОВАТЬ:
Спасибо MrBratch за ответ. Я сделал предложенные изменения, но теперь у меня есть другая проблема. Например, если у меня есть отношения:
is_a(calf, cow).
is_a(calf, animal).
is_a(cow, cool).
is_a(cool, awesome).
Но я ТОЛЬКО хочу путь от теленка до офигенного. Код даст мне ВСЕ возможные пути от теленка, х. Например,
descend(X,Y) :- is_a(X,Y).
descend(X,Y) :- is_a(X,Z), descend(Z,Y).
toAwesome(A,Y) :-
findall(X, descend(calf, X), Y).
даст мне список Y, который имеет
[cow,animal,cool,awesome].
но я хочу
[calf,cow,cool,awesome].
Как мне отфильтровать другие пути? а также добавить отправную точку? Я полагаю, что я могу добавить теленка в начало как голову, но как мне игнорировать другие пути?
РЕДАКТИРОВАТЬ:
Спасибо за помощь, я понял это, но я теряю конечный путь и начальный путь. Например, L содержит корову, круто. Но теленка и офигенного там нет. Я попытался добавить, но я не совсем понимаю синтаксис. Мне не разрешено делать добавления (X,L, новый список)?
descend(X,Y) :- is_a(X,Y).
descend(X,Y) :- is_a(X,Z), descend(Z,Y).
toAnimal(A,B) :-
setof(X, (descend(A,X), descend(X,'awesome')), B).
--> append(A, L,anewlist).
?? Is this line not allowed here? How else would I do it? or is there a simpler way to just add it from the beginning
3 ответа
Этот пример более или менее делает то, что вы хотите:
is_a(cow, animal).
is_a(calf, cow).
is_a(dog, animal).
is_a(snoopy, dog).
is_a(lassie, collie).
is_a(collie, dog).
toAnimal3( X, [X,animal] , animal ):- is_a( X, animal).
toAnimal3( X, [X|R], R ):- is_a( X, Y), toAnimal3(Y, R, _).
:- initialization(main).
main :- toAnimal3( lassie, A, B), write(A), write(B).
При запуске это вывод:
[Милочка, колли, собака, животное][колли, собака, животное]
Протестировал его онлайн с помощью этого онлайн переводчика Prolog
ПОСЛЕ РЕДАКТИРОВАНИЯ: Ах, вот и все! Я должен был написать "[X,animal]" вместо "[X|animal]" для первого предложения! Спасибо большое @mbratch, теперь программа делает именно то, что было задумано.
Вот. (ПРИМЕЧАНИЕ: вам не нужен предикат по убыванию, чтобы выяснить путь к определенной ветви дерева)
is_a(calf, cow).
is_a(calf, animal).
is_a(cow, cool).
is_a(cool, awesome).
path(X,Y,[Z|T]) :- \+ is_a(X,Y), is_a(X,Z), path(Z,Y,T).
path(X,Y,[Y]) :- is_a(X,Y).
find_path(X,Y,[X|L]) :- path(X,Y,L).
Использование:
| ?- find_path(calf,awesome,L).
L = [calf,cow,cool,awesome] ? ;
toAnimal(X,Y) :- setof(X, descend('animal', X), Y).
должен сделать это. Или же findall/3
,
Информация и некоторые примеры bagof, setof, findall.
Но помните, что вы просите descend(animal, X)
так что это не будет соответствовать действительности is_a(dog, animal)
например, который descend(X, animal)
будут. Вам нужно сделать descend
искать обе стороны, или просто быть уверенным, что ваш is_a
факты говорят, что животное только на левой стороне.
Если вы хотите отфильтровать, вы можете сделать
toAnimal(X,Y) :- setof(X, (descend('animal', X), not(X = animal)), Y).
но вы получаете animal
в результате, потому что я упоминал ранее.