【问题标题】:Using a list from a fact within Prolog rules在 Prolog 规则中使用事实列表
【发布时间】:2017-01-17 13:46:18
【问题描述】:

我目前正在编写一个铁路线程序,但在使用来自事实的列表时遇到了一点麻烦。我对 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] 而不是检查列表中的每个元素。任何指导来实现这一点将不胜感激!

【问题讨论】:

    标签: list prolog fact


    【解决方案1】:

    您可以检查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】:

      我怀疑这是因为规则只检查列表的第一个元素。

      否,程序会检查两个列表是否相同。因此,只有当两个 Lines 完全等价(相同元素、相同顺序)时,它们才会匹配。

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

      【讨论】:

      • 我猜他们将其指定为一个列表,因为这是一个练习。下一个练习很可能是“添加 20 行”。
      • 感谢您纠正我的怀疑并提供如此丰富的答案。 :)
      【解决方案3】:

      您的规则需要改进。
      现在,它会检查这两个位置是否具有完全相同的行列表。

      您应该做的是制定一个规则来检查两者之间是否存在重叠。您可以使用谓词来检查两个列表的交集。

      看起来像这样:

      hasCommonLine(Location1,Location2, CommonLines):-
          location(Location1,Line1),
          location(Location2,Line2),
          intersection(Line1,Line2,CommonLines).
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多