def test_generate_sparse6(self): # Checked against sage encoder assert_equal(nx.generate_sparse6(nx.empty_graph(0)), '>>sparse6<<:?') assert_equal(nx.generate_sparse6(nx.empty_graph(1)), '>>sparse6<<:@') assert_equal(nx.generate_sparse6(nx.empty_graph(5)), '>>sparse6<<:D') assert_equal(nx.generate_sparse6(nx.empty_graph(68)), '>>sparse6<<:~?@C') assert_equal(nx.generate_sparse6(nx.empty_graph(258049)), '>>sparse6<<:~~???~?@') G1 = nx.complete_graph(4) assert_equal(nx.generate_sparse6(G1, header=True), '>>sparse6<<:CcKI') assert_equal(nx.generate_sparse6(G1, header=False), ':CcKI') # Padding testing assert_equal(nx.generate_sparse6(nx.path_graph(4), header=False), ':Cdv') assert_equal(nx.generate_sparse6(nx.path_graph(5), header=False), ':DaYn') assert_equal(nx.generate_sparse6(nx.path_graph(6), header=False), ':EaYnN') assert_equal(nx.generate_sparse6(nx.path_graph(7), header=False), ':FaYnL') assert_equal(nx.generate_sparse6(nx.path_graph(8), header=False), ':GaYnLz')
def SBM(nvec,block_probs, directed=True, seed=None): """Return a graph sampled from a stochastic block model Parameters ---------- nvec : array [k,1] The number of vertices per block; there are k blocks. B : array [k,k] in (0,1)^{k x k} Probability for edge creation for each block. seed : int, optional Seed for random number generator (default=None). math Notes ----- loopy : bool, optional (default=True) If True return a loopy graph This algorithm iterates over pairs of blocks and then assigns edges uniformly at random between nodes in each block """ if (block_probs<0).any(): raise ValueError('some probability is <0') if (block_probs>1).any(): raise ValueError('some probability is >1') if np.shape(block_probs)[0] != len(nvec): raise ValueError('nvec must be of length equal to the number of columns/rows of block_probs') if seed: np.random.seed(seed) Nvertices=nvec.sum() # total number of vertices Nblocks=len(nvec) # number of groups if directed: G=nx.empty_graph(Nvertices,create_using=nx.DiGraph()) else: G=nx.empty_graph(Nvertices,create_using=nx.Graph()) block_idx = np.append(0, nvec).cumsum() block = np.zeros(Nvertices, dtype=np.int) for ii in xrange(Nblocks): nodes1 = np.arange(block_idx[ii],block_idx[ii+1]) block[block_idx[ii]:block_idx[ii+1]] = ii if directed: add_random_edges_between(G, nodes1, block_probs[ii,ii],nodes1) else: add_random_edges_between(G, nodes1, block_probs[ii,ii]) for jj in xrange(ii+1,Nblocks): nodes2 = np.arange(block_idx[jj],block_idx[jj+1]) if directed: add_random_edges_between(G, nodes1, block_probs[ii,jj],nodes2) add_random_edges_between(G, nodes2, block_probs[jj,ii],nodes1) else: add_random_edges_between(G, nodes1, block_probs[ii,jj],nodes2) nx.set_node_attributes(G, 'block', dict(zip(np.arange(Nvertices), block))) return G
def test_empty_subgraph(self): # Subgraph of an empty graph is an empty graph. test 1 nullgraph = nx.null_graph() E5 = nx.empty_graph(5) E10 = nx.empty_graph(10) H = E10.subgraph([]) assert_true(nx.is_isomorphic(H, nullgraph)) H = E10.subgraph([1, 2, 3, 4, 5]) assert_true(nx.is_isomorphic(H, E5))
def test_strong_product(): null=nx.null_graph() empty1=nx.empty_graph(1) empty10=nx.empty_graph(10) K2=nx.complete_graph(2) K3=nx.complete_graph(3) K5=nx.complete_graph(5) K10=nx.complete_graph(10) P2=nx.path_graph(2) P3=nx.path_graph(3) P5=nx.path_graph(5) P10=nx.path_graph(10) # null graph G=strong_product(null,null) assert_true(nx.is_isomorphic(G,null)) # null_graph X anything = null_graph and v.v. G=strong_product(null,empty10) assert_true(nx.is_isomorphic(G,null)) G=strong_product(null,K3) assert_true(nx.is_isomorphic(G,null)) G=strong_product(null,K10) assert_true(nx.is_isomorphic(G,null)) G=strong_product(null,P3) assert_true(nx.is_isomorphic(G,null)) G=strong_product(null,P10) assert_true(nx.is_isomorphic(G,null)) G=strong_product(empty10,null) assert_true(nx.is_isomorphic(G,null)) G=strong_product(K3,null) assert_true(nx.is_isomorphic(G,null)) G=strong_product(K10,null) assert_true(nx.is_isomorphic(G,null)) G=strong_product(P3,null) assert_true(nx.is_isomorphic(G,null)) G=strong_product(P10,null) assert_true(nx.is_isomorphic(G,null)) G=strong_product(P5,K3) assert_equal(nx.number_of_nodes(G),5*3) G=strong_product(K3,K5) assert_equal(nx.number_of_nodes(G),3*5) #No classic easily found classic results for strong product G = nx.erdos_renyi_graph(10,2/10.) H = nx.erdos_renyi_graph(10,2/10.) GH = strong_product(G,H) for (u_G,u_H) in GH.nodes_iter(): for (v_G,v_H) in GH.nodes_iter(): if (u_G==v_G and H.has_edge(u_H,v_H)) or \ (u_H==v_H and G.has_edge(u_G,v_G)) or \ (G.has_edge(u_G,v_G) and H.has_edge(u_H,v_H)): assert_true(GH.has_edge((u_G,u_H),(v_G,v_H))) else: assert_true(not GH.has_edge((u_G,u_H),(v_G,v_H)))
def extract_graph(self): graph = nx.Graph() nx.empty_graph(self.n, graph) for i in range(self.n): graph.node[i] = self.agent[i].opinion for j in range(self.agent[i].degree): graph.add_edge(i, self.agent[i].neighbors[j]) return graph
def __init__(self, n, f, q, id_topology = 'Nan', nmm = 1, noise = 0.00): nx.Graph.__init__(self) nx.empty_graph(n, self) self.init_agents(n, f, q) self.init_mass_media(nmm, f, q) if id_topology != 'Nan': self.set_topology(id_topology) self.noise = noise
def test_generate_graph6(self): assert_equal(nx.generate_graph6(nx.empty_graph(0)), '>>graph6<<?') assert_equal(nx.generate_graph6(nx.empty_graph(1)), '>>graph6<<@') G1 = nx.complete_graph(4) assert_equal(nx.generate_graph6(G1, header=True), '>>graph6<<C~') assert_equal(nx.generate_graph6(G1, header=False), 'C~') G2 = nx.complete_bipartite_graph(6,9) assert_equal(nx.generate_graph6(G2, header=False), 'N??F~z{~Fw^_~?~?^_?') # verified by Sage G3 = nx.complete_graph(67) assert_equal(nx.generate_graph6(G3, header=False), '~?@B' + '~' * 368 + 'w')
def random_social_graph(g, l, S, k, a): N = g*2**l G = nx.empty_graph(N) # create the social coordinates vs vs = np.zeros((S,N,l), dtype=int) # for every characteristic for s in range(S): # want to choose g elements at random for every coordinate random_nodes = list(range(N)) random.shuffle(random_nodes) for ch in all_coordinates(l): for node in random_nodes[0:g]: vs[s, node, :] = ch del random_nodes[0:g] # collect all distances in a matrix social_matrix = social_distance_matrix(vs) # now add edges until the average degree is greater or equal to k while nx.number_of_edges(G) < N*k/2: # choose random node node1 = np.random.randint(N) # and random characteristic s = np.random.randint(S) # create probabilities probs = [ np.exp( -a * social_matrix[s, node1, node2] ) for node2 in range(N) ] # finally pick a node to connect to node2 = node1 while node2 == node1 or G.has_edge(node1, node2): node2 = random_pick( list(range(N)), probs ) #while node2 == node1: node2 = random_pick( list(range(N)), probs ) G.add_edge(node1, node2) # done constructing the graph return G, social_matrix, vs
def random_tree(n, create_using=None,seed=None): """ Returns a random tree of size n Proceeds by creating nodes and selecting uniformly at random an existing node to connect to. Parameters: ----------- n : int Number of nodes create_using: networkx graph graph to determine type seed: int Random seed value Returns: -------- G: networkx Graph A random tree """ if seed is not None: random.seed(seed) G = nx.empty_graph(0,create_using) G.add_node(0) for i in range(1,n): u = random.choice(G.nodes()) G.add_node(i) G.add_edge(i,u) return G
def get_graph_of_cluster(self, grids): # print '%%%%%%%%%%%%%%%%%%%%%is valid: ', self.is_valid_cluster(grids), ' %%%' # print 'graph of cluster grids keys: ', grids.keys() indices_list = grids.keys() g = nx.empty_graph() for i in range(len(indices_list)): indices = indices_list[i] # print 'indices: ', indices for j in range(len(indices_list)): other_indices = indices_list[j] # print 'other_indices: ', other_indices # print 'i, oi: ', indices, other_indices if self.are_neighbors(indices, other_indices): # print '***** ', indices, other_indices, ' ARE neighbors' if g.has_edge(indices, other_indices) == False: g.add_edge(indices, other_indices) continue g.add_node(other_indices) if g.has_node(indices) == False: g.add_node(indices) # print 'g size {}'.format(g.size()) return g
def Gen2DLattice(size): side = sqrt(size) if not side.is_integer(): print("Error: the size of lattice is not perfect square!") sys.exit() G = nx.empty_graph(size) for i in range(size): r = i // side c = i % side # Now we have to add 4 edges to the neighbours of i_th node # Adding edge to the neighbour: (r+1,c) l = ((r+1) % side) * side + c G.add_edge(i,l) # Adding edge to the neighbour: (r-1,c) l = ((r-1) % side) * side + c G.add_edge(i,l) # Adding edge to the neighbour: (r,c+1) l = r * side + ((c+1) % side) G.add_edge(i,l) # Adding edge to the neighbour: (r,c-1) l = r * side + ((c-1) % side) G.add_edge(i,l) return G
def generate_graph(n, beta, mean_degree): """ Test Graph generation """ G = nx.empty_graph(n) degreeArray = utils.degreeDistribution(beta, n, mean_degree) utils.randPairings(G, degreeArray) # output of the RGG if not os.path.exists('generated'): os.mkdir('generated') txtName = "generated/adj-%s-%s-%s-.txt" % (str(n), str(beta), str(mean_degree)) nx.write_adjlist(G, txtName) # plotting utils.drawDegreeHistogram(G) if n < 1000: utils.drawGraph(G) pngname = "generated/graph-%s-%s-%s-.png" % (str(n), str(beta), str(mean_degree)) plt.savefig(pngname) if not os.path.exists('feed'): os.mkdir('feed') utils.generateFeed(n)
def test_cartesian_product_null(): null=nx.null_graph() empty10=nx.empty_graph(10) K3=nx.complete_graph(3) K10=nx.complete_graph(10) P3=nx.path_graph(3) P10=nx.path_graph(10) # null graph G=cartesian_product(null,null) assert_true(nx.is_isomorphic(G,null)) # null_graph X anything = null_graph and v.v. G=cartesian_product(null,empty10) assert_true(nx.is_isomorphic(G,null)) G=cartesian_product(null,K3) assert_true(nx.is_isomorphic(G,null)) G=cartesian_product(null,K10) assert_true(nx.is_isomorphic(G,null)) G=cartesian_product(null,P3) assert_true(nx.is_isomorphic(G,null)) G=cartesian_product(null,P10) assert_true(nx.is_isomorphic(G,null)) G=cartesian_product(empty10,null) assert_true(nx.is_isomorphic(G,null)) G=cartesian_product(K3,null) assert_true(nx.is_isomorphic(G,null)) G=cartesian_product(K10,null) assert_true(nx.is_isomorphic(G,null)) G=cartesian_product(P3,null) assert_true(nx.is_isomorphic(G,null)) G=cartesian_product(P10,null) assert_true(nx.is_isomorphic(G,null))
def wheel_graph(n, create_using=None): """ Return the wheel graph The wheel graph consists of a hub node connected to a cycle of (n-1) nodes. Parameters ========== n : int or iterable If an integer, node labels are 0 to n with center 0. If an iterable of nodes, the center is the first. create_using : Graph, optional (default Graph()) If provided this graph is cleared of nodes and edges and filled with the new graph. Usually used to set the type of the graph. Node labels are the integers 0 to n - 1. """ n_name, nodes = n if n_name == 0: G = nx.empty_graph(0, create_using=create_using) G.name = "wheel_graph(0)" return G G = star_graph(nodes, create_using) G.name = "wheel_graph(%s)" % (n_name,) if len(G) > 2: G.add_edges_from(pairwise(nodes[1:])) G.add_edge(nodes[-1], nodes[1]) return G
def create_c11_graph(N, g, l, S, k, alpha): G = nx.empty_graph(N) vs = np.zeros((S,N,l)) -1 for s in range(S): distinct = int(N/g + 0.5) vs_distinct = np.zeros((distinct, l)) for i in range(distinct): for j in range(l): vs_distinct[i,j] = i/(2**(l-j-1))%2 for i in range(distinct): for gg in range(int(g)): node = -1 while node == -1: node = np.random.randint(N) if vs[s, node,0] != -1: node = -1 vs[s, node,:] = vs_distinct[i,:] x = social_distance_matrix(vs) while nx.number_of_edges(G) < N*k: i = np.random.randint(N) s = np.random.randint(S) j = i probabilities = np.zeros(N) for q in range(N): probabilities[q] = np.exp(-alpha*x[s, i, q]) while j == i: j = random_pick(range(N), probabilities) G.add_edge(i,j) return G, x, vs
def generic_graph_view(G, create_using=None): if create_using is None: newG = G.__class__() else: newG = nx.empty_graph(0, create_using) if G.is_multigraph() != newG.is_multigraph(): raise NetworkXError("Multigraph for G must agree with create_using") newG = nx.freeze(newG) # create view by assigning attributes from G newG._graph = G newG.graph = G.graph newG._node = G._node if newG.is_directed(): if G.is_directed(): newG._succ = G._succ newG._pred = G._pred newG._adj = G._succ else: newG._succ = G._adj newG._pred = G._adj newG._adj = G._adj elif G.is_directed(): if G.is_multigraph(): newG._adj = UnionMultiAdjacency(G._succ, G._pred) else: newG._adj = UnionAdjacency(G._succ, G._pred) else: newG._adj = G._adj return newG
def test_eccentricity(self): assert_equal(networkx.eccentricity(self.G, 1), 6) e = networkx.eccentricity(self.G) assert_equal(e[1], 6) sp = dict(networkx.shortest_path_length(self.G)) e = networkx.eccentricity(self.G, sp=sp) assert_equal(e[1], 6) e = networkx.eccentricity(self.G, v=1) assert_equal(e, 6) # This behavior changed in version 1.8 (ticket #739) e = networkx.eccentricity(self.G, v=[1, 1]) assert_equal(e[1], 6) e = networkx.eccentricity(self.G, v=[1, 2]) assert_equal(e[1], 6) # test against graph with one node G = networkx.path_graph(1) e = networkx.eccentricity(G) assert_equal(e[0], 0) e = networkx.eccentricity(G, v=0) assert_equal(e, 0) assert_raises(networkx.NetworkXError, networkx.eccentricity, G, 1) # test against empty graph G = networkx.empty_graph() e = networkx.eccentricity(G) assert_equal(e, {})
def draw_graph(username, password, filename='graph.txt', label_flag=True, remove_isolated=True, different_size=True, iso_level=10, node_size=40): """Reading data from file and draw the graph.If not exists, create the file and re-scratch data from net""" print "Generating graph..." try: with open(filename, 'r') as f: G = p.load(f) except: G = getgraph(username, password) with open(filename, 'w') as f: p.dump(G, f) #nx.draw(G) # Judge whether remove the isolated point from graph if remove_isolated is True: H = nx.empty_graph() for SG in nx.connected_component_subgraphs(G): if SG.number_of_nodes() > iso_level: H = nx.union(SG, H) G = H # Ajust graph for better presentation if different_size is True: L = nx.degree(G) G.dot_size = {} for k, v in L.items(): G.dot_size[k] = v node_size = [G.dot_size[v] * 10 for v in G] pos = nx.spring_layout(G, iterations=50) nx.draw_networkx_edges(G, pos, alpha=0.2) nx.draw_networkx_nodes(G, pos, node_size=node_size, node_color='r', alpha=0.3) # Judge whether shows label if label_flag is True: nx.draw_networkx_labels(G, pos, alpha=0.5) #nx.draw_graphviz(G) plt.show() return G
def _lg_directed(G, create_using=None): """Return the line graph L of the (multi)digraph G. Edges in G appear as nodes in L, represented as tuples of the form (u,v) or (u,v,key) if G is a multidigraph. A node in L corresponding to the edge (u,v) is connected to every node corresponding to an edge (v,w). Parameters ---------- G : digraph A directed graph or directed multigraph. create_using : NetworkX graph constructor, optional Graph type to create. If graph instance, then cleared before populated. Default is to use the same graph class as `G`. """ L = nx.empty_graph(0, create_using, default=G.__class__) # Create a graph specific edge function. get_edges = _edge_func(G) for from_node in get_edges(): # from_node is: (u,v) or (u,v,key) L.add_node(from_node) for to_node in get_edges(from_node[1]): L.add_edge(from_node, to_node) return L
def k_random_intersection_graph(n,m,k): """Return a intersection graph with randomly chosen attribute sets for each node that are of equal size (k). Parameters ---------- n : int The number of nodes in the first bipartite set (nodes) m : int The number of nodes in the second bipartite set (attributes) k : float Size of attribute set to assign to each node. seed : int, optional Seed for random number generator (default=None). See Also -------- gnp_random_graph, uniform_random_intersection_graph References ---------- .. [1] Godehardt, E., and Jaworski, J. Two models of random intersection graphs and their applications. Electronic Notes in Discrete Mathematics 10 (2001), 129--132. """ G = nx.empty_graph(n + m) mset = range(n,n+m) for v in range(n): targets = random.sample(mset, k) G.add_edges_from(zip([v]*len(targets), targets)) return nx.projected_graph(G, range(n))
def full_rary_tree(r, n, create_using=None): """Creates a full r-ary tree of n vertices. Sometimes called a k-ary, n-ary, or m-ary tree. "... all non-leaf vertices have exactly r children and all levels are full except for some rightmost position of the bottom level (if a leaf at the bottom level is missing, then so are all of the leaves to its right." [1]_ Parameters ---------- r : int branching factor of the tree n : int Number of nodes in the tree create_using : Graph, optional (default None) If provided this graph is cleared of nodes and edges and filled with the new graph. Usually used to set the type of the graph. Returns ------- G : networkx Graph An r-ary tree with n nodes References ---------- .. [1] An introduction to data structures and algorithms, James Andrew Storer, Birkhauser Boston 2001, (page 225). """ G = nx.empty_graph(n, create_using) G.add_edges_from(_tree_edges(n, r)) return G
def binomial_tree(n): """Returns the Binomial Tree of order n. The binomial tree of order 0 consists of a single vertex. A binomial tree of order k is defined recursively by linking two binomial trees of order k-1: the root of one is the leftmost child of the root of the other. Parameters ---------- n : int Order of the binomial tree. Returns ------- G : NetworkX graph A binomial tree of $2^n$ vertices and $2^n - 1$ edges. """ G = nx.empty_graph(1) N = 1 for i in range(n): edges = [(u + N, v + N) for (u, v) in G.edges] G.add_edges_from(edges) G.add_edge(0,N) N *= 2 return G
def test_non_symmetric_min_unsat(self): G = nx.complete_graph(4) T = nx.empty_graph(4) edges = list(combinations(G.nodes(), 2)) T.add_edges_from(edges[1:]) F = SubgraphFormula(G, [T]) self.assertUNSAT(F)
def RGG(n, beta, mean_degree): G = nx.empty_graph(n) powerLawArray = utils.powerLawArray(n, beta, mean_degree) powerLawDegreeArray = np.array(powerLawArray, dtype = np.longlong) sumOfDegrees = powerLawDegreeArray.sum() delimiterArray = np.cumsum(powerLawDegreeArray) delimiterArray = np.insert(delimiterArray, 0, 0) delimiterArray = np.delete(delimiterArray, n) someCounter = 0 while someCounter < sumOfDegrees/2: G.add_edge(np.searchsorted(delimiterArray, rnd.randrange(sumOfDegrees)), np.searchsorted(delimiterArray, rnd.randrange(sumOfDegrees))) someCounter += 1 txtname = "generated/adj-%s-%s-%s-.txt" % (str(n), str(beta), str(mean_degree)) nx.write_adjlist(G, txtname) degreeSequence=sorted(nx.degree(G).values(),reverse=True) dmax=max(degreeSequence) plt.clf() plt.cla() plt.loglog(degreeSequence,'b-',marker='o') plt.title("Degree rank plot") plt.ylabel("degree") plt.xlabel("rank") if n < 1000: plt.axes([0.45,0.45,0.45,0.45]) plt.cla() Gcc=nx.connected_component_subgraphs(G)[0] pos=nx.spring_layout(Gcc) plt.axis('off') nx.draw_networkx_nodes(Gcc,pos,node_size=20) nx.draw_networkx_edges(Gcc,pos,alpha=0.4) pngname = "generated/graph-%s-%s-%s-.png" % (str(n), str(beta), str(mean_degree)) plt.savefig(pngname)
def draw_graph(label_flag=True, remove_isolated=True, different_size=True, iso_level=10, node_size=40): G=build_graph(fb.get_friends_network()) betweenness=nx.betweenness_centrality(G) degree=nx.degree_centrality(G) degree_num=[ degree[v] for v in G] maxdegree=max(degree_num);mindegree=min(degree_num); print maxdegree,mindegree clustering=nx.clustering(G) print nx.transitivity(G) # Judge whether remove the isolated point from graph if remove_isolated is True: H = nx.empty_graph() for SG in nx.connected_component_subgraphs(G): if SG.number_of_nodes() > iso_level: H = nx.union(SG, H) G = H # Ajust graph for better presentation if different_size is True: L = nx.degree(G) G.dot_size = {} for k, v in L.items(): G.dot_size[k] = v #node_size = [betweenness[v] *1000 for v in G] node_size = [G.dot_size[v] * 10 for v in G] node_color= [((degree[v]-mindegree))/(maxdegree-mindegree) for v in G] #edge_width = [getcommonfriends(u,v) for u,v in G.edges()] pos = nx.spring_layout(G, iterations=15) nx.draw_networkx_edges(G, pos, alpha=0.05) nx.draw_networkx_nodes(G, pos, node_size=node_size, node_color=node_color, vmin=0.0,vmax=1.0, alpha=0.3) # Judge whether shows label if label_flag is True: nx.draw_networkx_labels(G, pos, font_size=6,alpha=0.1) #nx.draw_graphviz(G) plt.show() return G
def setup_graph(ingredients, cuisine_name): # dict with random values for the position of the nodes p = dict((i,(random.gauss(0,2),random.gauss(0,2))) for i in range(len(ingredients))) # creating the graph G = nx.empty_graph() G.add_nodes_from(p) # Setting an attribute with the position of each node in the graph pos = nx.set_node_attributes(G,'pos', p) # Creating the nodes node_trace = Scatter( x = [], y = [], text = [], name = cuisine_name, mode = 'markers', hoverinfo = 'text') # adding positions for the nodes for node in G.nodes(): x, y = G.node[node]['pos'] node_trace['x'].append(x) node_trace['y'].append(y) # naming the nodes node_trace['text'].extend(ingredients) return node_trace
def bipartite_alternating_havel_hakimi_graph(aseq, bseq, create_using=None, ): """ Return a bipartite graph from two given degree sequences using a alternating Havel-Hakimi style construction. :Parameters: - `aseq`: degree sequence for node set A - `bseq`: degree sequence for node set B Nodes from the set A are connected to nodes in the set B by connecting the highest degree nodes in set A to alternatively the highest and the lowest degree nodes in set B until all stubs are connected. The sum of the two sequences must be equal: sum(aseq)=sum(bseq) """ if create_using==None: create_using=NX.MultiGraph() G=NX.empty_graph(0,create_using) # length of the each sequence naseq=len(aseq) nbseq=len(bseq) suma=sum(aseq) sumb=sum(bseq) if not suma==sumb: raise NX.NetworkXError, \ 'invalid degree sequences, sum(aseq)!=sum(bseq),%s,%s'\ %(suma,sumb) G.add_nodes_from(range(0,naseq)) # one vertex type (a) G.add_nodes_from(range(naseq,naseq+nbseq)) # the other type (b) if max(aseq)==0: return G # done if no edges # build list of degree-repeated vertex numbers astubs=[[aseq[v],v] for v in range(0,naseq)] bstubs=[[bseq[v-naseq],v] for v in range(naseq,naseq+nbseq)] while astubs: astubs.sort() (degree,u)=astubs.pop() # take of largest degree node in the a set if degree==0: break # done, all are zero bstubs.sort() small=bstubs[0:degree/2] # add these low degree targets large=bstubs[(-degree+degree/2):] # and these high degree targets stubs=[x for z in zip(large,small) for x in z] # combine, sorry if len(stubs)<len(small)+len(large): # check for zip truncation stubs.append(large.pop()) for target in stubs: v=target[1] G.add_edge(u,v) target[0] -= 1 # note this updates bstubs too. if target[0]==0: bstubs.remove(target) G.name="bipartite_alternating_havel_hakimi_graph" return G
def __init__(self, blockHeights): """ Creates an occurence graph based on navigatable nodes (nodes at height 0) """ self.width = len(blockHeights) self.height = len(blockHeights[0]) self.g = nx.empty_graph(self.width * self.height) self.blockHeights = blockHeights self.prob = np.zeros(len(self.g.nodes())) #[0.0] * len(self.g.nodes()) def isNavigabaleNode(nodeId): """ Returns false if a block is present else returns true """ x, y = self.getCood(nodeId) return False if self.blockHeights[x][y] > 0 else True def getNeighbouringNodes(nodeId): """ Returns a list of nodes in all 8 directions from the given node """ x, y = self.getCood(nodeId) neighbouringNodes = [] for xoffset in range(-1, 2): for yoffset in range(-1, 2): if xoffset == 0 and yoffset == 0: continue xn = x + xoffset yn = y + yoffset if xn < 0 or xn >= self.width or yn < 0 or yn >= self.height: continue neighbouringNodes.append(self.getNodeId(xn, yn)) return neighbouringNodes for nodeId in self.g.nodes(): neighbouringNodes = getNeighbouringNodes(nodeId) navigatableNodes = filter(isNavigabaleNode, neighbouringNodes) #print nodeId, len(navigatableNodes) self.g.add_edges_from([(nodeId, navigatableNode) for navigatableNode in navigatableNodes])
def firstFitTopo(self, jobs, reservations): if len(jobs) != len(reservations): raise IndexError("Length of jobs and reservations input lists do no match") import networkx as nx skeleton = nx.barabasi_albert_graph(780) G = nx.empty_graph()
def bipartite_preferential_attachment_graph(aseq,p,create_using=None): """Create a bipartite graph with a preferential attachment model from a given single degree sequence. Parameters ---------- aseq : list or iterator Degree sequence for node set A. p : float Probability that a new bottom node is added. create_using : NetworkX graph instance, optional Return graph of this type. Notes ----- @article{guillaume-2004-bipartite, author = {Jean-Loup Guillaume and Matthieu Latapy}, title = {Bipartite structure of all complex networks}, journal = {Inf. Process. Lett.}, volume = {90}, number = {5}, year = {2004}, issn = {0020-0190}, pages = {215--221}, doi = {http://dx.doi.org/10.1016/j.ipl.2004.03.007}, publisher = {Elsevier North-Holland, Inc.}, address = {Amsterdam, The Netherlands, The Netherlands}, } """ if create_using==None: create_using=networkx.MultiGraph() G=networkx.empty_graph(0,create_using) if p > 1: raise networkx.NetworkXError, "probability %s > 1"%(p) naseq=len(aseq) G.add_nodes_from(range(0,naseq)) vv=[ [v]*aseq[v] for v in range(0,naseq)] while vv: while vv[0]: source=vv[0][0] vv[0].remove(source) if random.random() < p or G.number_of_nodes() == naseq: target=G.number_of_nodes() G.add_edge(source,target) else: bb=[ [b]*G.degree(b) for b in range(naseq,G.number_of_nodes())] # flatten the list of lists into a list. bbstubs=reduce(lambda x,y: x+y, bb) # choose preferentially a bottom node. target=random.choice(bbstubs) G.add_edge(source,target) vv.remove(vv[0]) G.name="bipartite_preferential_attachment_model" return G
def configuration_model(aseq, bseq, create_using=None, seed=None): """Returns a random bipartite graph from two given degree sequences. Parameters ---------- aseq : list Degree sequence for node set A. bseq : list Degree sequence for node set B. create_using : NetworkX graph instance, optional Return graph of this type. seed : integer, random_state, or None (default) Indicator of random number generation state. See :ref:`Randomness<randomness>`. Nodes from the set A are connected to nodes in the set B by choosing randomly from the possible free stubs, one in A and one in B. Notes ----- The sum of the two sequences must be equal: sum(aseq)=sum(bseq) If no graph type is specified use MultiGraph with parallel edges. If you want a graph with no parallel edges use create_using=Graph() but then the resulting degree sequences might not be exact. The nodes are assigned the attribute 'bipartite' with the value 0 or 1 to indicate which bipartite set the node belongs to. This function is not imported in the main namespace. To use it you have to explicitly import the bipartite package. """ G = nx.empty_graph(0, create_using, default=nx.MultiGraph) if G.is_directed(): raise nx.NetworkXError("Directed Graph not supported") # length and sum of each sequence lena = len(aseq) lenb = len(bseq) suma = sum(aseq) sumb = sum(bseq) if not suma == sumb: raise nx.NetworkXError( 'invalid degree sequences, sum(aseq)!=sum(bseq),%s,%s' % (suma, sumb)) G = _add_nodes_with_bipartite_label(G, lena, lenb) if len(aseq) == 0 or max(aseq) == 0: return G # done if no edges # build lists of degree-repeated vertex numbers stubs = [] stubs.extend([[v] * aseq[v] for v in range(0, lena)]) astubs = [] astubs = [x for subseq in stubs for x in subseq] stubs = [] stubs.extend([[v] * bseq[v - lena] for v in range(lena, lena + lenb)]) bstubs = [] bstubs = [x for subseq in stubs for x in subseq] # shuffle lists seed.shuffle(astubs) seed.shuffle(bstubs) G.add_edges_from([[astubs[i], bstubs[i]] for i in range(suma)]) G.name = "bipartite_configuration_model" return G
def from_pydot(P): """Return a NetworkX graph from a Pydot graph. Parameters ---------- P : Pydot graph A graph created with Pydot Returns ------- G : NetworkX multigraph A MultiGraph or MultiDiGraph. Examples -------- >>> K5=nx.complete_graph(5) >>> A=nx.to_pydot(K5) >>> G=nx.from_pydot(A) # return MultiGraph >>> G=nx.Graph(nx.from_pydot(A)) # make a Graph instead of MultiGraph """ if P.get_strict(None): # pydot bug: get_strict() shouldn't take argument multiedges=False else: multiedges=True if P.get_type()=='graph': # undirected if multiedges: create_using=nx.MultiGraph() else: create_using=nx.Graph() else: if multiedges: create_using=nx.MultiDiGraph() else: create_using=nx.DiGraph() # assign defaults N=nx.empty_graph(0,create_using) N.name=P.get_name() # add nodes, attributes to N.node_attr for p in P.get_node_list(): n=p.get_name().strip('"') if n in ('node','graph','edge'): continue N.add_node(n,**p.get_attributes()) # add edges for e in P.get_edge_list(): u=e.get_source() v=e.get_destination() attr=e.get_attributes() s=[] d=[] if isinstance(u, basestring): s.append(u.strip('"')) else: for unodes in u['nodes'].iterkeys(): s.append(unodes.strip('"')) if isinstance(v, basestring): d.append(v.strip('"')) else: for vnodes in v['nodes'].iterkeys(): d.append(vnodes.strip('"')) for source_node in s: for destination_node in d: N.add_edge(source_node,destination_node,**attr) # add default attributes for graph, nodes, edges N.graph['graph']=P.get_attributes() try: N.graph['node']=P.get_node_defaults()[0] except:# IndexError,TypeError: N.graph['node']={} try: N.graph['edge']=P.get_edge_defaults()[0] except:# IndexError,TypeError: N.graph['edge']={} return N
def test_empty(self): with pytest.raises(nx.NetworkXException): G = nx.empty_graph() nx.second_order_centrality(G)
def expected_degree_graph(w, seed=None, selfloops=True): r"""Returns a random graph with given expected degrees. Given a sequence of expected degrees $W=(w_0,w_1,\ldots,w_{n-1})$ of length $n$ this algorithm assigns an edge between node $u$ and node $v$ with probability .. math:: p_{uv} = \frac{w_u w_v}{\sum_k w_k} . Parameters ---------- w : list The list of expected degrees. selfloops: bool (default=True) Set to False to remove the possibility of self-loop edges. seed : integer, random_state, or None (default) Indicator of random number generation state. See :ref:`Randomness<randomness>`. Returns ------- Graph Examples -------- >>> z = [10 for i in range(100)] >>> G = nx.expected_degree_graph(z) Notes ----- The nodes have integer labels corresponding to index of expected degrees input sequence. The complexity of this algorithm is $\mathcal{O}(n+m)$ where $n$ is the number of nodes and $m$ is the expected number of edges. The model in [1]_ includes the possibility of self-loop edges. Set selfloops=False to produce a graph without self loops. For finite graphs this model doesn't produce exactly the given expected degree sequence. Instead the expected degrees are as follows. For the case without self loops (selfloops=False), .. math:: E[deg(u)] = \sum_{v \ne u} p_{uv} = w_u \left( 1 - \frac{w_u}{\sum_k w_k} \right) . NetworkX uses the standard convention that a self-loop edge counts 2 in the degree of a node, so with self loops (selfloops=True), .. math:: E[deg(u)] = \sum_{v \ne u} p_{uv} + 2 p_{uu} = w_u \left( 1 + \frac{w_u}{\sum_k w_k} \right) . References ---------- .. [1] Fan Chung and L. Lu, Connected components in random graphs with given expected degree sequences, Ann. Combinatorics, 6, pp. 125-145, 2002. .. [2] Joel Miller and Aric Hagberg, Efficient generation of networks with given expected degrees, in Algorithms and Models for the Web-Graph (WAW 2011), Alan Frieze, Paul Horn, and Paweł Prałat (Eds), LNCS 6732, pp. 115-126, 2011. """ n = len(w) G = nx.empty_graph(n) # If there are no nodes are no edges in the graph, return the empty graph. if n == 0 or max(w) == 0: return G rho = 1 / sum(w) # Sort the weights in decreasing order. The original order of the # weights dictates the order of the (integer) node labels, so we # need to remember the permutation applied in the sorting. order = sorted(enumerate(w), key=itemgetter(1), reverse=True) mapping = {c: u for c, (u, v) in enumerate(order)} seq = [v for u, v in order] last = n if not selfloops: last -= 1 for u in range(last): v = u if not selfloops: v += 1 factor = seq[u] * rho p = min(seq[v] * factor, 1) while v < n and p > 0: if p != 1: r = seed.random() v += int(math.floor(math.log(r, 1 - p))) if v < n: q = min(seq[v] * factor, 1) if seed.random() < q / p: G.add_edge(mapping[u], mapping[v]) v += 1 p = q return G
def encoding(configs): ''' encode the subgraph to flat vector which is input of classifier ''' ''' Bulid the Graph ''' f = open(configs["basedir"] + "pa_edges_set.p", "rb") pa_edges_set = pickle.load(f) f.close() n_nodes = max(list(map(lambda x: max(x), pa_edges_set))) n_links = len(pa_edges_set) print("Encoding - # of total nodes in graph : ", n_nodes) print("Encoding - # of total links in graph : ", n_links) graph_edges = treat_Warning1(pa_edges_set) network = nx.empty_graph() network.add_edges_from(graph_edges) for node_idx in range(n_nodes): if node_idx not in list(network.nodes): network.add_node(node_idx) ''' Load Train data ''' f = open(configs["basedir"] + configs["target"] + "/pos_communities.p", "rb") _pos_communities = pickle.load(f) f.close() pos_communities = _pos_communities["data"] pos_communities = treat_Warning1(pos_communities) f = open(configs["basedir"] + configs["target"] + "/neg_communities.p", "rb") _neg_communities = pickle.load(f) f.close() neg_communities = _neg_communities["data"] query_Train_edges = pos_communities + neg_communities query_Train_labels = [1] * len(pos_communities) + [0 ] * len(neg_communities) query_Train_edges, query_Train_labels = shuffle(query_Train_edges, query_Train_labels) print("Encoding - # of Train edges : ", len(query_Train_edges)) ''' Load Test data ''' f = open(configs["basedir"] + "qpu_edges_raw_duplicate.p", 'rb') _query_Test_edges = pickle.load(f) f.close() _query_Test_edges = treat_Warning1(_query_Test_edges) f = open(configs["basedir"] + "apu_labels_raw_duplicate.p", 'rb') _query_Test_labels = pickle.load(f) f.close() if configs["target"] == "edges": query_Test_edges = [] query_Test_labels = [] for idx in range(len(_query_Test_edges)): if len(_query_Test_edges[idx]) == 2: query_Test_edges.append(_query_Test_edges[idx]) query_Test_labels.append(_query_Test_labels[idx]) elif configs["target"] == "raw": query_Test_edges = _query_Test_edges query_Test_labels = _query_Test_labels else: print("!!!Please check configs!!!") return print("Encoding - # of Test edges : ", len(query_Test_edges)) ''' Encoding ''' if configs["exist_node2vec"]: type_n2v = "n2v" else: type_n2v = "nn2v" dirname = configs["basedir"] + "encoded_vector/" + type_n2v + "/" + str( configs["h_size"]) + "/pickle/" if not os.path.isdir(dirname): os.mkdir(dirname) f = open(dirname + "configs.txt", "w") for k in configs.keys(): f.write(str(k) + " : " + str(configs[k])) f.write("\n") f.close() gwl = GWL(graph=network, configs=configs) start = time.time() num_train_batch = int(len(query_Train_edges) / configs["batch_size"]) for idx1 in range(num_train_batch): batch_dict = dict() cnt = 0 for idx2 in range(configs["batch_size"]): if idx2 % 100 == 0: print("Encoding Train data - ", idx1, idx2) try: query = tuple(query_Train_edges[idx1 * configs["batch_size"] + idx2]) except: break adj_vector = gwl.convert_into_adj_vector(query_data=query) if query in batch_dict.keys(): print(query) break else: batch_dict[cnt] = [ query, adj_vector, query_Train_labels[idx1 * configs["batch_size"] + idx2] ] cnt += 1 f = open(dirname + "train_adj_vectors_" + str(idx1) + ".p", "wb") pickle.dump(batch_dict, f) f.close() num_test_batch = int(len(query_Test_edges) / configs["batch_size"]) for idx1 in range(num_test_batch): batch_dict = dict() cnt = 0 for idx2 in range(configs["batch_size"]): if idx2 % 100 == 0: print("Encoding Test data - ", idx1, idx2) try: query = tuple(query_Test_edges[idx1 * configs["batch_size"] + idx2]) except: break adj_vector = gwl.convert_into_adj_vector(query_data=query) if query in batch_dict.keys(): print(query) break else: batch_dict[cnt] = [ cnt, adj_vector, query_Test_labels[idx1 * configs["batch_size"] + idx2] ] cnt += 1 f = open(dirname + "test_adj_vectors_" + str(idx1) + ".p", "wb") pickle.dump(batch_dict, f) f.close() print("Encoding - Elapsed time : ", time.time() - start)
def test_empty(self): expected = True actual = is_planar(nx.empty_graph()) self.assertEqual(expected, actual) actual = is_planar(nx.empty_graph(15)) self.assertEqual(expected, actual)
if visited[u]: continue # neighbors = sortlistwithmap(sigmamapping, list(G.neighbors(u))) neighbors = adjacencylist[u] for node in neighbors: if (sigmamapping[node] < sigmamapping[u] and not visited[node]): v = node M.append((v, u)) Nkv = BreadthFirstKLevels(G, v, k) Nku = BreadthFirstKLevels(G, u, k) for node in Nkv: visited[node] = True for node in Nku: visited[node] = True visited[u] = True visited[v] = True G.remove_nodes_from(Nkv) G.remove_nodes_from(Nku) return M #generate the tree graph n = 200 G = nx.empty_graph(n) G.add_edges_from(list(_tree_edges(n, 4))) H = G.copy() nx.write_adjlist(G, "test.adjlist") IM = induced_matching(H) k = 3 DkM = distancekmatching(H, k)
def join(rooted_trees, label_attribute=None): """Returns a new rooted tree with a root node joined with the roots of each of the given rooted trees. Parameters ---------- rooted_trees : list A list of pairs in which each left element is a NetworkX graph object representing a tree and each right element is the root node of that tree. The nodes of these trees will be relabeled to integers. label_attribute : str If provided, the old node labels will be stored in the new tree under this node attribute. If not provided, the node attribute ``'_old'`` will store the original label of the node in the rooted trees given in the input. Returns ------- NetworkX graph The rooted tree whose subtrees are the given rooted trees. The new root node is labeled 0. Each non-root node has an attribute, as described under the keyword argument ``label_attribute``, that indicates the label of the original node in the input tree. Notes ----- Graph, edge, and node attributes are propagated from the given rooted trees to the created tree. If there are any overlapping graph attributes, those from later trees will overwrite those from earlier trees in the tuple of positional arguments. Examples -------- Join two full balanced binary trees of height *h* to get a full balanced binary tree of depth *h* + 1:: >>> h = 4 >>> left = nx.balanced_tree(2, h) >>> right = nx.balanced_tree(2, h) >>> joined_tree = nx.join([(left, 0), (right, 0)]) >>> nx.is_isomorphic(joined_tree, nx.balanced_tree(2, h + 1)) True """ if len(rooted_trees) == 0: return nx.empty_graph(1) # Unzip the zipped list of (tree, root) pairs. trees, roots = zip(*rooted_trees) # The join of the trees has the same type as the type of the first # tree. R = type(trees[0])() # Relabel the nodes so that their union is the integers starting at 1. if label_attribute is None: label_attribute = "_old" relabel = partial( nx.convert_node_labels_to_integers, label_attribute=label_attribute ) lengths = (len(tree) for tree in trees[:-1]) first_labels = chain([0], accumulate(lengths)) trees = [ relabel(tree, first_label=first_label + 1) for tree, first_label in zip(trees, first_labels) ] # Get the relabeled roots. roots = [ next(v for v, d in tree.nodes(data=True) if d.get("_old") == root) for tree, root in zip(trees, roots) ] # Remove the old node labels. for tree in trees: for v in tree: tree.nodes[v].pop("_old") # Add all sets of nodes and edges, with data. nodes = (tree.nodes(data=True) for tree in trees) edges = (tree.edges(data=True) for tree in trees) R.add_nodes_from(chain.from_iterable(nodes)) R.add_edges_from(chain.from_iterable(edges)) # Add graph attributes; later attributes take precedent over earlier # attributes. for tree in trees: R.graph.update(tree.graph) # Finally, join the subtrees at the root. We know 0 is unused by the # way we relabeled the subtrees. R.add_node(0) R.add_edges_from((0, root) for root in roots) return R
def from_dict_of_dicts(d, create_using=None, multigraph_input=False): """Returns a graph from a dictionary of dictionaries. Parameters ---------- d : dictionary of dictionaries A dictionary of dictionaries adjacency representation. create_using : NetworkX graph constructor, optional (default=nx.Graph) Graph type to create. If graph instance, then cleared before populated. multigraph_input : bool (default False) When True, the values of the inner dict are assumed to be containers of edge data for multiple edges. Otherwise this routine assumes the edge data are singletons. Examples -------- >>> dod = {0: {1: {"weight": 1}}} # single edge (0,1) >>> G = nx.from_dict_of_dicts(dod) or >>> G = nx.Graph(dod) # use Graph constructor """ G = nx.empty_graph(0, create_using) G.add_nodes_from(d) # is dict a MultiGraph or MultiDiGraph? if multigraph_input: # make a copy of the list of edge data (but not the edge data) if G.is_directed(): if G.is_multigraph(): G.add_edges_from((u, v, key, data) for u, nbrs in d.items() for v, datadict in nbrs.items() for key, data in datadict.items()) else: G.add_edges_from((u, v, data) for u, nbrs in d.items() for v, datadict in nbrs.items() for key, data in datadict.items()) else: # Undirected if G.is_multigraph(): seen = set() # don't add both directions of undirected graph for u, nbrs in d.items(): for v, datadict in nbrs.items(): if (u, v) not in seen: G.add_edges_from((u, v, key, data) for key, data in datadict.items()) seen.add((v, u)) else: seen = set() # don't add both directions of undirected graph for u, nbrs in d.items(): for v, datadict in nbrs.items(): if (u, v) not in seen: G.add_edges_from( (u, v, data) for key, data in datadict.items()) seen.add((v, u)) else: # not a multigraph to multigraph transfer if G.is_multigraph() and not G.is_directed(): # d can have both representations u-v, v-u in dict. Only add one. # We don't need this check for digraphs since we add both directions, # or for Graph() since it is done implicitly (parallel edges not allowed) seen = set() for u, nbrs in d.items(): for v, data in nbrs.items(): if (u, v) not in seen: G.add_edge(u, v, key=0) G[u][v][0].update(data) seen.add((v, u)) else: G.add_edges_from(((u, v, data) for u, nbrs in d.items() for v, data in nbrs.items())) return G
def parse_edgelist(lines, comments='#', delimiter=None, create_using=None, nodetype=None, data=True): """Parse lines of an edge list representation of a graph. Parameters ---------- lines : list or iterator of strings Input data in edgelist format comments : string, optional Marker for comment lines delimiter : string, optional Separator for node labels create_using : NetworkX graph constructor, optional (default=nx.Graph) Graph type to create. If graph instance, then cleared before populated. nodetype : Python type, optional Convert nodes to this type. data : bool or list of (label,type) tuples If False generate no edge data or if True use a dictionary representation of edge data or a list tuples specifying dictionary key names and types for edge data. Returns ------- G: NetworkX Graph The graph corresponding to lines Examples -------- Edgelist with no data: >>> lines = ["1 2", ... "2 3", ... "3 4"] >>> G = nx.parse_edgelist(lines, nodetype = int) >>> list(G) [1, 2, 3, 4] >>> list(G.edges()) [(1, 2), (2, 3), (3, 4)] Edgelist with data in Python dictionary representation: >>> lines = ["1 2 {'weight':3}", ... "2 3 {'weight':27}", ... "3 4 {'weight':3.0}"] >>> G = nx.parse_edgelist(lines, nodetype = int) >>> list(G) [1, 2, 3, 4] >>> list(G.edges(data=True)) [(1, 2, {'weight': 3}), (2, 3, {'weight': 27}), (3, 4, {'weight': 3.0})] Edgelist with data in a list: >>> lines = ["1 2 3", ... "2 3 27", ... "3 4 3.0"] >>> G = nx.parse_edgelist(lines, nodetype = int, data=(('weight',float),)) >>> list(G) [1, 2, 3, 4] >>> list(G.edges(data=True)) [(1, 2, {'weight': 3.0}), (2, 3, {'weight': 27.0}), (3, 4, {'weight': 3.0})] See Also -------- read_weighted_edgelist """ from ast import literal_eval G = nx.empty_graph(0, create_using) for line in lines: p = line.find(comments) if p >= 0: line = line[:p] if not len(line): continue # split line, should have 2 or more s = line.strip().split(delimiter) if len(s) < 2: continue u = s.pop(0) v = s.pop(0) d = s if nodetype is not None: try: u = nodetype(u) v = nodetype(v) except: raise TypeError("Failed to convert nodes %s,%s to type %s." % (u, v, nodetype)) if len(d) == 0 or data is False: # no data or data type specified edgedata = {} elif data is True: # no edge types specified try: # try to evaluate as dictionary edgedata = dict(literal_eval(' '.join(d))) except: raise TypeError( "Failed to convert edge data (%s) to dictionary." % (d)) else: # convert edge data to dictionary with specified keys and type if len(d) != len(data): raise IndexError( "Edge data %s and data_keys %s are not the same length" % (d, data)) edgedata = {} for (edge_key, edge_type), edge_value in zip(data, d): try: edge_value = edge_type(edge_value) except: raise TypeError( "Failed to convert %s data %s to type %s." % (edge_key, edge_value, edge_type)) edgedata.update({edge_key: edge_value}) G.add_edge(u, v, **edgedata) return G
def directed_havel_hakimi_graph(in_deg_sequence, out_deg_sequence, create_using=None): """Returns a directed graph with the given degree sequences. Parameters ---------- in_deg_sequence : list of integers Each list entry corresponds to the in-degree of a node. out_deg_sequence : list of integers Each list entry corresponds to the out-degree of a node. create_using : NetworkX graph constructor, optional (default DiGraph) Graph type to create. If graph instance, then cleared before populated. Returns ------- G : DiGraph A graph with the specified degree sequences. Nodes are labeled starting at 0 with an index corresponding to the position in deg_sequence Raises ------ NetworkXError If the degree sequences are not digraphical. See Also -------- configuration_model Notes ----- Algorithm as described by Kleitman and Wang [1]_. References ---------- .. [1] D.J. Kleitman and D.L. Wang Algorithms for Constructing Graphs and Digraphs with Given Valences and Factors Discrete Mathematics, 6(1), pp. 79-88 (1973) """ in_deg_sequence = nx.utils.make_list_of_ints(in_deg_sequence) out_deg_sequence = nx.utils.make_list_of_ints(out_deg_sequence) # Process the sequences and form two heaps to store degree pairs with # either zero or nonzero out degrees sumin, sumout = 0, 0 nin, nout = len(in_deg_sequence), len(out_deg_sequence) maxn = max(nin, nout) G = nx.empty_graph(maxn, create_using, default=nx.DiGraph) if maxn == 0: return G maxin = 0 stubheap, zeroheap = [], [] for n in range(maxn): in_deg, out_deg = 0, 0 if n < nout: out_deg = out_deg_sequence[n] if n < nin: in_deg = in_deg_sequence[n] if in_deg < 0 or out_deg < 0: raise nx.NetworkXError( "Invalid degree sequences. Sequence values must be positive.") sumin, sumout, maxin = sumin + in_deg, sumout + out_deg, max( maxin, in_deg) if in_deg > 0: stubheap.append((-1 * out_deg, -1 * in_deg, n)) elif out_deg > 0: zeroheap.append((-1 * out_deg, n)) if sumin != sumout: raise nx.NetworkXError( "Invalid degree sequences. Sequences must have equal sums.") heapq.heapify(stubheap) heapq.heapify(zeroheap) modstubs = [(0, 0, 0)] * (maxin + 1) # Successively reduce degree sequence by removing the maximum while stubheap: # Remove first value in the sequence with a non-zero in degree (freeout, freein, target) = heapq.heappop(stubheap) freein *= -1 if freein > len(stubheap) + len(zeroheap): raise nx.NetworkXError("Non-digraphical integer sequence") # Attach arcs from the nodes with the most stubs mslen = 0 for i in range(freein): if zeroheap and (not stubheap or stubheap[0][0] > zeroheap[0][0]): (stubout, stubsource) = heapq.heappop(zeroheap) stubin = 0 else: (stubout, stubin, stubsource) = heapq.heappop(stubheap) if stubout == 0: raise nx.NetworkXError("Non-digraphical integer sequence") G.add_edge(stubsource, target) # Check if source is now totally connected if stubout + 1 < 0 or stubin < 0: modstubs[mslen] = (stubout + 1, stubin, stubsource) mslen += 1 # Add the nodes back to the heaps that still have available stubs for i in range(mslen): stub = modstubs[i] if stub[1] < 0: heapq.heappush(stubheap, stub) else: heapq.heappush(zeroheap, (stub[0], stub[2])) if freeout < 0: heapq.heappush(zeroheap, (freeout, target)) return G
def _configuration_model(deg_sequence, create_using, directed=False, in_deg_sequence=None, seed=None): """Helper function for generating either undirected or directed configuration model graphs. ``deg_sequence`` is a list of nonnegative integers representing the degree of the node whose label is the index of the list element. ``create_using`` see :func:`~networkx.empty_graph`. ``directed`` and ``in_deg_sequence`` are required if you want the returned graph to be generated using the directed configuration model algorithm. If ``directed`` is ``False``, then ``deg_sequence`` is interpreted as the degree sequence of an undirected graph and ``in_deg_sequence`` is ignored. Otherwise, if ``directed`` is ``True``, then ``deg_sequence`` is interpreted as the out-degree sequence and ``in_deg_sequence`` as the in-degree sequence of a directed graph. .. note:: ``deg_sequence`` and ``in_deg_sequence`` need not be the same length. ``seed`` is a random.Random or numpy.random.RandomState instance This function returns a graph, directed if and only if ``directed`` is ``True``, generated according to the configuration model algorithm. For more information on the algorithm, see the :func:`configuration_model` or :func:`directed_configuration_model` functions. """ n = len(deg_sequence) G = nx.empty_graph(n, create_using) # If empty, return the null graph immediately. if n == 0: return G # Build a list of available degree-repeated nodes. For example, # for degree sequence [3, 2, 1, 1, 1], the "stub list" is # initially [0, 0, 0, 1, 1, 2, 3, 4], that is, node 0 has degree # 3 and thus is repeated 3 times, etc. # # Also, shuffle the stub list in order to get a random sequence of # node pairs. if directed: pairs = zip_longest(deg_sequence, in_deg_sequence, fillvalue=0) # Unzip the list of pairs into a pair of lists. out_deg, in_deg = zip(*pairs) out_stublist = _to_stublist(out_deg) in_stublist = _to_stublist(in_deg) seed.shuffle(out_stublist) seed.shuffle(in_stublist) else: stublist = _to_stublist(deg_sequence) # Choose a random balanced bipartition of the stublist, which # gives a random pairing of nodes. In this implementation, we # shuffle the list and then split it in half. n = len(stublist) half = n // 2 seed.shuffle(stublist) out_stublist, in_stublist = stublist[:half], stublist[half:] G.add_edges_from(zip(out_stublist, in_stublist)) return G
def test_single_node(self): G = nx.empty_graph(1) ground_truth = {frozenset([0])} self._check_communities(G, ground_truth)
def havel_hakimi_graph(deg_sequence, create_using=None): """Returns 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 : NetworkX graph constructor, optional (default=nx.Graph) Graph type to create. If graph instance, then cleared before populated. 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_graphical(deg_sequence): raise nx.NetworkXError("Invalid degree sequence") p = len(deg_sequence) G = nx.empty_graph(p, create_using) if G.is_directed(): raise nx.NetworkXError("Directed graphs are not supported") num_degs = [[] for i in range(p)] 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 return G
def test_large_empty_graph(self): G = nx.empty_graph(68) result = BytesIO() nx.write_sparse6(G, result) self.assertEqual(result.getvalue(), '>>sparse6<<:~?@C\n')
def reverse_havel_hakimi_graph(aseq, bseq, create_using=None): """Returns a bipartite graph from two given degree sequences using a Havel-Hakimi style construction. Nodes from set A are connected to nodes in the set B by connecting the highest degree nodes in set A to the lowest degree nodes in set B until all stubs are connected. Parameters ---------- aseq : list Degree sequence for node set A. bseq : list Degree sequence for node set B. create_using : NetworkX graph instance, optional Return graph of this type. Notes ----- This function is not imported in the main namespace. To use it you have to explicitly import the bipartite package. The sum of the two sequences must be equal: sum(aseq)=sum(bseq) If no graph type is specified use MultiGraph with parallel edges. If you want a graph with no parallel edges use create_using=Graph() but then the resulting degree sequences might not be exact. The nodes are assigned the attribute 'bipartite' with the value 0 or 1 to indicate which bipartite set the node belongs to. """ G = nx.empty_graph(0, create_using, default=nx.MultiGraph) if G.is_directed(): raise nx.NetworkXError("Directed Graph not supported") # length of the each sequence lena = len(aseq) lenb = len(bseq) suma = sum(aseq) sumb = sum(bseq) if not suma == sumb: raise nx.NetworkXError( 'invalid degree sequences, sum(aseq)!=sum(bseq),%s,%s' % (suma, sumb)) G = _add_nodes_with_bipartite_label(G, lena, lenb) if len(aseq) == 0 or max(aseq) == 0: return G # done if no edges # build list of degree-repeated vertex numbers astubs = [[aseq[v], v] for v in range(0, lena)] bstubs = [[bseq[v - lena], v] for v in range(lena, lena + lenb)] astubs.sort() bstubs.sort() while astubs: (degree, u) = astubs.pop() # take of largest degree node in the a set if degree == 0: break # done, all are zero # connect the source to the smallest degree nodes in the b set for target in bstubs[0:degree]: v = target[1] G.add_edge(u, v) target[0] -= 1 # note this updates bstubs too. if target[0] == 0: bstubs.remove(target) G.name = "bipartite_reverse_havel_hakimi_graph" return G
def preferential_attachment_graph(aseq, p, create_using=None, seed=None): """Create a bipartite graph with a preferential attachment model from a given single degree sequence. Parameters ---------- aseq : list Degree sequence for node set A. p : float Probability that a new bottom node is added. create_using : NetworkX graph instance, optional Return graph of this type. seed : integer, random_state, or None (default) Indicator of random number generation state. See :ref:`Randomness<randomness>`. References ---------- .. [1] Guillaume, J.L. and Latapy, M., Bipartite graphs as models of complex networks. Physica A: Statistical Mechanics and its Applications, 2006, 371(2), pp.795-813. .. [2] Jean-Loup Guillaume and Matthieu Latapy, Bipartite structure of all complex networks, Inf. Process. Lett. 90, 2004, pg. 215-221 https://doi.org/10.1016/j.ipl.2004.03.007 Notes ----- This function is not imported in the main namespace. To use it you have to explicitly import the bipartite package. """ G = nx.empty_graph(0, create_using, default=nx.MultiGraph) if G.is_directed(): raise nx.NetworkXError("Directed Graph not supported") if p > 1: raise nx.NetworkXError("probability %s > 1" % (p)) naseq = len(aseq) G = _add_nodes_with_bipartite_label(G, naseq, 0) vv = [[v] * aseq[v] for v in range(0, naseq)] while vv: while vv[0]: source = vv[0][0] vv[0].remove(source) if seed.random() < p or G.number_of_nodes() == naseq: target = G.number_of_nodes() G.add_node(target, bipartite=1) G.add_edge(source, target) else: bb = [[b] * G.degree(b) for b in range(naseq, G.number_of_nodes())] # flatten the list of lists into a list. bbstubs = reduce(lambda x, y: x + y, bb) # choose preferentially a bottom node. target = seed.choice(bbstubs) G.add_node(target, bipartite=1) G.add_edge(source, target) vv.remove(vv[0]) G.name = "bipartite_preferential_attachment_model" return G
def test_disconnected_graph(self): """TestData that the Wiener index of a disconnected graph is positive infinity. """ assert wiener_index(empty_graph(2)) == float("inf")
def alternating_havel_hakimi_graph(aseq, bseq, create_using=None): """Returns a bipartite graph from two given degree sequences using an alternating Havel-Hakimi style construction. Nodes from the set A are connected to nodes in the set B by connecting the highest degree nodes in set A to alternatively the highest and the lowest degree nodes in set B until all stubs are connected. Parameters ---------- aseq : list Degree sequence for node set A. bseq : list Degree sequence for node set B. create_using : NetworkX graph instance, optional Return graph of this type. Notes ----- This function is not imported in the main namespace. To use it you have to explicitly import the bipartite package. The sum of the two sequences must be equal: sum(aseq)=sum(bseq) If no graph type is specified use MultiGraph with parallel edges. If you want a graph with no parallel edges use create_using=Graph() but then the resulting degree sequences might not be exact. The nodes are assigned the attribute 'bipartite' with the value 0 or 1 to indicate which bipartite set the node belongs to. """ G = nx.empty_graph(0, create_using, default=nx.MultiGraph) if G.is_directed(): raise nx.NetworkXError("Directed Graph not supported") # length of the each sequence naseq = len(aseq) nbseq = len(bseq) suma = sum(aseq) sumb = sum(bseq) if not suma == sumb: raise nx.NetworkXError( 'invalid degree sequences, sum(aseq)!=sum(bseq),%s,%s' % (suma, sumb)) G = _add_nodes_with_bipartite_label(G, naseq, nbseq) if len(aseq) == 0 or max(aseq) == 0: return G # done if no edges # build list of degree-repeated vertex numbers astubs = [[aseq[v], v] for v in range(0, naseq)] bstubs = [[bseq[v - naseq], v] for v in range(naseq, naseq + nbseq)] while astubs: astubs.sort() (degree, u) = astubs.pop() # take of largest degree node in the a set if degree == 0: break # done, all are zero bstubs.sort() small = bstubs[0:degree // 2] # add these low degree targets large = bstubs[(-degree + degree // 2):] # and these high degree targets stubs = [x for z in zip(large, small) for x in z] # combine, sorry if len(stubs) < len(small) + len(large): # check for zip truncation stubs.append(large.pop()) for target in stubs: v = target[1] G.add_edge(u, v) target[0] -= 1 # note this updates bstubs too. if target[0] == 0: bstubs.remove(target) G.name = "bipartite_alternating_havel_hakimi_graph" return G
def configuration_model(deg_sequence, create_using=None, seed=None): """Returns a random graph with the given degree sequence. The configuration model generates a random pseudograph (graph with parallel edges and self loops) by randomly assigning edges to match the given degree sequence. Parameters ---------- deg_sequence : list of nonnegative integers Each list entry corresponds to the degree of a node. create_using : NetworkX graph constructor, optional (default MultiGraph) Graph type to create. If graph instance, then cleared before populated. seed : integer, random_state, or None (default) Indicator of random number generation state. See :ref:`Randomness<randomness>`. Returns ------- G : MultiGraph A graph with the specified degree sequence. Nodes are labeled starting at 0 with an index corresponding to the position in deg_sequence. Raises ------ NetworkXError If the degree sequence does not have an even sum. See Also -------- is_graphical Notes ----- As described by Newman [1]_. A non-graphical degree sequence (not realizable by some simple graph) is allowed since this function returns graphs with self loops and parallel edges. An exception is raised if the degree sequence does not have an even sum. This configuration model construction process can lead to duplicate edges and loops. You can remove the self-loops and parallel edges (see below) which will likely result in a graph that doesn't have the exact degree sequence specified. The density of self-loops and parallel edges tends to decrease as the number of nodes increases. However, typically the number of self-loops will approach a Poisson distribution with a nonzero mean, and similarly for the number of parallel edges. Consider a node with *k* stubs. The probability of being joined to another stub of the same node is basically (*k* - *1*) / *N*, where *k* is the degree and *N* is the number of nodes. So the probability of a self-loop scales like *c* / *N* for some constant *c*. As *N* grows, this means we expect *c* self-loops. Similarly for parallel edges. References ---------- .. [1] M.E.J. Newman, "The structure and function of complex networks", SIAM REVIEW 45-2, pp 167-256, 2003. Examples -------- You can create a degree sequence following a particular distribution by using the one of the distribution functions in :mod:`~networkx.utils.random_sequence` (or one of your own). For example, to create an undirected multigraph on one hundred nodes with degree sequence chosen from the power law distribution: >>> sequence = nx.random_powerlaw_tree_sequence(100, tries=5000) >>> G = nx.configuration_model(sequence) >>> len(G) 100 >>> actual_degrees = [d for v, d in G.degree()] >>> actual_degrees == sequence True The returned graph is a multigraph, which may have parallel edges. To remove any parallel edges from the returned graph: >>> G = nx.Graph(G) Similarly, to remove self-loops: >>> G.remove_edges_from(nx.selfloop_edges(G)) """ if sum(deg_sequence) % 2 != 0: msg = "Invalid degree sequence: sum of degrees must be even, not odd" raise nx.NetworkXError(msg) G = nx.empty_graph(0, create_using, default=nx.MultiGraph) if G.is_directed(): raise nx.NetworkXNotImplemented("not implemented for directed graphs") G = _configuration_model(deg_sequence, G, seed=seed) return G
def from_agraph(A, create_using=None): """Return a NetworkX Graph or DiGraph from a PyGraphviz graph. Parameters ---------- A : PyGraphviz AGraph A graph created with PyGraphviz create_using : NetworkX graph class instance The output is created using the given graph class instance Examples -------- >>> K5 = nx.complete_graph(5) >>> A = nx.nx_agraph.to_agraph(K5) >>> G = nx.nx_agraph.from_agraph(A) >>> G = nx.nx_agraph.from_agraph(A) Notes ----- The Graph G will have a dictionary G.graph_attr containing the default graphviz attributes for graphs, nodes and edges. Default node attributes will be in the dictionary G.node_attr which is keyed by node. Edge attributes will be returned as edge data in G. With edge_attr=False the edge data will be the Graphviz edge weight attribute or the value 1 if no edge weight attribute is found. """ if create_using is None: if A.is_directed(): if A.is_strict(): create_using = nx.DiGraph() else: create_using = nx.MultiDiGraph() else: if A.is_strict(): create_using = nx.Graph() else: create_using = nx.MultiGraph() # assign defaults N = nx.empty_graph(0, create_using) N.name = '' if A.name is not None: N.name = A.name # add graph attributes N.graph.update(A.graph_attr) # add nodes, attributes to N.node_attr for n in A.nodes(): str_attr = {str(k): v for k, v in n.attr.items()} N.add_node(str(n), **str_attr) # add edges, assign edge data as dictionary of attributes for e in A.edges(): u, v = str(e[0]), str(e[1]) attr = dict(e.attr) str_attr = {str(k): v for k, v in attr.items()} if not N.is_multigraph(): if e.name is not None: str_attr['key'] = e.name N.add_edge(u, v, **str_attr) else: N.add_edge(u, v, key=e.name, **str_attr) # add default attributes for graph, nodes, and edges # hang them on N.graph_attr N.graph['graph'] = dict(A.graph_attr) N.graph['node'] = dict(A.node_attr) N.graph['edge'] = dict(A.edge_attr) return N
def draw_graph(network, ax=None, figsize=(10, 10), edge_mode='current', colorbar=False, TE_mode='local', **kwargs): if edge_mode == 'TE': if hasattr(network, 'TE'): TimeVector = network.TimeVector[network.sampling] else: print('No TE attached to network yet. Please calcualte TE first.') from sys import exit exit() else: TimeVector = network.TimeVector if 'TimeStamp' in kwargs: this_TimeStamp = kwargs['TimeStamp'] elif 'time' in kwargs: if kwargs['time'] in TimeVector: this_TimeStamp = np.where(TimeVector == kwargs['time'])[0][0] real_TimeStamp = np.where( network.TimeVector == kwargs['time'])[0][0] elif (kwargs['time'] < min(TimeVector)) or (kwargs['time'] > max(TimeVector)): print('Input time exceeds simulation period.') this_TimeStamp = np.argmin(abs(TimeVector - kwargs['time'])) real_TimeStamp = np.argmin(abs(network.TimeVector - kwargs['time'])) else: this_TimeStamp = np.argmin(abs(TimeVector - kwargs['time'])) real_TimeStamp = np.argmin(abs(network.TimeVector - kwargs['time'])) else: this_TimeStamp = 0 real_TimeStamp = 0 G = nx.from_numpy_array(network.connectivity.adj_matrix) pos = nx.layout.kamada_kawai_layout(G) edgeList = network.connectivity.edge_list sources = network.sources drains = network.drains this_switch = network.junctionSwitch[real_TimeStamp, :] if edge_mode == 'current': graphView = nx.DiGraph() graphView.add_nodes_from(range(network.numOfWires)) this_current = network.junctionVoltage[ real_TimeStamp, :] / network.junctionResistance[real_TimeStamp, :] for i in range(network.numOfJunctions): if this_switch[i]: if this_current[i] > 0: graphView.add_edge(edgeList[i, 0], edgeList[i, 1], weight=abs(this_current[i]), width=2, style='solid') else: graphView.add_edge(edgeList[i, 1], edgeList[i, 0], weight=abs(this_current[i]), width=2, style='solid') elif edge_mode == 'voltage': graphView = nx.empty_graph(network.numOfWires) this_voltage = network.junctionVoltage[this_TimeStamp, :] for i in range(network.numOfJunctions): if this_switch[i]: graphView.add_edge(edgeList[i, 0], edgeList[i, 1], weight=abs(this_voltage[i]), width=2, style='solid') else: graphView.add_edge(edgeList[i, 0], edgeList[i, 1], weight=abs(this_voltage[i]), width=1, style='dashed') elif edge_mode == 'filament': graphView = nx.empty_graph(network.numOfWires) this_filament = network.filamentState[this_TimeStamp, :] for i in range(network.numOfJunctions): if this_switch[i]: graphView.add_edge(edgeList[i, 0], edgeList[i, 1], weight=abs(this_filament[i]), width=2, style='solid') else: graphView.add_edge(edgeList[i, 0], edgeList[i, 1], weight=abs(this_filament[i]), width=1, style='dashed') elif edge_mode == 'Lyapunov': graphView = nx.empty_graph(network.numOfWires) if not hasattr(network, 'Lyapunov'): print('Lyapunov not calculated') network.Lyapunov = np.zeros(network.numOfJunctions) for i in range(network.numOfJunctions): if this_switch[i]: graphView.add_edge(edgeList[i, 0], edgeList[i, 1], weight=network.Lyapunov[i], width=2, style='solid') else: graphView.add_edge(edgeList[i, 0], edgeList[i, 1], weight=network.Lyapunov[i], width=1, style='dashed') elif edge_mode == 'TE': graphView = nx.empty_graph(network.numOfWires) if TE_mode == 'local': this_TE = network.TE[this_TimeStamp, :] elif TE_mode == 'average': this_TE = np.mean(network.TE[:this_TimeStamp, :], axis=0) for i in range(network.numOfJunctions): if this_switch[i]: graphView.add_edge(edgeList[i, 0], edgeList[i, 1], weight=this_TE[i], width=2, style='solid') else: graphView.add_edge(edgeList[i, 0], edgeList[i, 1], weight=this_TE[i], width=1, style='dashed') from analysis.GraphTheory import getOnGraph tempGraph = getOnGraph(network, this_TimeStamp=real_TimeStamp) pathFormed = nx.has_path(tempGraph, sources[0], drains[0]) edge_colors = [graphView[u][v]['weight'] for u, v in graphView.edges] widths = [graphView[u][v]['width'] for u, v in graphView.edges] styles = [graphView[u][v]['style'] for u, v in graphView.edges] node_colors = ['#1f78b4'] * len(graphView) for i in sources: node_colors[i] = 'g' for i in drains: node_colors[i] = 'r' plt.style.use('classic') if ax == None: fig, ax = plt.subplots(figsize=figsize) ax.axis('off') if pathFormed: cmap = plt.cm.Reds else: cmap = plt.cm.Blues cmap_min = 0 if len(edge_colors) == 0: cmap_max = 1 elif edge_mode == 'current': cmap_max = max(edge_colors) elif edge_mode == 'voltage': cmap_max = np.max(abs(network.junctionVoltage)) elif edge_mode == 'filament': cmap_max = np.max(network.filamentState) elif edge_mode == 'Lyapunov': cmap_min = np.min(network.Lyapunov) cmap_max = np.max(network.Lyapunov) elif edge_mode == 'TE': cmap_min = np.min(this_TE) cmap_max = np.max(this_TE) nx.draw_networkx(graphView, pos, node_size=350, node_color=node_colors, edge_color=edge_colors, edge_cmap=cmap, edge_vmin=cmap_min, edge_vmax=cmap_max, font_color='w', width=widths, style=styles, ax=ax) if edge_mode == 'current': nx.draw_networkx_edges(G, pos, width=1, alpha=0.15, ax=ax) ax.set_facecolor((0.8, 0.8, 0.8)) if (edge_mode == 'TE') & (TE_mode == 'average'): ax.set_title( f'Network average TE from t = 0 to {np.round(TimeVector[this_TimeStamp],3)}' ) else: ax.set_title('Network ' + edge_mode + f' at t = {np.round(TimeVector[this_TimeStamp],3)}') ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) if colorbar: sm = plt.cm.ScalarMappable(cmap=cmap, norm=plt.Normalize(vmin=cmap_min, vmax=cmap_max)) sm.set_array([]) cbar = plt.colorbar(sm, ax=ax, fraction=0.05, label=edge_mode) return ax
def test_must_be_connected(self): pytest.raises(nx.NetworkXNoPath, nx.barycenter, nx.empty_graph(5))
def joint_degree_graph(joint_degrees, seed=None): """ Generates a random simple graph with the given joint degree dictionary. Parameters ---------- joint_degrees : dictionary of dictionary of integers A joint degree dictionary in which entry ``joint_degrees[k][l]`` is the number of edges joining nodes of degree *k* with nodes of degree *l*. seed : integer, random_state, or None (default) Indicator of random number generation state. See :ref:`Randomness<randomness>`. Returns ------- G : Graph A graph with the specified joint degree dictionary. Raises ------ NetworkXError If *joint_degrees* dictionary is not realizable. Notes ----- In each iteration of the "while loop" the algorithm picks two disconnected nodes *v* and *w*, of degree *k* and *l* correspondingly, for which ``joint_degrees[k][l]`` has not reached its target yet. It then adds edge (*v*, *w*) and increases the number of edges in graph G by one. The intelligence of the algorithm lies in the fact that it is always possible to add an edge between such disconnected nodes *v* and *w*, even if one or both nodes do not have free stubs. That is made possible by executing a "neighbor switch", an edge rewiring move that releases a free stub while keeping the joint degree of G the same. The algorithm continues for E (number of edges) iterations of the "while loop", at the which point all entries of the given ``joint_degrees[k][l]`` have reached their target values and the construction is complete. References ---------- .. [1] M. Gjoka, B. Tillman, A. Markopoulou, "Construction of Simple Graphs with a Target Joint Degree Matrix and Beyond", IEEE Infocom, '15. Examples -------- >>> import networkx as nx >>> joint_degrees = {1: {4: 1}, ... 2: {2: 2, 3: 2, 4: 2}, ... 3: {2: 2, 4: 1}, ... 4: {1: 1, 2: 2, 3: 1}} >>> G=nx.joint_degree_graph(joint_degrees) >>> """ if not is_valid_joint_degree(joint_degrees): msg = 'Input joint degree dict not realizable as a simple graph' raise nx.NetworkXError(msg) # compute degree count from joint_degrees degree_count = { k: sum(l.values()) // k for k, l in joint_degrees.items() if k > 0 } # start with empty N-node graph N = sum(degree_count.values()) G = nx.empty_graph(N) # for a given degree group, keep the list of all node ids h_degree_nodelist = {} # for a given node, keep track of the remaining stubs h_node_residual = {} # populate h_degree_nodelist and h_node_residual nodeid = 0 for degree, num_nodes in degree_count.items(): h_degree_nodelist[degree] = range(nodeid, nodeid + num_nodes) for v in h_degree_nodelist[degree]: h_node_residual[v] = degree nodeid += int(num_nodes) # iterate over every degree pair (k,l) and add the number of edges given # for each pair for k in joint_degrees: for l in joint_degrees[k]: # n_edges_add is the number of edges to add for the # degree pair (k,l) n_edges_add = joint_degrees[k][l] if (n_edges_add > 0) and (k >= l): # number of nodes with degree k and l k_size = degree_count[k] l_size = degree_count[l] # k_nodes and l_nodes consist of all nodes of degree k and l k_nodes = h_degree_nodelist[k] l_nodes = h_degree_nodelist[l] # k_unsat and l_unsat consist of nodes of degree k and l that # are unsaturated i.e. nodes that have at least 1 available stub k_unsat = set(v for v in k_nodes if h_node_residual[v] > 0) if k != l: l_unsat = set(w for w in l_nodes if h_node_residual[w] > 0) else: l_unsat = k_unsat n_edges_add = joint_degrees[k][l] // 2 while n_edges_add > 0: # randomly pick nodes v and w that have degrees k and l v = k_nodes[seed.randrange(k_size)] w = l_nodes[seed.randrange(l_size)] # if nodes v and w are disconnected then attempt to connect if not G.has_edge(v, w) and (v != w): # if node v has no free stubs then do neighbor switch if h_node_residual[v] == 0: _neighbor_switch(G, v, k_unsat, h_node_residual) # if node w has no free stubs then do neighbor switch if h_node_residual[w] == 0: if k != l: _neighbor_switch(G, w, l_unsat, h_node_residual) else: _neighbor_switch(G, w, l_unsat, h_node_residual, avoid_node_id=v) # add edge (v, w) and update data structures G.add_edge(v, w) h_node_residual[v] -= 1 h_node_residual[w] -= 1 n_edges_add -= 1 if h_node_residual[v] == 0: k_unsat.discard(v) if h_node_residual[w] == 0: l_unsat.discard(w) return G
def test_very_large_empty_graph(self): G = nx.empty_graph(258049) result = BytesIO() nx.write_sparse6(G, result) self.assertEqual(result.getvalue(), '>>sparse6<<:~~???~?@\n')
def obtain_graph(args,suffix=""): """Build a Graph according to command line arguments Arguments: - `args`: command line options """ if getattr(args,'gnd'+suffix) is not None: n,d = getattr(args,'gnd'+suffix) if (n*d)%2 == 1: raise ValueError("n * d must be even") G=networkx.random_regular_graph(d,n) elif getattr(args,'gnp'+suffix) is not None: n,p = getattr(args,'gnp'+suffix) G=networkx.gnp_random_graph(n,p) elif getattr(args,'gnm'+suffix) is not None: n,m = getattr(args,'gnm'+suffix) G=networkx.gnm_random_graph(n,m) elif getattr(args,'grid'+suffix) is not None: G=networkx.grid_graph(getattr(args,'grid'+suffix)) elif getattr(args,'torus'+suffix) is not None: G=networkx.grid_graph(getattr(args,'torus'+suffix),periodic=True) elif getattr(args,'complete'+suffix) is not None: G=networkx.complete_graph(getattr(args,'complete'+suffix)) elif getattr(args,'empty'+suffix) is not None: G=networkx.empty_graph(getattr(args,'empty'+suffix)) elif getattr(args,'graphformat'+suffix) is not None: try: print("INFO: reading simple graph {} from '{}'".format(suffix,getattr(args,"input"+suffix).name), file=sys.stderr) G=readGraph(getattr(args,'input'+suffix), "simple", getattr(args,'graphformat'+suffix)) except ValueError as e: print("ERROR ON '{}'. {}".format( getattr(args,'input'+suffix).name,e), file=sys.stderr) exit(-1) else: raise RuntimeError("Command line does not specify a graph") # Graph modifications if getattr(args,'plantclique'+suffix)>1: cliquesize = getattr(args,'plantclique'+suffix) if cliquesize > G.order() : raise ValueError("Clique cannot be larger than graph") clique=random.sample(G.nodes(),cliquesize) for v,w in combinations(clique,2): G.add_edge(v,w) if getattr(args,'addedges'+suffix)>0: k = getattr(args,'addedges'+suffix) G.add_edges_from(sample_missing_edges(G,k)) if hasattr(G, 'name'): G.name = "{} with {} new random edges".format(G.name,k) # Output the graph is requested if getattr(args,'savegraph'+suffix) is not None: writeGraph(G, getattr(args,'savegraph'+suffix), 'simple', getattr(args,'graphformat'+suffix)) return G
def test_complete_1_partite_graph(self): """Tests that the complete 1-partite graph is the empty graph.""" G = nx.complete_multipartite_graph(3) H = nx.empty_graph(3) assert_nodes_equal(G, H) assert_edges_equal(sorted(G.edges()), sorted(H.edges()))
# # number of graph nodes numOfNodes = 9877 # list the files in the simulated graphs directory files = os.listdir('simNets/') adjLists = [] # read the grpahs adjacency lists for file in files: adjLists = adjLists + [np.genfromtxt('simNets/'+file, delimiter=",")] # build the graph diffGraph = nx.empty_graph(numOfNodes) counter = 1 numOfFiles = 1/100 diffGraph = nx.empty_graph(numOfNodes) for adjList in adjLists: numOfele = np.shape(adjList)[0] for i in range(0, numOfele): rowIndex = int(adjList[i,0]) - 1 colIndex = int(adjList[i,1]) - 1 if diffGraph.has_edge(rowIndex,colIndex): diffGraph[rowIndex][colIndex]['weight'] = diffGraph[rowIndex][colIndex]['weight'] + numOfFiles else: diffGraph.add_edge(rowIndex,colIndex,weight=numOfFiles) print("file "+str(counter)+" completed") counter = counter + 1
import networkx as nx import matplotlib.pyplot as plt G = nx.complete_graph(10) e = np.array(G.edges) print(G.edges, len(e)) X, y = [], [] count = 0 for i in range(10000): sample = np.random.normal(22, 10) if sample < 0: sample = 2 elif sample > 45: sample = 42 idx = np.random.permutation(len(e))[:int(sample)] #print(idx) edg = e[idx] G = nx.empty_graph(10) G.add_edges_from(edg) mat = np.zeros((10, 10), dtype=int) for i in edg: mat[tuple(i)] = True mat[tuple(i[::-1])] = True X.append(mat.reshape(1, -1)[0]) label = len(nx.maximal_independent_set(G)) y.append(int(label)) count += label print(i, label) y = np.asarray(y) X = np.asarray(X) import pickle
def test_symmetric_min_unsat(self): G = nx.empty_graph(4) G.add_edge(0, 1) T = nx.empty_graph(4) F = SubgraphFormula(G, [T]) self.assertUNSAT(F)