예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
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)
예제 #4
0
    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