Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/networkx/generators/random_clustered.py: 19%
31 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
1"""Generate graphs with given degree and triangle sequence.
2"""
3import networkx as nx
4from networkx.utils import py_random_state
6__all__ = ["random_clustered_graph"]
9@py_random_state(2)
10@nx._dispatch(graphs=None)
11def random_clustered_graph(joint_degree_sequence, create_using=None, seed=None):
12 r"""Generate a random graph with the given joint independent edge degree and
13 triangle degree sequence.
15 This uses a configuration model-like approach to generate a random graph
16 (with parallel edges and self-loops) by randomly assigning edges to match
17 the given joint degree sequence.
19 The joint degree sequence is a list of pairs of integers of the form
20 $[(d_{1,i}, d_{1,t}), \dotsc, (d_{n,i}, d_{n,t})]$. According to this list,
21 vertex $u$ is a member of $d_{u,t}$ triangles and has $d_{u, i}$ other
22 edges. The number $d_{u,t}$ is the *triangle degree* of $u$ and the number
23 $d_{u,i}$ is the *independent edge degree*.
25 Parameters
26 ----------
27 joint_degree_sequence : list of integer pairs
28 Each list entry corresponds to the independent edge degree and
29 triangle degree of a node.
30 create_using : NetworkX graph constructor, optional (default MultiGraph)
31 Graph type to create. If graph instance, then cleared before populated.
32 seed : integer, random_state, or None (default)
33 Indicator of random number generation state.
34 See :ref:`Randomness<randomness>`.
36 Returns
37 -------
38 G : MultiGraph
39 A graph with the specified degree sequence. Nodes are labeled
40 starting at 0 with an index corresponding to the position in
41 deg_sequence.
43 Raises
44 ------
45 NetworkXError
46 If the independent edge degree sequence sum is not even
47 or the triangle degree sequence sum is not divisible by 3.
49 Notes
50 -----
51 As described by Miller [1]_ (see also Newman [2]_ for an equivalent
52 description).
54 A non-graphical degree sequence (not realizable by some simple
55 graph) is allowed since this function returns graphs with self
56 loops and parallel edges. An exception is raised if the
57 independent degree sequence does not have an even sum or the
58 triangle degree sequence sum is not divisible by 3.
60 This configuration model-like construction process can lead to
61 duplicate edges and loops. You can remove the self-loops and
62 parallel edges (see below) which will likely result in a graph
63 that doesn't have the exact degree sequence specified. This
64 "finite-size effect" decreases as the size of the graph increases.
66 References
67 ----------
68 .. [1] Joel C. Miller. "Percolation and epidemics in random clustered
69 networks". In: Physical review. E, Statistical, nonlinear, and soft
70 matter physics 80 (2 Part 1 August 2009).
71 .. [2] M. E. J. Newman. "Random Graphs with Clustering".
72 In: Physical Review Letters 103 (5 July 2009)
74 Examples
75 --------
76 >>> deg = [(1, 0), (1, 0), (1, 0), (2, 0), (1, 0), (2, 1), (0, 1), (0, 1)]
77 >>> G = nx.random_clustered_graph(deg)
79 To remove parallel edges:
81 >>> G = nx.Graph(G)
83 To remove self loops:
85 >>> G.remove_edges_from(nx.selfloop_edges(G))
87 """
88 # In Python 3, zip() returns an iterator. Make this into a list.
89 joint_degree_sequence = list(joint_degree_sequence)
91 N = len(joint_degree_sequence)
92 G = nx.empty_graph(N, create_using, default=nx.MultiGraph)
93 if G.is_directed():
94 raise nx.NetworkXError("Directed Graph not supported")
96 ilist = []
97 tlist = []
98 for n in G:
99 degrees = joint_degree_sequence[n]
100 for icount in range(degrees[0]):
101 ilist.append(n)
102 for tcount in range(degrees[1]):
103 tlist.append(n)
105 if len(ilist) % 2 != 0 or len(tlist) % 3 != 0:
106 raise nx.NetworkXError("Invalid degree sequence")
108 seed.shuffle(ilist)
109 seed.shuffle(tlist)
110 while ilist:
111 G.add_edge(ilist.pop(), ilist.pop())
112 while tlist:
113 n1 = tlist.pop()
114 n2 = tlist.pop()
115 n3 = tlist.pop()
116 G.add_edges_from([(n1, n2), (n1, n3), (n2, n3)])
117 return G