我在prolog中编写了一个程序,用于查找地铁站之间的路线。它几乎与预期的线性路线(A -> B -> C -> D)
一致,但我不知道如何处理圆形路线(A -> B -> C -> D -> A -> B -> ...)
等等。
数据库:
stations.pl
train(
a,
[
station2,
station3,
station4,
station10
]
).
train(
b1,
[ station1,
station8,
station3,
station10,
station11
]
).
train(
b2,
[
station1,
station11,
station10,
station3,
station8
]
).
train(
c,
[
station0,
station8,
station21
]
).
程序:
rails.pl
:- include('stations.pl').
% Case: direct route (A) --> (B).
route(A, B, Trains, Acc, R) :-
train(Train, Stations),
\+ member(Train, Trains),
member(A, Stations),
member(B, Stations),
append(Acc, [[A, Train, B]], R).
% Case: intermediary station/s (I) between
% departure (A) and destination (B).
route(A, B, Trains, Acc0, R) :-
train(Train, Stations),
\+ member(Train, Trains),
member(A, Stations),
member(I, Stations),
A \= I,
I \= B,
length(Acc0, L),
L < 3, % do not find routes where more than 2 changes are needed
append(Acc0, [[A, Train, I]], Acc1),
route(I, B, [Train|Trains], Acc1, R).
线性路线: a
,c
循环路线: b1
,b2
现在让我们考虑以下情况。显示从station2
到station21
的所有路线。结果订单改为简单。
?- route(station2, station21, [], [], R).
R = [[station2, a, station3], [station3, b1, station8], [station8, c, station21]] ;
R = [[station2, a, station3], [station3, b2, station8], [station8, c, station21]] ;
R = [[station2, a, station3], [station3, b1, station1], [station1, b2, station8], [station8, c, station21]] ;
R = [[station2, a, station3], [station3, b2, station1], [station1, b1, station8], [station8, c, station21]] ;
...
...
问题:
问题是,即使名称不同,如何让程序知道b1
和b2
共享相同的路由。我想排除以下路线:
station2 (a) station3 -> station3 (b1) station1 ->
station1 (b2) station8 -> station8 (c) station21
因为station3
和station8
之间的距离可以在b1
或b2
上完成,所以无需在它们之间进行更改。
所以基本上我希望两条路线都被视为一条路线,但根据搜索方向有不同的名称。目前这不是效率问题,而是在同一条路线上不在b1
和b2
之间跳跃。
编辑:
b1 / b2
在10+之间是单数的,所以我不一定要寻找通用解决方案,所以原子名称检查会起作用(不知道怎么办)。答案 0 :(得分:0)
您的问题基本上是图搜索,其中图表是:
G=(V,E)
V = Stations
E = { (u,v) | u,v are stations connected by some train }
您当前的方法是Depth First Search (DFS)在图表上,从源头开始,首先深入到卡住/找到解决方案。 DFS的一个已知缺点是无限循环。
处理此问题的经典方法是添加visited
集,当您第一次“探索”某个节点(工作站)时,将其添加到visited
集,并避免展开任何已在此visited
集中的节点。