#python #pandas #numpy #directed-acyclic-graphs #adjacency-matrix
#python #панды #numpy #направленные ациклические графы #матрица смежности
Вопрос:
для ориентированного графа у меня есть ограничение, которое заключается в том, что матрица смежности A
должна быть верхней треугольной с диагональю 0 (утверждение ациклического условия). Теперь предположим, что я произвольно изменил порядок узлов, так что новая матрица смежности B
больше не является верхней треугольной. Я хочу восстановить A
треугольную матрицу B
. У меня может быть матрица как numpy.array
pandas.DataFrame
объект or, поэтому я ищу решение в этих библиотеках.
Пока мое решение выглядит следующим образом:
- мы знаем, что есть узел, у которого нет родителей (один столбец с нулевым значением), поэтому я нахожу его, сохраняю в массиве и удаляю соединение с другими узлами
- Я повторяю для всех узлов, пока не составлю упорядоченный список узлов.
вот код:
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). Я привел пример, который очень похож на ваш.