高效的分布式算法,用于将集合与公共元素合并

时间:2016-05-27 14:55:41

标签: algorithm scala merge distributed-computing apache-flink

我正在Flink上开发MinHash LSH的分布式实现,作为最后一步,我需要合并一些集群,这些集群被标识为类似的元素集。

所以我有一个分布式的集合集合作为输入,我需要一个算法来有效地将集合与公共元素合并。给定Flink的计算模型,该算法可以是迭代的,并且不一定像map-reduce那样。

这是一个例子:

来自{{1{1,2}},{2,{2,3}},{3,{4,5},{4{1,27}}}}

结果应该是{1,2,3,27},{4,5},因为集合#1,#2和#4至少有一个共同的元素。

3 个答案:

答案 0 :(得分:0)

只是一个想法,可能有更好的方法,但是如何:

  • 在地图步骤中,您为每个集合中的每个元素发出一个键值对,如:element -> other elements
  • 在缩减步骤中,您将收集其他元素并丢弃重复项
  • 重复直到数据结构停止更改

第一次迭代后,您的数据将如下所示:

1 -> 2, 27
2 -> 1,3
3 -> 2
4 -> 5
5 -> 4
27 -> 1

第二次之后:

1 -> 2, 3, 27
2 -> 1, 3, 27
3 -> 1, 2
4 -> 5
5 -> 4
27 -> 1, 2

最后在第三个之后:

1 -> 2, 3, 27
2 -> 1, 3, 27
3 -> 1, 2, 27
4 -> 5
5 -> 4
27 -> 1, 2, 3

我目前没有办法解决变更何时停止的问题。

要获得每个结果的一个副本,您可以删除密钥大于任何其他元素的所有内容。

答案 1 :(得分:0)

如果你有N个集合,每个元素大约有M个元素,那么天真的方式(每个集合中的每个元素都会相互测试)是O(N^2 * M^2),如果重复很少的话。但是,如果你实际上只有R << N*M个不同的元素,那就不那么糟糕了:你可以在找到某些东西后停止测试,这种情况发生在N*M比较后但仅R。 },所以你只有&#34;只有&#34; O(N*N*R)。但是,如果这些集合实际上只存在于L组中,则您不必对每个集合进行测试,因为一旦您点击了正确的组,您就会停止。所以它更像是O(N*L*R) + O(N*M)(第二项实际上是在找到要添加的正确组后将元素添加到组中。)

如果你从每个元素到它包含的集合列表制作一个地图 - 你可以在O(N*M)时间内完成 - 那么你可以遍历每个元素的集合树,访问每个不同的元素至多大约一次(即R个),并且每个访问每一组提到它(结果大约是N*M/R)并添加其所有元素(但只是一次!),如果您注意不要多次添加相同的设置,则整体时间为O(N*M)。 (你需要一套套装,这样你才可以判断你是否已经访问过它们。)这样会更快,但如果L*R非常小,你可能不在乎。

在Scala中,从元素到树的地图核心看起来像

case class W(s: Set[Int]) { var visited: Boolean = false }
def tree(ss: Seq[Set[Int]]) = {
  var m = new collection.mutable.HashMap[Int, List[W]]
  ss.foreach{ s =>
    s.foreach{i =>
      m(i) = W(s) :: m.getOrElse(i, Nil)
    }
  }
}

并且穿过群组会更复杂,但基本的想法是保留一张你已经看过的元素的地图,如果你碰到其中一个元素,就不要继续穿行,并且要跟踪你是否&#39 ;当您合并元素时,通过在W包装器中设置标志来遍历一个集合。

答案 2 :(得分:0)

这是一个想法:Gelly,它是Flink的一部分,有一个连接组件查找器。使用每个集合元素的节点和以最简单的方式连接每个集合的元素的边来制作图形,例如,对于{a,b,c,d,...},添加[a,b],[a,c],[a,d],[a,...现在找到连接的组件。他们的节点提供了您正在寻找的集合。

修改 如果你担心从集合转换为图形和返回的性能影响(尽管这种担心是过早的优化;你应该尝试一下),它可以很简单地重新实现Gelly的令牌推送方案。 。这是如何工作的。您的示例中已经有令牌:设置编号。设S [i]设置我在你的例子中显示。例如。 S [1] = {1,2}。设R是一个逆多图,它将每个集合元素带到它所属的集合集。例如。在你的例子中R [2] = {1,2}。设T [i]是可传递的非空交集&#34;链接&#34;从集合i可到达的元素。然后计算:

T[i] = S[i] for all i // with no links at all, a set reaches its own elements
loop
  for all i, Tnew[i] = \union_{ x \in T[i] } S[R[x]]  // add new reachables
  exit if Tnew == T
  T = Tnew
end loop

完成后,地图T的不同值就是您想要的答案。最大迭代次数应该是log | U |其中U是集合元素的宇宙。