• Caution

    • 원서에 있는 코드와 다른 부분이 다소 있음.




  • Main code

    import random
    from ch3.selection_rank_with_elite import selection_rank_with_elite
    from ch3.selection_proportional_with_elite import selection_proportional_with_elite
    from ch3.individual import Individual
     
    POPULATION_SIZE = 5  # 개체군 크기 설정
    random.seed(3)  # 난수 시드 고정 (동일한 난수 생성)
     
    # 개체군 생성
    population = Individual.create_random_population(POPULATION_SIZE)
     
    # Rank selection with elite 방식으로 개체 선택 (elite_size=1로 상위 1개 개체는 무조건 선택)
    selected = selection_rank_with_elite(population, elite_size=1)
    # Proportinal selection with elite 방식으로 개체 선택 (elite_size=1로 상위 1개 개체는 무조건 선택)
    selected = selection_proportional_with_elite(population, elite_size=1)
    # 생성된 개체군과 선택된 개체 출력
    print(f"Population: {population}")
    print(f"Selected: {selected}")
    • Result


    • Rank selection base

      • 순위 선택을 기반으로 한 엘리트 선택
        import random
         
        def selection_rank_with_elite(individuals, elite_size=0):  # elite_size는 상위 몇 개를 엘리트 선택으로 가져올 것인지 결정
         
            # 1. 개체들을 fitness 값에 따라 내림차순으로 정렬
            sorted_individuals = sorted(individuals, key=lambda ind: ind.fitness, reverse=True)
         
            # 2. 엘리트 선택: 상위 elite_size개의 개체를 먼저 선택
            selected = sorted_individuals[0:elite_size]
            
            # 3. 엘리트 개체를 제외한 나머지 개체들로 리스트 갱신
            del sorted_individuals[0:elite_size]
         
            # 4. 순위 선택을 위한 준비 작업
            rank_distance = 1 / len(sorted_individuals)  # 각 개체 간 순위 점수 차이 계산
            ranks = [(1 - i * rank_distance) for i in range(len(sorted_individuals))]  # 순위에 따른 가중치 부여
            ranks_sum = sum(ranks)  # 모든 가중치의 합 계산
            
            # 5. 엘리트 선택에서 제외된 개체들 중에서 순위 선택 방식으로 추가 개체를 선택
            shave = random.random() * ranks_sum  # 0과 ranks_sum 사이의 랜덤 값 생성
            rank_sum = 0  # 누적 가중치 초기화
         
            for i in range(len(sorted_individuals)):
                rank_sum += ranks[i]  # 현재 개체의 가중치를 누적
                if rank_sum >= shave:  # 누적 가중치가 shave 값을 초과하면 해당 개체 선택
                    selected.append(sorted_individuals[i])
                    break  # 선택했으므로 반복 종료
         
            # 6. 선택된 개체 리스트 반환
            return selected  

    • Proportional selection base

      • 비례 선택을 기반으로 한 엘리트 선택
        import random
         
        def selection_proportional_with_elite_1(individuals, elite_size=0):
            
            # 1. 개체들을 fitness 값에 따라 내림차순으로 정렬
            sorted_individuals = sorted(individuals, key=lambda ind: ind.fitness, reverse=True)
            
            # 2. 엘리트 선택: 상위 elite_size개의 개체를 먼저 선택
            selected = sorted_individuals[0:elite_size]
         
            # 3. 엘리트 개체를 제외한 나머지 개체들로 리스트 갱신
            del sorted_individuals[0:elite_size]
         
            # 4. 전체 fitness 값의 합을 계산
            fitness_sum = sum(ind.fitness for ind in sorted_individuals)
            
            # 5-1. 0과 fitness_sum 사이의 무작위 값 생성 (룰렛 휠에서 화살표 역할)
            shave = random.random() * fitness_sum
            roulette_sum = 0  # 룰렛 휠의 현재 값 초기화
         
            # 5-2. 룰렛 휠을 돌려 선택 과정 수행
            for ind in sorted_individuals:
                print(shave, roulette_sum)  # 디버깅용 출력 (필요 없으면 제거 가능)
                roulette_sum += ind.fitness  # 현재 개체의 fitness 값을 누적
         
                5-3. 누적 fitness 값이 무작위로 선택된 값(shave)을 초과하면 해당 개체 선택
                if roulette_sum > shave:
                    selected.append(ind)
                    break  # 한 개체를 선택했으므로 반복 종료
         
            # 6. 선택된 개체 리스트 반환
            return selected




  • Pros, Cons

    장점단점
    우수 개체 보존 및 손실 방지개체 다양성 감소
    빠른 수렴 및 빠른 성능 개선 가능지역 최적화 문제 심화
    알고리즘 안정성 증가과도한 편향 위험
    전반적인 알고리즘 성능 향상