爱因斯坦斑马问题实验
实验要求
确定性推理作业:设计一 Prolog 程序解决以下问题。
题目:有 5 间不同颜色的房间,每间住个不同国籍的人,每人有自己喜欢的饮料、香烟和宠物。已知信息:
英国人在红房间中
西班牙人有一条狗
挪威人住在左边第一间房里
黄房间中的人在抽库尔斯牌香烟
抽切斯菲尔德牌香烟的人是养了一只狐狸的人的邻居
挪威人住在蓝房间隔壁
抽温斯顿牌香烟的人有一只蜗牛
抽幸运牌香烟的人喝橘子汁
乌克兰人喝茶
日本人抽国会牌香烟
抽库尔斯牌烟的房间在有匹马的房间隔壁
绿房间中的人喝咖啡
绿房间在白房间的左边
中间房间的人喝牛奶
要求:试编程推理出各房间的颜色,以及每个客人所住的房间、各自的国籍、抽什么版的香烟、喝什么饮料、养的什么宠物。最终提交的作业要写明题意,给出程序清单和执行结果。程序中应有必要的注释说明。
实验分析
分析:这道题的解题关键在于,要以一种清晰的方式将每个房子相关的属性(颜色、国籍、香烟、宠物、饮料、编号)列出来,前面 5 个提示中包含了 5 个国家,那可以利用这一点画出一个表格,每一行表示一个国家,每一列表示房子的一种属性。一步步根据提示得到一些推论,将结果填入表格,答案便渐渐清晰起来,使用这种人工方式推理的结果如下图所示:
虽然我们知道了解题的关键,但这个问题仍然需要经过很多步的推导才能得出结果,如果使用 Prolog 那得到这个问题的答案就简单多了,只需要定义好事实和规则,然后向 Prolog 提出问题,逻辑引擎就会为我们查出结果来。
实验步骤
实验代码(Prolog实现)
/*描述房子的事实:建立五个房间*/
house(A,[A,_,_,_,_]).
house(A,[_,A,_,_,_]).
house(A,[_,_,A,_,_]).
house(A,[_,_,_,A,_]).
house(A,[_,_,_,_,A]).
/*描述房子的事实:建立房间之间的位置关系(left)*/
left(A,B,[A,B,_,_,_]).
left(A,B,[_,A,B,_,_]).
left(A,B,[_,_,A,B,_]).
left(A,B,[_,_,_,A,B]).
/*描述房子的事实:标记中间的房间(middle)*/
middle(A,[_,_,A,_,_]).
/*描述房子的事实:标记第一个房间(first)*/
first(A,[A,_,_,_,_]).
/*描述房子的事实:建立房间之间的邻居关系(neighbor)*/
neighbor(A,B,[A,B,_,_,_]).
neighbor(A,B,[_,A,B,_,_]).
neighbor(A,B,[_,_,A,B,_]).
neighbor(A,B,[_,_,_,A,B]).
neighbor(A,B,[B,A,_,_,_]).
neighbor(A,B,[_,B,A,_,_]).
neighbor(A,B,[_,_,B,A,_]).
neighbor(A,B,[_,_,_,B,A]).
/*建立人的五个属性*/
people[Country,Pet,Color,Drink,Smoke].
/*根据题目所给的信息描述房间分配的规则*/
find(Houses) :-
house(people(britsh,_,red,_,_), Houses),
house(people(spain,dog,_,_,_), Houses),
house(people(japan,_,_,_,congressCigarettes), Houses),
house(people(ukraine,_,_,tea,_), Houses), house(people(norway,_,_,_,_), Houses),
first(people(norway,_,_,_,_), Houses),
left(people(_,_,green,_,_), people(_,_,white,_,_), Houses),
house(people(_,snail,_,_,winstonCigarettes), Houses),
house(people(_,_,yellow,_,coorsCigarettes), Houses),
middle(people(_,_,_,milk,_), Houses),
house(people(_,_,green,cafe,_), Houses),
neighbor(people(norway,_,_,_,_), people(_,_,blue,_,_), Houses),
house(people(_,_,_,orange,luckCigarattes), Houses),
neighbor(people(_,fox,_,_,_), people(_,_,_,_,chesfieldCigarettes), Houses),
neighbor(people(_,horse,_,_,_), people(_,_,_,_,coorsCigarettes), Houses),
house(people(_,zebra,_,_,_), Houses),
house(people(_,_,_,water,_), Houses).
代码运行
运行环境:Prolog在线编译平台
输入问题:
?-find(X).
可见显示出的结果和我们之前分析的是一致的。
实验总结
建立人的五个属性时需要使用方括号“[]”,对变量进行处理,不能使用“()”,否则属性会被作为常量无法修改,从而报错无法执行。
people[Country,Pet,Color,Drink,Smoke].