一、背景

在上一篇博客https://www.cnblogs.com/wkfvawl/p/12056951.html上,我简单介绍了一下Prolog的一些基本语法,这篇博客主要通过老师课上讲过的一个问题,来体验一下prolog在逻辑推理上的优势。

在介绍问题之前,先引入一道Prolog题:

试编写一个描述亲属关系的Prolog程序,然后再给出一些事实数据,建立一个小型演绎数据库。

提示:可以以父亲和母亲为基本基本关系(作为基本谓词),再由此描述祖父、祖母、兄弟、姐妹以及其他亲属关系。

    mother(a,c).
mother(a,d).
mother(c,g).
mother(c,f).
father(b,c).
father(b,d).
father(e,g).
father(e,f).
grandfather(X,Z):-father(X,Z),father(Y,Z).
grandmother(X,Z):-mother(X,Y),mother(Y,Z).
sister(X,Y):-mother(Z,X),mother(Z,Y).
aunt(X,Y):-mother(Z,Y),sister(Z,X).

这里使用SWI-Prolog进行测试

注意,在 Prolog 中一个词若以小写开头,那么它是一个固定值,若以大写字母开头,则是一个变量

继续定义规则:

 family(F,M,C) :-father(F,C), mother(M,C).

提出查询,比如

prolog 将会求出X可能的取值并输出到控制台,中间的下划线是一个占位符,不会进行求值。有了上面的基础知识后,我们就可以利用它来解决逻辑问题了,下面就让我们来解决“斑马难题”吧。

二、爱因斯坦逻辑难题

有5间不同颜色的房间,每间住个不同国籍的人,每人有自己喜欢的饮料、香烟和宠物。已知信息:
英国人在红房间中
西班牙人有一条狗
挪威人住在左边第一间房里
黄房间中的人在抽库尔斯牌香烟
抽切斯菲尔德牌香烟的人是养了一只狐狸的人的邻居
挪威人住在蓝房间隔壁
抽温斯顿牌香烟的人有一只蜗牛
抽幸运牌香烟的人喝橘子汁
乌克兰人喝茶
日本人抽国会牌香烟
抽库尔斯牌烟的房间在有匹马的房间隔壁
绿房间中的人喝咖啡
绿房间在白房间的左边
中间房间的人喝牛奶

这道题的解题关键在于,要以一种清晰的方式将每个房子相关的属性(颜色、国籍、香烟、宠物、饮料、编号)列出来,前面5个提示中包含了5个国家,那可以利用这一点画出一个表格,每一行表示一个国家,每一列表示房子的一种属性。一步步根据提示得到一些推论,将结果填入表格,答案便渐渐清晰起来,使用这种人工方式推理的结果如下图所示:

虽然我们知道了解题的关键,但这个问题仍然需要经过很多步的推导才能得出结果,如果使用 prolog 那得到这个问题的答案就简单多了,只需要定义好事实和规则,然后向 Prolog 提出问题,逻辑引擎就会为我们查出结果来。

下面是解决这个问题的 Prolog 代码。

house(A,[A,_,_,_,_]).
house(A,[_,A,_,_,_]).
house(A,[_,_,A,_,_]).
house(A,[_,_,_,A,_]).
house(A,[_,_,_,_,A]). left(A,B,[A,B,_,_,_]).
left(A,B,[_,A,B,_,_]).
left(A,B,[_,_,A,B,_]).
left(A,B,[_,_,_,A,B]). middle(A,[_,_,A,_,_]). first(A,[A,_,_,_,_]). 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]). attr(Country,Pet,Color,Drink,Smoke). all_houses(Houses) :-
house(attr(britsh,_,red,_,_), Houses),
house(attr(spain,dog,_,_,_), Houses),
house(attr(japan,_,_,_,congressCigarettes), Houses),
house(attr(ukraine,_,_,tea,_), Houses),
house(attr(norway,_,_,_,_), Houses),
first(attr(norway,_,_,_,_), Houses),
left(attr(_,_,green,_,_), attr(_,_,white,_,_), Houses),
house(attr(_,snail,_,_,winstonCigarettes), Houses),
house(attr(_,_,yellow,_,coorsCigarettes), Houses),
middle(attr(_,_,_,milk,_), Houses),
house(attr(_,_,green,cafe,_), Houses),
neighbor(attr(norway,_,_,_,_), attr(_,_,blue,_,_), Houses),
house(attr(_,_,_,orange,luckCigarattes), Houses),
neighbor(attr(_,fox,_,_,_), attr(_,_,_,_,chesfieldCigarettes), Houses),
neighbor(attr(_,horse,_,_,_), attr(_,_,_,_,coorsCigarettes), Houses), house(attr(_,zebra,_,_,_), Houses),
house(attr(_,_,_,water,_), Houses).

在事实部分,将房子看做一个整体,描述了房子在5所房子中、房子的左右关系、中间的房子处于什么位置、第一所房子处于什么位置、房子间的相邻关系以及每所房子拥有哪些属性。
规则部分包含了对题目中提示的描述和最终问题的描述,这些定义是为了告诉逻辑引擎,在求值时必须满足这些条件。
最终的查询为 all_houses(A) ,prolog 逻辑引擎将会查找出满足结果的房子数组,注意每所房子由它的属性组成,这样最后得到的结果为:

最新文章

  1. 大型App要搞的几个系统
  2. openswan-ipsec.conf配置说明
  3. VirtrualBox使用已存在的镜像创建虚拟机
  4. android DisplayMetrics 获取屏幕分辨率
  5. unity3d插件Daikon Forge GUI 中文教程1-Daikon Forge介绍
  6. JS初级-作用域
  7. DB2表结构DDL脚本导出
  8. iOS中UIWebView使用JS交互 - 机智的新手
  9. 静态频繁子图挖掘算法用于动态网络——gSpan算法研究
  10. html日历(2)
  11. cookie设置域名问题,cookie跨域
  12. 瓦片切图工具gdal2tiles.py改写为纯c++版本(二)
  13. postgresql语句
  14. vlc sdl 播放视频可随窗口改变大小
  15. 利用CVE-2018-0950漏洞自动窃取Windows密码
  16. 小学生二元四则运算(F)
  17. windos 查看指定端口,将指定进程杀死
  18. Python之迭代器及生成器
  19. 使用VS2015 编译 64位的boost库
  20. Win下执行Swing程序的BAT文件 和 Linux下执行Swing程序的SH文件

热门文章

  1. 2019-11-19:xxe漏洞利用,笔记
  2. c#关于数据和方法在不同类中的引用-xdd
  3. Lambda入门,看这一篇幅就够了
  4. 对python的初步了解
  5. 对于web前端的理解
  6. Linux基础命令小技巧
  7. css6——通栏平均分布
  8. Python-TCP客户端程序开发
  9. luogu P2417 课程
  10. luogu P4408 [NOI2003]逃学的小孩