engine improvements
This commit is contained in:
parent
4504d0d412
commit
522b29269d
@ -2,6 +2,7 @@ from typing import Tuple, List
|
|||||||
|
|
||||||
from AgentBase import AgentBase
|
from AgentBase import AgentBase
|
||||||
from data.enum.Direction import Direction
|
from data.enum.Direction import Direction
|
||||||
|
from decision.Action import Action
|
||||||
from decision.ActionType import ActionType
|
from decision.ActionType import ActionType
|
||||||
|
|
||||||
|
|
||||||
@ -9,52 +10,52 @@ class ForkliftAgent(AgentBase):
|
|||||||
|
|
||||||
def __init__(self, model):
|
def __init__(self, model):
|
||||||
super().__init__(model)
|
super().__init__(model)
|
||||||
self.movement_queue = []
|
self.action_queue: List[Action] = []
|
||||||
self.current_position = Tuple[int, int]
|
self.current_position = Tuple[int, int]
|
||||||
self.current_rotation = Direction.right
|
self.current_rotation = Direction.right
|
||||||
|
|
||||||
def queue_movement_actions(self, movement_actions: List[ActionType]):
|
def queue_movement_actions(self, movement_actions: List[Action]):
|
||||||
self.movement_queue.extend(movement_actions)
|
self.action_queue.extend(movement_actions)
|
||||||
|
|
||||||
def move(self):
|
def move(self):
|
||||||
if len(self.movement_queue) > 0:
|
if len(self.action_queue) > 0:
|
||||||
action = self.movement_queue.pop(0)
|
action = self.action_queue.pop(0)
|
||||||
|
action_type = action.action_type
|
||||||
|
|
||||||
if action == ActionType.ROTATE_UP:
|
if action_type == ActionType.ROTATE_UP:
|
||||||
print("rotate {} --> {}".format(self.current_rotation, action))
|
print("rotate {} --> {}".format(self.current_rotation, action_type))
|
||||||
self.current_rotation = Direction.top
|
self.current_rotation = Direction.top
|
||||||
|
|
||||||
elif action == ActionType.ROTATE_RIGHT:
|
elif action_type == ActionType.ROTATE_RIGHT:
|
||||||
print("rotate {} --> {}".format(self.current_rotation, action))
|
print("rotate {} --> {}".format(self.current_rotation, action_type))
|
||||||
self.current_rotation = Direction.right
|
self.current_rotation = Direction.right
|
||||||
|
|
||||||
elif action == ActionType.ROTATE_DOWN:
|
elif action_type == ActionType.ROTATE_DOWN:
|
||||||
print("rotate {} --> {}".format(self.current_rotation, action))
|
print("rotate {} --> {}".format(self.current_rotation, action_type))
|
||||||
self.current_rotation = Direction.down
|
self.current_rotation = Direction.down
|
||||||
|
|
||||||
elif action == ActionType.ROTATE_LEFT:
|
elif action_type == ActionType.ROTATE_LEFT:
|
||||||
print("rotate {} --> {}".format(self.current_rotation, action))
|
print("rotate {} --> {}".format(self.current_rotation, action_type))
|
||||||
self.current_rotation = Direction.left
|
self.current_rotation = Direction.left
|
||||||
|
|
||||||
elif action == ActionType.MOVE:
|
elif action_type == ActionType.MOVE:
|
||||||
if self.current_rotation == Direction.top:
|
if self.current_rotation == Direction.top:
|
||||||
print("move {} --> {}".format(self.current_position, action))
|
print("move {} --> {}".format(self.current_position, action_type))
|
||||||
self.current_position = (self.current_position[0], self.current_position[1] + 1)
|
self.current_position = (self.current_position[0], self.current_position[1] + 1)
|
||||||
|
|
||||||
elif self.current_rotation == Direction.down:
|
elif self.current_rotation == Direction.down:
|
||||||
print("move {} --> {}".format(self.current_position, action))
|
print("move {} --> {}".format(self.current_position, action_type))
|
||||||
self.current_position = (self.current_position[0], self.current_position[1] - 1)
|
self.current_position = (self.current_position[0], self.current_position[1] - 1)
|
||||||
|
|
||||||
elif self.current_rotation == Direction.right:
|
elif self.current_rotation == Direction.right:
|
||||||
print("move {} --> {}".format(self.current_position, action))
|
print("move {} --> {}".format(self.current_position, action_type))
|
||||||
self.current_position = (self.current_position[0] + 1, self.current_position[1])
|
self.current_position = (self.current_position[0] + 1, self.current_position[1])
|
||||||
|
|
||||||
elif self.current_rotation == Direction.left:
|
elif self.current_rotation == Direction.left:
|
||||||
print("move {} --> {}".format(self.current_position, action))
|
print("move {} --> {}".format(self.current_position, action_type))
|
||||||
self.current_position = (self.current_position[0] - 1, self.current_position[1])
|
self.current_position = (self.current_position[0] - 1, self.current_position[1])
|
||||||
|
|
||||||
def step(self) -> None:
|
def step(self) -> None:
|
||||||
print("forklift step")
|
|
||||||
self.move()
|
self.move()
|
||||||
|
|
||||||
def creation_log(self):
|
def creation_log(self):
|
||||||
|
207
GameModel.py
207
GameModel.py
@ -1,3 +1,4 @@
|
|||||||
|
from enum import Enum
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from mesa import Model
|
from mesa import Model
|
||||||
@ -10,89 +11,229 @@ from InitialStateFactory import InitialStateFactory
|
|||||||
from PatchAgent import PatchAgent
|
from PatchAgent import PatchAgent
|
||||||
from PatchType import PatchType
|
from PatchType import PatchType
|
||||||
from data.GameConstants import GameConstants
|
from data.GameConstants import GameConstants
|
||||||
|
from data.Item import Item
|
||||||
|
from data.Order import Order
|
||||||
|
from data.enum.Direction import Direction
|
||||||
|
from data.enum.ItemType import ItemType
|
||||||
|
from decision.Action import Action
|
||||||
from decision.ActionType import ActionType
|
from decision.ActionType import ActionType
|
||||||
from pathfinding.PathfinderOnStates import PathFinderOnStates, PathFinderState
|
from pathfinding.PathfinderOnStates import PathFinderOnStates, PathFinderState
|
||||||
from util.PathDefinitions import GridLocation, GridWithWeights
|
from util.PathDefinitions import GridLocation, GridWithWeights
|
||||||
|
|
||||||
|
|
||||||
|
class Phase(Enum):
|
||||||
|
INIT = 1
|
||||||
|
ITEM_RECOGNITION = 2
|
||||||
|
CLIENT_SORTING = 3
|
||||||
|
PLAN_MOVEMENT = 4
|
||||||
|
EXECUTION = 5
|
||||||
|
|
||||||
|
|
||||||
class GameModel(Model):
|
class GameModel(Model):
|
||||||
|
|
||||||
def __init__(self, width, height, graph: GridWithWeights, graph2: GridWithWeights):
|
def __init__(self, width, height, graph: GridWithWeights):
|
||||||
# self.num_agents = 5
|
# self.num_agents = 5
|
||||||
|
self.first = True
|
||||||
|
self.item_recognised = False
|
||||||
self.running = True
|
self.running = True
|
||||||
self.grid = MultiGrid(height, width, True)
|
self.grid = MultiGrid(height, width, True)
|
||||||
self.schedule = RandomActivation(self)
|
self.schedule = RandomActivation(self)
|
||||||
self.agents = [AgentBase]
|
|
||||||
|
|
||||||
|
self.client_delivery: PatchAgent = None
|
||||||
|
self.drop_off: PatchAgent = None
|
||||||
|
|
||||||
|
self.agents = [AgentBase]
|
||||||
self.forklift_agent = ForkliftAgent(self)
|
self.forklift_agent = ForkliftAgent(self)
|
||||||
self.schedule.add(self.forklift_agent)
|
self.schedule.add(self.forklift_agent)
|
||||||
self.agents.append(self.forklift_agent)
|
self.agents.append(self.forklift_agent)
|
||||||
|
self.graph = graph
|
||||||
initial_state_factory = InitialStateFactory()
|
|
||||||
|
|
||||||
self.game_constants = GameConstants(
|
self.game_constants = GameConstants(
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
graph.walls,
|
graph.walls,
|
||||||
graph2.puddles
|
graph.puddles
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add the agent to a random grid cell
|
# INITIALIZATION #
|
||||||
x = 5
|
print("############## INITIALIZATION ##############")
|
||||||
y = 5
|
self.phase = Phase.INIT
|
||||||
self.grid.place_agent(self.forklift_agent, (x, y))
|
self.initialize_grid(graph)
|
||||||
self.forklift_agent.current_position = (x, y)
|
self.orderList: List[Order] = InitialStateFactory.generate_order_list(3)
|
||||||
|
|
||||||
start, goal = (x, y), (1, 3)
|
print("############## RECOGNISE ITEMS ##############")
|
||||||
|
self.phase = Phase.ITEM_RECOGNITION
|
||||||
|
self.provided_items = InitialStateFactory.generate_item_list(3)
|
||||||
|
self.recognised_items: List[Item] = []
|
||||||
|
|
||||||
|
print("Relocate forklift agent to loading area for item recognition")
|
||||||
|
|
||||||
pathFinder = PathFinderOnStates(
|
pathFinder = PathFinderOnStates(
|
||||||
self.game_constants,
|
self.game_constants,
|
||||||
goal,
|
self.drop_off.location,
|
||||||
PathFinderState(self.forklift_agent.current_position, self.forklift_agent.current_rotation, 0,
|
PathFinderState(self.forklift_agent.current_position, self.forklift_agent.current_rotation, 0,
|
||||||
ActionType.NONE, [])
|
Action(ActionType.NONE), [])
|
||||||
)
|
)
|
||||||
|
|
||||||
self.place_patch_agents()
|
|
||||||
self.place_walls_agents(graph.walls)
|
|
||||||
self.place_puddles(graph2.puddles)
|
|
||||||
|
|
||||||
actions = pathFinder.get_action_list()
|
actions = pathFinder.get_action_list()
|
||||||
print("PATHFINDING")
|
print("PATHFINDING")
|
||||||
print(actions)
|
print(actions)
|
||||||
self.forklift_agent.queue_movement_actions(actions)
|
self.forklift_agent.queue_movement_actions(actions)
|
||||||
|
|
||||||
def place_patch_agents(self):
|
def initialize_grid(self, graph: GridWithWeights):
|
||||||
agent = PatchAgent(self, PatchType.pickUp)
|
print("INITIALIZING GRID")
|
||||||
|
# Add the agent to a random grid cell
|
||||||
|
x = 5
|
||||||
|
y = 5
|
||||||
|
self.grid.place_agent(self.forklift_agent, (x, y))
|
||||||
|
self.forklift_agent.current_position = (x, y)
|
||||||
|
|
||||||
|
self.place_logistics()
|
||||||
|
self.place_walls_agents(graph.walls)
|
||||||
|
self.place_puddles(graph.puddles)
|
||||||
|
self.place_packing_stations(graph.packingStations)
|
||||||
|
|
||||||
|
def place_logistics(self):
|
||||||
|
agent = PatchAgent(self, (self.grid.width - 1, int(self.grid.height / 2)), PatchType.pickUp)
|
||||||
self.schedule.add(agent)
|
self.schedule.add(agent)
|
||||||
self.grid.place_agent(agent, (self.grid.width - 1, self.grid.height - 1))
|
self.grid.place_agent(agent, agent.location)
|
||||||
self.agents.append(agent)
|
self.agents.append(agent)
|
||||||
|
self.client_delivery = agent
|
||||||
|
|
||||||
agent = PatchAgent(self, PatchType.dropOff)
|
agent = PatchAgent(self, (0, int(self.grid.height / 2)), PatchType.dropOff)
|
||||||
# self.schedule.add(agent)
|
self.grid.place_agent(agent, agent.location)
|
||||||
self.grid.place_agent(agent, (0, self.grid.height - 1))
|
|
||||||
self.agents.append(agent)
|
self.agents.append(agent)
|
||||||
|
self.drop_off = agent
|
||||||
for i in range(3):
|
|
||||||
a = PatchAgent(self, PatchType.item)
|
|
||||||
self.agents.append(a)
|
|
||||||
self.grid.place_agent(a, (i, 0))
|
|
||||||
|
|
||||||
def place_walls_agents(self, walls: List[GridLocation]):
|
def place_walls_agents(self, walls: List[GridLocation]):
|
||||||
for w in walls:
|
for w in walls:
|
||||||
agent = PatchAgent(self, PatchType.wall)
|
agent = PatchAgent(self, w, PatchType.wall)
|
||||||
self.agents.append(agent)
|
self.agents.append(agent)
|
||||||
self.grid.place_agent(agent, w)
|
self.grid.place_agent(agent, w)
|
||||||
|
|
||||||
def place_puddles(self, puddles: List[GridLocation]):
|
def place_puddles(self, puddles: List[GridLocation]):
|
||||||
for p in puddles:
|
for p in puddles:
|
||||||
agent = PatchAgent(self, PatchType.diffTerrain)
|
agent = PatchAgent(self, p, PatchType.diffTerrain)
|
||||||
self.agents.append(agent)
|
self.agents.append(agent)
|
||||||
self.grid.place_agent(agent, p)
|
self.grid.place_agent(agent, p)
|
||||||
|
|
||||||
|
def place_packing_stations(self, packing_stations: List[tuple[PatchType, GridLocation]]):
|
||||||
|
for p in packing_stations:
|
||||||
|
agent = PatchAgent(self, p[1], p[0])
|
||||||
|
self.agents.append(agent)
|
||||||
|
self.grid.place_agent(agent, p[1])
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
self.schedule.step()
|
self.schedule.step()
|
||||||
|
|
||||||
print("update multiGrid")
|
|
||||||
|
|
||||||
self.grid.remove_agent(self.forklift_agent)
|
self.grid.remove_agent(self.forklift_agent)
|
||||||
self.grid.place_agent(self.forklift_agent, self.forklift_agent.current_position)
|
self.grid.place_agent(self.forklift_agent, self.forklift_agent.current_position)
|
||||||
|
|
||||||
|
if self.phase == Phase.ITEM_RECOGNITION:
|
||||||
|
if not self.item_recognised and self.forklift_agent.current_position == self.drop_off.location:
|
||||||
|
|
||||||
|
if len(self.provided_items) == 0:
|
||||||
|
print("FINISHED ITEM RECOGNITION")
|
||||||
|
self.item_recognised = True
|
||||||
|
self.phase = Phase.CLIENT_SORTING
|
||||||
|
else:
|
||||||
|
print("BEGIN ITEM RECOGNITION, left: {}".format(len(self.provided_items)))
|
||||||
|
item_to_recognise = self.provided_items.pop()
|
||||||
|
recognised = self.recognise_item(item_to_recognise)
|
||||||
|
self.recognised_items.append(recognised)
|
||||||
|
|
||||||
|
if self.phase == Phase.CLIENT_SORTING:
|
||||||
|
# TODO GENERICS SORTING
|
||||||
|
sorted(self.orderList, key=lambda x: len(x.items))
|
||||||
|
print("FINISHED CLIENT ORDER SORTING")
|
||||||
|
self.phase = Phase.PLAN_MOVEMENT
|
||||||
|
|
||||||
|
if self.phase == Phase.PLAN_MOVEMENT:
|
||||||
|
if len(self.orderList) > 0:
|
||||||
|
self.plan_actions()
|
||||||
|
self.phase = Phase.EXECUTION
|
||||||
|
else:
|
||||||
|
print("NO MORE ORDERS")
|
||||||
|
|
||||||
|
if self.phase == Phase.EXECUTION:
|
||||||
|
print("Execution")
|
||||||
|
if (len(self.forklift_agent.action_queue) == 0):
|
||||||
|
self.phase = Phase.PLAN_MOVEMENT
|
||||||
|
|
||||||
|
def plan_actions(self):
|
||||||
|
order = self.orderList.pop(0)
|
||||||
|
print("PLAN MOVEMENT")
|
||||||
|
for i in order.items:
|
||||||
|
if self.first:
|
||||||
|
# get item
|
||||||
|
pathFinder = PathFinderOnStates(
|
||||||
|
self.game_constants,
|
||||||
|
self.drop_off.location,
|
||||||
|
PathFinderState(self.forklift_agent.current_position,
|
||||||
|
self.forklift_agent.current_rotation,
|
||||||
|
0,
|
||||||
|
Action(ActionType.NONE),
|
||||||
|
[])
|
||||||
|
)
|
||||||
|
actions = pathFinder.get_action_list()
|
||||||
|
self.forklift_agent.queue_movement_actions(actions)
|
||||||
|
self.first = False
|
||||||
|
else:
|
||||||
|
# get item
|
||||||
|
pathFinder = PathFinderOnStates(
|
||||||
|
self.game_constants,
|
||||||
|
self.drop_off.location,
|
||||||
|
PathFinderState(self.client_delivery.location,
|
||||||
|
Direction.right,
|
||||||
|
0,
|
||||||
|
Action(ActionType.NONE),
|
||||||
|
[])
|
||||||
|
)
|
||||||
|
actions = pathFinder.get_action_list()
|
||||||
|
self.forklift_agent.queue_movement_actions(actions)
|
||||||
|
self.first = False
|
||||||
|
|
||||||
|
# go through station
|
||||||
|
packing_station: GridLocation = None
|
||||||
|
stations = dict(self.graph.packingStations)
|
||||||
|
if i.real_type == ItemType.PASTA:
|
||||||
|
packing_station = stations[PatchType.packingA]
|
||||||
|
elif i.real_type == ItemType.EGG:
|
||||||
|
packing_station = stations[PatchType.packingB]
|
||||||
|
elif i.real_type == ItemType.PIZZA:
|
||||||
|
packing_station = stations[PatchType.packingC]
|
||||||
|
|
||||||
|
pathFinder = PathFinderOnStates(
|
||||||
|
self.game_constants,
|
||||||
|
packing_station,
|
||||||
|
PathFinderState(self.drop_off.location,
|
||||||
|
Direction.left,
|
||||||
|
0,
|
||||||
|
Action(
|
||||||
|
desired_item=i,
|
||||||
|
action_type=ActionType.PICK_ITEM
|
||||||
|
),
|
||||||
|
[])
|
||||||
|
)
|
||||||
|
actions = pathFinder.get_action_list()
|
||||||
|
self.forklift_agent.queue_movement_actions(actions)
|
||||||
|
|
||||||
|
# go to client delivery area
|
||||||
|
pathFinder = PathFinderOnStates(
|
||||||
|
self.game_constants,
|
||||||
|
self.client_delivery.location,
|
||||||
|
PathFinderState(packing_station,
|
||||||
|
Direction.right,
|
||||||
|
0,
|
||||||
|
Action(ActionType.NONE),
|
||||||
|
[])
|
||||||
|
)
|
||||||
|
actions = pathFinder.get_action_list()
|
||||||
|
self.forklift_agent.queue_movement_actions(actions)
|
||||||
|
self.forklift_agent.queue_movement_actions(
|
||||||
|
[Action(ActionType.DROP_ITEM)]
|
||||||
|
)
|
||||||
|
|
||||||
|
def recognise_item(self, item: Item):
|
||||||
|
# TODO IMAGE PROCESSING
|
||||||
|
item.guessed_type = item.real_type
|
||||||
|
return item
|
||||||
|
@ -1,38 +1,47 @@
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
from data.Item import Item
|
from data.Item import Item
|
||||||
from data.enum.ItemType import ItemType
|
|
||||||
from data.Order import Order
|
from data.Order import Order
|
||||||
|
from data.enum.ItemType import ItemType
|
||||||
|
from util.ClientParamsFactory import ClientParamsFactory
|
||||||
|
|
||||||
|
|
||||||
class InitialStateFactory:
|
class InitialStateFactory:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate_order_list(self, output_order_list_size: int):
|
def generate_item_list(output_list_size: int):
|
||||||
order_list = [Order]
|
item_list : [Item] = []
|
||||||
for i in range(0, output_order_list_size):
|
for i in range(output_list_size):
|
||||||
order_list.append(self.__generate_order())
|
item_list.append(InitialStateFactory.__generate_item())
|
||||||
|
|
||||||
|
return item_list
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def generate_order_list(output_order_list_size: int):
|
||||||
|
order_list: [Order] = []
|
||||||
|
for i in range(output_order_list_size):
|
||||||
|
order_list.append(InitialStateFactory.__generate_order())
|
||||||
|
|
||||||
return order_list
|
return order_list
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __generate_order(self) -> Order:
|
def __generate_order() -> Order:
|
||||||
order_size = random.randint(1, 4)
|
order_size = random.randint(1, 4)
|
||||||
|
|
||||||
items = [Item]
|
items: [Item] = []
|
||||||
for i in range(order_size):
|
for i in range(order_size):
|
||||||
items.append(self.generate_item())
|
items.append(InitialStateFactory.__generate_item())
|
||||||
|
|
||||||
time_base = random.randint(8, 20)
|
time_base = random.randint(8, 20)
|
||||||
final_time = time_base * order_size
|
final_time = time_base * order_size
|
||||||
|
|
||||||
value = sum(i.price for i in items)
|
client_params = ClientParamsFactory.get_client_params()
|
||||||
|
|
||||||
return Order(final_time, items, value)
|
return Order(final_time, items, None, client_params)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate_input_sequence(self, input_sequence_size):
|
def generate_input_sequence(self, input_sequence_size):
|
||||||
sequence = [Item]
|
sequence : [Item] = []
|
||||||
for i in range(0, input_sequence_size):
|
for i in range(0, input_sequence_size):
|
||||||
sequence.append(self.__generate_item())
|
sequence.append(self.__generate_item())
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
from mesa import Agent, Model
|
|
||||||
|
|
||||||
from AgentBase import AgentBase
|
from AgentBase import AgentBase
|
||||||
from PatchType import PatchType
|
from PatchType import PatchType
|
||||||
|
from util.PathDefinitions import GridLocation
|
||||||
|
|
||||||
|
|
||||||
class PatchAgent(AgentBase):
|
class PatchAgent(AgentBase):
|
||||||
|
|
||||||
def __init__(self, model, patch_type: PatchType):
|
def __init__(self, model, location: GridLocation, patch_type: PatchType):
|
||||||
|
self.location = location
|
||||||
self.patch_type = patch_type
|
self.patch_type = patch_type
|
||||||
super().__init__(model)
|
super().__init__(model)
|
||||||
|
|
||||||
|
@ -7,3 +7,6 @@ class PatchType(enum.Enum):
|
|||||||
item = 3
|
item = 3
|
||||||
wall = 4
|
wall = 4
|
||||||
diffTerrain = 5
|
diffTerrain = 5
|
||||||
|
packingA = 6
|
||||||
|
packingB = 7
|
||||||
|
packingC = 8
|
||||||
|
11
data/Item.py
11
data/Item.py
@ -6,11 +6,10 @@ from data.enum.ItemType import ItemType
|
|||||||
class Item:
|
class Item:
|
||||||
id_counter = count(start=0)
|
id_counter = count(start=0)
|
||||||
|
|
||||||
def __init__(self, type: ItemType):
|
def __init__(self, item_type: ItemType):
|
||||||
self.id = next(self.id_counter)
|
self.id = next(self.id_counter)
|
||||||
self.category = type
|
self.real_type = item_type
|
||||||
self.price = self.price_factory(type)
|
self.guessed_type = None
|
||||||
|
|
||||||
@staticmethod
|
def __repr__(self) -> str:
|
||||||
def price_factory(self, type: ItemType):
|
return "|real: {} -- guessed: {}| \n".format(self.real_type, self.guessed_type)
|
||||||
return 1
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from itertools import count
|
from itertools import count
|
||||||
|
from typing import List
|
||||||
|
|
||||||
from data.ClientParams import ClientParams
|
from data.ClientParams import ClientParams
|
||||||
from data.Item import Item
|
from data.Item import Item
|
||||||
@ -8,9 +9,12 @@ from data.enum.Priority import Priority
|
|||||||
class Order:
|
class Order:
|
||||||
id_counter = count(start=0)
|
id_counter = count(start=0)
|
||||||
|
|
||||||
def __init__(self, time: int, items: [Item], value: int, priority: Priority, client_params: ClientParams):
|
def __init__(self, time: int, items: [Item], priority: Priority, client_params: ClientParams):
|
||||||
self.id = next(self.id_counter)
|
self.id = next(self.id_counter)
|
||||||
self.time = time
|
self.time = time
|
||||||
self.items = items
|
self.items: List[Item] = items
|
||||||
self.value = value
|
self.client_params = client_params
|
||||||
self.priority = priority
|
self.priority = priority
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return "items: {} priority: {}".format(self.items, self.priority)
|
||||||
|
@ -5,4 +5,3 @@ class ItemType(Enum):
|
|||||||
PIZZA = 1
|
PIZZA = 1
|
||||||
PASTA = 2
|
PASTA = 2
|
||||||
EGG = 3
|
EGG = 3
|
||||||
UNKNOWN = 4
|
|
9
decision/Action.py
Normal file
9
decision/Action.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from data.Item import Item
|
||||||
|
from decision.ActionType import ActionType
|
||||||
|
|
||||||
|
|
||||||
|
class Action:
|
||||||
|
|
||||||
|
def __init__(self, action_type: ActionType, desired_item: Item = None):
|
||||||
|
self.desired_item = desired_item
|
||||||
|
self.action_type = action_type
|
@ -1,25 +0,0 @@
|
|||||||
from typing import List
|
|
||||||
|
|
||||||
from InitialStateFactory import InitialStateFactory
|
|
||||||
from data.GameConstants import GameConstants
|
|
||||||
from decision.ActionType import ActionType
|
|
||||||
from decision.State import State
|
|
||||||
from util.PathDefinitions import GridLocation
|
|
||||||
|
|
||||||
|
|
||||||
class StateTree:
|
|
||||||
|
|
||||||
def __init__(self, initial_state_factory: InitialStateFactory, game_constants: GameConstants,
|
|
||||||
initial_forklift_position: GridLocation):
|
|
||||||
self.game_constants = game_constants
|
|
||||||
|
|
||||||
parent = State(
|
|
||||||
action_taken=ActionType.NONE,
|
|
||||||
forklift_position=initial_forklift_position,
|
|
||||||
pending_orders=initial_state_factory.generate_order_list(5),
|
|
||||||
filled_orders=[],
|
|
||||||
input_items=initial_state_factory.generate_input_sequence(20)
|
|
||||||
)
|
|
||||||
|
|
||||||
def expansion(self, from_state: State) -> List[State]:
|
|
||||||
return []
|
|
31
main.py
31
main.py
@ -1,25 +1,15 @@
|
|||||||
import csv
|
|
||||||
import random
|
import random
|
||||||
|
|
||||||
import pandas
|
|
||||||
import sklearn.tree
|
|
||||||
|
|
||||||
from mesa.visualization.ModularVisualization import ModularServer
|
from mesa.visualization.ModularVisualization import ModularServer
|
||||||
from mesa.visualization.modules import CanvasGrid
|
from mesa.visualization.modules import CanvasGrid
|
||||||
from sklearn import metrics, preprocessing
|
|
||||||
from sklearn.model_selection import train_test_split
|
|
||||||
from sklearn.tree import DecisionTreeClassifier
|
|
||||||
|
|
||||||
from ClientParamsFactory import ClientParamsFactory
|
|
||||||
from ForkliftAgent import ForkliftAgent
|
from ForkliftAgent import ForkliftAgent
|
||||||
from GameModel import GameModel
|
from GameModel import GameModel
|
||||||
from PatchAgent import PatchAgent
|
from PatchAgent import PatchAgent
|
||||||
from PatchType import PatchType
|
from PatchType import PatchType
|
||||||
from data.enum.CompanySize import CompanySize
|
|
||||||
from data.enum.Direction import Direction
|
from data.enum.Direction import Direction
|
||||||
from data.enum.Priority import Priority
|
|
||||||
from tree.DecisionTree import DecisionTree
|
|
||||||
from util.PathDefinitions import GridWithWeights
|
from util.PathDefinitions import GridWithWeights
|
||||||
|
from visualization.DisplayAttributeElement import DisplayAttributeElement
|
||||||
|
|
||||||
colors = [
|
colors = [
|
||||||
'blue', 'cyan', 'orange', 'yellow', 'magenta', 'purple', '#103d3e', '#9fc86c',
|
'blue', 'cyan', 'orange', 'yellow', 'magenta', 'purple', '#103d3e', '#9fc86c',
|
||||||
@ -63,24 +53,27 @@ def agent_portrayal(agent):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
base = 512
|
base = 512
|
||||||
gridWidth = 10
|
gridWidth = 10
|
||||||
gridHeight = 10
|
gridHeight = 10
|
||||||
scale = base / gridWidth
|
scale = base / gridWidth
|
||||||
|
|
||||||
diagram4 = GridWithWeights(gridWidth, gridHeight)
|
diagram = GridWithWeights(gridWidth, gridHeight)
|
||||||
diagram4.walls = [(6, 5), (6, 6), (6, 7), (6, 8), (2, 3), (2, 4), (3, 4), (4, 4), (6, 4)]
|
diagram.walls = [(6, 5), (6, 6), (6, 7), (6, 8), (2, 3), (2, 4), (3, 4), (4, 4), (6, 4)]
|
||||||
|
diagram.puddles = [(2, 2), (2, 5), (2, 6), (5, 4)]
|
||||||
diagram5 = GridWithWeights(gridWidth, gridHeight)
|
diagram.packingStations = [(PatchType.packingA, (4, 8)), (PatchType.packingB, (4, 6)), (PatchType.packingC, (4, 2))]
|
||||||
diagram5.puddles = [(2, 2), (2, 5), (2, 6), (5, 4)]
|
|
||||||
|
|
||||||
grid = CanvasGrid(agent_portrayal, gridWidth, gridHeight, scale * gridWidth, scale * gridHeight)
|
grid = CanvasGrid(agent_portrayal, gridWidth, gridHeight, scale * gridWidth, scale * gridHeight)
|
||||||
|
|
||||||
|
readyText = DisplayAttributeElement("phase")
|
||||||
|
provided_itesm = DisplayAttributeElement("provided_items")
|
||||||
|
recognised_items = DisplayAttributeElement("recognised_items")
|
||||||
|
ordersText = DisplayAttributeElement("orderList")
|
||||||
|
|
||||||
server = ModularServer(GameModel,
|
server = ModularServer(GameModel,
|
||||||
[grid],
|
[grid, readyText, provided_itesm, recognised_items],
|
||||||
"Automatyczny Wózek Widłowy",
|
"Automatyczny Wózek Widłowy",
|
||||||
{"width": gridHeight, "height": gridWidth, "graph": diagram4, "graph2": diagram5},)
|
{"width": gridHeight, "height": gridWidth, "graph": diagram}, )
|
||||||
|
|
||||||
server.port = 8888
|
server.port = 8888
|
||||||
server.launch()
|
server.launch()
|
||||||
|
@ -1,17 +1,23 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from data.enum.Direction import Direction
|
from data.enum.Direction import Direction
|
||||||
from decision.ActionType import ActionType
|
from decision.Action import Action
|
||||||
from util.PathDefinitions import GridLocation
|
from util.PathDefinitions import GridLocation
|
||||||
|
|
||||||
|
|
||||||
class PathFinderState:
|
class PathFinderState:
|
||||||
|
|
||||||
def __init__(self, agent_position: GridLocation, agent_direction: Direction, cost: float,
|
def __init__(self,
|
||||||
last_action: ActionType, action_taken: List[ActionType]):
|
agent_position: GridLocation,
|
||||||
|
agent_direction: Direction,
|
||||||
|
cost: float,
|
||||||
|
last_action: Action,
|
||||||
|
action_taken: List[Action],
|
||||||
|
desired_item=None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.agent_position = agent_position
|
self.agent_position = agent_position
|
||||||
self.agent_direction = agent_direction
|
self.agent_direction = agent_direction
|
||||||
self.cost = cost
|
self.cost = cost
|
||||||
self.last_action = last_action
|
self.last_action = last_action
|
||||||
self.action_taken = action_taken
|
self.action_taken = action_taken
|
||||||
|
self.desired_item = desired_item
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
|
|
||||||
from data.GameConstants import GameConstants
|
from data.GameConstants import GameConstants
|
||||||
from data.enum.Direction import Direction
|
from data.enum.Direction import Direction
|
||||||
|
from decision.Action import Action
|
||||||
from decision.ActionType import ActionType
|
from decision.ActionType import ActionType
|
||||||
from pathfinding.PathFinderState import PathFinderState
|
from pathfinding.PathFinderState import PathFinderState
|
||||||
from pathfinding.PrioritizedItem import PrioritizedItem
|
from pathfinding.PrioritizedItem import PrioritizedItem
|
||||||
@ -53,34 +53,34 @@ class PathFinderOnStates:
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def create_state(self, curr_state: PathFinderState, action: ActionType) -> PathFinderState:
|
def create_state(self, curr_state: PathFinderState, action: Action) -> PathFinderState:
|
||||||
|
|
||||||
if action == action.MOVE:
|
if action == action.action_type.MOVE:
|
||||||
if curr_state.agent_position in self.game_constants.diffTerrain:
|
if curr_state.agent_position in self.game_constants.diffTerrain:
|
||||||
cost = curr_state.cost + 20
|
cost = curr_state.cost + 20
|
||||||
# tutaj koszt kaluzy
|
# tutaj koszt kaluzy
|
||||||
else:
|
else:
|
||||||
cost = curr_state.cost + 1
|
cost = curr_state.cost + 1
|
||||||
#TODO: jezeli bedziemy rozpatrywac rozne stany to nalezy rozbic na kazdy mozliwy obrot
|
# TODO: jezeli bedziemy rozpatrywac rozne stany to nalezy rozbic na kazdy mozliwy obrot
|
||||||
else:
|
else:
|
||||||
cost = curr_state.cost + 10
|
cost = curr_state.cost + 10
|
||||||
|
|
||||||
last_action = action
|
last_action = action
|
||||||
action_taken: List[ActionType] = []
|
action_taken: List[Action] = []
|
||||||
action_taken.extend(curr_state.action_taken)
|
action_taken.extend(curr_state.action_taken)
|
||||||
action_taken.append(last_action)
|
action_taken.append(last_action)
|
||||||
agent_position = curr_state.agent_position
|
agent_position = curr_state.agent_position
|
||||||
agent_direction = curr_state.agent_direction
|
agent_direction = curr_state.agent_direction
|
||||||
|
|
||||||
if action == ActionType.ROTATE_UP:
|
if action.action_type == ActionType.ROTATE_UP:
|
||||||
agent_direction = Direction.top
|
agent_direction = Direction.top
|
||||||
elif action == ActionType.ROTATE_DOWN:
|
elif action.action_type == ActionType.ROTATE_DOWN:
|
||||||
agent_direction = Direction.down
|
agent_direction = Direction.down
|
||||||
elif action == ActionType.ROTATE_LEFT:
|
elif action.action_type == ActionType.ROTATE_LEFT:
|
||||||
agent_direction = Direction.left
|
agent_direction = Direction.left
|
||||||
elif action == ActionType.ROTATE_RIGHT:
|
elif action.action_type == ActionType.ROTATE_RIGHT:
|
||||||
agent_direction = Direction.right
|
agent_direction = Direction.right
|
||||||
elif action == ActionType.MOVE:
|
elif action.action_type == ActionType.MOVE:
|
||||||
agent_position = self.get_position_after_move(curr_state)
|
agent_position = self.get_position_after_move(curr_state)
|
||||||
|
|
||||||
return PathFinderState(agent_position, agent_direction, cost, last_action, action_taken)
|
return PathFinderState(agent_position, agent_direction, cost, last_action, action_taken)
|
||||||
@ -93,31 +93,31 @@ class PathFinderOnStates:
|
|||||||
# sprawdz w ktorym kierunku obrocony
|
# sprawdz w ktorym kierunku obrocony
|
||||||
possible_next_states: List[PathFinderState] = []
|
possible_next_states: List[PathFinderState] = []
|
||||||
if self.is_move_possible(curr_state):
|
if self.is_move_possible(curr_state):
|
||||||
possible_next_states.append(self.create_state(curr_state, ActionType.MOVE))
|
possible_next_states.append(self.create_state(curr_state, Action(ActionType.MOVE)))
|
||||||
|
|
||||||
if curr_state.agent_direction == Direction.top:
|
if curr_state.agent_direction == Direction.top:
|
||||||
possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_RIGHT))
|
possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_RIGHT)))
|
||||||
possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_LEFT))
|
possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_LEFT)))
|
||||||
possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_DOWN))
|
possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_DOWN)))
|
||||||
|
|
||||||
elif curr_state.agent_direction == Direction.down:
|
elif curr_state.agent_direction == Direction.down:
|
||||||
possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_RIGHT))
|
possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_RIGHT)))
|
||||||
possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_LEFT))
|
possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_LEFT)))
|
||||||
possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_UP))
|
possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_UP)))
|
||||||
|
|
||||||
elif curr_state.agent_direction == Direction.left:
|
elif curr_state.agent_direction == Direction.left:
|
||||||
possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_RIGHT))
|
possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_RIGHT)))
|
||||||
possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_UP))
|
possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_UP)))
|
||||||
possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_DOWN))
|
possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_DOWN)))
|
||||||
|
|
||||||
elif curr_state.agent_direction == Direction.right:
|
elif curr_state.agent_direction == Direction.right:
|
||||||
possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_UP))
|
possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_UP)))
|
||||||
possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_LEFT))
|
possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_LEFT)))
|
||||||
possible_next_states.append(self.create_state(curr_state, ActionType.ROTATE_DOWN))
|
possible_next_states.append(self.create_state(curr_state, Action(ActionType.ROTATE_DOWN)))
|
||||||
|
|
||||||
return possible_next_states
|
return possible_next_states
|
||||||
|
|
||||||
def get_action_list(self) -> List[ActionType]:
|
def get_action_list(self) -> List[Action]:
|
||||||
already_visited = {}
|
already_visited = {}
|
||||||
|
|
||||||
while not self.queue.empty():
|
while not self.queue.empty():
|
||||||
|
@ -6,7 +6,7 @@ from sklearn import metrics, preprocessing
|
|||||||
from sklearn.model_selection import train_test_split
|
from sklearn.model_selection import train_test_split
|
||||||
from sklearn.tree import DecisionTreeClassifier
|
from sklearn.tree import DecisionTreeClassifier
|
||||||
|
|
||||||
from ClientParamsFactory import ClientParamsFactory
|
from util.ClientParamsFactory import ClientParamsFactory
|
||||||
|
|
||||||
|
|
||||||
class DecisionTree:
|
class DecisionTree:
|
||||||
|
@ -3,25 +3,25 @@ import random
|
|||||||
from data.ClientParams import ClientParams
|
from data.ClientParams import ClientParams
|
||||||
from data.enum.CompanySize import CompanySize
|
from data.enum.CompanySize import CompanySize
|
||||||
|
|
||||||
|
|
||||||
class ClientParamsFactory:
|
class ClientParamsFactory:
|
||||||
|
|
||||||
def __init__(self) -> None:
|
@staticmethod
|
||||||
super().__init__()
|
def getTrueMore(per_of_true: int) -> bool:
|
||||||
|
custom = random.randint(0, per_of_true)
|
||||||
def getTrueMore(self, perOfTrue: int) -> bool:
|
|
||||||
custom = random.randint(0, perOfTrue)
|
|
||||||
|
|
||||||
return custom > 0
|
return custom > 0
|
||||||
|
|
||||||
def get_client_params(self) -> ClientParams:
|
@staticmethod
|
||||||
|
def get_client_params() -> ClientParams:
|
||||||
payment_delay = random.randint(0, 14)
|
payment_delay = random.randint(0, 14)
|
||||||
payed = self.getTrueMore(5)
|
payed = ClientParamsFactory.getTrueMore(5)
|
||||||
net_worth = random.randint(0, 100)
|
net_worth = random.randint(0, 100)
|
||||||
is_skarbowka = not self.getTrueMore(5)
|
is_skarbowka = not ClientParamsFactory.getTrueMore(5)
|
||||||
membership = random.getrandbits(1)
|
membership = random.getrandbits(1)
|
||||||
infuelnce_rate = random.randint(0, 100)
|
infuelnce_rate = random.randint(0, 100)
|
||||||
is_hat = random.getrandbits(1)
|
is_hat = random.getrandbits(1)
|
||||||
company_size = random.randint(1,6)
|
company_size = random.randint(1, 6)
|
||||||
|
|
||||||
return ClientParams(
|
return ClientParams(
|
||||||
payment_delay,
|
payment_delay,
|
@ -1,5 +1,7 @@
|
|||||||
from typing import Iterator, Protocol, List, TypeVar, Tuple, Dict
|
from typing import Iterator, Protocol, List, TypeVar, Tuple, Dict
|
||||||
|
|
||||||
|
from PatchType import PatchType
|
||||||
|
|
||||||
GridLocation = Tuple[int, int]
|
GridLocation = Tuple[int, int]
|
||||||
Location = TypeVar('Location')
|
Location = TypeVar('Location')
|
||||||
|
|
||||||
@ -14,6 +16,7 @@ class SquareGrid:
|
|||||||
self.height = height
|
self.height = height
|
||||||
self.walls: List[GridLocation] = []
|
self.walls: List[GridLocation] = []
|
||||||
self.puddles: List[GridLocation] = []
|
self.puddles: List[GridLocation] = []
|
||||||
|
self.packingStations: List[tuple[PatchType, GridLocation]] = []
|
||||||
|
|
||||||
def in_bounds(self, id: GridLocation) -> bool:
|
def in_bounds(self, id: GridLocation) -> bool:
|
||||||
(x, y) = id
|
(x, y) = id
|
||||||
|
18
visualization/DisplayAttributeElement.py
Normal file
18
visualization/DisplayAttributeElement.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from mesa.visualization.modules import TextElement
|
||||||
|
|
||||||
|
|
||||||
|
class DisplayAttributeElement(TextElement):
|
||||||
|
def __init__(self, attr_name):
|
||||||
|
'''
|
||||||
|
Create a new text attribute element.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
attr_name: The name of the attribute to extract from the model.
|
||||||
|
|
||||||
|
Example return: "happy: 10"
|
||||||
|
'''
|
||||||
|
self.attr_name = attr_name
|
||||||
|
|
||||||
|
def render(self, model):
|
||||||
|
val = getattr(model, self.attr_name)
|
||||||
|
return self.attr_name + ": " + str(val)
|
Loading…
Reference in New Issue
Block a user