2019独角兽企业重金招聘Python工程师标准>>>

Prolog 语言入门教程

作者: 阮一峰

日期: 2019年1月28日

Prolog 是一种与众不同的语言,不用来开发软件,专门解决逻辑问题。比如,"苏格拉底是人,人都会死,所以苏格拉底会死"这一类的问题。

Prolog 就是"逻辑编程"(programming of Logic)的意思。只要给出事实和规则,它会自动分析其中的逻辑关系,然后允许用户通过查询,完成复杂的逻辑运算。

本文简单介绍如何使用 Prolog 语言,主要参考了 xmonader 的教程。

一、SWI-Prolog

学习之前,请安装 Prolog 的运行环境 SWI-Prolog,才能运行后面的代码。

SWI-Prolog 官网有各个操作系统的二进制安装包,下载即可。Debian / Ubuntu 系统还可以用下面的命令。


$ sudo apt-get install swi-prolog

安装以后,Linux 系统可以命令行启动。


$ swipl
?-

然后,就进入了 Prolog 运行环境,?-是命令提示符。下面是 Hello world 的例子。


?- write("Hello, world").
Hello, world!
true.

上面命令输出 Hello world。

有几个地方需要注意。Prolog 所有语句的结尾都用一个"点"(.)表示结束。write()是打印命令。命令本身就是一个表达式,输出完成以后,返回值就是true.,也会显示出来。

如果想在 Hello world 之间插入一个换行,可以使用nl命令。


?- write('Hello,'), nl, write('world').
Hello,
world
true.

退出 SWI-Prolog,可以使用halt命令,别忘了后面还要加一个点。


?- halt.

二、基本语法

2.1 常量和变量

Prolog 的变量和常量规则很简单:小写字母开头的字符串,就是常量;大写字母开头的字符串,就是变量。


?- write(abc).
abc
true.?- write(Abc).
_3386
true.

上面代码中,abc是常量,输出就是自身;Abc是变量,输出就是该变量的值。

2.2 关系和属性

两个对象之间的关系,使用括号表示。比如,jack 的朋友是 peter,写成friend(jack, peter).

注意,jack 的朋友是 peter,不等于 peter 的朋友是 jack。如果两个人都认为对方是朋友,要写成下面这样。


friend(jack, peter).
friend(peter, jack).

如果括号里面只有一个参数,就表示对象拥有该属性,比如 jack 是男性,写成male(jack).

2.3 规则

规则是推理方法,即如何从一个论断得到另一个论断。

举例来说,我们定下一条规则:所有朋友关系都是相互的,规则写成下面这样。


friend(X, Y) :- friend(Y,X).

上面代码中,XY都是大写,表示这是两个变量。符号:-表示推理关系,含义是只要右边的表达式friend(Y, X)true,那么左边的表达式friend(X, Y)也为true。因此,根据这条规则,friend(jack, peter)就可以推理得到friend(peter, jack)

如果一条规则取决于多个条件同时为true,则条件之间使用逗号分隔。


mother(X, Y) :- child(Y,X), female(X).

上面代码中,XY的母亲(mother(X, Y))取决于两个条件:YX的小孩,X必须是女性。只有这两个条件都为truemother(X, Y)才为true

如果一条规则取决于某个条件为false,则在条件之前加上\+表示否定。


onesidelove(X, Y) :- loves(X, Y), \+ loves(Y,X).

上面代码中,X单相思Y,取决于两个条件。第一个条件是X喜欢Y,第二个条件是Y不喜欢X

2.5 查询

Prolog 支持查询已经设定的条件。我们先写一个脚本hello.pl


friend(john, julia).
friend(john, jack).
friend(julia, sam).
friend(julia, molly).

然后在 SWI-Prolog 里面加载这个脚本。


?- [hello].
true.

上面代码中,true.是返回的结果,表示加载成功。

然后,可以查询两个人是否为朋友。


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

listing()函数可以列出所有的朋友关系。


?- listing(friend).
friend(john, julia).
friend(john, jack).
friend(julia, sam).
friend(julia, molly).true.

还可以查询john有多少个朋友。


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

上面代码中,Who是变量名。任意的变量名都可以,只要首字母为大写。

三、地图着色问题

下面看看 Prolog 如何解决实际问题。

我们知道,地图的相邻区域不能使用同一种颜色。现在有三种颜色:红、绿、蓝。请问如何为上面这幅地图着色?

首先,定义三种颜色。


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.

上面代码中,colorify(A,B,C,D,E)是一个对 ABCDE 五个变量求值的表达式。该表达式为true的条件是,这五个变量各自为一种颜色,则相邻的变量不相等。

最后,这两段代码合在一起,组成一个脚本map.pl,再加载这个脚本。


?- [map].
true.

执行表达式colorify(A,B,C,D,E),SWI-Prolog 就会将三种颜色依次赋值给变量,测试哪些组合是可能的结果。


?- 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 ;

可以看到,计算机给出了6组解,即有6种可行的地图着色方法。

四、谁是凶手

下面看一个比较有趣的逻辑题。

Boddy 先生死于谋杀,现有六个嫌疑犯,每个人在不同的房间,每间房间各有一件可能的凶器,但不知道嫌疑犯、房间、凶器的对应关系。请根据下面的条件和线索,找出谁是凶手。

已知条件:六个嫌疑犯是三男(George、John、Robert)三女(Barbara、Christine、Yolanda)。


man(george). man(john). man(robert).
woman(barbara). woman(christine). woman(yolanda).

为了后面解题的方便,需要把"男人"和"女人"都定义为"人"。


person(X):- man(X).
person(X):- woman(X).

六个嫌疑犯分别待在六个房间:浴室(Bathroom)、饭厅(Dining Room)、厨房(Kitchen)、起居室(Living Room)、 储藏室(Pantry)、书房(Study)。每间房间都有一件可疑的物品,可以当作凶器:包(Bag)、火枪(Firearm)、煤气(Gas)、刀(Knife)、毒药(Poison)、绳索(Rope)。


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(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),变量X就是凶手。该表达式只有满足以下所有条件,才可能为true


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

注意,上面代码中BathroomBag这样的字符串,都是大写字母开头,所以都是变量,代表对应的人。至于具体是谁,就要通过推理得到。

线索一:厨房里面是一个男人,那里的凶器不是绳索、刀子、包和火枪。


man(Kitchen), \+Kitchen=Rope, \+Kitchen=Knife, \+Kitchen=Bag, \+Kitchen=Firearm,

线索二:Barbara 和 Yolanda 在浴室和书房。


woman(Bathroom), woman(Study), \+christine=Bathroom, \+christine=Study, \+barbara=Dining, \+barbara=Kitchen, \+barbara=Livingroom, \+barbara=Pantry,\+yolanda=Dining, \+yolanda=Kitchen, \+yolanda=Livingroom, \+yolanda=Pantry,

线索三:带包的那个人不是 Barbara 和 George,也不在浴室和饭厅。


\+barbara=Bag, \+george=Bag,
\+Bag=Bathroom, \+Bag=Dining,

线索四:书房里面是一个带绳子的女人。


woman(Rope), Rope=Study,

线索五:起居室里面那件凶器,与 John 或 George 在一起。


man(Livingroom), \+Livingroom=robert,

线索六:刀子不在饭厅。


\+Knife=Dining,

线索七:书房和食品储藏室里面的凶器,没跟 Yolanda 在一起。


\+yolanda=Pantry, \+yolanda=Study,

线索八:George 所在的那间屋子有火枪。


Firearm=george,

线索九:Boddy 先生死在食品储藏室里,那里的凶器是煤气。


Pantry=Gas, Pantry=X, Gas=X,

线索就是上面这些,然后把写好的所有表达式放在一起,组成一个完整的脚本crime.pl,代码看这里。

加载这个脚本,执行murderer(X)函数,由于条件复杂,运算时间较长,最终会显示凶手是谁。


?- [crime].
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 ;

(完)

转载于:https://my.oschina.net/u/2285247/blog/3041678

Prolog 语言入门教程相关推荐

  1. c++ 结构体赋值_《零基础看得懂的C语言入门教程》—(十二)结构体是这么回事

    一.学习目标 了解C语言的结构体的使用方法 了解C语言结构体的结构的赋值 了解多种C语言结构体变量的赋值方法和取值方法 目录 <零基础看得懂的C语言入门教程>--(二)简单带你了解流程 & ...

  2. c语言入门教程文库,C语言入门教程(全集)课件

    C语言入门教程(全集)课件 01123364105 Y N p AB X=0? YN P1 A A P2 a a b b Y Y N N y n A B P A A B X=0? 3 a97 3 U ...

  3. 2017年Go语言入门教程-徐培成-专题视频课程

    2017年Go语言入门教程-3763人已学习 课程介绍         Go语言入门教程,只要你懂中文都可以看的懂本套教程,为任何想学习Go语言研制的教程. 课程收益     让任何人都可以轻松掌握G ...

  4. GO语言入门教程(二)

    Hello,各位小伙伴,在接着之前发表的Go语言系列教程之投石问路之后,我们大致了解了一下Go语言的发展史和Go语言的优势,另外我也带着小伙伴进行了Go语言环境的安装和常用命令的介绍.接下来我们就正式 ...

  5. java编程输出平行四边形_JAVA语言入门教程之打印图形实例——打印平行四边形...

    本文主要向大家介绍了JAVA语言入门教程之打印图形实例--打印平行四边形,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. 输出平行四边形: public class Parallelo ...

  6. C语言入门教程学习 C语言学习包括哪些?

    嵌入式开发有一定了解的朋友们知道是在操作系统内部开发的,对于操作系统内部来说基本上都是用C语言来进行编译的,所以说对于C语言的学习在嵌入式开发过程中是非常重要的.下面就给大家介绍一些C语言入门教程的相 ...

  7. 小白都能看懂的C语言入门教程

    文章目录 C语言入门教程 1. 第一个C语言程序HelloWorld 2. C语言的数据类型 3. 常量变量的使用 4. 自定义标识符#define 5. 枚举的使用 6. 字符串和转义字符 7. 判 ...

  8. 计算机语言中的逻辑型数据,零基础易语言入门教程(五)之逻辑型数据类型

    在上篇文章给大家介绍了零基础易语言入门教程(四)之数据类型,上篇针对数值到文本类型知识,今天给大家介绍下逻辑型数据. 具体方法和步骤如下所示: 1.逻辑型数据非真即假: 首先申请一个局部变量(A)类型 ...

  9. iOS开发之c语言入门教程

    苹果作为移动互联的高端品牌,iOS操作系统也被用户公认为是最好用的移动互联网操作系统.据了解,曾一度拒绝为iOS平台对出浏览器的火狐在今年5月份的时候,他们却食言了.今天,Mozilla宣布iOS版F ...

  10. c语言5基础教程,[简001]《极简C语言入门教程》共5章

    Saturday,May 18,2019 ---Andy ###目录: 前言 第一章 数据类型 1.1 数据类型 1.2 宏定义.常量.变量(一般和指针型) 第二章 格式化输入输出 2.1 输入 2. ...

最新文章

  1. 什么是Python蛋?
  2. 回归、分类与聚类:三大方向剖解机器学习算法的优缺点
  3. 万字详解:腾讯如何自研大规模知识图谱 Topbase
  4. 一张图读懂nginx多线程高并发
  5. OpenCV与AIPCV库——学习笔记(一)
  6. EF批量添加数据BulkInsert
  7. Visual Studio2017 MSDN安装
  8. rmvb 转 avi 方法
  9. R语言中5种正态性检验的方法
  10. Access-Control-Allow-Origin跨域问题,使用Nginx配置来解决
  11. qt qml StackView 触摸滑动返回(swiping pop)
  12. 计算机网络 --- IP地址的详细分类
  13. 了解车辆驾驶行为、成功验证C-V2X技术
  14. navigation_plugin
  15. (创建型)设计模式——工厂模式(factory)
  16. 设计模式第一篇——简单工厂模式&类图
  17. linux 时间戳转换/dmesg 时间转换
  18. RiPro8.6美化包-huzao-child v3.0子主题简洁大气集成后台
  19. 研发工程师玩转Kubernetes——Node失效后恢复的实验
  20. android studio添加v7包,如何在Android Studio中添加RecyclerView-v7支持包

热门文章

  1. HTML页面基本结构
  2. SerDes知识详解
  3. microhard p900数传配置方法
  4. 【MyBatis基础】(09)- 逆向工程(代码自动生成)
  5. PCBA方案设计——蓝牙脂肪心率秤方案
  6. TSO/GSO/LRO/GRO
  7. 用计算机研究唐诗,妙哉,那个用文言文编程的小哥,竟从28万行唐诗中找出了对称矩阵...
  8. java 汉字 拼音排序_Java字符串按照汉语拼音排序
  9. android编程:调节视频画面分辨率,Android实现任意分辨率视频编码的思考与实现
  10. ( 教程 ) 微信公众号做淘宝优惠券自动查券返利机器人怎么设置?