解决方案
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)
谢谢
答案 0 :(得分:1)
你应该尽量避免断言/收回。
您的图表在f
和g
之间有一个循环,然后您无法使用朴素路径/ 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).