| """Generate graphs with given degree and triangle sequence.""" |
|
|
| import networkx as nx |
| from networkx.utils import py_random_state |
|
|
| __all__ = ["random_clustered_graph"] |
|
|
|
|
| @py_random_state(2) |
| @nx._dispatchable(graphs=None, returns_graph=True) |
| def random_clustered_graph(joint_degree_sequence, create_using=None, seed=None): |
| r"""Generate a random graph with the given joint independent edge degree and |
| triangle degree sequence. |
| |
| This uses a configuration model-like approach to generate a random graph |
| (with parallel edges and self-loops) by randomly assigning edges to match |
| the given joint degree sequence. |
| |
| The joint degree sequence is a list of pairs of integers of the form |
| $[(d_{1,i}, d_{1,t}), \dotsc, (d_{n,i}, d_{n,t})]$. According to this list, |
| vertex $u$ is a member of $d_{u,t}$ triangles and has $d_{u, i}$ other |
| edges. The number $d_{u,t}$ is the *triangle degree* of $u$ and the number |
| $d_{u,i}$ is the *independent edge degree*. |
| |
| Parameters |
| ---------- |
| joint_degree_sequence : list of integer pairs |
| Each list entry corresponds to the independent edge degree and |
| triangle degree of a node. |
| create_using : NetworkX graph constructor, optional (default MultiGraph) |
| Graph type to create. If graph instance, then cleared before populated. |
| seed : integer, random_state, or None (default) |
| Indicator of random number generation state. |
| See :ref:`Randomness<randomness>`. |
| |
| Returns |
| ------- |
| G : MultiGraph |
| A graph with the specified degree sequence. Nodes are labeled |
| starting at 0 with an index corresponding to the position in |
| deg_sequence. |
| |
| Raises |
| ------ |
| NetworkXError |
| If the independent edge degree sequence sum is not even |
| or the triangle degree sequence sum is not divisible by 3. |
| |
| Notes |
| ----- |
| As described by Miller [1]_ (see also Newman [2]_ for an equivalent |
| description). |
| |
| 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 |
| independent degree sequence does not have an even sum or the |
| triangle degree sequence sum is not divisible by 3. |
| |
| This configuration model-like 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] Joel C. Miller. "Percolation and epidemics in random clustered |
| networks". In: Physical review. E, Statistical, nonlinear, and soft |
| matter physics 80 (2 Part 1 August 2009). |
| .. [2] M. E. J. Newman. "Random Graphs with Clustering". |
| In: Physical Review Letters 103 (5 July 2009) |
| |
| Examples |
| -------- |
| >>> deg = [(1, 0), (1, 0), (1, 0), (2, 0), (1, 0), (2, 1), (0, 1), (0, 1)] |
| >>> G = nx.random_clustered_graph(deg) |
| |
| To remove parallel edges: |
| |
| >>> G = nx.Graph(G) |
| |
| To remove self loops: |
| |
| >>> G.remove_edges_from(nx.selfloop_edges(G)) |
| |
| """ |
| |
| joint_degree_sequence = list(joint_degree_sequence) |
|
|
| N = len(joint_degree_sequence) |
| G = nx.empty_graph(N, create_using, default=nx.MultiGraph) |
| if G.is_directed(): |
| raise nx.NetworkXError("Directed Graph not supported") |
|
|
| ilist = [] |
| tlist = [] |
| for n in G: |
| degrees = joint_degree_sequence[n] |
| for icount in range(degrees[0]): |
| ilist.append(n) |
| for tcount in range(degrees[1]): |
| tlist.append(n) |
|
|
| if len(ilist) % 2 != 0 or len(tlist) % 3 != 0: |
| raise nx.NetworkXError("Invalid degree sequence") |
|
|
| seed.shuffle(ilist) |
| seed.shuffle(tlist) |
| while ilist: |
| G.add_edge(ilist.pop(), ilist.pop()) |
| while tlist: |
| n1 = tlist.pop() |
| n2 = tlist.pop() |
| n3 = tlist.pop() |
| G.add_edges_from([(n1, n2), (n1, n3), (n2, n3)]) |
| return G |
|
|