将邻接矩阵的列和行排序为上三角 编辑:1

问题描述

对于有向图,我有一个约束,即邻接矩阵A应该是对角线为0的上三角(断言非循环条件)。现在,假设我已任意排列节点的顺序,以使新的邻接矩阵B不再是上三角。我想要从A恢复B的三角矩阵。我可以将矩阵作为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]
2 [0,1]
3 [0,1]
4 [0,0]]

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

其中A是完整的顺序DAG。 (在非周期性条件允许的情况下,完全连接

解决方法

要使我的pandas解决方案正常工作,请在数据帧中添加全1的列(以避免出现全零行):

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

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

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