【问题标题】:sort columns and rows of a (adjacency) matrix to be upper triangular将(邻接)矩阵的列和行排序为上三角
【发布时间】:2020-10-30 00:42:46
【问题描述】:

对于有向图,我有一个约束,即邻接矩阵A 应该是具有 0 对角线的上三角形(断言非循环条件)。现在假设我任意排列了节点的顺序,这样新的邻接矩阵B 就不再是上三角矩阵了。我想要的是从B 恢复A 三角矩阵。我可以将矩阵作为numpy.arraypandas.DataFrame 对象,因此我正在这些库中寻找解决方案。

目前我的解决方案如下:

  1. 我们知道有一个节点没有父节点(一个全零列),所以我找到它,将它存储在一个数组中,然后从其他节点中删除连接
  2. 重复所有节点,直到创建节点的有序列表。

代码如下:

def sort_nodes(adj_matrix: np.ndarray = None):
    ordered_list = []
    covered_nodes = 0
    while covered_nodes < adj_matrix.shape[0]:
        # sum of the columns
        sum_c = adj_matrix.sum(axis=0)
        # find nodes with no parents: sum should be zero
        parent_inds = list(np.where(sum_c == 0)[0])

        # an assertion to make sure the matrix can be sorted triangular
        assert len(parent_inds) != 0
        
        # update the while condition
        covered_nodes += len(parent_inds)
        # add to the list
        ordered_list += parent_inds

        # remove parent edges by set the corresponding row to zero
        adj_matrix[parent_inds, :] = 0
        # eliminate from columns by assigning values so that its sum cannot be zero
        adj_matrix[:, parent_inds] = 10
    return ordered_list

有什么解决办法吗?一个函数或更简洁的算法。我还研究了networkx 等图形库的表面,但一无所获……干杯!

编辑:1

此类问题的一个例子是:

A:
   1  2  3  4
1[[0, 1, 1, 1]
2 [0, 0, 1, 1]
3 [0, 0, 0, 1]
4 [0, 0, 0, 0]]

B:
   2  1  4  3
2[[0, 0, 1, 1]
1 [1, 0, 1, 1]
4 [0, 0, 0, 0]
3 [0, 0, 1, 0]]

其中 A 是完整的顺序 DAG。 (在非循环条件允许的情况下完全连接)

【问题讨论】:

  • 我们可以假设非零值都是1吗?或者图表是加权的?
  • @AminGheibi 是的,我们可以。元素是二进制的
  • 您实现的称为拓扑排序(它之所以有效,是因为该图是非循环的)。您可以通过 for 循环和 sum 在列上轻松地在 DataFrame 上实现此功能(与您使用的方法相同)。我在想是否有办法在熊猫中不使用 for 循环来实现它。我对此表示怀疑,因为您必须更新节点的连接并重复。
  • @AminGheibi 之前没有听过关键字“拓扑排序”。谢谢!我去看看
  • 请提供一个置换矩阵的例子。任何行都可以由全 0 组成吗?

标签: python pandas numpy directed-acyclic-graphs adjacency-matrix


【解决方案1】:

为了使我的pandas 解决方案能够正常工作,请将一列全为 1 的列添加到数据框中(以避免全零行):

df = pd.DataFrame([[0,1,1,0],[0,0,0,1],[0,0,1,1],[0,0,0,0]])
df.loc[:, df.shape[1]] = 1

现在你可以找到每一行最左边的 1 的索引。索引越小,原始非置换矩阵中的行就越高。最后,按该位置对行进行排序并删除最后一列 1:

df = df.reindex(df.idxmax(1) - 1).iloc[:,:-1]
#   0  1  2  3
#0  0  1  1  0
#2  0  0  1  1
#1  0  0  0  1
#3  0  0  0  0

【讨论】:

  • 我不太明白你的想法,但我只是在我的示例中检查了它(问题中的 B 矩阵),它返回了 [[1.0 0.0 1.0 1.0], [NaN NaN NaN NaN], [0.0 0.0 1.0 0.0], [1.0 0.0 1.0 1.0]] 你在我的示例中测试了吗?
  • 数据框必须有索引和列 0 到 N-1,而不是 1 到 N,因为它在 pandas(和 numpy)中是习惯的。我提供了一个与您的非常相似的示例。
猜你喜欢
  • 2011-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多