跳转到内容

Prolog/规则

来自维基教科书,自由的教科书,为自由的世界

本节讨论规则,这是一种用于表示谓词何时为真的通用方法。

到目前为止,我们还没有真正进行任何编程,只是定义了对象及其属性。Prolog 编程的第一步是使用**规则**。通过规则,我们说明一个谓词为真,前提是其他谓词为真。规则看起来像这样

a :- b, c, d.

这意味着如果 b、c 和 d 为真,则 a 为真。如果我们有以下数据库,

a :- b, c, d.
b.
c.
d :- e.
e.

,如果我们询问 Prolog 是否 a 为真,

 ?- a.

Prolog 会将查询(或目标)a 生成**子目标** b、c 和 d。它可以直接看到 b 和 c 为真,因为它们被声明为事实,但 d 只有在 e 为真时才为真,这会导致另一个子目标 e。由于 e 也是一个事实,所以 Prolog 会回答 yes。

带变量的规则

[编辑 | 编辑源代码]

我们也可以使用包含项的谓词。

car(corvette) :- haswheels(corvette), haswindows(corvette).

说明一辆有轮子和窗户的 Corvette 是一辆汽车。这不是一个很有用的陈述,因为我们也可以简单地声明一辆 Corvette 是一辆汽车,用

car(corvette).

然而,我们可以在规则中使用变量。这样,我们可以例如声明,只要有轮子和窗户的东西都是一辆汽车

car(A) :- haswheels(A), haswindows(A).
haswheels(corvette).
haswindows(corvette).

第一行说明,为了使 car(A) 为真,haswheels(A) 和 haswindows(A) 必须为真。如果 Prolog 被问到一辆 Corvette 是否是一辆汽车

?- car(corvette).

它会将 A 绑定到 corvette,并得到子目标**haswheels(corvette)**和**haswindows(corvette)**。如果它能证明这两个目标都为真(它能),那么 car(corvette) 必须为真。在程序中使用变量时,重要的是要注意,变量在它所在的句子之外没有任何意义。如果两个句子使用变量 A,它不是同一个变量。例如

bird(A) :- hasfeathers(A).
dog(A) :- barks(A).

第一行中的 A 只是表明谓词 bird 的项需要与谓词 hasfeathers 的项相同,它与第二行中的 A 无关。

现在我们可以回到我们的原始程序并添加一些规则。

human(david).
human(john).
human(suzie).
human(eliza).
man(david).
man(john).
woman(suzie).
woman(eliza).
parent(david, john).
parent(john, eliza).
parent(suzie, eliza).

father(X,Y) :- parent(X,Y), man(X).
mother(X,Y) :- parent(X,Y), woman(X).

我们可以询问 Prolog Eliza 的父亲是谁

?- father(X, eliza).

X = john ;
No

或者列出数据库中的所有父亲及其各自的孩子

?- father(Father, Child).

Father = david
Child = john ;

Father = john
Child = eliza ;

No
?- mother(Mother,Child).

Mother = suzie
Child = eliza ;

No

如果你使用过任何其他编程语言,你可能熟悉递归,它指的是函数调用自身。Prolog 特别适合递归,尽管在我们的例子中,它将是一个谓词引用自身,而不是一个函数。转到下一节,看看它是如何以及为什么完成的。


华夏公益教科书