检测和删除最少数量的不一致事实的算法(可能在 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 -- b
或 b -- z
,就足以断开两条“不一致”路径(删除剩余语句之间的所有不一致)。
此外,很明显,没有其他单个边缘的移除足以实现这一点。
【讨论】:
以上是关于检测和删除最少数量的不一致事实的算法(可能在 PROLOG 中)?的主要内容,如果未能解决你的问题,请参考以下文章
在计算 220 % 25 的余数为 20 而 420 % 25 的余数为 19 时计算余数的不一致? [复制]