给出一张图
如何用一个functor表示两个城市相连?
因为是一个无向图,所以两个方向都可以表示连通,需要用到分号;表示“或”。
directConn(X,Y,S) :- street(X,Y,S); street(Y,X,S).
两座可以连通的城市之间有多少座城市?
利用递归,每存在一个directConn的城市,城市计数Erg加一。最后加上首尾的两座城市。
两座可以连通的城市之间的距离?
求距离和求城市的数量不同,如课件上写到的“Berechnung des Ergebnisses auf dem Weg nach oben"。
distance(A,B,Dist) :- directConn(A, B, Dist).
distance(A.B,Dist) :- directConn(A,C,S), distance(C,B,Dist1), Dist is Dist1+s.
随着每次找到一个和起点连通的城市,这个城市和终点的距离在缩小。
两座可以连通的城市,按照正确的顺序给出从起点到终点的所有城市?
为了避免出现循环,访问过的城市要保存在一个叫做Visited的列表list里面。
需要使用+,表示not;member()给出一个元素是不是存在在列表当中; revertList()给出倒序的列表; printList()打印列表。
route(X,Y,Visited) :- + member(X, Visited), + member(Y,Visited), directConn(X,Y,),revertList([Y,X]|Visited, FinalRoute),printList(FinalRoute).
route(X,Z,Visited) :- +member(X,Visited), directConn(X,Y,), route(Y,Z,[X|Visited]).
每找到一座相连的城市,就把原来的城市添加到Visited的列表中。
另一个route,增加了正确顺序的城市的列表和最终的长度。
route2(X,Y,Visited,Dist,[X,Y]) :- + member(X,Visited), + member(Y,Visited), directConn(X,Y,Dist).
route2(X,Z,Visited,Dist,[X|Route1]) :- + member(X,Visited), directConn(X,Y,D), route2(Y,Z,[X|Visited],Dist1,Route1), Dist is Dist1+D.
Dist综合了前面的求距离。
第一种情况适用于最后找到两个直接相连的城市,这时候列表里只有这两个城市。递归后列表会增加其他的城市。
两个城市之间所有的连通方法:
allRoutes(X,Y,ResultList) :- findall((Route,Distance), route2(X,Y,[ ],Distance,Route),ResultList).
找到路程最短的连通方法:
shortestRoute(X,Y,Shortest) :- setof((Distance,Route), route2(X,Y,[ ],Distance,Route),[Shortest| _ ]).
[Shortest| _ ]这时候列表中已经按照顺序排序了,排在最前面的是距离最短的。取距离最短的即可。