diff --git a/classes/Garbagetruck.py b/classes/Garbagetruck.py index 3111bba..6fdead6 100644 --- a/classes/Garbagetruck.py +++ b/classes/Garbagetruck.py @@ -1,12 +1,15 @@ -import math import heapq +import math +import pickle + import numpy as np -from joblib import load import pygame +from joblib import load +from tensorflow.keras.models import load_model + from classes.Household import * from classes.Node import * from classes.Trashcan import Trashcan -from tensorflow.keras.models import load_model class Garbagetruck: @@ -18,7 +21,7 @@ class Garbagetruck: self.daytime = random.randint(0, 3) self.zapelnienie: int = 1 self.knowledge = [self.season, self.daytime, -1, -1, self.zapelnienie, -1, -1, self.weather] - self.capacity: int = 20 + self.capacity: int = 10 self.trash: list = [] self.trashweight: int = 0 self.image = pygame.image.load("sprites/smieciara.png").convert_alpha() @@ -32,15 +35,34 @@ class Garbagetruck: "Mixed": "mixed", "Bio": "bio_waste", "Szklo": "glass"} - self.route = None # jeszcze nie + self.route = pickle.load(open('classes/best_path.pkl', "rb")) # używane self.scanner = load_model("./classes/best_model_newD.h5") - self.planner = None # jeszcze nie self.driver = load("./classes/drzewo.joblib") self.orientation = 3 # Niech numery będą tak: N - 0, W - 1, S - 2, E - 3 -- po prostu odwrotnie do zegara self.runningtime = 0 self.movesequence = [] self.target = None # używane self.analising = False # używane + self.dumping = 0 + + def switchDumping(self): + self.dumping = 0 if self.dumping else 1 + + def goDumpTrash(self): + if self.dumping: + return + if self.trashweight >= 0.8 * self.capacity or not self.route: + self.addPointsToRoute() + print("Zaczynam wyrzucać śmieci") + self.switchDumping() + self.setTarget() + self.setMovesequence(self.graphsearch()) + + def addPointsToRoute(self): + points = [0] + points.extend([trash.getPosition() for trash in self.trashcans]) + points.extend(self.route) + self.route = points def identify(self, trash): obraz = trash.getImage() @@ -92,16 +114,6 @@ class Garbagetruck: self.movesequence = movesequence return self - def setTarget(self): - for place in self.houses: - if place.getFinal(): - self.target = place - return - for place in self.trashcans: - if place.getFinal(): - self.target = place - return - def getOrientation(self): return self.orientation @@ -152,7 +164,7 @@ class Garbagetruck: def changeZapelnienie(self) -> None: if self.trashweight < 0.25*self.capacity: self.zapelnienie = 1 - elif self.trashweight < self.capacity: + elif self.trashweight <= self.capacity: self.zapelnienie = 2 else: self.zapelnienie = 0 @@ -243,10 +255,16 @@ class Garbagetruck: return self.mult*x, self.mult*y def throwGarbage(self): - for item in self.trash: - if item.getTtype() == self.state.getTrashtype(): - self.addTrashweight(item.getWeight * (-1)) + for item in self.trash[:]: + con = True if item.getTtype() == self.state.getTrashtype() else False + print(con) + if con: + self.addTrashweight(item.getWaga() * (-1)) self.trash.remove(item) + print(f'{self.trashweight}/{self.capacity} - Pozostałe zapełnienie śmieciarki') + if self.trashweight == 0: + print("Skończyłem wyrzucać śmieci") + self.switchDumping() def rotateImage(self, arg): self.image = pygame.transform.rotate(self.image, 90*arg) @@ -317,7 +335,7 @@ class Garbagetruck: def heuristic(state): x, y, _ = state - target_x, target_y = self.target.getPosition() + target_x, target_y = self.target return abs(target_x - x) + abs(target_y - y) def cost(state): @@ -331,7 +349,7 @@ class Garbagetruck: fringe = [] explored = [] - target = self.target.getPosition() + target = self.target temp = self.getPosition()[:] temp.append(self.getOrientation()) initial = Node(temp) @@ -355,6 +373,7 @@ class Garbagetruck: lista = findWay(elem) result = lista[::-1] result.pop(0) + # self.switchAnalising() return result explored.append(elem) @@ -378,13 +397,25 @@ class Garbagetruck: elif element == "F": self.moveForward() - def randomTarget(self): - # wybor1 = random.random() - # if wybor1 < 0.75: - wybor2 = random.choice(self.houses) - while not wybor2.getGarbage().getContent(): - wybor2 = random.choice(self.houses) - # else: - # wybor2 = random.choice(self.trashcans) - wybor2.switchFinal() - # print(wybor2) + def setTarget(self): + self.route.pop(0) + self.target = self.route[0] + for house in self.houses: + if house.getPosition() == self.target: + house.switchFinal() + return + for can in self.trashcans: + if can.getPosition() == self.target: + can.switchFinal() + return + + def setFirstTarget(self): + self.target = self.route[0] + for house in self.houses: + if house.getPosition() == self.target: + house.switchFinal() + return + for can in self.trashcans: + if can.getPosition() == self.target: + can.switchFinal() + return diff --git a/classes/Household.py b/classes/Household.py index b518845..67c14e4 100644 --- a/classes/Household.py +++ b/classes/Household.py @@ -1,11 +1,9 @@ -import random - from classes.Garbage import * class Household: def __init__(self, mult): - self.paid = random.randint(0, 1) + self.paid = 1 if random.random() > 0.2 else 0 self.lastTaken = random.randint(0, 30) self.mult = mult self.id: int = 0 diff --git a/classes/NeuralNetwork.py b/classes/NeuralNetwork.py index b9abae5..b43704c 100644 --- a/classes/NeuralNetwork.py +++ b/classes/NeuralNetwork.py @@ -64,7 +64,7 @@ model.add(Conv2D(filters = 16, kernel_size = (3, 3), activation='relu', input_sh model.add(MaxPooling2D((2, 2))) model.add(Flatten()) model.add(Dense(128*128, activation='relu')) -model.add(Dense(1000, activation='relu')) +model.add(Dense(100, activation='relu')) # model.add(Dropout(0.2)) model.add(Dense(25, activation='relu')) # model.add(Dropout(0.2)) diff --git a/classes/Trash.py b/classes/Trash.py index 8f0b802..cb9980b 100644 --- a/classes/Trash.py +++ b/classes/Trash.py @@ -1,4 +1,5 @@ from random import choice as rd + from classes.trashFunctions import generatePicList @@ -59,7 +60,7 @@ class Papier(Trash): def __init__(self): super().__init__() self.tree_type = 1 - self.ttype = "Papier" + self.ttype = "paper" self.real_type = "Papier" self.scan_id = 0 self.waga = 2 @@ -73,7 +74,7 @@ class MetalPlastik(Trash): def __init__(self): super().__init__() self.tree_type = 2 - self.ttype = "MetalPlastik" + self.ttype = "metals_and_plastics" self.real_type = "MetalPlastik" self.scan_id = 4 self.waga = 3 @@ -87,7 +88,7 @@ class Mixed(Trash): def __init__(self): super().__init__() self.tree_type = 4 - self.ttype = "Mixed" + self.ttype = "mixed" self.real_type = "Mixed" self.scan_id = 2 self.waga = 1 @@ -101,7 +102,7 @@ class Bio(Trash): def __init__(self): super().__init__() self.tree_type = 0 - self.ttype = "Bio" + self.ttype = "bio" self.real_type = "Bio" self.scan_id = 1 self.waga = 2 @@ -115,7 +116,7 @@ class Szklo(Trash): def __init__(self): super().__init__() self.tree_type = 3 - self.ttype = "Szklo" + self.ttype = "glass" self.real_type = "Szklo" self.scan_id = 3 self.waga = 5 diff --git a/classes/best_path.pkl b/classes/best_path.pkl new file mode 100644 index 0000000..3bf4127 Binary files /dev/null and b/classes/best_path.pkl differ diff --git a/classes/genetic.py b/classes/genetic.py new file mode 100644 index 0000000..4a04d95 --- /dev/null +++ b/classes/genetic.py @@ -0,0 +1,67 @@ +import pickle +import random + + +def manhattan_distance(point1, point2): + return abs(point1[0] - point2[0]) + abs(point1[1] - point2[1]) + + +def calculate_fitness(individual, points): + return -sum(manhattan_distance(points[individual[i - 1]], points[individual[i]]) for i in range(len(individual))) + + +def crossover(parent1, parent2): + size = len(parent1) + start, end = sorted(random.sample(range(size), 2)) + child = [None] * size + + # Copy subset from first parent + child[start:end + 1] = parent1[start:end + 1] + + # Copy remaining genes from second parent, wrapping around + wrapped_parent2 = parent2[end + 1:] + parent2[:end + 1] + remaining_genes = [gene for gene in wrapped_parent2 if gene not in child] + + child[end + 1:] = remaining_genes[:size - end - 1] + child[:start] = remaining_genes[size - end - 1:] + + return child + + +def mutate(individual): + idx1, idx2 = random.sample(range(len(individual)), 2) + individual[idx1], individual[idx2] = individual[idx2], individual[idx1] + + +def genetic_algorithm(points, population_size, generations): + population = [random.sample(range(len(points)), len(points)) for _ in range(population_size)] + for _ in range(generations): + population.sort(key=lambda individual: calculate_fitness(individual, points), reverse=True) + next_generation = population[:population_size // 10] + while len(next_generation) < population_size: + parent1, parent2 = random.choices(population[:population_size // 2], k=2) + child = crossover(parent1, parent2) + if random.random() < 0.01: + mutate(child) + next_generation.append(child) + population = next_generation + best_individual = max(population, key=lambda individual: calculate_fitness(individual, points)) + best_path = [points[i] for i in best_individual] + + with open('best_path.pkl', 'wb') as f: + pickle.dump(best_path, f) + + return best_path, -calculate_fitness(best_individual, points) + + +point_list = [] +for i in range(1, 29): + if i % 2 == 1: + point_list.append((i, 6)) + point_list.append((i, 12)) + elif i % 2 == 0: + point_list.append((i, 9)) + if i % 2 == 1 and i % 4 != 1: + point_list.append((i, 10)) + +print(genetic_algorithm(point_list, 100, 1000)) diff --git a/main.py b/main.py index 26f7e11..c4b7b9f 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,8 @@ -from generators import * import time +import classes.Household +from generators import * + W = 30 H = 20 MULT = 50 @@ -14,7 +16,7 @@ targimage = pygame.transform.scale(targimage, (MULT, MULT)) trashcans = trashcanGenerator(MULT) houses = householdGenerator(MULT) garbagetruck = Garbagetruck(MULT).setHouses(houses).setTrashcans(trashcans) - +garbagetruck.setFirstTarget() # print("Kolejność danych do drzewa:") # print("Pora roku - Pora dnia - Typ śmieci - Zapełnienie kosza - Zapełnienie śmieciarki - Zapłacone - Ostatnio zabrane " # "- Pogoda") @@ -25,7 +27,6 @@ while running: if event.type == pygame.QUIT: running = False - garbagetruck.setTarget() garbagetruck.executeMovement() screen.fill((0, 0, 0)) tilemap.render(MULT) @@ -34,26 +35,33 @@ while running: screen.blit(i.getImage(), i.printme()) for h in houses: screen.blit(h.getImage(), h.printme()) - bruh = garbagetruck.target.getPosition() + bruh = garbagetruck.target bruhlist = [i*MULT for i in bruh] screen.blit(targimage, bruhlist) screen.blit(garbagetruck.getImage(), garbagetruck.printme()) pygame.display.update() garbagetruck.scanTile() state = garbagetruck.getState() + garbagetruck.goDumpTrash() + # print(type(state)) while garbagetruck.getAnalising(): garbagetruck.pickTrash() if not garbagetruck.movesequence: moves = garbagetruck.graphsearch() garbagetruck.setMovesequence(moves) if state: - if state.getFinal(): + if isinstance(state, classes.Household.Household) and state.getFinal(): # print([trash.getTtype() for trash in state.getGarbage().getContent()]) garbagetruck.switchAnalising() garbagetruck.getState().switchFinal() - elif not garbagetruck.movesequence: - garbagetruck.randomTarget() - time.sleep(0.5) + elif isinstance(state, classes.Trashcan.Trashcan) and state.getFinal(): + print("Wyrzucam") + garbagetruck.throwGarbage() + print([trash.getTtype() for trash in garbagetruck.getTrash()]) + garbagetruck.getState().switchFinal() + if not garbagetruck.movesequence and not garbagetruck.getAnalising(): + garbagetruck.setTarget() + time.sleep(0.25) pygame.quit()