如果你想获得更好的阅读体验,可以前往我在 github 上的博客进行阅读,http://lcomplete.github.io/blog/2013/06/28/sevenlang-prolog/


目前商业上广泛使用的编程语言多是命令式或函数式的编程语言,这些语言在某些方面具有很高的相似度,比如 python 和 ruby 在很多地方是相通的,学会了一门,再学另一门便能够事半功倍,很多语言都是如此,然而今天要介绍的这门语言,却跟主流编程语言截然不同,它就是prolog——一门逻辑编程语言。

prolog 是 Programming in Logic 的缩写,它被广泛应用在人工智能、自然语言等研究领域,使用它来解决逻辑难题完全不在话下,今天我们将使用它来解决着名的爱因斯坦逻辑难题(斑马难题),首先让我们来认识一下 prolog 的语法。

prolog 基本语法

prolog 中有3种基本元素:事实、规则和查询。事实和规则用于描述数据,查询用于获取问题的答案。
我们可以这样定义事实:

human(lucy).
human(lili).
father(lucy,david).
sister(lucy,lili).
sister(lili,lucy).

这段代码表示 lucy 和 lili 是人类,且她们是姐妹,david 是 lucy 的父亲,继续定义规则:

daughter(Father,A,B) :-
father(A,Father), sister(A,B)

这段规则表示对于变量A、B,如果Father变量是A的父亲,且A、B是姐妹,则A、B是Father对象的女儿。 
注意,在 prolog 中一个词若以小写开头,那么它是一个固定值,若以大写字母开头,则是一个变量。 
将这些事实和规则放在一个文件里面,在命令行下打开 prolog ,对这个文件进行编译,即可提出查询,比如 daughter(david,A,_),prolog 将会求出A可能的取值并输出到控制台,最后的下划线是一个占位符,不会进行求值。

在 prolog 中还可以使用递归完成列表和数学等运算,这部分是很强大的,但这里不打算讲,因为有了上面的基础知识后,我们就可以利用它来解决逻辑问题了,下面就让我们来解决“斑马难题”吧。

爱因斯坦逻辑难题

题目:5个不同国家且工作各不相同的人分别住在一条街上的5所房子里,每所房子的颜色不同,每个人都有自己养的不同宠物,喜欢喝不同的饮料。根据以下提示,你能告诉我哪所房子里的人养斑马,哪所房子里的人喜欢喝矿泉水吗?

  1. 英国人住在红色的房子里
  2. 西班牙人养了一条狗
  3. 日本人是一个油漆工
  4. 意大利人喜欢喝茶
  5. 挪威人住在左边的第一个房子里
  6. 绿房子在白房子的右边
  7. 摄影师养了一只蜗牛
  8. 外交官住在黄房子里
  9. 中间那个房子的人喜欢喝牛奶
  10. 喜欢喝咖啡的人住在绿房子里
  11. 挪威人住在蓝色的房子旁边
  12. 小提琴家喜欢喝橘子汁
  13. 养狐狸的人所住的房子与医生的房子相邻
  14. 养马的人所住的房子与外交官的房子相邻

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

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

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

house(A,[A,_,_,_,_]).
house(A,[_,A,_,_,_]).
house(A,[_,_,A,_,_]).
house(A,[_,_,_,A,_]).
house(A,[_,_,_,_,A]). right(A,B,[A,B,_,_,_]).
right(A,B,[_,A,B,_,_]).
right(A,B,[_,_,A,B,_]).
right(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,Work). all_houses(Houses) :-
house(attr(britsh,_,red,_,_), Houses),
house(attr(spain,dog,_,_,_), Houses),
house(attr(japan,_,_,_,painter), Houses),
house(attr(italy,_,_,tea,_), Houses),
house(attr(norway,_,_,_,_), Houses),
first(attr(norway,_,_,_,_), Houses),
right(attr(_,_,white,_,_), attr(_,_,green,_,_), Houses),
house(attr(_,snail,_,_,photographer), Houses),
house(attr(_,_,yellow,_,diplomat), Houses),
middle(attr(_,_,_,milk,_), Houses),
house(attr(_,_,green,cafe,_), Houses),
neighbor(attr(norway,_,_,_,_), attr(_,_,blue,_,_), Houses),
house(attr(_,_,_,orange,violinst), Houses),
neighbor(attr(_,fox,_,_,_), attr(_,_,_,_,doctor), Houses),
neighbor(attr(_,horse,_,_,_), attr(_,_,_,_,diplomat), Houses), house(attr(_,zebra,_,_,_), Houses),
house(attr(_,_,_,water,_), Houses).

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

[attr(norway, fox, yellow, water, diplomat), 
attr(italy, horse, blue, tea, doctor), 
attr(britsh, snail, red, milk, photographer), 
attr(spain, dog, white, orange, violinst), 
attr(japan, zebra, green, cafe, painter)] .

出处:http://www.cnblogs.com/lcomplete/p/3192488.html

使用prolog逻辑语言解决爱因斯坦斑马难题的更多相关文章

  1. 人工智能技术导论——使用PROLOG逻辑语言解决爱因斯坦斑马文件

    一.背景 在上一篇博客https://www.cnblogs.com/wkfvawl/p/12056951.html上,我简单介绍了一下Prolog的一些基本语法,这篇博客主要通过老师课上讲过的一个问 ...

  2. 七周七语言之使用prolog解决爱因斯坦斑马难题

    如果你想获得更好的阅读体验,可以前往我在 github 上的博客进行阅读,http://lcomplete.github.io/blog/2013/06/28/sevenlang-prolog/. 目 ...

  3. [Go] 使用go语言解决现代编程难题

    1.计算机一直在演化,64核,128核等等,但是我们依旧在使用为单核设计的技术编程2.Go语言让分享自己的代码包更容易3.Go语言重新思考传统的面向对象,提供了更高效的复用代码手段4.Go不仅提供高性 ...

  4. 十年磨一剑,王坚自研的MaxCompute如何解决世界级算力难题

    摘要: 2009年这项关于大数据的技术长征开始.王坚带队,目标是自研大数据计算平台MaxCompute统一阿里巴巴内部的数据和大数据计算体系. 大数据时代,随着企业数据规模的急剧增长,传统软件已无法承 ...

  5. 斑马难题Step by Step

    问题描述 分析 代码 在exercism.io被这个 Zebra Puzzle 难住了.这里一步一步的解决... 1.There are five houses. 2.The Englishman l ...

  6. C语言解决约瑟夫问题详解的代码

    将开发过程中比较重要的一些内容做个收藏,下面的内容是关于C语言解决约瑟夫问题详解的内容,希望能对码农有帮助. #pragma once #include<vector> class PRO ...

  7. 15 GIL 全局解释器锁 C语言解决 top ps

    1.GIL 全局解释器锁:保证同一时刻只有一个线程在运行. 什么是全局解释器锁GIL(Global Interpreter Lock) Python代码的执行由Python 虚拟机(也叫解释器主循环, ...

  8. indexDB解决过的难题

    我第一次使用indexDB是1年前(2018年10月),运用这个黑科技,解决过3个异常棘手的问题(如果不是indexDB 几乎找不到其他解决方案)所以我经常强调,前端一定要学indexDB! 难题一: ...

  9. 关于C语言解决汉诺塔(hanoi)问题

    C语言解决汉诺塔问题 汉诺塔是典型的递归调用问题: hanoi简介:印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔.不论白天黑夜,总有一个僧侣 ...

随机推荐

  1. Three Pieces CodeForces - 1065D (BFS)

    链接 大意: n*n棋盘, 每个格子写有数字, 各不相同, 范围[1,n*n], 初始在数字1的位置, 可以操纵knight,bishop,rook三种棋子, 每走一步花费1, 交换棋子花费1, 问按 ...

  2. hdu-4678-sg

    Mine Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submis ...

  3. zzuli 1432(二进制特点)

      1432: 背包again Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 222  Solved: 65 SubmitStatusWeb Board ...

  4. JDBC连接SqlServer数据库(非默认实例)方法

    一般我们在连接数据库的时候都是用的默认实例名,今天遇到了用非默认是实例名:连接代码如下(Java): URL=jdbc:microsoft:sqlserver://192.168.1.85//DEMO ...

  5. transition多个属性同时渐变(width,height,background)

    <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head>    < ...

  6. Oracle12c 中RAC功能增强新特性之ASM&amp;Grid

    1.    自动存储管理(ASM)方面的增强 1.1.   Flex ASM 在典型的网格架构安装中,每个节点有自己的ASM实例运行并扮演该节点上数据库的存储容器的角色,对这种安装配置,存在单点失败的 ...

  7. json格式化

    jar包:gson-xxx.jar   import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.goog ...

  8. bzoj3601

    题解:gi(pq=pqi-pqi+di 至于为什么,可以看看往上的题解 代码: #include<bits/stdc++.h> using namespace std; typedef l ...

  9. Kafka生产者APi

    kafka客户端发布record(消息)到kafka集群. 新的生产者是线程安全的,在线程之间共享单个生产者实例,通常单例比多个实例要快. 一个简单的例子,使用producer发送一个有序的key/v ...

  10. Runtime的基本运用

    一.什么是runtime(也就是所谓的“运行时”,因为是在运行时实现的.)           1.runtime是一套底层的c语言API(包括很多强大实用的c语言类型,c语言函数);  [runti ...