def sim_first(n, m0, m, steps): print("Running first") # Static parameters G = generate_sf(n, m0, m) print(G) show_metrics(G) plot_degree_hist(G) for i in progressbar.progressbar(range(steps)): # choose an edge edge = random.choice(list(G.edges())) # choose which side of it to keep source = edge[0] if len(G[source]) > len(G[edge[1]]): source = edge[1] G.remove_edge(edge[0], edge[1]) # connect to a new place degrees = { node: val for (node, val) in G.degree() if node not in G.neighbors(source) } target = weighted_choice(degrees) G.add_edge(source, target) show_metrics(G) plot_degree_hist(G)
def random_k_out_graph(n, k, alpha, self_loops=True, seed=None): if alpha < 0: raise ValueError("alpha must be positive") G = nx.empty_graph(n, create_using=nx.MultiDiGraph) weights = Counter({v: alpha for v in G}) for i in range(k * n): u = seed.choice([v for v, d in G.out_degree() if d < k]) # If self-loops are not allowed, make the source node `u` have # weight zero. if not self_loops: adjustment = Counter({u: weights[u]}) else: adjustment = Counter() v = weighted_choice(weights - adjustment, seed=seed) G.add_edge(u, v) weights[v] += 1 return G
def random_k_out_graph(n, k, alpha, self_loops=True, seed=None): """Returns a random `k`-out graph with preferential attachment. A random `k`-out graph with preferential attachment is a multidigraph generated by the following algorithm. 1. Begin with an empty digraph, and initially set each node to have weight `alpha`. 2. Choose a node `u` with out-degree less than `k` uniformly at random. 3. Choose a node `v` from with probability proportional to its weight. 4. Add a directed edge from `u` to `v`, and increase the weight of `v` by one. 5. If each node has out-degree `k`, halt, otherwise repeat from step 2. For more information on this model of random graph, see [1]. Parameters ---------- n : int The number of nodes in the returned graph. k : int The out-degree of each node in the returned graph. alpha : float A positive :class:`float` representing the initial weight of each vertex. A higher number means that in step 3 above, nodes will be chosen more like a true uniformly random sample, and a lower number means that nodes are more likely to be chosen as their in-degree increases. If this parameter is not positive, a :exc:`ValueError` is raised. self_loops : bool If True, self-loops are allowed when generating the graph. seed : integer, random_state, or None (default) Indicator of random number generation state. See :ref:`Randomness<randomness>`. Returns ------- :class:`~networkx.classes.MultiDiGraph` A `k`-out-regular multidigraph generated according to the above algorithm. Raises ------ ValueError If `alpha` is not positive. Notes ----- The returned multidigraph may not be strongly connected, or even weakly connected. References ---------- [1]: Peterson, Nicholas R., and Boris Pittel. "Distance between two random `k`-out digraphs, with and without preferential attachment." arXiv preprint arXiv:1311.5961 (2013). <https://arxiv.org/abs/1311.5961> """ if alpha < 0: raise ValueError("alpha must be positive") G = nx.empty_graph(n, create_using=nx.MultiDiGraph) weights = Counter({v: alpha for v in G}) for i in range(k * n): u = seed.choice([v for v, d in G.out_degree() if d < k]) # If self-loops are not allowed, make the source node `u` have # weight zero. if not self_loops: adjustment = Counter({u: weights[u]}) else: adjustment = Counter() v = weighted_choice(weights - adjustment, seed=seed) G.add_edge(u, v) weights[v] += 1 return G
def random_k_out_graph(n, k, alpha, self_loops=True, seed=None): """Returns a random `k`-out graph with preferential attachment. A random `k`-out graph with preferential attachment is a multidigraph generated by the following algorithm. 1. Begin with an empty digraph, and initially set each node to have weight `alpha`. 2. Choose a node `u` with out-degree less than `k` uniformly at random. 3. Choose a node `v` from with probability proportional to its weight. 4. Add a directed edge from `u` to `v`, and increase the weight of `v` by one. 5. If each node has out-degree `k`, halt, otherwise repeat from step 2. For more information on this model of random graph, see [1]. Parameters ---------- n : int The number of nodes in the returned graph. k : int The out-degree of each node in the returned graph. alpha : float A positive :class:`float` representing the initial weight of each vertex. A higher number means that in step 3 above, nodes will be chosen more like a true uniformly random sample, and a lower number means that nodes are more likely to be chosen as their in-degree increases. If this parameter is not positive, a :exc:`ValueError` is raised. self_loops : bool If True, self-loops are allowed when generating the graph. seed: int If provided, this is used as the seed for the random number generator. Returns ------- :class:`~networkx.classes.MultiDiGraph` A `k`-out-regular multidigraph generated according to the above algorithm. Raises ------ ValueError If `alpha` is not positive. Notes ----- The returned multidigraph may not be strongly connected, or even weakly connected. References ---------- [1]: Peterson, Nicholas R., and Boris Pittel. "Distance between two random `k`-out digraphs, with and without preferential attachment." arXiv preprint arXiv:1311.5961 (2013). <https://arxiv.org/abs/1311.5961> """ if alpha < 0: raise ValueError('alpha must be positive') random.seed(seed) G = nx.empty_graph(n, create_using=nx.MultiDiGraph()) weights = Counter({v: alpha for v in G}) for i in range(k * n): u = random.choice([v for v, d in G.out_degree() if d < k]) # If self-loops are not allowed, make the source node `u` have # weight zero. if not self_loops: adjustment = Counter({u: weights[u]}) else: adjustment = Counter() v = weighted_choice(weights - adjustment) G.add_edge(u, v) weights[v] += 1 return G
def test_random_weighted_choice(): mapping = {'a': 10, 'b': 0} c = weighted_choice(mapping) assert_equal(c, 'a')
def test_random_weighted_choice(): mapping = {"a": 10, "b": 0} c = weighted_choice(mapping, seed=1) c = weighted_choice(mapping) assert c == "a"
def test_random_weighted_choice(): mapping = {'a': 10, 'b': 0} c = weighted_choice(mapping, seed=1) c = weighted_choice(mapping) assert c == 'a'
def path_kpath_centrality(self, k=None, alpha=0.2, weight='invWeight', seed=123456, path_len=1): ''' Adapted from Alakahoon et al. and published code by extending from single node to path centrality ''' kpath_path_cent = defaultdict(float) if self.g.is_multigraph(): raise nx.NetworkXError("Not implemented" + \ "for multigraphs.") n = self.g.number_of_nodes() ne = self.g.number_of_edges() if n <= path_len + 4 or ne < path_len + 4: # network is too small for calculating # path centr. of this length return {} if k is None: k = int(math.log(n + ne)) if k < path_len + 4: k = min(path_len + 4, n) T = 2. * k**2 * n**(1 - 2 * alpha) * math.log(n) random.seed(seed) for i in range(int(T + 1)): st_path = [] # choose source node s = random.choice(list(self.g.nodes)) # choose a random path length l = random.randint(path_len + 2, k) st_path.append(s) # fill out a path of length l for j in range(l): # invert distance again - # get association nbrs = {nbr: 1./d.get(weight, 1.0) \ for nbr,d in self.g[s].items() \ if nbr not in st_path} if not nbrs: break v = weighted_choice(nbrs) st_path.append(v) # set the current path source # (current node) to v s = v if len(st_path) < path_len + 4: continue # sub_paths exclude end-points sub_paths = [wn for wn in window(st_path[1:-1], n=path_len)] for sub_path in sub_paths: sub_path_str_list = \ [str(node) for node in sub_path] if path_len == 1: kpath_path_cent[\ '_'.join(sub_path_str_list)] += 2. continue if not self.directed: kpath_path_cent['_'.join(\ reversed(sub_path_str_list))] += 1. kpath_path_cent[\ '_'.join(sub_path_str_list)] += 1. else: kpath_path_cent[\ '_'.join(sub_path_str_list)] += 2. for path in kpath_path_cent: kpath_path_cent[path] *= (0.5 / T) return kpath_path_cent
def test_random_weighted_choice(): mapping = {"a": 10, "b": 0} c = weighted_choice(mapping) assert_equal(c, "a")