问题描述
我正在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之外看看。
解决方法
一些想法:
逻辑程序为什么失败:“ 为什么” 的答案当然是“,因为没有变量分配可以满足Prolog程序给出的约束”
这显然是无济于事的,但“蓝狗”确实是这样:没有这样的东西(至少在您建模的问题中如此)。
实际上,当系统进入完全定理证明模式并输出以下信息时,就可以得出蓝狗问题的唯一可接受答案:
blue(X) <=> ~dog(X)
或者也许只是
dog(X) => ~blue(X)
或者也许只是
blue(X) => ~dog(X)
取决于假设。 “没有蓝狗的证据”。的确如此,因为程序就是如此。因此,这个问题的“原因”是要求重写程序...
可能不是一个很好的答案:“为什么没有x使得x²作为答案”只是因为“ 或”因为您将自己限制在实数之内” 或“因为等式中的0只是错误的” ...所以这取决于非常。
要使“ 为什么”更有用,您必须以某种方式限定此“为什么” 。可以通过构造程序并扩展查询来完成,以便在构建证明树期间收集更多信息,但是您必须事先确定以下信息:
query(Sought,[Info1,Info2,Info3])
此查询将始终成功(对于query/2
,“成功”不再表示“成功找到了建模问题的解决方案”,而是“成功完成了计算”)
变量Sought
将是您要回答的实际查询的确切答案,即原子true
或false
(如果已经有unknown
之一)足够具有二值逻辑)和Info1,Info3
,这些细节将帮助您回答为什么有些东西,以防Sought
为false
。
请注意,在很多时候,询问“为什么”的愿望归结为两个不同的失败之间的混淆:“未能找到建模问题的解决方案”和“完成计算失败”。例如,您想将maplist/3
应用于两个列表,并希望它能正常工作,但是错误地两个列表的长度不同:您将得到false
-但这将是false
计算(在这种情况下,由于错误),而不是建模中的false
。对assertion/1
施加压力可能会有所帮助,但这以其自己的方式很难看。
实际上,与没有逻辑编程部分的命令或功能语言进行比较:如果发生故障(可能是例外?),对应的“为什么”是什么?尚不清楚。
附录
这是一个很好的问题,但是我对它的思考越多,我认为它只能以一种特定于任务的方式回答:您必须将逻辑程序构造为why
才能运行,并且您必须确定why
应该实际返回哪种信息。 将是特定于任务的:有关丢失信息的信息,“仅当此为真”指示,其中“此或那”是从谓词组中选择的。这当然是意料之中的,因为也没有通用的方法来使命令式程序或功能性程序解释其结果(或缺乏结果)。
我已经寻找了一些有关此方面的论文(包括IEEE Xplore和ACM库),并且刚刚发现:
- Reasoning about Explanations for Negative Query Answers in DL-Lite,实际上是用于描述逻辑,并使用abductive reasoning。
- WhyNot: Debugging Failed Queries in Large Knowledge Bases讨论了Cyc的工具。
- 我还随机查看了Flora-2的文档,但他们基本上似乎是在说“使用调试器”。但是调试只是调试,不是解释。
必须有更多。
,只要您停留在Prolog的纯单调子集中,就可以将归纳化作为说明。以您的示例为例,根据您对blue/1
和dog/1
的精确定义,可以考虑以下概括。
?- blue(foo),*dog(foo). false.
在这种概括中,整个目标dog(foo)
被删除。前缀*
实际上是一个谓词,类似于:- op(950,fy,*). *(_).
非正式地,以上内容可以理解为:不仅此查询失败,而且该通用查询也失败。
?- blue(_X/*foo*/),dog(_X/*foo*/). false.
现在,我们通过将foo
替换为新变量_X
来推广程序。这样,两个目标之间的共享得以保留。
还有更多这样的概括,例如引入dif/2
。
可以手动和自动应用此技术。有关更多信息,请参见collection of example sessions。另请参见Declarative program development in Prolog with GUPU