сортировка столбцов и строк матрицы (смежности) по верхнему треугольнику

#python #pandas #numpy #directed-acyclic-graphs #adjacency-matrix

#python #панды #numpy #направленные ациклические графы #матрица смежности

Вопрос:

для ориентированного графа у меня есть ограничение, которое заключается в том, что матрица смежности A должна быть верхней треугольной с диагональю 0 (утверждение ациклического условия). Теперь предположим, что я произвольно изменил порядок узлов, так что новая матрица смежности B больше не является верхней треугольной. Я хочу восстановить A треугольную матрицу B . У меня может быть матрица как numpy.array pandas.DataFrame объект or, поэтому я ищу решение в этих библиотеках.

Пока мое решение выглядит следующим образом:

  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 — полная последовательная база данных. (полностью подключен настолько, насколько позволяет ациклическое условие)

Комментарии:

1. можем ли мы предположить, что все ненулевые значения равны 1? или график взвешен?

2. @AminGheibi да, мы можем. элементы являются двоичными

3. то, что вы реализовали, называется топологической сортировкой (это работает, потому что граф ациклический). Вы можете легко реализовать это в фрейме данных с помощью цикла for и sum для столбцов (тот же подход, что и у вас). Я думаю, есть ли способ реализовать это без цикла for в pandas. Я сомневаюсь в этом, потому что вам нужно обновлять соединения узлов и повторять.

4. @AminGheibi раньше не слышал ключевое слово «топологическая сортировка». Спасибо! Я проверю это

5. Пожалуйста, приведите пример перестановочной матрицы. Может ли какая-либо строка состоять из всех 0?

Ответ №1:

Чтобы мое pandas решение работало, добавьте столбец из всех единиц в dataframe (чтобы избежать строки со всеми нулями):

 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 в каждой строке. Чем меньше индекс, тем выше была строка в исходной неперестановленной матрице. Наконец, отсортируйте строки по этой позиции и удалите последний столбец из 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
  

Комментарии:

1. Я не совсем понял вашу идею, но просто я проверил ее на своем примере (матрица 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]] вы проверили это на моем примере?

2. Фрейм данных должен иметь индексы и столбцы от 0 до N-1, а не от 1 до N, как это принято в pandas (и numpy). Я привел пример, который очень похож на ваш.