Prolog 语言入门教程

栏目: 数据库 · 发布时间: 5年前

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

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

Prolog 语言入门教程

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

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

一、SWI-Prolog

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

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 如何解决实际问题。

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 ;

(完)


以上所述就是小编给大家介绍的《Prolog 语言入门教程》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

编程语言实现模式

编程语言实现模式

Terence Parr / 李袁奎、尧飘海 / 华中科技大学出版社 / 2012-3-20 / 72.00元

《编程语言实现模式》旨在传授开发语言应用(工具)的经验和理念,帮助读者构建自己的语言应用。这里的语言应用并非特指用编译器或解释器实现编程语言,而是泛指任何处理、分析、翻译输入文件的程序,比如配置文件读取器、数据读取器、模型驱动的代码生成器、源码到源码的翻译器、源码分析工具、解释器,以及诸如此类的工具。为此,作者举例讲解已有语言应用的工作机制,拆解、归纳出31种易于理解且常用的设计模式(每种都包括通......一起来看看 《编程语言实现模式》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具