Генерация графа с определенной степенью распределения? - PullRequest
8 голосов
/ 01 декабря 2010

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

Ответы [ 4 ]

7 голосов
/ 02 декабря 2010

Если вы хотите использовать модель конфигурации, в NetworkX должно работать нечто подобное:

import random 
import networkx as nx
z=[int(random.gammavariate(alpha=9.0,beta=2.0)) for i in range(100)]
G=nx.configuration_model(z)

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

В примечаниях к документации NetworkX для configuration_model приведен еще один пример, ссылка и способ удаления параллельных ребер и собственных циклов:

Notes
-----
As described by Newman [1]_.

A non-graphical degree sequence (not realizable by some simple
graph) is allowed since this function returns graphs with self
loops and parallel edges.  An exception is raised if the degree
sequence does not have an even sum.

This configuration model construction process can lead to
duplicate edges and loops.  You can remove the self-loops and
parallel edges (see below) which will likely result in a graph
that doesn't have the exact degree sequence specified.  This
"finite-size effect" decreases as the size of the graph increases.

References
----------
.. [1] M.E.J. Newman, "The structure and function
       of complex networks", SIAM REVIEW 45-2, pp 167-256, 2003.

Examples
--------
>>> from networkx.utils import powerlaw_sequence
>>> z=nx.create_degree_sequence(100,powerlaw_sequence)
>>> G=nx.configuration_model(z)

To remove parallel edges:

>>> G=nx.Graph(G)

To remove self loops:

>>> G.remove_edges_from(G.selfloop_edges())

Вот пример, аналогичный приведенному на http://networkx.lanl.gov/examples/drawing/degree_histogram.html, который делает чертеж, включающий в себя макет графика наибольшего подключенного компонента:

#!/usr/bin/env python
import random
import matplotlib.pyplot as plt
import networkx as nx

def seq(n):
    return [random.gammavariate(alpha=2.0,beta=1.0) for i in range(100)]    
z=nx.create_degree_sequence(100,seq)
nx.is_valid_degree_sequence(z)
G=nx.configuration_model(z)  # configuration model

degree_sequence=sorted(nx.degree(G).values(),reverse=True) # degree sequence
print "Degree sequence", degree_sequence
dmax=max(degree_sequence)

plt.hist(degree_sequence,bins=dmax)
plt.title("Degree histogram")
plt.ylabel("count")
plt.xlabel("degree")

# draw graph in inset 
plt.axes([0.45,0.45,0.45,0.45])
Gcc=nx.connected_component_subgraphs(G)[0]
pos=nx.spring_layout(Gcc)
plt.axis('off')
nx.draw_networkx_nodes(Gcc,pos,node_size=20)
nx.draw_networkx_edges(Gcc,pos,alpha=0.4)

plt.savefig("degree_histogram.png")
plt.show()
2 голосов
/ 01 декабря 2010

Я сделал это некоторое время назад в базовом Python ... IIRC, я использовал следующий метод. По памяти это может быть не совсем точно, но, надеюсь, оно чего-то стоит:

  1. Выберите количество узлов N в вашем графике и плотность (существующие ребра по возможным ребрам), D. Это подразумевает количество ребер, E.
  2. Для каждого узла назначьте его степень, сначала выбрав случайное положительное число x и найдя P (x), где P - ваш pdf. Степень узла (P (x) * E / 2) -1.
  3. Случайно выберите узел и подключите его к другому случайному узлу. Если какой-либо узел реализовал присвоенную ему степень, исключите ее из дальнейшего выбора. Повторите E раз.

N.B. что это не создает связный граф в целом.

1 голос
/ 06 октября 2013

Я знаю, что это очень поздно, но вы можете сделать то же самое, хотя и немного более просто, с mathematica.

RandomGraph [DegreeGraphDistribution [{3, 3, 3, 3, 3, 3, 3, 3}], 4]

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

0 голосов
/ 25 июля 2017

Включая вышеупомянутое, networkx предоставляет 4 алгоритма, которые получают степень_распределения в качестве входных данных:

  • configuration_model : объяснить с помощью @ eric
  • Ожидаемый_град_граф : использовать вероятностный подход, основанный на ожидаемой степени каждого узла.Это не даст вам точные градусы, но приблизительное значение.
  • havel_hakimi_graph : этот пытается сначала соединить узлы с наивысшей степенью
  • random_degree_sequence_graph : насколько я вижу, это похоже на то, что предложил @JonC;он имеет параметр trials, поскольку нет гарантии нахождения подходящей конфигурации.

Полный список (включая некоторые версии алгоритмов для ориентированных графов): здесь .

Я также нашел пару статей:

...