在 Prolog 中解决和调试逻辑难题

Solving and debugging a logic puzzle in Prolog

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

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

  1. Flash Automotive赞助的车手以第三名完赛。没有得到 Crank Motor Oil 赞助的霍华德没有以第五名的成绩完赛。
  2. Ryan,姓氏不对,不是由 NAPA Auto Parts 赞助的。 Barry Straight 不是由 Fleet Bodyworks 赞助的。
  3. Crank Motor Oil 赞助的车手比悉尼高一位,他的姓氏不是 Element。
  4. 先生。战车,他的名字不是亚当,获得了第一名。 Howard比Mr. Right低一位
  5. NAPA Auto Parts 赞助了获得第四名的车手,但他不是巴里。
  6. 五位车手排名不分先后,分别是第二名车手Adam、Tredco轮胎赞助车手、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 的新手,但我想知道可能导致此失败的原因以及如何修复它(因为我了解如何使用它的调试器在这种情况下不是很有帮助) .另外,有没有更简洁的方法来解决类似的逻辑问题?

您对 'search space' 的表示不正确:在您链接的示例中,请注意只有 一个 值槽绑定到常量。这样的常量将有效地用于 识别 其他变量元素在给定约束条件下到达正确位置后。

此外,让 Prolog 应用由各种 member/2 执行的 'permutation game',并且仅 after 检查身份、差异等...之后得到一个解决方案,你可以尝试优化搜索过程,向上移动检查,但总是分配相关插槽之后...

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

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.

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

这是一个基于 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.