added GeneticFinder
This commit is contained in:
parent
47bd1c456d
commit
62cae15baa
@ -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
39
Engine/Fitness.py
Normal 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
|
@ -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
58
Engine/GeneticFinder.py
Normal 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
121
Engine/Population.py
Normal 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.
BIN
Engine/__pycache__/Fitness.cpython-39.pyc
Normal file
BIN
Engine/__pycache__/Fitness.cpython-39.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
Engine/__pycache__/GeneticFinder.cpython-39.pyc
Normal file
BIN
Engine/__pycache__/GeneticFinder.cpython-39.pyc
Normal file
Binary file not shown.
BIN
Engine/__pycache__/Population.cpython-39.pyc
Normal file
BIN
Engine/__pycache__/Population.cpython-39.pyc
Normal file
Binary file not shown.
BIN
Engine/tree.pkl
BIN
Engine/tree.pkl
Binary file not shown.
14
main.py
14
main.py
@ -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()
|
Loading…
Reference in New Issue
Block a user