2016-12-27 26 views
0

我正在尝试编写一个过程,用于检查图形中的2个节点是相邻还是邻居。在序言中编写图形的相邻过程

我正在使用SWI-prolog。

我想:

adjacent(X,Y,graph(_,E)):- 
    member(e(X,Y), E). 

然而,这并不工作,我很困惑,为什么。

我用这个作为测试图。

tem(graph([s,t,u,v], [e(a,b), e(b,d), e(b,c), e(c,d)])). 

而且我检查它在这样的REPL:

?- tem(graph(_, E)), adjacent(a, b, E). 
false. 

但那些2都是邻居,所以应该返回true。

回答

1

要重复,令人惊讶地失败是查询:

 
?- tem(graph(_, E)), adjacent(a, b, E). 
false. 

在Prolog,一个很好的方式来定位exacte 导致这样的问题是想 声明,并系统地尝试适合概括专业您的计划和目标。

例如,可以通过分别与变量A和  B更换a和  b,使上述显著更一般查询:

 
?- tem(graph(_, E)), adjacent(A, B, E). 
false. 

所以,这仍然失败!因此,具体而言,因为程序完全是和  单调,所以更具体的查询也将失败 ,这使得这样的推理是可接受的。

让我们继续这和推广adjacent/2的单一目标。

相反的:

 
adjacent(X,Y,graph(_,E)):- 
    member(e(X,Y), E). 

我现在写的:

 
adjacent(X,Y,graph(_,E)) :- 
    true. 

当然,这使得整个谓语显著更 一般:在原来的谓词成功任何情况下,这种变种将成功 

即使有这种显著更一般的定义,我们仍然有:

 
?- tem(graph(_, E)), adjacent(A, B, E). 
false. 

而且现在没有更多的遗体找到:错误必须在剩余部分,并在以下ERGO片段:

 
adjacent(X, Y, graph(_,E)) :- ... 

如果你仔细观察,它是这一条款导致失败:要调用ŧ他以  列表谓词作为第三个参数,但在此定义中,第三个参数是而不是 a  列表。

这种方法被称为声明调试,你将在找到更多信息。一般而言,Prolog和逻辑编程语言对于允许应用这种功能强大的调试技术非常独特。注意,这种方法可以很容易地自动化:通过简单地断言,该查询应该成功,一个 程序可能得出上面的片段和你显示的 问题的确切原因

0

除了mat的优秀答案之外,相邻的过程期待functor图作为第三个参数。

tem(graph(_, E)), adjacent(a, b, E).将作为第三个参数传递给列表adjacent,而不是图函子。

tem(G), adjacent(a, q, G).将作为第三个参数传递给图函子,而不仅仅是图函子的一部分。

+1

一个好的命名约定是使用以“s”结尾的变量来表示* lists *。例如:'graph(_,Es)'。这更清楚地表明'Es'是一个列表。相比之下,当使用'相邻(a,q,G)'时,我希望'G'不*是一个列表。 – mat