def start_evolution(self, verbose): print("=== Pieces: {}\n".format(len(self._pieces))) if verbose: plot = Plot(self._image) ImageAnalysis.analyze_image(self._pieces) fittest = None best_fitness_score = float("-inf") termination_counter = 0 for generation in range(self._generations): print_progress(generation, self._generations - 1, prefix="=== Solving puzzle: ") new_population = [] # Elitism elite = self._get_elite_individuals(elites=self._elite_size) new_population.extend(elite) selected_parents = roulette_selection(self._population, elites=self._elite_size) for first_parent, second_parent in selected_parents: crossover = Crossover(first_parent, second_parent) crossover.run() child = crossover.child() new_population.append(child) fittest = self._best_individual() if fittest.fitness <= best_fitness_score: termination_counter += 1 else: best_fitness_score = fittest.fitness if termination_counter == self.TERMINATION_THRESHOLD: print("\n\n=== GA terminated") print("=== There was no improvement for {} generations".format( self.TERMINATION_THRESHOLD)) return fittest self._population = new_population if verbose: plot.show_fittest( fittest.to_image(), "Generation: {} / {}".format(generation + 1, self._generations)) return fittest
def start_evolution(self, verbose): with open('result_file_%d.csv' % Config.round_id, 'w') as f: line = "%s,%s,%s,%s,%s,%s,%s\n" % ( 'time', 'cog_index', 'correct_in_db', 'total_in_db', 'correct_in_GA', 'total_in_GA', 'precision') f.write(line) ''' print("=== Pieces: {}\n".format(len(self._pieces))) ''' if verbose: from gaps.plot import Plot plot = Plot(self._image) #ImageAnalysis.analyze_image(self._pieces) start_time = time.time() fittest = None best_fitness_score = float("-inf") solution_found = False if Config.multiprocess: data_q = Queue() res_q = Queue() processes = [] for pid in range(Config.process_num): p = Process(target=worker, args=(pid, start_time, self._pieces[:], 0)) p.start() processes.append(p) redis_key = 'round:%d:parents' % (Config.round_id) redis_cli.hdel(redis_key, 'process:%d' % pid) redis_key = 'round:%d:children' % (Config.round_id) redis_cli.hdel(redis_key, 'process:%d' % pid) old_crowd_edge_count = 1 for generation in range(self._generations): if not Config.cli_args.online and not Config.cli_args.hide_detail: print_progress(generation, self._generations - 1, prefix="=== Solving puzzle offline: ", start_time=start_time) refreshTimeStamp(start_time) ## In crowd-based algorithm, we need to access database to updata fintess measure ## at the beginning of each generation. # update fitness from database. generation_start_time = time.time() db_update() if not Config.cli_args.hide_detail: print("edge_count:{}/edge_prop:{}".format( db_update.crowd_edge_count, db_update.crowd_edge_count / Config.total_edges)) redis_key = 'round:%d:dissimilarity' % Config.round_id dissimilarity_json = json.dumps(dissimilarity_measure.measure_dict) #print(dissimilarity_json) redis_cli.set(redis_key, dissimilarity_json) # calculate dissimilarity and best_match_table. ImageAnalysis.analyze_image(self._pieces) # fitness of all individuals need to be re-calculated. for _individual in self._population: _individual._objective = None _individual._fitness = None db_update_time = time.time() new_population = [] # random.shuffle(self._population) self._population.sort(key=attrgetter("objective")) #print(','.join([str(ind.get_pieces_id_list()) for ind in self._population])) # Elitism # elite = self._get_elite_individuals(elites=self._elite_size) elite = self._population[-self._elite_size:] new_population.extend(elite) if Config.fitness_func_name == 'rank-based': #!!! self._population needs to be sorted first # for rank, indiv in enumerate(self._population): # indiv.calc_rank_fitness(rank) self.calc_rank_fitness() select_elite_time = time.time() if solution_found: print("GA found a solution for round {}!".format( Config.round_id)) if Config.cli_args.online: GA_time = time.time() - ( mongo_wrapper.get_round_start_milisecs() / 1000.0) print("GA time: %.3f" % GA_time) else: winner_time = mongo_wrapper.get_round_winner_time_milisecs( ) / 1000.0 GA_time = time.time() - start_time + \ mongo_wrapper.get_round_winner_time_milisecs() * Config.offline_start_percent / 1000.0 print("solved, winner time: %.3f, GA time: %.3f" % (winner_time, GA_time)) if Config.multiprocess: for p in processes: p.terminate() notify_crowdjigsaw_server() exit(0) self._get_common_edges(elite[:4]) selected_parents = roulette_selection(self._population, elites=self._elite_size) select_parent_time = time.time() result = set() if Config.multiprocess: # multiprocessing worker_args = [] # assign equal amount of work to process_num-1 processes redis_key = 'round:%d:parents' % (Config.round_id) redis_data = {} for pid in range(Config.process_num): parents_data = json.dumps([(f_parent.get_pieces_id_list(), s_parent.get_pieces_id_list()) for (f_parent, s_parent) in selected_parents[(len(selected_parents)//Config.process_num)*pid \ : (len(selected_parents)//Config.process_num)*(pid+1)]]) redis_data['process:%d' % pid] = parents_data redis_cli.hmset(redis_key, redis_data) redis_key = 'round:%d:children' % (Config.round_id) for pid in range(Config.process_num): while True: children_json = redis_cli.hget(redis_key, 'process:%d' % pid) if children_json: children_data = json.loads(children_json) if children_data: if len(children_data) != 49: continue redis_key = 'round:%d:parents' % ( Config.round_id) redis_cli.hdel(redis_key, 'process:%d' % pid) redis_key = 'round:%d:children' % ( Config.round_id) redis_cli.hdel(redis_key, 'process:%d' % pid) result.update(children_data) break else: # non multiprocessing for first_parent, second_parent in selected_parents: crossover = Crossover(first_parent, second_parent) crossover.run() child = crossover.child() result.add(','.join( [str(_) for _ in child.get_pieces_id_list()])) while len(result) < len(selected_parents): random_child = [str(i) for i in range(len(self._pieces))] np.random.shuffle(random_child) result.add(','.join(random_child)) result = list(map(lambda x: [int(_) for _ in x.split(',')], result)) result = [ Individual([self._pieces[_] for _ in c], Config.cli_args.rows, Config.cli_args.cols, False) for c in result ] new_population.extend(result) for child in new_population: if child.is_solution(): fittest = child redis_key = 'round:' + str(Config.round_id) + ':GA_edges' res = redis_cli.set(redis_key, json.dumps(list(child.edges_set()))) solution_found = True break crossover_time = time.time() if not solution_found: fittest = self._best_individual() if fittest.fitness > best_fitness_score: best_fitness_score = fittest.fitness self._population = new_population if verbose: from gaps.plot import Plot plot.show_fittest( fittest.to_image(), "Generation: {} / {}".format(generation + 1, self._generations)) times = { 'generation_time': time.time() - generation_start_time, 'db_update_time': db_update_time - generation_start_time, 'select_elite_time': select_elite_time - db_update_time, 'select_parent_time': select_parent_time - select_elite_time, 'crossover_time': crossover_time - select_parent_time } print(times) return fittest
def worker(pid, start_time, pieces, elite_size): def calc_rank_fitness(population): rank1 = 0 while rank1 < len(population): fitness1 = Config.get_rank_fitness(rank1, len(population)) indiv1 = population[rank1] rank2 = rank1 + 1 for rank2 in range(rank1 + 1, len(population)): indiv2 = population[rank2] if abs(indiv1.objective - indiv2.objective) > 1e-6: break fitness2 = Config.get_rank_fitness(rank2 - 1, len(population)) for indiv in population[rank1:rank2]: indiv._fitness = (fitness1 + fitness2) / 2.0 rank1 = rank2 from gaps.crowd.fitness import db_update children = set() while True: redis_key = 'round:%d:dissimilarity' % Config.round_id dissimilarity_json = redis_cli.get(redis_key) if dissimilarity_json: dissimilarity_measure.measure_dict = json.loads(dissimilarity_json) else: continue refreshTimeStamp(start_time) #db_update() ImageAnalysis.analyze_image(pieces) redis_key = 'round:%d:parents' % (Config.round_id) parents_json = redis_cli.hget(redis_key, 'process:%d' % pid) parents = [] elite = [] if parents_json: parents_data = json.loads(parents_json) #print(pid, len(parents_data)) if parents_data and len(parents_data) == 49: parents = [(Individual([pieces[_] for _ in f], Config.cli_args.rows, Config.cli_args.cols, False), Individual([pieces[_] for _ in s], Config.cli_args.rows, Config.cli_args.cols, False)) for (f, s) in parents_data] #print('process %d get %d parents from redis' % (pid, len(parents))) if not parents: if not children: continue children = list( map(lambda x: [int(_) for _ in x.split(',')], children)) children = [ Individual([pieces[_] for _ in c], Config.cli_args.rows, Config.cli_args.cols, False) for c in children ] children.sort(key=attrgetter("objective")) elite = children[-elite_size:] if elite_size > 0 else [] calc_rank_fitness(children) parents = roulette_selection(children, elites=elite_size) #print('process %d get %d parents from itself' % (pid, len(parents))) children = set() for first_parent, second_parent in parents: crossover = Crossover(first_parent, second_parent) crossover.run() child = crossover.child() children.add(','.join([str(_) for _ in child.get_pieces_id_list()])) #print(len(children)) while len(children) < 49: random_child = [str(i) for i in range(len(pieces))] np.random.shuffle(random_child) #print(random_child) children.add(','.join(random_child)) #print(len(children)) #print('process %d put %d children' % (pid, len(children))) redis_key = 'round:%d:children' % (Config.round_id) children_data = json.dumps(list(children)) redis_cli.hset(redis_key, 'process:%d' % pid, children_data)
def start_evolution(self, verbose): print("=== Pieces: {}\n".format(len(self._pieces))) if verbose: plot = Plot(self._image) ImageAnalysis.analyze_image(self._pieces) fittest = None best_fitness_score = float("-inf") termination_counter = 0 for generation in range(self._generations): print_progress(generation, self._generations - 1, prefix="=== Solving puzzle: ") new_population = [] # Elitism # 取适应度最高的两个图片 elite = self._get_elite_individuals(elites=self._elite_size) new_population.extend(elite) # 从种群中随机选择popultation - elite_size个父母 selected_parents = roulette_selection(self._population, elites=self._elite_size) # 通过父母生成子代,加入到new_population中 for first_parent, second_parent in selected_parents: # 交叉互换,生成子代 crossover = Crossover(first_parent, second_parent) crossover.run() child = crossover.child() # child.mutate() new_population.append(child) # 从上一代中选出适应度最高的一个 fittest = self._best_individual() fittest.mutate() # min_fitness = 0 # for index in range(len(new_population)): # if new_population[index].fitness < new_population[min_fitness].fitness: # min_fitness = index # fittest.clear_fitness() # if fittest.fitness > new_population[min_fitness].fitness: # new_population[min_fitness] = fittest print("old_fittest : ", fittest.fitness, end="") # image = fittest.to_image() # rightImage = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) # cv2.imwrite("temp_image_" + str(generation) + ".jpg", rightImage) best_adjoin = fittest.best_adjoin(self._piece_size) rightImage = cv2.cvtColor(best_adjoin, cv2.COLOR_RGB2BGR) cv2.imwrite("temp_image_best_adjoin_" + str(generation) + ".jpg", rightImage) # penalisze = fittest.penalize() # print(" new_fittest : ", fittest.fitness) # rightImage = cv2.cvtColor(penalize, cv2.COLOR_RGB2BGR) # cv2.imwrite("temp_image_penalize_" + str(generation) + ".jpg", rightImage) # 如果上一代最佳比历史最佳好,则termination_counter += 1,否则替换 if fittest.fitness < best_fitness_score: termination_counter += 1 else: best_fitness_score = fittest.fitness termination_counter = 0 if termination_counter % 4 == 2: predicate = Individual(fittest.pieces, fittest.rows, fittest.columns, shuffle=False) predicate.penalize_image = fittest.penalize_image # 处理局部最优 predicate.manually_select() # predicate.shuffle_assembling() print("predicate_fitness : %s " % str(predicate.fitness)) image = predicate.to_image() rightImage = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) cv2.imwrite("predicate_image_" + str(generation) + ".jpg", rightImage) for index in range(len(new_population)): if new_population[index].fitness < predicate.fitness: new_population[index] = predicate break # 如果连续十代都没有更优子代,则退出 if termination_counter == self.TERMINATION_THRESHOLD: print("\n\n=== GA terminated") print("=== There was no improvement for {} generations".format( self.TERMINATION_THRESHOLD)) return fittest self._population = new_population if verbose: plot.show_fittest( fittest.to_image(), "Generation: {} / {}".format(generation + 1, self._generations)) return fittest