核心连通组件算法

时间:2016-07-29 13:47:30

标签: algorithm graph space-complexity

对于无向图,我有4,000,000,000(40亿)个边。它们在大型文本文件中表示为节点ID对。我想计算此图的连接组件。不幸的是,一旦你将带有边缘的节点ID加载到内存中,这就需要超过128GB的RAM。

是否有一种用于查找相对简单的连接组件的核心算法?或者甚至更好,它可以与Unix命令工具和现有(python)库拼凑在一起吗?

2 个答案:

答案 0 :(得分:4)

根据您提供的问题的描述以及您在评论中提供的答案,我认为最简单的方法可能是使用类似@dreamzor描述的方法。这是一个更加充实的答案版本。

基本思想是将数据转换为适合内存的更压缩格式,对该数据运行常规连接组件算法,然后对其进行解压缩。请注意,如果为每个节点分配一个32位数字ID,则存储所有节点所需的总空间最多为40亿个节点和80亿个边缘的空间(假设您存储了每个边缘的两个副本),这是空间容量为120亿32位整数,只有大约48GB的空间,低于你的内存阈值。

首先,编写一个读取边缘文件的脚本,为每个节点分配一个数字ID(可能按照它们出现的顺序依次)。让此脚本将此映射写入文件,然后编写一个新的边文件,该文件使用节点的数字ID而不是字符串名称。完成后,您将拥有一个名称文件,将ID映射到名称和边缘文件,占用的空间比以前少得多。您在评论中提到可以将所有节点名称放入内存中,因此这一步应该非常合理。请注意,您不需要将所有边缘存储在内存中 - 您可以通过程序对它们进行流式处理 - 这样就不会成为瓶颈。

接下来,编写一个程序,将边缘文件(而不是名称文件)读入内存,并使用任何合理的算法找到连接的组件(BFS或DFS在这里会很棒)。如果你小心你的记忆(使用C或C ++之类的东西,这将是一个很好的调用),这应该适合主存储器。完成后,按数字ID将所有群集写入外部文件。您现在按ID列出了所有CC。

最后,编写一个程序,从名称文件读入ID到节点映射,然后在集群ID中流,并将每个集群中所有节点的名称写出到最终文件。

这种方法实现起来应该相对简单,因为关键的想法是保留您已经习惯的现有算法,只需将图表的表示更改为更高的内存效率。在过去处理大型图表(维基百科)之前,我曾经使用过这样的方法,并且即使在内存少于你的系统上也能很好地工作。

答案 1 :(得分:1)

您只能将一个顶点数组作为"颜色" (一个int值),然后在没有加载整个链接集的情况下运行文件,用一种颜色标记顶点,如果两个顶点都没有颜色则标记一个新颜色,如果一个颜色是彩色而另一个颜色是相同的颜色,两种颜色中最低的一种,再加上重新绘制阵列中用最高颜色绘制的所有其他顶点(如果两者都是彩色的)。伪代码示例:

int nextColor=1;
int merges=0;
int[] vertices;
while (!file.eof()) {
    link=file.readLink();
    c1=vertices[link.a];
    c2=vertices[link.b];
    if ((c1==0)&&(c2==0)) {
        vertices[link.a]=nextColor;
        vertices[link.b]=nextColor;
        nextColor++;
    } else if ((c1!=0)&&(c2!=0)) {
        // both colored, merge
        for (i=vertices.length-1;i>=0;i--) if (vertices[i]==c2) vertices[i]=c1;
        merges++;
    } else if (c1==0) vertices[link.a]=c2; // only c1 is 0
    else vertices[link.b]=c1; // only c2 is 0
}

如果您选择小于32位的类型来存储顶点的颜色,您可能需要首先检查nextColor是否最大化,是否使用未使用的颜色数组(在合并中释放),并跳过如果不能使用任何颜色,则着色一组新的两个顶点,如果两种颜色都被使用并且发生任何合并,则重新运行文件读取过程。

更新:由于顶点实际上并不是字符串而是字符串,因此在解析该文件时,还应该有一个string到int的映射。如果你的字符串受到长度的限制,你可以将它们全部作为哈希表放入内存中,但是我通过创建另一个包含所有字符串的文件来预处理文件" s1"替换为" 1"," s2"使用" 2"等,其中" s1"," s2"是什么名称在文件中显示为顶点,以便将数据压缩为一对int的列表。如果您以后要处理类似的数据(也就是说,您的图表不会发生太大变化,并且包含大致相同的顶点名称,请使用名称中的链接存储"元数据"文件以便进一步简化预处理。