人工智能蔡自兴实验2事实表示.docx
《人工智能蔡自兴实验2事实表示.docx》由会员分享,可在线阅读,更多相关《人工智能蔡自兴实验2事实表示.docx(11页珍藏版)》请在冰豆网上搜索。
人工智能蔡自兴实验2事实表示
实验2Prolog程序事实表示
VisualProlog是面向对象的、严格类型化的和模式检验的程序设计语言。
在编写VisualProlog程序时,必须掌握这些内容,但是在这里将集中在编写代码这个核心问题上,也就是说,编写这些代码时暂时不考虑类、类型和模式。
为此,将使用包含在VisualProlog6中的PIE例子。
PIE是一个经典的Prolog解释器,通过它,可以学会和实现Prolog程序,而不必关心类、类型等方面的知识。
这里的内容是基于使用Build6004或者是以后的VisualProlog6版本,否则,PIE应用程序将不会象现在描述的这样工作。
这个编译号可以在VDE的About对话框中找到。
1.Horn子句逻辑
VisualProlog和其它Prolog用语都是基于Horn子句逻辑的。
Horn子句逻辑是对事物及其相互关系进行推理的形式系统。
在自然语言中,可以有这样样的一个陈述句:
John是Bill的父亲。
这里涉及两个实体,John和Bill,以及他们之间的关系,即一个是另一个的父亲.在Horn子句逻辑中,可以这样形式化地表述上面的陈述句:
father(“Bill”,”John”).
上面的father是带两个参量的一个谓词或关系,它表示第2个人是第1个人的父亲。
注意:
此处已经选择了第2个人是第1个人的父亲,也可以选择另外的方式,变量的顺序形式化设计者的选择,然而一旦选定了,就必须保持一致,在这里的表述中,父亲始终是第2个人。
已经选择用人名来代表人,因为在现实世界中,许多人有相同的名字,所以这一方法不一定有效。
但在这里,用这一简单的形式化表示。
有了上面的形式化方法,可以表示任何人之间的任何类型的家庭关系,但是,为了让这些表述更为有趣,制定下面的规则。
X是Z的祖父,如果X是Y的父亲且Y是Z的父亲
其中X,Y,Z指人。
在Horn子句逻辑中,可以这样表述
grandFathe(Person,GrandFathe):
-
father(Person,Father),father(Father,GrandFather).
已经选择使用了比X,Y,Z更容易理解的变量名。
另外,还引入了一个谓词来描述祖父关系。
再次选择了祖父作为第二个变量,像这样的保持一致是明智的,不同谓词的变量可以遵循相同的规则,当解读这些规则时,可以将:
-解释为“如果(if)”,将隔开关系的逗号解释为“与(and)”.
像“John是Bill的父亲”这样的陈述称为事实,而“X是Z的祖父,如果X是Y的父亲且Y是Z的父亲“称为规则。
可以用事实和规则来形成定理,一个定理是事实和规则的集合,下面陈述一个小定理:
father(“Bill”,”John”).
fathaer(“Pam””Bill”).
grandFather(Person,GrandFather):
-
father(Person,Father),father(Father,GrandFather).
这个定理的作用是回答这样的一些问题:
John是Sue的父亲吗?
谁是Pam的父亲?
John是Pam的祖父吗?
^……
这些问题称为目标(goal),它们可以这样形式化表示:
?
-father(“Sue”,”John”).
?
-father(“Pam”,X).
?
-grandfather(“Pam”,”John”).
这些问题被称为目标子句(goalclause)或简称为目标。
事实(facts),规则(rules)及目标合起来称为Horn子句,因此得名为Horn子句逻辑。
某些目标,如第一个和最后一个目标,可以简单地用“是”或“不是”来回答,其他目标,如第2个目标,需要寻找一个解,例如,X=“Bill”.
一个目标可以有多个解,例如:
?
-father(X,Y).
E有两个解:
X=“Bill”,Y=”John”.
X=“Pam”,Y=”Bill”.
一个Prolog程序是一个定理和目标的集合。
当程序开始时,它试图使用定理为目标找到一个解。
探索Prolog
Prolog在英语中的意思就是ProgramminginLOGic(逻辑编程)。
它是建立在逻辑学的理论基础之上的,最初是运用于自然语言的研究领域。
然而现在它被广泛的应用在人工智能的研究中,它可以用来建造专家系统、自然语言理解、智能知识库等。
同时它对一些通常的应用程序的编写也很有帮助。
使用它能够比其他的语言更快速地开发程序,因为它的编程方法更象是使用逻辑的语言来描述程序。
从纯理论的角度来讲,Prolog是一种令人陶醉的编程语言,但是在这本书中还是着重介绍他的实际使用方法。
逻辑编程
什么叫逻辑编程?
也许你还没有一个整体的印象,还是让我们首先来研究一个简单的例子吧。
运用经典的逻辑理论,我们可以说“所有的人(person)都属于人类(moral)”,如果用Prolog的语言来说就是“对于所有的X,只要X是一个人,它就属于人类。
”
moral(X):
-person(X).
同样,我们还可以加入一些简单的事实,比如:
苏格拉底(socrates)是一个人。
person(socrates).
有了这两条逻辑声明,Prolog就可以判断苏格拉底是不是属于人类。
在Prolog的Listener中键入如下的命令:
?
-mortal(socrates).(此句中的'?
-'是Listener的提示符,本句表示询问苏格拉底是不是属于人类。
)
Linstener将给出答案:
yes
我们还可以询问,“谁属于人类?
”
?
-mortal(X).
我们会得到如下的答案:
X=socrates
这个简单的例子显示了Prolog的一些强大的功能。
它能让程序代码更简洁、更容易编写。
在多数情况下Prolog的程序员不需要关心程序的运行流程,这些都由Prolog自动地完成了。
当然,一个完整的程序不能只包括逻辑运算部分,还必须拥有输入输出,乃至用户界面部分。
很遗憾,Prolog在这些方面做得不好,或者说很差。
不过它还是提供了一些基本的方法的。
下面是上述的程序一个完整的例子。
%Thisisthesyntaxforcomments.%MORTAL-ThefirstillustrativeProlog
programmortal(X):
-person(X).
person(socrates).
person(plato).
person(aristotle).
mortal_report:
-
write('Knownmortalsare:
'),nl,mortal(X),
write(X),nl,
fail.
把这个程序调入Listener中,运行mortal_report.。
?
-mortal_report.
Knownmortalsare:
socrates
plato
aristotle
no
以上程序中的一些函数以后还会详细的介绍的。
最后的那个no表示没有其他的人了。
进入下一章
从下一章起,就开始正式介绍Prolog的编程方法了。
我将用一个实例来介绍Prolog,这是一个文字的冒险游戏,你所扮演的角色是一个三岁的小女孩,你想睡觉了,可是没有毛毯(nani)你就不能安心的睡觉。
所以你必须在那个大房子中找到你的毛毯,这就是你的任务。
这个游戏能够显示出一些Prolog的独到之处,不过Prolog的功能远不止编个简单的游戏,所以文中还将介绍一些其他的小程序。
事实(facts)注:
斜粗体字表示Prolog的专有名词
事实(facts)是prolog中最简单的谓词(predicate)。
它和关系数据库中的记录十分相似。
在下一章中我们会把事实作为数据库来搜索。
谓词:
Prolog语言的基本组成元素,可以是一段程序、一个数据类型或者是一种关系。
它由谓词名和参数组成。
两个名称相同而参数的数目不同的谓词是不同的谓词。
事实的语法结构如下:
pred(arg1,arg2,...argN).
其中pred为谓词的名称。
arg1,...为参数,共有N个。
‘.’是所有的Prolog子句的结束符。
没有参数的谓词形式如下:
pred.
参数可以是以下四种之一:
整数(integer)
绝对值小于某一个数的正数或负数。
原子(atom)
由小写字母开头的字符串。
变量(variable)
由大写字母或下划线(_)开头。
结构(structure)
在以后的章节介绍。
不同的Prolog还增加了一些其他的数据类型,例如浮点数和字符串等。
Prolog字符集包括:
大写字母,A-Z;小写字母,a-z;数字,0-9;+-/\^,.~:
.?
#$等。
原子通常是字母和数字组成,开头的字符必须是小写字母。
例如:
hello
twoWordsTogether
x14
为了方便阅读,可以使用下划线把单词分开。
例如:
a_long_atom_name
z_23
下面的是不合法的原子,
no-embedded-hyphens
123nodigitsatbeginning
_nounderscorefirst
Nocapsfirst
使用单引号扩起来的字符集都是合法的原子。
例如:
'this-hyphen-is-ok'
'UpperCase'
'embeddedblanks'
下面的由符号组成的也是合法的原子:
-->
++
变量和原子相似,但是开头字符四大写字母或是下划线。
例如:
X
Input_List
_4th_argument
Z56
有了这些基本的知识,我们就可以开始编写事实了。
事实通常用来储存程序所需的数据。
例如,某次商业买卖中的顾客数据。
customer/3。
(/3表示customer有三个参数)
customer('JohnJones',boston,good_credit).
customer('SallySmith',chicago,good_credit).
必须使用单引号把顾客名引起来,因为它们是由大写字母开头的,并且中间有空格。
再看一个例子,视窗系统使用事实储存不同的窗口信息。
在这个例子中参数有窗口名称和窗口的位置坐标。
window(main,2,2,20,72).
window(errors,15,40,20,78).
某个医疗专家系统可能有如下的疾病数据库。
disease(plague,infectious).{疾病(瘟疫,有传染性)}
Prolog的解释器提供了动态储存事实和规则的方法,并且也提供了访问它们的方法。
数据库的更新是通过运行‘consult’或‘reconsult’命令。
我们也可以直接在解释器中输入谓词,但是这些谓词不会被储存到硬盘上。
寻找Nani
下面我们正式开始“寻找Nani”游戏的编写。
我们从定义基本的事实开始,这些事实是本游戏的基本的数据库。
它们包括:
∙房间和它们的联系
∙物体和它们的位置
∙物体的属性
∙玩家在游戏开始时的位置
图2.1“寻找Nani”游戏的的房间格局
首先我们使用room/1谓词定义房间,一共有五条子句,它们都是事实,如图2.1。
room(kitchen).
room(office).
room(hall).
room('diningroom').
room(cellar).
我们使用具有两个参数的谓词来定义物体的位置。
第一个参数代表物体的名称,第二个参数表示物体的位置。
开始时,我们加入如下的物体。
location(desk,office).
location(apple,kitchen).
location(flashlight,desk).
location('washingmachine',cellar).
location(nani,'washingmachine').
location(broccoli,kitchen).
location(crackers,kitchen).
location(computer,office).
注意:
我们定义的那些符号,例如:
kitchen、desk等对于我们是有意义的,可是它们对于Prolog是没有任何意义的,完全可以使用任何符号来表示房间的名称。
谓词location/2的意思是“第一个参数所代表的物体位于第二个参数所代表的物体中”。
Prolog能够区别location(sink,kitchen)和location(kitchen,sink)。
因此,参数的顺序是我们定义事实时需要考虑的一个重要问题。
下面我们来表达房间的联系。
使用door/2来表示两个房间有门相连,这里遇到了一个小小的困难:
door(office,hall).
我们想要表达的意思是,office和hall之间有一个门。
可是由于Prolog能够区分door(office,hall)和door(hall,office),所以如果我们想要表达一种双向的联系,就必须把每种联系都定义一遍。
door(office,hall).
door(hall,office).
参数的顺序对定义物体的位置有帮助,可是在定义房间的联系时却带来了麻烦。
我们不得不把每个房门都定义两次!
在这一章里,只定义单向的门,以后会很好地解决此问题的。
door(office,hall).
door(kitchen,office).
door(hall,'diningroom').
door(kitchen,cellar).
door('diningroom',kitchen).
下面定义某些物体的属性,
edible(apple).
edible(crackers).
tastes_yucky(broccoli).
最后,定义手电筒(由于是晚上,玩家必须想找到手电筒,并打开它才能到那些关了灯的房间)的状态和玩家的初始位置。
turned_off(flashlight).
here(kitchen).
好了,到此你应该学会了如何使用Prolog的事实来表达数据了。
用事实表达完成以下描述
作业1
作业2
比如一群年轻人正在恋爱,每个人都有自己心中所追求的对象:
张学友爱王菲
张学友爱周慧敏
王菲爱谢廷峰
周慧敏爱张学友
谢廷峰爱王菲
谢廷峰爱周慧敏
刘德华爱周慧敏
......