<s> """<STR_LIT>""" <EOL> from __future__ import division <EOL> import random <EOL> import networkx as nx <EOL> __all__ = [ '<STR_LIT>' , <EOL> '<STR_LIT>' ] <EOL> def is_valid_joint_degree ( joint_degrees ) : <EOL> """<STR_LIT>""" <EOL> degree_count = { } <EOL> for k in joint_degrees : <EOL> if k > <NUM_LIT:0> : <EOL> k_size = sum ( joint_degrees [ k ] . values ( ) ) / k <EOL> if not k_size . is_integer ( ) : <EOL> return False <EOL> degree_count [ k ] = k_size <EOL> for k in joint_degrees : <EOL> for l in joint_degrees [ k ] : <EOL> if not float ( joint_degrees [ k ] [ l ] ) . is_integer ( ) : <EOL> return False <EOL> if ( k != l ) and ( joint_degrees [ k ] [ l ] > <EOL> degree_count [ k ] * degree_count [ l ] ) : <EOL> return False <EOL> elif k == l : <EOL> if joint_degrees [ k ] [ k ] > degree_count [ k ] * ( degree_count [ k ] - <NUM_LIT:1> ) : <EOL> return False <EOL> if joint_degrees [ k ] [ k ] % <NUM_LIT:2> != <NUM_LIT:0> : <EOL> return False <EOL> return True <EOL> def _neighbor_switch ( G , w , unsat , h_node_residual , avoid_node_id = None ) : <EOL> """<STR_LIT>""" <EOL> if ( avoid_node_id is None ) or ( h_node_residual [ avoid_node_id ] > <NUM_LIT:1> ) : <EOL> w_prime = next ( iter ( unsat ) ) <EOL> else : <EOL> iter_var = iter ( unsat ) <EOL> while True : <EOL> w_prime = next ( iter_var ) <EOL> if w_prime != avoid_node_id : <EOL> break <EOL> w_prime_neighbs = G [ w_prime ] <EOL> for v in G [ w ] : <EOL> if ( v not in w_prime_neighbs ) and ( v != w_prime ) : <EOL> switch_node = v <EOL> break <EOL> G . remove_edge ( w , switch_node ) <EOL> G . add_edge ( w_prime , switch_node ) <EOL> h_node_residual [ w ] += <NUM_LIT:1> <EOL> h_node_residual [ w_prime ] -= <NUM_LIT:1> <EOL> if h_node_residual [ w_prime ] == <NUM_LIT:0> : <EOL> unsat . remove ( w_prime ) <EOL> def joint_degree_graph ( joint_degrees , seed = None ) : <EOL> """<STR_LIT>""" <EOL> if not is_valid_joint_degree ( joint_degrees ) : <EOL> msg = '<STR_LIT>' <EOL> raise nx . NetworkXError ( msg ) <EOL> if seed is not None : <EOL> random . seed ( seed ) <EOL> degree_count = { k : sum ( l . values ( ) ) // k for k , l in joint_degrees . items ( ) if k > <NUM_LIT:0> } <EOL> N = sum ( degree_count . values ( ) ) <EOL> G = nx . empty_graph ( N ) <EOL> h_degree_nodelist = { } <EOL> h_node_residual = { } <EOL> nodeid = <NUM_LIT:0> <EOL> for degree , num_nodes in degree_count . items ( ) : <EOL> h_degree_nodelist [ degree ] = range ( nodeid , nodeid + num_nodes ) <EOL> for v in h_degree_nodelist [ degree ] : <EOL> h_node_residual [ v ] = degree <EOL> nodeid += int ( num_nodes ) <EOL> for k in joint_degrees : <EOL> for l in joint_degrees [ k ] : <EOL> n_edges_add = joint_degrees [ k ] [ l ] <EOL> if ( n_edges_add > <NUM_LIT:0> ) and ( k >= l ) : <EOL> k_size = degree_count [ k ] <EOL> l_size = degree_count [ l ] <EOL> k_nodes = h_degree_nodelist [ k ] <EOL> l_nodes = h_degree_nodelist [ l ] <EOL> k_unsat = set ( v for v in k_nodes if h_node_residual [ v ] > <NUM_LIT:0> ) <EOL> if k != l : <EOL> l_unsat = set ( w for w in l_nodes if h_node_residual [ w ] > <NUM_LIT:0> ) <EOL> else : <EOL> l_unsat = k_unsat <EOL> n_edges_add = joint_degrees [ k ] [ l ] // <NUM_LIT:2> <EOL> while n_edges_add > <NUM_LIT:0> : <EOL> v = k_nodes [ random . randrange ( k_size ) ] <EOL> w = l_nodes [ random . randrange ( l_size ) ] <EOL> if not G . has_edge ( v , w ) and ( v != w ) : <EOL> if h_node_residual [ v ] == <NUM_LIT:0> : <EOL> _neighbor_switch ( G , v , k_unsat , h_node_residual ) <EOL> if h_node_residual [ w ] == <NUM_LIT:0> : <EOL> if k != l : <EOL> _neighbor_switch ( G , w , l_unsat , h_node_residual ) <EOL> else : <EOL> _neighbor_switch ( G , w , l_unsat , h_node_residual , avoid_node_id = v ) <EOL> G . add_edge ( v , w ) <EOL> h_node_residual [ v ] -= <NUM_LIT:1> <EOL> h_node_residual [ w ] -= <NUM_LIT:1> <EOL> n_edges_add -= <NUM_LIT:1> <EOL> if h_node_residual [ v ] == <NUM_LIT:0> : <EOL> k_unsat . discard ( v ) <EOL> if h_node_residual [ w ] == <NUM_LIT:0> : <EOL> l_unsat . discard ( w ) <EOL> G . name = "<STR_LIT>" % ( G . order ( ) ) <EOL> return G </s>
