- 1、本文档共4页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
prolog递归
递归
递归的确是一种功能强大的编程算法,现在绝大部分的程序语言都支持函数的递归调用,Prolog也不例外,而且如果没有递归,Prolog就不能叫做Prolog了。
在Prolog中,当某个谓词的目标中包含了此谓词本身时,Prolog将进行递归调用。
正如前面所述的,某一规则被调用时,Prolog使用新的变量为此规则的body部分建立新的查询。由于每次的查询都是独立的,所以某一规则调用其自身与调用其他规则没有任何区别。
任何语言中的递归定义都包括两个部分:边界条件与递归部分。
边界条件定义最简单的情况。而递归部分,则首先解决一部分问题,然后再调用其自身来解决剩下的部分,每一次都将进行边界检测,如果剩下的部分已经是边界条件中所定义的情况时,那么递归就圆满成功了。
下面我们将定义一个能够检测某物体在其他物体中的谓词,这里将使用到递归。
以前所定义的location/2谓词,表述了手电筒(flashlight)在桌子(desk)里,而桌子在办公室(office)中。但是那时Prolog并不能判断手电筒是否在办公室中。
?- location(flashlight, office). no
如果使用递归,我们就可以很轻松地写出谓词is_contained_in/2,它能够跟踪物体的所在的位置,因此它能判断手电筒是否在办公室中。
为了让问题更加有趣一些,我们再加入一些物品,它们的位置是一层一层地嵌套的。
location(envelope, desk). location(stamp, envelope).location(key, envelope).
要想列出办公室中的所有物品,我们首先可以列出直接位于办公室的物品,例如桌子;然后,再列出桌子中的物品,再桌子中的物品中的物品......
如果把房间也看作一个物品的话,我们就可以很容易地写出具有两个部分的规则,它能够判断某物品是否在另一个物品中的。
如果物品T1直接位于物品T2中,则物品T1在物品T2中。(此为边界条件)
如果某一物品X直接位于T2中,而物品T1在物品X中(此处为递归调用),则物品T1在物品T2中。
用Prolog的语言来表达,上面的第一句可以写成,
is_contained_in(T1,T2) :- location(T1,T2).
而第二句则是,
is_contained_in(T1,T2) :- location(X,T2), is_contained_in(T1,X).
上面的递归很直接,请注意它是如何调用其自身的。
下面是此谓词的运行实例,
?- is_contained_in(X, office). X = desk ; X = computer ; X = flashlight ; X = envelope ; X = stamp ; X = key ; no
?- is_contained_in(envelope, office).yes
?- is_contained_in(apple, office).no
递归的工作原理
规则中所定义的变量都是局部的。这意味着每次调用某一规则时,Prolog都将为此次调用新建一个独立的变量集。因此递归第一层的变量X、T1、T2,与第二层的变量X、T1、T2的变量名虽然相同,但是它们的值却是不同的。
我们可以使用带标号的变量或者Prolog的内部变量来区分这些局部变量。一开始,查询的目标是,
?- is_contained_in(XQ, office).
第一层递归的子句是:(在此使用带标号的变量来区分不同的递归级别,此处,T11表示是T1在第一层递归中的变量)
is_contained_in(T11, T21) :- location(X1, T21), is_contained_in(T11, X1).
当查询的目标与此子句匹配时,变量的绑定情况如下:
XQ = _01 T11 = _01 T21 = office X1 = _02
注意,查询目标中的变量XQ与T11同时绑定为_01,因此,一旦_01的值找到了,则XQ和T11的值也就同时找到了。
使用这些绑定后的变量,可以重写上面的子句,
is_contained_in(_01, office) :-location(_02, office), is_contained_in(_01, _02).
当locatio/2目标成功后,变量_02绑定为desk,即_02=desk,那么后面的递归调用就变成了,
is_contained_in(_01, desk)
这个新的目标将与is_contained_in/2的子句匹配,此时Prolog为本次匹配重新分配变量,,此时所有产生的变量如下,
XQ = _01
文档评论(0)