ai

GA- 12-24

hyebing_KIM 2023. 12. 24. 19:35
# import
import random
import pandas as pd
import openpyxl
import numpy as np
import matplotlib.pyplot as plt
import copy
# calling the data
Parameter=pd.read_csv(r"C:\Users\user\Desktop\Parameter.csv")
Test_Data_Q=pd.read_csv(r"C:\Users\user\Desktop\Test_Data_Q.csv")
Test_Data_Q=Test_Data_Q.iloc[:36,:20]


# number of row and column
people_row=len(Test_Data_Q) #36
people_column=len(Test_Data_Q.columns) # 20 라인


#coefficients
zero_payload_desel=Parameter.iloc[0,1]
zero_payload_electric=Parameter.iloc[1,1]
variable_electric=Parameter.iloc[0,2]
variable_desel=Parameter.iloc[1,2]
ratio_desel=Parameter.iloc[0,3]
ratio_electric=Parameter.iloc[1,3]

# lists
fitness_value=[]
num_generation=[]
repaired_population=[]
operating_interval = []

# Ebs constraint
Ebs_constraint=500
Ebs_constraint_list= pd.DataFrame([Ebs_constraint]*people_row).T

# NUM OF Ebs

num_of_row_ebs = pd.DataFrame([0]*people_row).T


#interval of dispatching and distance

dispatching_interval = [5, 10, 20, 20, 10, 5, 5, 10, 20, 20, 10, 5, 10, 5, 5, 20, 10, 20, 5, 5, 10, 20, 20,10, 20, 20, 10, 5]
distance = [59, 30, 39, 20, 26, 60, 70, 35, 27, 57, 82, 44, 53, 74, 84, 48, 46, 87, 81, 50, 61, 34, 42, 20 ]
dispatching_interval = dispatching_interval[:20]
distance = distance[:20]


# operatng_interval
for _ in range(len(distance)) :
    if distance[_] <=30 :
       operating_interval .append(1)
    elif distance[_] >31 and distance[_] <=60:
        operating_interval .append(2)
    else :
        operating_interval.append(3)

# repair_rule
def repair_rule(repair):

    repair = pd.DataFrame(repair)

    row_sums = repair.sum(axis=1)

    if (row_sums > 20).any():
    # 무작위로 선택된 위치의 값을 1에서 0으로 변경
        while True:
            row = random.randint(0, people_row - 1)
            col = random.randint(0, people_column - 1)
            if repair.iloc[row, col] == 1:
                repair.iloc[row, col] = 0
                break  # 변경이 이루어지면 반복 종료

    repair = repair.values.tolist()
    return repair

# initialize population
def initialize_population(population_size):

   
    pre_population = [[[random.randint(0, 1) for _ in range(people_column)] for _ in range(people_row)] for _ in range(population_size)]

    # for i in range(population_size) :
    #     repaired_population.append(repair_rule(pre_population[i]))

    # return repaired_population

    return pre_population

    #interpreter

def interpreter(subject): #subject 는 data frame
   
    interpreted = subject

    for col in range (len(dispatching_interval)) : # 20번  
        if dispatching_interval[col] == 10:
            for row in range(1, interpreted .shape[0]) :
                if row  % 2 != 0 :
                     interpreted .iloc[row , col] =2
        elif dispatching_interval[col] == 20:
            for row in range(1, interpreted .shape[0]) :
                if row  % 4 != 0 :
                     interpreted .iloc[row , col] =2      
   
    return interpreted

def changing_capacity(interpreted): # 거리 고려 완료
     
    def_list = copy.deepcopy(Ebs_constraint_list)
   
    for col in range (len(operating_interval)) : # 20번

        if operating_interval[col] == 1:
            for row in range(interpreted.shape[0]-1):
                try:
                    if interpreted.iloc[row, col] == 1:
                        def_list.iloc[:,row+1:row+13] -= 1
                except IndexError:
                        continue
        elif operating_interval[col] == 2:
            for row in range(interpreted.shape[0]-1):
                try:
                    if interpreted.iloc[row, col] == 1:
                        def_list.iloc[:,row+1:row+25] -= 1
                except IndexError:
                        continue
        else :
             for row in range(interpreted.shape[0]-1):
                try:
                    if interpreted.iloc[row, col] == 1:
                        def_list.iloc[:,row+1:row+37] -= 1
                except IndexError:
                        continue

    return def_list

def cumulative_Ebs(interpreted):
   
    def_list = copy.deepcopy(num_of_row_ebs)

    for col in range (len(operating_interval)) : # 20번

            if operating_interval[col] == 1:
                for row in range(interpreted.shape[0]):
                    try:
                        if interpreted.iloc[row, col] == 1:
                            def_list.iloc[:,row+1:row+13] += 1
                    except IndexError:
                            continue
            elif operating_interval[col] == 2:
                for row in range(interpreted.shape[0]):
                    try:
                        if interpreted.iloc[row, col] == 1:
                            def_list.iloc[:,row+1:row+25] += 1
                    except IndexError:
                            continue
            else :
                for row in range(interpreted.shape[0]):
                    try:
                        if interpreted.iloc[row, col] == 1:
                            def_list.iloc[:,row+1:row+37] += 1
                    except IndexError:
                            continue

    return def_list

# fitness function
def fitness(individual): #a = best_individual = 16x20
   
    global people
    total_value = 0
    individual = pd.DataFrame(individual)
    interpreted = interpreter(individual)

    num_row_Ebs = cumulative_Ebs(interpreted)
    Ebs_capacity= changing_capacity(interpreted) #16x1의 dataframe
   
    # print("num row ebs")
    # print(num_row_Ebs)
    # print("ebs_capa")
    # print(Ebs_capacity)

    if (num_row_Ebs.values>Ebs_capacity.values).any() :
        return 1/999999
             
    for row in range(people_row):  # 36
        for column in range(people_column):  # 20
            if interpreted.iloc[row, column] == 1:
                total_value += (distance[column] * zero_payload_electric + variable_electric * distance[column] * people.iloc[row, column]) * 0.6
            elif interpreted.iloc[row, column] ==0 :
                total_value += (distance[column] * zero_payload_desel + variable_desel * distance[column] * people.iloc[row,column]) * 3.06

    return 1/total_value

# 교차 연산 (두 부모에서 두 자식 생성)
def crossover(parent1, parent2):
   
    parent1 = pd.DataFrame(parent1)
    parent2 = pd.DataFrame(parent2)

    num_rows, num_columns = parent1.shape
    crossover_point1 = random.randint(0, num_columns - 1)
    crossover_point2 = random.randint(crossover_point1, num_columns)

    child1 = pd.concat((parent1.iloc[:,:crossover_point1], parent2.iloc[:, crossover_point1:crossover_point2] ,parent1.iloc[:, crossover_point2:]), axis = 1)
    child2 = pd.concat((parent2.iloc[:,:crossover_point1], parent1.iloc[:, crossover_point1:crossover_point2] ,parent2.iloc[:, crossover_point2:]), axis = 1)

    return child1, child2

# 돌연변이 연산 (돌연변이가 발생할 확률이 있음)
def mutate(individual, mutation_rate):

    num_rows ,num_columns  = individual.shape

    # print(num_rows)
   
    for i in range(int(num_rows*num_columns*mutation_rate)):

        row_idx = random.randint(0, num_rows - 1)
        col_idx = random.randint(0, num_columns - 1)
       
        current_value = individual.iloc[row_idx, col_idx]
        individual.iloc[row_idx, col_idx] = 1 if current_value == 0 else 0
 
    individual = individual.values.tolist()
    return individual

# 유전 알고리즘 메인 함수
def genetic_algorithm(population_size, generations, crossover_rate, mutation_rate):
   
    global last_optimal
    global x
    global fitness_value
    population = initialize_population(population_size)
   

    for generation in range(generations):
       
        population.sort(key=fitness, reverse=True)

        # 적합도가 가장 높은 개체 출력
        best_individual = population[0]  
        a=best_individual

        print(f"Generation {generation + 1}: Best Individual - {pd.DataFrame(best_individual)}, Fitness - {1/(fitness(a))}")
        fitness_value.append(1/fitness(a))
        num_generation.append(generation+1)
       
        # 새로운 세대 생성
        new_population = []

        # 엘리트 개체(적합도가 가장 높은 개체)는 그대로 다음 세대로 전이 , 10개
        for i in range(int(population_size/10)):
            new_population.append(population[i])


        # 교차 연산과 돌연변이 연산을 통해 새로운 개체 생성
        while len(new_population) < population_size:
           
       
            weights = [2**(-i) for i in range(len(population))] # 가중치
            parent1 = random.choices(population, weights=weights)[0]
            parent2 = random.choices(population, weights=weights)[0]
            child1, child2 = crossover(parent1, parent2)
            child1 = mutate(child1, mutation_rate)
            child2 = mutate(child2, mutation_rate)

            new_population.extend([child1,child2])

        # 현재 세대 갱신
        population = new_population
       
       
    x = pd.DataFrame(population[0])

    last_optimal=interpreter(x)

    return  

if __name__ == "__main__":
      people=Test_Data_Q
      genetic_algorithm(population_size=100, generations=50, crossover_rate=0.8, mutation_rate=0.05)


print("interpreted last optimal")
print(last_optimal)
print("last optimal Row Sums:" )
print(cumulative_Ebs(last_optimal))
print("dispatching_interval = ", dispatching_interval)
print("operatining_interval : ", operating_interval)


# figure
plt.plot(num_generation, fitness_value, marker='o')
plt.title('Fitness over Generations')
plt.xlabel('Generation')
plt.ylabel('Fitness')
plt.grid(True)
plt.show()


print(people_column)
print(people_row)

'ai' 카테고리의 다른 글

GA-1208  (0) 2023.12.08