def local_search(graph, part_init=None, weight='weight', resolution=1., randomize=None): if type(graph) != nx.Graph: raise TypeError("Bad graph type, use only non directed graph") # special case, when there is no link # the best partition is everyone in its community if graph.number_of_edges() == 0: part = dict([]) for node in graph.nodes(): part[node] = node return [part] current_graph = graph.copy() status = Status() status.init(current_graph, weight, part_init) __one_level(current_graph, status, weight, resolution, randomize) partition = __renumber(status.node2com) return partition
def contribution_nodeneighbor(partition, graph, weight='weight'): contribution = dict([]) participation = dict([]) node_neighbor = dict([]) newstatus = Status() newstatus.init(graph, weight, partition) links = newstatus.total_weight if links == 0: raise ValueError("A graph without link has an undefined modularity") for node in graph: com_node = newstatus.node2com[node] deg_node = newstatus.gdegrees.get(node, 0.) deg_com = newstatus.degrees.get(com_node, 0.) neigh_communities = __neighcom(node, graph, newstatus, weight_key=weight) if neigh_communities: contribution[node] = round( neigh_communities.get(com_node, 0) - (0.5 * deg_node * deg_com) / links, 4) for com, dnc in neigh_communities.items(): participation[node] = participation.get( node, 1) - (dnc / deg_node)**2 if com != com_node: if node_neighbor.has_key(node): node_neighbor[node].append(com) else: node_neighbor[node] = [com] if node_neighbor.has_key(node): pass else: node_neighbor[node] = [com_node] return contribution, participation, node_neighbor
def node_contribution(partition, graph, weight='weight'): indegree = dict([]) contribution = dict([]) links = graph.size(weight=weight) newstatus = Status() newstatus.init(graph, weight, partition) if links == 0: raise ValueError("A graph without link has an undefined modularity") for node in graph: com = partition[node] for neighbor, datas in graph[node].items(): edge_weight = datas.get(weight, 1) if partition[neighbor] == com: if neighbor != node: indegree[node] = indegree.get(node, 0.) + float(edge_weight) contribution[node] = round( indegree[node] - (0.5 * newstatus.gdegrees[node] * newstatus.degrees[com]) / links, 4) return contribution
def generate_dendrogram(graph, inc_fnc, part_init=None, weight='weight', randomize=False): """Find communities in the graph and return the associated dendrogram A dendrogram is a tree and each level is a partition of the graph nodes. Level 0 is the first partition, which contains the smallest communities, and the best is len(dendrogram) - 1. The higher the level is, the bigger are the communities """ # special case, when there is no link # the best partition is everyone in its community if graph.number_of_edges() == 0: part = dict([]) for node in list(graph.nodes()): part[node] = node return [part] current_graph = graph.copy() status = Status() status.init(current_graph, weight, part_init) status_list = list() changed = one_level(current_graph, inc_fnc, status, weight, randomize) partition = renumber(status.node2com) status_list.append(partition) current_graph = induced_graph(partition, current_graph, weight) status.init(current_graph, weight) while False: changed = one_level(current_graph, inc_fnc, status, weight, randomize) if not changed: break partition = renumber(status.node2com) status_list.append(partition) current_graph = induced_graph(partition, current_graph, weight) status.init(current_graph, weight) return status_list[:]
def generate_dendrogram(graph, part_init=None, weight='weight', resolution=1., randomize=None): """Find communities in the graph and return the associated dendrogram A dendrogram is a tree and each level is a partition of the graph nodes. Level 0 is the first partition, which contains the smallest communities, and the best is len(dendrogram) - 1. The higher the level is, the bigger are the communities Parameters ---------- graph : networkx.Graph the networkx graph which will be decomposed part_init : dict, optional the algorithm will start using this partition of the nodes. It's a dictionary where keys are their nodes and values the communities weight : str, optional the key in graph to use as weight. Default to 'weight' resolution : double, optional Will change the size of the communities, default to 1. represents the time described in "Laplacian Dynamics and Multiscale Modular Structure in Networks", R. Lambiotte, J.-C. Delvenne, M. Barahona Returns ------- dendrogram : list of dictionaries a list of partitions, ie dictionnaries where keys of the i+1 are the values of the i. and where keys of the first are the nodes of graph Raises ------ TypeError If the graph is not a networkx.Graph See Also -------- best_partition Notes ----- Uses Louvain algorithm References ---------- .. 1. Blondel, V.D. et al. Fast unfolding of communities in large networks. J. Stat. Mech 10008, 1-12(2008). Examples -------- >>> G=nx.erdos_renyi_graph(100, 0.01) >>> dendo = generate_dendrogram(G) >>> for level in range(len(dendo) - 1) : >>> print("partition at level", level, >>> "is", partition_at_level(dendo, level)) :param weight: :type weight: """ if type(graph) != nx.Graph: raise TypeError("Bad graph type, use only non directed graph") # special case, when there is no link # the best partition is everyone in its community if graph.number_of_edges() == 0: part = dict([]) for node in graph.nodes(): part[node] = node return [part] current_graph = graph.copy() status = Status() status.init(current_graph, weight, part_init) status_list = list() __one_level(current_graph, status, weight, resolution, randomize) new_mod = __modularity(status) partition = __renumber(status.node2com) status_list.append(partition) mod = new_mod current_graph = induced_graph(partition, current_graph, weight) status.init(current_graph, weight) while True: __one_level(current_graph, status, weight, resolution) new_mod = __modularity(status) if new_mod - mod < __MIN: break partition = __renumber(status.node2com) status_list.append(partition) mod = new_mod current_graph = induced_graph(partition, current_graph, weight) status.init(current_graph, weight) return status_list[:]
def generate_dendrogram(graph, part_init=None, weight='weight', resolution=1.): """Find communities in the graph and return the associated dendrogram A dendrogram is a tree and each level is a partition of the graph nodes. Level 0 is the first partition, which contains the smallest communities, and the best is len(dendrogram) - 1. The higher the level is, the bigger are the communities Parameters ---------- graph : networkx.Graph the networkx graph which will be decomposed part_init : dict, optional the algorithm will start using this partition of the nodes. It's a dictionary where keys are their nodes and values the communities weight : str, optional the key in graph to use as weight. Default to 'weight' resolution : double, optional Will change the size of the communities, default to 1. represents the time described in "Laplacian Dynamics and Multiscale Modular Structure in Networks", R. Lambiotte, J.-C. Delvenne, M. Barahona Returns ------- dendrogram : list of dictionaries a list of partitions, ie dictionnaries where keys of the i+1 are the values of the i. and where keys of the first are the nodes of graph Raises ------ TypeError If the graph is not a networkx.Graph See Also -------- best_partition Notes ----- Uses Louvain algorithm References ---------- .. 1. Blondel, V.D. et al. Fast unfolding of communities in large networks. J. Stat. Mech 10008, 1-12(2008). Examples -------- >>> G=nx.erdos_renyi_graph(100, 0.01) >>> dendo = generate_dendrogram(G) >>> for level in range(len(dendo) - 1) : >>> print("partition at level", level, >>> "is", partition_at_level(dendo, level)) :param weight: :type weight: """ if type(graph) != nx.Graph: raise TypeError("Bad graph type, use only non directed graph") # special case, when there is no link # the best partition is everyone in its community if graph.number_of_edges() == 0: part = dict([]) for node in graph.nodes(): part[node] = node return [part] current_graph = graph.copy() status = Status() status.init(current_graph, weight, part_init) status_list = list() __one_level(current_graph, status, weight, resolution) new_mod = __modularity(status) partition = __renumber(status.node2com) status_list.append(partition) mod = new_mod current_graph = induced_graph(partition, current_graph, weight) status.init(current_graph, weight) while True: __one_level(current_graph, status, weight, resolution) new_mod = __modularity(status) if new_mod - mod < __MIN: break partition = __renumber(status.node2com) status_list.append(partition) mod = new_mod current_graph = induced_graph(partition, current_graph, weight) status.init(current_graph, weight) return status_list[:]
def generate_dendrogram(graph, part_init=None, weight='weight', resolution=1., randomize=None, random_state=None): """Find communities in the graph and return the associated dendrogram A dendrogram is a tree and each level is a partition of the graph nodes. Level 0 is the first partition, which contains the smallest communities, and the best is len(dendrogram) - 1. The higher the level is, the bigger are the communities Parameters ---------- graph : networkx.Graph the networkx graph which will be decomposed part_init : dict, optional the algorithm will start using this partition of the nodes. It's a dictionary where keys are their nodes and values the communities weight : str, optional the key in graph to use as weight. Default to 'weight' resolution : double, optional Will change the size of the communities, default to 1. represents the time described in "Laplacian Dynamics and Multiscale Modular Structure in Networks", R. Lambiotte, J.-C. Delvenne, M. Barahona Returns ------- dendrogram : list of dictionaries a list of partitions, ie dictionnaries where keys of the i+1 are the values of the i. and where keys of the first are the nodes of graph Raises ------ TypeError If the graph is not a networkx.Graph See Also -------- best_partition Notes ----- Uses Louvain algorithm References ---------- .. 1. Blondel, V.D. et al. Fast unfolding of communities in large networks. J. Stat. Mech 10008, 1-12(2008). Examples -------- >>> G=nx.erdos_renyi_graph(100, 0.01) >>> dendo = generate_dendrogram(G) >>> for level in range(len(dendo) - 1) : >>> print("partition at level", level, >>> "is", partition_at_level(dendo, level)) :param weight: :type weight: """ if graph.is_directed(): raise TypeError("Bad graph type, use only non directed graph") # Properly handle random state, eventually remove old `randomize` parameter # NOTE: when `randomize` is removed, delete code up to random_state = ... if randomize is not None: warnings.warn( "The `randomize` parameter will be deprecated in future " "versions. Use `random_state` instead.", DeprecationWarning) # If shouldn't randomize, we set a fixed seed to get determinisitc results if randomize is False: random_state = 0 # We don't know what to do if both `randomize` and `random_state` are defined if randomize and random_state is not None: raise ValueError( "`randomize` and `random_state` cannot be used at the " "same time") random_state = check_random_state(random_state) # special case, when there is no link # the best partition is everyone in its community if graph.number_of_edges() == 0: part = dict([]) for i, node in enumerate(graph.nodes()): part[node] = i return [part] current_graph = graph.copy() status = Status() status.init(current_graph, weight, part_init) status_list = list() __one_level(current_graph, status, weight, resolution, random_state) new_mod = __modularity(status) partition = __renumber(status.node2com) status_list.append(partition) mod = new_mod current_graph = induced_graph(partition, current_graph, weight) status.init(current_graph, weight) while True: __one_level(current_graph, status, weight, resolution, random_state) new_mod = __modularity(status) if new_mod - mod < __MIN: break partition = __renumber(status.node2com) status_list.append(partition) mod = new_mod current_graph = induced_graph(partition, current_graph, weight) status.init(current_graph, weight) return status_list[:]
def generate_dendrogram(graph, part_init=None, weight='weight', resolution=1., randomize=None, random_state=None): """Finds communities in the graph and return the associated dendrogram A dendrogram is a tree and each level is a partition of the graph nodes. Level 0 is the first partition, which contains the smallest communities, and the best is len(dendrogram) - 1. The higher the level is, the bigger are the communities. """ random_state = check_random_state(random_state) # special case, when there is no link # the best partition is everyone in its community if graph.number_of_edges() == 0: part = dict([]) for i, node in enumerate(graph.nodes()): part[node] = i return [part] current_graph = graph.copy() status = Status() status.init(current_graph, weight, part_init) status_list = list() __one_level(current_graph, status, weight, resolution, random_state) # runs the investigation multiple times until the improvement is smaller than the predefined threshold new_mod = __modularity(status) # computes the modularity of the graph, based on discovered communities partition = __renumber(status.node2com) # resets the community indices such that they start with 0 and goes up one by one (instead of random list of numbers between 1 and n that we had) status_list.append(partition) # appends a set of assigned communities at a certain level of detection to $status_list mod = new_mod # computes the modularity after the first change in community assignment but on the same graph (not induced graph) current_graph = induced_graph(partition, current_graph, weight) # createsa new graph based on the former one such that each community becomes a node in this new one. status.init(current_graph, weight) # updates the $status such that obliterates the former one. while True: __one_level(current_graph, status, weight, resolution, random_state) # runs the investigation multiple times until the improvement is smaller than the predefined threshold new_mod = __modularity(status) if new_mod - mod < __MIN: # check if the new modularity after creating a new graph and assign new communities is improved more than threshold in comparison with the former graph or not # this if statement checks the modularity value for two different graphs but the stop condition for $__one_level is for one graph with new community assignment break partition = __renumber(status.node2com) status_list.append(partition) mod = new_mod current_graph = induced_graph(partition, current_graph, weight) status.init(current_graph, weight) # while loop ends when the new induced graph (with more convoluted and merged communities) is no better than the former step. return status_list[:]
def generate_dendrogram(graph, IncFnc, part_init=None, weight='weight'): """Find communities in the graph and return the associated dendrogram A dendrogram is a tree and each level is a partition of the graph nodes. Level 0 is the first partition, which contains the smallest communities, and the best is len(dendrogram) - 1. The higher the level is, the bigger are the communities Parameters ---------- graph : networkx.Graph the networkx graph which will be decomposed part_init : dict, optional the algorithm will start using this partition of the nodes. It's a dictionary where keys are their nodes and values the communities weight : str, optional the key in graph to use as weight. Default to 'weight' Returns ------- dendrogram : list of dictionaries a list of partitions, ie dictionnaries where keys of the i+1 are the values of the i. and where keys of the first are the nodes of graph Raises ------ TypeError If the graph is not a networkx.Graph See Also -------- best_partition Notes ----- Uses Louvain's optimization algorithm References ---------- .. 1. Blondel, V.D. et al. Fast unfolding of communities in large networks. J. Stat. Mech 10008, 1-12(2008). .. 2. reference to SIWO paper TODO Examples -------- >>> G=nx.erdos_renyi_graph(100, 0.01) >>> dendo = generate_dendrogram(G) >>> for level in range(len(dendo) - 1) : >>> print("partition at level", level, >>> "is", partition_at_level(dendo, level)) :param weight: :type weight: """ if type(graph) != nx.Graph: raise TypeError("Bad graph type, use only non directed graph") # special case, when there is no link # the best partition is everyone in its community if graph.number_of_edges() == 0: part = dict([]) for node in graph.nodes(): part[node] = node return [part] current_graph = graph.copy() status = Status() status.init(current_graph, weight, part_init) status_list = list() changed = __one_level(current_graph, IncFnc, status, weight) partition = __renumber(status.node2com) status_list.append(partition) current_graph = induced_graph(partition, current_graph, weight) status.init(current_graph, weight) while True: changed = __one_level(current_graph, IncFnc, status, weight) if not changed: break partition = __renumber(status.node2com) status_list.append(partition) current_graph = induced_graph(partition, current_graph, weight) status.init(current_graph, weight) return status_list[:]
def generate_dendrogram(graph, part_init=None, weight='weight', resolution=1., randomize=False): """Find communities in the graph and return the associated dendrogram A dendrogram is a tree and each level is a partition of the graph nodes. Level 0 is the first partition, which contains the smallest communities, and the best is len(dendrogram) - 1. The higher the level is, the bigger are the communities Parameters ---------- graph : networkx.Graph the networkx graph which will be decomposed part_init : dict, optional the algorithm will start using this partition of the nodes. It's a dictionary where keys are their nodes and values the communities weight : str, optional the key in graph to use as weight. Default to 'weight' resolution : double, optional Will change the size of the communities, default to 1. represents the time described in "Laplacian Dynamics and Multiscale Modular Structure in Networks", R. Lambiotte, J.-C. Delvenne, M. Barahona Returns ------- dendrogram : list of dictionaries a list of partitions, ie dictionnaries where keys of the i+1 are the values of the i. and where keys of the first are the nodes of graph Raises ------ TypeError If the graph is not a networkx.Graph See Also -------- best_partition Notes ----- Uses Louvain algorithm References ---------- .. 1. Blondel, V.D. et al. Fast unfolding of communities in large networks. J. Stat. Mech 10008, 1-12(2008). Examples -------- >>> G=nx.erdos_renyi_graph(100, 0.01) >>> dendo = generate_dendrogram(G) >>> for level in range(len(dendo) - 1) : >>> print("partition at level", level, >>> "is", partition_at_level(dendo, level)) :param weight: :type weight: """ if graph.is_directed(): raise TypeError("Bad graph type, use only non directed graph") # special case, when there is no link # the best partition is everyone in its community if graph.number_of_edges() == 0: part = dict([]) for node in graph.nodes(): part[node] = node return [part] current_graph = graph.copy() #status = Status() #status.init(current_graph, weight, part_init) status_list = list() posStatus = Status() posGraph = nx.Graph() posGraph.add_nodes_from(current_graph.nodes) posGraph.add_edges_from([(a, b, { 'weight': c }) for (a, b, c) in current_graph.edges.data('weight', default=1) if c > 0]) posStatus.init(posGraph, weight, part_init) #posStatus.list=list() negStatus = Status() negGraph = nx.Graph() negGraph.add_nodes_from(current_graph.nodes) negGraph.add_edges_from([(a, b, { 'weight': -c }) for (a, b, c) in current_graph.edges.data('weight', default=-1) if c < 0]) negStatus.init(negGraph, weight, part_init) #negStatus.list = list() print(posStatus.total_weight) print(negStatus.total_weight) print(len(negGraph.nodes()), len(posGraph.nodes())) print(len(negGraph.edges()), len(posGraph.edges())) #print(negGraph.nodes(),negGraph.edges()) #print(current_graph.edges.data('weight', default=-1)) #print(current_graph.edges.data('weight', default=0)) __one_level(posGraph, negGraph, posStatus, negStatus, weight, resolution, randomize) #TODO Edit one_levl function posMul = float(posStatus.total_weight / (posStatus.total_weight + negStatus.total_weight)) #Multip by 2 is impactless negMul = float(negStatus.total_weight / (posStatus.total_weight + negStatus.total_weight)) #Multip by 2 is impactless new_mod = posMul * __modularity(posStatus) - negMul * __modularity( negStatus) #TODO check modularity works correct partition = __renumber(posStatus.node2com) status_list.append(partition) mod = new_mod #current_graph = induced_graph(partition, current_graph, weight) #status.init(current_graph, weight) posGraph = induced_graph(partition, posGraph, weight) posStatus.init(posGraph, weight, part_init) negGraph = induced_graph(partition, negGraph, weight) negStatus.init(negGraph, weight, part_init) print(" WHile ") while True: print(" WHile ") __one_level(posGraph, negGraph, posStatus, negStatus, weight, resolution, randomize) #__one_level(current_graph, status, weight, resolution, randomize) #new_mod = __modularity(status) pos_mod = __modularity(posStatus) neg_mod = __modularity(negStatus) new_mod = posMul * pos_mod - negMul * neg_mod #TODO Sth is not double if new_mod - mod < __MIN: break partition = __renumber(posStatus.node2com) status_list.append(partition) mod = new_mod posGraph = induced_graph(partition, posGraph, weight) negGraph = induced_graph(partition, negGraph, weight) posStatus.init(posGraph, weight) negStatus.init(negGraph, weight) print("\n\n\n our modularity: ", mod) print("eow WHile ") return status_list[:]