在火车时刻表中找到一种方法并使用line-nr获得变更站

时间:2016-06-16 11:54:03

标签: algorithm search prolog

我正试图在火车时刻表中找到一种方法并获得变更站和线路。但是当你不得不改变火车时我会遇到麻烦。首先是时间表数据库中的代码和(长)片段。

数据库

%Linie 3A (Richtung Wiler Mann) 
%          lineNr, A,B,time(minute)
verbindung('3A',[pirnaischer, platz], [albertplatz], [18, 28, 38, 48, 58, 08]).
verbindung('3A',[albertplatz], [bahnhof, neustadt], [23, 33, 43, 53, 03, 13]).
verbindung('3A',[bahnhof, neustadt], [hansastraße], [25, 35, 45, 55, 05, 15]).
verbindung('3A',[hansastraße], [liststraße], [26, 36, 46, 56, 06, 16]).
verbindung('3A',[liststraße], [trachenberger, platz], [30, 40, 50, 00, 10, 20]).
verbindung('3A',[trachenberger, platz], [hubertusplatz], [33, 43, 53, 03, 13, 23]).
verbindung('3A',[hubertusplatz], [wilder, mann], [35, 45, 55, 05, 15, 25]).
verbindung('3A',[wilder, mann], [xxx1], [38, 48, 58, 08, 18, 28]). 
%xxx ist hier damit man auch die ankuftszeiten an der Enthaltestelle angeben kann.

%Linie 3B = Linie 3 Richtung coschütz
verbindung('3B',[wilder, mann],[hubertusplatz], [04, 14, 24, 34, 44, 54]). 
verbindung('3B',[hubertusplatz],[trachenberger, platz], [06, 16, 26, 36, 46, 56]).
verbindung('3B',[trachenberger, platz],[liststraße], [08, 18, 28, 38, 48, 58]).
verbindung('3B',[liststraße],[hansastraße], [11, 21, 31, 41, 51, 01]).
verbindung('3B',[hansastraße], [bahnhof, neustadt], [14, 24, 34, 44, 54, 04]).
verbindung('3B',[bahnhof, neustadt], [albertplatz],[16, 26, 36, 46, 56, 06]).
verbindung('3B',[albertplatz], [pirnaischer, platz], [18, 28, 38, 48, 58, 08]).
verbindung('3B',[pirnaischer, platz], [xxx2], [23, 33, 43, 53, 03, 13]).

%Linie 1 (Richtung leutewitz)
verbindung('1A',[pirnaischer, platz],[postplatz],[31,41,51,01,11,21]).
verbindung('1A',[postplatz],[bahnhof, mitte],[34,44,54,04,14,24]).
verbindung('1A',[bahnhof, mitte],[waltherstraße],[38,48,58,08,18,28]).
verbindung('1A',[waltherstraße],[flügelweg],[42,52,02,12,22,32]).
verbindung('1A',[flügelweg],[gottfried-keller-straße],[45,55,05,15,25,35]).
verbindung('1A',[gottfried-keller-straße],[leutewitz],[48,58,08,18,28,38]).
verbindung('1A',[leutewitz],[xxx3],[50,00,10,20,30,40]).

%Linie 1 (Richtung prohlis, schleife)
verbindung('1B',[leutewitz],[gottfried-keller-straße],[04,14,24,34,44,54]).
verbindung('1B',[gottfried-keller-straße],[flügelweg],[06,16,26,36,46,56]).
verbindung('1B',[flügelweg],[waltherstraße],[09,19,29,39,49,59]).
verbindung('1B',[waltherstraße],[bahnhof, mitte],[12,22,32,42,52,02]).
verbindung('1B',[bahnhof, mitte],[postplatz],[17,27,37,47,57,07]).
verbindung('1B',[postplatz],[altmarkt],[21,31,41,51,01,11]).
verbindung('1B',[altmarkt],[pirnaischer, platz],[22,32,42,52,02,12]).
verbindung('1B',[pirnaischer, platz],[xxx4],[24,34,44,54,04,14]).

%Linie94
verbindung('94A',[postplatz],[bahnhof, mitte],[07, 27, 47]).
verbindung('94A',[bahnhof, mitte],[krankenhaus, friedrichstadt],[11, 31, 51]).
verbindung('94A',[krankenhaus, friedrichstadt],[waltherstraße],[14, 34, 54]).
verbindung('94A',[waltherstraße],[flügelweg],[17, 37, 57]).
verbindung('94A',[flügelweg],[gottfried-geller-straße],[20, 40, 50]).
verbindung('94A',[gottfried-keller-straße],[zschonergrundstraße],[23, 43, 03]).
verbindung('94A',[zschonergrundstraße],[am, urnenfeld],[27, 47, 07]).
verbindung('94A',[am, urnenfeld],[ludwigstraße],[32, 52, 12]).
verbindung('94A',[ludwigstraße],[erna-berger-straße],[35, 55, 15]).
verbindung('94A',[erna-berger-straße],[cossebaude, bahnhof],[37, 57, 17]).
verbindung('94A',[cossebaude, bahnhof],[xxx9],[38, 58, 18]).

搜索谓词

dlDfs(Node, Goal, Path,LinienPath,UmstiegPath, LinienLimit, ReturnPath, ReturnLinie, ReturnUmstieg) :-
    Node = Goal,
    reverse(Path, ReturnPath),
    reverse(LinienPath, ReturnLinie),
    reverse(UmstiegPath, ReturnUmstieg)
    ;
    0 =< LinienLimit,
    verbindung(Linie,Node,NewNeighbor,_),
    not(member(NewNeighbor,Path)),
    (
        (
            not(member(Linie, LinienPath)), NewLinienLimit is LinienLimit - 1,
            dlDfs(NewNeighbor, Goal, [NewNeighbor|Path], [Linie|LinienPath], [Node|UmstiegPath], NewLinienLimit, ReturnPath, ReturnLinie, ReturnUmstieg)
        )
    ;
        (dlDfs(NewNeighbor, Goal, [NewNeighbor|Path], LinienPath, UmstiegPath, LinienLimit, ReturnPath, ReturnLinie,ReturnUmstieg)
    )).

idDfsLoop(Start, Goal,L, ReturnPath, ReturnLinie, ReturnUmstieg) :-
    dlDfs(Start, Goal, [Start],[], [], L, ReturnPath, ReturnLinie, ReturnUmstieg)
    ;
    L1 is L + 1,
    idDfsLoop(Start, Goal, L1, ReturnPath, ReturnLinie, ReturnUmstieg).

idDfs(Start, Goal, ReturnPath, ReturnLinie, ReturnUmstieg) :-
    idDfsLoop(Start, Goal, 1, ReturnPath, ReturnLinie, ReturnUmstieg),
    !.

如果我试图找到从“albertplatz”到“erna-berger-straße”的方式,我必须改变3次火车线路。 现在,当我打电话

 idDfs([albertplatz], [erna-berger-straße], Path, ChangeLine,
 ChangeStop).

程序应该返回

 Path = [The hole Path],
 ChangeLine = ['3B', '1A', '94A'],
 ChangeStop[[albertplatz],[pirnaischer,platz], [...]].

但我只能

 Path = [The hole Path], 
 ChangeLine = ['3B', '94A'],   
 ChangeLine = [[albertplatz], [am, urnenfeld]].

我不知道为什么。如果我测试从[albertplatz]到[postplatz]的方式,程序会给我正确答案,可能是因为只有一个更改停止。

编辑:

感谢@ SQB的帮助,我解决了我的问题,这是新的工作搜索谓词

搜索谓词 - 解决方案

dlDfs(Goal, Goal, Path, LinienPath, CurrentLine, UmstiegPath, ReturnPath, ReturnLinie, ReturnUmstieg) :-
    reverse(Path, ReturnPath),
    reverse(LinienPath, ReturnLinie),
    reverse(UmstiegPath, ReturnUmstieg).


dlDfs(Node, Goal, Path, LinienPath, CurrentLine, UmstiegPath,  ReturnPath, ReturnLinie, ReturnUmstieg) :-
    verbindung(CurrentLine, Node, NewNeighbor,_),
    not(member(NewNeighbor, Path)),
    (
        not(member(CurrentLine, LinienPath)),
        dlDfs(NewNeighbor, Goal, [NewNeighbor|Path], [CurrentLine|LinienPath], CurrentLine, [Node|UmstiegPath], ReturnPath, ReturnLinie, ReturnUmstieg)
    ;
        dlDfs(NewNeighbor, Goal, [NewNeighbor|Path], LinienPath, CurrentLine, UmstiegPath, ReturnPath, ReturnLinie,ReturnUmstieg)
    ).

dlDfs(Node, Goal, Path, LinienPath, CurrentLine, UmstiegPath, ReturnPath, ReturnLinie, ReturnUmstieg) :-
    verbindung(Linie, Node, NewNeighbor,_),
    not(Linie == CurrentLine),
    not(member(NewNeighbor, Path)),
    not(member(Linie, LinienPath)),
    dlDfs(NewNeighbor, Goal, [NewNeighbor|Path], [Linie|LinienPath], Linie, [Node|UmstiegPath], ReturnPath, ReturnLinie, ReturnUmstieg). 

1 个答案:

答案 0 :(得分:0)

问题出在dlDfs/9,我冒昧地分手了。

dlDfs(Goal, Goal, Path, LinienPath, UmstiegPath, _LinienLimit, ReturnPath, ReturnLinie, ReturnUmstieg) :-
    reverse(Path, ReturnPath),
    reverse(LinienPath, ReturnLinie),
    reverse(UmstiegPath, ReturnUmstieg).

dlDfs(Node, Goal, Path, LinienPath, UmstiegPath, LinienLimit, ReturnPath, ReturnLinie, ReturnUmstieg) :-
    0 =< LinienLimit,
    verbindung(Linie, Node, NewNeighbor,_),
    not(member(NewNeighbor, Path)),
    (
        not(member(Linie, LinienPath)),
        NewLinienLimit is LinienLimit - 1,
        dlDfs(NewNeighbor, Goal, [NewNeighbor|Path], [Linie|LinienPath], [Node|UmstiegPath], NewLinienLimit, ReturnPath, ReturnLinie, ReturnUmstieg)
    ;
        dlDfs(NewNeighbor, Goal, [NewNeighbor|Path], LinienPath, UmstiegPath, LinienLimit, ReturnPath, ReturnLinie,ReturnUmstieg)
    ).

问题出在第二个问题上。你做了一些检查,然后你有两条路径。第一个是新的Linie是否已经在LinienPath中(顺便提一下,英语和德语的有趣组合)。您减少LinienLimit并再次调用dlDfs 然而,如果失败,例如因为LinienLimit低于0,则采用第二条路径,其中新找到的节点仍然添加到路径中,但未添加该行到行列表 - ,即使它是一个新行

我认为,您需要做的不仅仅是检查行是否在已经拍摄的行列表中,还要检查您找到连接的行是否是您当前所在的行。

我的建议是将谓词分成几个子句,而不是使用分号。然后,对于dlDfs,您有几种情况需要定义。

  1. 你找到了自己的目标。那是我已经拆分的那个。
  2. 您找到了一条与您已经在同一条线上的新连接。
  3. 您找到了一个新连接,但它已经在您之前没有骑过的路线上。
  4. 完全不同的方法是检查您的起点在哪一行,您的目标在哪一行,以及如何连接这些行。
    这就是人类会这样做的原因:“啊,是的,ErnaBergerstraße在第94行,我现在在第3行的Albertplatz,让我们看看,这些线路没有连接,但我可以在Pirnaischer Platz改变到上线1,再到Ludwigstrasse,乘94号线前往ErnaBergerstraße。“

    另外,你曾经拼错过“gottfried-keller-straße”。