问题描述
对于有向图,我有一个约束,即邻接矩阵A
应该是对角线为0的上三角(断言非循环条件)。现在,假设我已任意排列节点的顺序,以使新的邻接矩阵B
不再是上三角。我想要从A
恢复B
的三角矩阵。我可以将矩阵作为numpy.array
或pandas.DataFrame
对象,因此我正在这些库中寻找解决方案。
到目前为止,我的解决方案如下:
代码如下:
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