我目前正在撰写铁路线计划,但使用来自事实的列表时遇到了一些麻烦。我是Prolog的新手,到目前为止已经写了以下事实和规则:
location(euston, [northernLine]).
location(warrenStreet, [victoriaLine, northernLine]).
location(warwickAvenue, [bakerlooLine]).
location(paddington, [bakerlooLine]).
hasCommonLine(Location1, Location2, Line) :-
location(Location1, Line),
location(Location2, Line).
该想法是规则返回两个位置共有的行的名称。如果我尝试hasCommonLine(warwickAvenue,paddington,Line).
,这会有效,但如果我尝试hasCommonLine(euston,warrenStreet,Line).
,则会返回false。
我怀疑这是因为规则只检查列表的第一个元素,因此只比较[northernLine]
和[victoriaLine]
而不是检查列表中的每个元素。任何有关实现这一目标的指导都将非常感谢!
答案 0 :(得分:2)
我怀疑这是因为规则只检查列表的第一个元素。
不,程序会检查两个列表是否相同。因此,只有当两个Line
完全等效(相同的元素,相同的顺序)时,它们才匹配。
使用列表指定行列表是 un-Prolog 。通常他们将其表示为以下事实列表:
location_new(euston,northernLine).
location_new(warrenStreet,victoriaLine).
location_new(warrenStreet,northernLine).
location_new(warwickAvenue,bakerlooLine).
location_new(paddington,bakerlooLine).
所以此处warrenStreet
发生两次:一次使用victoriaLine
,一次使用northernLine
。然后你可以简单地写:
hasCommonLine(Location1, Location2, Line) :-
location_new(Location1, Line),
location_new(Location2, Line).
尽管如此,你可以写一个帮助谓词location_helper/2
:
location_helper(A,B) :-
location(A,L),
member(B,L).
然后定义:
hasCommonLine(Location1, Location2, Line) :-
location_helper(Location1, Line),
location_helper(Location2, Line).
答案 1 :(得分:2)
您可以检查Line
是否是两个列表的成员:
hasCommonLine(Location1, Location2, Line) :-
location(Location1, Lines1),
location(Location2, Lines2),
member(Line, Lines1),
member(Line, Lines2).
然后,如果您需要找到两个位置之间共有的所有行,您只需调用
即可 ?- findall(X, hasCommonLine(euston, warrenStreet, X), Y).
Y = [northernLine].
答案 2 :(得分:1)
你的规则需要改进 现在,它检查两个位置是否具有完全相同的行列表。
你应该做的是制定检查两者之间是否重叠的规则。您可以使用一个谓词来检查两个列表的交集。
它看起来像这样:
hasCommonLine(Location1,Location2, CommonLines):-
location(Location1,Line1),
location(Location2,Line2),
intersection(Line1,Line2,CommonLines).