我对Prolog很新,我希望这个问题没有得到回答,但如果我有道歉,我就无法理解任何其他类似的问题和答案。
我的问题是我有3个城镇,通过公路连接。大多数是单向的,但有两个城镇通过双向连接。即
facts:
road(a, b, 1).
road(b, a, 1).
road(b, c, 3).
其中a,b和c是城镇,数字是距离
我需要能够从城镇a到c而不会卡在a和b之间
到此为止我可以用谓词来解决:(其中r是路线上的城镇列表)
route(A, B, R, N) :-
road(A, B, N),
R1 = [B],
R = [A|R1],
!.
route(A, B, R, N) :-
road(A, C, N1),
route(C, B, R1, N2),
\+ member(A, R1),
R = [A | R1],
N is N1+N2.
然而,如果我添加一个像这样的城镇
facts:
road(b, d, 10)
我无法让Prolog认识到这是第二种可能的途径。我知道这是因为我使用了切割,但没有切割它不会停止并以堆栈溢出结束。
此外,我需要能够编写一个新的谓词,当R作为a和c之间的最短路径给出时,该谓词返回true。
很抱歉这么长的说明。我希望有人可以帮助我!
答案 0 :(得分:1)
这是图形遍历的问题。我认为你的问题是你有一个循环图 - 你发现腿a-->b
而你找到的下一条腿是b-->a
,它再次找到了腿a-->b
和...好吧,你明白了。
我会像这样处理问题,使用 helper 谓词和 accumulators 来构建我的路线并计算总距离。像这样:
% ===========================================================================
% route/4: find the route(s) from Origin to Destination and compute the total distance
%
% This predicate simply invoke the helper predicate with the
% accumulator(s) variables properly seeded.
% ===========================================================================
route(Origin,Destination,Route,Distance) :-
route(Origin,Destination,[],0,Route,Distance)
.
% ------------------------------------------------
% route/6: helper predicate that does all the work
% ------------------------------------------------
route(D,D,V,L,R,L) :- % special case: you're where you want to be.
reverse([D|V],R) % - reverse the visited list since it get built in reverse order
. % - and unify the length accumulator with the final value.
route(O,D,V,L,Route,Length) :- % direct connection
road(O,D,N) , % - a segment exists connecting origin and destination directly
L1 is L+N , % - increment the length accumulator
V1 = [O|V] , % - prepend the current origin to the visited accumulator
route(D,D,V1,L1,Route,Length) % - recurse down, indicating that we've arrived at our destination
. %
route(O,D,V,L,Route,Length) :- % indirect connection
road(O,X,N) , % - a segment exists from the current origin to some destination
X \= D , % - that destination is other than the desired destination
not member(X,V) , % - and we've not yet visited that destination
L1 is L+N , % - increment the length accumulator
V1 = [O|V] , % - prepend the current origin to the visited accumulator
route(X,D,V1,L1,Route,Length) % - recurse down using the current destination as the new origin.