У меня есть дерево, например. как networkx объект. Чтобы ввести его в алгоритм черного ящика, мне нужно сохранить его в следующем странном формате:

Пройдите по дереву по часовой стрелке. Проходя через одну сторону края, я помечаю его постепенно. Затем я хочу сохранить для каждого края метки с двух сторон.

Например, звезда станет списком [(0,1),(2,3),(4,5),...], а путь с 3 вершинами будет [(0,3),(1,2)].

Я озадачен реализацией этого. Как это может быть сделано? Я могу использовать любую библиотеку.

0
Emolga 19 Июл 2020 в 15:50

2 ответа

Лучший ответ

Я отвечу на это без ссылки на какую-либо библиотеку.

Вам необходимо выполнить обход в глубину и зарегистрировать (глобальный) инкрементный номер до посещения вами поддерева, а также после посещения вами. Эти два числа составляют кортеж, который вы должны добавить к результату, который вы получите от обхода поддерева.

Вот реализация, которая нуждается в представлении графа в виде списка смежности. Основная функция должна получить корневой узел и список смежности

def iter_naturals(): # helper function to produce sequential numbers
    n = 0
    while True:
        yield n
        n += 1

def half_edges(root, adj):
    visited = set()
    sequence = iter_naturals()

    def dfs(node):
        result = []
        visited.add(node)
        for child in adj[node]:
            if child not in visited:
                forward = next(sequence)
                path = dfs(child)
                backward = next(sequence)
                result.extend([(forward, backward)] + path)
        return result

    return dfs(root)

Вот как вы можете запустить его для двух упомянутых вами примеров. Я только что реализовал эти графы в виде списков смежности, где узлы идентифицируются по их индексу в этом списке:

Пример 1: «звезда»:

Корень является родителем всех других узлов

adj = [
    [1,2,3], # 1,2,3 are children of 0
    [], 
    [],
    []
]
print(half_edges(0, adj))  # [(0, 1), (2, 3), (4, 5)]

Пример 2: один путь с 3 узлами

adj = [
    [1], # 1 is a child of 0
    [2], # 2 is a child of 1
    []
]
print(half_edges(0, adj))  # [(0, 3), (1, 2)]
1
trincot 19 Июл 2020 в 13:24

Я нашел эту замечательную встроенную функцию dfs_labeled_edges в сети x. Оттуда это ветер.

def get_new_encoding(G):
    dfs = [(v[0],v[1]) for v in nx.dfs_labeled_edges(G, source=1) if v[0]!=v[1] and v[2]!="nontree"]
    dfs_ind = sorted(range(len(dfs)), key=lambda k: dfs[k])
    new_tree_encoding = [(dfs_ind[i],dfs_ind[i+1]) for i in range(0,len(dfs_ind),2)]
    return new_tree_encoding
0
Emolga 19 Июл 2020 в 13:50