Пролог Предок со Списком

Я искал вокруг и не мог найти ответ. У меня проблемы с составлением генеалогического списка.

Итак, у меня есть некоторые отношения 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 в результате, потому что я упоминал ранее.

Другие вопросы по тегам