0

我四处寻找,找不到答案。我在制作家谱清单时遇到了麻烦。

所以,我有一些 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).

但我只想要从小牛到真棒的道路。该代码将为我提供来自小牛,x 的所有可能路径。例如,

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 包含牛,酷。但是calf和awesome都不在。我尝试追加,但我并不真正理解语法。我不允许追加(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
4

3 回答 3

1

这里是。(注意:您不需要下降谓词来确定树的特定分支的路径)

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] ? ;
于 2014-02-01T06:36:00.660 回答
0

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的结果是因为我之前提到的。

于 2014-01-31T20:15:52.477 回答
0

该示例或多或少可以满足您的需求:

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).

运行时,输出如下:

[lassie,collie,dog,animal][collie,dog,animal]

使用这个 Prolog 在线解释器在线测试它

后编辑:啊,就是这样!我应该在第一个子句中写成“[X,animal]”而不是“[X|animal]”!感谢@mbratch,现在该程序完全按照预期进行。

于 2014-01-31T23:05:25.893 回答