• 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 * y, 2) * x / (3 * pow(x * x * x / 4 + 1, 2) + pow(y, 4) + 1)
     
    # 개체 클래스 정의
    class Individual:
        def __init__(self, gene_list: List[float]) -> None:
            self.gene_list = [constraints(g) for g in gene_list]
            self.fitness = func(self.gene_list[0], self.gene_list[1])
     
        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.5)
        return Individual(child1_genes), Individual(child2_genes)
     
    # 돌연변이 함수
    def mutate(ind):
        mutated_gene = mutation_random_deviation(ind.gene_list, 0, 1, 0.5)
        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_LIST = [6, 10, 20, 50]   # 집단의 개체 수
        CROSSOVER_PROBABILITY = 0.8              # 교차 확률
        MUTATION_PROBABILITY = 0.2               # 돌연변이 확률
        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 POPULATION_SIZE in POPULATION_SIZE_LIST:
            # 초기 개체 집단 생성
            first_population = [create_random() for _ in range(POPULATION_SIZE)]
            # 초기 최적 개체 선택
            best_ind = 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_ind.fitness < best_of_generation.fitness:
                    best_ind = 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"Population size: {POPULATION_SIZE}, Generation: {generation_number}\n"
                    f"Best Individual: {round(best_ind.fitness, 2)}")
            # 개체들의 현재 위치 시각화 (검정색 점)
            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_ind} for population size: {POPULATION_SIZE}')
     
     
    # ✅ 진입점 보호 (Windows 환경에서 반드시 필요)
    if __name__ == '__main__':
        freeze_support()
        main()
    • Results