在Prolog上寻找杀手er

我们公司每个星期天习惯安排有趣的测验,这是其中之一。

谜语


要找到Boddy先生的杀手,您需要找出每个人的位置以及房间中的武器。 提示分散在整个测验中(您必须阅读所有十个答案才能回答第一个问题)。

  • 首先,想象一下犯罪嫌疑人。 有三名男子(乔治,约翰,罗伯特)和三名女子(芭芭拉,克里斯蒂娜,约兰达)。 每个人都在单独的房间中(浴室,餐厅,厨房,客厅,厨房,办公室)。 在每个房间里发现了可疑武器(袋子,枪支,汽油,小刀,毒药,绳索)。 问题:谁在厨房里被发现?
  • 提示1.一个男人在厨房里既没有绳索,也没有刀子,也没有袋子。 该武器不是枪支。 问题:在厨房里发现了什么武器?

  • 提示2。芭芭拉在书房或浴室中,而约兰达在两个命名的房间中。 芭芭拉在哪个房间找到了?
  • 提示3.提包的人既不是芭芭拉也不是乔治,他既不在浴室也不在饭厅。 谁拿了袋子?
  • 提示4.在办公室里发现了一个有绳子的女人。 那是谁啊
  • 提示5.客厅里的武器属于约翰或乔治。 客厅里有什么样的武器?
  • 提示6.饭厅里没有刀。 刀在哪里?
  • 提示7.约兰达既没有在办公室也没有在餐具室里,没有为这些房间配备适当的武器。 尤兰达拥有哪种武器?
  • 提示8.乔治找到了枪支。 哪个房间
  • 人们发现博迪先生在储藏室里被毒气了。 那个房间里的嫌疑犯是杀手。 这是谁啊

我对这样的难题感到困惑(实际上几乎所有难题都如此)。 他们可能需要花费数小时和数小时的反思,但是Prolog总是可以帮助您! 让我们看看如何解决推理中的此类问题。

序言101


安装SWI-Prolog


~> swipl Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.6.6) Copyright (c) 1990-2013 University of Amsterdam, VU Amsterdam SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. Please visit http://www.swi-prolog.org for details. For help, use ?- help(Topic). or ?- apropos(Word). ?- write('Hello, World!'). Hello, World! true. ?- write('Hello,'), nl, write('world'). Hello, world true. ?- X is 3*4 + 2. X = 14. 

  • swipl -Prolog解释器
  • write称为函子, write/1表示表示它需要1个参数(Erlang和Elixir中的相同概念将参数数量添加到函数名称中)
  • nl用于打印新行
  • 命令序列用逗号分隔,也替换了AND运算符
  • 赋值运算符后跟一个数学表达式
  • 变量以大写X而不是x书写

知识库


Prolog的实质是陈述事实,汇编事实并提出要求。

创建hello.pl文件:

 friend(john, julia). friend(john, jack). friend(julia, sam). friend(julia, molly). loves(john, julia). loves(julia, sam). loves(sam, julia). male(brad). male(john). male(jim). male(alfred). female(marry). child(brad, alfred). child(john, jim). child(john, marry). 

  • 我们使用[hello].进行加载[hello]. :注意最后一点
  • listing列出了知识库中的所有事实

 ?- [hello]. % hello compiled 0.00 sec, 3 clauses true. ?- listing(friend). friend(john, julia). friend(john, jack). friend(julia, sam). friend(julia, molly). true. ?- listing(loves). loves(john, julia). loves(julia, sam). loves(sam, julia). true. 

要求事实


在知识库中陈述事实之后,我们可以走得更远,并提出有关事实真相的问题,以及可以从中得出什么结论的问题。

 ?- friend(john, julia). true . ?- friend(john, jack). true. ?- loves(john, julia). true. ?- loves(john, sam). false. 

我们可以提出更复杂的问题。 例如,谁是John的朋友,或者是谁喜欢Julia。

 ?- friend(john, Who). Who = julia ; Who = jack. 

 ?- listing(child). child(brad, alfred). child(john, jim). child(john, mary). true. ?- child(john, X). X = jim ; X = mary. 

约翰在朋友圈吗?


我们已经建立了John与Julia的友谊( friend(john, julia) ),但是对于Prolog,这并不意味着Julia是John的朋友:您需要添加另一个事实friend(julia, john) 。 我们还指出了谁有孩子,显然不想重复代码,分别指出了每个孩子的父母。 我们不想写这样的东西

 child(brad, alfred). child(john, jim). child(john, mary). parent(alfred, brad). parent(jim, john). parent(mary, john). 

Prolog有助于避免与逻辑结论规则重复:

 rule :- stmt1, stmt2,... 

如果所有内部语句为真(列出并用逗号逻辑折叠),则该规则为真。

 friend(X, Y) :- friend(Y,X). parent(X, Y) :- child(Y,X). father(X, Y) :- child(Y,X), male(X). mother(X, Y) :- child(Y,X), female(X). friendzoned(X) :- loves(X, Y), \+ loves(Y,X). 

  • friend(X,Y)friend(Y,Xfriend(X,Y)正确的
  • child(Y,X)parent(X,Y) true
  • father(X,Y)parent(X,Y)male(X)
  • mother(X,Y) parent(X,Y)female(X)mother(X,Y)
  • 如果X爱SOMEONE Y而Y不爱X,则friendzoned(X)真(注意隐藏变量Y?)

 ?- friend(julia, john). true . ?- male(jim). true. ?- parent(jim,X). X = john. ?- father(jim, X). X = john. ?- mother(X, john). X = marry. ?- mother(marry,X). X = john. ?- mother(marry, john). true. ?- loves(julia, X). X = sam. ?- friendzoned(julia). false. ?- friendzoned(john). true. 

好的,现在我们掌握了所有必要的知识。 让我们练习一下地图的着色。

卡片着色


让我们从众所周知的数学问题开始。 要求相邻区域的颜色不要相同。



因此,推理应该是这样,我们有三件事:

  1. 变量是我们要着色的区域:A,B,C,D,E。
  2. 域-可以分配给变量的值的范围:红色,蓝色,绿色。
  3. 限制是相邻区域不能具有相同的颜色。


定义我们区域的域(红色,绿色,蓝色)。

 color(red). color(green). color(blue). 

仅此而已。

我们要求解决方案


 colorify(A,B,C,D,E) :- color(A), color(B), color(C), color(D), color(E), \+ A=B, \+ A=C, \+ A=D, \+ A=E, \+ B=C, \+ C=D, \+ D=E. 

在这里,我们将解决方案定义为使用五个变量A,B,C,D,E进行着色的规则,并在规则内为变量分配域颜色(红色,蓝色,绿色),并设置A不等于B,不等于C的限制...以及等

\+ X=Y表示X不等于Y

Prolog将继续生成值,直到找到满足限制条件的规则的选项为止。

 ?- [mapcoloring] | . true. ?- colorify(A,B,C,D,E) | . A = red, B = D, D = green, C = E, E = blue ; A = red, B = D, D = blue, C = E, E = green ; A = green, B = D, D = red, C = E, E = blue ; A = green, B = D, D = blue, C = E, E = red ; A = blue, B = D, D = red, C = E, E = green ; A = blue, B = D, D = green, C = E, E = red 

 color(red). color(green). color(blue). colorify(A,B,C,D,E) :- color(A), color(B), color(C), color(D), color(E), \+ A=B, \+ A=C, \+ A=D, \+ A=E, \+ B=C, \+ C=D, \+ D=E. 

...但是我们不是在给图片上色,而是在寻找杀手.。

杀人


首先,想象一下犯罪嫌疑人。 有三名男子(乔治,约翰,罗伯特)和三名女子(芭芭拉,克里斯蒂娜,约兰达)。 每个人都在单独的房间中(浴室,餐厅,厨房,客厅,厨房,办公室)。 在每个房间里发现了可疑武器(袋子,枪支,汽油,小刀,毒药,绳索)。

谁在厨房里找到的?


由此我们可以得出结论,我们有五个域: manwomanperson或嫌疑人, locationweapons ,我们的变量(A,B,C,D,E,F)应同时代表人,地点和武器具有一些局限性,这些局限性将在以后的技巧中揭示。

 man(george). man(john). man(robert). woman(barbara). woman(christine). woman(yolanda). person(X):- man(X). person(X):- woman(X). location(bathroom). location(dining). location(kitchen). location(livingroom). location(pantry). location(study). weapon(bag). weapon(firearm). weapon(gas). weapon(knife). weapon(poison). weapon(rope). 

uniq_ppl规则为我们的变量生成唯一值。

 uniq_ppl(A,B,C,D,E,F):- person(A), person(B), person(C), person(D), person(E), person(F), \+A=B, \+A=C, \+A=D, \+A=E, \+A=F, \+B=C, \+B=D, \+B=E, \+B=F, \+C=D, \+C=E, \+C=F, \+D=E, \+D=F, \+E=F. 

解决方案


我们首先定义一个地方拥有独特武器的人和拥有武器独特的人的杀手的规则,现在将说明地方武器与拥有武器的人之间的关系

请注意,我们还有六个嫌疑人。

参赛作品


 murderer(X) :- uniq_ppl(Bathroom, Dining, Kitchen, Livingroom, Pantry, Study), uniq_ppl(Bag, Firearm, Gas, Knife, Poison, Rope), 

为了轻松讨论变量,例如浴室,饭厅,枪支,煤气,我们立即确定:

  • 浴室-浴室里是同一名嫌疑犯(男性或女性)
  • 枪支-拥有枪支的嫌疑犯(男性或女性)
  • 等等...你可以把它想象成一个网格

现在,我们在murderer规则的最后一个逗号之后继续添加限制。

秘诀1


有一个男人在厨房里,没有绳子,刀子或袋子。 该武器不是枪支。 厨房里有什么武器?

 % 2. Clue 1: The man in the kitchen was not found with the rope, knife, or bag. % Which weapon, then, which was not the firearm, was found in the kitchen? man(Kitchen), \+Kitchen=Rope, \+Kitchen=Knife, \+Kitchen=Bag, \+Kitchen=Firearm, 

在这里,我们说Kitchen变量满足了man的事实(在我们的领域中定义),并声明无论该人在厨房中的是谁,他都不具有以下任何一项: RopeKnifeBagFirearm

提示2


提示2。芭芭拉在书房或浴室中,而约兰达在两个命名的房间中。 芭芭拉在哪个房间找到了?

因此,我们可以说在办公室和浴室里有一个woman ,而这不是克里斯蒂娜,我们还排除了芭芭拉和约兰达的其他选择(厨房,餐厅,客厅,厨房)。

 % % 3. Clue 2: Barbara was either in the study or the bathroom; Yolanda was in the other. % % Which room was Barbara found in? woman(Bathroom), woman(Study), \+christine=Bathroom, \+christine=Study, \+barbara=Dining, \+barbara=Kitchen, \+barbara=Livingroom, \+barbara=Pantry, 

秘诀3


那个拿着袋子的男人既不是芭芭拉也不是乔治,他既不在浴室也不在饭厅。 谁拿了袋子?

 % % 4. Clue 3: The person with the bag, who was not Barbara nor George, was not in the bathroom nor the dining room. % % Who had the bag in the room with them? \+barbara=Bag, \+george=Bag, \+Bag=Bathroom, \+Bag=Dining, 

秘诀4


在办公室里发现了一个有绳子的女人。 那是谁啊

 % % 5. Clue 4: The woman with the rope was found in the study. % % Who had the rope? woman(Rope), Rope=Study, 

秘诀5


提示5.客厅里的武器属于约翰或乔治。 客厅里有什么样的武器?

 man in Livingroom Livingroom isn't robert % % 6. Clue 5: The weapon in the living room was found with either John or George. % % What weapon was in the living room? man(Livingroom), \+Livingroom=robert, 

秘诀6


饭厅里没有刀。 刀在哪里?

 % % 7. Clue 6: The knife was not in the dining room. % % So where was the knife? \+Knife=Dining, 

秘诀7


提示7. Yolanda既不在办公室也不在食品储藏室。 尤兰达的房间里有什么武器?

 % % 8. Clue 7: Yolanda was not with the weapon found in the study nor the pantry. % % What weapon was found with Yolanda? \+yolanda=Pantry, \+yolanda=Study, 

秘诀8


乔治找到了枪支。

 % % 9. Clue 8: The firearm was in the room with George. % % In which room was the firearm found? Firearm=george, 

秘诀9


人们发现博迪先生在储藏室里被毒气了。 那个房间里的嫌疑犯是杀手。 那是谁啊

 % % 10. It was discovered that Mr. Boddy was gassed in the pantry. The suspect found in that room was the murderer. % % Who, then, do you point the finger towards? Pantry=Gas, Pantry=X, write("KILLER IS :"), write(X), nl, writeanswers(Bathroom, Dining, Kitchen, Livingroom, Pantry, Study, Bag, Firearm, Gas, Knife, Poison, Rope). 

匹配气体,食品储藏室和杀手,然后使用write writeanswers

 writeanswers(Bathroom, Dining, Kitchen, Livingroom, Pantry, Study, Bag, Firearm, Gas, Knife, Poison, Rope):- write("Bathroom: "), write(Bathroom), nl, write("Dining: "), write(Dining), nl, write("Livingroom: "), write(Livingroom), nl, write("Pantry: "), write(Pantry), nl, write("Study: "), write(Study), nl, write("Kitchen: "), write(Kitchen), nl, write("Knife: "), write(Knife), nl, write("Gas: "), write(Gas), nl, write("Rope: "), write(Rope), nl, write("Bag: "), write(Bag), nl, write("Poison: "), write(Poison), nl, write("Firearm: "), write(Firearm), nl. 

谁是杀手?


  ?- [crime2]. true. ?- murderer(X). KILLER IS :christine Bathroom: yolanda Dining: george Livingroom: john Pantry: christine Study: barbara Kitchen: robert Knife: yolanda Gas: christine Rope: barbara Bag: john Poison: robert Firearm: george X = christine ; 

该代码在此处发布。 因为我不是Prolog专家,所以它可能会好得多:)

Source: https://habr.com/ru/post/zh-CN434172/


All Articles