【问题标题】:Solving and debugging a logic puzzle in Prolog在 Prolog 中解决和调试逻辑难题
【发布时间】:2015-12-12 06:31:42
【问题描述】:

我正在尝试使用 Prolog 解决以下逻辑难题:

确定比赛中每位车手的姓名、每辆赛车的赞助商以及每位车手结束比赛的位置。

  1. Flash Automotive 赞助的车手以第三名完赛。没有获得 Crank Motor Oil 赞助的霍华德没有以第五名完赛。
  2. 瑞恩的姓氏不对,不是由 NAPA Auto Parts 赞助的。 Barry Straight 并非由 Fleet Bodyworks 赞助。
  3. Crank Motor Oil 赞助的车手比姓氏不是 Element 的 Sydney 高一位。
  4. 先生战车,名字不是亚当,获得了第一名。霍华德的位置比右先生低一位。
  5. NAPA Auto Parts 赞助了获得第四名的车手,而不是 Barry。
  6. 五位车手,排名不分先后,分别是第二名车手 Adam、Tredco Tires 赞助的车手、Mr. Right 和 Mr. Rafe。

使用与此处找到的方法类似的方法:http://www.anselm.edu/internet/compsci/faculty_staff/mmalita/HOMEPAGE/logic/aa6.txt

我想出了以下答案:

    race(Drivers) :- Drivers = [[howard,_,_,_],[barry,_,_,_],[ryan,_,_,_],
        [sydney,_,_,_],[adam,_,_,_],[_,straight,_,_],[_,chariot,_,_],
        [_,right,_,_],[_,element,_,_],[_,rafe,_,_],[_,_,flashautomotive,_],
        [_,_,crankmotoroil,_],[_,_,napaautoparts,_],[_,_,fleetbodyworks,_],
        [_,_,tredcotires,_],[_,_,_,1],[_,_,_,2],[_,_,_,3],[_,_,_,4],[_,_,_,5]],
        member([barry,straight,C,D], Drivers), C \= fleetbodyworks, 
            C \= napaautoparts, D \= 4,
        member([howard,_,G,H], Drivers), G \= crankmotoroil, H \= 5, H =:= X - 1,
        member([ryan,J,K,_], Drivers), J \= right, K \= napaautoparts,
        member([sydney,N,_,P], Drivers), N \= element,
        member([Q,chariot,_,T], Drivers), Q \= adam, T = 1,
        member([_,right,_,X], Drivers),
        member([_, _, _, crankmotoroil, DD], Drivers), DD =:= P + 1,
        member([EE,_,napaautoparts,HH], Drivers), HH = 4, EE \= barry,
        member([_,_,flashautomotive,LL], Drivers), LL = 3.

将其加载到 Windows SWI-Prolog IDE 中时,它不会出错,但在调试时会产生以下结果:

[debug] [1] 12 ?- race(X)
|    .
    T Call: (13) race(_G4168)
    T Fail: (13) race(_G4168)
false.

我显然对 Prolog 很陌生,但我想知道是什么可能导致它失败以及如何修复它(因为据我了解如何使用它的调试器在这种情况下不是很有帮助)。另外,有没有更简洁的方法来解决类似的逻辑问题?

【问题讨论】:

标签: debugging prolog logic


【解决方案1】:

您对“搜索空间”的表示不正确:在您链接的示例中,请注意只有 一个 值槽绑定到常量。在给定约束条件后,此类常量将有效地识别其他变量元素。

此外,让 Prolog 应用各个成员/2 执行的“排列游戏”,并且仅在 检查身份、差异等之后... 得到解决方案后,您可以尝试优化搜索过程向上移动检查,但总是在分配相关插槽之后...

一个不错的选择是使用数字字段,因此您可以以明显的方式应用算术来强制执行约束。所以,我试图修改你的代码:

race(Drivers) :-
    Drivers = [
        [_,_,_,1],
        [_,_,_,2],
        [_,_,_,3],
        [_,_,_,4],
        [_,_,_,5]
    ],
        member([barry,straight,C,D], Drivers),
        member([howard,_,G,H], Drivers),
        member([ryan,J,K,_], Drivers),
        member([sydney,N,_,P], Drivers),
        member([Q,chariot,_,T], Drivers),
        member([_,right,_,X], Drivers),
        member([_,_,crankmotoroil,DD], Drivers),
        member([EE,_,napaautoparts,HH], Drivers),
        member([_,_,flashautomotive,LL], Drivers),

    C \= fleetbodyworks, C \= napaautoparts, D \= 4,
    G \= crankmotoroil, H \= 5, H =:= X - 1,
    J \= right, K \= napaautoparts,
    N \= element,
    Q \= adam, T = 1,
%   DD =:= P + 1,
    HH = 4, EE \= barry,
    LL = 3.

注意注释行:如果取消注释,则没有可用的解决方案...注释掉限制是可用于这种简单模式的更简单的调试工具。

【讨论】:

  • 太棒了!这很有帮助。非常感谢!
【解决方案2】:

这是基于 CapelliC 回答的有效解决方案。在我最初误读了部分问题并忘记了一些规则的帮助下,因此修复了错误并在此解决方案中添加了其他规则。

    race(Drivers) :-
        Drivers = [
            [_,_,_,1],
            [_,_,_,2],
            [_,_,_,3],
            [_,_,_,4],
            [_,_,_,5]
        ],
            member([barry,straight,Barrysponsor,Barryplace], Drivers),
            member([howard,_,Howardsponsor,Howardplace], Drivers),
            member([ryan,Ryanlastname,Ryansponsor,_], Drivers),
            member([sydney,Sydneylastname,_,Sydneyplace], Drivers),
            member([adam,Adamlastname,Adamsponsor,Adamplace], Drivers),
            member([Chariotfirstname,chariot,_,1], Drivers),
            member([Rightfirstname,right,Rightsponsor,Rightplace], Drivers),
            member([_,element,_,_], Drivers),
            member([_,rafe,_,_], Drivers),
            member([_,_,crankmotoroil,Crankmotoroilplace], Drivers),
            member([Napaautopartsfirstname,_,napaautoparts,4], Drivers),
            member([_,_,flashautomotive,3], Drivers),
            member([Tredcotiresfirstname,Tredcotireslastname,tredcotires,Tredcotiresplace], Drivers),
            member([_,_,fleetbodyworks,_], Drivers),

    Barrysponsor \= fleetbodyworks, Barrysponsor \= napaautoparts, Barryplace \= 4,
    Howardsponsor \= crankmotoroil, Howardplace \= 5, Howardplace =:= Rightplace + 1,
    Ryanlastname \= right, Ryansponsor \= napaautoparts,
    Adamplace \= 2, Adamsponsor \= tredcotires,
    Adamlastname \= right, Adamlastname \= rafe,
    Sydneylastname \= element,
    Chariotfirstname \= adam,
    Rightfirstname \= adam, Rightplace \= 2, Rightsponsor \= tredcotires,
    Crankmotoroilplace =:= Sydneyplace - 1,
    Napaautopartsfirstname \= barry,
    Tredcotiresfirstname \= adam, Tredcotiresplace \= 2, 
    Tredcotireslastname \= rafe, Tredcotireslastname \= right.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 2023-03-27
    • 2013-08-19
    • 1970-01-01
    • 1970-01-01
    • 2014-06-06
    • 1970-01-01
    相关资源
    最近更新 更多