庄周梦蝶

生活、程序、未来
   :: 首页 ::  ::  :: 聚合  :: 管理

Logic Programming With Prolog学习笔记(一)

Posted on 2008-05-28 23:05 dennis 阅读(4028) 评论(0)  编辑  收藏 所属分类: 动态语言
第一章:Getting start

1hello world

write(“Hello World”),nl,write(“Welcome to Prolog”),nl.

.号做结束,有一系列目标(goal)组成(一般也称为查询query),目标之间用,号隔开,这里的writenl其实是内建的IO谓词,总共4个目标按顺序执行,nl是开始一个新行,所有目标达成,Prolog系统会输出yes

2halt也是BIPs,用于结束Prolog系统,statistics用于系统统计(cpu、内存等)。BIPs都是会产生副作用的谓词。比如write就是会产生输出到用户屏幕副作用的IO谓词。

3、第一个程序,写入下列代码并保存为prog1.pl:

dog(fido).

cat(felix).

animal:-dog(X).

通过consult谓词,将该程序导入数据库(本质上,Prolog系统就是一个全局数据库), 分析下代码:

dog(fido).

cat(felix).

就是所谓事实(fact),dogcat就是谓词,而fidofelixatom,这里陈述了两个事实:fido是一只狗,felix是一只猫。animal:-dog(X). 这句就是规则(rule),:-符号可以理解为如果(注:if)X是变量,这里描述的规则就是:如果X是狗,那么X就是动物。因此,依据事实和规则,Prolog的推理系统可以推论:fido是狗,所以fido是动物:

| ?- animal(fido).

yes

显然,根据animal规则,felix不是动物,虽然它是:

| ?- animal(felix).

no

4Prolog的注释 /* this is a comment */

5、查询,dog(X),查询所有满足谓词dogX,也就是找出所有的狗狗。

dog(X),cat(X).查询所有是狗又是猫的“东西”。Listing(dog),列出所有定义了谓词dog的语句。


6Prolog的数据类型:

1)数字,Number623,+3,-.245

2)Atom,所有的不包括数值在内的常量,这与Erlang中的atom概念是一脉相承

包括:以小写字母开头的字母、数字、下划线的组合,单引号括起来的字符序列,+-*/<>=@&#特殊字符组成的序列

3)变量:在查询中代表未决的term,以大写字母或者下划线开头,跟Erlang一样,_表示哑元

4)组合Term,类似其他语言中的记录结构,以一个atom开头,后接一个参数列表,参数也都是term,参数的个数就是它的arityErlang也是如此),例如:

read(X)

dog(henry)

likes(dog(henry),Y)

5)列表,如:

[dog,cat,mypred,[a,b,c],hello]

6)其他类型,某些 Prolog方言可能会有字符串类型,用于处理字符串。

第二章 语句和谓词

  1. 一个Prolog程序就是由一系列语句(clause)组成的,语句可以多行,以引文句号结束。两种基础语句:事实和规则。

  2. 事实语句,是由atom或者组合term构成(两者统称为call terms),如:

chrismas.

likes(john,mary).

  1. 规则,形式如下:

head:-t1,t2,…,tk. (k>=1)

head成为规则的头部,也必须是call term:-称为颈部操作符,读作if,而t1,t2…tk就是语句的body,它们描述了头部的结论所需要满足的条件。Body是由一个或者多个componet组成,compont就是目标,以逗号隔开,逗号表示and的关系。从另一个角度看,head可以成为目标,body是它的子目标,规则就是为了达到目标head,必须先达到子目标t1,t2…tk

例子:

large_animal(X):-animal(X),large(X).

go:-write(‘hello world’),nl.

  1. 谓词,所有语句的头部都包括了一个谓词定义,不同参数的同名谓词是不同的谓词,参数数目就是所谓元数(arity)。谓词可以记录为pred/n,比如parent/1,表示谓词名为parent,而参数个数是一个,这个与Erlang相同。谓词可分为用户自定义的维持和built-in谓词(BIPs)。IO谓词如write,nl就是BIPs,它们都是总会成功的谓词,并带来相应的IO副作用(输出和换行)。用户不能重定义BIPs

  2. 谓词的递归定义,分为直接和间接递归,例子:

likes(john,X):-likes(X,Y),dog(Y). 描述的规则为:john喜欢的是那种至少喜欢一只狗的人。

  1. loading语句,包括两个BIPsconsult/1reconsult/1,用于产生将文件中的语句导入数据库的副作用,两者的区别是,reconsult会覆盖之前定义的相同谓词,而consult不会。consult[‘prog1.pl’]可以简化为[‘prog1.pl’].同样,reconslt[‘prog1.pl’]可以简写为[-‘prog1.pl’]

  2. 变量,一开始所有的变量都是未绑定的,当目标被执行时,变量可能被绑定或者解绑定。变量存在作用域,不同语句中的同名变量没有任何关系。

  3. 量词,

1)全称量词,出现在事实或者规则head部分的变量,表示事实或者规则的该变量的所有可能值,这样的变量成为全称量词,如

large_animal(X):-animal(X),large(X). 中的X

2)存在量词,不在事实或者规则的head部分中存在,但是在body部分中出现的量词,仅仅为了表示该变量至少存在一个值,这样的变量称为存在量词。例如:

person(dennis,zane,male,25,programmer).

man(A):-person(A,B,male,C,D).

man谓词body部分的B,C,D变量就是存在量词


9.匿名变量,就是所谓哑元,下划线_表示,表示你并不care这个变量的值是什么,仅仅为了占位,用以表示任意值,与Erlang中的意义一致。


第三章

1、这一章主要将描述Prolog系统是如何满足目标的执行。

2Prolog系统是按照顺序执行目标的,每个目标都是由call term组成,每个目标都与一个相应的谓词相关联,谓词的名称称为functor,而参数个数就是元数(arity)。Prolog系统是从上到下,依据语句的head部分来匹配目标,如果匹配,将输出yes,否则就是no。对于用户定义的目标,Prolog没有找到任何事实或者规则与之匹配的话,那么就是fail。这不是什么未知或者不确定,这个其实就是所谓的封闭世界假设(closed world assumption):任何结论如果无法从数据库中的事实和规则中得到证明,那么这个结论就是否定的,没有什么系统不确定或者未知这样的中间位置。

3Prolog的匹配算法——联合(unification),

变量可以跟任何term联合,其中包括了变量,其实就是变量的绑定。例如:

X=1X1联合. dog(X)dog(ferris),将Xferris联合。

call terms的联合过程:


1)如果两个call term都是atom,只有当它们是一样的时候才可以联合,比如:

testtest联合成功

dennis跟'dennis'联合成功

applefuck联合失败

2)对于组合call term的联合,要求两个call term有一样的functorarity,并且参数也要成对地联合成功。

联合的详细规则如下:

1)两个atom当且仅当它们是一样的时候才是联合成功的。

2)两个组合的term联合成功,当且仅当两者有一样的functorairty,并且参数也要从左到右两两成对地联合成功。

3)两个number联合成功,当且仅当它们是一样的时候,例如77联合成功,而76.9就失败

4)两个未绑定的变量总是联合成功的,两者互相绑定

5)一个未绑定变量和一个不是变量的term也总是联合成功的,将变量绑定为该term

6)一个绑定的变量可以被认为它所绑定的值。例如

pred(X,X,man)

pred(landon,dog,A)联合失败,因为在第一个参数联合成功后,X就被认为是landon,那么在尝试联合第二个参数的时候,显然landondog联合失败。

7)两个列表联合成功,当且仅当它们拥有相同数目的元素,并且元素间从左到右成对地联合成功。

8)嵌套结构按照这些规则递归,其他情况下的联合都是失败的。


4、目标的求值,两张图描述:


5、回溯(backtracking),回溯就是一个返回前一个满足的目标,寻找其他方式重新满足该目标的过程。回溯,顾名思义就是退回去,再来过,当输入;号,就强制Prolog系统回溯以寻找更多的匹配

6、目标求值的概览:



第四章 操作符

1、通过op谓词,可以将用户自定义的谓词转成某种操作符,例如:

likes(dennis,catty).

我们更希望表达成:

dennis likes catty.

这在默认情况是不行的,通过op谓词转化likes谓词成中缀操作符:

op(150,xfy,likes).

然后就可以这样使用likes谓词了:

dennis likes catty.


op谓词一般形式

op(操作符优先级,(xfy|xf|fy),谓词名称)

2、算术运算:通过内建的is/2谓词来进行算术运算,is/2是一个内建的中缀运算符,例如:

X is 2.

X is 3,Y is X+3.

出现在第二个参数的变量必须是已经绑定。+ - * /称为算术运算符,还有一类称为算术函数,它们并不是谓词,例如abs/1 sqrt/1等,完整列表:

+ - * /

X//Y 两个整数的商

X^Y 表示XY次方,在gnu prolog上是**,与ruby一样。

-X 一元操作符

abs(X)

sqrt(X)

sin(X)

cos(X)

max(X,Y)


is/2的第一个参数也可以是表达式或者数字,在此情况下,两个参数都会被计算,如果相等,则succeeds,否则失败。因此is/2谓词也可以解释为,求值看两个参数是否可以联合成功。如果第一个参数是变量,就将第二个参数的值绑定在该变量上,如果第一个参数是数值或者算术表达式,就比较两个参数的值是否相等,相等则联合成功,如果第一个参数是atom,term.list等,联合的情况依赖于实现。永远失败的is/2:

X is X+1.总是失败。


操作符的优先级与算术中的一样,可以通过括号强制优先级。


算术比较操作符:=:=,=\=,>,>=,<,=<


3、等价操作符:

1)算术表达式比较:

E1=:=E2 成功当且仅当两个表达式求值的结果一致。

E1=\=E2 成功当且仅当两个表达式求值的结果不一致。

2Term相同比较:

Term1==Term2成功当且仅当Trem1Term2完全相同。

因此:

likes(X,prolog)==likes(X,prolog)相同

likes(Y,prolog)==likes(Y,prolog)失败,XY是不同的变量

3+7==6+4 失败,两个表达式不会被求值,显然不同

Term1 \==Term2成功当且仅当Trem1Term2不同。


3Term联合的比较:

=操作符与==类似,不同在于,Term1=Term2当且仅当Term1Term2联合成功的时候成功,也就是能找到某种方式绑定变量的值,来让两者相同。例如

6+X=6+3。成功,X绑定为3

6+4=3+7 仍然失败

X=0,X=:=0. 成功,将X绑定为0,算术比较成功。

=的相反操作符就是\=


4、逻辑操作符:取反操作符not,表示or;

例如:

X=0,not X is 0. 返回no

6<3;7 is 2+5.返回yes


只有注册用户登录后才能发表评论。


网站导航: