Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/graphs/generators/degree_sequence.py
8815 views
1
# -*- coding: utf-8 -*-
2
r"""
3
Graphs with a given degree sequence
4
5
The methods defined here appear in :mod:`sage.graphs.graph_generators`.
6
"""
7
8
###########################################################################
9
#
10
# Copyright (C) 2006 Robert L. Miller <[email protected]>
11
# and Emily A. Kirkman
12
# Copyright (C) 2009 Michael C. Yurko <[email protected]>
13
#
14
# Distributed under the terms of the GNU General Public License (GPL)
15
# http://www.gnu.org/licenses/
16
###########################################################################
17
18
# import from Sage library
19
from sage.graphs.graph import Graph
20
from sage.misc.randstate import current_randstate
21
22
23
def DegreeSequence(deg_sequence):
24
"""
25
Returns a graph with the given degree sequence. Raises a NetworkX
26
error if the proposed degree sequence cannot be that of a graph.
27
28
Graph returned is the one returned by the Havel-Hakimi algorithm,
29
which constructs a simple graph by connecting vertices of highest
30
degree to other vertices of highest degree, resorting the remaining
31
vertices by degree and repeating the process. See Theorem 1.4 in
32
[CharLes1996]_.
33
34
INPUT:
35
36
- ``deg_sequence`` - a list of integers with each
37
entry corresponding to the degree of a different vertex.
38
39
40
EXAMPLES::
41
42
sage: G = graphs.DegreeSequence([3,3,3,3])
43
sage: G.edges(labels=False)
44
[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
45
sage: G.show() # long time
46
47
::
48
49
sage: G = graphs.DegreeSequence([3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3])
50
sage: G.show() # long time
51
52
::
53
54
sage: G = graphs.DegreeSequence([4,4,4,4,4,4,4,4])
55
sage: G.show() # long time
56
57
::
58
59
sage: G = graphs.DegreeSequence([1,2,3,4,3,4,3,2,3,2,1])
60
sage: G.show() # long time
61
62
REFERENCE:
63
64
.. [CharLes1996] Chartrand, G. and Lesniak, L.: Graphs and Digraphs.
65
Chapman and Hall/CRC, 1996.
66
"""
67
import networkx
68
return Graph(networkx.havel_hakimi_graph([int(i) for i in deg_sequence]))
69
70
def DegreeSequenceBipartite(s1 ,s2 ):
71
r"""
72
Returns a bipartite graph whose two sets have the given
73
degree sequences.
74
75
Given two different sequences of degrees `s_1` and `s_2`,
76
this functions returns ( if possible ) a bipartite graph
77
on sets `A` and `B` such that the vertices in `A` have
78
`s_1` as their degree sequence, while `s_2` is the degree
79
sequence of the vertices in `B`.
80
81
INPUT:
82
83
- ``s_1`` -- list of integers corresponding to the degree
84
sequence of the first set.
85
- ``s_2`` -- list of integers corresponding to the degree
86
sequence of the second set.
87
88
ALGORITHM:
89
90
This function works through the computation of the matrix
91
given by the Gale-Ryser theorem, which is in this case
92
the adjacency matrix of the bipartite graph.
93
94
EXAMPLES:
95
96
If we are given as sequences ``[2,2,2,2,2]`` and ``[5,5]``
97
we are given as expected the complete bipartite
98
graph `K_{2,5}` ::
99
100
sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5])
101
sage: g.is_isomorphic(graphs.CompleteBipartiteGraph(5,2))
102
True
103
104
Some sequences being incompatible if, for example, their sums
105
are different, the functions raises a ``ValueError`` when no
106
graph corresponding to the degree sequences exists. ::
107
108
sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,1],[5,5])
109
Traceback (most recent call last):
110
...
111
ValueError: There exists no bipartite graph corresponding to the given degree sequences
112
113
TESTS:
114
115
Trac ticket #12155::
116
117
sage: graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]).complement()
118
complement(): Graph on 7 vertices
119
"""
120
121
from sage.combinat.integer_vector import gale_ryser_theorem
122
from sage.graphs.bipartite_graph import BipartiteGraph
123
124
s1 = sorted(s1, reverse = True)
125
s2 = sorted(s2, reverse = True)
126
127
m = gale_ryser_theorem(s1,s2)
128
129
if m is False:
130
raise ValueError("There exists no bipartite graph corresponding to the given degree sequences")
131
else:
132
return Graph(BipartiteGraph(m))
133
134
def DegreeSequenceConfigurationModel(deg_sequence, seed=None):
135
"""
136
Returns a random pseudograph with the given degree sequence. Raises
137
a NetworkX error if the proposed degree sequence cannot be that of
138
a graph with multiple edges and loops.
139
140
One requirement is that the sum of the degrees must be even, since
141
every edge must be incident with two vertices.
142
143
INPUT:
144
145
- ``deg_sequence`` - a list of integers with each
146
entry corresponding to the expected degree of a different vertex.
147
148
- ``seed`` - for the random number generator.
149
150
151
EXAMPLES::
152
153
sage: G = graphs.DegreeSequenceConfigurationModel([1,1])
154
sage: G.adjacency_matrix()
155
[0 1]
156
[1 0]
157
158
Note: as of this writing, plotting of loops and multiple edges is
159
not supported, and the output is allowed to contain both types of
160
edges.
161
162
::
163
164
sage: G = graphs.DegreeSequenceConfigurationModel([3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3])
165
sage: G.edges(labels=False)
166
[(0, 2), (0, 10), (0, 15), (1, 6), (1, 16), (1, 17), (2, 5), (2, 19), (3, 7), (3, 14), (3, 14), (4, 9), (4, 13), (4, 19), (5, 6), (5, 15), (6, 11), (7, 11), (7, 17), (8, 11), (8, 18), (8, 19), (9, 12), (9, 13), (10, 15), (10, 18), (12, 13), (12, 16), (14, 17), (16, 18)]
167
sage: G.show() # long time
168
169
REFERENCE:
170
171
.. [Newman2003] Newman, M.E.J. The Structure and function of complex
172
networks, SIAM Review vol. 45, no. 2 (2003), pp. 167-256.
173
"""
174
if seed is None:
175
seed = current_randstate().long_seed()
176
import networkx
177
return Graph(networkx.configuration_model([int(i) for i in deg_sequence], seed=seed), loops=True, multiedges=True, sparse=True)
178
179
def DegreeSequenceTree(deg_sequence):
180
"""
181
Returns a tree with the given degree sequence. Raises a NetworkX
182
error if the proposed degree sequence cannot be that of a tree.
183
184
Since every tree has one more vertex than edge, the degree sequence
185
must satisfy len(deg_sequence) - sum(deg_sequence)/2 == 1.
186
187
INPUT:
188
189
- ``deg_sequence`` - a list of integers with each
190
entry corresponding to the expected degree of a different vertex.
191
192
193
EXAMPLE::
194
195
sage: G = graphs.DegreeSequenceTree([3,1,3,3,1,1,1,2,1])
196
sage: G.show() # long time
197
"""
198
import networkx
199
return Graph(networkx.degree_sequence_tree([int(i) for i in deg_sequence]))
200
201
def DegreeSequenceExpected(deg_sequence, seed=None):
202
"""
203
Returns a random graph with expected given degree sequence. Raises
204
a NetworkX error if the proposed degree sequence cannot be that of
205
a graph.
206
207
One requirement is that the sum of the degrees must be even, since
208
every edge must be incident with two vertices.
209
210
INPUT:
211
212
- ``deg_sequence`` - a list of integers with each
213
entry corresponding to the expected degree of a different vertex.
214
215
- ``seed`` - for the random number generator.
216
217
218
EXAMPLE::
219
220
sage: G = graphs.DegreeSequenceExpected([1,2,3,2,3])
221
sage: G.edges(labels=False)
222
[(0, 2), (0, 3), (1, 1), (1, 4), (2, 3), (2, 4), (3, 4), (4, 4)]
223
sage: G.show() # long time
224
225
REFERENCE:
226
227
.. [ChungLu2002] Chung, Fan and Lu, L. Connected components in random
228
graphs with given expected degree sequences.
229
Ann. Combinatorics (6), 2002 pp. 125-145.
230
"""
231
if seed is None:
232
seed = current_randstate().long_seed()
233
import networkx
234
return Graph(networkx.expected_degree_graph([int(i) for i in deg_sequence], seed=seed), loops=True)
235
236