首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在C中将edgelist转换为压缩稀疏行

在C中将edgelist转换为压缩稀疏行
EN

Stack Overflow用户
提问于 2012-10-19 07:58:46
回答 2查看 1.8K关注 0票数 1

我有一个包含数百万条边的无向边列表。10x10稀疏邻接矩阵的无向边列表的简化示例:

代码语言:javascript
复制
0 2
0 9
2 8
6 9

我想把边缘列表转换成压缩稀疏行(定义)格式。这意味着读取边缘列表并将其写入三个数组: Value (在我的示例中总是"1“)、Column_Index和Row_Pointer。

从示例边列表中读取,我可以轻松地重构第0行:它在第2和第9列中有一个"1“。然后,第一行没有非零项。

问题

对于第二行,因为边是无向的,所以我应该在第0和第8列中有一个"1“,但是列表中没有”2.0“项。我想这个信息已经被编码在"0 2“条目中了。

我可以读取部分构造的压缩稀疏行数组,以查看“2.0”条目是否存在,但对于包含数百万条目的大型edgelist来说,这是行不通的。

问题

我该怎么解决这个问题?还是我的做法错了?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-10-19 09:12:49

您可以扫描边缘列表,交换索引,这样对于每个(i, j)i < j总是正确的。这是你在O(N)中做的。

您还需要一个排序的边缘列表,这是O(N log )。一旦您有排序的边缘列表,您可以存储它的对称-CSR格式。读取单元格(y,x)时,如果y > x,则交换yx。然后读取row_pointer[y]row_pointer[y+1],让它们是PaPb,并开始扫描PaPb之间的i;退出if x >= CSR[i] (找到与否取决于if =或>),或者如果i == Pb (未找到)。

您还可以在其中生成第二个边缘列表,并对其进行排序。此时,您可以同时扫描两个边,并生成不需要对称的CSR列表。

代码语言:javascript
复制
j0 = j1 = N+1
# i-th row:
    # we are scanning NodesIJ[ij] and NodesJI[ji].
    If NodesIJ[ij][0] == i
        j0 = NodesIJ[ij][1]
    If NodesJI[ji][0] == i
        j1 = NodesIJ[ji][1]
    if (j0 < j1)
        j = j0
        j0 = N+1
        ij++
    else
        if (j1 == N+1)
           # Nothing more on this row, and j0 and j1 are both N+1.
           i++;
           continue
        j = j1
        j1 = N+1
        ji++
    # We may now store (i,j) in CSR
    if (-1 == row_ind[i])
        row_ind[i]     = csr;
    col_ind[csr++] = j

上述算法可以改进,对于任何给定的i,如果存在pq这样的NodesIJ[p] = iNodesJI[q] = i,则总是NodesIJ[p][1] > NodesJI[q][1],因为前者描述右上三角,后者描述左下角。所以我们可以扫描NodesJI,直到NodesJI[p][0]是i,然后继续到NodesJI[q]

我们还可以避免总是检查row_ind初始化,注意如果csr索引没有改变,那么行是空的,相应的值可以是-1 (或者N+1,或者任何我们想要的“无效”值),否则它必须是csr的前一个值。

代码语言:javascript
复制
    scsr = csr;
    while NodesIJ[ij][0] == i
        col_ind[csr++] = NodesIJ[ij++][1]
    while NodesJI[ji][0] == i
        col_ind[csr++] = NodesJI[ji++][1]
    row_ind[i++] = (csr == scsr) ? -1 : scsr;

以上运行在O(N log N)中。

另一种方法是分配矩阵,将边缘列表解码为矩阵,并将其解析为CSR。这是O( N ),但可能需要太多内存;对于N的列表大小,您可能有最多N^2 (或(N/a)^2,即连接的平均数量)单元格。数以百万计的边缘列表可能很容易就需要数十of的存储空间。

票数 0
EN

Stack Overflow用户

发布于 2012-10-19 13:22:14

您的数据采用所谓的三重集稀疏格式,其中有显式的行列索引。你想做的是两件事:

  • 将三重奏格式转换为CRS格式
  • 由于有些条目可能会丢失,并且您需要一个无方向图,所以最终的矩阵将是A= A+A‘(转置)。

为了跟进您的示例,final将同时包含(0,2)(2,0)条目。

转换可以通过多种方式进行。看看一个非常完善的SuiteSparse库,特别是cholmod_triplet.c文件,它实现了您需要的功能。本质上,它是在行索引和列索引上使用两个阶段桶排序来执行的,同时删除重复项。该算法具有线性复杂度,如果您对处理大数据集感兴趣的话,这是很好的。换位和许多其他有用的稀疏操作也可以使用该包完成。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12969842

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档