import copy import random import matplotlib.pyplot as plt import numpy as np from City import City from Item import Item from Thief import Thief def loader(file_name): f = open(file_name, "r") contents = f.readlines() temp = contents[2].split("\t") dimentions = int(temp[temp.__len__() - 1]) temp = contents[3].split("\t") number_of_items = int(temp[temp.__len__() - 1]) temp = contents[4].split("\t") capacity_of_knapsack = int(temp[temp.__len__() - 1]) temp = contents[5].split("\t") min_speed = float(temp[temp.__len__() - 1]) temp = contents[6].split("\t") max_speed = float(temp[temp.__len__() - 1]) cities = [] for i in range(dimentions): temp = contents[10 + i].split("\t") city_index = int(temp[0]) cord_x = float(temp[1]) cord_y = float(temp[2]) city = City(city_index, cord_x, cord_y) cities.append(city) for i in range(number_of_items): temp = contents[11 + dimentions + i].split("\t") index = int(temp[0]) reward = int(temp[1]) weight = int(temp[2]) city_index = int(temp[3]) item = Item(index, reward, weight) for city_object in cities: if city_object.index == city_index: city_object.add_item(item) return cities, capacity_of_knapsack, min_speed, max_speed def generate_first_thieves(capacity_of_knapsack, min_speed, max_speed, quantity_of_thieves): thieves = [] for i in range(0, quantity_of_thieves): thief = Thief(capacity_of_knapsack, min_speed, max_speed) thieves.append(thief) return thieves def calculate_thieves_distance(thieves): max = -np.inf min = np.inf for thief in thieves: # cities=[] # for city in thief.visited_cities: # cities.append(city.index) # print(cities) temp_dist = 0 temp_time = 0 thief.temp_weight = 0 thief.items_in_knapsack = [] for i in range(len(thief.visited_cities)): best_profit = Item(-1, 0, -1) for item in thief.visited_cities[i].items: # print(thief.visited_cities[i].index, "dupa", item.index) if item.profitability > best_profit.profitability: best_profit = item if thief.temp_weight + best_profit.weight <= thief.capasity_of_knapsack and best_profit.index != -1: thief.items_in_knapsack.append(best_profit) thief.temp_weight += best_profit.weight v_temp = thief.max_speed - thief.temp_weight * ( (thief.max_speed - thief.min_speed) / thief.capasity_of_knapsack) if i < len(thief.visited_cities) - 1: temp_dist += np.sqrt(pow(thief.visited_cities[i + 1].cord_x - thief.visited_cities[i].cord_x, 2) + pow( thief.visited_cities[i + 1].cord_y - thief.visited_cities[i].cord_y, 2)) temp_time += temp_dist / v_temp # print(np.sqrt(pow(2,thief.visited_cities[i+1].cord_x-thief.visited_cities[i].cord_x)+pow(2,thief.visited_cities[i+1].cord_x-thief.visited_cities[i].cord_y))) else: temp_dist += np.sqrt( pow(thief.visited_cities[0].cord_x - thief.visited_cities[i].cord_x, 2) + pow( thief.visited_cities[0].cord_y - thief.visited_cities[i].cord_y, 2)) temp_time += temp_dist / v_temp sum = 0 for item in thief.items_in_knapsack: sum += item.reward thief.distanse = temp_dist thief.time = temp_time thief.fitness = sum - thief.time # print(temp_dist) # print(temp_time) # print("fitness",thief.fitness) if thief.fitness > max: max = thief.fitness if thief.fitness < min: min = thief.fitness return max, min def set_thief_truck(thieves, cities): for thiev in thieves: for city in cities: thiev.visited_cities.append(city) random.shuffle(thiev.visited_cities) def mutation(thieves, pm): new_pop = [] for thief in thieves: rand = np.random.rand() if rand < pm: rand = int(np.random.rand() * len(thief.visited_cities) - 1) temp = copy.deepcopy(thief) temp.visited_cities[rand], temp.visited_cities[len(thief.visited_cities) - rand - 1] = \ thief.visited_cities[ len( thief.visited_cities) - rand - 1], \ thief.visited_cities[ rand] new_pop.append(temp) else: new_pop.append(thief) return new_pop def repair(thief, point, list): list2 = [] for i in range(len(thief.visited_cities)): for city in list: if thief.visited_cities[i].index == city.index: list.remove(city) for i in range(len(thief.visited_cities)): if i < point: list2.append(thief.visited_cities[i]) else: for city in list2: if city.index == thief.visited_cities[i].index: new_city = list[0] thief.visited_cities[i] = new_city list.remove(list[0]) return thief def crossover(thief1, thief2): point = int(len(thief1.visited_cities) * (np.random.rand())) list = [] for city in thief1.visited_cities: list.append(city) list2 = list.copy() for i in range(len(thief1.visited_cities)): if i >= point: temp = thief1.visited_cities[i] thief1.visited_cities[i] = thief2.visited_cities[i] thief2.visited_cities[i] = temp repair(thief1, point, list) repair(thief2, point, list2) cities = [] return thief1, thief2 def calculate_data(thieves, pop): max, min = calculate_thieves_distance(thieves) data = [] data.append(pop) data.append(max) avarage = 0 for thief in thieves: avarage += thief.fitness # cities=[] # for city in thief.visited_cities: # cities.append(city.index) # print(cities) avarage = avarage / pop_size data.append(avarage) data.append(min) return data def compare_thieves(temps): best = temps[0] for thief in temps: if thief.fitness > best.fitness: best = thief return best def select_population(thieves, tour_size, pop_size): # data=calculate_data(thieves,pop_size) # print("prze",data[2]) new_population = [] for i in range(pop_size): temps = [] for j in range(tour_size): temps.append(thieves[int(np.random.rand() * pop_size)]) best = compare_thieves(temps) new_population.append(best) # data = calculate_data(new_population, pop_size) # print("po",data[2]) return new_population def crossover_population(thieves, pop_size, px): new_pop = [] while thieves.__len__() > 0: rand = random.randrange(0, thieves.__len__()) new_pop.append(thieves[rand]) del thieves[rand] numOfThieves = new_pop.__len__() numbers = [] for i in range(numOfThieves): numbers.append(i) while numbers.__len__() > 0: rand1 = numbers.__len__() - 1 rand2 = numbers.__len__() - 2 thief_1 = new_pop[rand1] thief_2 = new_pop[rand2] if np.random.rand() < px: temp1, temp2 = crossover(thief_1, thief_2) new_pop[rand1] = temp1 new_pop[rand2] = temp2 del numbers[rand1] del numbers[rand2] return new_pop def check_if_correct(thieves): for thief in thieves: cities = [] for city in cities: cities.append(city.index) numbers = [] for i in range(thieves.__len__()): numbers.append(i) for i in range(cities.__len__()): for j in range(numbers.__len__()): if i == j: del numbers[j] return True def generate_generations(thieves, pop_size): Px = 0.7 pm = 0.01 gen = 100 tour_size = 5 iterator = 0 while iterator < gen: best_average = -np.inf print("iterator", iterator) iterator += 1 thieves = select_population(thieves, tour_size, pop_size) thieves = mutation(thieves, pm) thieves = crossover_population(thieves, pop_size, Px) new_data = calculate_data(thieves, iterator + 1) all_data.append(new_data) print(all_data) return all_data pop_size = 100 loader = loader("data/hard_0.ttp") cities = loader[0] thieves = generate_first_thieves(loader[1], loader[2], loader[3], pop_size) set_thief_truck(thieves, cities) max, min = calculate_thieves_distance(thieves) data = [] data.append(0) data.append(max) avarage = 0 for thief in thieves: avarage += thief.fitness avarage = avarage / pop_size data.append(avarage) data.append(min) all_data = [] all_data.append(data) new_table = generate_generations(thieves, pop_size) all_data.append(new_table) temp_average = [] empty_time = [] max_pop = [] min_pop = [] for i in range(len(all_data) - 1): temp_average.append(all_data[i][2]) empty_time.append(i) max_pop.append(all_data[i][1]) min_pop.append(all_data[i][3]) plt.plot(empty_time, temp_average) plt.plot(empty_time, max_pop) plt.plot(empty_time, min_pop) plt.show()