跳转到内容

Prolog/将它们放在一起

来自维基教科书,开放世界中的开放书籍

本节旨在结合前几章的知识并对其进行回顾。Prolog 首先被更详细地解释,忠于其基本结构,然后展示一个小型程序,该程序结合了前几章的知识。

Prolog 程序由规则数据库组成。这些规则被加载到编译器中。然后用户可以在数据库上运行查询。编译器将尝试证明查询是正确的。

Prolog 中的一切都用逻辑来描述(Prolog 逻辑是经典谓词逻辑或一阶逻辑的变体)。从原子(最小的位)开始,这些是构成 Prolog 程序或查询的最重要的逻辑符号。

这些由一个或多个小写字母组成,以字母开头。常量不是由其他 Prolog 符号组成(它是一个原子),它在 Prolog 世界中除了它本身之外不代表任何东西。将原子视为 Prolog 世界中的对象是一个好方法。它们没有附加的含义。有效常量的示例

foo
cd_p0345
a
dirk

变量是容器。它们可以表示几乎任何 Prolog 结构,从常量到谓词。变量由一个或多个小写或大写字母组成,以大写字母开头。重要的是要注意,Prolog 中的变量与大多数编程语言中的变量功能不同。您不会为它们分配一个值然后使用它们,当您运行一个查询以尝试使查询为真时,Prolog 会为它们分配各种值。有效变量的示例

B
Parent
Result

谓词由一个函符(一个或多个小写字母,以字母开头)组成,后面可能跟着方括号之间的一些项,用逗号隔开。谓词根据其项为真或假。有效谓词的示例

childof(Child, Father)
predicate(dog(x), cat(Y))
architect(a_vandelay)
termless_predicate

函数的构建方式与谓词相同,但它不是假或真,它可以代表变量可以代表的任何东西。例如,函数 sqrt(A) 将返回 A 代表的任何数字的平方根。

原子句子

[编辑 | 编辑源代码]

原子句子是 Prolog 程序中最小的部分,可以取真或假。所有谓词都是原子句子。一些其他 Prolog 语句,例如统一 (=) 也是原子句子。原子句子的示例

childof(george_w_b, george_b)
A = tan(B, C) + D

句子(和连接词)

[编辑 | 编辑源代码]

句子是 Prolog 结构,可以取真或假。原子句子当然就是句子。其他句子(即非原子句子)由通过连接词连接在一起的原子句子组成。Prolog 中最重要的连接词是,(“和”连接词)。如果一个句子用逗号将两个原子句子连接起来,那么如果(且仅当)这两个原子句子都为真,则该句子为真。Prolog 中的大多数句子只是一些谓词,它们之间用逗号隔开,表示所有原子句子都必须为真,才能使该句子为真。注意:其他连接词虽然很重要,但将在后面介绍。 句子的示例。

childof(a, b), male(a), female(b)
A = B * 3, even(A)
dog(poochie), cat(scratchy), mouse(itchy)

规则是一种特殊的句子类型。它在左边有一个谓词,在右边有一个句子,用:-分隔。它以句号结束。句子是 Prolog 程序中的行。规则指出,如果句子为真,则谓词为真。如果规则中存在变量,则对于任何使句子为真的变量实例化,谓词都为真。没有句子在谓词之后(因此没有:-)的规则称为事实,并且被认为是真实的。Prolog 程序中的每个句子都是一个规则。

规则示例。

mother(A) :- has_child(A), female(A).
car(porsche).
equal(X, X).

项是任何代表对象的 Prolog 结构。常量和函数始终是项,变量可以代表项。

其他 Prolog 概念在词汇表中解释。

Prolog 编译器

[编辑 | 编辑源代码]

Prolog 编译器允许用户在规则数据库(Prolog 程序)上运行查询。查询是特殊的规则类型,在:-之前没有谓词。一旦输入查询,Prolog 将在给定数据库中的规则为真的情况下检查它是否为真。如果查询包含变量,Prolog 将尝试找到一个变量实例化,使查询为真。

这种变量实例化是基于统一过程。如果 Prolog 正在尝试验证查询:- a(X).并在数据库中遇到规则a(a).,它将把变量 X 与常量 a 统一起来。换句话说,它将把变量 X 实例化为值 a。由于 a(a) 为真,因此 Prolog 将返回 X = a 作为解决方案。统一采用两个谓词,并查看是否可以使用一个来实例化另一个的变量。以下两个谓词统一

p(A, y)
p(z, B)
unification: A = z, B = y

这些也是如此

q(A, [y,z,C])
q(x, B)
unification: A = x, B = [y,z,C]

但是,这些不会统一

q(A, A)
q(x, y)

这是因为 A 可以是 x 或 y,但不能同时是两者。另一方面,这些

q(A, B)
q(x, x)

将统一,因为两个不同的变量可以绑定到同一个常量。

如果 Prolog 正在尝试验证查询:- b(X).并在数据库中遇到规则b(A) :- c(A).它将把变量 X 统一到变量 A。这两个变量都没有被实例化(即,没有分配给它们值),但它们相互绑定,它们只能被实例化为相同的值。现在,Prolog 将c(A)添加到其查询列表中以进行验证。如果它在数据库中遇到规则c(c) :- d.,它将(临时)用 c 实例化 A,并尝试验证 d。如果 d 成功,Prolog 将返回X = c 作为原始查询的解决方案,如果 Prolog 无法在数据库中找到任何使 d 为真的内容,Prolog 将忘记这条规则,并尝试以其他方式使c(A) 为真。这就是所谓的回溯

示例程序

[编辑 | 编辑源代码]

以下程序检查一列数字的总和是否等于零

sum_is_zero(List) :- 
	sum(List, Sum),			% Sum is the sum of the List
	Sum = 0.			% Sum needs to be 0


sum([], 0).				% the sum of an empty list is always 0 (stop predicate)

sum([FirstNumber|Tail], Sum) :-		% The list is split into its first number and its tail
	sum(Tail, TailSum),		% TailSum is the sum of the tail
	Sum is FirstNumber + TailSum.	% Add the first number to that to get the Sum of the list.

程序中的第一个规则非常简单。它使用 sum 谓词对列表进行求和,并检查它是否等于零。后两个规则构成了 sum 谓词。第一个规则是停止谓词。它简单地说明空列表的和为 0。第二个规则首先将列表拆分为 FirstNumber(列表中的第一个数字,即“头部”)和 Tail(列表的其余部分)。它递归地计算尾部的和,并将第一个数字添加到尾部的和中。


一些查询

?- sum_is_zero([1, -1]).
Yes

?- sum_is_zero([1, 1, -2]).
Yes

?- sum([-1.5, 2.7849, 3.383724], A).
A = 4.66862 ;
No

?- sum([-1.5, 2.7849, 3.383724], 42).
No

(1)以下哪些谓词对可以统一?如果可以,请给出变量的实例化,如果不可以,请解释原因。

1 child_of(M, P)
  child_of(martha, doug)
2 dog(A)
  dog(B)
3 f(X, Y, e, Z)
  f(a, b, d, c)
4 r(D, F)
  r(p, c(martha, D))



上一篇:数学、函数和等式 下一篇:剪切和否定

华夏公益教科书