def test_valid_degree_sequence2(): n = 100 for i in range(10): G = nx.barabasi_albert_graph(n,1) deg = list(G.degree().values()) assert_true( nx.is_valid_degree_sequence(deg, method='eg') ) assert_true( nx.is_valid_degree_sequence(deg, method='hh') )
def test_valid_degree_sequence2(): n = 100 for i in range(10): G = nx.barabasi_albert_graph(n, 1) deg = (d for n, d in G.degree()) assert_true(nx.is_valid_degree_sequence(deg, method="eg")) assert_true(nx.is_valid_degree_sequence(deg, method="hh"))
def test_valid_degree_sequence1(): n = 100 p = 0.3 for i in range(10): G = nx.erdos_renyi_graph(n, p) deg = (d for n, d in G.degree()) assert_true(nx.is_valid_degree_sequence(deg, method="eg")) assert_true(nx.is_valid_degree_sequence(deg, method="hh"))
def test_valid_degree_sequence1(): n = 100 p = .3 for i in range(10): G = nx.erdos_renyi_graph(n,p) deg = list(G.degree().values()) assert_true( nx.is_valid_degree_sequence(deg, method='eg') ) assert_true( nx.is_valid_degree_sequence(deg, method='hh') )
def gen_delta_graph(n, ks, ps, simple=False, model='conf'): ''' Generate a graph whose degree distribution is of finite support. Parameters ---------- n : number of nodes ks : list Degrees the nodes can have ps : list Probability for each edge, must have same length as ks and sum to 1 ''' # the following function generates a degree sequence of length n pkmap = choicemap(ks,ps) dseqfun = lambda n: [ nx.utils.weighted_choice(pkmap) for i in range(n) ] success = False while not success: dseq = dseqfun(n) if nx.is_valid_degree_sequence(dseq): success = True if model == 'conf': G = nx.configuration_model(dseq) elif model == 'chung-lu': G = nx.expected_degree_graph(dseq) else: raise Exception('wrong graph model requested') if simple: G = nx.Graph(G) # removes multi-edges G.remove_edges_from( G.selfloop_edges() ) # remove self loop return G
def generate_graph(type = 'PL', n = 100, seed = 1.0, parameter = 2.1): if type == 'ER': G = nx.erdos_renyi_graph(n, p=parameter, seed=seed, directed=True) G = nx.DiGraph(G) G.remove_edges_from(G.selfloop_edges()) elif type == 'PL': z = nx.utils.create_degree_sequence(n, nx.utils.powerlaw_sequence, exponent = parameter) while not nx.is_valid_degree_sequence(z): z = nx.utils.create_degree_sequence(n, nx.utils.powerlaw_sequence, exponent = parameter) G = nx.configuration_model(z) G = nx.DiGraph(G) G.remove_edges_from(G.selfloop_edges()) elif type == 'BA': G = nx.barabasi_albert_graph(n, 3, seed=None) G = nx.DiGraph(G) elif type == 'grid': G = nx.grid_2d_graph(int(np.ceil(np.sqrt(n))), int(np.ceil(np.sqrt(n)))) G = nx.DiGraph(G) elif type in ['facebook', 'enron', 'twitter', 'students', 'tumblr', 'facebookBig']: #print 'start reading' #_, G, _, _ = readRealGraph(os.path.join("..","..","Data", type+".txt")) _, G, _, _ = readRealGraph(os.path.join("..","Data", type+".txt")) print 'size of graph', G.number_of_nodes() #Gcc = sorted(nx.connected_component_subgraphs(G.to_undirected()), key = len, reverse=True) #print Gcc[0].number_of_nodes() #print 'num of connected components', len(sorted(nx.connected_component_subgraphs(G.to_undirected()), key = len, reverse=True)) #exit() if G.number_of_nodes() > n: G = getSubgraph(G, n) #G = getSubgraphSimulation(G, n, infP = 0.3) #nx.draw(G) #plt.show() return G
def seqGen(n): seq = [1, 2] #start with invalid deg seq while not nx.is_valid_degree_sequence(seq): seq = [] for x in range(0, n): seq.append(random.randint(1, 4)) return seq
def generate_simple_graph(sfunction, N, avg_degree): """generate a simple random graph with sfunction degree sequence""" graphical_deg_seq = False is_connected_graph = False while is_connected_graph == False: while graphical_deg_seq == False: seq = sfunction(N, avg_degree, seqtype="simple_degree") graphical_deg_seq = nx.is_valid_degree_sequence(seq) G = nx.havel_hakimi_graph(seq) G.remove_edges_from(G.selfloop_edges()) if not nx.is_connected(G): try: connect_simple_graph(G) is_connected_graph = True randomize_graph(G) except (IndexError): is_connected_graph = False if not nx.is_connected(G): try: connect_simple_graph(G) is_connected_graph = True except (IndexError): is_connected_graph = False graphical_deg_seq = False return G
def create_total_degree_sequence (n, sfunction, avg_degree, mod_nodes, tolerance, max_tries=2000, **kwds): """ Creates a total-degree sequence.Ensures that the minimum degree is 1 and the max degree is 1 less than the number of nodes and that the average degree of the sequence generated is within a tolerance of 0.05. `n`: number of nodes `sfunction`: a sequence generating function with signature (number of nodes, mean) `avg_degree`: mean degree `max_tries`: maximum number of tries before dying. 8Nov 2013: function now assigns total degree to the nodes module-wise, to ensure that mean(d(k))= mean(d). ie., mean degree of each module is equal to the network mean degree """ seqlist=[] # this loop assumes modules are indexed sequentially from 0 to K-1 for mod in xrange(len(mod_nodes.keys())): tries = 0 max_deg = len(mod_nodes[mod]) -1 is_valid_seq = False tol = 5.0 while tol > tolerance or (not is_valid_seq) or (tries > max_tries): trialseq = sfunction(len(mod_nodes[mod]), avg_degree, seqtype="degree") seq = [min(max_deg, max( int(round(s)), 1 )) for s in trialseq] is_valid_seq = nx.is_valid_degree_sequence(seq) if not is_valid_seq and sum(seq)%2 !=0: x = rnd.choice(xrange(len(seq))) seq[x] += 1 is_valid_seq = nx.is_valid_degree_sequence(seq) # check if d_k (bar) = d(bar) tol = abs(avg_degree - np.mean(seq)) tries += 1 if (tries > max_tries): raise nx.NetworkXError, \ "Exceeded max (%d) attempts at a valid sequence."%max_tries seqlist.append(seq) deg_list = [val for sublist in seqlist for val in sublist] return deg_list
def __init__(self, degree, seed=None): if not nx.is_valid_degree_sequence(degree): raise nx.NetworkXUnfeasible('degree sequence is not graphical') if seed is not None: random.seed(seed) self.degree = list(degree) # node labels are integers 0,...,n-1 self.m = sum(self.degree)/2.0 # number of edges try: self.dmax = max(self.degree) # maximum degree except ValueError: self.dmax = 0
def test_small_graph_false(): z=[1000,3,3,3,3,2,2,2,1,1,1] assert_false(nx.is_valid_degree_sequence(z, method='hh')) assert_false(nx.is_valid_degree_sequence(z, method='eg')) z=[6,5,4,4,2,1,1,1] assert_false(nx.is_valid_degree_sequence(z, method='hh')) assert_false(nx.is_valid_degree_sequence(z, method='eg')) z=[1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4] assert_false(nx.is_valid_degree_sequence(z, method='hh')) assert_false(nx.is_valid_degree_sequence(z, method='eg'))
def test_small_graph_true(): z=[5,3,3,3,3,2,2,2,1,1,1] assert_true(nx.is_valid_degree_sequence(z, method='hh')) assert_true(nx.is_valid_degree_sequence(z, method='eg')) z=[10,3,3,3,3,2,2,2,2,2,2] assert_true(nx.is_valid_degree_sequence(z, method='hh')) assert_true(nx.is_valid_degree_sequence(z, method='eg')) z=[1, 1, 1, 1, 1, 2, 2, 2, 3, 4] assert_true(nx.is_valid_degree_sequence(z, method='hh')) assert_true(nx.is_valid_degree_sequence(z, method='eg'))
def undirected_degree_preserving_random_graph(degreeSequence): """Returns a random graph with n nodes, with the degree distribution same as that given by the argument ``degreeSequence``. """ assert (nx.is_valid_degree_sequence(degreeSequence)) num_nodes = len(degreeSequence) G = nx.empty_graph(num_nodes, create_using) num_degrees = [] for i in range(num_nodes): num_degrees.append([]) dmax, dsum, n = 0, 0, 0 for d in degreeSequence: if d > 0: num_degrees[d].append(n) dmax, dsum, n = max(dmax, d), dsum + d, n + 1 if n == 0: return G modstubs = [(0, 0)] * (dmax + 1) while n > 0: while len(num_degrees[dmax]) == 0: dmax -= 1 if dmax > n - 1: raise nx.NetworkXError( 'Sequence provided cannot be used on a graph.') source = num_degrees[dmax].pop() n -= 1 mslen = 0 k = dmax for i in range(dmax): while len(num_degrees[k]) == 0: k -= 1 target = num_degrees[k].pop() G.add_edge(source, target) n -= 1 if k > 1: modstubs[mslen] = (k - 1, target) mslen += 1 for i in range(mslen): (stubval, stubtarget) = modstubs[i] num_degrees[stubval].append(stubtarget) n += 1 return G
def scale_free_powerlaw(n=4000, lam=3, k_avg=4): """ n : number of nodes lam : exponent """ noftries = 2147483647 standard = k_avg + 0.5 while (1): s = generate(n, lam) ratio = standard / np.mean(s) for i in range(len(s)): s[i] = int(ratio * s[i]) if (nx.is_valid_degree_sequence(s)): G = nx.random_degree_sequence_graph(s, tries=noftries) break return G
def GenGraph(Nodes_CC,Lambda): import numpy as np import networkx as nx Lmin=min(1,len(Nodes_CC)) Lmax=len(Nodes_CC)-1 flag=0 if len(Nodes_CC)==1: D=[0] while len(Nodes_CC)!=1 and flag==0: D=[Distribution(Lmin,Lmax,Lambda) for i in range(0,len(Nodes_CC))] if nx.is_valid_degree_sequence(D, method='eg') ==True: # eg:Erdős-Gallai hh: Havel-Hakimi flag=1 return D
def create_degree_sequence(n, sfunction=None, max_tries=50, **kwds): _warnings.warn("create_degree_sequence() is deprecated", DeprecationWarning) """ Attempt to create a valid degree sequence of length n using specified function sfunction(n,**kwds). Parameters ---------- n : int Length of degree sequence = number of nodes sfunction: function Function which returns a list of n real or integer values. Called as "sfunction(n,**kwds)". max_tries: int Max number of attempts at creating valid degree sequence. Notes ----- Repeatedly create a degree sequence by calling sfunction(n,**kwds) until achieving a valid degree sequence. If unsuccessful after max_tries attempts, raise an exception. For examples of sfunctions that return sequences of random numbers, see networkx.Utils. Examples -------- >>> from networkx.utils import uniform_sequence, create_degree_sequence >>> seq=create_degree_sequence(10,uniform_sequence) """ tries=0 max_deg=n while tries < max_tries: trialseq=sfunction(n,**kwds) # round to integer values in the range [0,max_deg] seq=[min(max_deg, max( int(round(s)),0 )) for s in trialseq] # if graphical return, else throw away and try again if nx.is_valid_degree_sequence(seq): return seq tries+=1 raise nx.NetworkXError(\ "Exceeded max (%d) attempts at a valid sequence."%max_tries)
def generate_graph(type='PL', n=100, seed=1.0, parameter=2.1): if type == 'ER': G = nx.erdos_renyi_graph(n, p=parameter, seed=seed, directed=True) G = nx.DiGraph(G) G.remove_edges_from(G.selfloop_edges()) elif type == 'PL': z = nx.utils.create_degree_sequence(n, nx.utils.powerlaw_sequence, exponent=parameter) while not nx.is_valid_degree_sequence(z): z = nx.utils.create_degree_sequence(n, nx.utils.powerlaw_sequence, exponent=parameter) G = nx.configuration_model(z) G = nx.DiGraph(G) G.remove_edges_from(G.selfloop_edges()) elif type == 'BA': G = nx.barabasi_albert_graph(n, 3, seed=None) G = nx.DiGraph(G) elif type == 'grid': G = nx.grid_2d_graph(int(np.ceil(np.sqrt(n))), int(np.ceil(np.sqrt(n)))) G = nx.DiGraph(G) elif type in [ 'facebook', 'enron', 'twitter', 'students', 'tumblr', 'facebookBig' ]: #print 'start reading' #_, G, _, _ = readRealGraph(os.path.join("..","..","Data", type+".txt")) _, G, _, _ = readRealGraph(os.path.join("..", "Data", type + ".txt")) print 'size of graph', G.number_of_nodes() #Gcc = sorted(nx.connected_component_subgraphs(G.to_undirected()), key = len, reverse=True) #print Gcc[0].number_of_nodes() #print 'num of connected components', len(sorted(nx.connected_component_subgraphs(G.to_undirected()), key = len, reverse=True)) #exit() if G.number_of_nodes() > n: G = getSubgraph(G, n) #G = getSubgraphSimulation(G, n, infP = 0.3) #nx.draw(G) #plt.show() return G
Random graph from given degree sequence. Draw degree histogram with matplotlib. """ __author__ = """Aric Hagberg ([email protected])""" try: import matplotlib.pyplot as plt import matplotlib except: raise import networkx as nx z=nx.utils.create_degree_sequence(100,nx.utils.powerlaw_sequence,exponent=2.1) nx.is_valid_degree_sequence(z) print "Configuration model" G=nx.configuration_model(z) # configuration model degree_sequence=sorted(nx.degree(G).values(),reverse=True) # degree sequence #print "Degree sequence", degree_sequence dmax=max(degree_sequence) plt.loglog(degree_sequence,'b-',marker='o') plt.title("Degree rank plot") plt.ylabel("degree") plt.xlabel("rank") # draw graph in inset plt.axes([0.45,0.45,0.45,0.45])
def test_iterable(): G = nx.path_graph(4) seq = iter(G.degree().values()) assert_true(nx.is_valid_degree_sequence(seq, method='hh')) assert_true(nx.is_valid_degree_sequence(seq, method='eg'))
def test_negative_input(): assert_false(nx.is_valid_degree_sequence([-1],'hh')) assert_false(nx.is_valid_degree_sequence([-1],'eg')) assert_false(nx.is_valid_degree_sequence([72.5],'eg'))
def test_string_input(): a = nx.is_valid_degree_sequence([],'foo')
def havel_hakimi_graph(deg_sequence,create_using=None): """Return a simple graph with given degree sequence constructed using the Havel-Hakimi algorithm. Parameters ---------- deg_sequence: list of integers Each integer corresponds to the degree of a node (need not be sorted). create_using : graph, optional (default Graph) Return graph of this type. The instance will be cleared. Directed graphs are not allowed. Raises ------ NetworkXException For a non-graphical degree sequence (i.e. one not realizable by some simple graph). Notes ----- The Havel-Hakimi algorithm constructs a simple graph by successively connecting the node of highest degree to other nodes of highest degree, resorting remaining nodes by degree, and repeating the process. The resulting graph has a high degree-associativity. Nodes are labeled 1,.., len(deg_sequence), corresponding to their position in deg_sequence. The basic algorithm is from Hakimi [1]_ and was generalized by Kleitman and Wang [2]_. References ---------- .. [1] Hakimi S., On Realizability of a Set of Integers as Degrees of the Vertices of a Linear Graph. I, Journal of SIAM, 10(3), pp. 496-506 (1962) .. [2] Kleitman D.J. and Wang D.L. Algorithms for Constructing Graphs and Digraphs with Given Valences and Factors Discrete Mathematics, 6(1), pp. 79-88 (1973) """ if not nx.is_valid_degree_sequence(deg_sequence): raise nx.NetworkXError('Invalid degree sequence') if create_using is not None: if create_using.is_directed(): raise nx.NetworkXError("Directed graphs are not supported") p = len(deg_sequence) G=nx.empty_graph(p,create_using) num_degs = [] for i in range(p): num_degs.append([]) dmax, dsum, n = 0, 0, 0 for d in deg_sequence: # Process only the non-zero integers if d>0: num_degs[d].append(n) dmax, dsum, n = max(dmax,d), dsum+d, n+1 # Return graph if no edges if n==0: return G modstubs = [(0,0)]*(dmax+1) # Successively reduce degree sequence by removing the maximum degree while n > 0: # Retrieve the maximum degree in the sequence while len(num_degs[dmax]) == 0: dmax -= 1 # If there are not enough stubs to connect to, then the sequence is # not graphical if dmax > n-1: raise nx.NetworkXError('Non-graphical integer sequence') # Remove largest stub in list source = num_degs[dmax].pop() n -= 1 # Reduce the next dmax largest stubs mslen = 0 k = dmax for i in range(dmax): while len(num_degs[k]) == 0: k -= 1 target = num_degs[k].pop() G.add_edge(source, target) n -= 1 if k > 1: modstubs[mslen] = (k-1,target) mslen += 1 # Add back to the list any nonzero stubs that were removed for i in range(mslen): (stubval, stubtarget) = modstubs[i] num_degs[stubval].append(stubtarget) n += 1 G.name="havel_hakimi_graph %d nodes %d edges"%(G.order(),G.size()) return G
import numpy as np import networkx as nx import matplotlib.pyplot as plt import random DOPART1 = 1 DOPART2 = 1 #calculate mean fractional size per part 1, Q6 if (DOPART1): NUMBERITERATIONS = 2663 #confidence level-99, confidence interval-2.5 resultsArray = np.zeros(NUMBERITERATIONS) for index in range(0, NUMBERITERATIONS): degreeSequence = [0] * 1000 degreeSequence[0] = 1 while (not nx.is_valid_degree_sequence(degreeSequence)): for index2 in range(0, 1000): #generate degree sequence rollTheDice = random.random() if (rollTheDice <= .6): degreeSequence[index2] = 1 else: degreeSequence[index2] = 3 graph = nx.configuration_model(degreeSequence) resultsArray[index] = len( max(nx.connected_component_subgraphs(graph), key=len)) print "mean of largest component after", NUMBERITERATIONS, "iterations =", np.mean( resultsArray) print "mean fractional size =", np.mean(resultsArray) / 1000 if (DOPART2): NUMBERITERATIONS = 666 #confidence level-99, confindence interval-5
dataset_tag=sys.argv[3] num_iter=int(sys.argv[4]); else: print('Input is required as:\n 1) full edgelist filename \n 2) name of output directory \n 3) name tag for output files \n 4) number of iterations'); sys.exit(); if not os.path.exists(dir): os.makedirs(dir) G=nx.read_weighted_edgelist(original_graph) boo = nx.is_valid_degree_sequence(G.degree().values()) if boo == False: print 'la successione dei gradi non e valida' GD = nx.configuration_model(G.degree().values()) GD.remove_edges_from(GD.selfloop_edges()) GD = nx.Graph(GD) ww = nx.utils.powerlaw_sequence(GD.number_of_edges()) m = min(ww) M = max(ww) def new_weights(ww): return [(ww[i]-m)/(M-m) for i in range(len(ww))]
def li_smax_graph(degree_seq, create_using=None): """Generates a graph based with a given degree sequence and maximizing the s-metric. Experimental implementation. Maximum s-metrix means that high degree nodes are connected to high degree nodes. - `degree_seq`: degree sequence, a list of integers with each entry corresponding to the degree of a node. A non-graphical degree sequence raises an Exception. Reference:: @unpublished{li-2005, author = {Lun Li and David Alderson and Reiko Tanaka and John C. Doyle and Walter Willinger}, title = {Towards a Theory of Scale-Free Graphs: Definition, Properties, and Implications (Extended Version)}, url = {http://arxiv.org/abs/cond-mat/0501169}, year = {2005} } The algorithm:: STEP 0 - Initialization A = {0} B = {1, 2, 3, ..., n} O = {(i; j), ..., (k, l),...} where i < j, i <= k < l and d_i * d_j >= d_k *d_l wA = d_1 dB = sum(degrees) STEP 1 - Link selection (a) If |O| = 0 TERMINATE. Return graph A. (b) Select element(s) (i, j) in O having the largest d_i * d_j , if for any i or j either w_i = 0 or w_j = 0 delete (i, j) from O (c) If there are no elements selected go to (a). (d) Select the link (i, j) having the largest value w_i (where for each (i, j) w_i is the smaller of w_i and w_j ), and proceed to STEP 2. STEP 2 - Link addition Type 1: i in A and j in B. Add j to the graph A and remove it from the set B add a link (i, j) to the graph A. Update variables: wA = wA + d_j -2 and dB = dB - d_j Decrement w_i and w_j with one. Delete (i, j) from O Type 2: i and j in A. Check Tree Condition: If dB = 2 * |B| - wA. Delete (i, j) from O, continue to STEP 3 Check Disconnected Cluster Condition: If wA = 2. Delete (i, j) from O, continue to STEP 3 Add the link (i, j) to the graph A Decrement w_i and w_j with one, and wA = wA -2 STEP 3 Go to STEP 1 The article states that the algorithm will result in a maximal s-metric. This implementation can not guarantee such maximality. I may have misunderstood the algorithm, but I can not see how it can be anything but a heuristic. Please contact me at [email protected] if you can provide python code that can guarantee maximality. Several optimizations are included in this code and it may be hard to read. Commented code to come. A POSSIBLE ALTERNATIVE: For an 'unconstrained' graph, that is one they describe as having the sum of the degree sequence be even(ie all undirected graphs) they present a simpler algorithm. It is as follows "For each vertex i: if di is even then attach di/2 self-loops; if di is odd, then attach (di-1)/2 self-loops, leaving one available "stub". Second for all remaining vertices with "stubs" connect them in pairs according to decreasing values of di."[1] Since this only works for undirected graphs anyway, perhaps this is the better method? Note this also returns a graph with a larger s_metric than the other method, and it seems to have the same degree sequence, though I haven't tested it extensively. """ if not nx.is_valid_degree_sequence(degree_seq): raise nx.NetworkXError('Invalid degree sequence') if create_using is not None and create_using.is_directed(): raise nx.NetworkXError("Directed Graph not supported") degree_seq.sort(reverse=True) # make sure it's sorted if not (sum(degree_seq) %2): #check if the sum of the degree sequence is even, Should be if it is undirected dseven = [di for di in degree_seq if (not di % 2)] dsodd = [di for di in degree_seq if (di % 2)] Gmax = nx.MultiGraph() i = 0 for di in dseven: Gmax.add_node(i) for k in range(di // 2): Gmax.add_edge(i,i) i=i+1 for j in range(0,len(dsodd),2): #do this iteratively to connect Gmax.add_node(i) #node stubs as we go Gmax.add_node(i+1) for k in range((dsodd[j]-1) // 2): Gmax.add_edge(i,i) for k in range((dsodd[j+1]-1) // 2): Gmax.add_edge(i+1,i+1) Gmax.add_edge(i,i+1) i=i+2 return Gmax else: degrees_left = degree_seq[:] A_graph = empty_graph(0,create_using) A_graph.add_node(0) a_list = [False]*len(degree_seq) b_set = set(range(1,len(degree_seq))) a_open = set([0]) O = [] for j in b_set: heapq.heappush(O, (-degree_seq[0]*degree_seq[j], (0,j))), wa = degrees_left[0] #stubs in a_graph db = sum(degree_seq) - degree_seq[0] #stubs in b-graph a_list[0] = True #node 0 is now in a_Graph bsize = len(degree_seq) -1 #size of b_graph selected = [] weight = 0 while O or selected: if len(selected) <1 : firstrun = True while O: (newweight, (i,j)) = heapq.heappop(O) if degrees_left[i] < 1 or degrees_left[j] < 1 : continue if firstrun: firstrun = False weight = newweight if not newweight == weight: break heapq.heappush(selected, [-degrees_left[i], \ -degrees_left[j], (i,j)]) if not weight == newweight: heapq.heappush(O,(newweight, (i,j))) weight *= -1 if len(selected) < 1: break [w1, w2, (i,j)] = heapq.heappop(selected) if degrees_left[i] < 1 or degrees_left[j] < 1 : continue if a_list[i] and j in b_set: #TYPE1 a_list[j] = True b_set.remove(j) A_graph.add_node(j) A_graph.add_edge(i, j) degrees_left[i] -= 1 degrees_left[j] -= 1 wa += degree_seq[j] - 2 db -= degree_seq[j] bsize -= 1 newweight = weight if not degrees_left[j] == 0: a_open.add(j) for k in b_set: if A_graph.has_edge(j, k): continue w = degree_seq[j]*degree_seq[k] if w > newweight: newweight = w if weight == w and not newweight > weight: heapq.heappush(selected, [-degrees_left[j], \ -degrees_left[k], (j,k)]) else: heapq.heappush(O, (-w, (j,k))) if not weight == newweight: while selected: [w1,w2,(i,j)] = heapq.heappop(selected) if degrees_left[i]*degrees_left[j] > 0: heapq.heappush(O, [-degree_seq[i]*degree_seq[j],(i,j)]) if degrees_left[i] == 0: a_open.discard(i) else: #TYPE2 if db == (2*bsize - wa): #tree condition #print "removing because tree condition " continue elif db < 2*bsize -wa: raise nx.NetworkXError(\ "THIS SHOULD NOT HAPPEN!-not graphable") continue elif wa == 2 and bsize > 0: #print "removing because disconnected cluster" #disconnected cluster condition continue elif wa == db - (bsize)*(bsize-1): #print "MYOWN removing because disconnected cluster" continue A_graph.add_edge(i, j) degrees_left[i] -= 1 degrees_left[j] -= 1 if degrees_left[i] < 1: a_open.discard(i) if degrees_left[j] < 1: a_open.discard(j) wa -= 2 if not degrees_left[i] < 0 and not degrees_left[j] < 0: selected2 = (selected) selected = [] while selected2: [w1,w1, (i,j)] = heapq.heappop(selected2) if degrees_left[i]*degrees_left[j] > 0: heapq.heappush(selected, [-degrees_left[i], \ -degrees_left[j], (i,j)]) return A_graph
def create_indegree_sequence(n, m, sfunction, mod_nodes, wd, degree_list, tolerance, **kwds): """ Creates indegree sequence. Ensures that (i)the within-module degree of node is less than or equal to its total degree; (ii) the within-module degree sequence is graphical nodes; and (iii) the average within module degree of the sequence generated is within a tolerance of 0.05 'n': number of nodes 'sfunction': a sequence generating function with signature (number of nodes, mean) 'wd' = mean within-module degree, m= total modules in the network 'nc'=average community size 'mod_nodes'= dictionary of nodal membership to communities 'avg_degree': mean degree 'degree_list'= total degree sequence """ is_valid_seq = False is_valid_indegree = False is_valid_module_size = False is_valid_outdegree = True tol = 5.0 connect_trial = 0 # Return empty list if the main loop breaks indegree_list = [] while (not is_valid_seq) or (not is_valid_indegree) or (not is_valid_module_size) or (not is_valid_outdegree): indegree_seq = sfunction(n, wd, seqtype="indegree") indegree_sort = list(np.sort(indegree_seq)) degree_sort = list(np.sort(degree_list)) is_valid_indegree = all([indegree_sort[i] <= degree_sort[i] for i in range(n)]) == True mod_sizes = [len(mod_nodes[x]) for x in mod_nodes.keys()] is_valid_module_size = min(mod_sizes) >= max(indegree_seq) is_valid_seq = True if not is_valid_module_size: connect_trial += 1 if is_valid_indegree and is_valid_seq and is_valid_module_size: # assign within-degree to a node such that wd(i)<=d(i) indegree_list = sort_inedge(indegree_sort, degree_sort, degree_list, n) # if network has two modules then sum(outdegree) for module 1 has to be equal to sum(outdegree) of module 2 if m == 2: mod1, mod2 = mod_nodes.keys() is_valid_outdegree = sum([(degree_list[i] - indegree_list[i]) for i in mod_nodes[mod1]]) == sum( [(degree_list[i] - indegree_list[i]) for i in mod_nodes[mod2]] ) for module in mod_nodes: seq = [indegree_list[i] for i in mod_nodes[module]] while (sum(seq) % 2) != 0: # choose a random node in the module node_add_degree = rnd.choice([i for i in mod_nodes[module]]) # ensure that wd<=d and wd< (module size -1)after adding a within-degree to the node if indegree_list[node_add_degree] < degree_list[node_add_degree] and indegree_list[ node_add_degree ] < len(mod_nodes[module]): indegree_list[node_add_degree] += 1 seq = [indegree_list[i] for i in mod_nodes[module]] is_valid_seq = nx.is_valid_degree_sequence(seq) tol = abs(wd - (sum(seq) / (1.0 * len(seq)))) # ensure that wd_k(bar) = wd(bar) if (not is_valid_seq) and tol > tolerance: break if connect_trial > 10: break return indegree_list
def havel_hakimi_graph(deg_sequence,create_using=None): """Return a simple graph with given degree sequence constructed using the Havel-Hakimi algorithm. Parameters ---------- deg_sequence: list of integers Each integer corresponds to the degree of a node (need not be sorted). create_using : graph, optional (default Graph) Return graph of this type. The instance will be cleared. Multigraphs and directed graphs are not allowed. Raises ------ NetworkXException For a non-graphical degree sequence (i.e. one not realizable by some simple graph). Notes ----- The Havel-Hakimi algorithm constructs a simple graph by successively connecting the node of highest degree to other nodes of highest degree, resorting remaining nodes by degree, and repeating the process. The resulting graph has a high degree-associativity. Nodes are labeled 1,.., len(deg_sequence), corresponding to their position in deg_sequence. See Theorem 1.4 in [1]_. This algorithm is also used in the function is_valid_degree_sequence. References ---------- .. [1] G. Chartrand and L. Lesniak, "Graphs and Digraphs", Chapman and Hall/CRC, 1996. """ if not nx.is_valid_degree_sequence(deg_sequence): raise nx.NetworkXError('Invalid degree sequence') if create_using is not None: if create_using.is_directed(): raise nx.NetworkXError("Directed Graph not supported") if create_using.is_multigraph(): raise nx.NetworkXError("Havel-Hakimi requires simple graph") N=len(deg_sequence) G=nx.empty_graph(N,create_using) if N==0 or max(deg_sequence)==0: # done if no edges return G # form list of [stubs,name] for each node. stublist=[ [deg_sequence[n],n] for n in G] # Now connect the stubs while stublist: stublist.sort() if stublist[0][0]<0: # took too many off some vertex return False # should not happen if deg_seq is valid (freestubs,source) = stublist.pop() # the node with the most stubs if freestubs==0: break # the rest must also be 0 --Done! if freestubs > len(stublist): # Trouble--can't make that many edges return False # should not happen if deg_seq is valid # attach edges to biggest nodes for stubtarget in stublist[-freestubs:]: G.add_edge(source, stubtarget[1]) stubtarget[0] -= 1 # updating stublist on the fly G.name="havel_hakimi_graph %d nodes %d edges"%(G.order(),G.size()) return G
def havel_hakimi_graph(deg_sequence, create_using=None): """Return a simple graph with given degree sequence constructed using the Havel-Hakimi algorithm. Parameters ---------- deg_sequence: list of integers Each integer corresponds to the degree of a node (need not be sorted). create_using : graph, optional (default Graph) Return graph of this type. The instance will be cleared. Multigraphs and directed graphs are not allowed. Raises ------ NetworkXException For a non-graphical degree sequence (i.e. one not realizable by some simple graph). Notes ----- The Havel-Hakimi algorithm constructs a simple graph by successively connecting the node of highest degree to other nodes of highest degree, resorting remaining nodes by degree, and repeating the process. The resulting graph has a high degree-associativity. Nodes are labeled 1,.., len(deg_sequence), corresponding to their position in deg_sequence. See Theorem 1.4 in [1]_. This algorithm is also used in the function is_valid_degree_sequence. References ---------- .. [1] G. Chartrand and L. Lesniak, "Graphs and Digraphs", Chapman and Hall/CRC, 1996. """ if not nx.is_valid_degree_sequence(deg_sequence): raise nx.NetworkXError('Invalid degree sequence') if create_using is not None: if create_using.is_directed(): raise nx.NetworkXError("Directed Graph not supported") if create_using.is_multigraph(): raise nx.NetworkXError("Havel-Hakimi requires simple graph") N = len(deg_sequence) G = nx.empty_graph(N, create_using) if N == 0 or max(deg_sequence) == 0: # done if no edges return G # form list of [stubs,name] for each node. stublist = [[deg_sequence[n], n] for n in G] # Now connect the stubs while stublist: stublist.sort() if stublist[0][0] < 0: # took too many off some vertex return False # should not happen if deg_seq is valid (freestubs, source) = stublist.pop() # the node with the most stubs if freestubs == 0: break # the rest must also be 0 --Done! if freestubs > len(stublist): # Trouble--can't make that many edges return False # should not happen if deg_seq is valid # attach edges to biggest nodes for stubtarget in stublist[-freestubs:]: G.add_edge(source, stubtarget[1]) stubtarget[0] -= 1 # updating stublist on the fly G.name = "havel_hakimi_graph %d nodes %d edges" % (G.order(), G.size()) return G
def test_atlas(): for graph in nx.graph_atlas_g(): deg = list(graph.degree().values()) assert_true( nx.is_valid_degree_sequence(deg, method='eg') ) assert_true( nx.is_valid_degree_sequence(deg, method='hh') )
def test_negative_input(): assert_false(nx.is_valid_degree_sequence([-1], "hh")) assert_false(nx.is_valid_degree_sequence([-1], "eg")) assert_false(nx.is_valid_degree_sequence([72.5], "eg"))
def test_atlas(self): for graph in self.GAG: deg = (d for n, d in graph.degree()) assert_true(nx.is_valid_degree_sequence(deg, method="eg")) assert_true(nx.is_valid_degree_sequence(deg, method="hh"))
dataset_tag=sys.argv[3] num_iter=int(sys.argv[4]); else: print('Input is required as:\n 1) full edgelist filename \n 2) name of output directory \n 3) name tag for output files \n 4) number of iterations'); sys.exit(); if not os.path.exists(dir): os.makedirs(dir) G=nx.read_weighted_edgelist(original_graph) boo = nx.is_valid_degree_sequence(G.degree().values()) if boo == False: print 'la successione dei gradi non e valida' GD = nx.configuration_model(G.degree().values()) GD.remove_edges_from(GD.selfloop_edges()) GD = nx.Graph(GD) ww = nx.utils.powerlaw_sequence(GD.number_of_edges(), 2.6) m = min(ww) M = max(ww) def new_weights(ww): return [(ww[i]-m)/(M-m) for i in range(len(ww))]
def test_atlas(self): for graph in self.GAG: deg = (d for n, d in graph.degree()) assert_true( nx.is_valid_degree_sequence(deg, method='eg') ) assert_true( nx.is_valid_degree_sequence(deg, method='hh') )
def setup_network(num_of_banks, num_of_assets, round_rvs, kind='man_half_half', p=2.5, min_holdings=10, single_net=False, project_network=False, av_deg=False, add_fedfunds=None): if not single_net: if kind == 'er': # np.random.seed(1) if av_deg: G = nx.bipartite.random_graph(num_of_banks, num_of_assets, av_deg/num_of_banks) # ,seed=1 else: G = nx.bipartite.random_graph(num_of_banks, num_of_assets, np.mean(round_rvs)/num_of_banks) # ,seed=1 if not nx.is_connected(G): G = max(nx.connected_component_subgraphs(G), key=len) bot, top = nx.bipartite.sets(G) assets = {t: 'a' + str(t-num_of_banks) for t in top} banks = {b: 'b' + str(b) for b in bot} z = assets.copy() z.update(banks) nx.relabel_nodes(G, z, copy=False) for node, data in G.nodes(data=True): if node.startswith('b'): data['kind'] = 'bank' elif node.startswith('a'): data['kind'] = 'asset' # print 'random: ', average_degree(G), len(G) elif kind == 'powpow': G = nx.bipartite.configuration_model(map(int, round_rvs), map(int, round_rvs), create_using=nx.Graph()) bot, top = nx.bipartite.sets(G) assets = {t: 'a' + str(t-num_of_banks) for t in top} banks = {b: 'b' + str(b) for b in bot} z = assets.copy() z.update(banks) nx.relabel_nodes(G, z, copy=False) for node,data in G.nodes(data=True): if node.startswith('b'): data['kind'] = 'bank' else: data['kind'] = 'asset' # print 'powpow: ', average_degree(G) elif kind == 'man_half_half': banks = ['b'+str(i) for i in range(num_of_banks)] assets = ['a'+str(i) for i in range(num_of_assets)] G = nx.Graph() G.add_nodes_from(banks,kind='bank') G.add_nodes_from(assets,kind='asset') # np.random.seed(1) for i,j in enumerate(round_rvs): G.add_edges_from([('b'+str(i),'a'+str(k)) for k in np.random.choice(num_of_assets,int(j),replace=False)]) # print 'power law: ', average_degree(G) elif kind == 'auto_half_and_half': temp_rvs = round_rvs[:-1] # np.random.seed(1) while True: pois = np.random.poisson(np.mean(round_rvs),num_of_assets) pd.Series(pois).hist() rem = sum(pois)-sum(temp_rvs) if rem < 0: continue else: if ((p-1)*(min_holdings**(p-1)))*(rem**(-p)) > 0.0001: round_rvs[-1] = rem break else: continue G = nx.bipartite.configuration_model(map(int, round_rvs), map(int, pois), create_using=nx.Graph()) bot,top = nx.bipartite.sets(G) assets = {t: 'a' + str(t-num_of_banks) for t in top} banks = {b: 'b' + str(b) for b in bot} z = assets.copy() z.update(banks) nx.relabel_nodes(G,z,copy=False) for node,data in G.nodes(data=True): if node.startswith('b'): data['kind'] = 'bank' else: data['kind'] = 'asset' # print 'auto_h_h: ', average_degree(G) if project_network: G = nx.bipartite.project(G,[node for node,data in G.nodes(data=True) if data['kind']=='bank']) for node,data in G.nodes(data=True): data['init_deg'] = G.degree(node) else: if add_fedfunds: G.add_node('f01') new_edges = [('f01', 'b'+str(i)) for i in random.sample(range(num_of_banks), add_fedfunds)] G.add_edges_from(new_edges) G.node['f01']['kind'] = 'fed' else: if kind == 'er': # np.random.seed(1) G = nx.fast_gnp_random_graph(num_of_banks, np.mean(round_rvs)/num_of_banks) elif kind == 'man_half_half': if not nx.is_valid_degree_sequence(map(int,round_rvs)): round_rvs[0] += 1 G = nx.configuration_model(map(int, round_rvs), create_using=nx.Graph()) banks = {b: 'b' + str(b) for b in range(num_of_banks)} nx.relabel_nodes(G, banks, copy=False) for node, data in G.nodes(data=True): data['kind'] = 'bank' for node,data in G.nodes(data=True): data['init_deg'] = G.degree(node) return G
Random graph from given degree sequence. Draw degree histogram with matplotlib. """ __author__ = """Aric Hagberg ([email protected])""" try: import matplotlib.pyplot as plt import matplotlib except: raise import networkx as nx z=nx.create_degree_sequence(100,nx.utils.powerlaw_sequence,exponent=2.1) nx.is_valid_degree_sequence(z) print "Configuration model" G=nx.configuration_model(z) # configuration model degree_sequence=sorted(nx.degree(G).values(),reverse=True) # degree sequence #print "Degree sequence", degree_sequence dmax=max(degree_sequence) plt.loglog(degree_sequence,'b-',marker='o') plt.title("Degree rank plot") plt.ylabel("degree") plt.xlabel("rank") # draw graph in inset plt.axes([0.45,0.45,0.45,0.45])
def __init__(self, population,degree_seq=None,m=None): # Create a population of agents self.agents=list() if type(population)==int and population>0: for a in range(population): self.agents.append(Agent(agent_id=a)) else: raise ValueError("Model must have positive number of agents") # Get total wealth in state self.state_wealth=sum(map(lambda a: a.get_wealth(),self.agents)) if m is None: self.threshold=.25*self.state_wealth else: if m>=0 and m<=1: self.threshold=m*self.state_wealth else: raise ValueError("Value for m must be between 0 and 1") # Create network if degree_seq is None: # If no degree sequence is provided create wealth-based preferential attachment # This is the default setting for the model for i in xrange(population): for j in xrange(population): if i!=j: prob_tie=uniform(low=0,high=1) # Tie probability function of agent's wealth relative to # total wealth in state if prob_tie<=self.agents[j].get_wealth()/self.state_wealth: # Create symmetric ties between neighbors self.agents[i].make_tie(self.agents[j]) self.agents[j].make_tie(self.agents[i]) else: if(nx.is_valid_degree_sequence(degree_seq) and len(degree_seq)==population): # Use NX configuration model to create network from degree sequence. By default, # the configuration model returns a MultiGraph type with edges assigned at random. # For consistency, the network type returned is Graph, and the random seed is # always set to the number of agents in the environment. G=nx.generators.configuration_model(degree_seq,create_using=nx.Graph(),seed=population) for e in G.edges(): self.agents[e[0]].make_tie(self.agents[e[1]]) self.agents[e[1]].make_tie(self.agents[e[0]]) else: raise nx.NetworkXError('Invalid degree sequence') # Calculate all agent's m_net parameter for a in self.agents: agent_neighbors=a.get_neighbors() # Get wealth of all neighbors y_net=sum(map(lambda n: self.agents[n].get_wealth(),agent_neighbors)) # Calculate m_net m_net=0 for n in agent_neighbors: n_wealth=self.agents[n].get_wealth() n_disposition=self.agents[n].get_disposition() m_net+=n_disposition*(n_wealth/y_net) a.set_mnet(m_net) # Set all agents contribution levels based on their network position for a in self.agents: # Get all relevant agent info agent_type=a.get_type() agent_mnet=a.get_mnet() agent_wealth=a.get_wealth() agent_neighbors=a.get_neighbors() if agent_type == 0: # Altruistic type a.set_contrib(0.5*a.get_disposition()) else: if agent_type==1: # Community type unmet=self.threshold-agent_mnet # Level of weath needed to meet threshold if unmet>0: if unmet<agent_wealth: a.set_contrib((unmet/agent_wealth)*a.get_disposition()) else: # Agent commits all wealth if threshold out of reach a.set_contrib(1.0*a.get_disposition()) else: a.set_contrib(0.0) else: if agent_type==2: # Min-match type if agent_mnet>0: min_neighbor=min(map(lambda n: self.agents[n].get_wealth(),agent_neighbors)) min_prop=min_neighbor/agent_mnet if min_prop<1: a.set_contrib(min_prop*a.get_disposition()) else: a.set_contrib(1.0*a.get_disposition()) else: a.set_contrib(random()*a.get_disposition()) else: if agent_type==3: # Max-match type if agent_mnet>0: max_neighbor=max(map(lambda n: self.agents[n].get_wealth(),agent_neighbors)) max_prop=max_neighbor/agent_mnet if max_prop<1: a.set_contrib(max_prop*a.get_disposition()) else: a.set_contrib(1.0*a.get_disposition()) else: a.set_contrib(random()*a.get_disposition()) else: # Miserly type a.set_contrib(uniform(0.0,0.05)*a.get_disposition()) # Finally, check to see if threshold has been met self.total_contribs=sum(map(lambda a: a.get_contrib()*a.get_wealth(),self.agents)) if(self.total_contribs>=self.threshold): self.threshold_met=True else: self.threshold_met=False