Ну, может, мой калькулятор сломан, но он показывает, что 7 + 18 + (19-15) + 7 = 36, а не 29, что приводит нас к тому, что ваша задача - вычислить сумму предков всех узлов , Есть два способа их вычисления:
Загрузка процессора, но экономия памяти и простота чтения:
В библиотеке Python networkx
это можно решить с помощью одной строки:
sum(DAG.nodes[n]['cost'] for n in nx.ancestors(DAG, your_node) | {your_node})
Где cost
- атрибут на узел, представляющий его значение.
Вот полный рабочий процесс, вы можете скопировать его в блокнот Jupyter и проверить в интерактивном режиме:
import networkx as nx
from random import randint
# Create DAG
G = nx.gnp_random_graph(10,0.3,directed=True)
DAG = nx.DiGraph([(u,v) for (u,v) in G.edges() if u<v])
# Fill 'cost' attributes
for n in DAG.nodes:
DAG.nodes[n]['cost'] = randint(1,10)
# Set the start node
node = 8
# Print the ancestors sum
print(sum(DAG.nodes[n]['cost'] for n in nx.ancestors(DAG, node) | {node}))
Обратите внимание, что ancestors
довольно потребляет процессор ( O (n ^ 2) для каждого узла в невзвешенном графе, как я понимаю) и не должен использоваться для больших графов.
Экономия ЦП, но занимающая много памяти и довольно сложная для чтения:
Если информация о предках необходима для всех узлов, нет необходимости пересчитывать все возможные предки для каждого узла, вы можете повторно использовать предков предшественников. Таким образом, вы должны реализовать эту логику вручную:
def set_node_ancestors(DAG, node):
ancestors = {node}
for n in DAG.predecessors(node):
ancestors = ancestors | DAG.nodes[n]['ancestors']
DAG.nodes[node]['ancestors'] = ancestors
Этот алгоритм проверяет всех предшественников данного узла, принимает их параметры ancestors
, объединяет их и записывает результат в параметр ancestors
данного узла. Затем для каждого узла вы можете суммировать все затраты на узлы в параметре ancestors
.
Вы добавляете узлы один за другим, поэтому вы можете гарантировать, что каждый родительский узел заполнен параметром ancestors
. Но если вы хотите вычислить всех предков в данном графе, вы должны топологически отсортировать его и запустить эту функцию в следующем порядке.
Второй алгоритм намного быстрее первого. Вот сравнение общего времени вычисления предков для каждого узла графа (ось X содержит количество узлов в графе, ось Y - время в миллисекундах):