Merge pull request 'genetic -> master' (#4) from genetic into master

Reviewed-on: #4
This commit is contained in:
Jeremi Lisek 2022-06-09 22:05:44 +02:00
commit 3ae78c6ee5
10 changed files with 446 additions and 15 deletions

View File

@ -18,8 +18,10 @@ from data.Order import Order
from data.enum.ItemType import ItemType
from decision.Action import Action
from decision.ActionType import ActionType
from genetic_order.GeneticOrder import GeneticOrder
from imageClasification.Classificator import image_classification
from pathfinding.PathfinderOnStates import PathFinderOnStates, PathFinderState
from tree.DecisionTree import DecisionTree
from util.PathByEnum import PathByEnum
from util.PathDefinitions import GridLocation, GridWithWeights
@ -179,8 +181,26 @@ class GameModel(Model):
self.recognised_items.append(recognised)
if self.phase == Phase.CLIENT_SORTING:
# TODO GENERICS SORTING
sorted(self.orderList, key=lambda x: len(x.items))
orders: [Order] = self.orderList
tree: DecisionTree = DecisionTree()
# CLIENT RECOGNITION
orders_with_prio = tree.get_data_good(orders)
# print("before:" )
# for i in range(len(orders_with_prio)):
# print("ORDER {}, PRIO: {}".format(orders_with_prio[i].id, orders_with_prio[i].priority))
# GENERICS SORTING
genericOrder: GeneticOrder = GeneticOrder(orders_with_prio)
new_orders = genericOrder.get_orders_sorted(orders)
# print("after:" )
# for i in range(len(new_orders)):
# print("ORDER {}, PRIO: {}".format(new_orders[i].id, new_orders[i].priority))
self.orderList = new_orders
print("FINISHED CLIENT ORDER SORTING")
self.phase = Phase.EXECUTION

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,38 @@ 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, 3)
type = Priority.LOW
if x == 0:
type = Priority.MEDIUM
elif x == 1:
type = Priority.HIGH
x = random.randint(20, 300)
return Order(final_time, items, type, x, client_params)
@staticmethod
def __generate_order() -> Order:
order_size = random.randint(1, 4)
@ -37,7 +70,7 @@ class InitialStateFactory:
client_params = ClientParamsFactory.get_client_params()
return Order(final_time, items, None, client_params)
return Order(final_time, items, Priority.LOW, 0, client_params)
@staticmethod
def generate_input_sequence(self, input_sequence_size):

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

@ -9,12 +9,18 @@ from data.enum.Priority import Priority
class Order:
id_counter = count(start=0)
def __init__(self, time: int, items: [Item], priority: Priority, client_params: ClientParams):
def __init__(self, time: int, items: [Item], priority: Priority, sum: int, client_params: ClientParams):
self.id = next(self.id_counter)
self.time = time
self.items: List[Item] = items
self.client_params = client_params
self.priority = priority
self.sum = sum
# 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,218 @@
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 = 10
reverse_chance = 60
cross_chance = 5
best_fit_special = 50
best_fit_super_special = 20
population_size = 200
number_of_populations = 1000
punish_low = 500
punish_med = 300
punish_sum = 50
def __init__(self, orders: [Order]) -> None:
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 y - x > 2 or 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 correct_sum(self, last_prio: Priority, last_sum: float, o: Order) -> bool:
if o.priority == last_prio:
return last_sum > o.sum / o.time
return True
def sum_wrong(self, member: [int]) -> int:
last_high = 0
last_med = 0
last_prio = Priority.HIGH
last_sum = 0
counter = 0
for i in range(len(member)):
o: Order = self.orders[member[i]]
if o.priority == Priority.HIGH:
last_high = i
elif o.priority == Priority.MEDIUM:
last_med = i
if not self.correct_sum(last_prio, last_sum, o):
counter += int(last_sum - (o.sum / o.time))
last_prio = o.priority
last_sum = o.sum / o.time
for i in range(last_high):
o: Order = self.orders[member[i]]
if o.priority == Priority.MEDIUM:
counter += self.punish_med
elif o.priority == Priority.LOW:
counter += self.punish_low
for i in range(last_med):
o: Order = self.orders[member[i]]
if o.priority == Priority.LOW:
counter += self.punish_low
return counter
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 += 30
#
# if x.sum / x.time < y.sum / y.time:
# result += int(y.sum / y.time)
# return result
return self.sum_wrong(member)
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 = []
for i in range(len(population) - self.best_fit_special - self.best_fit_super_special):
result.append(population[i])
for i in range(self.best_fit_special):
x = random.randint(0, self.best_fit_special)
result.append(population[x])
for i in range(self.best_fit_super_special):
x = random.randint(0, self.best_fit_super_special)
result.append(population[x])
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

70
main.py
View File

@ -1,3 +1,4 @@
import math
import random
from mesa.visualization.ModularVisualization import ModularServer
@ -5,11 +6,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
@ -94,7 +100,69 @@ if __name__ == '__main__':
[grid, readyText, provided_itesm, recognised_items, ordersText,
fulfilled_orders],
"Automatyczny Wózek Widłowy",
dict(width=gridHeight, height=gridWidth, graph=diagram, items=50, orders=3, classificator=model))
dict(width=gridHeight, height=gridWidth, graph=diagram, items=50, orders=20, classificator=model))
# def order_rule(order: Order):
# return order.id
#
#
# punish_low = 500
# punish_med = 300
# def sum_wrong(member: [Order]) -> int:
# last_high = 0
# last_med = 0
#
# sum_high = 0
# sum_med = 0
# sum_low = 0
#
# counter = 0
#
# for i in range(len(member)):
# o: Order = member[i]
# if o.priority == Priority.HIGH :
# sum_high += 1
# last_high = i
# elif o.priority == Priority.MEDIUM:
# sum_med += 1
# last_med = i
# else:
# sum_low += 1
#
# for i in range(last_high):
# o: Order = member[i]
# if o.priority == Priority.MEDIUM:
# counter += punish_med
# elif o.priority == Priority.LOW:
# counter += punish_low
#
# for i in range(last_med):
# o: Order = member[i]
# if o.priority == Priority.LOW:
# counter += punish_low
#
# print("sum: high:", sum_high, "med:", sum_med, "low:", sum_low)
# print("last_high:", last_high, "last_med:", last_med, "sum:", counter)
# return counter
#
# orders = InitialStateFactory.generate_order_list_XD(20)
# test: GeneticOrder = GeneticOrder(orders)
# punish_low = test.punish_low
# punish_med = test.punish_med
#
# print("SIEMA before: ")
# sum_wrong(orders)
# for i in orders:
# print("id:", i.id, "priority:", i.priority, "sum/time:", i.sum/i.time)
# # print("id:", i.id, "priority:", i.priority)
#
# newOrders = test.get_orders_sorted(orders)
#
# print("NAURA after:")
# sum_wrong(newOrders)
# for i in newOrders:
# print("id:", i.id, "priority:", i.priority, "sum/time:", i.sum/i.time)
# # print("id:", i.id, "priority:", i.priority)
server.port = 8888
server.launch()

View File

@ -1,11 +1,17 @@
import csv
import numpy as np
import pandas
import sklearn
from sklearn import metrics, preprocessing
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from InitialStateFactory import InitialStateFactory
from data.ClientParams import ClientParams
from data.Order import Order
from data.enum.CompanySize import CompanySize
from data.enum.Priority import Priority
from util.ClientParamsFactory import ClientParamsFactory
@ -58,6 +64,63 @@ class DecisionTree:
print("\nDecisionTrees's Accuracy: ", metrics.accuracy_score(y, prediction))
def get_data_good(self, orders: [Order]) -> [Order]:
n_array_input = []
for i in range(len(orders)):
o:Order = orders[i]
cp: ClientParams = o.client_params
pom = []
pom.append(cp.payment_delay)
pom.append(cp.payed)
pom.append(cp.net_worth)
pom.append(cp.infuence_rate)
pom.append(cp.is_skarbowka)
pom.append(cp.membership)
pom.append(cp.is_hat)
size: CompanySize = cp.company_size
if(size == CompanySize.NO):
pom.append(0)
if (size == CompanySize.SMALL):
pom.append(1)
if (size == CompanySize.NORMAL):
pom.append(2)
if (size == CompanySize.BIG):
pom.append(3)
if (size == CompanySize.HUGE):
pom.append(4)
if (size == CompanySize.GIGANTISHE):
pom.append(5)
n_array_input.append(pom)
n_array = np.array(n_array_input)
# print(n_array)
# print(n_array[0])
tree = self.get_decision_tree()
priority = tree.predict(n_array)
for i in range(len(orders)):
print(orders[i].priority)
orders[i].priority = priority[i]
if priority[i] == "LOW":
orders[i].priority = Priority.LOW
if priority[i] == "MEDIUM":
orders[i].priority = Priority.MEDIUM
if priority[i] == "HIGH":
orders[i].priority = Priority.HIGH
print(orders[i].priority)
return orders
def get_decision_tree(self) -> DecisionTreeClassifier:
@ -72,15 +135,25 @@ class DecisionTree:
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, train_size=0.8)
# print(len(X_train[0]))
# print(X_train[0])
drugTree = DecisionTreeClassifier(criterion="entropy", max_depth=4)
clf = drugTree.fit(X_train, y_train)
predicted = drugTree.predict(X_test)
# print(type(X_test))
y_test = y_test.to_list()
self.print_logs(X_test, y_test, predicted)
# self.print_logs(X_test, y_test, predicted)
print(sklearn.tree.export_text(clf, feature_names=X_headers))
# print(sklearn.tree.export_text(clf, feature_names=X_headers))
return drugTree
return drugTree
# kurwa = DecisionTree()
# kurwa.get_data_good(InitialStateFactory.generate_order_list(50))