【问题标题】:Reporting *why* a query failed in Prolog in a systematic way以系统的方式在 Prolog 中报告 *为什么* 查询失败
【发布时间】:2020-08-24 05:06:06
【问题描述】:

我正在寻找 Prolog 中的一种方法、模式或内置功能,我可以使用它来返回为什么一组谓词失败,至少就数据库中的谓词而言担心。当用户在系统中提出查询时,我试图说的不仅仅是“那是错误的”。

例如,假设我有两个谓词。如果某物是蓝色的,blue/1 为真,如果某物是狗,dog/1 为真:

blue(X) :- ...
dog(X) :- ...

如果我向 Prolog 提出以下查询并且 foo 是一只狗,但不是蓝色,Prolog 通常只会返回“false”:

? blue(foo), dog(foo)
false.

我想要找出为什么谓词的连接不正确,即使它是带外调用,例如:

? getReasonForFailure(X)
X = not(blue(foo))

如果谓词必须以某种方式编写,我可以,我只是在寻找人们使用过的任何方法。

到目前为止,我已经取得了一些成功的方法是通过以程式化的方式编写谓词并使用一些辅助谓词来找出事后的原因。例如:

blue(X) :-
    recordFailureReason(not(blue(X))),
    isBlue(X).

然后实现 recordFailureReason/1 以便它始终记住发生在堆栈最深处的“原因”。如果查询失败,则无论发生最深的失败都被记录为失败的“最佳”原因。这种启发式方法在许多情况下都非常有效,但确实需要仔细构建谓词才能正常工作。

有什么想法吗?如果有为这种分析设计的谓词逻辑系统,我愿意在 Prolog 之外寻找。

【问题讨论】:

  • 这听起来有点像en.wikipedia.org/wiki/Halting_problem
  • 只为所有谓词添加默认子句,当谓词失败时应该达到默认谓词并报告谓词失败。完成此操作后,您的下一个问题将是 How do I get the path Prolog took to get to the failed predicate?。如果您继续沿着这条滑坡走下去,您会发现自己正在创建一个调试器,然后您会希望它美观且图形化。因此,使用 SWI-Prolog 可以省去麻烦并使用gtrace

标签: prolog first-order-logic


【解决方案1】:

一些想法:

逻辑程序为什么会失败:“为什么”的答案当然是“因为没有满足Prolog程序给定的约束的变量赋值” .

这显然是无益的,但“蓝狗”的情况正是如此:没有这样的东西(至少在你建模的问题中)。

事实上,蓝狗问题唯一可接受的答案是在系统进入完全定理证明模式并输出时获得:

blue(X) <=> ~dog(X)

或者只是

dog(X) => ~blue(X)

或者只是

blue(X) => ~dog(X)

取决于假设。 “没有蓝狗的证据”。这是真的,因为这就是程序所说的。所以这个问题中的“为什么”是要求重写程序......

可能没有一个好的答案:“为什么没有 x 使得 x² 是不适定的并且可能有作为答案”只是因为“”因为您将自己限制在实数中”“因为等式中的 0 是错误的” ...所以这取决于非常喜欢。

要使“为什么”更有帮助,您必须以某种方式限定这个“为什么”。这可以通过构建程序和扩展查询来完成,这样在证明树构建期间收集的额外信息就会冒泡,但您必须事先决定哪些信息是:

query(Sought, [Info1, Info2, Info3])

而且这个查询总是会成功(对于query/2,“成功”不再意味着“成功找到建模问题的解决方案”而是“成功完成计算”),

变量Sought 将是您想要回答的实际查询的具体答案,即原子truefalse 之一(如果您已经受够了二值逻辑,可能还有unknown)和如果SoughtfalseInfo1, Info2, Info3 将提供更多详细信息,以帮助您回答为什么会发生某事

请注意,很多时候,询问“为什么”的愿望归结为两种不同的失败之间的混淆:“未能找到建模问题的解决方案”和“未能完成计算”。例如,您想将maplist/3 应用于两个列表并期望它可以工作,但错误地这两个列表的长度不同:您将得到false - 但它将是来自计算的false(在这种情况下,由于错误),而不是建模中的false。对assertion/1 采取严厉措施可能会有所帮助,但这本身就是丑陋的。

事实上,与没有逻辑编程部分的命令式或函数式语言相比:如果发生故障(可能是异常?),相应的“为什么”会是什么?不清楚。

附录

这是一个很好的问题,但我越想它,我就越认为它只能以特定于任务的方式来回答:你必须将你的逻辑程序构造为why-able,你必须决定why 应该返回什么样的信息。它是特定于任务的:关于缺失信息的东西,“如果只有这个或那个是真的”指示,其中“这个或那个”是从一组专用谓词中选择的。这当然是意料之中的,因为也没有通用方法可以让命令式或函数式程序解释其结果(或缺乏)。

我查了一下这方面的论文(包括 IEEE Xplore 和 ACM 库),刚刚发现:

肯定还有更多。

【讨论】:

  • 显然是一个很难“回答”的问题。感谢您对您发现的一些伟大的研究和对方法的想法的指点。这至少给了我一些继续关注的好途径。
【解决方案2】:

只要您保持在 Prolog 的纯单调子集内,您就可以将 概括 视为解释。以您为例,根据您对blue/1dog/1 的精确定义,可能会想到以下概括。

?- blue(foo), * dog(foo)。 错误的。

在这个概括中,整个目标dog(foo) 被删除。前缀* 实际上是一个像:- op(950, fy, *). *(_). 这样定义的谓词 非正式地,上面可以理解为:不仅这个查询失败,甚至这个通用查询也失败了。根本没有蓝色的 foo(前提是没有)。 但也许有 有一个蓝色的 foo,但根本没有蓝色的狗……

?- 蓝色(_X/*foo*/),狗(_X/*foo*/)。 错误的。

现在我们通过用新变量_X 替换foo 来概括程序。通过这种方式,两个目标之间的共享得以保留。

还有更多这样的概括,比如引入dif/2

这种技术既可以手动应用,也可以自动应用。如需更多信息,请联系collection of example sessions。另见Declarative program development in Prolog with GUPU

【讨论】:

  • 在阅读了您的示例会话和(一些)GUPU 文档后,这些似乎是很好的调试最佳实践!感谢您单独分享。我得到了切片的想法以及如何将其应用于特定谓词以确定什么“应该是真的”以使其成为真的并报告它。看起来,如果自动应用,报告的错误可能与谓词连词的一部分有关,这对运行程序的(非程序员)人类没有太大意义。也许在谓词上添加一些额外的标签可以解决这个问题。我去看看谢谢!
  • @EricZinda:“附加标签”如何改进您示例中的解释?
  • 我认为在上面的示例中不会,但在实际代码中,有更复杂的谓词,其中仅报告单个术语的结合失败不会给人类足够的信息真正了解发生了什么。在这些情况下,我可以添加一些额外的元数据,上面写着:“如果这些 X 项中的任何一个连词失败,则对人类来说意味着 Y”。这基本上就是我在当前解决方案中所做的。这有帮助吗?
  • 你举了一个不完整的例子。你需要给出一个完整的例子。
猜你喜欢
  • 1970-01-01
  • 2015-11-15
  • 2023-03-23
  • 2021-08-22
  • 1970-01-01
  • 2021-04-10
  • 1970-01-01
  • 1970-01-01
  • 2017-09-11
相关资源
最近更新 更多