genetic -> master #4

Merged
s464943 merged 4 commits from genetic into master 2022-06-09 22:05:44 +02:00
8 changed files with 277 additions and 9 deletions
Showing only changes of commit 53cf8c9937 - Show all commits

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -0,0 +1,7 @@
from enum import Enum
class GeneticMutationType(Enum):
MUTATION = 1
CROSS = 2
REVERSE = 3

View File

@ -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]
):

View File

@ -0,0 +1,9 @@
from data.GameConstants import GameConstants
class ForkliftActions:
def __init__(self, game: GameConstants,
) -> None:
self.game = game

View File

@ -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

47
main.py
View File

@ -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()