Debugging Prolog中逻辑难题的解决与调试

Debugging Prolog中逻辑难题的解决与调试,debugging,prolog,logic,Debugging,Prolog,Logic,我正在尝试使用Prolog解决以下逻辑难题: 确定比赛中每个车手的名字和姓氏,每辆赛车的赞助商,以及每个车手结束比赛的位置 由Flash Automotive赞助的车手以第三名的成绩完成了比赛。霍华德没有得到曲柄机油公司的赞助,他没有以第五名的成绩完成比赛 Ryan的姓氏不对,他不是NAPA汽车配件公司的赞助商。巴里·斯特朗不是车队车身公司赞助的 由Crank Motor Oil赞助的车手排名比悉尼高一位,悉尼的姓不是Element 查里特先生,他的名字不是亚当,排在第一位。霍华德比右先生低一个

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

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

  • 由Flash Automotive赞助的车手以第三名的成绩完成了比赛。霍华德没有得到曲柄机油公司的赞助,他没有以第五名的成绩完成比赛
  • Ryan的姓氏不对,他不是NAPA汽车配件公司的赞助商。巴里·斯特朗不是车队车身公司赞助的
  • 由Crank Motor Oil赞助的车手排名比悉尼高一位,悉尼的姓不是Element
  • 查里特先生,他的名字不是亚当,排在第一位。霍华德比右先生低一个位置
  • 纳帕汽车配件公司赞助了获得第四名的车手,他不是巴里
  • 这五位车手,没有特别的顺序,分别是亚当斯,第二名车手,由特雷德科轮胎公司赞助的车手,右先生和雷夫先生
  • 使用与此处类似的方法:

    我得出了以下答案:

        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很陌生,但我想知道是什么原因导致它失败,以及如何修复它(因为我所理解的调试器在这种情况下如何使用它不是很有帮助)。还有,有没有更干净的方法来解决类似的逻辑问题?

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

    此外,让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.
    

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

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

        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.
    

    使用而不是
    (\=)/2
    !令人惊叹的!这很有帮助。非常感谢你!