111
第第第 第第第第第第第第第第

第二章 人工智能程序设计语言

  • Upload
    lilika

  • View
    77

  • Download
    1

Embed Size (px)

DESCRIPTION

第二章 人工智能程序设计语言. 目录. 2 .1 综述 2.2 函数型程序设计语言 LISP 2.3 逻辑型程序设计语言 PROLOG 2.4Turbo PROLOG 程序设计. 2.1 综述 ( 1 ). 人工智能解决的问题 人工智能解决的问题是实现对脑功能的模拟和再现,人工智能程序要面向问题、面向逻辑,要能支持知识表示,能描述逻辑关系和抽象概念,其处理对象更多是知识,或者说是符号。 第一个程序设计语言 1960 年美国麦卡锡和他的研究小组设计实现 LISP ( LISt Processing ),是一种表处理语言。. 2.1 综述. 函数型语言 逻辑型语言 - PowerPoint PPT Presentation

Citation preview

Page 1: 第二章 人工智能程序设计语言

第二章 人工智能程序设计语言

Page 2: 第二章 人工智能程序设计语言

目录 2.1 综述 2.2 函数型程序设计语言 LISP 2.3 逻辑型程序设计语言 PROLOG 2.4Turbo PROLOG 程序设计

Page 3: 第二章 人工智能程序设计语言

2.1 综述( 1 ) 人工智能解决的问题 人工智能解决的问题是实现对脑功能的模拟和再

现,人工智能程序要面向问题、面向逻辑,要能支持知识表示,能描述逻辑关系和抽象概念,其处理对象更多是知识,或者说是符号。

第一个程序设计语言 1960 年美国麦卡锡和他的研究小组设计实现 LISP

( LISt Processing ),是一种表处理语言。

Page 4: 第二章 人工智能程序设计语言

2.1 综述 函数型语言 逻辑型语言 面向对象语言 混合型语言

Page 5: 第二章 人工智能程序设计语言

2.1.1 函数型语言 典型代表 LISP LISP 程序由一组函数组成,程序的执行

过程就是一系列的函数调用和求值过程。 纯函数型程序设计语言 FP

Page 6: 第二章 人工智能程序设计语言

2.1.2 逻辑型语言 典型代表 PROLOG ( PROgramming in L

OGic ) PROLOG 程序是陈述性语言,不需要告诉

计算机“怎么做”,只需要告诉计算机“做什么”。

PROLOG 语言是以 Horn 子句逻辑为基础的程序设计语言,是目前最具代表性的一种逻辑程序设计语言。

PARLOG 、 Concurrent PROLOG 、 GHC

Page 7: 第二章 人工智能程序设计语言

2.1.3 面向对象语言 面向对象语言信息隐蔽、封装、继承、

多态、消息传递,改善了软件的复杂性、模块性、重用性和可维护性。

面向对象程序设计的类、对象、继承等概念与人工智能的知识表示和知识库联系紧密。

Smalltalk 、 C ++、 Java

Page 8: 第二章 人工智能程序设计语言

2.1.4 混合型语言( 1 ) 函数型与逻辑型相结合

耦合型 LOGLISP 。在 LISP 的基础上增加了表达合一、

回溯机制的系统函数。 FUNLOG 。在 PROLOG 的基础上怎家了函数定

义机制,系统以归结语义执行 PROLOG 程序。 POPLOG 。是 POP - 11 、 PROLOG 、 LISP

的混合型语言。 统一型

具有归结语义的函数型语言 集成式语言( LEAF 、 APPLOG )

Page 9: 第二章 人工智能程序设计语言

2.1.4 混合型语言( 2 ) 函数型与面向对象相结合的语言

Flavors LOOPS CommonLoops CLOS CommonObjects OBJ2

Page 10: 第二章 人工智能程序设计语言

2.1.4 混合型语言( 3 ) 逻辑型与面向对象相结合的语言

SPOOL Orient 84k Vulan

Page 11: 第二章 人工智能程序设计语言

2.2 函数型程序设计语言 LISP( 1 ) LISP 的特点

LISP 程序由一组函数组成,程序的执行过程时函数的调用过程。

程序和数据在形式上是相同的,都是符号表达式,简称为 S -表达式。

递归是 LISP 语言的主要控制结构,适于过程描述和问题求解。

程序以交互形式运行,便于开发各类程序。

Page 12: 第二章 人工智能程序设计语言

2.2 函数型程序设计语言 LISP( 2 ) LISP 的程序结构与运行机制 S -表达式 基本函数 自定义函数 程序举例

Page 13: 第二章 人工智能程序设计语言

2.2.1LISP 的程序结构与运行机制( 1 ) LISP 程序结构

函数的定义( DEFUN ( < 函数名 > ( < 形参表 > ) < 函数名 > )( < 函数名 > ( < 形参表 > ) < 函数名 > ) …( < 函数名 > ( < 形参表 > ) < 函数名 > )( < 函数名 > < 实参表 > ) …( < 函数名 > < 实参表 > ) 函数的调用

Page 14: 第二章 人工智能程序设计语言

2.2.1LISP 的程序结构与运行机制( 2 ) LISP 程序(DUFUN HANOI(a b c n) (COND((=n 1)(MOVE_DISK a c)) (T (HANOI a c b (- n 1)) (MOVE-DISK a c) (HANOI b a c(- n 1))))(DEFUN MOVE-DISK(from to) (TERPRI) (PRINC”Movie Disk From”) (PRINC from) (PRINC “To”) (PRINC to))

(HONOI ‘a ‘b ‘c 3)

Page 15: 第二章 人工智能程序设计语言

2.2.2S- 表达式( 1 ) 原子

文字原子 由字母和数字组成得字符串,是 S-表达式得最简单的情况,用来表示常量、变量和函数的名字等。

串原子 由双引号括起来的一串字符。 数字原子 数字串组成。

S -表达式的定义 原子是 s -表达式。 若 S1 和 S2 是 S -表达式,则( S1•S2 )是

S -表达式。

Page 16: 第二章 人工智能程序设计语言

2.2.2 S- 表达式( 2 ) 表

表是 LISP 语言中最常用的数据类型,也是主要的处理对象。

表由圆括号括起来得由空格分开的若干元素的集合。 表的一般形式为:

(<S- 表达式 >< S- 表达式 >…< S- 表达式 >) 表是一种特殊的 S -表达式 (A ) (A•NIL) (A B) (A • (B•NIL)) (A B C) (A • B •(C•NIL)) (A B C D) (A • B •C(D•NIL))

Page 17: 第二章 人工智能程序设计语言

2.2.3 基本函数( 1 ) 表处理函数

CAR 函数 格式 ( CAR<表 >) 功能 取出表中的表头。

CDR 函数 格式 ( CDR<表 >) 功能 取出表中的表尾。

CONS 函数 格式 ( CONS<S- 表达式 ><表 >) 功能 将 S -表达式作为一个元素加到表中去, 并作为所构成新表中的第一个元素。

Page 18: 第二章 人工智能程序设计语言

2.2.3 基本函数( 2 ) APPEND函数

格式 ( APPEND<表 1> <表 2>…… <表 n> ) 功能 将 n 个表中的元素合并成一个新表。

LIST函数 格式 ( LIST<S- 表达式 1> <S- 表达式 1> <S- 表 达式 1> ) 功能 将 n 个表中的元素合并成一个新表。

Page 19: 第二章 人工智能程序设计语言

2.2.3 基本函数( 3 ) 算术函数 LISP 的算术表达式也是用函数

表示,称为算术函数。 求值与赋值函数

SET 格式 ( SET< 变量 ><S- 表达式 >) 功能 把 S -表达式赋给变量。

SETQ SETF ( COMMON LISP )

Page 20: 第二章 人工智能程序设计语言

2.2.3 基本函数( 4 ) 谓词函数

原子谓词 ATOM 格式 ( ATOM<参数 >) 功能 检测其参数是否为原子,是则返回 T,否则返回 NIL 。

相等谓词 EQUAL 格式 ( EQUAL< 参数 >< 参数 >) 功能 判断两个参数是否逻辑相等。

判空表函数 NULL 格式 ( NULL< 参数 >) 功能 判断参数是否为空表,是则返回 T,否则返回 NIL

Page 21: 第二章 人工智能程序设计语言

2.2.3 基本函数( 5) 条件函数

格式 (COND(P1e1) (P2e2) …… (Pnen)

功能控制程序流程

Page 22: 第二章 人工智能程序设计语言

2.2.4 自定义函数( 1 ) 自定义函数的格式为: ( DEFUN<函数名 >( <形参表 >) <函数体 >) 函数体,是用户自定义的函数或 LISP 基

本函数的某种组合。 一般来讲, LISP 自定义函数就是由其基

本函数组合而成的。常用的组合方法有复合、分支、递归、迭代等。其中最具特色的构造方法是递归。

Page 23: 第二章 人工智能程序设计语言

2.2.4 自定义函数( 2 )例 2.1 定义求 N!的 LISP 函数。 阶乘的公式是 n! = n×(n-1)! 1! = 1 0! = 1 由此我们给出其 LISP 函数如下: (DEFUNN!(n) (COND((=n 0)1) ((=n 1)1) (T(* n(N!(- n 1))))))

Page 24: 第二章 人工智能程序设计语言

2.2.4 自定义函数( 3 ) 一个函数是否能递归定义,要取决于以下两条: 函数的求值存在最简的情形,在这种情形下函数值是显然的或已知的;

该函数对于其参数的求值,可以归结为对另一些参数的求值,而且后者比前者更容易求值,即使问题朝最简情形逼近了一步。

Page 25: 第二章 人工智能程序设计语言

2.2.5 程序举例( 1 )例 2.2 符号微分程序。 这里是指数学上的一元函数求导。 我们用 D(ex)表示数学上的 de/dx, 这里 e 为需求导的函数表达式, x为自变量。程序如下: (DEFUN D(ex) (COND((ATOM e)(IF(Eq e x)1 0)) (T(APPLY(D-RULE(CAR e)) (APPEND(CDR e)) (LIST x)))))

Page 26: 第二章 人工智能程序设计语言

2.2.5 程序举例( 2 ) D-RULE 是一个获取给定操作符的微分规则的 LISP 函数。微分规则的存放,是通过为相应操作符建立 d特性的方法完成的。 D-RULE 的定义为

(DEFUN D-RULE(operator) (GET operator′d)) 其中操作符 d的特性值需事先用 SETF 函数建立好。例如对于操作符加+和乘•,在数学上有

d(u + v)/dx = du/dx+ dv/dx d(u•v)/dx = v•du/dx+ u•dv/dx

Page 27: 第二章 人工智能程序设计语言

2.2.5 程序举例( 3 )用 LISP 表示就是 (SETF(GET′+′D)′(LAMBDA(u v x)′(+,(Dux),(D v x)))) (SETF(GET′*′D)′(LAMBDA(u v x)′(+(*,(D u x),v)(*,(D v x),u))))) 给出如下的函数调用 (D′(+(*2x)(*x x))′x); 即求一元

函数 2x+x 2 关于 x的导函数则得到返回值为 (+(+(* 0 x)(* 1 2))(+(* 1 x)(*1 x))) 即 2+2x,结果正确。

Page 28: 第二章 人工智能程序设计语言

2.3 逻辑型程序设计语言 PROLOG PROLOG 的语句 PROLOG 程序 PROLOG 程序的运行机理

Page 29: 第二章 人工智能程序设计语言

2.3.1PROLOG 的语句( 1 ) 事实

格式 < 谓词名 >(< 项表 >). 谓词名是以小写英文字母打头的字母、数字、下划线等组

成的字符串 项表是以逗号隔开的项序列。 项包括由常量或变量表示的简单对象以及函数、结构和表。

事实的形式是一个原子谓词公式。 例如:

student(john). like( mary ,music).

Page 30: 第二章 人工智能程序设计语言

2.3.1PROLOG 的语句( 2 ) 功能 一般表示对象的性质或关系。 作为特殊情形,一个事实也可以只有谓词名而无参量。

例如: abc. repeat.

Page 31: 第二章 人工智能程序设计语言

2.3.1PROLOG 的语句( 3 ) 规则 (rule)

格式 < 谓词名 >(< 项表 >):-< 谓词名 >(< 项表 >){,< 谓词名 >(< 项表 >)}.

其中“ :-” 号表示“ if” (也可以直接写为 if),

其左部的谓词是规则的结论(亦称为头), 右部的谓词是规则的前提(亦称为体), {}表示零次或多次重复, 逗号表示 and(逻辑与 ), 规则的形式是一个逻辑蕴含式。

Page 32: 第二章 人工智能程序设计语言

2.3.1PROLOG 的语句( 4 ) 例如:

bird(X):-animal(X),has(X,feather). “如果 X是动物,并且 X有羽毛,则 X是鸟” grandfather(X,Y):-father(X,Z),father(Z,Y). “X是 Y的祖父,如果存在 Z, X是 Z的父亲并且Z

又是 Y的父亲”。 就是 PROLOG 的合法规则。

功能 一般表示对象间的因果关系、蕴含关系或对应关系。

特殊情况规则中的谓词也可以只有谓词名而无参量。

Page 33: 第二章 人工智能程序设计语言

2.3.1PROLOG 的语句( 5) 问题 (question)

格式 ?-< 谓词名 >(< 项表 >){,< 谓词名 >(< 项表 >)}.

例如: ?-student(john). ?-like(mary,X). 就是两个合法的问题。

功能 问题表示用户的询问,它就是程序运行的目标。

Page 34: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序( 1 ) PROLOG 程序有一组事实、规则和问题组成。 例子 likes(bell,sports). likes(mary,music). likes(mary,sports) likes(jane ,smith). friend(john,X):-likes(X,reading),likes(X,mus

ic). friend(john,X):-likes(X,sports),likes(X,musi

c). ?-friend(john,Y).

Page 35: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序( 2 ) PROLOG 程序中的目标可以变化,也可以含有多个语

句 (上例中只有一个 )。如果有多个语句,则这些语句称为子目标。

?-likes(mary,X). 或 ?-likes(mary,music). 或 ?-friend(X,Y). 或 ?-likes(bell,sports), likes(mary,music), friend(john,X).

Page 36: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序的运行机理( 1 ) POROLOG 程序运行机理是基于归结原理的演绎推理。 PROLOG 程序的运行是从目标出发,并不断进行匹配、合一、归结,回溯,直到目标被完全满足。

自由变量与约束变量 无值的变量为自由变量。 有值的变量为约束变量。 一个变量取了某值就说该变量约束于某值,或者说该变量被某值所约束,或者说该变量被某值实例化了。

Page 37: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序的运行机理( 2 ) 匹配合一

两个谓词可匹配合一,是指两个谓词的名相同,参量项的个数相同,参量类型对应相同,并且对应参量项还满足下列条件之一:

如果两个都是常量,则必须完全相同。 如果两个都是约束变量,则两个约束值必须相同。 如果其中一个是常量,一个是约束变量,则约束

值与常量必须相同。 至少有一个是自由变量。

合一操作 两个自由变量 一个自由变量一个常量

Page 38: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序的运行机理( 3 ) 例如:下面的两个谓词 pre1("ob1","ob2",Z) pre1("ob1",X,Y) 只有当变量 X 被约束为 "ob2",且 Y、Z的约束值相同或者至少有一个是自由变量时,它们才是匹配合一的。

Page 39: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序的运行机理( 4 ) 回溯,

回溯就是在程序运行期间,当某一个子目标不能满足(即谓词匹配失败)时,控制就返回到前一个已经满足的子目标(如果存在的话),并撤消其有关变量的约束值,然后再使其重新满足。

成功后,再继续满足原子目标。 如果失败的子目标前再无子目标,则控制就返回到该子目标的上一级目标(即该子目标谓词所在规则的头部)使它重新匹配。

Page 40: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序的运行机理( 5) 运行过程 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,m

usic). ?-friend(john,Y).

Page 41: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序的运行机理( 6 ) 系统对程序进行扫描,寻找能与目标谓词匹配合一的事实或规则头部。规则

friend(john,X):-likes(X,reading),likes(X,music).

的头部可与目标谓词匹配合一,对原目标的求解就转化为对新目标

likes(X,reading),likes(X,music). 的求解。

Page 42: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序的运行机理( 7) 子目标的求解过程与主目标完全一样,也是从头对程序进行扫描,不断进行测试和匹配合一等,直到匹配成功或扫描完整个程序为止。可以看出,对第一个子目标 like(X,reading)的求解因无可匹配的事实和规则而立即失败,进而导致规则

friend(john,X):-likes(X,reading),likes(X,music).

的整体失败。于是,刚才的子目标 likes(X,reading)和 likes(X,music)

被撤消,系统又回溯到原目标 friend(john,X)。

Page 43: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序的运行机理( 8 ) 系统从该目标刚才的匹配语句处(即第五句)

向下继续扫描程序中的子句,试图重新使原目标匹配,结果发现第六条语句的左部,即规则

friend(john,X):-likes(X,sports),likes(X,music).

的头部可与目标为谓词匹配。但由于这个语句又是一个规则,于是,这时对原目标的求解,就又转化为依次对子目标

likes(X,sports)和 likes(X,music) 的求解。

Page 44: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序的运行机理( 9 ) 子目标 likes(X,sports) 与程序中的事实立即匹配成功,且变量 X 被约束为 bell 。于是,系统便接着求解第二个子目标。由于变量 X 已被约束,所以这时第二个子目标实际上已变成了

likes(bell,music). 由于程序中不存在事实 likes(bell,m

usic),所以该目标的求解失败。

Page 45: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序的运行机理( 10 ) 系统就放弃这个子目标,并使变量 X恢复为自

由变量,然后回溯到第一个子目标,重新对它进行求解。由于系统已经记住了刚才已同第一子目标谓词匹配过的事实的位置,所以重新求解时,便从下一个事实开始测试。

易见,当测试到程序中第三个事实时,第一个子目标便求解成功,且变量 X被约束为 mary。这样,第二个子目标也就变成了

likes(mary,music). 再对它进行求解。

Page 46: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序的运行机理( 11 ) 由于两个子目标都求解成功,所以,原

目标 friend(john,Y) 也成功,且变量 Y被约束为 mary(由 Y与 X的合一关系 )。于是,系统回答: Y=mary

程序运行结束。

Page 47: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序的运行机理( 11 )

图 2─1 PROLOG 程序运行机理示例

Page 48: 第二章 人工智能程序设计语言

2.3.2PROLOG 程序的运行机理( 12 ) PROLOG 程序的执行过程是一个归结演绎的过程。 特点是推理方式为反向推理,控制策略是深度优先,且有回溯机制。

具体实现为匹配子句的顺序是自上而下;子目标选择顺序是从左向右;(归结后)产生的新子目标总是插入被消去的目标处(即目标队列的左部)。

PROLOG 的这种归结演绎方法被称为 SLD(LinearresolutionwithSelectionfunctionforDefiniteclause)归结,或 SLD反驳 - 消解法。 SLD归结也就是所谓的 PROLOG 语言的过程性语义。

Page 49: 第二章 人工智能程序设计语言

2.4Turbor PROLOG 程序设计 Turbor PROLOG 的程序结构 Turbor PROLOG 的数据与表达式 输入与输出 分支和循环 动态数据库 表处理和递归 回溯控制 程序举例

Page 50: 第二章 人工智能程序设计语言

2.4.1Turbor PROLOG 的程序结构( 1 ) 一般包括常量段、领域段、数据库段、谓词段、目标段和子句段等六个部分。各段以其相应的关键字 constants 、 domains 、 database 、 predicates 、 goal 和 clauses 开头加以标识。

Page 51: 第二章 人工智能程序设计语言

2.4.1Turbor PROLOG 的程序结构( 2 ) /*<注释 >*/ <编译指令 > constants < 常量说明 > domains <域说明 > database <数据库说明 > predicates < 谓词说明 > goal <目标语句 > clauses <子句集 >

Page 52: 第二章 人工智能程序设计语言

2.4.1Turbor PROLOG 的程序结构( 3 )

例 2.3 如果把上节中的程序要作为 Turbor PROLOG 程序,则应改写为:

/* 例子程序 -1*/

DOMAINS

name=symbol

PREDICATES

likes(name,name).

friend(name,name)

Page 53: 第二章 人工智能程序设计语言

2.4.1Turbor PROLOG 的程序结构( 4 )GOAL

friend(john,Y),write(″Y=″,Y).

CLAUSES

likes(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).

Page 54: 第二章 人工智能程序设计语言

2.4.1Turbor PROLOG 的程序结构( 4 ) 领域段

Page 55: 第二章 人工智能程序设计语言

2.4.1Turbor PROLOG 的程序结构( 5) 谓词段该段说明程序中用到的谓词的名和参量项的名 (但 Turbo PROLOG 的内部谓词无须说明 )。

子句段该段是 Turbo PROLOG 程序的核心,程序中的所有事实和规则就放在这里,系统在试图满足程序的目标时就对它们进行操作

目标段该段是放置程序目标的地方。目标段可以只有一个目标谓词,例如上面的例子中就只有一个目标谓词;也可以含有多个目标谓词。

Page 56: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 1 ) 领域 常量与变量 算术表达式 关系表达式

Page 57: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 2 )

1.领域 1) 标准领域 Turbo PROLOG中不定义变量的类型,

只说明谓词中各个项的取值域。 2)结构 结构也称复合对象,它是 TurboPRO

LOG谓词中的一种特殊的参量项(类似于谓词逻辑中的函数)。

Page 58: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 3 )

结构的一般形式为 <函子 >(< 参量表 >) 其中函子及参量的标识符与谓词相

同。注意,这意味着结构中还可包含结构。所以,复合对象可表达树形数据结构。例如下面的谓词

likes(Tom,sports(football,basketball,table-tennis)).

reading(" 王宏 ",book(" 人 工 智 能技术基 础教程 ","西安电子科技大学出版社 ")).

Page 59: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 4 ) 复合对象在程序中的说明,需分层进行。

例如,对于上面的谓词 likes(Tom,sports(football,basketball,table-ten

nis)). 在程序中可说明如下: domains name=symbol sy=symbol sp=sports(sy,sy,sy) predicates likes(name,sp)

Page 60: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 5)

3) 表 表的一般形式是[ x1,x2,…,xn]

其中 xi(i=1,2,…,n)为 PROLOG 的项,一般要求同一个表的元素必须属于同一领域。不含任何元素的表称为空表,记为[]。例如下面就是一些合法的表。

[ 1,2,3] [ apple,orange,banana,grape,cane] [ "PROLOG","MAENS","PROGRAMMING","in logi

c"] [[ a,b] ,[ c,d] ,[ e]]

Page 61: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 6 )

表的最大特点是其元素个数可在程序运行期间动态变化。表的元素也可以是结构或表,且这时其元素可以属于不同领域。

例如: [ name("Li Ming"),age(20),sex(male),address(xi a

n)] [[ 1,2] ,[ 3,4,5] ,[ 6,7]] 都是合法的表。后一个例子说明,表也可

以嵌套。

Page 62: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 7)

实际上,表是一种特殊的结构。它是递归结构的另一种表达形式。这个结构的函数名取决于具体的 PROLOG版本。这里我们就用一个圆点来表示。

结构形式 表形式

•(a,[] ) [ a]

•(a,•(b,[] )) [ a,b]

•(a,•(b,•(c,[] ))) [ a,b,c]

Page 63: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 8 )

表的说明方法是在其组成元素的说明符后加一个星号 *。如

domains lists=string* predicates pl(lists) 就说明谓词 pl中的项 lists 是一个由

串 string 组成的表。

Page 64: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 9 )

对于由结构组成的表,至少得分三步说明。例如对于下面谓词 p中的表

p([ name("Liming"),age(20)] )

则需这样说明 : domains rec=seg* seg=name(string);age(integer) predicates p(rec)

Page 65: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 10 )

2 、常量与变量 Turbo PROLOG 的常量有整数、实数、字

符、串、符号、结构、表和文件这八种数据类型。 变量也就有这八种取值。另外,变量名要求必须是以大写字母或下划线开头的字母、数字和下划线序列,或者只有一个下划线(无名变量)。

Page 66: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 11 )3. 算术表达式 基本的算术运算:加、减、乘、除和取模, 相应运算符号为 +、 - 、 *、 /、 mod。 运算的顺序为: *、 /、 mod 优先于 +、 - 。 同级从左到右按顺序运算,括号优先。 表达形式如下 数学 中缀形式 结构形式 x+y z X+Y*Z +(X,*(Y,Z)) ab-c/d A*B-C/D -(*(A,B),/(C,D)) u mod v U mod V mod(U,V)

Page 67: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 12 ) 一个算术表达式中的变元全部被实例化(即被约束)的话,则这个算术表达式的值就会被求出。求出的值可用来实例化某变量,也可用来同其他数量进行比较,用一个算术表达式的值实例化一个变量的方法是用谓词“ is” 或“ =” 来实现。例如:

Y is X+5 或 Y=X+5 (*) 异体谓词 这里对变量 Y的实例化方法类似于其他高级程序语

言中的“赋值”,但又不同于赋值。例如,在 PROLOG中下面的式子是错误的 :

X=X+1

Page 68: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 13 )

4. 关系表达式 六种常用的关系运算,即小于、小于或等于、

等于、大于、大于或等于和不等于 其运算符依次为 <,<=,=,>,>=,<> 数学中 中缀形式 前缀形式 X+1≥Y X+1>=Y >=(X+1,Y) X≠Y X<>Y <>(X,Y)

Page 69: 第二章 人工智能程序设计语言

2.4.2Turbor PROLOG 的数据与表达式( 13 )

六个关系运算符可用来比较两个算术表达式的大小。

brother(Name1,Name2):-person(Name1,man,Age1),

person(Name2,man,Age2),

mother(Z,Name1),mother(Z,Name2), Age1>Age2. “=” 的用法比较特殊,它既可以表示比较,也可以表示约束值,即使在同一个规则中的同一个“ =”也是如此。

p(X,Y,Z):-Z=X+Y.

Page 70: 第二章 人工智能程序设计语言

2.4.3输入与输出( 1 )

PROLOG输入功能有限,且运行时需从键盘输入有关数据或者信息,因此提供专门的输入输出函数:

(1) readln (X)。 这个谓词的功能是从键盘上读取一个字符

串,然后约束给变量 X。 (2) readint (X)。 这个谓词的功能是从键盘上读取一个整数,然后约束给变量 X,如果键盘上打入的不是整数则该谓词失败。

Page 71: 第二章 人工智能程序设计语言

2.4.3输入与输出( 2 ) (3) readreal (X)。 从键盘上读取一个实数,然后约束给变量 X,如果键盘上打入的不是实数则该谓词失败。

(4) readchar(X)。 从键盘上读取一个字符,然后约束给变量X,如果键盘上打入的不是单个字符,则该谓词失败。

(5) write(X1,X2,…  Xn)。 把项 Xi(i=1,2,…n)的值显示在屏幕上或者打印在纸上,当有某个 Xi未实例化时,该谓词失败,其中的 Xi 可以是变量,也可以是字符串或数字。

Page 72: 第二章 人工智能程序设计语言

2.4.3输入与输出( 2 )

(6) nl换行谓词。 它使后面的输出 (如果有的话 )另起一行。另外,利用 write 的输出项 "\n" 也同样可起换行作用。例如:

write("name"), n l ,write("age") 与 write("name","\n","age") 的效果完全一样。

Page 73: 第二章 人工智能程序设计语言

2.4.3输入与输出( 3 )例 2.4 用上面的输入输出谓词编写一个简单的学生成绩数

据库查询程序。 PREDICATES student(integer,string,real) grade GOAL grade. CLAUSES student(1,"张三 ",90.2). student(2,"李四 ",95.5). student(3,"王五 ",96.4).

Page 74: 第二章 人工智能程序设计语言

2.4.3输入与输出( 4 )

grade:-write("请输入姓名 :"),readln(Name), student(-,Name,Score), nl,write(Name,"的成绩是 ",Score).grade:-write(“ 对不起,找不到这个学生 !”).

下面是程序运行时的屏幕显示 :请输入姓名: 王五

王五的成绩是 96.4 。

Page 75: 第二章 人工智能程序设计语言

2.4.4分支与循环( 1 )

PROLOG中并无专门的分支和循环语句,但 PROLOG也可实现分支和循环程序结构。

1.分支 对于通常的 IF-THEN-ELSE分支结构, P

ROLOG 可用两条同头的并列规则实现。例如,将

IF x>0THENx:=1 ELSE x:=0

Page 76: 第二章 人工智能程序设计语言

2.4.4分支与循环( 2 )

用 PROLOG 实现则是 Br :-x>0,x=1. Br :-x=0. 类似地,对于多分支,可以用多条规则实现。

例如: Br :-x>0,x=1. Br :-x=0,x=0. Br :-x<0,x=-1.

Page 77: 第二章 人工智能程序设计语言

2.4.4分支与循环( 3 ) 2.循环 PROLOG 可以实现计循环次数的 FOR循环,也可以实现不计循环次数的 DO循环。

下面的程序段就实现了循环,它使得write 语句重复执行了三次,而打印输出了三个学生的记录。

student(1,"张三",90.2). student(2,"李四 ",95.5). student(3,"王五",96.4). print:-student(Number,Name,Score), write(Number,Name,Score),n l , Number=3.

Page 78: 第二章 人工智能程序设计语言

2.4.4分支与循环( 4 )

不计数的 DO循环。 student(1,"张三 ",90.2). student(2,"李四 ",95.5). student(3,"王五 ",96.4). print:-student(Number,Name,Score), write(Number,Name,Score),nl, fail. print:-. (出口)

Page 79: 第二章 人工智能程序设计语言

2.4.5 动态数据库( 1 )

动态数据库就是在内存中实现的动态数据结构。它由事实组成,程序可以对它操作,所以在程序运行期间它可以动态变化。 Turbo PROLOG提供了三个动态数据库操作谓词 :

asserta (<fact>).把 fact插入当前动态数据库中 的同名谓词的事实之前; assertz (<fact>).把 fact插入当前动态数据库中 的同名谓词的事实之后; retract (<fact>).把 fact从当前动态数据库中删 除。

Page 80: 第二章 人工智能程序设计语言

2.4.5 动态数据库( 2 ) 例如语句 asserta(student(20,"李明 ",90.5)). 将在内存的谓词名为 student 的事实前插入

一个新事实: student(20,"李明 ",90.5) 如果内存中还没有这样的事实,则它就是

第一个。又如语句 retract(student(20,-,-)). 将从内存的动态数据库中的删除事实 student(20,-,-) 它可解释为学号为 20 的一个学生的记录。

Page 81: 第二章 人工智能程序设计语言

2.4.5 动态数据库( 3 )

PROLOG提供的动态数据库机制,可非常方便地实现堆栈、队列等动态数据结构,提供的数据库操作谓词大大简化了编程。

另外, PROLOG还提供了谓词 save(<filename>).将当前的动态数据库 存入磁盘文件 consult(<filename>).将磁盘上的一个事 实数据文件调入内存。

Page 82: 第二章 人工智能程序设计语言

2.4.6 表处理与递归( 1 ) 表的描述

表是 PROLOG中一种重要的数据结构。 表的表达能力强,能表示序列、集合、数组、记录。

表的特点是长度不固定,运行中可动态变化。在程序运行中,可以对表实施一些操作。对表添加一个元素,或从中删除一个元素,将两个表合并为一个表。用表可以方便构造堆栈、队列、链表、树等动态结构。

表分表头和表尾两部分。

Page 83: 第二章 人工智能程序设计语言

2.4.6 表处理与递归( 2 )

表头是表中第一个元素,而表尾是表中除第一个元素外的其余元素按原来顺序组成的表。例如下面的例子:

表 表头 表尾[ 1,2,3,4,5] 1 [ 2,3,4,5][apple,orange,banana] apple [ orange,banana]

[[ a,b ] , [ c ] , [ d,e ]][ a,b ][[ c ] ,[ d,e]]

[ "PROLOG"] "PROLOG“ [] [] 无定义 无定义

Page 84: 第二章 人工智能程序设计语言

2.4.6 表处理与递归( 3 ) 程序中表的应用

在程序中是用竖线“ |” 来区分表头和表尾的,而且还可以使用变量。

例如一般地用[ H|T]来表示一个表,其中H 、 T都是变量, H 为表头, T为表尾。注意,此处 H 是一个元素(表中第一个元素),而T则是一个表(除第一个元素外的表中其余元素按原来顺序组成的表)。

Page 85: 第二章 人工智能程序设计语言

2.4.6 表处理与递归( 4 )用这种表示法通过匹配合一提取表头和表尾的例

子 表 1 表 2 合一后的变量值[ X|Y] [ a,b,c] X=a,Y=[ b,c][ X|Y] [ 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|Y,Z]就是错误的。但竖杠的前面的变量可以多于一个。

Page 86: 第二章 人工智能程序设计语言

2.4.6 表处理与递归( 5) 例如写法[ 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=c 。其中变量Z并非等于[ c]。

Page 87: 第二章 人工智能程序设计语言

2.4.6 表处理与递归( 6 )

例 2.5 设计一个能判断对象 X是表 L 的成员的程序。

我们可以这样设想: (1) 如果 X与表 L中的第一个元素(即表头)是同一个对象,则 X就是 L 的成员 ;

member(X,[ X|Tail] ). (2) 如果 X是 L 的尾部的成员,则 X也就是

L 的成员。 member(X,[ Head|Tail] ):-member(X,Tai

l).

Page 88: 第二章 人工智能程序设计语言

2.4.6 表处理与递归( 7)

例如,我们取表 L 为[ a,b,c,d],取 X为 a ,对上面的程序提出如下询问 :

Goal:member(a,[ a,b,c,d] ). 则有回答 :yes 同样对于询问 : Goal:member(b,[ a,b,c,d] ). Goal:member(c,[ a,b,c,d] ). Goal:member(d,[ a,b,c,d] ). 都有回答 :yes

Page 89: 第二章 人工智能程序设计语言

2.4.6 表处理与递归( 8 )

但若询问 Goal:member(e,[ a,b,c,d] ). 则回答 :no 如果我们这样询问 Goal:member(X,[ a,b,c,d] ). 意思是要证明存在这样的 X,它是该表的成员,这时系统返回 X的值,即

X=a 如果需要的话,系统还会给出 X的其他所有

值。

Page 90: 第二章 人工智能程序设计语言

2.4.6 表处理与递归( 9 )例 2.6 表的拼接程序,即把两个表连接成一个表。 append([] ,L,L). append([ H|T] ,L2,[ H|Tn] ):- append(T,L2,Tn). 可以看出,谓词 append是递归定义的,子句 append([] ,L,L). 为终结条件,即递归出口。

如果我们询问 Goal:append([ 1,2,3] ,[ 4,5] ,L). 则系统便三次递归调用程序中的第二个子句,最后从第一个子句终止,然后反向依次求出每次的拼接表,最后输出

L=[ 1,2,3,4,5]

Page 91: 第二章 人工智能程序设计语言

2.4.6 表处理与递归( 10 )当然,对于这个程序也可以给出其他各种询问,如:Goal: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,5]Goal:append(X,[ 4,5] ,[ 1,2,3,4,5] ). 系统回答 :X=[ 1,2,3]

Page 92: 第二章 人工智能程序设计语言

2.4.6 表处理与递归( 11 )

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]…

等等(如果需要所有解的话)。

Page 93: 第二章 人工智能程序设计语言

2.4.6 表处理与递归( 12 )

例 2.7 表的输出。 print([] ). print([ H|T] ):-write(H),print(T).例 2.8 表的倒置,即求一个表的逆序表。 reverse([] ,[] ). reverse([ H|T] ,L):- reverse(T,L1),append(L1,[ H] ,L).

这里, reverse 的第一个项是输入,即原表,第二个项是输出,即原表的倒置。

Page 94: 第二章 人工智能程序设计语言

2.4.7回溯控制( 1 )

PROLOG 在搜索目标解的过程中,具有回溯机制,即当某一个子目标 Gi 不能满足时,就返回到该子目标的前一个子目标 Gi-1 ,并放弃Gi-1 的当前约束值,使它重新匹配合一。在实际问题中,有时却不需要回溯,为此 PROLOG中就专门定义了一个阻止回溯的内部谓词——“ !” ,称为截断谓词。

Page 95: 第二章 人工智能程序设计语言

2.4.7回溯控制( 2 )

截断谓词 !的语义是: (1) 若将“ !”插在子句体内作为一个子目标,它总

是立即成功; (2) 若“ !”位于子句体的最后,则它就阻止对它所

在子句的头谓词的所有子句的回溯访问,而让回溯跳过该头谓词 (子目标 ),去访问前一个子目标(如果有的话);

(3) 若“ !”位于其他位置,则当其后发生回溯且回溯到“ !” 处时,就在此处失败,并且“ !”还使它所在子句的头谓词(子目标)整个失败(即阻止再去访问头谓词的其余子句(如果有的话),即迫使系统直接回溯到该头谓词 (子目标 )的前一个子目标 (如果有的话 ))。

Page 96: 第二章 人工智能程序设计语言

2.4.7回溯控制( 3 )例 2.9考虑下面的程序: 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′) 时,却无解。

Page 97: 第二章 人工智能程序设计语言

2.4.7回溯控制( 4 )例 2.10 设有程序: g0:-g11,g12,g13. (2─5) g0:-g14. (2─6) g12:-g21,!,g23. (2─7) g12:-g24,g25. (2─8) ......... 给出目标 :g0. 假设运行到子目标 g23 时失败,这时如果子句 (2─7) 中无 !的话,则会回溯到 g21 ,并且,如果 g21也失败的话,则会访问下面的子句 (2─8)。但由于有 !存在,所以不能回溯到 g21 ,而直接宣告 g12失败。于是,由子句 (2─5),这时则回溯到 g11 。

Page 98: 第二章 人工智能程序设计语言

2.4.7回溯控制( 5)如果我们把子句 (2─7)改为 g0:-g11,g12,g13. (2─5) g0:-g14. (2─6) g12: -g21, g23,!. (2─9) g12:-g24,g25. (2─8) ......... 当然这时若 g23失败时,便可回溯到 g21 ,而当

g21也失败时,便回溯到 g12 ,即子句 (2─8) 被“激活”。但对于修改后的程序,如果 g13失败,则虽然可回溯到 g12 ,但对 g12 不做任何事情,便立即跳过它,而回溯到 g11 ,如果子句 (2─9) 中无 !,则当 g13失败时,回溯到 g12 便去考虑子句 (2─8),只有当子句 (2─8)再失败时才回溯到 g11 。

Page 99: 第二章 人工智能程序设计语言

2.4.8 程序举例( 1 )

例 2.11 下面是一个简单的路径查询程序。程序中的事实描述了如图 2─2所示的有向图,规则是图中两节点间有通路的定义。

图 2─2 有向图

Page 100: 第二章 人工智能程序设计语言

2.4.8 程序举例( 2 )predicates road(symbol,symbol) path(symbol,symbol)clauses road(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).

Page 101: 第二章 人工智能程序设计语言

2.4.8 程序举例( 3 )

程序中未含目标,所以运行时需给出外部目标。例如当给目标:

path(a,e). 系统将回答 :yes 但当给目标 : path(e,a). 时,系统则回答: no 如果给出目标: run.

Page 102: 第二章 人工智能程序设计语言

2.4.8 程序举例( 4 )且在程序中增加子句 run:-path(a,X),write("X=",X),nl,fail. run.屏幕上将会输出 : X=b X=c X=d X=e X=d X=e X=e即从 a出发到其他节点的全部路径。

Page 103: 第二章 人工智能程序设计语言

2.4.8 程序举例( 5)例 2.12 下面是一个求阶乘程序,程序中使用了

递归。 /*aFactorialProgram*/ domains n,f=integer predicates factorial(n,f) goal readint (I), factorial(I,F), write(I,"!=",F).

Page 104: 第二章 人工智能程序设计语言

2.4.8 程序举例( 6 ) clauses factorial(1,1). factorial(N,Res):- N>0, N1=N-1, factorial(N1,FacN1), Res=N*FacN1. 程序运行时,从键盘输入一个整数,屏幕

上将显示其阶乘数。

Page 105: 第二章 人工智能程序设计语言

2.4.8 程序举例( 7)例 2.13 下面是一个表的排序程序,采用插入排序法。

/*insertsort*/ domains listi=integer* predicates insert-sort(listi , listi) insert(integer,listi,listi) asc-order(integer,integer) clauses insert-sort([] ,[] ).

Page 106: 第二章 人工智能程序设计语言

2.4.8 程序举例( 8 )insert-sort([ H|Tail] ,Sorted-list):- insert-sort(Tail,Sorted-Tail), insert(H,Sorted-Tail,Sorted-list).insert(X,[ Y|Sorted-list] ,[ Y|Sorted-list1] ):- asc-order(X,Y),!, insert(X,Sorted-list,Sorted-list1).insert(X,Sorted-list,[ X|Sorted-list] ).asc-order(X,Y):-X>Y.例如当给目标: insert-sort([ 5,3,4,2,6,1,7,8,9,0] ,L). 系统将输出 : L=[ 0,1,2,3,4,5,6,7,8,9]

Page 107: 第二章 人工智能程序设计语言

2.4.8 程序举例( 9 )例 2.14下面是一个简单的通信录管理程序,其中用到输入输出、动态数据库等。通过阅读这个程序,我们还可以掌握循环结构和简单的菜单程序编写方法。

/* 通信录 */ database person(string,integer) predicates address-book chose(integer) input

Page 108: 第二章 人工智能程序设计语言

2.4.8 程序举例( 10 )query repeatgoal address-book.clauses address-book:- repeat, clearwindow, write("=============="),nl,

Page 109: 第二章 人工智能程序设计语言

2.4.8 程序举例( 11 ) 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,!.

Page 110: 第二章 人工智能程序设计语言

2.4.8 程序举例( 12 )input:-clearwindow, write("姓名 :"),readln(Name), write("电话 :"),readint(Tel), assertz(person(Name,Tel)),!. query:-clearwindow, write("姓名 :"),readln(Name), person(Name,Tel), write("电话 :",Tel), readchar(-),!.repeat.repeat:-repeat.

Page 111: 第二章 人工智能程序设计语言

2.4.8 程序举例( 13 ) 程序中的 repeat恒成功。它与内部谓词 fa

il配合实现了循环。 需说明的是,这仅是一个演示性程序,还

不能实用。因为这里的通信录并未存入磁盘文件。用谓词 save 就可方便地把通信录存入磁盘文件。例如用语句

save("addrbook.dat") 就可把已插入内存的 person事实存入文

件 addrbook.dat中。而语句 consult("addrbook.dat") 则可又将该文件中的事实装入内存。