检测和删除最少数量的不一致事实的算法(可能在 PROLOG 中)?

Posted

技术标签:

【中文标题】检测和删除最少数量的不一致事实的算法(可能在 PROLOG 中)?【英文标题】:Algorithm to detect and remove least number of inconsistent facts (probably in PROLOG)? 【发布时间】:2014-11-07 19:53:28 【问题描述】:

你如何编写以下算法?

想象一下这样的“事实”列表,其中字母代表绑定到数值的变量:

x = 1
y = 2
z = 3
a = 1
b = 2
c = 3
a = x
b = z
c = z

这些“事实”显然不一定都是“真实的”:b=z 而 b=2 和 z=3 是不可能的。如果 b=z 或 b=2 被删除,所有事实都将是一致的。如果 z=3 并且 b=z 或 c=z 被删除,那么所有事实都将是一致的,但会比上面少一个事实。该集合包含许多这样的一致子集。例如,a=1、b=2、c=3 是一致的子集,许多其他子集也是如此。

在此示例中,两个一致子集比任何其他一致子集都大:

x = 1
y = 2
z = 3
a = 1
b = 2
c = 3
a = x
c = z

x = 1
y = 2
z = 3
a = 1
c = 3
a = x
b = z
c = z

使用适当的编程语言(我在想 PROLOG,但也许我错了)你将如何处理包含一致和不一致事实的大集合,然后输出最大可能的一致事实子集(或多个子集如上例)?

【问题讨论】:

您是否有明确的策略来偏好一个事实而不是另一个事实?您(在您的特定应用中)是否有“证据”的概念,是否存在具有不同证据来源的事实? 【参考方案1】:

这与 NP-hard 多路切割问题密切相关。在(未加权)多路切割问题中,我们有一个无向图和一组 terminal 顶点。目标是尽可能少地删除边,以便每个终端顶点位于其自己的连接组件中。

对于这个问题,我们可以将每个变量和每个常数解释为一个顶点,将每个等式解释为从其左侧到右侧的一条边。终端顶点是与常量相关联的顶点。

对于只有两个终端,多路割问题是多项式时间可解的 s-t 最小割问题。我们可以使用最小割来获得多路割问题的多项式时间 2 逼近,方法是找到分隔两个终端的最便宜割,删除所涉及的边,然后在剩余的连接组件上递归。多路割的理论文献中提出了几种具有较好比值的逼近算法。

实际上,多路切割出现在计算机视觉应用中,所以我希望在获得精确解决方案方面有一些工作。不过,我不知道那里有什么。

【讨论】:

感谢您的 cmets。我的应用程序是数据清理(在“脏”数据集中找到最可能的正确值)。在选择此作为最佳答案之前,我会等待给其他人一个机会。【参考方案2】:

Prolog 可以作为一种方便的实现语言,但对算法的一些思考表明,一种专门的方法可能是有利的。

在这些类型的陈述中(两个变量之间或一个变量和一个常数之间的相等性),唯一可能出现的不一致是连接两个不同常数的路径。

因此,如果我们找到连接不同常数对的所有“不一致”路径,则有必要且足够找到断开所有这些路径的一组边(原始等式)。

这里很容易认为贪心算法是最优的:总是选择一条边来删除,这条边对​​于剩余的“不一致”路径数量最多。因此我建议:

1) 找出所有连接两个不同常量的简单路径P(不经过任何第三个常量),并在这些路径及其边缘之间构造一个链接结构。

2) 计算边缘E 出现在那些“不一致”路径P 上的频率。

3) 通过采用贪心策略找到足够数量的边来删除,删除最常出现的下一条边并相应地更新剩余路径中的边数。

4) 考虑到需要移除边的上限(以保留一致的语句子集),应用回溯策略来确定是否有更少量的边就足够了。


正如应用于问题中的示例,证明恰好有两个“不一致”路径:

    2 -- b -- z -- 3
 2 -- b -- z -- c -- 3

删除两条路径共有的两条边中的任何一条,2 -- bb -- z,就足以断开两条“不一致”路径(删除剩余语句之间的所有不一致)。

此外,很明显,没有其他单个边缘的移除足以实现这一点。

【讨论】:

以上是关于检测和删除最少数量的不一致事实的算法(可能在 PROLOG 中)?的主要内容,如果未能解决你的问题,请参考以下文章

在计算 220 % 25 的余数为 20 而 420 % 25 的余数为 19 时计算余数的不一致? [复制]

厂商开过来的增值税发票中的货物和数量与所下订单的不一致,这样可以吗?

贪心算法:用最少数量的箭引爆气球

贪心算法2无重叠区间(中等)

一致 Hash 算法分析

leetcode 452 用最少数量的箭引爆气球 贪心算法