如何根据他们所在的行获取所有电台列表?

时间:2017-01-25 17:39:16

标签: list prolog

我有以下几点事实:

行名称:

line(ecLine).
line(wcLine).
line(mLine).
line(gwLine).
line(swLine).

电台名称和各自的行列表:

station(london,       [ecLine, wcLine, mLine, gwLine, swLine]).
station(bristol,      [gwLine, wcLine]).
station(rugby,        [wcLine]).
station(birmingham,   [wcLine]).
station(crewe,        [wcLine]).
station(liverpool,    [wcLine]).
station(manchester,   [wcLine, mLine]).
station(carlisle,     [wcLine]).
station(glasgow,      [wcLine]).
station(edinburgh,    [wcLine]).
station(leicester,    [mLine]).
station(sheffield,    [mLine]).
station(peterborough, [ecLine]).
station(york,         [ecLine]).
station(newcastle,    [ecLine]).
station(edinburgh,    [ecLine]).
station(oxford,       [ecLine]).

彼此相邻的站点:

adjacent(london,       bristol).
adjacent(london,       oxford).
adjacent(london,       rugby).
adjacent(london,       leicester).
adjacent(london,       peterborough).
adjacent(bristol,      birmingham).
adjacent(rugby,        birmingham).
adjacent(birmingham,   crewe).
adjacent(rugby,        crewe).
adjacent(crewe,        liverpool).
adjacent(crewe,        manchester).
adjacent(crewe,        carlisle).
adjacent(manchester,   carlisle).
adjacent(carlisle,     glasgow).
adjacent(carlisle,     edinburgh).
adjacent(leicester,    sheffield).
adjacent(sheffield,    manchester).
adjacent(peterborough, york).
adjacent(york,         newcastle).
adjacent(newcastle,    edinburgh).

以下规则:

使相邻关系成双向的规则:

twoWay(X, Y) :- adjacent(X, Y); adjacent(Y, X).

我的规则返回给定行名称的站点列表:

line(Line, StationList) :-
    findall(Station,
        (line(Line),
         station(Station, ListOfLines),
         member(Line, ListOfLines)
        ),
        StationList).

在查询中给出行名称时,这样可以正常工作,如下所示:

?- line(mLine, LineList).
LineList = [london,manchester,leicester,sheffield].

但是,如果我没有为规则'行'提供行名称,则会返回以下内容:

?- line(Line, StationList).
StationList = [london,peterborough,york,newcastle,edinburgh,oxford,london,bristol|...].

它不会返回所有电台,因为它太大而无法写入控制台 - 此时我认为它将所有电台都放到一个列表中。但是,如果我按如下方式覆盖Prolog' answer_write_options

set_prolog_flag(answer_write_options,[max_depth(0)]).

这是发生的事情:

?- line(Line, StationList).
StationList = [london,peterborough,york,newcastle,edinburgh,oxford,
              london,bristol,rugby,birmingham,crewe,liverpool,
              manchester,carlisle,glasgow,edinburgh,london,manchester,
              leicester,sheffield,london,bristol,london,oxford].

它不仅会给所有电台,而且会重复其中一些电台。

简而言之:鉴于上述所有事实,是否有可能编写一条规则,返回每个行名称后跟该行中的站点列表,最好采用以下格式(我可以容忍任何格式,但这是我的偏好):

Line = ecLine
LineList = [london,peterborough,york,newcastle,edinburgh,oxford]

Line = mLine
LineList = [london,manchester,leicester,sheffield]

Line = ...

等等。

提前致谢。

1 个答案:

答案 0 :(得分:2)

首先使用Line首先实例化line/1

line(Line,StationList) :-
    line(Line), %ground Line with a valid line
    findall(Station,(station(Station,Lines),member(Line,Lines)),StationList).

如果我查询两个未实例化的变量:

?- line(Line,StationList).
Line = ecLine,
StationList = [london, peterborough, york, newcastle, edinburgh, oxford] ;
Line = wcLine,
StationList = [london, bristol, rugby, birmingham, crewe, liverpool, manchester, carlisle, glasgow|...] ;
Line = mLine,
StationList = [london, manchester, leicester, sheffield] ;
Line = gwLine,
StationList = [london, bristol] ;
Line = swLine,
StationList = [london].

Line已修复:

?- line(wcLine,StationList).
StationList = [london, bristol, rugby, birmingham, crewe, liverpool, manchester, carlisle, glasgow|...].

StationList

?- line(Line,[london]).
Line = swLine.

或最后两者:

?- line(wcLine,[london]).
false.

?- line(swLine,[london]).
true.

通过调用line(Line),结果是从现在开始Line的基础是:例如Line = gwLine,然后运行查询,如:

findall(Station,(station(Station,Lines),member(gwLine,Lines)),StationList).

哪个 - 就像您自己已经找到的那样 - 找到Lines列表中映射的所有电台,其中gwLinemember/2。然后将它们放入StationList并因此可以返回。