1、第2章 逻辑程序设计语言PROLOG2.1 基本PROLOG2.2 Turbo PROLOG程序设计,2.1 基本PROLOG 2.1.1 PROLOG的语句 1. 事实(fact) 格式 谓词名(项表).student(john). like(mary,music).abc. repeat.功能 一般表示对象的性质或关系。 ,2. 规则(rule)格式 谓词名(项表):-谓词名(项表),谓词名(项表). bird(X):-animal(X),has(X,feather). grandfather(X,Y):- father(X,Z),father(Z,Y).run:-start,step1(
2、X),step2(X),end. 功能 一般表示对象间的因果关系、蕴含关系或对应关系。,3. 问题(question)格式 ?-谓词名(项表),谓词名(项表). ? -student(john). ? -like(mary,X). 功能 问题表示用户的询问, 它就是程序运行的目标。,2.1.2 PROLOG的程序PROLOG程序一般由一组事实、 规则和问题组成。问题是程序执行的起点, 称为程序的目标。likes(bell,sports).likes(mary,music).likes(mary,sports).likes(jane,smith).friend(john,X):-likes(X,
3、reading),likes(X,music). friend(john,X):-likes(X,sports),likes(X,music).?-friend(john,Y).,?-likes(mary,X). 或 ?-likes(mary,music). 或 ?-friend(X,Y). 或 ?-likes(bell,sports), likes(mary,music), friend(john,X).,2.1.3 PROLOG程序的运行机理1. 自由变量与约束变量2. 匹配合一两个谓词可匹配合一, 是指两个谓词的名相同, 参量项的个数相同, 参量类型对应相同, 并且对应参量项还满足下列条
4、件之一: (1) 如果两个都是常量, 则必须完全相同。 (2) 如果两个都是约束变量, 则两个约束值必须相同。 (3) 如果其中一个是常量, 一个是约束变量, 则约束值与常量必须相同。 (4) 至少有一个是自由变量。,考虑下面的各组谓词是否可匹配合一? pre1(ob1,ob2,Z) pre1(ob1, ob3,Y)pre1(ob1,ob2,Z) pre1(ob1,X, ob3)pre1(ob1,ob2,Z) pre1(ob1,X,Y),3. 回溯所谓回溯, 就是在程序运行期间, 当某一个子目标不能满足(即谓词匹配失败)时,控制就返回到前一个已经满足的子目标(如果存在的话), 并撤消其有关变量
5、的约束值, 然后再使其重新满足。 成功后, 再继续满足原子目标。如果失败的子目标前再无子目标, 则控制就返回到该子目标的上一级目标(即该子目标谓词所在规则的头部)使它重新匹配。回溯也是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).?-friend(john,Y).则求解目标为
6、friend(john,Y). 新目标 likes(X,reading),likes(X,music).,2.2 Turbo PROLOG程序设计 2.2.1 程序结构/* 注 释 */编译指令constants常量说明domains域说明database数据库说明predicates谓词说明goal目标语句clauses子句集,例 如果把上节的例子程序作为Turbo PROLOG程序, 则应改写为: DOMAINSname=symbolPREDICATESlikes(name,name).friend(name,name)GOALfriend(john,Y), write(Y=, Y).CL
7、AUSESlikes(bell,sports).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 的内部谓词无须说明) 子句段
8、 该段是Turbo PROLOG程序的核心, 程序中的所有事实和规则就放在这里, 系统在试图满足程序的目标时就对它们进行操作。 目标段 该段是放置程序目标的地方。 目标段可以只有一个目标谓词, 例如上面的例子中就只有一个目标谓词; 也可以含有多个目标谓词, 如 goal readint(X),Y=X+3,write(Y=,Y). 就有三个目标谓词。 这种目标称为复合目标。,2.2.2 数据与表达式1. 领域1) 标准领域整数、实数、 字符、 串和符号2) 结构结构也称复合对象, 一般形式为 函子(参量表) likes(Tom, sports(football, basketball, tabl
9、e_tennis). reading(王宏,book(人工智能技术导论,西安电子科技大学出版社). friend(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, , xn其中xi(i=1, 2, , n)为
10、PROLOG的项, 一般要求同一个表的元素必须属于同一领域。不含任何元素的表称为空表, 记为 。1, 2, 3apple, orange, banana, grape, canePROLOG,PROGRAMMING,in logica, b, c, d, e name(LiMing), age(20),sex(male),addr(xian),表的说明方法是在其组成元素的说明符后加一个星号*。 如: domains lists=string* predicates pl(lists) 例如,谓词p(name(Liming), age(20) 则需这样说明: domains rec=seg* s
11、eg=name(string);age(integer) predicates p(rec),2. 常量与变量Turbo PROLOG的常量有整数、实数、 字符、串、符号、结构、表和文件这八种数据类型。同理, Turbo PROLOG的变量也就有这八种取值。另外, 变量名要求必须是以大写字母或下划线开头的字母、数字和下划线序列, 或者只有一个下划线。 这后一种变量称为无名变量。,3. 算术表达式Turbo PROLOG提供了五种最基本的算术运算:加、减、 乘、除和取模, 相应运算符号为+、 -、*、 /、 mod。 这五种运算的顺序为: *、/、 mod优先于+、 -。数学中的算术表达式 PR
12、OLOG中的算术表达式 x+yz X+Y*Zab-c/d A*B-C/Du mod v U mod V Y=X+5 X=X+1 ,4.关系表达式Turbo PROLOG提供了六种常用的关系运算, 即小于、 小于或等于、等于、大于、大于或等于和不等于, 其运算符依次为, =, 数学中的关系式 Turbo PROLOG中的关系式X+1Y X+1=YXY XY,brother(Name1, Name2):-person(Name1, man, Age1), person(Name2, man, Age2),mother(Z, Name1), mother(Z, Name2), Age1Age2.,
13、“=”的用法 :比较符和约束符p(X, Y, Z):-Z=X+Y. 当变量X、Y、Z全部被实例化时, “=”就是比较符。 如: 对于问题 Goal: p(3, 5, 8). 机器回答: yes。 而对于 Goal: p(3, 5, 7). 机器回答: no。 但当X, Y被实例化, 而Z未被实例化时, “=”号就是约束符。 如: Goal: p(3, 5, Z). 机器回答: Z=8 这时, 机器使Z实例化为X+Y的结果。,2.2.3 输入与输出(1) readln (X) (2) readint (X)(3) readreal (X) (4) readchar (X)(5) write (X
14、1, X2, ,Xn) (6) nl,例 用输入输出谓词编写一个简单的成绩 数据库查询程序。PREDICATESstudent(integer, string, real)gradeGOALgrade.CLAUSES student(1, 张三, 90.2). student(2, 李四, 95.5).student(3, 王五, 96.4). grade: -write(请输入姓名:), readln(Name), student(_, Name, Score), nl, write(Name, 的成绩是, Score).grade: -write(对不起, 找不到这个学生!).,2.2.4
15、 分支与循环1. 分支将 IF x0 THEN x:=1 ELSE x:=0 用PROLOG实现则可以是 br:-x0, x=1. br:-x=0.,2. 循环程序1: student(1, 张三, 90.2).student(2, 李四, 95.5).student(3, 王五, 96.4).print:-student(Number, Name, Score), write(Number, Name, Score), nl, Number=3.,程序2:student(1, 张三, 90.2).student(2, 李四, 95.5).student(3, 王五, 96.4).print:
16、-student(Number, Name, Score), write(Number, Name, Score), nl, fail.print:-.,2.2.5 动态数据库动态数据库操作谓词: asserta(fact). assertz(fact). retract(fact). 例 asserta(student(20, 李明, 90.5).retract(student(20,_,_).,2.2.6 表处理与递归 1.表头与表尾表头是表中的第一个元素;表尾是表中除第一个元素外的其余元素按原来顺序组成的表。表头与表尾示例,表 表头 表尾 1, 2, 3,4,5 1 2, 3,4,5 a
17、pple, orange, banana apple orange, banana a, b, c, d, e a, b c, d, e PROLOG PROLOG 无定义 无定义 ,2. 表的匹配合一表的匹配合一示例,表1 表2 合一后的变量值 XY a, b, c X=a, Y= b, c XY a X=a, Y= a Y X, b X=a, Y= b X,Y,Z a, b, c X=a, Y=b, Z=c a, Y Z X, b , c X=a, Y=b, Z= c ,例 设计一个能判断对象X是表L的成员的程序。 分析: (1) 如果X与表L中的第一个元素(即表头)是同一个对象, 则X就
18、是L的成员。(2) 如果X是L的尾部的成员, 则X也就是L的成员。 程序: member(X, X|_).member(X, Head|Tail):-member(X, Tail).Goal: member(a, a, b, c, d).yesGoal: member(e, a, b, c, d).noGoal: member(X, a, b, c, d).X=a,例 表的拼接程序, 即把两个表连接成一个表。 append(, L, L).append(H|T, L2,H|Tn):-append(T,L2, Tn).Goal: append(1, 2, 3, 4, 5, L).L=1, 2,
19、3, 4, 5Goal: append(1,2,3,4,5,1,2,3,4,5).yes Goal: append(1,2,3,4,5,1,2,3,4,5,6). no,Goal: append(1, 2, 3, Y, 1, 2, 3, 4, 5).Y=4, 5 Goal: append(X, 4, 5, 1, 2, 3, 4, 5).X=1, 2, 3 Goal: 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, 5 X=1, 2, 3, Y=4, 5,例 表的输出。 print
20、().print(H|T):-write(H), print(T).例 表的倒置, 即求一个表的逆序表。 reverse(,).reverse(H|T,L):-reverse(T,L1), append(L1,H,L).,2.2.7 回溯控制 截断谓词“!”的语义: (1) 若将“!”插在子句体内作为一个子目标, 它总是立即成功。 (2) 若“!”位于子句体的最后, 则它就阻止对它所在子句的头谓词的所有子句的回溯访问, 而让回溯跳过该头谓词(子目标), 去访问前一个子目标(如果有的话)。 (3) 若“!”位于其他位置, 则当其后发生回溯且回溯到“!”处时, 就在此处失败, 并且“!”还使它所在
21、子句的头谓词(子目标)整个失败(即阻止再去访问头谓词的其余子句(如果有的话), 即迫使系统直接回溯到该头谓词(子目标)的前一个子目标(如果有的话)。,例 考虑下面的程序: p(a). (2-1)p(b). (2-2)q(b). (2-3)r(X):-p(X), q(X). (2-4)r(c).对于目标: r(Y).可有一个解 Y=b但当把式(2-4)改为r(X):-p(X), !, q(X). (2-4)时, 却无解。 为什么呢?,例 设有程序: g0:-g11, g12, g13. (2-5)g0:-g14. (2-6)g12:-g21, !, g23. (2-7)g12:-g24, g25
22、. (2-8) 给出目标: g0. 把子句(2-7) 改为 g12:-g21, g23, !. (2-9),2.2.8 程序举例 例 一个简单的路径查询程序。 predicatesroad(symbol, symbol)path(symbol, symbol) clausesroad(a, b).road(a, c).road(b, d).road(c, d). road(d, e).road(b, e).path(X, Y):-road(X, Y).path(X, Y):-road(X, Z), path(Z, Y).,Goal: path(a, e).yes Goal :path(e, a).no Goal : run.run:-path(a, X), write(X=, X), nl, fail. run. X=b X=c X=d X=e X=d X=e X=e,例 下面是一个求阶乘程序, 程序中使用了递归。 domainsn, f = integerpredicatesfactorial(n, f)goalreadint(I), factorial(I, F), write(I, !=, F). clausesfactorial(1, 1).factorial(N, Res):-N0, N1=N-1, factorial(N1, FacN1), Res=N*FacN1.,