Какова наиболее эффективная структура данных графа в Python? [закрытый]


Мне нужно уметь манипулировать большим (10^7 узлов) графом в python. Данные, соответствующие каждому узлу / краю, минимальны, скажем, небольшое количество строк. Что является наиболее эффективным, с точки зрения память и скорость, как это сделать?

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

graph[I][J]["Property"]="value"

что бы вы предложили?


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

загрузка данных в память не является огромной проблемой. Это делается раз и навсегда. Трудоемкая часть посещает узлы, поэтому я могу извлечь информацию и измерить интересующие меня показатели в.

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

7 63

7 ответов:

Я бы настоятельно рекомендовал вам посмотреть на NetworkX. Это испытанный в бою Боевой конь и первый инструмент, который большинство типов "исследований" достигают, когда им нужно сделать анализ сетевых данных. Я без проблем манипулировал графиками с 100 тысячами ребер на ноутбуке. Его особенность богата и очень проста в использовании. Вы обнаружите, что больше фокусируетесь на текущей проблеме, а не на деталях в базовой реализации.

пример Erdős-Rényi генерация и анализ случайных графов


"""
Create an G{n,m} random graph with n nodes and m edges
and report some properties.

This graph is sometimes called the Erd##[m~Qs-Rényi graph
but is different from G{n,p} or binomial_graph which is also
sometimes called the Erd##[m~Qs-Rényi graph.
"""
__author__ = """Aric Hagberg (hagberg@lanl.gov)"""
__credits__ = """"""
#    Copyright (C) 2004-2006 by 
#    Aric Hagberg 
#    Dan Schult 
#    Pieter Swart 
#    Distributed under the terms of the GNU Lesser General Public License
#    http://www.gnu.org/copyleft/lesser.html

from networkx import *
import sys

n=10 # 10 nodes
m=20 # 20 edges

G=gnm_random_graph(n,m)

# some properties
print "node degree clustering"
for v in nodes(G):
    print v,degree(G,v),clustering(G,v)

# print the adjacency list to terminal 
write_adjlist(G,sys.stdout)

визуализации также просты:

enter image description here

дополнительная визуализация:http://jonschull.blogspot.com/2008/08/graph-visualization.html

хотя этот вопрос теперь довольно старый, я думаю, что стоит упомянуть мой собственный модуль python для манипуляций с графами под названием graph-tool. Это очень эффективно, так как структуры данных и алгоритмы реализованы в C++, с шаблонным метапрограммированием, с использованием библиотеки графов Boost. Поэтому его производительность (как в использовании памяти, так и во время выполнения) сопоставима с чистой библиотекой C++ и может быть на порядок лучше, чем типичный код python, без ущерба для простота использования. Я сам постоянно использую его для работы с очень большими графиками.

Как уже упоминалось, NetworkX очень хорош, с другим вариантомigraph. Оба модуля будут иметь большинство (если не все) инструментов анализа, которые вам, вероятно, понадобятся, и обе библиотеки обычно используются с большими сетями.

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

судя по вашему примеру, "свойство", было бы лучше с классовым подходом для конечного уровня и реальных свойств? Или имена свойств сильно меняются от узла к узлу?

Я бы сказал, что то, что означает "эффективный", зависит от a много чего, например:

  • скорость обновления (вставка, обновление, удаление)
  • скорость поиска произвольного доступа
  • скорость последовательного поиска
  • память используется

Я думаю, что вы обнаружите, что структура данных, которая является быстрой, обычно потребляет больше памяти, чем медленная. Это не всегда так, но большинство структур данных, похоже, следуют этому.

словарь может быть простым в использовании, и дать вам относительно равномерно быстрый доступ, он, скорее всего, будет использовать больше памяти, чем, как вы предлагаете, списки. Списки, однако, как правило, содержат больше накладных расходов при вставке данных в него, если они предварительно не выделяют узлы X, в которых они снова будут использовать больше памяти.

мое предложение, в общем, было бы просто использовать метод, который кажется вам наиболее естественным, а затем сделать "стресс-тест" системы, добавив к нему значительное количество данных и посмотреть, станет ли он проблема.

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

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

однако на фронте производительности загрузка его в память может не быть проблемой, но если вы используете слишком много, вы в конечном итоге замените диск, что убьет производительность даже высокоэффективных диктовок Python. Старайтесь как можно меньше использовать память. Кроме того, ОЗУ удивительно дешево прямо сейчас; если вы делаете такие вещи много, нет причин не иметь по крайней мере 4 ГБ.

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

создание структуры на основе классов, вероятно, будет иметь больше накладных расходов, чем структура на основе dict, поскольку в классах python фактически используются dicts при их реализации.

без сомнения NetworkX является лучшей структурой данных до сих пор для графика. Он поставляется с такими утилитами, как вспомогательные функции, структуры данных и алгоритмы, генераторы случайных последовательностей, декораторы, заказ Cuthill-Mckee, контекстные менеджеры

NetworkX отлично подходит, потому что он wowrs для графиков, орграфов и мультиграфов. Он может писать график несколькими способами: список смежности, многострочный список смежности, Список краев, GEXF, GML. Он работает с рассолом, GraphML, JSON, SparseGraph6 и т. д.

Он имеет реализация различных алгоритмов radimade в том числе: Аппроксимация, Двудольная, Граничная, Центральная, Клика, Кластеризация, Окраска, Компоненты, Связность, Циклы, Направленные Ациклические Графы, Меры Расстояния, Доминирующие Множества, Эйлеровы, Изоморфизм, Анализ Связей, Предсказание Связей, Сопоставление, Минимальное Связующее Дерево, Богатый Клуб, Кратчайший Путь, Обход, Дерево.