@@ -44,8 +44,9 @@ class SwitchGraph:
4444 def get_edges (self ):
4545 ret : List [Tuple [int , int ]] = []
4646 for k in self .__edges :
47- ret .extend (itertools .repeat (k , self .__edges [k ]))
48- return ret
47+ if self .directed or k [0 ] <= k [1 ]:
48+ ret .extend (itertools .repeat (k , self .__edges [k ]))
49+ return sorted (ret )
4950
5051 def __insert (self , u : int , v : int ):
5152 if (u , v ) not in self .__edges :
@@ -78,9 +79,9 @@ def __init__(self,
7879 self .__edges = {}
7980 for e in E :
8081 if isinstance (e , Edge ):
81- self .__insert (e .start , e .end )
82+ self .insert (e .start , e .end )
8283 else :
83- self .__insert (e [0 ], e [1 ])
84+ self .insert (e [0 ], e [1 ])
8485
8586 def switch (self , * , self_loop : bool = False , repeated_edges : bool = False ):
8687 """Mutates the current directed graph by swapping pairs of edges, without impacting the degree sequence.
@@ -94,8 +95,8 @@ def switch(self, *, self_loop: bool = False, repeated_edges: bool = False):
9495 first , second = random .choices (list (self .__edges .keys ()),
9596 list (self .__edges .values ()),
9697 k = 2 )
97- x1 , y1 = first
98- x2 , y2 = second
98+ x1 , y1 = first if self . directed else sorted ( first )
99+ x2 , y2 = second if self . directed else sorted ( second )
99100
100101 if self_loop :
101102 if x1 == x2 or y1 == y2 :
@@ -162,6 +163,51 @@ def from_directed_degree_sequence(
162163
163164 return ret
164165
166+ @staticmethod
167+ def from_undirected_degree_sequence (
168+ degree_sequence : Sequence [int ],
169+ start_id : int = 1 ,
170+ * ,
171+ self_loop : bool = False ,
172+ repeated_edges : bool = False ) -> "SwitchGraph" :
173+ if any (x < 0 for x in degree_sequence ):
174+ raise ValueError ("Degree sequence is not graphical." )
175+
176+ if sum (degree_sequence ) % 2 != 0 :
177+ raise ValueError ("Degree sequence is not graphical." )
178+
179+ if len (degree_sequence ) == 0 :
180+ return SwitchGraph ((), False )
181+
182+ degseq = [[deg , i ] for i , deg in enumerate (degree_sequence , start_id )]
183+ degseq .sort (reverse = True )
184+
185+ edges : List [Tuple [int , int ]] = []
186+ try :
187+ while len (edges ) * 2 < sum (degree_sequence ):
188+ deg , x = degseq [0 ]
189+ degseq [0 ][0 ] = 0
190+ if self_loop :
191+ while deg > 1 :
192+ deg -= 2
193+ edges .append ((x , x ))
194+ if not repeated_edges :
195+ break
196+ y = 1
197+ while deg :
198+ while deg and degseq [y ][0 ]:
199+ deg -= 1
200+ degseq [y ][0 ] -= 1
201+ edges .append ((x , degseq [y ][1 ]))
202+ if not repeated_edges :
203+ break
204+ y += 1
205+ degseq .sort (reverse = True )
206+ except IndexError :
207+ raise ValueError ("Degree sequence is not graphical." )
208+
209+ return SwitchGraph (edges , False )
210+
165211 def __iter__ (self ):
166212 return iter (self .__edges )
167213
0 commit comments