我正在尝试在SWI-Prolog中编写简单的图搜索。我想出了以下程序:
adjacent(1,4). adjacent(4,2). adjacent(3,6).
adjacent(6,4). adjacent(7,10). adjacent(4,9).
adjacent(5,10). adjacent(7,10). adjacent(7,12).
adjacent(6, 11). adjacent(13,11). adjacent(9,14).
adjacent(14,12). adjacent(10,15). adjacent(9,12).
connected(X,Y) :- adjacent(X,Y); adjacent(Y,X).
path(A,B,[A|B]) :-
connected(A,B).
path(A,B,[A|R]) :-
\+member(R,A),
connected(A,C),
A \== C,
path(C,B,R).
但是这个程序导致堆栈溢出。我做错了什么以及如何解决?
答案 0 :(得分:3)
您正在尝试使用返回的路径作为检查以避免循环。这在搜索路径时不起作用,因为路径尚未在否定时实例化。
最简单的解决方案是在收集已访问过的节点时添加另一个输入参数,并检查这些参数以避免重复。
另外,我认为你应该检查A \ == B而不是A \ == C.你没有节点上的循环,所以后者永远不会发生。案例A == B在第一个子句中处理,因此您不希望在第二个子句中再次执行此操作。
你也得到了成员倒退的论据,并且需要修正第一个子句中的列表,正如Martin写的那样。
在没有额外参数的情况下避免无限循环的高级方法是在否定时使用freeze / 2.
另请参阅Prolog中调试的工作原理,这可能有助于您更好地理解事物。
答案 1 :(得分:2)
这里的主要问题是成员测试:签名是member(Element,List)
;你似乎认为这些论点是另一种方式。
此外,您的第一个路径谓词用于测试两个元素的列表,但是,B确实与其余列表(后来未连接)统一。
如果修复了这些问题,您会发现这只适用于完全实例化的变量,因为否定对未绑定的变量不起作用。