如何从传递成对关系中有效地构建依赖图?

How to efficiently construct a dependency graph from a transitive pairwise relation?

我正在处理的代码生成问题需要以下算法。我目前的算法是 O(n^2),但我觉得有更好的方法。

假设我有一个谓词函数来计算是否 x < y。

less?: (x:T, y:T) -> True|False

我先验地知道这种关系是可传递的。这样,

less?(a, b) and less?(b, c)

暗示

less?(a, c)

我想计算一组对象 (x1, ..., xn) 的依赖图。它应该看起来像:

x1 => (x2, x4, x5)
x2 => (x3)
x5 => (x7)
x10 => ()
etc...

其中每个节点 xi 与 xj 的列表相关联,使得 less?(xj, xi) 为真。计算此图的最简单方法是调用 less?在所有可能的 (xi, xj) 对上。但是越少?关系很昂贵,我想尽量减少对 less 的调用?

感谢您的帮助。

-帕特里克

如果 < 关系足够昂贵,您可以通过维护一个矩阵来存储关于 a 与 b 的当前知识状态。我们可以有 a < b, !(a < b), 或未知。然后,当您计算 a 与 b 的比较时,将其存储在矩阵中,并为每个结果未知的可能 c 寻找关于 a 与 c 和 b 与 c 的推论。你也有a < b => !(b < a)吗?

例如a vs b 和 b vs c 只有有限数量的可能性来检查兼容性和不兼容性以查看推导的可能性,但显然 a < b 和 b < c => a < c。因此我们也有 a < b 和 !(a < c) => !(b < c)。也许如果你写出所有的可能性,你会发现更多。

我倾向于慢慢增长已知值的平方,以随机顺序逐个添加新变量,因此在第 i 阶段,您知道第 i 个随机选择变量的矩阵的全部内容。当您添加每个新变量时,我会以随机顺序将其与已经处理过的变量进行比较。你正在使每一个推论成为可能。如果有一个非常聪明的变量比较顺序,您可能希望使用随机比较顺序它会足够接近最佳顺序,这样您就不会比它低效很多。

在最坏的情况下,我对此表示怀疑。如果你从来没有找到任何 a, b 的 a < b,我认为你必须检查每一种可能性。