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

时间:2015-12-12 06:31:42

标签: debugging prolog logic

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

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

  1. 由Flash Automotive赞助的车手以第三名完赛。不是由Crank Motor Oil赞助的霍华德没有以第五名的成绩完成比赛。
  2. Ryan,其姓氏不对,不是由NAPA Auto Parts赞助的。 Barry Straight不是由Fleet Bodyworks赞助的。
  3. 由Crank Motor Oil赞助的车手比悉尼的位置高出一个位置,悉尼的姓氏不是Element。
  4. 先生。战车的名字不是亚当,最终名列第一。霍华德的位置低于右先生。
  5. NAPA Auto Parts赞助了排在第四位的车手,而不是巴里。
  6. 五位车手,没有特别的顺序,是亚当,第二位车手,由Tredco Tires,Right先生和Rafe先生赞助的车手。
  7. 使用与此处相似的方法: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很新,但我想知道是什么原因可能会导致失败以及如何解决它(因为我理解如何使用它的调试器在这个实例中并不是很有帮助)。还有,有更简洁的方法来解决类似的逻辑问题吗?

2 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:0)

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