逻辑编程原理

通过一阶逻辑, 可定义一个子串(substr)的谓词, 该定义由以下的一组逻辑公式完成:

(1)∀xsubstr(x,x)

(2)∀x∀ysuffix(x,y⋅x)

(3)∀x∀yprefix(x,x⋅y)

(4)∀x∀y∀z(substr(x,y)∧suffix(y,z)→substr(x,z))

(5)∀x∀y∀z(substr(x,y)∧prefix(y,z)→substr(x,z))

将这组一阶逻辑公式转化为子句标准形:

(1)substr(x,x)

(2)suffix(x,y⋅x)

(3)prefix(x,x⋅y)

(4)substr(x,y)∧suffix(y,z)→substr(x,z)

(5)substr(x,y)∧prefix(y,z)→substr(x,z)

基于谓词substr的定义, 可以尝试求解这样的问题: 求满足substr(X,a⋅a⋅a⋅b⋅c⋅c)的x.

这里称substr(X,a⋅a⋅a⋅b⋅c⋅c)为目标(Goal). 求解该问题的思路是: 结合替换, 通过归结方法证否该目标的否命题。然后, 问题的解可通过相应的替换得到。

该目标的否命题是: ¬(∃Xsubstr(w,a⋅a⋅a⋅b⋅c⋅c))

即: ∀X¬substr(w,a⋅a⋅a⋅b⋅c⋅c)

接下来, 以子句标准形为基础进行归结。

(6)¬substr(X,a⋅a⋅a⋅b⋅c⋅c)

(7)¬substr(X,y1)∨ ¬suffix(y1,a⋅a⋅b⋅c⋅c)

6,4,{x←X,y←y1,z←a⋅a⋅b⋅c⋅c}

(8)¬substr(X,a⋅b⋅c⋅c)

7,2,{x←a⋅b⋅c⋅c,y←a,y1←a⋅b⋅c⋅c}

(9)¬substr(X,y2)∨ ¬suffix(y2,a⋅b⋅c⋅c)

8,5,{x←X,y←y2,z←a⋅b⋅c⋅c}

(10)¬substr(X,a⋅b⋅c)

9,3,{x←a⋅b⋅c,y←c,y2←a⋅b⋅c}

(11)◻

10,1,{x←X,X←a⋅b⋅c}

于是, 得到一个替换{X←a⋅b⋅c}, 正是这个替换使得目标的否不成立。也就是说替换{X←a⋅b⋅c}是满足目标substr(X,a⋅a⋅a⋅b⋅c⋅c)的一个解。

归结过程不是唯一的, 不同的归结过程可能带来不同的解。 事实上, 目标substr(X,a⋅a⋅a⋅b⋅c⋅c)也确实存在不同的解。

一个霍恩子句(Horn Clause)具有以下的标准形式:

A←B1,B2,⋯,Bn

霍恩子句等价于A∨¬B1∨¬B2∨¬⋯∨¬Bn.

左边的A是头部(Head), 右边¬Bi称为身子(Body).

一个事实(Fact)是退化的霍恩子句: A←.

一个数据库(Database)由若干个事实构成。

一个目标子句(Goal Clause)是另一种退化的霍恩子句: ←B1,B2,⋯,Bn.

在逻辑编程中, 一个程序子句(Program Clause)就是一个霍恩子句。

运行:

其中,数据库包括事实m1和f1-f3; s1-s2和p1是程序子句。

目标等价于¬sibling(sally,X), 而子句s1等价于sibling(X,Y)∨¬parent_child(Z,X)∨¬parent_child(Z,Y). 所以目标将与s1进行合一操作, 得到替换 {sally←X,X←Y}

对所有子句进行替换后, 继续进行下一步合一操作

⋯⋯

等归结完成后,可得到替换{X←mei}为所求的解。

不过,除了"mei"之外,也会得到平凡解"ting".

可通过修改sibling谓词的定义完善此程序。

在增加"\+ X=Y"后, 得到唯一解"mei".