Prolog LanguageProlog语言入门


备注

实现

  1. SWI-Prolog (免费)
  2. SICStus (商业)
  3. YAP (免费)
  4. GNU Prolog (免费)
  5. XSB (免费)
  6. B (商业)
  7. IF (商业)
  8. Ciao (免费)
  9. 密涅瓦 (商业)
  10. ECLiPSe-CLP (免费)
  11. Jekejeke Prolog (商业)
  12. Prolog IV
  13. 收益Prolog (免费)
  14. Visual Prolog (商业)

附加/ 3

append([], Bs, Bs).
append([A|As], Bs, [A|Cs]) :-
    append(As, Bs, Cs).
 

append/3 是最着名的Prolog关系之一。它定义了三个参数之间的关系, 如果第三个参数是一个表示第一个和第二个参数中指定的列表的串联的列表,则为true。

值得注意的是,正如良好的Prolog代码一样, append/3 可用于多个方向 :它可用于:

  • 附加两个完全或部分实例化的列表:

      ?- A = [1, 2, 3], B=[4, 5, 6], append(A, B, Y)
      Output:
      A = [1, 2, 3],
      B = [4, 5, 6],
      Y = [1, 2, 3, 4, 5, 6].
     
  • 检查三个完全实例化列表的关系是否为真:

      ?- A = [1, 2, 3], B = [4, 5], C = [1, 2, 3, 4, 5, 6], append(A, B, C)
      Output:
      false
     
  • 生成所有可能的方法将两个列表附加到给定列表:

      ?- append(A, B, [1, 2, 3, 4]).
      Output:
      A = [],
      B = [1, 2, 3, 4] ;
      A = [1],
      B = [2, 3, 4] ;
      A = [1, 2],
      B = [3, 4] ;
      A = [1, 2, 3],
      B = [4] ;
      A = [1, 2, 3, 4],
      B = [] ;
      false.
     

CLP(FD)约束

CLP(FD)约束由所有严肃的Prolog实现提供。它们允许我们以纯粹的方式推理整数

?- X #= 1 + 2.
X = 3.

?- 5 #= Y + 2.
Y = 3.
 

数据库编程

Prolog将所有内容归类为:

  • 原子 - 任何不以大写字母开头的字符序列。例如 - abokay
  • 数字 - 数字没有特殊语法,不需要声明。例如12235.8
  • 变量 - 以大写字符或下划线( _ )开头的字符串。例如XYAbcAA
  • 复杂术语 - 它们由仿函数和一系列参数组成 。复杂术语的名称始终是原子,而参数可以是原子或变量。例如father(john,doe)relative(a)mother(X,Y)

逻辑数据库包含一组事实规则

仅将原子作为参数的复杂术语称为事实,而将变量作为参数的复杂术语称为规则。

Prolog中的事实示例:

father_child(fred, susan).
mother_child(hillary, joe).
 

Prolog中的规则示例:

child_of(X,Y):-
    father_child(Y,X)
    ;
    mother_child(Y,X).
 

注意; 这里就像其他语言中的or 运算符。

Prolog是一种声明性语言,您可以按如下方式阅读此数据库:

弗雷德是苏珊的父亲

希拉里是乔的母亲。

对于所有的XYX 是一个孩子Y 如果Y 是孩子的父亲XY 是孩子的母亲X

实际上,一组有限的事实和/或规则构成了逻辑程序

通过查询来演示这种程序的使用。查询允许您从逻辑程序中检索信息。

要将数据库加载到解释器中(假设您已将数据库保存到正在运行解释器的目录中),只需输入:

?- [nameofdatabase].
 

用实际文件名替换nameofdatabase (请注意,这里我们将.pl 扩展名排除在文件名之外)。

上述程序的解释器中的查询示例和结果:

?- child_of(susan,fred).
true

?- child_of(joe,hillary).
true

?- child_of(fred,susan).
false

?- child_of(susan,hillary).
false

?- child_of(susan,X).
X = fred

?- child_of(X,Y).
X = susan,
Y = fred ;
X = joe,
Y = hillary.
 

上述查询及其答案可以解读如下:

苏珊是弗雷德的孩子吗? - 是的

乔是希拉里的孩子吗? - 是的

是一个苏珊的孩子? - 假

是苏珊是希拉里的孩子吗? - 假

谁是苏珊的孩子? - 弗雷德

这就是我们在Prolog中编程逻辑的方式。逻辑程序更正式:一组公理或规则,定义对象之间的关系(也就是谓词)。以更正式的逻辑方式解释上述数据库的另一种方法是:

关系father_child 在fred和susan之间持有

mother_child 关系在希拉里和乔之间

对于所有XY ,如果关系father_child 保持在YX 之间,或者关系mother_child 保持在YX 之间,则关系child_of 保持在XY 之间。

你好,世界

Hello,World in the interactive interpreter

打印“Hello,World!”在Prolog解释器中(这里我们使用swipl ,SWI Prolog的shell):

$ swipl
<...banner...>
?- write('Hello, World!'), nl.
 

?- 是系统提示符:它表示系统已准备好供用户输入必须以a终止的目标序列(即查询. (句号)。

这里的查询write('Hello World!'), nl 有两个目标:

  • write('Hello World!')'Hello World!' 必须显示,
  • 必须遵循新的一行( nl )。

write/1 /1 用于表示谓词采用一个参数)和nl/0 内置谓词 (该定义由Prolog系统预先提供)。内置谓词提供了纯Prolog定义无法获得的功能,或者使程序员无需定义它们。

输出:

你好,世界!

yes 结尾意味着查询已成功。在某些系统中,打印为true 而不是yes

你好,来自一个文件的世界

打开一个名为hello_world.pl 的新文件并插入以下文本:

:- initialization hello_world, halt.

hello_world :-
    write('Hello, World!'), nl.
 

initialization 指令指定在加载文件时应调用目标hello_world, halthalt 退出程序。

然后,您的Prolog可执行文件可以执行此文件。确切的标志取决于Prolog系统。如果您正在使用SWI Prolog:

$ swipl -q -l hello_world.pl 
 

这将产生输出Hello, World!-q 标志禁止在调用run swipl 时通常显示的横幅。 -l 指定要加载的文件。

安装或设置

SWI-Prolog的

Windows和Mac:

  • 官方网站上下载SWI-Prolog
  • 只需按照安装说明进行安装。

Linux(PPA):

  • 将PPA ppa:swi-prolog/stable 到系统的软件源中(开发人员可以选择ppa:swi-prolog/devel ):

    • 打开终端(Ctrl + Alt + T)并输入: sudo add-apt-repository ppa:swi-prolog/stable

    • 然后,更新包信息: sudo apt-get update

  • 现在通过包管理器安装SWI-Prolog: sudo apt-get install swi-prolog

  • 您现在可以使用命令swipl 通过命令行启动SWI-Prolog