├── .gitignore ├── README.md ├── Datasets └── Dynamic │ └── Custom │ ├── graph-2.csv │ ├── graph-3.csv │ └── graph-1.csv ├── app ├── __pycache__ │ ├── bcsa.cpython-37.pyc │ ├── analysis.cpython-37.pyc │ ├── bcsa_dcd.cpython-37.pyc │ ├── food_source.cpython-37.pyc │ ├── functions.cpython-37.pyc │ ├── read_network.cpython-37.pyc │ ├── read_configuration.cpython-37.pyc │ └── population_initializer.cpython-37.pyc ├── read_configuration.py ├── food_source.py ├── write_results.py ├── bcsa_dcd.py ├── read_network.py ├── main.py ├── analysis.py ├── functions.py ├── population_initializer.py └── bcsa.py ├── config.csv ├── Dynamic network generator └── generate_dynamic_benchmark.py └── test_algorithms ├── cnm.py ├── label_propagation.py ├── gn.py ├── read_network.py └── functions.py /.gitignore: -------------------------------------------------------------------------------- 1 | Datasets/** 2 | **/__pycache__/** 3 | results.csv -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # An artificial bee colony and simulated annealing algorithm for dynamic community detection 2 | -------------------------------------------------------------------------------- /Datasets/Dynamic/Custom/graph-2.csv: -------------------------------------------------------------------------------- 1 | 9 8 2 | 7 9 3 | 7 8 4 | 0 1 5 | 1 2 6 | 2 0 7 | 1 3 8 | 3 2 9 | 4 5 10 | 5 6 11 | 6 4 12 | 3 5 13 | 6 7 14 | 1 9 -------------------------------------------------------------------------------- /Datasets/Dynamic/Custom/graph-3.csv: -------------------------------------------------------------------------------- 1 | 1 2 2 | 2 3 3 | 3 1 4 | 3 5 5 | 5 4 6 | 4 6 7 | 6 5 8 | 4 9 9 | 6 7 10 | 9 7 11 | 6 9 12 | 9 8 13 | 7 8 14 | 5 8 -------------------------------------------------------------------------------- /Datasets/Dynamic/Custom/graph-1.csv: -------------------------------------------------------------------------------- 1 | 0 1 2 | 0 2 3 | 1 2 4 | 1 9 5 | 9 8 6 | 8 7 7 | 7 9 8 | 2 3 9 | 7 6 10 | 3 6 11 | 4 5 12 | 3 4 13 | 5 6 14 | 3 5 15 | 4 6 -------------------------------------------------------------------------------- /app/__pycache__/bcsa.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meanis/Artificial-Bee-Colony-Optimization-for-dynamic-community-detection/HEAD/app/__pycache__/bcsa.cpython-37.pyc -------------------------------------------------------------------------------- /app/__pycache__/analysis.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meanis/Artificial-Bee-Colony-Optimization-for-dynamic-community-detection/HEAD/app/__pycache__/analysis.cpython-37.pyc -------------------------------------------------------------------------------- /app/__pycache__/bcsa_dcd.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meanis/Artificial-Bee-Colony-Optimization-for-dynamic-community-detection/HEAD/app/__pycache__/bcsa_dcd.cpython-37.pyc -------------------------------------------------------------------------------- /app/__pycache__/food_source.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meanis/Artificial-Bee-Colony-Optimization-for-dynamic-community-detection/HEAD/app/__pycache__/food_source.cpython-37.pyc -------------------------------------------------------------------------------- /app/__pycache__/functions.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meanis/Artificial-Bee-Colony-Optimization-for-dynamic-community-detection/HEAD/app/__pycache__/functions.cpython-37.pyc -------------------------------------------------------------------------------- /app/__pycache__/read_network.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meanis/Artificial-Bee-Colony-Optimization-for-dynamic-community-detection/HEAD/app/__pycache__/read_network.cpython-37.pyc -------------------------------------------------------------------------------- /app/__pycache__/read_configuration.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meanis/Artificial-Bee-Colony-Optimization-for-dynamic-community-detection/HEAD/app/__pycache__/read_configuration.cpython-37.pyc -------------------------------------------------------------------------------- /config.csv: -------------------------------------------------------------------------------- 1 | nb_exec:1 2 | nb_s:100 3 | nb_cycles:50 4 | limit_cycles:10 5 | employed_bees_percentage:0.5 6 | T0:1000 7 | Tmin:100 8 | alpha:0.6 9 | cycles_per_t:5 10 | gamma:0.8 11 | sigma:0 12 | delta:0.05 -------------------------------------------------------------------------------- /app/__pycache__/population_initializer.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meanis/Artificial-Bee-Colony-Optimization-for-dynamic-community-detection/HEAD/app/__pycache__/population_initializer.cpython-37.pyc -------------------------------------------------------------------------------- /Dynamic network generator/generate_dynamic_benchmark.py: -------------------------------------------------------------------------------- 1 | from rdyn import RDyn 2 | import sys 3 | 4 | def main(argv): 5 | 6 | gen = RDyn(size=200, iterations=200, avg_deg=4, sigma=.8) 7 | gen.execute(simplified=True) 8 | 9 | if __name__ == '__main__': 10 | sys.exit(main(sys.argv)) -------------------------------------------------------------------------------- /app/read_configuration.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | def read(file_): 4 | 5 | params = {} 6 | 7 | with open(file_) as file: 8 | reader = csv.reader(file, delimiter=':') 9 | 10 | for line in reader: 11 | params[line[0]]=float(line[1]) 12 | 13 | return params -------------------------------------------------------------------------------- /test_algorithms/cnm.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import csv 3 | from networkx.algorithms.community import greedy_modularity_communities 4 | 5 | from functions import cost 6 | import read_network 7 | 8 | def main(argv): 9 | 10 | g = read_network.read_static_network(argv[1]) 11 | 12 | cnm_output = greedy_modularity_communities(g) 13 | print('modularité maximale détectée par CNM: ', cost(cnm_output, g)) 14 | 15 | if __name__ == '__main__': 16 | sys.exit(main(sys.argv)) -------------------------------------------------------------------------------- /app/food_source.py: -------------------------------------------------------------------------------- 1 | class food_source(object): 2 | 3 | def __init__(self, initial_solution, initial_cost): 4 | 5 | super(food_source, self).__init__() 6 | 7 | self.trials = 0 8 | 9 | self.solution = initial_solution 10 | self.cost = initial_cost 11 | 12 | def increment_trials(self): 13 | self.trials +=1 14 | 15 | def __repr__(self): 16 | 17 | return f'' -------------------------------------------------------------------------------- /test_algorithms/label_propagation.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import csv 3 | from networkx.algorithms.community import asyn_lpa_communities 4 | 5 | from functions import modularity 6 | import read_network 7 | 8 | def main(argv): 9 | 10 | g = read_network.read_static_network(argv[1]) 11 | 12 | label_propagation_algorithm_output = list(asyn_lpa_communities(g)) 13 | print('''modularité maximale détectée par l'algorithme de propagation d'étiquettes: ''', modularity(g, label_propagation_algorithm_output)) 14 | 15 | if __name__ == '__main__': 16 | sys.exit(main(sys.argv)) -------------------------------------------------------------------------------- /test_algorithms/gn.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import csv 3 | from networkx.algorithms.community import girvan_newman 4 | 5 | from functions import modularity 6 | import read_network 7 | 8 | def main(argv): 9 | 10 | g = read_network.read_static_network(argv[1]) 11 | 12 | gn_output = list(girvan_newman(g)) 13 | solutions = [] 14 | for solution in gn_output: 15 | solutions.append(modularity(g, solution)) 16 | 17 | print('modularité maximale détectée par Girvan et Newman: ', max(solutions)) 18 | 19 | if __name__ == '__main__': 20 | sys.exit(main(sys.argv)) -------------------------------------------------------------------------------- /test_algorithms/read_network.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | import networkx as nx 4 | 5 | ######################################################################### 6 | 7 | def read_static_network(file_): 8 | 9 | with open(file_) as file: 10 | 11 | reader = csv.reader(file, delimiter=' ') 12 | 13 | g = nx.Graph() 14 | 15 | for line in reader: 16 | g.add_edge(line[0], line[1]) 17 | g = nx.convert_node_labels_to_integers(g) 18 | 19 | print(nx.info(g)) # debug 20 | 21 | return g 22 | 23 | ######################################################################### -------------------------------------------------------------------------------- /app/write_results.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | def write_results(writer, params, analysis_data): 4 | writer.writerow([ 5 | params['nb_s'], 6 | params['nb_cycles'], 7 | params['limit_cycles'], 8 | params['employed_bees_percentage'], 9 | params['T0'], 10 | params['Tmin'], 11 | params['alpha'], 12 | params['cycles_per_t'], 13 | params['gamma'], 14 | params['sigma'], 15 | params['delta'], 16 | ] + [ 17 | snapshot_analysis_data['global_optimal'][-1] for snapshot_analysis_data in analysis_data 18 | ]) -------------------------------------------------------------------------------- /app/bcsa_dcd.py: -------------------------------------------------------------------------------- 1 | from bcsa import bcsa 2 | from population_initializer import population_initializer as pop_init 3 | 4 | class bcsa_dcd(object): 5 | def __init__(self, params, snapshots): 6 | super(bcsa_dcd, self).__init__() 7 | 8 | ###################################################### 9 | 10 | self.params = params 11 | self.snapshots = snapshots 12 | 13 | ###################################################### 14 | 15 | def execute(self): 16 | 17 | pop_init_ = pop_init(float(self.params['sigma']), int(self.params['nb_s'])) 18 | initial_population = pop_init_.init_snapshot_pop(self.snapshots[0]) 19 | 20 | mobcsa_ = bcsa(self.params) 21 | 22 | community_structures = [] 23 | 24 | analysis_data = [] 25 | 26 | for snapshot in self.snapshots: 27 | community_structure, initial_population, snapshot_analysis_data = mobcsa_.execute(snapshot, initial_population) 28 | community_structures.append(community_structure) 29 | analysis_data.append(snapshot_analysis_data) 30 | 31 | return community_structures, analysis_data -------------------------------------------------------------------------------- /test_algorithms/functions.py: -------------------------------------------------------------------------------- 1 | import networkx as nx 2 | 3 | def cost(cnm_output, network): 4 | 5 | solution = [ 0 for _ in range(0, network.number_of_nodes()) ] 6 | 7 | for c in cnm_output: 8 | for node1 in c: 9 | for node2 in c: 10 | if (node2 in network[node1]): 11 | solution[node1] = node2 12 | 13 | community_structure = locus_decode(solution) 14 | q = modularity(network, community_structure) 15 | return q 16 | 17 | def locus_decode(solution): 18 | 19 | n = len(solution) 20 | g = nx.Graph() 21 | 22 | for i in range(n): 23 | g.add_edge(i, solution[i]) 24 | 25 | return list(nx.connected_components(g)) 26 | 27 | def modularity(network, community_structure): 28 | 29 | m = network.number_of_edges() 30 | 31 | e = [] 32 | a = [] 33 | 34 | for c in community_structure: 35 | 36 | i = network.subgraph(c).number_of_edges() 37 | e.append(i/m) 38 | 39 | j = 0.0 40 | for n in c: 41 | j += network.degree[n] 42 | a.append(j/(2*m)) 43 | 44 | q = 0.0 45 | for ei,ai in zip(e,a): 46 | q += (ei - ai**2) 47 | 48 | return q -------------------------------------------------------------------------------- /app/read_network.py: -------------------------------------------------------------------------------- 1 | from os import listdir 2 | import re 3 | import csv 4 | from copy import deepcopy 5 | 6 | import networkx as nx 7 | 8 | ######################################################################### 9 | 10 | def read_static_network(file_): 11 | 12 | snapshots = [] 13 | 14 | with open(file_) as file: 15 | 16 | reader = csv.reader(file, delimiter=' ') 17 | 18 | g = nx.Graph() 19 | 20 | for line in reader: 21 | g.add_edge(line[0], line[1]) 22 | g = nx.convert_node_labels_to_integers(g) 23 | 24 | print(nx.info(g)) # debug 25 | snapshots.append(g) 26 | 27 | return snapshots 28 | 29 | ######################################################################### 30 | 31 | def read_dynamic_network(folder_): 32 | 33 | snapshots = [] 34 | 35 | network_files = [file_ for file_ in listdir(folder_) if re.match('^graph+.*.csv$', file_)] 36 | g = nx.Graph() 37 | 38 | for file_ in network_files: 39 | 40 | g.remove_edges_from(list(g.edges)) 41 | 42 | file = open(folder_ + '/' + file_) 43 | 44 | reader = csv.reader(file, delimiter=' ') 45 | 46 | for line in reader: 47 | g.add_edge(line[0], line[1]) 48 | 49 | snapshots.append(deepcopy(g)) 50 | 51 | snapshots = [nx.convert_node_labels_to_integers(g) for g in snapshots] 52 | 53 | return snapshots 54 | 55 | ######################################################################### -------------------------------------------------------------------------------- /app/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import csv 3 | 4 | from bcsa_dcd import bcsa_dcd 5 | import read_configuration 6 | import read_network 7 | from write_results import write_results 8 | import analysis as anal 9 | 10 | def main(argv): 11 | 12 | params = read_configuration.read(argv[1]) 13 | 14 | if argv[2] == 'static': 15 | snapshots = read_network.read_static_network(argv[3]) 16 | elif argv[2] == 'dynamic': 17 | snapshots = read_network.read_dynamic_network(argv[3]) 18 | 19 | with open('results.csv', 'w') as _file: 20 | writer = csv.writer(_file, lineterminator = '\n') 21 | writer.writerow([ 22 | 'nb_s', 23 | 'nb_cycles', 24 | 'limit_cycles', 25 | 'employed_bees_percentage', 26 | 'T0', 27 | 'Tmin', 28 | 'alpha', 29 | 'cycles_per_t', 30 | 'gamma', 31 | 'sigma', 32 | 'delta', 33 | ] + [ 34 | f"Modularité of snapshot {i+1}" for i,v in enumerate(snapshots) 35 | ]) 36 | 37 | for _ in range(int(params['nb_exec'])): 38 | print('execution number: ', (_ + 1)) 39 | mobcsa_dcd_ = bcsa_dcd(params, snapshots) 40 | partitions, analysis_data = mobcsa_dcd_.execute() 41 | write_results(writer, params, analysis_data) 42 | 43 | anal.draw(snapshots, partitions, analysis_data) 44 | 45 | if __name__ == '__main__': 46 | sys.exit(main(sys.argv)) -------------------------------------------------------------------------------- /app/analysis.py: -------------------------------------------------------------------------------- 1 | import networkx as nx 2 | import matplotlib.pyplot as plt 3 | 4 | from functions import locus_decode 5 | from functions import node_labeling 6 | 7 | def draw(snapshots, partitions, analysis_data): 8 | 9 | for moment in range(len(snapshots)): 10 | 11 | g = snapshots[moment] 12 | fs = partitions[moment] 13 | snapshot_analysis_data = analysis_data[moment] 14 | 15 | pos = nx.spring_layout(g) 16 | labels = node_labeling(fs.solution) 17 | 18 | plt.figure('Résultat de la détection de communautés') 19 | plt.title('Les communautés du réseau social') 20 | 21 | nx.draw(g, pos=pos, with_labels=True, node_color=labels, node_size=80) 22 | plt.show() 23 | 24 | global_optimals = snapshot_analysis_data['global_optimal'] 25 | plt.figure('Résultat de la détection de communautés') 26 | plt.title("Evolution de la qualité de la solution à travers les cycles de recherche") 27 | plt.bar(range(len(global_optimals)), global_optimals, width=0.1, color='green') 28 | plt.xlabel('cycle de recherche') 29 | plt.ylabel('coût de la meilleure solution trouvée') 30 | 31 | xMax = len(global_optimals) 32 | yMin = global_optimals[0] 33 | yMax = global_optimals[-1] 34 | 35 | plt.text(5, yMax, 'f: ' + str(yMax), style='oblique', bbox={'facecolor':'orange', 'alpha':0.5, 'pad':10}) 36 | plt.axis([0, xMax + 1, yMin - 0.01, yMax + 0.01]) 37 | plt.grid(True, which='both', axis='y') 38 | plt.show() -------------------------------------------------------------------------------- /app/functions.py: -------------------------------------------------------------------------------- 1 | from sklearn.metrics.cluster import normalized_mutual_info_score 2 | from scipy.stats import pearsonr 3 | import networkx as nx 4 | import math 5 | 6 | def modularity(snapshot, community_structure): 7 | 8 | m = snapshot.number_of_edges() 9 | 10 | e = [] 11 | a = [] 12 | 13 | for c in community_structure: 14 | 15 | i = snapshot.subgraph(c).number_of_edges() 16 | e.append(i/m) 17 | 18 | j = 0.0 19 | for n in c: 20 | j += snapshot.degree[n] 21 | a.append(j/(2*m)) 22 | 23 | q = 0.0 24 | for ei,ai in zip(e,a): 25 | q += (ei - ai**2) 26 | 27 | return q 28 | 29 | def NMI(A, B): 30 | A = node_labeling(A) 31 | B = node_labeling(B) 32 | if (len(A) < len(B)): 33 | B = B[0:len(A)] 34 | return normalized_mutual_info_score(A, B) 35 | 36 | def pearson_correlation(snapshot): 37 | 38 | r = [] 39 | A = nx.to_numpy_array(snapshot) 40 | for n in range(snapshot.number_of_nodes()): 41 | l = [] 42 | for m in snapshot[n]: 43 | x = pearsonr(A[n], A[m])[0] 44 | l.append(1 / (1 + math.exp(-x))) 45 | r.append(l) 46 | return r 47 | 48 | def locus_decode(solution): 49 | 50 | n = len(solution) 51 | g = nx.Graph() 52 | 53 | for i in range(n): 54 | g.add_edge(i, solution[i]) 55 | 56 | return list(nx.connected_components(g)) 57 | 58 | def node_labeling(solution): 59 | 60 | labels = [0 for _ in range(len(solution))] 61 | partition = locus_decode(solution) 62 | 63 | label = 0 64 | for community in partition: 65 | for member in community: 66 | labels[member] = label 67 | label += 1 68 | 69 | return labels -------------------------------------------------------------------------------- /app/population_initializer.py: -------------------------------------------------------------------------------- 1 | import random as rand 2 | import networkx as nx 3 | from networkx.algorithms.community import greedy_modularity_communities 4 | 5 | import functions as fun 6 | from food_source import food_source 7 | 8 | class population_initializer(object): 9 | 10 | def __init__(self, sigma, nb_s): 11 | super(population_initializer, self).__init__() 12 | 13 | ###################################################### 14 | 15 | self.rand_fs_number = round(nb_s * (1 - sigma)) 16 | self.elite_fs_number = round(nb_s * sigma) 17 | 18 | ###################################################### 19 | 20 | def init_snapshot_pop(self, snapshot): 21 | 22 | self.snapshot = snapshot 23 | #self.pearson_correlation = fun.pearson_correlation(self.snapshot) 24 | 25 | population = [] 26 | 27 | rand_population = [self.random_selection() for _ in range(self.rand_fs_number)] 28 | population.extend(rand_population) 29 | 30 | elite_population = [self.elite_selection() for _ in range(self.elite_fs_number)] 31 | population.extend(elite_population) 32 | 33 | return population 34 | 35 | def random_selection(self): 36 | 37 | n = self.snapshot.number_of_nodes() 38 | 39 | solution = [] 40 | 41 | for i in range(0, n): 42 | try: 43 | solution.append(rand.choice(list(self.snapshot[i]))) 44 | #solution = [rand.choices(list(self.snapshot[i]), self.pearson_correlation[i])[0] for i in range(n)] 45 | except IndexError: 46 | solution.append(i) 47 | 48 | cost = self.cost(solution) 49 | 50 | return food_source(solution, cost) 51 | 52 | def elite_selection(self): 53 | 54 | solution = [ 0 for _ in range(0, self.snapshot.number_of_nodes()) ] 55 | 56 | for c in greedy_modularity_communities(self.snapshot): 57 | for node1 in c: 58 | for node2 in c: 59 | if (node2 in self.snapshot[node1]): 60 | solution[node1] = node2 61 | cost = self.cost(solution) 62 | 63 | return food_source(solution, cost) 64 | 65 | def cost(self, solution): 66 | 67 | community_structure = fun.locus_decode(solution) 68 | return fun.modularity(self.snapshot, community_structure) -------------------------------------------------------------------------------- /app/bcsa.py: -------------------------------------------------------------------------------- 1 | from operator import attrgetter 2 | import copy 3 | import random as rand 4 | import numpy as np 5 | import networkx as nx 6 | 7 | from food_source import food_source 8 | import functions as fun 9 | 10 | class bcsa(object): 11 | def __init__(self, params): 12 | super(bcsa, self).__init__() 13 | 14 | ###################################################### 15 | 16 | self.nb_s = int(params['nb_s']) 17 | self.nb_cycles = int(params['nb_cycles']) 18 | self.limit_cycles = int(params['limit_cycles']) 19 | self.employed_bees_number = self.nb_s 20 | 21 | E = params['employed_bees_percentage'] 22 | self.onlooker_bees_number = round(self.nb_s * ((1 / E) - 1)) 23 | 24 | ###################################################### 25 | 26 | self.T0 = params['T0'] 27 | self.Tmin = params['Tmin'] 28 | self.alpha = params['alpha'] 29 | self.cycles_per_t = int(params['cycles_per_t']) 30 | 31 | ###################################################### 32 | 33 | self.gamma = params['gamma'] 34 | self.delta = params['delta'] 35 | 36 | ###################################################### 37 | 38 | self.population = [] 39 | 40 | ###################################################### 41 | 42 | self.snapshot_analysis_data = { 43 | 'global_optimal': [] 44 | } 45 | 46 | ######################################################################################### 47 | 48 | def execute(self, snapshot, initial_population): 49 | 50 | self.snapshot_analysis_data = { 51 | 'global_optimal': [] 52 | } 53 | 54 | self.snapshot = snapshot 55 | #self.pearson_correlation = fun.pearson_correlation(self.snapshot) 56 | 57 | self.last_snapshot_community_structure = max(initial_population, key = attrgetter('cost')).solution 58 | self.population = self.repair_population(initial_population, self.snapshot) 59 | self.global_best_fs = copy.deepcopy(self.best_fs()) 60 | 61 | for _ in range(self.nb_cycles): 62 | self.employed_bees_stage() 63 | self.onlooker_bees_stage() 64 | self.scout_bees_stage() 65 | self.simulated_annealing_stage(self.best_fs()) 66 | 67 | if (self.best_fs().cost > self.global_best_fs.cost ): 68 | self.global_best_fs = copy.deepcopy(self.best_fs()) 69 | print(self.global_best_fs.cost) # debug 70 | 71 | self.snapshot_analysis_data['global_optimal'].append(self.global_best_fs.cost) 72 | 73 | return self.global_best_fs, self.population, self.snapshot_analysis_data 74 | 75 | ######################################################################################### 76 | 77 | def employed_bees_stage(self): 78 | 79 | for index in range(self.employed_bees_number): 80 | fs = self.population[index] 81 | new_fs = self.generate_fs(fs) 82 | 83 | best_fs = self.greedy_selection(fs, new_fs) 84 | 85 | self.update_fs(fs, best_fs) 86 | 87 | ######################################################################################### 88 | 89 | def onlooker_bees_stage(self): 90 | 91 | for _ in range(self.onlooker_bees_number): 92 | 93 | selected_fs = self.global_selection() 94 | new_fs = self.generate_fs(selected_fs) 95 | 96 | best_fs = self.greedy_selection(selected_fs, new_fs) 97 | self.update_fs(selected_fs, best_fs) 98 | 99 | ######################################################################################### 100 | 101 | def scout_bees_stage(self): 102 | 103 | for fs in self.population: 104 | 105 | if fs.trials > self.limit_cycles: 106 | 107 | new_fs = self.random_selection() 108 | 109 | fs.solution = new_fs.solution 110 | fs.cost = new_fs.cost 111 | fs.trials = new_fs.trials 112 | 113 | ######################################################################################### 114 | 115 | def accept(self, new_fs_cost, current_fs_cost, T): 116 | 117 | if (new_fs_cost > current_fs_cost): 118 | return True 119 | else: 120 | r = rand.uniform(1, np.e) 121 | return (r < ( np.exp( ( current_fs_cost - new_fs_cost ) / T ) )) 122 | 123 | def simulated_annealing_stage(self, fs): 124 | 125 | T = self.T0 126 | 127 | while T > self.Tmin: 128 | 129 | for _ in range(self.cycles_per_t): 130 | 131 | new_fs = self.generate_fs(fs) 132 | 133 | if self.accept(new_fs.cost, fs.cost, T): 134 | 135 | fs.solution = new_fs.solution 136 | fs.cost = new_fs.cost 137 | 138 | T = T * self.alpha 139 | 140 | ######################################################################################### 141 | 142 | def generate_fs(self, fs): 143 | 144 | new_solution = fs.solution.copy() 145 | 146 | n = len(fs.solution) 147 | indexes = range(0, n) 148 | chosen_indexes = rand.sample(indexes, int(n * self.delta)) 149 | 150 | for i in chosen_indexes: 151 | try: 152 | new_solution[i] = rand.choice(list(self.snapshot[i])) 153 | #new_solution[i] = rand.choices(list(self.snapshot[i]), self.pearson_correlation[i])[0] 154 | except IndexError: 155 | new_solution[i] = i 156 | 157 | return food_source(new_solution, self.cost(new_solution)) 158 | 159 | ######################################################################################### 160 | 161 | def greedy_selection(self, fs1, fs2): 162 | 163 | if fs1.cost > fs2.cost: 164 | return fs1 165 | else: 166 | return fs2 167 | 168 | ######################################################################################### 169 | 170 | def global_selection(self): 171 | 172 | sum_costs = sum([fs.cost for fs in self.population]) 173 | probabilities = [(fs.cost / sum_costs) for fs in self.population] 174 | 175 | selected_fs = rand.choices(self.population, probabilities)[0] 176 | 177 | return selected_fs 178 | 179 | ######################################################################################### 180 | 181 | def random_selection(self): 182 | 183 | n = self.snapshot.number_of_nodes() 184 | 185 | solution = [] 186 | 187 | for i in range(0, n): 188 | try: 189 | solution.append(rand.choice(list(self.snapshot[i]))) 190 | #solution.append(rand.choices(list(self.snapshot[i]), self.pearson_correlation[i])[0]) 191 | except IndexError: 192 | solution.append(i) 193 | 194 | cost = self.cost(solution) 195 | 196 | return food_source(solution, cost) 197 | 198 | ######################################################################################### 199 | 200 | def cost(self, solution): 201 | 202 | community_structure = fun.locus_decode(solution) 203 | cost = (self.gamma * fun.modularity(self.snapshot, community_structure)) + ((1-self.gamma) * fun.NMI(self.last_snapshot_community_structure, solution)) 204 | return cost 205 | 206 | ######################################################################################### 207 | 208 | def update_fs(self, fs, new_fs): 209 | 210 | if fs.cost == new_fs.cost: 211 | fs.increment_trials() 212 | else: 213 | fs.solution = new_fs.solution 214 | fs.cost = new_fs.cost 215 | fs.trials = new_fs.trials 216 | 217 | ######################################################################################### 218 | 219 | def best_fs(self): 220 | 221 | best_fs = max(self.population, key = attrgetter('cost')) 222 | return best_fs 223 | 224 | ######################################################################################### 225 | 226 | def repair_population(self, initial_population, snapshot): 227 | 228 | for fs in initial_population: 229 | 230 | for v in range(len(fs.solution)): 231 | 232 | if fs.solution[v] not in snapshot[v]: 233 | try: 234 | fs.solution[v] = rand.choice(list(self.snapshot[v])) 235 | except IndexError: 236 | fs.solution[v] = v 237 | 238 | for v in range(len(fs.solution), snapshot.number_of_nodes()): 239 | 240 | try: 241 | fs.solution.append(rand.choice(list(self.snapshot[v]))) 242 | except IndexError: 243 | fs.solution.append(v) 244 | 245 | fs.cost = self.cost(fs.solution) 246 | 247 | return initial_population 248 | 249 | ######################################################################################### --------------------------------------------------------------------------------