绘制查询搜索树时感到困惑?

Confusion whilst drawing query search tree?

我们正在使用以下知识库:

house_elf(dobby).

witch(hermione).
witch('McGonagall').
witch(rita_skeeter).

magic(X):- house_elf(X).
magic(X):- wizard(X).
magic(X):- witch(X).

练习题是:

Which of the following queries are satisfied? Where relevant, give all the variable instantiations that lead to success.

我卡在问题 5 上了:

?- magic(Hermione).

Also draw the search tree for the query magic(Hermione) .

虽然我明白查询发生了什么,但我对如何绘制查询搜索树感到困惑。此外,在我们的查询中 (Hermione) 是一个变量的事实也导致了更多的混淆?

当这个查询被提交给 Prolog 时,你能否介意指导我并解释发生了什么?

谢谢

原子与变量

以大写字母开头的字符串,如Hermione,是一个变量。如果它以小写字母开头,如 hermione,则它是一个原子(将其视为 "constant",就像在其他语言中一样)。或者如果它在单引号中,如 'Hermione',它也是一个原子。

以下是事实:

witch(hermione).

可以读作:hermione是一个witch。如何真正阅读它(或者更具体地说,它的语义是什么)取决于你,程序员。

如果我在 Prolog 提示符下查询这个事实,它将成功:

| ?- witch(hermione).

yes

(注意,这是 gprolog,所以它产生 yes。我认为 SWI Prolog 会说 true,但它们都表示 "success"。)

我也可以使用变量进行查询,Prolog 会告诉您变量的哪些实例化(设置)将使它为真:

| ?- witch(Hermione).

Hermione = hermione ? ;

Hermione = 'McGonagall' ? ;

Hermione = rita_skeeter

(1 ms) yes

记住:Hermione是一个变量,hermione是一个原子。它们不是同一件事。因此变量 Hermione 可以具有上述任何一个值以使 witch(Hermione) 为真。您也可以查询 witch(Fred) 并使用 Fred 而不是 Hermione 获得与上面相同的结果。

基本谓词逻辑

现在让我们看一下谓词,magic/1(这里的1表示arity,或者参数magic有多少个) :

magic(X):- house_elf(X).
magic(X):- wizard(X).
magic(X):- witch(X).

从语义上讲,您可以将其理解为,如果 Xhouse_elf,则 Xmagic,或者 Xmagic 如果 Xwizard,或者 Xmagic 如果 Xwitch

如果我们再查询:

| ?- magic(Hermione).

Prolog 将尝试找出 Hermione 的哪些实例化会使其成功并告诉您这些值是什么。在您所有的事实和谓词中,它会在子句 magic(X):- house_elf(X). 处找到第一个匹配项,使用 Hermione 作为变量代替 X,它会发现如果 Hermione = dobby,则 house_elf(Hermione) 将为真,因此 magic(Hermione) 将为真。它将显示第一个解决方案:Hermione = dobby:

| ?- magic(Hermione).

Hermione = dobby ? ;

通过在此处按;(或SPACE),Prolog 将尝试找到下一个解决方案,在这种情况下直到进入下一个子句才会找到下一个成功, magic(X):- wizard(X).。假设您有 wizard/1 的一些事实,它将在这些方面取得成功。如果 wizard/1 没有在你的事实或谓词中定义,那么你会从 Prolog 得到一个存在性错误,指出它不知道 wizard/1 是什么。 Prolog 将继续遍历您的谓词子句,寻找使其成功的方法,并告诉您 Hermione 的什么值(实例化)将使它成功,直到它用尽所有情况。然后它终于停止了。

我将把它留作计算搜索树的练习,但在 "Prolog search tree" 上进行 Google 搜索以找到一些 good examples。我假设您有 Prolog 解释器,您可以在其中输入代码并进行查询以查看会发生什么。您可以启用跟踪(输入 trace.)以查看有关 Prolog 对查询所做的操作的一些详细信息。所有这些方法都可以帮助理解 Prolog 操作的某些方面。