逻辑型程序设计语言PROLOG详细教程_第1页
逻辑型程序设计语言PROLOG详细教程_第2页
逻辑型程序设计语言PROLOG详细教程_第3页
逻辑型程序设计语言PROLOG详细教程_第4页
逻辑型程序设计语言PROLOG详细教程_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、逻辑型程序设计语言 PROLOG 教程2.3. 1 逻辑型程序设计语言 PROLOGPROLOG的语句PROLOG语言只有三种语句,分别称为事实、规则和问题。1. 事实 (fact)格式 : 谓词名 (项表 ).功能 一般表示对象的性质或关系。其中谓词名是以小写英文字母打头的字母、数字、下划线等组成的字符串,项表是以逗号 隔开的项序列。例如 :student(john).like( mary ,music).表示 “约翰是学生 ”和“玛丽喜欢音乐 ”。2. 规则 (rule)格式 : 谓词名 (项表 ):-谓词名 (项表 ),谓词名 (项表 ).功能 : 一般表示对象间的因果关系、蕴含关系或对

2、应关系。其中“:”号表示“if (也可以直接写为if),其左部的谓词是规则的结论(亦称为头),右部 的谓词是规则的前提(亦称为体),表示零次或多次重复,逗号表示and(逻辑与),即规则的形式是一个逻辑蕴含式。例如:bird(X):-animal(X),has(X,feather). grandfather(X,Y):-father(X,Z),father(Z,Y).第一条规则表示如果X是动物,并且X有羽毛,则X是鸟”第二条规则就表示“X是丫的祖父,如果存在 乙X是Z的父亲并且Z又是丫的父亲”3. 问题 (question)格式: -谓词名 (项表),谓词名 (项表).功能 表示用户的询问,它就

3、是程序运行的目标。例如 : -student(john).-like(mary,X).2.3. 2 PROLOG 程序PROLOG程序一般由一组事实、规则和问题组成。问题是程序执行的起点,称为程序的目标。 例如下面就是一个PROLOG程序。likes(bell,sports). likes(mary,music). likes(mary,sports). likes(jane ,smith).friend(john,X):-likes(X,reading),likes(X,music). friend(john,X):-likes(X,sports),likes(X,music).-frie

4、nd(joh n, Y). 可以看出,这个程序中有四条事实、两条规则和一个问题。其中事实、规则和问题都分行书写。 规则和事实可连续排列在一起, 其顺序可随意安排, 但同一谓词名的事实或规则必须集中排列在 一起。问题不能与规则及事实排在一起, 它作为程序的目标要么单独列出, 要么在程序运行时临 时给出。这个程序的事实描述了一些对象(包括人和事物)间的关系;而规则则描述了 john 交朋友的条 件,即如果一个人喜欢读书并且喜欢音乐(或者喜欢运动和喜欢音乐),则这个人就是 john 的 朋友(当然,这个规则也可看作是 john 朋友的定义);程序中的问题是 “约翰的朋友是谁 ”当然,PROLOG程序

5、中的目标可以变化,也可以含有多个语句(上例中只有一个)。如果有多个语句,则这些语句称为子目标。例如对上面的程序,其问题也可以是-likes(mary,X).或-likes(mary,music).或-friend(X,Y).或-likes(bell,sports), likes(mary,music), friend(john,X). 等等。当然,对于不同的问题,程序运行的结果一般是不一样的。2.3.3 PROLOG程序的运行机理PROLOG程序的运行是从目标岀发,并不断进行匹配、合一、归结,有时还要回溯,直到 目标被完全满足或不能满足时为止。1. 自由变量与约束变量PROLOG中称无值的变量

6、为自由变量,有值的变量为约束变量。一个变量取了某值就说该 变量约束于某值,或者说该变量被某值所约束,或者说该变量被某值实例化了。2. 匹配合一两个谓词可匹配合一,是指两个谓词的名相同,参量项的个数相同,参量类型对应相同, 并且对应参量项还满足下列条件之一:(1) 如果两个都是常量,则必须完全相同。(2) 如果两个都是约束变量,则两个约束值必须相同。(3) 如果其中一个是常量,一个是约束变量,则约束值与常量必须相同。(4) 至少有一个是自由变量。例如:下面的两个谓词pre1(ob1,ob2,Z)pre1(ob1,X,Y)只有当变量X被约束为ob2,且丫、Z的约束值相同或者至少有一个是自由变量时,

7、它们 才是匹配合一的。3. 回溯所谓回溯,就是在程序运行期间,当某一个子目标不能满足(即谓词匹配失败)时,控制 就返回到前一个已经满足的子目标(如果存在的话),并撤消其有关变量的约束值,然后再使其重新满足。成功后,再继续满足原子目标。如果失败的子目标前再无子目标,则控制就返回到该子目标的上一级目标 (即该子目标谓词所在规则的头部)使它重新匹配。 回溯也是PROLOG的一个重要机制。下面,我们介绍 PROLOG程序的运行过程。我们仍以上面的程序为例。设所给的询问是-friend(john,Y).(john 和谁是朋友)则求解目标为frie nd(joh n, Y).这时,系统对程序进行扫描,寻找

8、能与目标谓词匹配合一的事实或规则头部。显然,程序 中前面的四条事实均不能与目标匹配,而第五个语句的左端即规则frie nd(joh n,X):-likes(X,readi ng),likes(X,music).的头部可与目标谓词匹配合一。但由于这个语句又是一个规则,所以其结论要成立则必须其前提全部成立。于是,对原目标的求解就转化为对新目标likes(X,readi ng),likes(X,music).的求解。这实际是经归结,规则头部被消去,而目标子句变为-likes(X,readi ng),likes(X,music).现在依次对子目标likes(X,reading)和 likes(X,mu

9、sic)求解。子目标的求解过程与主目标完全一样,也是从头对程序进行扫描,不断进行测试和匹配合一等, 直到匹配成功或扫描完整个程序为止。可以看岀,对第一个子目标like(X,reading)的求解因无可匹配的事实和规则而立即失败,进而导致规则frie nd(joh n,X):-likes(X,readi ng),likes(X,music).的整体失败。于是,刚才的子目标likes(X,reading)和 likes(X,music)被撤消,系统又回溯到原目标friend(john,X)。这时,系统从该目标刚才的匹配语句处(即第五句)向下继续扫描程序中的子句,试图重新使原目标匹配,结果发现第六条

10、语句的左部,即规则frie nd(joh n, X):-likes(X,sports),likes(X,music).的头部可与目标为谓词匹配。但由于这个语句又是一个规则,于是,这时对原目标的求解, 就又转化为依次对子目标likes(X,sports)和 likes(X,music)的求解。这次子目标likes(X,sports)与程序中的事实立即匹配成功,且变量 X被约束为bell。于是,系统便接着求解第二个子目标。由于变量X已被约束,所以这时第二个子目标实际上已变成了likes(bell,music).由于程序中不存在事实likes(bell,music),所以该目标的求解失败。于是,系统

11、就放弃这个子目标,并使变量 X恢复为自由变量,然后回溯到第一个子目标,重新对它进行求解。由于系统已经记住了刚才已同第一子目标谓词匹配过的事实的位置,所以重新求解时,便从下一个事实开始测试。易见,当测试到程序中第三个事实时,第一个子目标便求解成功,且变量X被约束为mary。这样,第二个子目标也就变成了likes(mary,music).再对它进行求解。这次很快成功。由于两个子目标都求解成功,所以,原目标friend(john,Y)也成功,且变量丫被约束为mary(由丫与X的合一关系)。于是,系统回答:Y=mary程序运行结束。上面只给岀了问题的一个解。如果需要和可能的话,系统还可把john的所有

12、朋友都找岀来。我们把上述程序的运行过程再用示意图(图2 1)描述如下:friend (john, !)1 ikeslikes (bellf sports)(likes (mary, music)likes (niary, sports)图2 1PROLOG程序运行机理示例上述程序的运行是一个通过推理实现的求值过程。我们也可以使它变为证明过程。例如,把上述程序中的询问改为frie nd(joh n, mary)则系统会回答:yes若将询问改为:rie nd(joh n,smith)则系统会回答:no从上述程序的运行过程可以看岀,PROLOG程序的执行过程是一个(归结)演绎推理过程。其特点是:推理

13、方式为反向推理,控制策略是深度优先,且有回溯机制。其具体实现方法是:匹配子句的顺序是自上而下;子目标选择顺序是从左向右;(归结后)产生的新子目标总是插入被消去的目标处(即目标队列的左部)。PROLOG的这种归结演绎方法被称为SLD(LinearresolutionwithSelectionfunctionforDefiniteclause)归结,或 SLD反驳-消解法。SLD归结就 是PROLOG程序的运行机理,它也就是所谓的PROLOG语言的过程性语义。TurboPROLOG程序设计2.4.1 Turbo PROLOG 的程序结构一个完整的Turbo PROLOG版)程序一般包括常量段、领域

14、段、数据库段、谓词段、目标段和子句段等六个部分。各段以其相应的关键字constants、domains、database、predicates、goal和clauses开头加以标识。:另外,在程序的首部还可以设置指示编译程序执行特定任务的编译指令;在程序的任何位置都可设置注解。总之,一个完整的TurboPROLOG版)程序的结构如下/*注释*/编译指令con sta ntsdomainsdatabasepredicatesgoalclauses当然, 一个程序不一定要包括上述所有段, 但一个程序至少要有一个 predicates 段、 clauses 段和 goal 段。在大多数情形中,还需要

15、一个 domains 段,以说明表、复合结构及用户自定义的域名。 如若省略 goal 段,则可在程序运行时临时给出,但这仅当在开发环境中运行程序时方可给出。 若要生成一个独立的可执行文件,则在程序中必须包含 goal 段。另一方面,一个程序也只能有 一个 goal 段。例 如果把上节中的程序要作为 TurboPROLOG 程序,则应改写为:/* 例子程序 -1*/DOMAINSname=symbolPREDICATESlikes(name,name).friend(name,name)GOALfriend(john,Y),write( Y=,丫).CLAUSESlikes(bell,sport

16、s).likes(mary,music).likes(mary,sports).likes(jane,smith).friend(john,X):-likes(X,sports),likes(X,music). friend(john,X):-likes(X,reading),likes(X,music).结合上例,我们再对上述程序结构中的几个主要段的内容和作用加以说明 (其余段在后面用到时 再作说明 ):领域段该段说明程序谓词中所有参量项所属的领域。领域的说明可能会出现多层说明,直到最终说明到 Turbo PROLOG的标准领域为止(如上例所示)。Turbo PROLOG的标准领域即标准数

17、据类型,包括整数、实数、符号、串和符号等,其具体说明如表所示。表Turbo PROLOG的标准领域领戦名称聪值范別ft Vinteger32 节開32 767 ,realilE307LE-F3O8乎符char用单引号括拄的新有可能的字符申string L用一对双引号拈住的任羸字符序列程序 中的串业长可达E佛小字符,而文件中的H 长可为64 k789% F TurboS*prog 11J符号symbd 以小写字邸打头的字時、最字和下効 賤序列 审N prolog programin严直me i agesddressatr-check-a谓词段:该段说明程序中用到的谓词的名和参量项的名(但Turb

18、o PROLOG的内部谓词无须说明)子句段:该段是Turbo PROLOG程序的核心,程序中的所有事实和规则就放在这里,系统在 试图满足程序的目标时就对它们进行操作。目标段:该段是放置程序目标的地方。目标段可以只有一个目标谓词,例如上面的例子中就只有一个目标谓词;也可以含有多个目标谓词,如:goalreadi nt(X),Y=X+3,write(Y=,Y).就有三个目标谓词。这种目标称为复合目标。另外,一般称程序目标段中的目标为内部目标,而称在程序运行时临时给岀的目标为外部 目标。242Turbo PROLOG的数据与表达式1领域1) 标准领域Turbo PROLOG中不定义变量的类型,只说明

19、谓词中各个项的取值域。2) 结构结构也称复合对象,它是TurboPROLOG谓词中的一种特殊的参量项(类似于谓词逻辑中的函数)。结构的一般形式为函子 (参量表)其中函子及参量的标识符与谓词相同。注意,这意味着结构中还可包含结构。所以,复合 对象可表达树形数据结构。例如下面的谓词likes (T om,sports(football,basketball,table-te nni s).中的sports(football,basketball,table-te nn is)就是一个结构,即复合对象。又如:person(张华,student(西安石油学院“),address(“中国,陕西,西安).

20、reading(“王宏“,book(“人工智能技术基础教程,“西安电子科技大学岀版社).frie nd(father(Li),father(Zhao).这几个谓词中都有复合对象。复合对象在程序中的说明,需分层进行。例如,对于上面的谓词likes(Tom,sports(football,basketball,table-tennis).在程序中可说明如下: domains name=symbol sy=symbol sp=sports(sy,sy,sy) predicates likes(name,sp)3) 表表的一般形式是x1,x2,水 n其中xi(i=1,2,PROLOG的项,一般要求同一

21、个表的元素必须属于同一领域。不含任何元素的表称为空表,记为。例如下面就是一些合法的表。1,2,3 apple,orange,banana,grape,cane PROLOG,MAENS,PROGRAMMING,in logic a,b,c,d,e表的最大特点是其元素个数可在程序运行期间动态变化。表的元素也可以是结构或表, 且这时其元素可以属于不同领域。例如:n ame(Li Min g),age(20),sex(male),address(xi an) 1,2, 3,4,5 ,6,7 都是合法的表。后一个例子说明,表也可以嵌套。 实际上, 表是一种特殊的结构。 它是递归结构的另一种表达形式。

22、这个结构的函数名取决于具体 的PROLOG版本。这里我们就用一个圆点来表示。下面就是一些这样的结构及它们的表表示形式:结构形式表形式(a, : ):a(a, (b, : ): a,b(a, (b, (c, : ): a,b,c表的说明方法是在其组成元素的说明符后加一个星号 *。如:domainslists=string*predicatespl(lists)就说明谓词 pl 中的项 lists 是一个由串 string 组成的表。对于由结构组成的表,至少得分三步说明。例如对于下面谓词p 中的表p( name(Liming),age(20) )则需这样说明 :domainsrec=seg* se

23、g=name(string);age(integer)predicates2. 常量与变量由上面的领域可知,Turbo PROLOG的常量有整数、实数、字符、串、符号、结构、表和文件这八种数据类型。同理,Turbo PROLOG的变量也就有这八种取值。另外,变量名要求必须是以大写字母或下划线开头的字母、数字和下划线序列,或者只有一个下划线。这后一种变量称为无名变量。3. 算术表达式Turbo PROLOG提供了五种最基本的算术运算:加、减、乘、除和取模,相应运算符号为+、-、*、/、mod。这五种运算的顺序为:*、/、mod优先于+、-。同级从左到右按顺序运算,括号优先。算术表达式的形式与数学

24、中的形式基本一样。例如:数学中的算术表达式PROLOG中的算术表达式x+yzX+Y*Zab-c/dA*B-C/Du mod vU mod V(表示求U除以V所得的余数)即是说,Turbo PROLOG中算术表达式采用通常数学中使用的中缀形式。这种算术表达式为PROLOG的一种异体结构,若以PROLOG的结构形式来表示,则它们应为+(X,*(Y,Z)-(*(A,B),/(C,D)mod(U,V)所以,运算符+、-、*、/和mod实际也就是 PROLOG内部定义好了的函数符。在Turbo PROLOG程序中,如果一个算术表达式中的变元全部被实例化(即被约束)的话,则这 个算术表达式的值就会被求岀。

25、求岀的值可用来实例化某变量,也可用来同其他数量进行比较, 用一个算术表达式的值实例化一个变量的方法是用谓词“is或 “ =来实现。例如:Y is X+5 或 Y=X+5(*)就使变量丫实例化为X+5的值(当然X也必须经已被某值实例化 ),可以看岀,这里对变量 丫的实 例化方法类似于其他高级程序语言中的赋值”,但又不同于赋值。例如,在 PROLOG中下面的式子是错误的:X=X+14. 关系表达式Turbo PROLOG提供了六种常用的关系运算,即小于、小于或等于、等于、大于、大于或等 于和不等于,其运算符依次为,=,Turbo PROLOG的关系表达式的形式和数学中的也基本一样,例如: 数学中的

26、关系式Turbo PROLOG中的关系式X+1 YX+1=YX YXY即是说,Turbo PROLOG中的关系式也用中缀形式。当然,这种关系式为 Turbo PROLOG中的异体原子。若按Turbo PROLOG中的原子形式来表示,则上面的两个例子为=(X+1,丫和 (X,Y)所以上述六种关系运算符,实际上也就是Turbo PROLOG内部定义好了的六个谓词。这六个关系运算符可用来比较两个算术表达式的大小。例如:brother(Name1,Name2):-pers on( Name1,ma n,Age1),pers on (Name2,ma n,Age2),mother(Z,Name1),mo

27、ther( Z,Name2), Age1Age2.需要说明的是,“=勺用法比较特殊,它既可以表示比较,也可以表示约束值,即使在同一 个规则中的同一个“= 也是如此。例如:(例一)p(X,Y,Z):-Z=X+Y.当变量X、丫、Z全部被实例化时,“=勺是比较符。如:对于问题Goal:p(3,5,8).机器回答:yes。而对于Goal:p(3,5,7).机器回答:no。即这时机器把X+Y的值,与Z的值进行比较。(例二)但当X,Y被实例化,为 Z未被实例化时,“=勺就是约束符。如:Goal:p(3,5,Z).机器回答:Z=8这时,机器使Z实例化为X+Y的结果。2.4.3 输入与输岀虽然PROLOG能自

28、动输岀目标子句中的变量的值,但这种输岀功能必定有限,往往不能满足实际需要;另一方面,对通常大多数的程序来说,运行时从键盘上输入有关数据或信息也是必不可少的。为此每种具体PROLOG 一般都提供专门的输入和输岀谓词,供用户直接调用。例如,下面就是TorboPROLOG的几种输入输岀谓词:(1) readln (X)。这个谓词的功能是从键盘上读取一个字符串,然后约束给变量X readi nt (X)。这个谓词的功能是从键盘上读取一个整数, 则该谓词失败。(3) readreal (X)。这个谓词的功能是从键盘上读取一个实数, 则该谓词失败。 readchar(X)。这个谓词的功能是从键盘上读取一个

29、字符, 字符,则该谓词失败。然后约束给变量 X,如果键盘上打入的不是整数然后约束给变量 X,如果键盘上打入的不是实数然后约束给变量X,如果键盘上打入的不是单个(5) write(X1,X2, Xn)。这个谓词的功能是把项Xi(i=1,2,的值显示在屏幕上或者打印在纸上,当有某个Xi未实例化时,该谓词失败,其中的 Xi可以是变量,也可以是字符串或数字。(6) nl换行谓词。它使后面的输岀(如果有的话)另起一行。另外,利用write的输岀项n也同样可起换行作用。例如:write( name), n l ,write(age)与 write(name,n,age)的效果完全一样。例用上面的输入输岀谓

30、词编写一个简单的学生成绩数据库查询程序。PREDICATESstudent(integer,string,real)gradeGOAL grade.CLAUSES student(1, 张三 ,. student(2, 李四 ,. student(3, 王五 ,. grade:-write( 请输入姓名 :),readln(Name), student(-,Name,Score), nl,write(Name, 的成绩是 ,Score).grade:- write( 对“不起,找不到这个学生 ! ” ). grade:-write( 对不起,找不到这个学生 !). 下面是程序运行时的屏幕显示

31、: 请输入姓名: 王五 王五的成绩是。2.4.4 分支与循环PROLOG中并无专门的分支和循环语句,但PROLOG也可实现分支和循环程序结构。1. 分支对于通常的IF-THEN-ELSE分支结构,PROLOG可用两条同头的并列规则实现。例如,将IF x0THENx:=1ELSE x:=0用PROLOG实现则是Br :-x0,x=1.Br :-x=0.类似地,对于多分支,可以用多条规则实现。例如:Br :-x0,x=1.Br :-x=0,x=0.Br :-x0,x=-1.2. 循环PROLOG可以实现计循环次数的FOR循环,也可以实现不计循环次数的DO循环。例如下面的程序段就实现了循环,它使得

32、write 语句重复执行了三次,而打印输出了三个学生的 记录。student(1, 张三 ,.student(2, 李四 ,.student(3, 王五 ,. print:-student(Number,Name,Score), write(Number,Name,Score),n l , Number=3.这个例子可以看作是计数循环。 当然, 也可以通过设置计数器而实现真正的计数循环。 下面的程 序段实现的则是不计数的DO循环。student(1, 张三 ,.student(2, 李四 ,.student(3, 王五 ,.print:-student(Number,Name,Score),w

33、rite(Number,Name,Score),nl,fail.print:-.这个程序段中的 fail 是一个内部谓词,它的语义是恒失败。这个程序段与上面的程序段的差别仅 在于把原来用计数器(或标记数)循环控制语句变成了恒失败谓词fail ,另外再增加了一个 print语句。增加这个语句的目的是为程序设置一个出口。因为 fail 是恒失败,下面若无出口的话,将 引起 print 本身的失败。进而又会导致程序中的连锁失败。2.4.5 动态数据库 动态数据库就是在内存中实现的动态数据结构。 它由事实组成, 程序可以对它操作, 所以在程序 运行期间它可以动态变化。Turbo PROLOG提供了三个

34、动态数据库操作谓词 :asserta (). assertz ().retract ().其中 fact 表示事实。这三个谓词的功能是:asserta (). 把 fact 插入当前动态数据库中的同名谓词的事实之前;assertz (). 把 fact 插入当前动态数据库中的同名谓词的事实之后;retract(). 把 fact 从当前动态数据库中删除。 例如语句asserta(student(20, 李明 ,).将在内存的谓词名为 student 的事实前插入一个新事实:student(20, 李明 ,如果内存中还没有这样的事实,则它就是第一个。又如语句retract(student(20,

35、-,-). 将从内存的动态数据库中的删除事实 student(20,-,-)它可解释为学号为 20 的一个学生的记录。注意,这里用了无名变量 -。可以看岀,PROLOG提供的动态数据库机制,可非常方便地实现堆栈、队列等动态数据结构,提 供的数据库操作谓词大大简化了编程。另外,PROLOG还提供了谓词save(). consult(). 前者可将当前的动态数据库存入磁盘文件,后者则可将磁盘上的一个事实数据文件调入内存。2.4.6 表处理与递归表是PROLOG中一种非常有用的数据结构。表的表述能力很强,数字中的序列、 集合,通常语言中的数组、 记录等均可用表来表示。 表的最大特点是其长度不固定,

36、在程序的运行过程中可 动态地变化。具体来讲,就是在程序运行时,可对表施行一些操作,如给表中添加一个元素,或 从中删除一个元素, 或者将两个表合并为一个表等等。 用表还可以方便地构造堆栈、 队列、 链表、 树等动态数据结构。表还有一个重要特点, 就是它可分为头和尾两部分。 表头是表中第一个元素, 而表尾是表中除第 一个元素外的其余元素按原来顺序组成的表。例如下面的例子:表表头表尾1,2,3,4,5 1 2,3,4,5apple,orange,banana :a,b , : c , : d,e门applea,borange,banana c , : d,e:PROLOGPROLOG “:口无定义无

37、定义在程序中是用竖线 “ |来区分表头和表尾的,而且还可以使用变量。例如一般地用H|T 来表示一个表,其中H、T都是变量,H为表头,T为表尾。注意,此处H是一个元素(表中第一个元素),而T则是一个表(除第一个元素外的表中其余元素按原来顺序组成的表)。表的这种表示 法很有用,它为表的操作提供了极大的方便。下面我们就给岀用这种表示法通过匹配合一提取表头和表尾的例子。表1表2合一后的变量值X|Y a,b,c X=a,Y= : b,c X|Y aX=a,Y=:a|Y X,bX=a,Y= : bX,Y,乙a,b,c X=a,Y=b,Z=ca,Y |Z X,b , : cX=a,Y=b,Z= : c还需说

38、明的是,表中的竖杠“|后面只能有一个变量。例如写法X|Y,Z就是错误的。但竖杠的前面的变量可以多于一个。例如写法X,Y|Z是允许的。这样,这个表同a,b,c匹配合一后,有X=a,Y=b,Z= : c 另外,竖杠的前面和后面也可以是常量,例如 a|Y 和X|b 都是允许的,但注意,后一个表 称为无尾表,如果它同表a|Y 匹配,则有X=a,Y=b(而不是 Y= b )如果无竖杠“,则不能分离岀表尾。例如,表X,Y,Z与a,b,c合一后得 X=a,Y=b,Z=co其中变量Z并非等于c。例设计一个能判断对象X是表L的成员的程序。我们可以这样设想:如果X与表L中的第一个元素(即表头)是同一个对象,则X就

39、是L的成员;(2) 如果X是L的尾部的成员,贝U X也就是L的成员。根据这种逻辑关系,于是有下面的PROLOG程序:member(X, X|Tail ).member(X, Head|Tail ):-member(X,Tail).其中第一个子句的语义就是上面的第一句话,第二个子句的语义就是上面的第二句话。可以看岀,这个程序中使用了递归技术,因为谓词member的定义中又含有它自身。利用这个程序我们就可以判定任意给定的一个对象和一个表之间是否具有member (成员)关系。例如,我们取表 L为a,b,c,d ,取X为a,对上面的程序提岀如下询问:Goal:member(a, a,b,c,d).则

40、有回答:yes同样对于询问:Goal:member(b, a,b,c,d ).Goal:member(c, a,b,c,d).Goal:member(d, a,b,c,d ).都有回答:yes但若询问Goal:member(e, a,b,c,d).则回答:no如果我们这样询问Goal:member(X, a,b,c,d ).意思是要证明存在这样的X,它是该表的成员,这时系统返回 X的值,即X=a如果需要的话,系统还会给岀X的其他所有值。例 表的拼接程序,即把两个表连接成一个表。append(:丄,L).append( : H|T 丄2, : H|Tn ):-append(T丄2,Tn).一个非

41、L1的尾T程序中第一个子句的意思是空表同任一表L拼接的结果仍为表 L;第二个子句的意思是说,空的表L1与另一个表L2拼接的结果L3是这样一个表,它的头是L1的头,它的尾是由 同L2拼接的结果Tn。这个程序刻划了两个表与它们的拼接表之间的逻辑关系。可以看岀,谓词 append是递归定义的,子句append( 口丄丄)为终结条件,即递归岀口。对于这个程序,如果我们询问Goal:append( 1,2,3 , 4,5丄).则系统便三次递归调用程序中的第二个子句,最后从第一个子句终止,然后反向依次求岀 每次的拼接表,最后输岀L= : 1,2,3,4,5 当然,对于这个程序也可以给岀其他各种询问,如:G

42、oal:append( : 1,2,3 , : 4,5 , : 1,2,3,4,5 ).系统回答:yesGoal:append( : 1,2,3 , : 4,5 , : 1,2,3,4,5,6 ).系统回答:noGoal:append( : 1,2,3 ,Y, : 1,2,3,4,5 ).系统回答:Y= :4,5Goal:append(X, 4,5 , 1,2,3,4,5 ).系统回答:X= : 1,2,3Goal:append(X,Y, 1,2,3,4,5 ).系统回答:X= : ,Y= : 1,2,3,4,5 X= : 1 ,Y= : 2,3,4,5 X= : 1,2 ,Y= : 3,4,

43、5 X= : 1,2,3 ,Y= : 4,5 等等(如果需要所有解的话)。例表的输岀。print(:).print( : H|T ):-write(H),print(T).例 表的倒置,即求一个表的逆序表。reverse(:,:).reverse( H|T ,L):-reverse(T,L1),append(L1, H丄).这里,reverse的第一个项是输入,即原表,第二个项是输岀,即原表的倒置。247 回溯控制PROLOG在搜索目标解的过程中,具有回溯机制,即当某一个子目标Gi不能满足时,就返回到该子目标的前一个子目标Gi-1,并放弃Gi-1的当前约束值,使它重新匹配合一。在实际问题中,有

44、时却不需要回溯,为此PROLOG中就专门定义了一个阻止回溯的内部谓词一一“!,”称为截断谓?词。截断谓词的语法格式很简单,就是一个感叹号“!。 !的语义是:(1) 若将“插在子句体内作为一个子目标,它总是立即成功;若“位于子句体的最后,则它就阻止对它所在子句的头谓词的所有子句的回溯访问,而 让回溯跳过该头谓词(子目标),去访问前一个子目标(如果有的话);(3) 若“位于其他位置,则当其后发生回溯且回溯到“处时,就在此处失败,并且“还使它所在子句的头谓词(子目标)整个失败(即阻止再去访问头谓词的其余子句(如果有的话),即迫使系统直接回溯到该头谓词 例考虑下面的程序:(子目标)的前一个子目标(如果

45、有的话)。p(a).p(b).q(b). r(X):-p(X),q(X). r(c).对于目标:r(Y).可有一个解(2 1)(2 2)(2 3)(2 4)Y=b但当我们把式(2 4)改为r(X):-p(X),!,q(X).(2-4)时,却无解。这是由于添加了截断谓词“!。因为式(2-4)中求解子目标p(X)时,X被约束到a,然后跳过“!,”但在求解子目标 q(a)时遇到麻烦,于是又回溯到“!,”而“!阻止了对p(X)的下一个子句 p(b)和r的下一个定义子句 r(c)的访问。从而,导致整个求解失败。例设有程序:(2- 5)(26)(2-7)(2 8)g0:-g11,g12,g13. g0:-

46、g14. g12:-g21,!,g23. g12:-g24,g25.给岀目标:g0.假设运行到子目标 g23时失败,这时如果子句(2 7)中无 啲话,则会回溯到g21,并且,如果g21 也失败的话,则会访问下面的子句(2 8)。但由于有!存在,所以不能回溯到 g21,而直接宣告g12 失败。于是,由子句(25),这时则回溯到 g11。如果我们把子句(2 7)改为g12: -g21, g23,L(2 9)当然这时若g23失败时,便可回溯到g21,而当g21也失败时,便回溯到g12,即子句(2 8)被激 活”但对于修改后的程序,如果 g13失败,则虽然可回溯到g12,但对g12不做任何事情,便立即

47、跳过它,而回溯到g11,如果子句(29)中无!,则当g13失败时,回溯到 g12便去考虑子句(2 8),只有当子句(2 8)再失败时才回溯到g11o248 程序举例下面我们给岀几个简单而又典型的例子程序。通过这些程序,读者可以进一步体会和理解 PROLOG程序的风格和能力,也可以掌握一些基本的编程技巧。例下面是一个简单的路径查询程序。程序中的事实描述了如图2-2所示的有向图,规则是图中两节点间有通路的定义。图2 2有向图predicatesroad(symbol,symbol)path(symbol,symbol)clausesroad(a,b).road(a,c).road(b,d).roa

48、d(c,d).road(d,e).road(b,e).path(X,Y):-road(X,Y). path(X,Y):-road(X,Z),path(Z,Y).程序中未含目标,所以运行时需给岀外部目标。例如当给目标:path(a,e).系统将回答:yes但当给目标:path(e,a).时,系统则回答:no如果给岀目标:run.且在程序中增加子句run:-path(a,X),write(X=,X), nl,fail.run.屏幕上将会输岀:X=bX=cX=dX=eX=dX=eX=e即从a岀发到其他节点的全部路径。例下面是一个求阶乘程序,程序中使用了递归。/*aFactorialProgram*/

49、doma insn,f=in tegerpredicatesfactorial( n,f)goalreadi nt (I),factorial(l,F),write(l,!=,F).clausesfactorial(1,1).factorial(N,Res):-N0,N仁 N-1,factorial(N1,FacN1),Res=N*FacN1.程序运行时,从键盘输入一个整数,屏幕上将显示其阶乘数。例下面是一个表的排序程序,采用插入排序法。/*in sertsort*/doma inslisti=i nteger*predicatesin sert-sort(listi , listi)in s

50、ert(i nteger,listi,listi)asc-order(i nteger,i nteger)clausesinsert-sort( , ).insert-sort( H|Tai门,Sorted-list):- insert-sort(Tail,Sorted-Tail),in sert(H,Sorted-Tail,Sorted-list).insert(X, Y|Sorted-list , Y|Sorted-list1 ):- asc-order(X,Y),!,in sert(X,Sorted-list,Sorted-list1).insert(X,Sorted-list,X|So

51、rted-list ).asc-order(X,Y):-XY.程序中对表处理使用了递归。程序中也未给岀目标,需要在运行时临时给岀。例如当给目标:insert-sort( : 5,3,4,2,6,1,7,8,9,0 ,L).系统将输出 :L= 0,1,2,3,4,5,6,7,8,9 例下面是一个简单的通信录管理程序,其中用到输入输出、动态数据库等。通过阅读这个程序, 我们还可以掌握循环结构和简单的菜单程序编写方法。/* 通信录 */databaseperson(string,integer)predicatesaddress-bookchose(integer)inputqueryrepeatg

52、oaladdress-book.clausesaddress-book:- repeat,clearwindow, write(=),nl, write(1- 录入 ),nl, write(2- 查询 ),nl, write(3- 退出 ),nl, write(=),nl, write( 请选择 :-), readint(N), chose(N). chose(1):-input,fail. chose(2):-query,fail. chose(3):-clearwindow,!.input:-clearwindow,write( 姓名 :),readln(Name), write( 电话

53、:),readint(Tel), assertz(person(Name,Tel),!.query:-clearwindow,write( 姓名 :),readln(Name), person(Name,Tel), write( 电话 :,Tel), readchar(-),!.repeat.repeat:-repeat.程序中的 repeat 恒成功。它与内部谓词 fail 配合实现了循环。用谓需说明的是,这仅是一个演示性程序,还不能实用。 因为这里的通信录并未存入磁盘文件。 词 save 就可方便地把通信录存入磁盘文件。例如用语句save()就可把已插入内存的person事实存入文件中。而语句con sult()则可又将该文件中的事实装

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论