diff --git a/DNA.py b/DNA.py new file mode 100644 index 0000000..36c69d6 --- /dev/null +++ b/DNA.py @@ -0,0 +1,55 @@ +import random +import string +from astar import Astar +from random import shuffle +import numpy as np + +A = np.zeros((10, 10), dtype=int) + +goals = [[0, 4], [4, 0], [4, 4]] + +recordDistance = 0 + +class DNA: + + def __init__(self, target, recordDistance): + shuffle(target) + self.genes = target.copy() + self.fitness = 1.0 + self.recordDistance = recordDistance + + def calcFitness(self, A): + start = [0, 0] + sum = 1 + + for goal in self.genes: + path = Astar(A, start, goal) + sum = sum + len(path) - 1 + start = goal + + self.fitness = sum + + def crossover(self, partner): + + child = DNA(self.genes, self.recordDistance) + start = abs(random.randint(0, len(self.genes)) - 1) + end = abs(random.randint(start - 1, len(self.genes))) + + child.genes = child.genes[start:end] + + for i in range(len(self.genes)): + node = partner.genes[i] + + if node not in child.genes: + child.genes.append(node) + + return child + + def mutate(self, mutationRate): + + for i in range(len(self.genes)): + if random.random() < mutationRate: + indexA = abs(random.randint(0, len(self.genes)) - 1) + indexB = (indexA + 1) % len(self.genes) + self.genes[indexA], self.genes[indexB] = self.genes[indexB], self.genes[indexA] + diff --git a/GarbageTruck.png b/GarbageTruck.png new file mode 100644 index 0000000..5d44e1d Binary files /dev/null and b/GarbageTruck.png differ diff --git a/Home.png b/Home.png new file mode 100644 index 0000000..6d9d028 Binary files /dev/null and b/Home.png differ diff --git a/astar.py b/astar.py new file mode 100644 index 0000000..2f7d23c --- /dev/null +++ b/astar.py @@ -0,0 +1,87 @@ +import numpy as np + +class node: + + def __init__(self, x, y): + self.x = x + self.y = y + self.neighbours = [] + self.parent = None + self.g = 0 + self.f = 0 + self.h = 0 + + def makeNeighbours(self, matrix): + + if self.x - 1 >= 0 and matrix[self.x - 1, self.y] != 3: + self.neighbours.append([self.x - 1, self.y]) + + if self.x + 1 < matrix.shape[0] and matrix[self.x + 1, self.y] != 3: + self.neighbours.append([self.x + 1, self.y]) + + if self.y + 1 < matrix.shape[1] and matrix[self.x, self.y + 1] != 3: + self.neighbours.append([self.x, self.y + 1]) + + if self.y - 1 >= 0 and matrix[self.x, self.y - 1] != 3: + self.neighbours.append([self.x, self.y - 1]) + + def calcHeuristic(self, goal): + self.h = abs(self.x - goal.x) + abs(self.y - goal.y) + +def Astar(A, start, goal): + frontier = [] + + objects = {} + + for i in range(A.shape[0]): + for j in range(A.shape[1]): + objects[i, j] = node(i, j) + + objects[0, 0].visited = True + goal = objects[goal[0], goal[1]] + start = objects[start[0], start[1]] + + frontier.append(start) + + open = [] + closed = [] + + open.append(start) + + while open: + open.sort(key=lambda o: o.f) + + current = open.pop(0) + + closed.append(current) + + current.makeNeighbours(A) + + if current == goal: + break + + for next in current.neighbours: + if objects[next[0], next[1]] in closed: + continue + + if objects[next[0], next[1]] in open: + new_g = current.g + 1 + if objects[next[0], next[1]].g > new_g: + objects[next[0], next[1]].g = new_g + objects[next[0], next[1]].parent = objects[current.x, current.y] + + else: + objects[next[0], next[1]].g = objects[current.x, current.y].g + 1 + objects[next[0], next[1]].calcHeuristic(goal) + objects[next[0], next[1]].parent = objects[current.x, current.y] + open.append(objects[next[0], next[1]]) + + path = [] + while current.parent: + path.append([current.x, current.y]) + current = current.parent + + path.append([start.x, start.y]) + path.reverse() + + return path \ No newline at end of file diff --git a/genetic.py b/genetic.py new file mode 100644 index 0000000..f7cc056 --- /dev/null +++ b/genetic.py @@ -0,0 +1,52 @@ +from astar import Astar +import numpy as np +from DNA import DNA +import random +import copy + +def genetic(goals, A): + recordDistance = 1000000000 + + #count = 0 + generation = 0 + totalPopulaton = 10 + population = [] + matingPool = [] + + mutationRate = 0.01 + + for i in range(totalPopulaton): + population.append(DNA(goals, recordDistance)) + + for j in range(totalPopulaton): + matingPool.clear() + generation = generation + 1 + for i in range(totalPopulaton): + population[i].calcFitness(A) + + if population[i].fitness < recordDistance: + recordDistance = population[i].fitness + best = copy.deepcopy(population[i]) + bestGeneration = generation + + for i in range(totalPopulaton): + n = population[i].fitness * 100 + + for j in range(int(n)): + matingPool.append(population[i]) + + for i in range(totalPopulaton): + if matingPool: + a = random.randint(0, len(matingPool) - 1) + b = random.randint(0, len(matingPool) - 1) + + partnerA = matingPool[a] + partnerB = matingPool[b] + + child = partnerA.crossover(partnerB) + + child.mutate(mutationRate) + + population[i] = child + + return best diff --git a/main.py b/main.py new file mode 100644 index 0000000..a4d7647 --- /dev/null +++ b/main.py @@ -0,0 +1,115 @@ +import pygame +from pygame.locals import * +from astar import Astar +from genetic import genetic +import numpy as np +import time + +def drawGrid(w, rows, surface, goals): + sizeBtwn = w // rows + x = 0 + y = 0 + for l in range(rows): + x = x + sizeBtwn + y = y + sizeBtwn + + pygame.draw.line(surface, (255, 0, 255), (x, 0), (x, width)) + pygame.draw.line(surface, (255, 0, 255), (0, y), (width, y)) + +def drawHouses(houses): + for house in houses: + screen.blit(home, (13 + house[1] * 60, 15 + house[0] * 60)) + +def drawObstacles(obs): + for ob in obs: + screen.blit(xobstacle, (13 + ob[1] * 60, 15 + ob[0] * 60)) + +def findObstacles(A): + obstacles = [] + for i in range(10): + for j in range(10): + if A[i][j] == 3: + obstacles.append([i, j]) + + return obstacles + + + +pygame.init() + +width = 600 +height = 600 +FPS = 60 +running = True +fpsClock = pygame.time.Clock() + +screen = pygame.display.set_mode((height, height), 0, 32) + +pygame.display.set_caption('InteligentnaSmieciarka2000') +truck = pygame.image.load('GarbageTruck.png') +home = pygame.image.load('Home.png') +xobstacle = pygame.image.load("x.png") + +w = 10 +rows = 10 +A = np.zeros((w, rows), dtype=int) + +A[1, 0] = 3 +A[0, 2] = 3 +A[4, 1] = 3 +rows = 10 +x = 15 +y = 20 + +sizeBtwn = width // rows + +parent = [0, 0] + +goals = [[0, 4], [4, 0], [4, 4], [6, 7]] +houses = goals.copy() + +goals = genetic(goals, A).genes + +start = [0, 0] + +obsta = findObstacles(A) + +while goals: + + goal = goals.pop(0) + path = Astar(A, start, goal) + start = goal + while path: + screen.fill((0, 0, 0)) + drawGrid(width, rows, screen, goals) + drawHouses(houses) + drawObstacles(obsta) + + pygame.event.get() + + if path: + destination = path.pop(0) + temp = destination + destination = [destination[0] - parent[0], destination[1] - parent[1]] + + if destination[0] == 1: + y += 60 + time.sleep(0.3) + elif destination[0] == -1: + y -= 60 + time.sleep(0.3) + elif destination[1] == 1: + x += 60 + time.sleep(0.3) + elif destination[1] == -1: + x -= 60 + time.sleep(0.3) + + parent = temp + screen.blit(truck, (x, y)) + pygame.display.update() + + #screen.blit(truck, (x, y)) + #pygame.display.update() + +time.sleep(5) \ No newline at end of file diff --git a/x.png b/x.png new file mode 100644 index 0000000..d3ac62b Binary files /dev/null and b/x.png differ