Prolog 真的基于封闭世界假设吗?
Is Prolog really based on the closed-world assumption?
what is not currently known to be true, is false
Prolog 的语义通常被认为遵循封闭世界假设,例如,here:
Prolog is based on closed world assumption (CWA) -- that is, if a proposition is not in the fact database and not derivable from the fact database, then it is not true.
但是,它的行为并不完全如此。在 CWA 下,我希望
?- a.
false.
但是,在 SWI-Prolog 中,我得到:
?- a.
ERROR: Undefined procedure: a/0 (DWIM could not correct goal)
这是为什么?说Prolog基于CWA是不是错了?
您的查询必须使用语言本身,因为 a
是命题 a/0
必须使用语言,即定义为谓词。语言中的所有无效谓词都是命题。如果不先将新术语添加到语言中,则不能将其作为谓词进行查询。
对于 a/1
,当您将它定义为 a(b).
它在语言中时,查询 a(X), dif(X,b)
将失败,因为 prolog 系统不知道任何其他满足条件的术语它并假设没有其他世界。
在 Prolog 上下文中讨论封闭世界假设 (CWA) 时,必须区分 unknown 谓词与 known[=49] 谓词=] 到(运行时)系统。在这两种情况下,谓词都有或没有子句。
默认情况下,调用 unknown 谓词会引发谓词存在错误。有一个标准标志,unknown
(https://www.swi-prolog.org/pldoc/man?section=flags#flag:unknown),其默认值为 error
,可以设置为 fail
(或 warning
)。这将为您提供您显然正在寻找的行为。不过,我强烈建议您将标志设置为默认值 error
,因为它可以更容易地检测编程错误(例如谓词名称或元数中的拼写错误)。
什么使谓词 为运行时所知?谓词指令或谓词子句。最熟悉的例子是 dynamic/1
指令。如果您的代码仅包含以下文本:
:- dynamic(foo/1).
那么,编译加载后,可以得到:
?- foo(_).
no.
但其他指令具有相同的效果(例如 multifile/1
和 discontiguous/1
,假设这是符合标准的 Prolog 实现!)。
因此,对于 known 谓词,CWA 在 Prolog 中的解释很简单:我们无法证明为真的东西就是假的。 IE。 失败否定,与逻辑否定非相同。 Prolog 这个名字来自 programming in logic 但 Prolog 也旨在成为一种实用的编程语言。
Prolog 中缺少的内容(由 Logtalk) is being able to declare a predicate without being forced to declare it as dynamic, or multifile, or ... or requiring providing clauses for it (see e.g. this example 等提供)。这提供了更简单和更清晰的 CWA 语义:调用没有子句的已声明谓词失败(不需要弄乱有问题的 unknown
标志);调用未声明的谓词会引发谓词存在错误。
希望这对您有所帮助。搜索 negation as failure 应该会提供进一步的说明。
what is not currently known to be true, is false
Prolog 的语义通常被认为遵循封闭世界假设,例如,here:
Prolog is based on closed world assumption (CWA) -- that is, if a proposition is not in the fact database and not derivable from the fact database, then it is not true.
但是,它的行为并不完全如此。在 CWA 下,我希望
?- a.
false.
但是,在 SWI-Prolog 中,我得到:
?- a.
ERROR: Undefined procedure: a/0 (DWIM could not correct goal)
这是为什么?说Prolog基于CWA是不是错了?
您的查询必须使用语言本身,因为 a
是命题 a/0
必须使用语言,即定义为谓词。语言中的所有无效谓词都是命题。如果不先将新术语添加到语言中,则不能将其作为谓词进行查询。
对于 a/1
,当您将它定义为 a(b).
它在语言中时,查询 a(X), dif(X,b)
将失败,因为 prolog 系统不知道任何其他满足条件的术语它并假设没有其他世界。
在 Prolog 上下文中讨论封闭世界假设 (CWA) 时,必须区分 unknown 谓词与 known[=49] 谓词=] 到(运行时)系统。在这两种情况下,谓词都有或没有子句。
默认情况下,调用 unknown 谓词会引发谓词存在错误。有一个标准标志,unknown
(https://www.swi-prolog.org/pldoc/man?section=flags#flag:unknown),其默认值为 error
,可以设置为 fail
(或 warning
)。这将为您提供您显然正在寻找的行为。不过,我强烈建议您将标志设置为默认值 error
,因为它可以更容易地检测编程错误(例如谓词名称或元数中的拼写错误)。
什么使谓词 为运行时所知?谓词指令或谓词子句。最熟悉的例子是 dynamic/1
指令。如果您的代码仅包含以下文本:
:- dynamic(foo/1).
那么,编译加载后,可以得到:
?- foo(_).
no.
但其他指令具有相同的效果(例如 multifile/1
和 discontiguous/1
,假设这是符合标准的 Prolog 实现!)。
因此,对于 known 谓词,CWA 在 Prolog 中的解释很简单:我们无法证明为真的东西就是假的。 IE。 失败否定,与逻辑否定非相同。 Prolog 这个名字来自 programming in logic 但 Prolog 也旨在成为一种实用的编程语言。
Prolog 中缺少的内容(由 Logtalk) is being able to declare a predicate without being forced to declare it as dynamic, or multifile, or ... or requiring providing clauses for it (see e.g. this example 等提供)。这提供了更简单和更清晰的 CWA 语义:调用没有子句的已声明谓词失败(不需要弄乱有问题的 unknown
标志);调用未声明的谓词会引发谓词存在错误。
希望这对您有所帮助。搜索 negation as failure 应该会提供进一步的说明。