【问题标题】:Prolog recursion and accumulatorsProlog 递归和累加器
【发布时间】:2016-05-08 01:02:49
【问题描述】:

我是 Prolog 编程的新手。我正在使用累加器进行递归分类谓词(我相信我需要累加器)。假设我有以下规则:

species(tiger).
species(carnivora).
species(ferae).
species(scrotifera).
species(laurasiatheria).

isa(tiger,carnivora).
isa(carnivora,ferae).
isa(ferae,scrotifera).
isa(scrotifera,laurasiatheria).
isa(laurasiatheria, mammalia).

我需要返回给定物种的类层次结构的分类谓词。这是我的工作:

classification_aux(mammalia,[H|T],[]).
classification_aux(Specie, Class, Accum) :-
    isa(Specie, Y),
    classification_aux(Y, [Y|Class], Accum).    

classification(Specie, Class) :- classification_aux(Specie,Class,[]).

这是它应该如何工作的示例:

classification(gray_tree_frog, X).
X = [amphibia, anura, hylidae, hyla].

编辑:我改进了我的代码。现在它似乎根据跟踪工作。但是什么都没有返回。

【问题讨论】:

  • 我觉得你应该看看transitive-closureclosure0/3的定义。
  • gray_tree_frog 不会出现在您的事实库中的任何地方。请在示例中包含所有必要的事实,以得出您想要的结果。
  • @mat,不,这只是一个使用示例,当然,当我测试时,我会说“老虎”)
  • 请使您的示例独立,以便查询清楚地表明 显示 事实库的预期结果是什么。例如,请在在您的问题中明确tiger 的预期结果。

标签: prolog


【解决方案1】:

仅基于分层描述(因为物种/1 似乎至少是对生物学中涉及的复杂术语的误解)

classification(Specie, Classification) :-
    isa(Specie, Class) ->
      Classification = [Class|SuperClasses],
      classification(Class, SuperClasses)
    ; Classification = [].

产量

?- classification(tiger, X).
X = [carnivora, ferae, scrotifera, laurasiatheria, mammalia].

编辑

如果你有兴趣,这个 sn-p

:- use_module(carlo(snippets/genealogy/pqGraphviz_emu)).

classification :-
    graph_window(build_graph, []).

build_graph(G) :-
    forall(species(S), make_node(G, S, [shape=diamond], _)),
    forall(isa(X, Y), (lookup_node(G, X, Xp), lookup_node(G, Y, Yp), new_edge(G, Xp, Yp))).

lookup_node(G, N, Np) :-
    find_node(G, N, Np) -> true ; make_node(G, N, Np).

生成这个 SVG 文件

接口来自github,需要安装Graphviz。

【讨论】:

    【解决方案2】:

    您已经非常接近正确了。

    首先要考虑的是如何在没有蓄能器的情况下解决问题。累加器通常是可选的,因为它们有助于提高性能而不是帮助您获得正确的答案。

    首先为您的谓词制定规范:如果 L 是 S 的层次结构,则分类(S,L) 应该为真。

    现在你可以写一个公理:哺乳动物的分类层次是 [mammalia]。

    并且你可以写一个规则:某个物种 S 的分类层次是前面有 S 和尾部有某个值 R 的列表,如果你能证明 S 分类为 P 并且 P 的层次是 R。或者换种说法:给定一个 S,我们首先找到 S 的类(称为 P)和 P 的层次结构(称为 R),然后 S 的层次结构是 [S|R]。

    希望这些描述足以让您编写子句。

    现在到累加器的问题:classification_aux(S,C,A) 应该为真,如果 S 的分类层次结构已经累积的 C 层次结构是 A。

    如果您现在将其与您的子句相匹配,您会发现有什么问题:

    classification_aux(mammalia,[H|T],[]).
    

    这表示当前层次结构 [H|T] 的哺乳动物分类是 []。这显然不符合规范。相反,您想要的是具有当前层次结构 L 的哺乳动物分类是 [mammalia|L]

    classification_aux(Specie, Class, Accum) :-
    isa(Specie, Y),
    classification_aux(Y, [Y|Class], Accum).    
    

    这表示:如果 Specie 是 Y 并且具有层次结构 [Y|Class] 的 Y 的分类是 Accum,则具有当前类层次结构 Class 的 Specie 的分类是 Accum。我认为这很好。

    但是,如果您同时尝试这两种方法,您会发现累加器版本以相反的顺序生成层次结构。这是由于 [mammalia|L] 和 [Y|Class] 将类放在列表的前面而不是末尾。您可以通过使用追加(慢)或差异列表(更复杂)或仅使用非累加器版本来解决此问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-30
      • 2012-05-26
      • 1970-01-01
      • 2021-07-06
      • 1970-01-01
      • 2013-12-25
      • 2022-10-06
      相关资源
      最近更新 更多