• 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}")

    • 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

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