Оптимизация алгоритма всех путей

Я успешно использовал следующий алгоритм, чтобы завершить все пути до длины пути 10 на графиках ~900 узлов. Тем не менее, я хочу увеличить масштаб до больших графиков, и мне интересно, есть ли дальнейшая оптимизация, которую я могу сделать. Пока что у меня есть:

  • После того, как узел завершил свою DFS, пути сохраняются в хеш-таблицу. Если указанный узел встречается, к нему добавляются пути из хеш-таблицы, поэтому работа не повторяется.
  • Узлы отсортированы по степени (по возрастанию). Таким образом, наиболее вероятные узлы уже будут в хеш-таблице.

Специфика алгоритма: строит сеть из химических веществ (узлов) и реакций (ребер) и создает пути, чтобы впоследствии их можно было искать намного быстрее для теоретических путей, которые впоследствии можно будет проверить экспериментально.

Алгоритм основан на сети x all_simple_paths алгоритм:

def _all_simple_paths_graph(DG, cutoff):
    memorizedPaths = {}
    nlist = []
    #sorts nodes into highest -> lowest degree order
    degreelist = sorted(DG.degree_iter(),key=itemgetter(1),reverse=True)
    for i in degreelist:
        t = re.findall("'\s*([^\"]*)\s*'",str(i))
        nlist.extend(t)
    with open ('PythonOutput.txt', "wb") as csvfile:
        writer = csv.writer(csvfile, delimiter=' ', quotechar='|')
        numberdone = 0
        #for each node start a new DFS
        for source in nlist:
            print source 
            print numberdone
            numberdone += 1
            uniqueTreePaths = []
            if cutoff < 1:
                return
            visited = [source]
            stack = [iter(DG[source])]
            while stack:
                children = stack[-1]
                child = next(children, None)
                if child is None:
                    stack.pop()
                    visited.pop()
                #If a node has been searched before, append its paths
                elif child in memorizedPaths:
                    for path in memorizedPaths[child]:
                        newPath = (tuple(visited) + tuple(path))
                        if (len(newPath) <= cutoff) and (len(set(visited) & set(path)) == 0):
                            uniqueTreePaths.append(newPath)
                    continue
                elif len(visited) < cutoff:
                    if child not in visited:
                        visited.append(child)
                        stack.append(iter(DG[child]))
                        if visited not in uniqueTreePaths:
                            uniqueTreePaths.append(tuple(visited))
                else: #len(visited) == cutoff:
                    if (visited not in uniqueTreePaths) and (child not in visited):
                        uniqueTreePaths.append(tuple(visited + [child]))
                    stack.pop()
                    visited.pop()
            #for each node, write to disk to save RAM
            for path in uniqueTreePaths:
                writer.writerow(path)
            #add paths for each node to the hash table
            memorizedPaths[source] = uniqueTreePaths

Если у кого-нибудь есть предложения по дальнейшей оптимизации алгоритма, это будет с благодарностью.

1 ответ

Прежде всего - измерение - ваш лучший друг. Если вы не собираете информацию о том, сколько времени занимает алгоритм, то у вас нет реального способа узнать, помогает ли изменение или нет. Ваша идея кэшировать свои результаты умна, но вы должны проверить время с и без кэширования, чтобы убедиться, что оно действительно помогает.

В частности, одна часть вашего кода, в которой я вижу возможности для улучшения, if (visited not in uniqueTreePaths)..., Вы проверяете, содержится ли список в списке списков. Я не уверен, что лучший способ исправить это (опять же, собрать данные синхронизации из вашего кода), но одна из возможностей - представить пути в виде строк, а не списков, позволяя хранить их с помощью хэшей.

Другие вопросы по тегам