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

@ -1,235 +1,250 @@
import numpy as np, random, operator, pandas as pd, matplotlib.pyplot as plt import numpy as np, random, operator, pandas as pd, matplotlib.pyplot as plt
from path_search_algorthms.a_star import get_cost from path_search_algorthms.a_star import get_cost
from decision_tree import decisionTree from decision_tree import decisionTree
from settings import * from settings import *
import math 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)
def distance(self, city):
#dystans to d = sqrt(x^2 + y^2)
#getting distance by astar gives wrong final distance (intial = final) def distance(self, city):
#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) #getting distance by astar gives wrong final distance (intial = final)
yDis = abs(self.y - city.y) 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)
distance = np.sqrt((xDis ** 2) + (yDis ** 2)) # xDis = abs(self.x - city.x)
return distance # yDis = abs(self.y - city.y)
# distance = np.sqrt((xDis ** 2) + (yDis ** 2))
def __repr__(self): # return distance
return "(" + str(self.x) + "," + str(self.y) + ")"
def __repr__(self):
return "(" + str(self.x) + "," + str(self.y) + ")"
# fitness function,
# inverse of route distance
# we want to minimize distance so the larger the fitness the better # fitness function,
class Fitness: # inverse of route distance
def __init__(self, route): # we want to minimize distance so the larger the fitness the better
self.route = route class Fitness:
self.distance = 0 def __init__(self, route, distanceArray):
self.fitness = 0.0 self.route = route
self.distance = 0
def routeDistance(self): self.fitness = 0.0
if self.distance == 0: self.distanceArray = distanceArray
pathDistance = 0
for i in range(0, len(self.route)): def routeDistance(self):
fromCity = self.route[i] if self.distance == 0:
toCity = None pathDistance = 0
if i + 1 < len(self.route): # for returning to point 0? for i in range(0, len(self.route)):
toCity = self.route[i + 1] fromCity = self.route[i]
else: toCity = None
toCity = self.route[0] if i + 1 < len(self.route): # for returning to point 0?
pathDistance += fromCity.distance(toCity) toCity = self.route[i + 1]
self.distance = pathDistance else:
return self.distance toCity = self.route[0]
# pathDistance += fromCity.distance(toCity)
def routeFitness(self): pathDistance += self.distanceArray[str(fromCity.x)+" "+str(fromCity.y)+" "+str(toCity.x)+" "+str(toCity.y)]
if self.fitness == 0: self.distance = pathDistance
self.fitness = 1 / float(self.routeDistance()) return self.distance
return self.fitness
def routeFitness(self):
if self.fitness == 0:
# creating one individual - single route from city to city (trash to trash) self.fitness = 1 / float(self.routeDistance())
def createRoute(cityList): return self.fitness
route = random.sample(cityList, len(cityList))
return route
# creating one individual - single route from city to city (trash to trash)
def createRoute(cityList):
# creating initial population of given size route = random.sample(cityList, len(cityList))
def initialPopulation(popSize, cityList): return route
population = []
for i in range(0, popSize): # creating initial population of given size
population.append(createRoute(cityList)) def initialPopulation(popSize, cityList):
return population population = []
for i in range(0, popSize):
# ranking fitness of given route, output is ordered list with route id and its fitness score population.append(createRoute(cityList))
def rankRoutes(population): return population
fitnessResults = {}
for i in range(0, len(population)):
fitnessResults[i] = Fitness(population[i]).routeFitness() # ranking fitness of given route, output is ordered list with route id and its fitness score
return sorted(fitnessResults.items(), key=operator.itemgetter(1), reverse=True) def rankRoutes(population, distanceArray):
fitnessResults = {}
for i in range(0, len(population)):
# selecting "mating pool" fitnessResults[i] = Fitness(population[i], distanceArray).routeFitness()
# we are using here "Firness proportionate selection", its fitness-weighted probability of being selected return sorted(fitnessResults.items(), key=operator.itemgetter(1), reverse=True)
# moreover we are using elitism to ensure that the best of the best will preserve
def selection(popRanked, eliteSize): # selecting "mating pool"
selectionResults = [] # we are using here "Firness proportionate selection", its fitness-weighted probability of being selected
# roulette wheel # moreover we are using elitism to ensure that the best of the best will preserve
df = pd.DataFrame(np.array(popRanked), columns=["Index", "Fitness"])
df['cum_sum'] = df.Fitness.cumsum() def selection(popRanked, eliteSize):
df['cum_perc'] = 100 * df.cum_sum / df.Fitness.sum() selectionResults = []
# roulette wheel
for i in range(0, eliteSize): # elitism df = pd.DataFrame(np.array(popRanked), columns=["Index", "Fitness"])
selectionResults.append(popRanked[i][0]) df['cum_sum'] = df.Fitness.cumsum()
for i in range(0, df['cum_perc'] = 100 * df.cum_sum / df.Fitness.sum()
len(popRanked) - eliteSize): # comparing randomly drawn number to weights for selection for mating pool
pick = 100 * random.random() for i in range(0, eliteSize): # elitism
for i in range(0, len(popRanked)): selectionResults.append(popRanked[i][0])
if pick <= df.iat[i, 3]: for i in range(0,
selectionResults.append(popRanked[i][0]) len(popRanked) - eliteSize): # comparing randomly drawn number to weights for selection for mating pool
break pick = 100 * random.random()
return selectionResults # returns list of route IDs for i in range(0, len(popRanked)):
if pick <= df.iat[i, 3]:
selectionResults.append(popRanked[i][0])
# creating mating pool from list of routes IDs from "selection" break
def matingPool(population, selectionResults): return selectionResults # returns list of route IDs
matingpool = []
for i in range(0, len(selectionResults)):
index = selectionResults[i] # creating mating pool from list of routes IDs from "selection"
matingpool.append(population[index]) def matingPool(population, selectionResults):
return matingpool matingpool = []
for i in range(0, len(selectionResults)):
index = selectionResults[i]
# creating new generation matingpool.append(population[index])
# ordered crossover bc we need to include all locations exactly one time return matingpool
# randomly selecting a subset of the first parent string and then filling the remainder of route
# with genes from the second parent in the order in which they appear, without duplicating any genes from the first parent
def breed(parent1, parent2): # creating new generation
child = [] # ordered crossover bc we need to include all locations exactly one time
childP1 = [] # randomly selecting a subset of the first parent string and then filling the remainder of route
childP2 = [] # with genes from the second parent in the order in which they appear, without duplicating any genes from the first parent
def breed(parent1, parent2):
geneA = int(random.random() * len(parent1)) child = []
geneB = int(random.random() * len(parent1)) childP1 = []
childP2 = []
startGene = min(geneA, geneB)
endGene = max(geneA, geneB) geneA = int(random.random() * len(parent1))
geneB = int(random.random() * len(parent1))
for i in range(startGene, endGene): # ordered crossover
childP1.append(parent1[i]) startGene = min(geneA, geneB)
endGene = max(geneA, geneB)
childP2 = [item for item in parent2 if item not in childP1]
for i in range(startGene, endGene): # ordered crossover
child = childP1 + childP2 childP1.append(parent1[i])
return child
childP2 = [item for item in parent2 if item not in childP1]
# creating whole offspring population child = childP1 + childP2
def breedPopulation(matingpool, eliteSize): return child
children = []
length = len(matingpool) - eliteSize
pool = random.sample(matingpool, len(matingpool)) # creating whole offspring population
def breedPopulation(matingpool, eliteSize):
# using elitism to retain best genes (routes) children = []
for i in range(0, eliteSize): length = len(matingpool) - eliteSize
children.append(matingpool[i]) pool = random.sample(matingpool, len(matingpool))
# filling rest generation # using elitism to retain best genes (routes)
for i in range(0, length): for i in range(0, eliteSize):
child = breed(pool[i], pool[len(matingpool) - i - 1]) children.append(matingpool[i])
children.append(child)
return children # filling rest generation
for i in range(0, length):
child = breed(pool[i], pool[len(matingpool) - i - 1])
# using swap mutation children.append(child)
# with specified low prob we swap two cities in route return children
def mutate(individual, mutationRate):
for swapped in range(len(individual)):
if (random.random() < mutationRate): # using swap mutation
swapWith = int(random.random() * len(individual)) # with specified low prob we swap two cities in route
def mutate(individual, mutationRate):
city1 = individual[swapped] for swapped in range(len(individual)):
city2 = individual[swapWith] if (random.random() < mutationRate):
swapWith = int(random.random() * len(individual))
individual[swapped] = city2
individual[swapWith] = city1 city1 = individual[swapped]
return individual city2 = individual[swapWith]
individual[swapped] = city2
# extending mutate function to run through new pop individual[swapWith] = city1
def mutatePopulation(population, mutationRate): return individual
mutatedPop = []
for ind in range(0, len(population)): # extending mutate function to run through new pop
mutatedInd = mutate(population[ind], mutationRate) def mutatePopulation(population, mutationRate):
mutatedPop.append(mutatedInd) mutatedPop = []
return mutatedPop
for ind in range(0, len(population)):
mutatedInd = mutate(population[ind], mutationRate)
# creating new generation mutatedPop.append(mutatedInd)
def nextGeneration(currentGen, eliteSize, mutationRate): return mutatedPop
popRanked = rankRoutes(currentGen) # rank routes in current gen
selectionResults = selection(popRanked, eliteSize) # determining potential parents
matingpool = matingPool(currentGen, selectionResults) # creating mating pool # creating new generation
children = breedPopulation(matingpool, eliteSize) # creating new gen def nextGeneration(currentGen, eliteSize, mutationRate, distanceArray):
nextGeneration = mutatePopulation(children, mutationRate) # applying mutation to new gen popRanked = rankRoutes(currentGen, distanceArray) # rank routes in current gen
return nextGeneration selectionResults = selection(popRanked, eliteSize) # determining potential parents
matingpool = matingPool(currentGen, selectionResults) # creating mating pool
children = breedPopulation(matingpool, eliteSize) # creating new gen
def geneticAlgorithm(population, popSize, eliteSize, mutationRate, generations): nextGeneration = mutatePopulation(children, mutationRate) # applying mutation to new gen
pop = initialPopulation(popSize, population) return nextGeneration
print("Initial distance: " + str(1 / rankRoutes(pop)[0][1]))
for i in range(0, generations): def geneticAlgorithm(population, popSize, eliteSize, mutationRate, generations, distanceArray):
pop = nextGeneration(pop, eliteSize, mutationRate) pop = initialPopulation(popSize, population)
print("Initial distance: " + str(1 / rankRoutes(pop, distanceArray)[0][1]))
print("Final distance: " + str(1 / rankRoutes(pop)[0][1]))
bestRouteIndex = rankRoutes(pop)[0][0] for i in range(0, generations):
bestRoute = pop[bestRouteIndex] pop = nextGeneration(pop, eliteSize, mutationRate, distanceArray)
return bestRoute
print("Final distance: " + str(1 / rankRoutes(pop, distanceArray)[0][1]))
bestRouteIndex = rankRoutes(pop, distanceArray)[0][0]
# tutaj ma być lista kordów potencjalnych śmietników z drzewa decyzyjnego bestRoute = pop[bestRouteIndex]
return bestRoute
cityList = []
# tutaj ma być lista kordów potencjalnych śmietników z drzewa decyzyjnego
# for i in range(0,25):
# cityList.append(City(x=int(random.random() * 200), y=int(random.random() * 200))) cityList = []
# geneticAlgorithm(population=cityList, popSize=100, eliteSize=20, mutationRate=0.01, generations=1000)
# for i in range(0,25):
# cityList.append(City(x=int(random.random() * 200), y=int(random.random() * 200)))
# plotting the progress
# geneticAlgorithm(population=cityList, popSize=100, eliteSize=20, mutationRate=0.01, generations=1000)
def geneticAlgorithmPlot(population, popSize, eliteSize, mutationRate, generations):
pop = initialPopulation(popSize, population)
progress = [] # plotting the progress
progress.append(1 / rankRoutes(pop)[0][1])
print("Initial distance: " + str(1 / rankRoutes(pop)[0][1])) 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)
for i in range(0, generations):
pop = nextGeneration(pop, eliteSize, mutationRate) def geneticAlgorithmPlot(population, popSize, eliteSize, mutationRate, generations, array):
progress.append(1 / rankRoutes(pop)[0][1]) a_star_distances = {}
for city in population:
print("Final distance: " + str(1 / rankRoutes(pop)[0][1])) for target in population:
bestRouteIndex = rankRoutes(pop)[0][0] if city == target:
bestRoute = pop[bestRouteIndex] continue
else:
plt.plot(progress) a_star_distances[str(city.x)+" "+str(city.y)+" "+str(target.x)+" "+str(target.y)] = distanceFromCityToCity(city, target, array)
plt.ylabel('Distance')
plt.xlabel('Generation') pop = initialPopulation(popSize, population)
plt.show() progress = []
return bestRoute progress.append(1 / rankRoutes(pop, a_star_distances)[0][1])
print("Initial distance: " + str(1 / rankRoutes(pop, a_star_distances)[0][1]))
# geneticAlgorithmPlot(population=cityList, popSize=100, eliteSize=20, mutationRate=0.01, generations=1000)
for i in range(0, generations):
pop = nextGeneration(pop, eliteSize, mutationRate, a_star_distances)
progress.append(1 / rankRoutes(pop, a_star_distances)[0][1])
print("Final distance: " + str(1 / rankRoutes(pop, a_star_distances)[0][1]))
bestRouteIndex = rankRoutes(pop, a_star_distances)[0][0]
bestRoute = pop[bestRouteIndex]
plt.plot(progress)
plt.ylabel('Distance')
plt.xlabel('Generation')
plt.show()
return bestRoute
# geneticAlgorithmPlot(population=cityList, popSize=100, eliteSize=20, mutationRate=0.01, generations=1000)

512
main.py
View File

@ -1,256 +1,258 @@
import os import os
import sys import sys
from random import randint from random import randint
import math import math
import pygame as pg import pygame as pg
import numpy import numpy
from game_objects.player import Player from game_objects.player import Player
from game_objects.aiPlayer import aiPlayer from game_objects.aiPlayer import aiPlayer
from game_objects.trash import Trash from game_objects.trash import Trash
from map import map from map import map
from map import map_utils from map import map_utils
from settings import * from settings import *
from path_search_algorthms import bfs from path_search_algorthms import bfs
from path_search_algorthms import a_star_controller, a_star from path_search_algorthms import a_star_controller, a_star
from decision_tree import decisionTree from decision_tree import decisionTree
from NeuralNetwork import prediction from NeuralNetwork import prediction
from game_objects.trash import Trash from game_objects.trash import Trash
from genetic_algorithm import TSP from genetic_algorithm import TSP
from game_objects import aiPlayer from game_objects import aiPlayer
import itertools import itertools
def getTree(): def getTree():
tree = decisionTree.tree() tree = decisionTree.tree()
decisionTree.tree_as_txt(tree) decisionTree.tree_as_txt(tree)
# decisionTree.tree_to_png(tree) # decisionTree.tree_to_png(tree)
decisionTree.tree_to_structure(tree) decisionTree.tree_to_structure(tree)
drzewo = decisionTree.tree_from_structure('./decision_tree/tree_model') drzewo = decisionTree.tree_from_structure('./decision_tree/tree_model')
# print("Dla losowych danych predykcja czy wziąć kosz to: ") # print("Dla losowych danych predykcja czy wziąć kosz to: ")
# dec = decisionTree.decision(drzewo, *(4,1,1,1)) # dec = decisionTree.decision(drzewo, *(4,1,1,1))
# print('---') # print('---')
# print(f"decision is{dec}") # print(f"decision is{dec}")
# print('---') # print('---')
return drzewo return drzewo
class Game(): class Game():
def __init__(self): def __init__(self):
pg.init() pg.init()
pg.font.init() pg.font.init()
self.clock = pg.time.Clock() self.clock = pg.time.Clock()
self.dt = self.clock.tick(FPS) / 333.0 self.dt = self.clock.tick(FPS) / 333.0
self.screen = pg.display.set_mode((WIDTH, HEIGHT)) self.screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption("Trashmaster") pg.display.set_caption("Trashmaster")
self.load_data() self.load_data()
self.init_game() self.init_game()
# because dont work without data.txt # because dont work without data.txt
# self.init_bfs() # self.init_bfs()
# self.init_a_star() # self.init_a_star()
self.t = aiPlayer.aiPlayer(self.player, game=self) self.t = aiPlayer.aiPlayer(self.player, game=self)
def init_game(self): def init_game(self):
# initialize all variables and do all the setup for a new game # initialize all variables and do all the setup for a new game
self.text_display = '' self.text_display = ''
# sprite groups and map array for calculations # sprite groups and map array for calculations
(self.roadTiles, self.wallTiles, self.trashbinTiles), self.mapArray = map.get_tiles() (self.roadTiles, self.wallTiles, self.trashbinTiles), self.mapArray = map.get_tiles()
# save current map # save current map
file = open('last_map.nparr', 'wb') file = open('last_map.nparr', 'wb')
numpy.save(file, self.mapArray, allow_pickle=True) numpy.save(file, self.mapArray, allow_pickle=True)
file.close file.close
self.trashDisplay = pg.sprite.Group() self.trashDisplay = pg.sprite.Group()
self.agentSprites = pg.sprite.Group() self.agentSprites = pg.sprite.Group()
# player obj # player obj
self.player = Player(self, 32, 32) self.player = Player(self, 32, 32)
# camera obj # camera obj
self.camera = map_utils.Camera(MAP_WIDTH_PX, MAP_HEIGHT_PX) self.camera = map_utils.Camera(MAP_WIDTH_PX, MAP_HEIGHT_PX)
# other # other
self.debug_mode = False self.debug_mode = False
def init_bfs(self): def init_bfs(self):
start_node = (0, 0) start_node = (0, 0)
target_node = (18, 18) target_node = (18, 18)
find_path = bfs.BreadthSearchAlgorithm(start_node, target_node, self.mapArray) find_path = bfs.BreadthSearchAlgorithm(start_node, target_node, self.mapArray)
path = find_path.bfs() path = find_path.bfs()
# print(path) # print(path)
realPath = [] realPath = []
nextNode = target_node nextNode = target_node
for i in range(len(path) - 1, 0, -1): for i in range(len(path) - 1, 0, -1):
node = path[i] node = path[i]
if node[0] == nextNode: if node[0] == nextNode:
realPath.insert(0, node[0]) realPath.insert(0, node[0])
nextNode = node[1] nextNode = node[1]
print(realPath) print(realPath)
def init_decision_tree(self): def init_decision_tree(self):
# logika pracy z drzewem # logika pracy z drzewem
self.positive_decision = [] self.positive_decision = []
self.negative_decision = [] self.negative_decision = []
for i in self.trashbinTiles: for i in self.trashbinTiles:
atrrs_container = i.get_attributes() atrrs_container = i.get_attributes()
x, y = i.get_coords() x, y = i.get_coords()
dec = decisionTree.decision(getTree(), *atrrs_container) dec = decisionTree.decision(getTree(), *atrrs_container)
# if dec[0] == 1: # if dec[0] == 1:
self.positive_decision.append(i) # zmiana po to by losowało wszystkie smietniki a nie poprawne tylko, zeby ladniej bylo widac algorytm genetyczny self.positive_decision.append(i) # zmiana po to by losowało wszystkie smietniki a nie poprawne tylko, zeby ladniej bylo widac algorytm genetyczny
# else: # else:
# self.negative_decision.append(i) # self.negative_decision.append(i)
print('positive actions') print('positive actions')
print(len(self.positive_decision)) print(len(self.positive_decision))
# print('positive actions') # print('positive actions')
# for i in self.positive_actions: # for i in self.positive_actions:
# print('----') # print('----')
# print(i) # print(i)
# print('----') # print('----')
self.draw() self.draw()
def decsion_tree_move(self): def decsion_tree_move(self):
for i in range(0,len(self.positive_decision)): for i in range(0,len(self.positive_decision)):
# print(i.get_coords()) # print(i.get_coords())
print('action') print('action')
# trash_x, trash_y = i.get_coords() # trash_x, trash_y = i.get_coords()
# for ii in self.tsp_list: # for ii in self.tsp_list:
temp_tsp = str(self.tsp_list[i]) temp_tsp = str(self.tsp_list[i])
temp_tsp = temp_tsp.strip("()") temp_tsp = temp_tsp.strip("()")
temp_tsp = temp_tsp.split(",") temp_tsp = temp_tsp.split(",")
trash_x = int(temp_tsp[0]) trash_x = int(temp_tsp[0])
trash_y = int(temp_tsp[1]) trash_y = int(temp_tsp[1])
print(trash_x, trash_y) print(trash_x, trash_y)
action = a_star_controller.get_actions_for_target_coords(trash_x, trash_y, self) action = a_star_controller.get_actions_for_target_coords(trash_x, trash_y, self)
print(action) print(action)
self.t.startAiController(action) self.t.startAiController(action)
print('') print('')
print('--rozpoczecie sortowania smietnika--') print('--rozpoczecie sortowania smietnika--')
dir = "./resources/trash_dataset/test/all" dir = "./resources/trash_dataset/test/all"
files = os.listdir(dir) files = os.listdir(dir)
for j in range(0, 10): for j in range(0, 10):
random = randint(0, 48) random = randint(0, 48)
file = files[random] file = files[random]
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()
self.trashDisplay.add(trash) trash = Trash(img, math.floor(-offset_x * TILESIZE), math.floor(-offset_y * TILESIZE), 128, 128)
self.text_display = result self.trashDisplay.empty()
self.draw() self.trashDisplay.add(trash)
# print(result + ' ' + file) self.text_display = result
pg.time.wait(100) self.draw()
self.text_display = '' pg.time.wait(100)
self.draw() self.text_display = ''
self.trashDisplay.empty()
# print(self.positive_actions[0]) self.draw()
# self.t.startAiController(self.positive_actions[0]) # print(self.positive_actions[0])
def init_TSP(self):
# self.t.startAiController(self.positive_actions[0])
city_list =[] def init_TSP(self):
for i in self.positive_decision: city_list =[]
trash_x, trash_y = i.get_coords()
# city_list.append(TSP.City(x=int(trash_x), y=int(trash_y), array=self.mapArray)) for i in self.positive_decision:
city_list.append(TSP.City(x=int(trash_x), y=int(trash_y))) 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=trash_x, y=trash_y, array=self.mapArray))
# dist = a_star.get_cost
self.tsp_list = TSP.geneticAlgorithmPlot(population=city_list, popSize=100, eliteSize=20, mutationRate=0.01, generations=300)
print(self.tsp_list) # dist = a_star.get_cost
self.tsp_list = TSP.geneticAlgorithmPlot(population=city_list, popSize=100, eliteSize=20, mutationRate=0.01, generations=300, array=self.mapArray)
def load_data(self): print(self.tsp_list)
game_folder = os.path.dirname(__file__)
img_folder = os.path.join(game_folder, 'resources/textures') def load_data(self):
game_folder = os.path.dirname(__file__)
self.player_img = pg.image.load(os.path.join(img_folder, PLAYER_IMG)).convert_alpha() img_folder = os.path.join(game_folder, 'resources/textures')
self.player_img = pg.transform.scale(self.player_img, (PLAYER_WIDTH, PLAYER_HEIGHT))
self.player_img = pg.image.load(os.path.join(img_folder, PLAYER_IMG)).convert_alpha()
def run(self): self.player_img = pg.transform.scale(self.player_img, (PLAYER_WIDTH, PLAYER_HEIGHT))
# game loop - set self.playing = False to end the game
self.playing = True def run(self):
self.init_decision_tree() # game loop - set self.playing = False to end the game
self.init_TSP() self.playing = True
self.decsion_tree_move() self.init_decision_tree()
self.init_TSP()
while self.playing: self.decsion_tree_move()
self.dt = self.clock.tick(FPS) / 1000.0
self.events() while self.playing:
self.update() self.dt = self.clock.tick(FPS) / 1000.0
self.draw() self.events()
self.update()
def quit(self): self.draw()
pg.quit()
sys.exit() def quit(self):
pg.quit()
def update(self): sys.exit()
# update portion of the game loop
self.agentSprites.update() def update(self):
self.camera.update(self.player) # update portion of the game loop
# pygame.display.update() self.agentSprites.update()
self.camera.update(self.player)
def draw(self): # pygame.display.update()
# display fps as window title
pg.display.set_caption("{:.2f}".format(self.clock.get_fps())) def draw(self):
# display fps as window title
# rerender map pg.display.set_caption("{:.2f}".format(self.clock.get_fps()))
map.render_tiles(self.roadTiles, self.screen, self.camera)
map.render_tiles(self.wallTiles, self.screen, self.camera, self.debug_mode) # rerender map
map.render_tiles(self.trashbinTiles, self.screen, self.camera) map.render_tiles(self.roadTiles, self.screen, self.camera)
map.render_tiles(self.trashDisplay, self.screen, self.camera) map.render_tiles(self.wallTiles, self.screen, self.camera, self.debug_mode)
map.render_tiles(self.trashbinTiles, self.screen, self.camera)
# draw text map.render_tiles(self.trashDisplay, self.screen, self.camera)
text_surface = pg.font.SysFont('Comic Sans MS', 30).render(self.text_display, False, (255, 255, 255))
self.screen.blit(text_surface, (0, 128)) # draw text
text_surface = pg.font.SysFont('Comic Sans MS', 30).render(self.text_display, False, (255, 255, 255))
# rerender additional sprites self.screen.blit(text_surface, (0, 128))
for sprite in self.agentSprites:
self.screen.blit(sprite.image, self.camera.apply(sprite)) # rerender additional sprites
if self.debug_mode: for sprite in self.agentSprites:
pg.draw.rect(self.screen, CYAN, self.camera.apply_rect(sprite.hit_rect), 1) self.screen.blit(sprite.image, self.camera.apply(sprite))
if self.debug_mode:
# self.player.hud_group.draw(self.screen) pg.draw.rect(self.screen, CYAN, self.camera.apply_rect(sprite.hit_rect), 1)
# finally update screen
pg.display.flip() # self.player.hud_group.draw(self.screen)
# finally update screen
def events(self): pg.display.flip()
for event in pg.event.get():
if event.type == pg.QUIT: def events(self):
self.quit() for event in pg.event.get():
if event.type == pg.KEYDOWN: if event.type == pg.QUIT:
if event.key == pg.K_ESCAPE: self.quit()
self.quit() if event.type == pg.KEYDOWN:
if event.key == pg.K_h: if event.key == pg.K_ESCAPE:
self.debug_mode = not self.debug_mode self.quit()
if event.type == pg.MOUSEBUTTONUP: if event.key == pg.K_h:
pos = pg.mouse.get_pos() self.debug_mode = not self.debug_mode
offset_x, offset_y = self.camera.offset() if event.type == pg.MOUSEBUTTONUP:
clicked_coords = [math.floor(pos[0] / TILESIZE) - offset_x, math.floor(pos[1] / TILESIZE) - offset_y] pos = pg.mouse.get_pos()
actions = a_star_controller.get_actions_by_coords(clicked_coords[0], clicked_coords[1], self) offset_x, offset_y = self.camera.offset()
clicked_coords = [math.floor(pos[0] / TILESIZE) - offset_x, math.floor(pos[1] / TILESIZE) - offset_y]
if (actions != None): actions = a_star_controller.get_actions_by_coords(clicked_coords[0], clicked_coords[1], self)
self.t.startAiController(actions)
if (actions != None):
self.t.startAiController(actions)
# create the game object
if __name__ == "__main__": # create the game object
g = Game()
if __name__ == "__main__":
g.run() g = Game()
g.run()
g.show_go_screen() g.show_go_screen()

View File

@ -1,76 +1,79 @@
from data_structures.heap import Heap from data_structures.heap import Heap
from path_search_algorthms import a_star_utils as utils 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)
if actions is None: print('length')
return 1 if actions is None:
return len(actions) print('0')
return 1
print(len(actions))
def search_path(start_x: int, start_y: int, agent_rotation: utils.Rotation, target_x: int, target_y: int, array): return len(actions)
start_node = utils.Node(start_x, start_y, agent_rotation)
target_node = utils.Node(target_x, target_y, utils.Rotation.NONE)
def search_path(start_x: int, start_y: int, agent_rotation: utils.Rotation, target_x: int, target_y: int, array):
# heap version start_node = utils.Node(start_x, start_y, agent_rotation)
target_node = utils.Node(target_x, target_y, utils.Rotation.NONE)
# nodes for check
search_list = Heap() # heap version
search_list.append(start_node, 0)
# nodes for check
# checked nodes search_list = Heap()
searched_list: list[(int, int)] = [] search_list.append(start_node, 0)
while (search_list.length() > 0): # checked nodes
node: utils.Node = search_list.take_first() searched_list: list[(int, int)] = []
searched_list.append((node.x, node.y)) while (search_list.length() > 0):
node: utils.Node = search_list.take_first()
# check for target node
if ((node.x, node.y) == (target_x, target_y)): searched_list.append((node.x, node.y))
return trace_path(node)
# check for target node
# neightbours processing if ((node.x, node.y) == (target_x, target_y)):
neighbours = utils.get_neighbours(node, searched_list, array) return trace_path(node)
for neighbour in neighbours:
# neightbours processing
# calculate new g cost for neightbour (start -> node -> neightbour) neighbours = utils.get_neighbours(node, searched_list, array)
new_neighbour_cost = node.g_cost + utils.get_neighbour_cost(node, neighbour) for neighbour in neighbours:
if (new_neighbour_cost < neighbour.g_cost or not search_list.contains(neighbour)): # calculate new g cost for neightbour (start -> node -> neightbour)
new_neighbour_cost = node.g_cost + utils.get_neighbour_cost(node, neighbour)
# replace cost and set parent node
neighbour.g_cost = new_neighbour_cost if (new_neighbour_cost < neighbour.g_cost or not search_list.contains(neighbour)):
neighbour.h_cost = utils.get_h_cost(neighbour, target_node)
neighbour.parent = node # replace cost and set parent node
neighbour.g_cost = new_neighbour_cost
# add to search neighbour.h_cost = utils.get_h_cost(neighbour, target_node)
if (not search_list.contains(neighbour)): neighbour.parent = node
search_list.append(neighbour, neighbour.f_cost())
# add to search
if (not search_list.contains(neighbour)):
def trace_path(end_node: utils.Node): search_list.append(neighbour, neighbour.f_cost())
path = []
node = end_node
def trace_path(end_node: utils.Node):
# set final rotation of end_node because we don't do it before path = []
node.rotation = utils.get_needed_rotation(node.parent, node) node = end_node
while (node.parent != False): # set final rotation of end_node because we don't do it before
if (node.parent == utils.Rotation.NONE): node.rotation = utils.get_needed_rotation(node.parent, node)
path += "forward"
else: while (node.parent != False):
path += utils.get_move(node.parent, node) if (node.parent == utils.Rotation.NONE):
node = node.parent path += "forward"
else:
# delete move on initial tile path += utils.get_move(node.parent, node)
path.pop() node = node.parent
# we found path from end, so we need to reverse it (get_move reverse move words) # delete move on initial tile
path.reverse() path.pop()
# last forward to destination # we found path from end, so we need to reverse it (get_move reverse move words)
path.append("forward") path.reverse()
return path # last forward to destination
path.append("forward")
return path