List 带列表的Prolog祖先
我四处寻找,找不到答案。我很难列出家谱 因此,我有一些is_a关系,例如:List 带列表的Prolog祖先,list,prolog,ancestor,genealogy,List,Prolog,Ancestor,Genealogy,我四处寻找,找不到答案。我很难列出家谱 因此,我有一些is_a关系,例如: is_a(cow, animal). is_a(calf, cow). is_a(dog, animal). .... etc. 我希望有一个执行以下操作的过程: toAnimal(cow, X). that outputs X= [calf, cow, animal]. 基本上,如果我给它一个输入(cow),那么它将从cow一直到animal,并将每个步骤添加到列表中 到目前为止,我有: toAnimal(A,
is_a(cow, animal).
is_a(calf, cow).
is_a(dog, animal).
.... etc.
我希望有一个执行以下操作的过程:
toAnimal(cow, X).
that outputs
X= [calf, cow, animal].
基本上,如果我给它一个输入(cow),那么它将从cow一直到animal,并将每个步骤添加到列表中
到目前为止,我有:
toAnimal(A, B) :- is_a(A,B).
toAnimal(A, B) :- is_a(A, X), toAnimal(X, B).
其输出为
X= cow;
X = animal;
false
我怎样才能把它变成一个列表
编辑:
在看了这个建议之后,我更新了它。但是,如何打印列表?我对序言还是新手。findall页面说它会返回列表,但不是为我这样做
toAnimal(calf, Y)
outputs:
false.
编辑:
它现在返回一个空列表。我不确定这里有什么问题。我根本没有更改代码,因此输出不应该更改,但它已经更改了
编辑:
谢谢布拉奇先生的回复。
我做了建议的修改,但我现在有另一个问题。
例如
如果我有关系:
is_a(calf, cow).
is_a(calf, animal).
is_a(cow, cool).
is_a(cool, awesome).
但我只想要从小牛到令人敬畏的道路。
代码将给出calf,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).
会给我一份清单吗
[cow,animal,cool,awesome].
但我想要的是
[calf,cow,cool,awesome].
如何过滤其他路径?
还要加起点吗?我想我可以将calf附加到开头作为head,但是如何忽略其他路径呢
编辑:
谢谢你的帮助
我想出来了,但我失去了终点和起点。例如
我有牛,酷。
但是小牛和可怕的不在那里。我试着附加,但我不太懂语法。我不允许做附加(X,L,一个新列表)
toAnimal(X,Y):-setof(X,down('animal',X),Y)。
应该这样做。或findall/3
但请记住,您要求的是下降(动物,X),因此它与以下事实不匹配:是一只(狗,动物)
,例如,下降(动物,X)
将。你需要使下降
来搜索两边,或者只需确保你的是一只在左边的动物
如果你想过滤,你可以这样做
toAnimal(X,Y):-setof(X,(下降('animal',X),而不是(X=animal)),Y.
但是你得到的是动物
,因为我前面提到的。这个样本或多或少符合你的要求:
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).
运行时,这是输出:
[莱西,柯利牧羊犬,狗,动物][柯利牧羊犬,狗,动物]
使用
后期编辑:啊,就是这样!我应该在第一句写“[X,animal]”而不是“[X | animal]”!非常感谢@mbrach,现在该程序完全实现了预期目的。在这里。(注意:不需要使用下降谓词来计算树的特定分支的路径)
用法:
| ?- find_path(calf,awesome,L).
L = [calf,cow,cool,awesome] ? ;
您可以使用findall/3
或setof/3
。请参阅序言文档,了解它们是如何工作的。您没有使用B
作为列表,而是将其与一个基本术语(即animal
)统一起来。我对我的帖子进行了编辑,我不确定现在如何打印列表。谢谢你的回复!这类函数的诀窍是添加一个额外的参数,该参数不是原始调用方真正使用的,而是由函数用作存储此类列表的临时位置,在该额外参数中,将每一步放在列表的开头:[X | Y]这不是使用findall/3
的正确方法。因为您使用的是findall/3
,所以不应该实例化第一个参数,这就是整点。否则,您只需选择一个特定的X
。如果找到满足特定标准的X
的所有值,则findall
会做什么。像findall(X,后代(cow,X),L)
将创建一个列表L
,其中包含使后代(cow,X)
为true的所有X
。或者您可以编写toAnimal(Y):-findall(X,后代(Y,X),L)。
然后查询toAnimal(cow)。
很抱歉,我忘了在前面指定我想要到指定点的特定路径。但这确实适用于所有路径。我在我的帖子中对此进行了编辑。感谢您的回复,尽管我非常感谢您的帮助。请查看如何使用减少回溯代码>。谢谢,这非常有帮助<代码>[X |动物]
是一个由一个元素组成的列表,即复合词|(X,动物)
。在这个上下文中,它没有太多的语义意义。如果你想有一个包含两个元素的列表X
和animal
,你只需要编写它[X,animal]
。工作完美!!对不起,“\+”是做什么的?如果不是要求太高,请您简单描述一下您的解决方案是如何工作的?@JoePineda\+
是“无法证明”。哦!谢谢但是在这种情况下,如果你只是把第二个“路径”的定义移到第一个定义之上,那不是一样吗?如果失败,prolog将尝试使用更长的定义,在这种情况下,“\+is_a(X,Y)”的检查将是多余的。我的意思是这样的,尝试过它,至少在这个小示例中工作正常:path(X,Y,[Y]):-is_a(X,Y)。path(X,Y,[Z | T]):-是_a(X,Z),path(Z,Y,T)。让你的子句互斥是件好事,不管它们的顺序如何。对于初学者来说,让谓词的意义依赖于它的从句顺序通常被认为不是一个好的做法。话虽如此,你看。
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).
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] ? ;