Prolog需要解决它

时间:2013-09-26 09:51:08

标签: prolog shortest-path

解决方案

ppath(X,Y,M,Path,[Y|Path]) :- edge(X,Y,M), 

\+ memberchk(Y,Path).
path(X,Y,P,SoFar,Path) :- edge(X,W,M), \+ 

memberchk(W,SoFar),
    path(W,Y,N,[W|SoFar],Path), P is M+N.


pravilo(X,Y,Z) :-
    aggregate(min(W), P^path(X,Y,W,[],P), 

Z).

之后我尝试使用?- pravilo(a,z,M).得到结果。但它说错了。

我的版本SWI-Prolog(多线程,64位,版本6.4.1)

谢谢

1 个答案:

答案 0 :(得分:1)

你应该尽量避免断言/收回。

您的图表在fg之间有一个循环,然后您无法使用朴素路径/ 4谓词,或者您的程序将循环。

为了避免循环,你应该反转路径结构(现在是'自下而上'),“自上而下”向路径/ 4添加另一个参数(累加器),并检查是否已经访问过某个节点在递归之前。

您可以使用memberchk进行测试。

编辑:这是代码

path(X,Y,M,Path,[Y|Path]) :- edge(X,Y,M), \+ memberchk(Y,Path).
path(X,Y,P,SoFar,Path) :- edge(X,W,M), \+ memberchk(W,SoFar),
    path(W,Y,N,[W|SoFar],Path), P is M+N.

这会产生

?- path(a,z,W,[],P).
W = 27,
P = [z, e, j, b] ;
W = 26,
P = [z, g, b] ;
...

让我们使用库(aggregate)完成作业:

pravilo(X,Y,Z) :-
    aggregate(min(W), P^path(X,Y,W,[],P), Z).

现在我得到了

?- pravilo(a,z,M).
M = 24.

编辑要获取(完整)有序路径,这些更改在递归基础中是必需的

path(X,Y,M,Path,FullPath) :-
   edge(X,Y,M), \+ memberchk(Y,Path), reverse([Y|Path], FullPath).

并在顶级谓词中:

pravilo(X,Y,Z) :-
    aggregate(min(W), P^path(X,Y,W,[X],P), Z).