我们可以把简单的查询连接起来,组成一些较复杂的查询。例如,如果我们想知道厨房里能吃的东西,就可以向Prolog进行如下的询问。

?- location(X, kitchen), edible(X).

简单的查询只有一个目标,而混合查询可以把这些目标连接起来,从而进行较为复杂的查询。上面的连接符号','是并且的意思。

上面的式子用语言来描述就是“寻找满足条件的X,条件是:X在厨房里,并且X能吃。”如果某个变量在询问中多次出现,则此变量在所有出现的位置都必须绑定为相同的值。所以上面的查询只有找到某一个X的值,使得两个目标都成立时,才算查询成功。

每次查询所使用的变量都是局部的变量,它只在本查询中有意义,所以当我们进行了如下的查询后,

?- location(X, kitchen), edible(X).
X = apple ;
X = crackers ;
no

查询结果中没有broccoli(椰菜),因为我们没有把它定义为可吃的东西。此后,还可以用X进行其他的查询。

?- room(X).
X = kitchen ;
X = office ;
X = hall ;
...;
no

除了使用逻辑的方法理解混合查询外,还可以通过分析程序的运行步骤来理解。用程序的语言来说就是“首先找到一样位于厨房的东西,然后判断它能否食用,如果不能,就到厨房里找下一样东西,再判断能否食用。一直如此重复,直到找到答案或把厨房的东西全部查完为止。”

请参照下图来理解。

调用查询后,程序将按照下面的步骤运行,请参照上图来理解。

搜索第一个目标,如果成功转到2,如果失败则回答'no',查询结束。
搜索第二个目标,如果成功转到3,如果失败转到1。
把绑定的变量的值输出。用户输入';'后转到2。
上面的例子中只有一个变量,下面我们再来看一个有两个变量的例子。

?- door(kitchen, R), location(T,R).
R = office
T = desk ;

R = office
T = computer ;

R = cellar
T = 'washing machine' ;

no

上面的查询用逻辑的语言来解释就是:“找房间R,使得从厨房到房间R有门相连,并且把房间R中的物品T(这里是房间R的所有物品)也找出来。”

下面是此查询的单步运行过程。

Goal: door(kitchen, R), location(T,R)

1 CALL door(kitchen, R)
1 EXIT (2) door(kitchen, office)
2 CALL location(T, office)
2 EXIT (1) location(desk, office)
R = office
T = desk ;

2 REDO location(T, office)
2 EXIT (8) location(computer, office)
R = office
T = computer ;

2 REDO location(T, office)
2 FAIL location(T, office)
1 REDO door(kitchen, R)
1 EXIT (4) door(kitchen, cellar)
2 CALL location(T, cellar)
2 EXIT (4) location('washing machine', cellar)
R = cellar
T = 'washing machine' ;

2 REDO location(T, cellar)
2 FAIL location(T, cellar)
1 REDO door(kitchen, R)
1 FAIL door(kitchen, R)
no

内部谓词

讲了这么多了,我们还只是用到了Prolog的一些语法,完全没有使用Prolog提供的一些内部的函数,我把这些内部函数称为内部谓词。和其他的程序语言一样,Prolog也提供了一些基本的输入输出函数,下面我们要编写一个较复杂的查询,它能够找到所有厨房里能够吃的东西,并把它们列出来。而不是像以前那样需要人工输入';'。

要想完成上面的任务,我们首先必须了解内部谓词的概念。内部谓词是指已经在Prolog中事先定义好的谓词。在内存中的动态数据库中是没有内部谓词的子句的。当解释器遇到了内部谓词的目标,它就直接调用事先编好的程序。

内部谓词一般所完成的工作都是与逻辑程序无关的,例如输入输出的谓词。所以我们可以把这些谓词叫做非逻辑谓词。

但是这些谓词也可以作为Prolog的目标,所以它们也必须拥有和逻辑谓词相同的四个端口:Call、Fail、Redo和Exit。

下面介绍几个常用的输出谓词。

write/1
此谓词被调用时永远是成功的,并且它可以把它的参数作为字符串输出到屏幕上。当回溯时,它永远是失败,所以回溯是不会把已经写到屏幕上的字符又给删除的。

nl/0
此谓词没有参数,和write一样,从Call端口调用时总是成功的,从Redo端口回溯时总是失败的,它的作用是在屏幕上输出一个回车符。

tab/1
此谓词的参数是一个整数,它的作用是输出n个空格,n为它的参数。其控制流程与上面两个相同。

下图是一般情况下的Prolog目标的内部流程控制示意图。我们将使用此图和内部谓词的流程控制图相比较。

上图中左上角的菱形方块表示从Call端口进入目标时所进行的处理。它从某谓词的第一个子句开始搜索,如果匹配成功就到Exit端口,如果没有找到任何一个子句与目标匹配就转到Fail端口。

右下角的方块表示从Redo端口进入目标时所进行的处理,从最近一次成功的子句开始向下搜索,如果匹配成功就转到Exit端口,如果没有找个更多的子句满足目标就转到Fail端口。

I/O谓词的流程控制和上述的不同,它不会改变流程的方向,如果流程从它的左边进入,就会从它的右边流出;而如果从它的右边进入,则会从它的左边流出。请参考下图理解。

I/O谓词不会改变变量的值,但是它们可以把变量的值输出。

还有一个专门引起回溯的内部谓词fail/0,从它的名字不难看出,它的调用永远是失败的。如果fail/0从左边得到控制权,则它立即把控制权再传回到左边。它不会从右边得到控制,因为没法通过fail/0把控制权传到右侧。它的内部流程控制如下:

以前我们是靠使用';'来进入目标的Redo端口的,并且变量的值的输出是靠解释器完成的。现在有了上面几个内部谓词,我们就可以靠I/O谓词来显示变量的值,靠fail谓词来引起自动的回溯。

下面是此查询语句及其运行结果。

?- location(X, kitchen), write(X) ,nl, fail.
apple
broccoli
crackers
no

下面是此查询的流程图。

下面是此查询的单步调试过程。

Goal: location(X, kitchen), write(X), nl, fail.
1 CALL location(X, kitchen)
1 EXIT (2) location(apple, kitchen)
2 CALL write(apple)
apple
2 EXIT write(apple)
3 CALL nl

3 EXIT nl
4 CALL fail
4 FAIL fail
3 REDO nl
3 FAIL nl
2 REDO write(apple)
2 FAIL write(apple)
1 REDO location(X, kitchen)
1 EXIT (6) location(broccoli, kitchen)
2 CALL write(broccoli)
broccoli
2 EXIT write(broccoli)
3 CALL nl

3 EXIT nl
4 CALL fail
4 FAIL fail
3 REDO nl
3 FAIL nl
2 REDO write(broccoli)
2 FAIL write(broccoli)
1 REDO location(X, kitchen)
1 EXIT (7) location(crackers, kitchen)
2 CALL write(crackers) crackers
2 EXIT write(crackers)
3 CALL nl

3 EXIT nl
4 CALL fail
4 FAIL fail
3 REDO nl
3 FAIL nl
2 REDO write(crackers)
2 FAIL write(crackers)
1 REDO location(X, kitchen)
1 FAIL location(X, kitchen)
no

下面请你分析一下,

?- door(kitchen, R), write(R), nl, location(T,R), tab(3), write(T), nl, fail.

的输出的结果是什么呢?

Prolog教程 5相关推荐

  1. Atitit.5gl 第五代语言编程语言 PROLOG教程  人工智能语言的标准 与实现

    Atitit.5gl 第五代语言编程语言 PROLOG教程  人工智能语言的标准 与实现 1. 第五代语言就是自然语言又被称为知识库语言或人工智能语言,1 2. 人工智能语言特点2 2.1. 试探法2 ...

  2. Prolog教程 16

      Prolog特别适合开发自然语言的应用系统.在这一章,我们将为寻找Nani游戏添加自然语言理解的部分.(由于Prolog谓词是使用的英文符号,所以这里的自然语言理解只能局限在英文中) 在着手于编制 ...

  3. Prolog教程 1

    (转)Prolog教程 1 今天是2019年1月1日, 因为AI课要用到Prolog, 看到不错的入门教程收录下来学习. 如果你是一位prolog的新手,希望你首先阅读这篇文章,好对prolog的全局 ...

  4. Prolog教程 3

    facts, predicate, pred(arg1,arg2,-argN). argument type: interger, atom( low case begin, ' '), variab ...

  5. Prolog教程 14--cut的功能

    cut,使用符号!来表示. 直到目前为止,我们都一直在使用Prolog内建的回溯功能.使用此功能可以方便地写出结构紧凑的谓词来. 但是,并不是所有的回溯都是必须的,这时我们需要能够人工地控制回溯过程. ...

  6. Prolog教程 4

      现在我们的游戏中已经有了一些事实,使用Prolog的解释器调入此程序后,我们就可以对这些事实进行查询了.本章和下一章中的Prolog程序只包括事实,我们要学会如何对这些事实进行查询. Prolog ...

  7. Prolog教程 7

      到现在为止,我们已经对Prolog有了一个基本的了解,现在有必要对我们所学过的知识做一个系统的总结. Prolog的程序是由一系列的事实和规则组成的数据库. 规则之间的调用是通过联合操作完成的,P ...

  8. Prolog教程 9

    Prolog的程序就是谓词的数据库,我们通常把这些谓词的子句写入Prolog的程序中的.在运行Prolog时,解释器首先把所有的子句调入到内存中.所以这些写在程序中的子句都是固定不变的.那么有没有办法 ...

  9. Prolog教程 10

    到目前为止,所介绍的事实.查询以及规则都使用的是最简单的数据结构.谓词的参数都是原子或者整数,这些都是Prolog的基本组成元素.例如我们所使用过的原子有: office, apple flashli ...

最新文章

  1. 网页设计千千万,网站建设万万千
  2. windows和linux下的spice客户端使用方法
  3. 西单大悦城苹果店4s_“神秘列车”复活!金融街-西单,3号免费专线今天回归...
  4. 【深度学习系列】——深度学习简介
  5. yolov5-detect.py解析与重写
  6. leetcode python3 简单题119. Pascal's Triangle II
  7. FreeSwitch通过远程接口验证用户登录
  8. java cas单点登录_JAVA - 登录 单点登录 cas
  9. 人声歌姬语音合成器+11个歌手音源-Yamaha Vocaloid 5.2.1 + Libraries WiN
  10. 联创机房管理系统服务器密码,高校机房管理系统解决方案.doc
  11. 第五周:Raptor:三色球问题
  12. Spark:Container exited with a non-zero exit code 137
  13. QCustomPlot系列(2)-绘制两条曲线+自动全显+鼠标拖放+rescaleAxes()函数简介
  14. ssh 提示Connection closed by * 的解决方案
  15. C语言——函数的一些基本概念
  16. flowable中BPM实现核心对象
  17. java.lang.IllegalArgumentException: Illegal pattern character 'Y' 解决办法
  18. 休闲零食加盟店项目该如何选择品牌?
  19. 华三NS228交换机虚拟局域网划分方法
  20. Jlink v9虚拟串口功能,不用再单独购买串口线了

热门文章

  1. 九月最热门的25个开源项目
  2. 天然气管道折弯测量与失效分析
  3. ROS编译时ps3joy出错
  4. 第三方依赖库中kotlin代码提示/*compiled code*/
  5. Dangling meta character '+' near index 0 + 报错 解决方法
  6. Microsoft Office 2013下载
  7. 快速搭建迷你云 mini cloud storage
  8. 金蝶迷你版云服务器没有响应,连接云服务器异常金蝶迷你版
  9. Android下发送和接收OBD数据
  10. 差分时钟信号的使用与引脚绑定(ucf)