diff --git a/InitialStateFactory.py b/InitialStateFactory.py index a1b61f2..f147bc9 100644 --- a/InitialStateFactory.py +++ b/InitialStateFactory.py @@ -3,6 +3,7 @@ import random from data.Item import Item from data.Order import Order from data.enum.ItemType import ItemType +from data.enum.Priority import Priority from util.ClientParamsFactory import ClientParamsFactory @@ -24,6 +25,36 @@ class InitialStateFactory: return order_list + @staticmethod + def generate_order_list_XD(output_order_list_size: int): + order_list: [Order] = [] + for i in range(output_order_list_size): + order_list.append(InitialStateFactory.__generate_order_XD()) + + return order_list + + @staticmethod + def __generate_order_XD() -> Order: + order_size = random.randint(1, 4) + + items: [Item] = [] + for i in range(order_size): + items.append(InitialStateFactory.__generate_item()) + + time_base = random.randint(8, 20) + final_time = time_base * order_size + + client_params = ClientParamsFactory.get_client_params() + + x = random.randint(0, 2) + type = Priority.LOW + if x == 0: + type = Priority.MEDIUM + elif x == 2: + type = Priority.HIGH + + return Order(final_time, items, type, client_params) + @staticmethod def __generate_order() -> Order: order_size = random.randint(1, 4) diff --git a/data/GameConstants.py b/data/GameConstants.py index 81397d2..42bb980 100644 --- a/data/GameConstants.py +++ b/data/GameConstants.py @@ -1,5 +1,7 @@ from typing import Dict +from data.Item import Item +from data.Order import Order from data.enum.ItemType import ItemType from util.PathDefinitions import GridLocation @@ -9,16 +11,10 @@ class GameConstants: self, grid_width: int, grid_height: int, - # delivery_pos: GridLocation, - # order_pos: GridLocation, - # special_positions: Dict[ItemType, GridLocation], walls: [GridLocation], diffTerrain: [GridLocation] ): self.grid_width = grid_width self.grid_height = grid_height - # self.delivery_pos = delivery_pos - # self.order_pos = order_pos - # self.special_positions = special_positions self.walls = walls self.diffTerrain = diffTerrain diff --git a/data/Order.py b/data/Order.py index 7fd9c88..0e05d3a 100644 --- a/data/Order.py +++ b/data/Order.py @@ -15,6 +15,12 @@ class Order: self.items: List[Item] = items self.client_params = client_params self.priority = priority + self.sum = 0 + + # def sum_items(self, items: [Item]): + # result = 0 + # for i in range(len(items)): + # result += items[i] def __repr__(self) -> str: return "items: {} priority: {}".format(self.items, self.priority) diff --git a/data/enum/GeneticMutationType.py b/data/enum/GeneticMutationType.py new file mode 100644 index 0000000..a34ac2e --- /dev/null +++ b/data/enum/GeneticMutationType.py @@ -0,0 +1,7 @@ +from enum import Enum + + +class GeneticMutationType(Enum): + MUTATION = 1 + CROSS = 2 + REVERSE = 3 diff --git a/decision/State.py b/decision/State.py index 3cd6be8..4f6f65c 100644 --- a/decision/State.py +++ b/decision/State.py @@ -1,6 +1,7 @@ from data.enum.Direction import Direction from data.Item import Item from data.Order import Order +from data.enum.Priority import Priority from decision.ActionType import ActionType from util.PathDefinitions import GridLocation @@ -10,7 +11,7 @@ class State: action_taken: ActionType, forklift_position: GridLocation, forklift_rotation: Direction, - pending_orders: [Order], + pending_orders: [Priority, [Order]], filled_orders: [Order], input_items: [Item] ): diff --git a/decision/test/ForkliftActions.py b/decision/test/ForkliftActions.py new file mode 100644 index 0000000..5c4c883 --- /dev/null +++ b/decision/test/ForkliftActions.py @@ -0,0 +1,9 @@ +from data.GameConstants import GameConstants + + +class ForkliftActions: + + def __init__(self, game: GameConstants, + ) -> None: + self.game = game + diff --git a/genetic_order/GeneticOrder.py b/genetic_order/GeneticOrder.py new file mode 100644 index 0000000..fe1c311 --- /dev/null +++ b/genetic_order/GeneticOrder.py @@ -0,0 +1,175 @@ +import itertools +import random + +from data.Order import Order +from data.enum.GeneticMutationType import GeneticMutationType +from data.enum.Priority import Priority + + +class GeneticOrder: + mutation_chance = 50 + reverse_chance = 20 + cross_chance = 10 + best_fit_special = 40 + best_fit_special_2 = 20 + population_size = 500 + + def __init__(self, orders: [Order]) -> None: + self.number_of_populations = 10000 + self.orders = orders + + def get_mutation_type(self) -> GeneticMutationType: + x = random.randint(0, self.mutation_chance + self.cross_chance + self.reverse_chance) + + if (x < self.mutation_chance): + return GeneticMutationType.MUTATION + + if (x > self.mutation_chance + self.cross_chance): + return GeneticMutationType.REVERSE + + return GeneticMutationType.CROSS + + def mutation(self, population: [int]) -> [int]: + x = random.randint(0, len(population)-1) + y = random.randint(0, len(population)-1) + while x == y: + y = random.randint(0, len(population)-1) + + result = population + + pom = population[x] + result[x] = population[y] + result[y] = pom + + if(result[x] == result[y]): + print("PIZDA I CHUJ") + + return result + + def cross(self, population: [int]) -> [int]: + x = random.randint(1, len(population)-1) + + result = [] + + for i in range(len(population)): + result.append(population[(i + x) % len(population)]) + + return result + + def reverse(self, population: [int]) -> [int]: + x = random.randint(0, len(population)) + y = random.randint(0, len(population)-1) + while x >= y: + x = random.randint(0, len(population)) + y = random.randint(0, len(population)-1) + + result = [] + # print("X: ", x, " y: ", y) + + for i in range(len(population)): + if x <= i <= y: + new_i = i - x + # print("len:", len(population), " new_i: ", new_i) + result.append(population[y - new_i]) + else: + result.append(population[i]) + + return result + + def generate_first_population(self, k: int) -> [[int]]: + result = [] + + s = range(len(self.orders)) + p = itertools.permutations(s) + while len(result) < k: + n = p.__next__() + if n not in result: + result.append(n) + + return [list(x) for x in result] + + # result = itertools.permutations(range(len(self.orders))) + # + # return [list(x) for x in result] + + def evaluate(self, member: [int]) -> int: + result = 0 + for i in range(len(self.orders) - 1): + x: Order = self.orders[member[i]] + y: Order = self.orders[member[i + 1]] + + if ((x.priority == Priority.MEDIUM or x.priority == Priority.LOW) and y.priority == Priority.HIGH) or (x.priority == Priority.LOW and y.priority == Priority.MEDIUM): + result += 5000 + elif x.sum / x.time < y.sum / y.time: + result += y.sum * 5 + y.time + + return result + + def mutate_population(self, order_population: [[int]]) -> [[int]]: + result = [] + + for i in range(len(order_population)): + member: [int] = order_population[i] + operation: GeneticMutationType = self.get_mutation_type() + + if operation == GeneticMutationType.MUTATION: + member = self.mutation(member) + elif operation == GeneticMutationType.REVERSE: + member = self.reverse(member) + else: + member = self.cross(member) + + result.append(member) + + return result + + def get_next_population(self, population: [[int]]) -> [[int]]: + result = [] + + result = population + + # for i in range(len(population) - self.best_fit_special): + # result.append(population[i]) + # + # k = len(population) - self.best_fit_special + # while k < len(population) - self.best_fit_special_2: + # n = random.randint(0, self.best_fit_special) + # result.append(population[n]) + # + # left_size = len(population) - k + # while left_size < len(population): + # n = random.randint(0, self.best_fit_special_2) + # result.append(population[n]) + + return result + + def get_orders_sorted(self, orders: [Order]) -> [Order]: + self.orders = orders + + population: [[int]] = self.generate_first_population(self.population_size) + print(population) + + population.sort(key=self.evaluate) + best_fit: [int] = population[0] + + for i in range(self.number_of_populations): + # print("population: ", i) + population = self.mutate_population(population) + population.sort(key=self.evaluate) + + if self.evaluate(best_fit) > self.evaluate(population[0]): + best_fit = population[0] + + # population = self.get_next_population(population).sort(key=self.evaluate) + + if self.evaluate(best_fit) < self.evaluate(population[0]): + population[0] = best_fit + + + best: [int] = population[0] + result: [Order] = [] + + for i in range(len(best)): + result.append(self.orders[best[i]]) + + return result \ No newline at end of file diff --git a/main.py b/main.py index c72ea9e..0e8914e 100644 --- a/main.py +++ b/main.py @@ -5,11 +5,16 @@ from mesa.visualization.modules import CanvasGrid from ForkliftAgent import ForkliftAgent from GameModel import GameModel +from InitialStateFactory import InitialStateFactory from PatchAgent import PatchAgent from PatchType import PatchType from PictureVisualizationAgent import PictureVisualizationAgent +from data.Order import Order from data.enum.Direction import Direction from tensorflow import keras + +from data.enum.Priority import Priority +from genetic_order.GeneticOrder import GeneticOrder from util.PathDefinitions import GridWithWeights from visualization.DisplayAttributeElement import DisplayAttributeElement from visualization.DisplayItemListAttribute import DisplayItemListAttributeElement @@ -96,5 +101,43 @@ if __name__ == '__main__': "Automatyczny Wózek Widłowy", dict(width=gridHeight, height=gridWidth, graph=diagram, items=50, orders=3, classificator=model)) - server.port = 8888 - server.launch() + def pizda(order: Order): + return order.id + + def evaluate(member: [Order]) -> int: + result = 0 + for i in range(len(member) - 1): + x: Order = member[i] + y: Order = member[i + 1] + + if ((x.priority == Priority.MEDIUM or x.priority == Priority.LOW) and y.priority == Priority.HIGH) or (x.priority == Priority.LOW and y.priority == Priority.MEDIUM): + result += 5000 + + return result + + orders = InitialStateFactory.generate_order_list_XD(20) + test: GeneticOrder = GeneticOrder(orders) + print("SIEMA: ", evaluate(orders)) + # for i in orders: + # print("id: {}, priority: {}", i.id, i.priority) + + newOrders = test.get_orders_sorted(orders) + + print("NAURA:", evaluate(newOrders)) + # for i in newOrders: + # print("id: {}, priority: {}", i.id, i.priority) + + # orders.sort(key=pizda) + # newOrders.sort(key=pizda) + # + # print("SIEMA:") + # for i in orders: + # print("id: {}, priority: {}", i.id, i.priority) + # + # print("NAURA:") + # for i in newOrders: + # print("id: {}, priority: {}", i.id, i.priority) + + + # server.port = 8888 + # server.launch()