在路线寻找算法中处理循环路线

时间:2017-03-25 13:54:56

标签: algorithm graph prolog

我在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).

线性路线: ac
循环路线: b1b2

现在让我们考虑以下情况。显示从station2station21的所有路线。结果订单改为简单。

?- 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]] ;
...
...

问题:

问题是,即使名称不同,如何让程序知道b1b2共享相同的路由。我想排除以下路线:

station2 (a) station3 -> station3 (b1) station1 -> 
  station1 (b2) station8 -> station8 (c) station21

因为station3station8之间的距离可以在b1b2上完成,所以无需在它们之间进行更改。

所以基本上我希望两条路线都被视为一条路线,但根据搜索方向有不同的名称。目前这不是效率问题,而是在同一条路线上不在b1b2之间跳跃。

编辑:

  • 在第一个结果不是选项后停止回溯
  • 这条火车路线b1 / b2在10+之间是单数的,所以我不一定要寻找通用解决方案,所以原子名称检查会起作用(不知道怎么办)。

1 个答案:

答案 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集中的节点。