• Population create

    import random
    from ch3.selection_rank import selection_rank
    from ch3.individual import Individual
     
    POPULATION_SIZE = 5  # 개체군 크기 설정
    random.seed(18)  # 난수 시드를 고정하여 동일한 난수 생성
     
    # 개체군 생성
    population = Individual.create_random_population(POPULATION_SIZE)
     
    # Rank Selection 방식으로 개체 선택
    selected = selection_rank(population)
     
    # 개체군과 선택된 개체 출력
    print(f'Population: {population}')  # 생성된 개체군 출력
    print(f'Selected: {selected}')  # 선택된 개체들 출력
    • ch3
      • selection_rank

        import random
         
        def selection_rank(individuals):
            # 개체들을 fitness 값에 따라 내림차순 정렬
            sorted_individuals = sorted(individuals, key=lambda ind: ind.fitness, reverse=True)
         
            # 개체 수에 맞는 순위 간격 계산
            rank_distance = 1 / len(individuals)
            
            # 각 개체의 순위에 따른 선택 확률 계산
            ranks = [(1 - i * rank_distance) for i in range(len(individuals))]
         
            # 순위 확률의 총합 계산
            ranks_sum = sum(ranks)
            
            # 선택된 개체들을 저장할 리스트
            selected = []
            
            # 선택된 개체 수만큼 반복
            for _ in range(len(sorted_individuals)):
                # 임의의 선택 지점 (룰렛 휠의 '샤브' 위치)
                shave = random.random() * ranks_sum
                
                rank_sum = 0
                
                # 룰렛 휠을 돌리며 선택
                for i in range(len(sorted_individuals)):
                    rank_sum += ranks[i]
                    if rank_sum > shave:
                        # 선택된 개체를 리스트에 추가
                        selected.append(sorted_individuals[i])
                        break
                        
            return selected



  • Visualization

    import random
    import pandas as pd
    import matplotlib.pyplot as plt
    from ch3.individual import Individual  # 개체 클래스 불러오기
     
    # 개체군의 크기 설정
    POPULATION_SIZE = 5
    random.seed(2)
     
    # 랜덤한 개체 생성
    unsorted_population = Individual.create_random_population(POPULATION_SIZE)
    population = sorted(unsorted_population, key=lambda ind: ind.fitness, reverse=True)
     
    # 전체 개체군의 fitness 합계 계산
    fitness_sum = sum([ind.fitness for ind in population])
     
    # 개체별 fitness 값을 저장할 딕셔너리 초기화
    fitness_map = {}
     
    # 각 개체의 fitness 값에 따라 선택 확률 계산
    for i in population:
        i_prob = round(100 * i.fitness / fitness_sum)  # 선택 확률을 백분율(%)로 변환
        i_label = f'{i.name} | fitness: {i.fitness}, prob: {i_prob}%'  # 개체 정보 문자열 생성
        fitness_map[i_label] = i.fitness  # 딕셔너리에 저장 (key: 개체 정보, value: fitness 값)
     
    # 데이터프레임 생성 (개체별 fitness 값을 저장)
    proportional_df = pd.DataFrame(fitness_map, index=['Sectors'])
     
    # 수평 막대 그래프 생성 (개체들의 fitness 비율을 시각화)
    proportional_df.plot.barh(stacked=True)
    plt.tick_params(axis='x', which='both', bottom=False, top=False, labelbottom=False)
    plt.title('Fitness Proportional Sectors')
    plt.show()
     
    # Rank 선택을 위한 비례 확률 계산
    rank_step = 1 / POPULATION_SIZE
    rank_sum = sum([1 - rank_step * i for i in range(len(population))])
     
    # 각 개체의 rank에 따른 선택 확률 계산
    rank_map = {}
     
    for i in range(len(population)):
        i_rank = i + 1  # 개체의 rank (1부터 시작)
        i_rank_proportion = 1 - i * rank_step  # rank에 따른 확률 비율 계산
        i_prob = round(100 * i_rank_proportion / rank_sum)  # 확률을 백분율(%)로 변환
        i_label = f'{population[i].name} | rank: {i_rank}, prob: {i_prob}%'  # 개체 정보 문자열 생성
        rank_map[i_label] = i_rank_proportion  # 딕셔너리에 저장 (key: 개체 정보, value: rank에 따른 확률)
     
    # 데이터프레임 생성 (개체별 rank 확률 값을 저장)
    rank_df = pd.DataFrame(rank_map, index=['Sectors'])
     
    # 수평 막대 그래프 생성 (개체들의 rank 비율을 시각화)
    rank_df.plot.barh(stacked=True)
    plt.tick_params(axis='x', which='both', bottom=False, top=False, labelbottom=False)
    plt.title('Rank Proportional Sectors')
    plt.show()
  • Pros, Cons

    장점단점
    다양성 유지에 좋음매 세대마다 순위 정렬로 인한 추가 비용
    조기 수렴 위험 완화적합도 값의 절대적 차이 무시
    안정적인 선택 압력 유지적합도 동점 처리의 복잡성 존재
    스케일링 문제 완화