• Caution

    • 주의! 원서에 있는 코드랑 다른 부분이 존재합니다!

      • 1, 52 ~ 116번 줄 - 계속 에러가 나서 GPT에게 물어보니 Windows 환경에서 꼭 필요한 코드라네요
      • 서버에서 실행시 필요 없는 부분
        from multiprocessing import freeze_support
         
        def main():
            ```
        if __name__ == '__main__':
          freeze_support()
          main()
      • 58~61번 줄 - 94번 줄 보면 Z가 있는데 이전 코드들에서 Z가 정의되지 않아 추가해줌
        # 94번 줄
        im = plt.imshow(Z, cmap=cm.bwr, extent=[-10, 10, -10, 10])
         
        # 추가된 내용
        X_range = arange(-10, 10, 0.2)
        Y_range = arange(-10, 10, 0.2)
        X, Y = meshgrid(X_range, Y_range)
        Z = func(X, Y)
    • Windows 환경에서 실행 시 시간이 오래 걸립니다!



  • Population size

    from multiprocessing import freeze_support
    import random
    from typing import List
    from numpy import arange
    import matplotlib.pyplot as plt
    from pylab import meshgrid, cm
     
    from ch7.toolbox import (
        crossover_blend,
        mutation_random_deviation,
        constraints,
        selection_rank_with_elite,
        crossover_operation,
        mutation_operation,
    )
     
    # 최적화할 함수 정의
    def func(x, y):
        return -10 * (pow(x, 5) / (3 * pow(x * x * x / 3 + 1, 2) + pow(y, 4) + 10) + pow(x * y / 2, 2) / 1000) + x / 2
     
    # 개체 클래스 정의
    class Individual:
        counter = 0
     
        def __init__(self, gene_list: List[float]) -> None:
            self.gene_list = [constraints(g) for g in gene_list]
            self.fitness = round(func(self.gene_list[0], self.gene_list[1]), 2)
            self.__class__.counter += 1
            self.id = self.__class__.counter
     
        def __str__(self):
            return f'x: {self.gene_list[0]}, y: {self.gene_list[1]}, fitness: {self.fitness}'
     
    # 교차 연산
    def crossover(parent1, parent2):
        child1_genes, child2_genes = crossover_blend(parent1.gene_list, parent2.gene_list, 0.8)
        return Individual(child1_genes), Individual(child2_genes)
     
    # 돌연변이 연산
    def mutate(ind):
        mutated_gene = mutation_random_deviation(ind.gene_list, 0, 1, 0.8)
        return Individual(mutated_gene)
     
    # 선택 연산
    def select(population):
        return selection_rank_with_elite(population, elite_size=2)
     
    # 무작위 개체 생성
    def create_random():
        return Individual([
            round(random.uniform(-10, 10), 2),
            round(random.uniform(-10, 10), 2)
        ])
     
    def main():
        POPULATION_SIZE = 8                   # 집단의 개체 수
        CROSSOVER_PROBABILITY = 0.8           # 교차 확률
        MUTATION_PROBABILITIES = [0, 0.3, 1]  # 실험할 돌연변이 확률 목록
        MAX_GENERATIONS = 10                  # 최대 세대 수
     
        X_range = arange(-10, 10, 0.2)        # x축 범위 생성
        Y_range = arange(-10, 10, 0.2)        # y축 범위 생성
        X, Y = meshgrid(X_range, Y_range)     # 2차원 격자 좌표 생성
        Z = func(X, Y)                        # 목적 함수의 함수값 계산 (히트맵용)
     
        # 각 돌연변이 확률에 대해 실험 반복
        for MUTATION_PROBABILITY in MUTATION_PROBABILITIES:
            # 초기 개체 집단 생성
            first_population = [create_random() for _ in range(POPULATION_SIZE)]
            # 초기 최적 개체 선택
            best_individual = random.choice(first_population)
            # 세대 수 초기화
            generation_number = 0
            # 현재 집단 복사
            population = first_population.copy()
     
            # 최대 세대 수만큼 반복
            while generation_number < MAX_GENERATIONS:
                # 세대 수 증가
                generation_number += 1
                # 선택 연산으로 자식 개체 생성
                offspring = select(population)
                # 교차 확률에 따라 교차 연산 수행
                crossed_offspring = crossover_operation(offspring, crossover, CROSSOVER_PROBABILITY)
                # 돌연변이 확률에 따라 돌연변이 연산 수행
                mutated_offspring = mutation_operation(crossed_offspring, mutate, MUTATION_PROBABILITY)
                # 새로운 집단으로 교체
                population = mutated_offspring.copy()
                # 이번 세대의 최고 개체 찾기
                best_of_generation = max(population, key=lambda ind: ind.fitness)
     
                # 현재까지의 최고 개체보다 나으면 업데이트
                if best_individual.fitness < best_of_generation.fitness:
                    best_individual = best_of_generation
     
            # 히트맵 시각화
            im = plt.imshow(Z, cmap=cm.bwr, extent=[-10, 10, -10, 10])
            # 색상 바 추가
            plt.colorbar(im)
            # 축 눈금 제거
            plt.xticks([])
            plt.yticks([])
            # 그래프 제목 설정
            plt.title(f"Mutation Probability: {MUTATION_PROBABILITY}, Generation: {generation_number}\n"
                    f"Best Individual: {best_individual.fitness}")
            # 현재 세대의 개체 분포 시각화
            plt.scatter([ind.gene_list[0] for ind in population],
                        [ind.gene_list[1] for ind in population], color='black')
            # 그래프 화면에 출력
            plt.show()
            # 콘솔에 최적 개체 정보 출력
            print(f'Best Individual : {best_individual} for mutation probability: {MUTATION_PROBABILITY}')
     
    if __name__ == '__main__':
        freeze_support()
        main()
    • Results