added GeneticFinder

This commit is contained in:
barmal4 2021-06-14 22:20:20 +02:00
parent 47bd1c456d
commit 62cae15baa
13 changed files with 243 additions and 8 deletions

View File

@ -21,7 +21,7 @@ class DecisionTree:
decision_tree_model_pkl = open('tree.pkl', 'wb')
pickle.dump(dtree, decision_tree_model_pkl)
decision_tree_model_pkl.close()
decision_tree_model_pkl = open('Engine/tree.pkl', 'rb')
decision_tree_model_pkl = open('C:\\Users\\kratu\\PycharmProjects\\Projekt_AI-Automatyczny_saper\\Engine\\tree.pkl', 'rb')
self.dtree = pickle.load(decision_tree_model_pkl)
def getTree(self):

39
Engine/Fitness.py Normal file
View File

@ -0,0 +1,39 @@
import numpy as np
from Engine.GeneticFinder import GeneticFinder
from Engine.State import State
from Constants import RIGHT
class Fitness:
def __init__(self, route, board, dTree):
self.route = route
self.distance = 0
self.fitness = 0.0
self.board = board
self.dTree = dTree
def routeDistance(self):
if self.distance == 0:
pathDistance = 0
for i in range(0, len(self.route)):
fromPoint = self.route[i]
toPoint = None
if i + 1 < len(self.route):
toPoint = self.route[i + 1]
else:
toPoint = self.route[0]
pathDistance += self.cdistance(fromPoint, toPoint)
self.distance = pathDistance
return self.distance
def routeFitness(self):
if self.fitness == 0:
self.fitness = 1 / float(self.routeDistance())
return self.fitness
def cdistance(self, fromP, toP):
xDis = abs(fromP.getX() - toP.getX())
yDis = abs(fromP.getY() - toP.getY())
distance = np.sqrt((xDis ** 2) + (yDis ** 2))
return distance

View File

@ -5,6 +5,7 @@ from Constants import SQUARE_SIZE, GREEN, RIGHT, LEFT, UP, DOWN, COLS, ROWS, DEC
from Engine.Board import Board
from Engine.Agent import Agent
from Engine.BombFactory import BombFactory
from Engine.GeneticFinder import GeneticFinder
from Engine.Point import Point
from Engine.Stone import Stone
from Engine.BfsPathFinder import BfsPathFinder
@ -70,7 +71,7 @@ class Game:
while i < 10:
point = Point(random.randint(0, 9), random.randint(0, 9))
if(point.getX() == 0 and point.getY() == 0):
continue;
continue
if point not in self.board.bombMap:
object = self.pickObject(random.randint(0, 4))
self.board.bombMap[point] = object
@ -114,6 +115,10 @@ class Game:
# return BfsPathFinder(self.board).findBomb(State(self.agent.getOrientation(),Point(self.agent.getPoint().getX(),self.agent.getPoint().getY())))
return PathFinder(self.board,self.dTree).findBomb(State(self.agent.getOrientation(),Point(self.agent.getPoint().getX(),self.agent.getPoint().getY())))
def getBombPath(self, point):
self.agent.changeImage(AGENT)
return GeneticFinder(self.board,self.dTree).bombDistance(State(self.agent.getOrientation(),Point(self.agent.getPoint().getX(),self.agent.getPoint().getY())), State(None,point))
def finalState(self):
if len(self.board.bombMap) == 0 and len(self.path) == 0:
@ -185,11 +190,13 @@ class Game:
def poligionAction(self):
self.defuseBomb()
self.agent.changeImage(POLIGON)
self.update()
path = PoligonPath(self.board, self.dTree).findBomb(
State(self.agent.getOrientation(), Point(self.agent.getPoint().getX(), self.agent.getPoint().getY())))
self.savePath(path)
self.defuseBomb()
# self.agent.changeImage(POLIGON)
# self.update()
# path = PoligonPath(self.board, self.dTree).findBomb(
# State(self.agent.getOrientation(), Point(self.agent.getPoint().getX(), self.agent.getPoint().getY())))
# self.savePath(path)

58
Engine/GeneticFinder.py Normal file
View File

@ -0,0 +1,58 @@
from Engine.Node import Node
from Engine.PathFinder import PathFinder
class GeneticFinder(PathFinder):
def __init__(self, board, dTree):
super().__init__(board, dTree)
self.board = board
self.openList = []
self.cameFrom = {}
self.gScore = {}
self.fScore = {}
def bombDistance(self,startState, endState):
x = Node(startState, None)
self.openList.append(x)
self.gScore[x] = 0
self.fScore[x] = 0
self.endState = endState
cameFrom = dict()
cameFrom[x] = None
while self.openList:
current = self.minKey(self.fScore, self.openList)
if self.checkGoal(current):
return self.constructActions(current, startState)
self.openList.remove(current)
for next in self.getNeighbour(current):
tentativeGScore = self.gScore.get(current) + self.weight(next)
if tentativeGScore < self.gScore.get(next, float('inf')):
self.cameFrom[next] = current
next.parent = current
self.gScore[next] = tentativeGScore
self.fScore[next] = tentativeGScore + self.heuristic(startState, next)
if next not in self.openList:
self.openList.append(next)
return []
def checkGoal(self, current):
if current.state.getPoint().__eq__(self.endState.getPoint()):
bomb = self.board.getBomb(current.state.getPoint())
bombMapping = bomb.getMapping()
if(bombMapping[0] != None):
actionOnBomb = self.dTree.mapAction(self.dTree.getTree().predict([bombMapping])[0])
self.goal = Node(current, actionOnBomb)
else:
self.goal = Node(current, None)
return True
return False
def getDistance(self,startState, endState):
distance = 0
for state in self.bombDistance(startState,endState):
distance += 1
return distance

121
Engine/Population.py Normal file
View File

@ -0,0 +1,121 @@
import numpy as np, random, operator, pandas as pd, matplotlib.pyplot as plt
from Engine.Fitness import Fitness
class Population:
def __init__(self, board, dTree):
self.board = board
self.dTree = dTree
def initialPopulation(self, popSize, points):
population = []
for i in range(0, popSize):
population.append(self.createRoute(points))
return population
def createRoute(self, points):
route = random.sample(points, len(points))
return route
def rankRoutes(self, population):
fitnessResults = {}
for i in range(0, len(population)):
fitnessResults[i] = Fitness(population[i], self.board, self.dTree).routeFitness()
return sorted(fitnessResults.items(), key=operator.itemgetter(1), reverse=True)
def selection(self, popRanked, eliteSize):
selectionResults = []
df = pd.DataFrame(np.array(popRanked), columns=["Index", "Fitness"])
df['cum_sum'] = df.Fitness.cumsum()
df['cum_perc'] = 100 * df.cum_sum / df.Fitness.sum()
for i in range(0, eliteSize):
selectionResults.append(popRanked[i][0])
for i in range(0, len(popRanked) - eliteSize):
pick = 100 * random.random()
for i in range(0, len(popRanked)):
if pick <= df.iat[i, 3]:
selectionResults.append(popRanked[i][0])
break
return selectionResults
def matingPool(self, population, selectionResults):
matingpool = []
for i in range(0, len(selectionResults)):
index = selectionResults[i]
matingpool.append(population[index])
return matingpool
def breed(self, parent1, parent2):
child = []
childP1 = []
childP2 = []
geneA = int(random.random() * len(parent1))
geneB = int(random.random() * len(parent1))
startGene = min(geneA, geneB)
endGene = max(geneA, geneB)
for i in range(startGene, endGene):
childP1.append(parent1[i])
childP2 = [item for item in parent2 if item not in childP1]
child = childP1 + childP2
return child
def mutate(self, individual, mutationRate):
for swapped in range(len(individual)):
if (random.random() < mutationRate):
swapWith = int(random.random() * len(individual))
city1 = individual[swapped]
city2 = individual[swapWith]
individual[swapped] = city2
individual[swapWith] = city1
return individual
def mutatePopulation(self, population, mutationRate):
mutatedPop = []
for ind in range(0, len(population)):
mutatedInd = self.mutate(population[ind], mutationRate)
mutatedPop.append(mutatedInd)
return mutatedPop
def nextGeneration(self, currentGen, eliteSize, mutationRate):
popRanked = self.rankRoutes(currentGen)
selectionResults = self.selection(popRanked, eliteSize)
matingpool = self.matingPool(currentGen, selectionResults)
children = self.breedPopulation(matingpool, eliteSize)
nextGeneration = self.mutatePopulation(children, mutationRate)
return nextGeneration
def geneticAlgorithm(self, population, popSize, eliteSize, mutationRate, generations):
pop = self.initialPopulation(popSize, population)
print("Initial distance: " + str(1 / self.rankRoutes(pop)[0][1]))
for i in range(0, generations):
pop = self.nextGeneration(pop, eliteSize, mutationRate)
print("Final distance: " + str(1 / self.rankRoutes(pop)[0][1]))
bestRouteIndex = self.rankRoutes(pop)[0][0]
bestRoute = pop[bestRouteIndex]
return bestRoute
def breedPopulation(self,matingpool, eliteSize):
children = []
length = len(matingpool) - eliteSize
pool = random.sample(matingpool, len(matingpool))
for i in range(0, eliteSize):
children.append(matingpool[i])
for i in range(0, length):
child = self.breed(pool[i], pool[len(matingpool) - i - 1])
children.append(child)
return children

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

14
main.py
View File

@ -1,15 +1,25 @@
import pygame
from Engine.Game import Game
from Engine.Point import Point
from Engine.Population import Population
WIN = pygame.display.set_mode((800, 800))
FPS = 60
def getPopulation(game):
bombList = []
# bombList.append(Point(0,0))
for x in game.board.bombMap:
bombList.append(x)
return bombList
def main():
run = True
clock = pygame.time.Clock()
game = Game(WIN)
population = Population(game.board, game.dTree)
points = population.geneticAlgorithm(getPopulation(game), popSize=100, eliteSize=20, mutationRate=0.01, generations=500)
while run:
pygame.init()
@ -23,10 +33,10 @@ def main():
if game.finalState():
break
if len(game.getPath()) == 0:
path = game.findBomb()
path = game.getBombPath(points.pop(0))
game.savePath(path)
game.moveToNext()
game.update()
main()
main()