【问题标题】:Printing path in PrologProlog中的打印路径
【发布时间】:2014-04-19 20:15:41
【问题描述】:

我想在有向图中打印节点的路径。 此代码适用于边缘,但不适用于整个路径。 当涉及到路径时,它返回 false。 这是我的代码,但它仅针对边缘而不是整个路径运行。 请帮帮我。

这是我的代码:

path(Node1, Node2, X) :-
  edge(Node1, Node2),
  append([Node1], [Node2], X).
path(Node1, Node2, X, N) :-
  edge(Node1, SomeNode),
  append([Node1], [SomeNode], X),
  path(SomeNode, Node2, X, N),
  append([], [Node2], X).

X 是一个列表。

【问题讨论】:

    标签: prolog program-slicing


    【解决方案1】:

    虽然@WouterBeek 已经指出了您的问题,但 Wouter 的声明

    如果不运行此代码,您已经可以观察到第二个子句总是会失败,因为长度为 2 的列表不能与长度为 1 的列表统一

    需要详细说明。对于有经验的 Prolog 程序员来说,很容易发现这些问题。但是初学者能做什么呢?他们可以应用以下技术:泛化你的程序,如果泛化的程序仍然过于专业化,那么剩下的部分肯定有错误。

    推广纯 Prolog 程序

    有几种方法可以泛化纯 Prolog 程序:要么删除目标,要么删除头部或目标参数中的子项。要删除目标,我将在目标前添加*,使用:

    :- op(950,fy, *)。
    
    *_。
    
    路径(节点 1,节点 2,X):-
      * edge(Node1, Node2),
      追加([节点 1],[节点 2],X)。
    路径(节点 1,节点 2,X):-
      * edge(Node1, SomeNode),
      附加([Node1],[SomeNode],X),
      * path(SomeNode, Node2, X),
      追加([],[Node2],X)。

    现在我们可以询问这个新谓词的最一般查询:

    | ?- path(N1, N2, P).
    P = [N1,N2] ? ;
    no
    

    因此:虽然这个定义现在是一个(过度)概括,但它仍然只承认长度为 2 的路径。这个问题完全独立于 edge/3 的定义,只负责剩下的部分。所以看看剩下的部分来解决问题吧!

    【讨论】:

      【解决方案2】:

      在您的第二个子句中,您有以下两个语句:

      append([Node1], [SomeNode], X),
      append([], [Node2], X).
      

      请注意,变量X 出现在两个语句中,并且必须将其实例化为同一个列表。这意味着[Node1]+[SomeNode] = []+[Node2][Node1,SomeNode]=[Node2]

      如果不运行此代码,您已经可以观察到第二个子句总是会失败,因为长度为 2 的列表无法统一为长度为 1 的列表。

      另外一点:两个子句不属于同一个谓词,因为前者的元数为 3,而后者的元数为 4。通常,为了计算路径或任意深度,您需要一个由两个子句组成的谓词属于一起:基本情况和递归情况。对于递归情况,通常使用头/尾符号来构造路径:[FromNode,ToNode|RestOfPath]

      希望这会有所帮助!

      【讨论】:

        猜你喜欢
        • 2023-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-18
        • 1970-01-01
        • 1970-01-01
        • 2023-01-23
        相关资源
        最近更新 更多