我们正在使用以下知识库:
house_elf(dobby).
witch(hermione).
witch('McGonagall').
witch(rita_skeeter).
magic(X):- house_elf(X).
magic(X):- wizard(X).
magic(X):- witch(X).
演习的问题是:
满足以下哪些查询?在相关的情况下,提供导致成功的所有变量实例化。
我被困在问题5上:
?- magic(Hermione).
还画出查询魔法(赫敏)的搜索树。
虽然我了解查询发生了什么,但我对如何绘制查询搜索树感到困惑。此外,在我们的查询中(赫敏)是一个变量这一事实也会导致更多的混乱?
你能介意指导我并解释当这个查询被提议给Prolog时发生了什么吗?
谢谢
原子与变量
以大写字母开头的字符串(如 Hermione
)是一个变量。如果它以小写字母开头,如hermione
,它是一个原子(像其他语言一样将其视为"常量")。或者如果它是单引号,比如'Hermione'
,它也是一个原子。
以下是事实:
witch(hermione).
可以读作: hermione
是一个witch
.它如何真正被阅读(或者更具体地说,它的语义是什么)取决于你,程序员。
如果我在Prolog提示符下查询此事实,它将成功:
| ?- witch(hermione).
yes
(注意,这是gprolog
,所以它产生yes
。我认为SWI Prolog会说true
,但它们都意味着"成功"。
我也可以使用变量进行查询,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).
从语义上讲,你可以这样理解, 如果X
是house_elf
,X
是magic
,或者如果X
是wizard
,X
是magic
,或者X
是magic
如果X
是一个witch
。
如果我们随后查询:
| ?- magic(Hermione).
Prolog将尝试找出哪些实例化Hermione
将使它成功,并告诉你这些值是什么。在你的所有事实和谓词中,它会在子句magic(X):- house_elf(X).
找到第一个匹配项,使用 Hermione
作为变量代替 X
,它会发现如果Hermione = dobby
,那么house_elf(Hermione)
将为真,因此,magic(Hermione)
将为真。它将显示作为第一个解决方案: Hermione = dobby
:
| ?- magic(Hermione).
Hermione = dobby ? ;
通过在此处按;
(或空格),Prolog将尝试找到下一个解决方案,在这种情况下,它不会找到下一个成功,直到它进入下一个子句,magic(X):- wizard(X).
。假设你有一些事实wizard/1
,它将在这些方面取得成功。如果wizard/1
没有在您的事实或谓词中定义,那么您将从 Prolog 收到一个存在错误,指出它不知道wizard/1
什么。Prolog将继续浏览你的谓词子句,寻找使其成功的方法,并告诉您Hermione
的什么值(实例化)会使其成功,直到它用尽所有情况。然后它最终会停止。
我将把它作为一个练习来找出搜索树,但在"Prolog搜索树"上进行谷歌搜索以找到一些很好的例子。我假设你有Prolog解释器,您可以在其中输入代码并使用查询以查看会发生什么。您可以启用跟踪(输入trace.
)以查看有关Prolog对查询执行的操作的一些详细信息。所有这些方法都可以帮助理解Prolog操作的某些方面。