在 Prolog 中解决和调试逻辑难题
Solving and debugging a logic puzzle in Prolog
我正在尝试使用 Prolog 解决以下逻辑难题:
确定比赛中每位车手的名字和姓氏、每辆赛车的赞助商以及每位车手在比赛结束时的位置。
- Flash Automotive赞助的车手以第三名完赛。没有得到 Crank Motor Oil 赞助的霍华德没有以第五名的成绩完赛。
- Ryan,姓氏不对,不是由 NAPA Auto Parts 赞助的。 Barry Straight 不是由 Fleet Bodyworks 赞助的。
- Crank Motor Oil 赞助的车手比悉尼高一位,他的姓氏不是 Element。
- 先生。战车,他的名字不是亚当,获得了第一名。 Howard比Mr. Right低一位
- NAPA Auto Parts 赞助了获得第四名的车手,但他不是巴里。
- 五位车手排名不分先后,分别是第二名车手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.
我正在尝试使用 Prolog 解决以下逻辑难题:
确定比赛中每位车手的名字和姓氏、每辆赛车的赞助商以及每位车手在比赛结束时的位置。
- Flash Automotive赞助的车手以第三名完赛。没有得到 Crank Motor Oil 赞助的霍华德没有以第五名的成绩完赛。
- Ryan,姓氏不对,不是由 NAPA Auto Parts 赞助的。 Barry Straight 不是由 Fleet Bodyworks 赞助的。
- Crank Motor Oil 赞助的车手比悉尼高一位,他的姓氏不是 Element。
- 先生。战车,他的名字不是亚当,获得了第一名。 Howard比Mr. Right低一位
- NAPA Auto Parts 赞助了获得第四名的车手,但他不是巴里。
- 五位车手排名不分先后,分别是第二名车手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.