Merge branch 'genetic_algorithm' of https://git.wmi.amu.edu.pl/s462072/Trashmaster into genetic_algorithm

This commit is contained in:
Radosław Trzmielewski 2022-06-10 11:02:07 +02:00
commit f55886a199
4 changed files with 633 additions and 566 deletions

View File

@ -4,12 +4,21 @@
| | | |--- class: 0 | | | |--- class: 0
| | |--- feature_0 > 1.50 | | |--- feature_0 > 1.50
| | | |--- feature_3 <= 3.50 | | | |--- feature_3 <= 3.50
<<<<<<< HEAD
| | | | |--- feature_4 <= 2.50 | | | | |--- feature_4 <= 2.50
| | | | | |--- class: 1 | | | | | |--- class: 1
| | | | |--- feature_4 > 2.50 | | | | |--- feature_4 > 2.50
| | | | | |--- feature_2 <= 2.50 | | | | | |--- feature_2 <= 2.50
| | | | | | |--- class: 1 | | | | | | |--- class: 1
| | | | | |--- feature_2 > 2.50 | | | | | |--- feature_2 > 2.50
=======
| | | | |--- feature_2 <= 2.50
| | | | | |--- class: 1
| | | | |--- feature_2 > 2.50
| | | | | |--- feature_4 <= 2.50
| | | | | | |--- class: 1
| | | | | |--- feature_4 > 2.50
>>>>>>> a16ec52642067a2be0b41a5c3bcab24193122343
| | | | | | |--- class: 0 | | | | | | |--- class: 0
| | | |--- feature_3 > 3.50 | | | |--- feature_3 > 3.50
| | | | |--- feature_3 <= 4.50 | | | | |--- feature_3 <= 4.50
@ -26,24 +35,42 @@
| | | | | | | |--- feature_1 > 1.50 | | | | | | | |--- feature_1 > 1.50
| | | | | | | | |--- class: 0 | | | | | | | | |--- class: 0
| | | | | | |--- feature_0 > 2.50 | | | | | | |--- feature_0 > 2.50
<<<<<<< HEAD
| | | | | | | |--- feature_2 <= 2.50 | | | | | | | |--- feature_2 <= 2.50
| | | | | | | | |--- class: 1 | | | | | | | | |--- class: 1
| | | | | | | |--- feature_2 > 2.50 | | | | | | | |--- feature_2 > 2.50
| | | | | | | | |--- feature_4 <= 2.50 | | | | | | | | |--- feature_4 <= 2.50
| | | | | | | | | |--- class: 1 | | | | | | | | | |--- class: 1
| | | | | | | | |--- feature_4 > 2.50 | | | | | | | | |--- feature_4 > 2.50
=======
| | | | | | | |--- feature_4 <= 2.50
| | | | | | | | |--- class: 1
| | | | | | | |--- feature_4 > 2.50
| | | | | | | | |--- feature_2 <= 2.50
| | | | | | | | | |--- class: 1
| | | | | | | | |--- feature_2 > 2.50
>>>>>>> a16ec52642067a2be0b41a5c3bcab24193122343
| | | | | | | | | |--- class: 0 | | | | | | | | | |--- class: 0
| | | | | |--- feature_1 > 2.50 | | | | | |--- feature_1 > 2.50
| | | | | | |--- feature_1 <= 3.50 | | | | | | |--- feature_1 <= 3.50
| | | | | | | |--- feature_0 <= 3.50 | | | | | | | |--- feature_0 <= 3.50
| | | | | | | | |--- class: 0 | | | | | | | | |--- class: 0
| | | | | | | |--- feature_0 > 3.50 | | | | | | | |--- feature_0 > 3.50
<<<<<<< HEAD
| | | | | | | | |--- feature_2 <= 2.50 | | | | | | | | |--- feature_2 <= 2.50
| | | | | | | | | |--- class: 1 | | | | | | | | | |--- class: 1
| | | | | | | | |--- feature_2 > 2.50 | | | | | | | | |--- feature_2 > 2.50
| | | | | | | | | |--- feature_4 <= 2.00 | | | | | | | | | |--- feature_4 <= 2.00
| | | | | | | | | | |--- class: 1 | | | | | | | | | | |--- class: 1
| | | | | | | | | |--- feature_4 > 2.00 | | | | | | | | | |--- feature_4 > 2.00
=======
| | | | | | | | |--- feature_4 <= 2.50
| | | | | | | | | |--- class: 1
| | | | | | | | |--- feature_4 > 2.50
| | | | | | | | | |--- feature_2 <= 2.00
| | | | | | | | | | |--- class: 1
| | | | | | | | | |--- feature_2 > 2.00
>>>>>>> a16ec52642067a2be0b41a5c3bcab24193122343
| | | | | | | | | | |--- class: 0 | | | | | | | | | | |--- class: 0
| | | | | | |--- feature_1 > 3.50 | | | | | | |--- feature_1 > 3.50
| | | | | | | |--- class: 0 | | | | | | | |--- class: 0
@ -59,6 +86,7 @@
| | | | | | |--- class: 1 | | | | | | |--- class: 1
| | | | |--- feature_3 > 3.50 | | | | |--- feature_3 > 3.50
| | | | | |--- feature_1 <= 2.50 | | | | | |--- feature_1 <= 2.50
<<<<<<< HEAD
| | | | | | |--- feature_0 <= 2.50 | | | | | | |--- feature_0 <= 2.50
| | | | | | | |--- class: 0 | | | | | | | |--- class: 0
| | | | | | |--- feature_0 > 2.50 | | | | | | |--- feature_0 > 2.50
@ -66,6 +94,15 @@
| | | | | | | | |--- class: 1 | | | | | | | | |--- class: 1
| | | | | | | |--- feature_3 > 4.50 | | | | | | | |--- feature_3 > 4.50
| | | | | | | | |--- class: 0 | | | | | | | | |--- class: 0
=======
| | | | | | |--- feature_3 <= 4.50
| | | | | | | |--- feature_0 <= 2.50
| | | | | | | | |--- class: 0
| | | | | | | |--- feature_0 > 2.50
| | | | | | | | |--- class: 1
| | | | | | |--- feature_3 > 4.50
| | | | | | | |--- class: 0
>>>>>>> a16ec52642067a2be0b41a5c3bcab24193122343
| | | | | |--- feature_1 > 2.50 | | | | | |--- feature_1 > 2.50
| | | | | | |--- class: 0 | | | | | | |--- class: 0
| | | |--- feature_4 > 4.50 | | | |--- feature_4 > 4.50
@ -76,6 +113,7 @@
| |--- feature_1 <= 1.50 | |--- feature_1 <= 1.50
| | |--- feature_4 <= 1.50 | | |--- feature_4 <= 1.50
| | | |--- feature_2 <= 4.50 | | | |--- feature_2 <= 4.50
<<<<<<< HEAD
| | | | |--- feature_0 <= 1.50 | | | | |--- feature_0 <= 1.50
| | | | | |--- class: 0 | | | | | |--- class: 0
| | | | |--- feature_0 > 1.50 | | | | |--- feature_0 > 1.50
@ -83,6 +121,15 @@
| | | | | | |--- class: 1 | | | | | | |--- class: 1
| | | | | |--- feature_3 > 4.50 | | | | | |--- feature_3 > 4.50
| | | | | | |--- class: 0 | | | | | | |--- class: 0
=======
| | | | |--- feature_3 <= 4.50
| | | | | |--- feature_0 <= 1.50
| | | | | | |--- class: 0
| | | | | |--- feature_0 > 1.50
| | | | | | |--- class: 1
| | | | |--- feature_3 > 4.50
| | | | | |--- class: 0
>>>>>>> a16ec52642067a2be0b41a5c3bcab24193122343
| | | |--- feature_2 > 4.50 | | | |--- feature_2 > 4.50
| | | | |--- class: 0 | | | | |--- class: 0
| | |--- feature_4 > 1.50 | | |--- feature_4 > 1.50

View File

@ -6,21 +6,23 @@ import math
# klasa tworząca miasta czy też śmietniki # klasa tworząca miasta czy też śmietniki
class City: class City:
def __init__(self, x, y): def __init__(self, x, y, array):
self.x = x self.x = x
self.y = y self.y = y
#self.array = array self.array = array
# self.dist = distance # self.dist = distance
#dystans to d = sqrt(x^2 + y^2) #dystans to d = sqrt(x^2 + y^2)
def distance(self, city): def distance(self, city):
#getting distance by astar gives wrong final distance (intial = final) #getting distance by astar gives wrong final distance (intial = final)
#return get_cost(math.floor(self.x / TILESIZE), math.floor(self.y / TILESIZE), math.floor(city.x / TILESIZE), math.floor(city.y / TILESIZE), self.array) return get_cost(math.floor(self.x / TILESIZE), math.floor(self.y / TILESIZE), math.floor(city.x / TILESIZE), math.floor(city.y / TILESIZE), self.array)
xDis = abs(self.x - city.x) # xDis = abs(self.x - city.x)
yDis = abs(self.y - city.y) # yDis = abs(self.y - city.y)
distance = np.sqrt((xDis ** 2) + (yDis ** 2)) # distance = np.sqrt((xDis ** 2) + (yDis ** 2))
return distance # return distance
def __repr__(self): def __repr__(self):
return "(" + str(self.x) + "," + str(self.y) + ")" return "(" + str(self.x) + "," + str(self.y) + ")"
@ -30,10 +32,11 @@ class City:
# inverse of route distance # inverse of route distance
# we want to minimize distance so the larger the fitness the better # we want to minimize distance so the larger the fitness the better
class Fitness: class Fitness:
def __init__(self, route): def __init__(self, route, distanceArray):
self.route = route self.route = route
self.distance = 0 self.distance = 0
self.fitness = 0.0 self.fitness = 0.0
self.distanceArray = distanceArray
def routeDistance(self): def routeDistance(self):
if self.distance == 0: if self.distance == 0:
@ -45,7 +48,8 @@ class Fitness:
toCity = self.route[i + 1] toCity = self.route[i + 1]
else: else:
toCity = self.route[0] toCity = self.route[0]
pathDistance += fromCity.distance(toCity) # pathDistance += fromCity.distance(toCity)
pathDistance += self.distanceArray[str(fromCity.x)+" "+str(fromCity.y)+" "+str(toCity.x)+" "+str(toCity.y)]
self.distance = pathDistance self.distance = pathDistance
return self.distance return self.distance
@ -71,10 +75,10 @@ def initialPopulation(popSize, cityList):
# ranking fitness of given route, output is ordered list with route id and its fitness score # ranking fitness of given route, output is ordered list with route id and its fitness score
def rankRoutes(population): def rankRoutes(population, distanceArray):
fitnessResults = {} fitnessResults = {}
for i in range(0, len(population)): for i in range(0, len(population)):
fitnessResults[i] = Fitness(population[i]).routeFitness() fitnessResults[i] = Fitness(population[i], distanceArray).routeFitness()
return sorted(fitnessResults.items(), key=operator.itemgetter(1), reverse=True) return sorted(fitnessResults.items(), key=operator.itemgetter(1), reverse=True)
@ -177,8 +181,8 @@ def mutatePopulation(population, mutationRate):
# creating new generation # creating new generation
def nextGeneration(currentGen, eliteSize, mutationRate): def nextGeneration(currentGen, eliteSize, mutationRate, distanceArray):
popRanked = rankRoutes(currentGen) # rank routes in current gen popRanked = rankRoutes(currentGen, distanceArray) # rank routes in current gen
selectionResults = selection(popRanked, eliteSize) # determining potential parents selectionResults = selection(popRanked, eliteSize) # determining potential parents
matingpool = matingPool(currentGen, selectionResults) # creating mating pool matingpool = matingPool(currentGen, selectionResults) # creating mating pool
children = breedPopulation(matingpool, eliteSize) # creating new gen children = breedPopulation(matingpool, eliteSize) # creating new gen
@ -186,15 +190,15 @@ def nextGeneration(currentGen, eliteSize, mutationRate):
return nextGeneration return nextGeneration
def geneticAlgorithm(population, popSize, eliteSize, mutationRate, generations): def geneticAlgorithm(population, popSize, eliteSize, mutationRate, generations, distanceArray):
pop = initialPopulation(popSize, population) pop = initialPopulation(popSize, population)
print("Initial distance: " + str(1 / rankRoutes(pop)[0][1])) print("Initial distance: " + str(1 / rankRoutes(pop, distanceArray)[0][1]))
for i in range(0, generations): for i in range(0, generations):
pop = nextGeneration(pop, eliteSize, mutationRate) pop = nextGeneration(pop, eliteSize, mutationRate, distanceArray)
print("Final distance: " + str(1 / rankRoutes(pop)[0][1])) print("Final distance: " + str(1 / rankRoutes(pop, distanceArray)[0][1]))
bestRouteIndex = rankRoutes(pop)[0][0] bestRouteIndex = rankRoutes(pop, distanceArray)[0][0]
bestRoute = pop[bestRouteIndex] bestRoute = pop[bestRouteIndex]
return bestRoute return bestRoute
@ -212,18 +216,29 @@ cityList = []
# plotting the progress # plotting the progress
def geneticAlgorithmPlot(population, popSize, eliteSize, mutationRate, generations): def distanceFromCityToCity(cityFrom, city, array):
return get_cost(math.floor(cityFrom.x / TILESIZE), math.floor(cityFrom.y / TILESIZE), math.floor(city.x / TILESIZE), math.floor(city.y / TILESIZE), array)
def geneticAlgorithmPlot(population, popSize, eliteSize, mutationRate, generations, array):
a_star_distances = {}
for city in population:
for target in population:
if city == target:
continue
else:
a_star_distances[str(city.x)+" "+str(city.y)+" "+str(target.x)+" "+str(target.y)] = distanceFromCityToCity(city, target, array)
pop = initialPopulation(popSize, population) pop = initialPopulation(popSize, population)
progress = [] progress = []
progress.append(1 / rankRoutes(pop)[0][1]) progress.append(1 / rankRoutes(pop, a_star_distances)[0][1])
print("Initial distance: " + str(1 / rankRoutes(pop)[0][1])) print("Initial distance: " + str(1 / rankRoutes(pop, a_star_distances)[0][1]))
for i in range(0, generations): for i in range(0, generations):
pop = nextGeneration(pop, eliteSize, mutationRate) pop = nextGeneration(pop, eliteSize, mutationRate, a_star_distances)
progress.append(1 / rankRoutes(pop)[0][1]) progress.append(1 / rankRoutes(pop, a_star_distances)[0][1])
print("Final distance: " + str(1 / rankRoutes(pop)[0][1])) print("Final distance: " + str(1 / rankRoutes(pop, a_star_distances)[0][1]))
bestRouteIndex = rankRoutes(pop)[0][0] bestRouteIndex = rankRoutes(pop, a_star_distances)[0][0]
bestRoute = pop[bestRouteIndex] bestRoute = pop[bestRouteIndex]
plt.plot(progress) plt.plot(progress)

10
main.py
View File

@ -148,13 +148,15 @@ class Game():
result = prediction.getPrediction(dir + '/' + file, 'trained_nn_20.pth') result = prediction.getPrediction(dir + '/' + file, 'trained_nn_20.pth')
img = pg.image.load(dir + '/' + file).convert_alpha() img = pg.image.load(dir + '/' + file).convert_alpha()
img = pg.transform.scale(img, (128, 128)) img = pg.transform.scale(img, (128, 128))
trash = Trash(img, 0, 0, 128, 128) offset_x, offset_y = self.camera.offset()
trash = Trash(img, math.floor(-offset_x * TILESIZE), math.floor(-offset_y * TILESIZE), 128, 128)
self.trashDisplay.empty()
self.trashDisplay.add(trash) self.trashDisplay.add(trash)
self.text_display = result self.text_display = result
self.draw() self.draw()
# print(result + ' ' + file)
pg.time.wait(100) pg.time.wait(100)
self.text_display = '' self.text_display = ''
self.trashDisplay.empty()
self.draw() self.draw()
# print(self.positive_actions[0]) # print(self.positive_actions[0])
@ -167,11 +169,11 @@ class Game():
for i in self.positive_decision: for i in self.positive_decision:
trash_x, trash_y = i.get_coords() trash_x, trash_y = i.get_coords()
# city_list.append(TSP.City(x=int(trash_x), y=int(trash_y), array=self.mapArray)) # city_list.append(TSP.City(x=int(trash_x), y=int(trash_y), array=self.mapArray))
city_list.append(TSP.City(x=int(trash_x), y=int(trash_y))) city_list.append(TSP.City(x=trash_x, y=trash_y, array=self.mapArray))
# dist = a_star.get_cost # dist = a_star.get_cost
self.tsp_list = TSP.geneticAlgorithmPlot(population=city_list, popSize=100, eliteSize=20, mutationRate=0.01, generations=300) self.tsp_list = TSP.geneticAlgorithmPlot(population=city_list, popSize=100, eliteSize=20, mutationRate=0.01, generations=300, array=self.mapArray)
print(self.tsp_list) print(self.tsp_list)
def load_data(self): def load_data(self):

View File

@ -4,8 +4,11 @@ from path_search_algorthms import a_star_utils as utils
def get_cost(start_x: int, start_y: int, target_x: int, target_y: int, array): def get_cost(start_x: int, start_y: int, target_x: int, target_y: int, array):
actions = search_path(start_x, start_y, utils.Rotation.NONE, target_x, target_y, array) actions = search_path(start_x, start_y, utils.Rotation.NONE, target_x, target_y, array)
print('length')
if actions is None: if actions is None:
print('0')
return 1 return 1
print(len(actions))
return len(actions) return len(actions)