`

Logic Programming With Prolog学习笔记(一)

阅读更多

第一章:Getting start

1 hello world

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

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

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

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

dog(fido).

cat(felix).

animal:-dog(X).

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

dog(fido).

cat(felix).

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

| ?- animal(fido).

yes

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

| ?- animal(felix).

no

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

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

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


6 Prolog的数据类型:

1)数字 ,Number 623,+3,-.245

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

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

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

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

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语句,包括两个 BIPs consult/1 reconsult/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系统是如何满足目标的执行。

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

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

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

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

call terms的联合过程:


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

test test联合成功

dennis跟' dennis'联合成功

apple fuck联合失败

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

联合的详细规则如下:

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

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

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

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

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

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

pred(X,X,man)

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

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 表示 X Y次方,在 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 成功当且仅当两个表达式求值的结果不一致。

2 Term相同比较:

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

因此:

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

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

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

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


3 Term联合的比较:

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

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics