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 正在尝试验证查询:- 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))