- 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()