code refactoring, preparation to decision tree integration
This commit is contained in:
parent
c74d1f0925
commit
51bab9921d
@ -44,5 +44,5 @@
|
|||||||
- [ ] **Drzewa decyzyjne: wymagania dot. trzeciego przyrostu**
|
- [ ] **Drzewa decyzyjne: wymagania dot. trzeciego przyrostu**
|
||||||
- [ ] Należy wykorzystać algorytm ID3 (tj. schemat indukcyjnego uczenia drzewa decyzyjnego oraz procedurę wyboru atrybutu o największym przyroście informacji) lub któreś z jego uogólnień.
|
- [ ] Należy wykorzystać algorytm ID3 (tj. schemat indukcyjnego uczenia drzewa decyzyjnego oraz procedurę wyboru atrybutu o największym przyroście informacji) lub któreś z jego uogólnień.
|
||||||
- [ ] Należy przygotować zbiór uczący złożony z co najmniej 200 przykładów.
|
- [ ] Należy przygotować zbiór uczący złożony z co najmniej 200 przykładów.
|
||||||
- [ ] Decyzja stanowiąca cel uczenia powinna zostać opisana przynajmniej ośmioma atrybutami.
|
- [x] Decyzja stanowiąca cel uczenia powinna zostać opisana przynajmniej ośmioma atrybutami.
|
||||||
- [ ] Powinna pojawić się opcja podglądu wyuczonego drzewa (np. w logach lub w pliku z graficzną reprezentacją drzewa).
|
- [ ] Powinna pojawić się opcja podglądu wyuczonego drzewa (np. w logach lub w pliku z graficzną reprezentacją drzewa).
|
||||||
|
5
agent.py
5
agent.py
@ -7,7 +7,7 @@ from src.obj.Table import Table
|
|||||||
from src.UserController import UserController
|
from src.UserController import UserController
|
||||||
from src.StateController import StateController
|
from src.StateController import StateController
|
||||||
|
|
||||||
SCREEN_SIZE = (800, 800)
|
SCREEN_SIZE = [800, 800]
|
||||||
SQUARE_SIZE = 40
|
SQUARE_SIZE = 40
|
||||||
|
|
||||||
waiter = Waiter([0, 0], 0, SQUARE_SIZE, SCREEN_SIZE)
|
waiter = Waiter([0, 0], 0, SQUARE_SIZE, SCREEN_SIZE)
|
||||||
@ -26,8 +26,7 @@ for i in range(150):
|
|||||||
if (random.randint(0, 1)):
|
if (random.randint(0, 1)):
|
||||||
objects.append(Block(pos, 0, SQUARE_SIZE, SCREEN_SIZE))
|
objects.append(Block(pos, 0, SQUARE_SIZE, SCREEN_SIZE))
|
||||||
else:
|
else:
|
||||||
objects.append(Table(pos, 0, SQUARE_SIZE,
|
objects.append(Table(pos, 0, SQUARE_SIZE, SCREEN_SIZE))
|
||||||
SCREEN_SIZE, random.randint(0, 3)))
|
|
||||||
|
|
||||||
user = UserController(waiter)
|
user = UserController(waiter)
|
||||||
state = StateController(waiter)
|
state = StateController(waiter)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import time
|
import time
|
||||||
import pygame
|
import pygame
|
||||||
from .obj.Object import Object
|
from .obj.Object import Object
|
||||||
|
from .obj.Waiter import Waiter
|
||||||
from .UserController import UserController
|
from .UserController import UserController
|
||||||
from .StateController import StateController
|
from .StateController import StateController
|
||||||
|
|
||||||
@ -10,12 +11,14 @@ class Engine:
|
|||||||
def __init__(self, screen_size, square_size, user: UserController, state: StateController):
|
def __init__(self, screen_size, square_size, user: UserController, state: StateController):
|
||||||
pygame.display.set_caption('Waiter Agent')
|
pygame.display.set_caption('Waiter Agent')
|
||||||
|
|
||||||
self.user = user
|
self.action_clock = 0
|
||||||
self.state = state
|
|
||||||
self.screen_size = screen_size
|
self.user: Waiter = user
|
||||||
|
self.state: StateController = state
|
||||||
|
self.screen_size: list[int] = screen_size
|
||||||
self.screen = pygame.display.set_mode(self.screen_size)
|
self.screen = pygame.display.set_mode(self.screen_size)
|
||||||
|
|
||||||
self.square_size = square_size
|
self.square_size: int = square_size
|
||||||
self.num_squares = self.screen_size[0] // self.square_size
|
self.num_squares = self.screen_size[0] // self.square_size
|
||||||
self.squares = self.__init_squares_field__(
|
self.squares = self.__init_squares_field__(
|
||||||
self.num_squares, self.square_size)
|
self.num_squares, self.square_size)
|
||||||
@ -23,7 +26,7 @@ class Engine:
|
|||||||
self.objects: list[Object] = []
|
self.objects: list[Object] = []
|
||||||
self.goals: list = []
|
self.goals: list = []
|
||||||
|
|
||||||
self.runnin = False
|
self.runnin: bool = False
|
||||||
|
|
||||||
def __init_squares_field__(self, num_squares, square_size):
|
def __init_squares_field__(self, num_squares, square_size):
|
||||||
squares = []
|
squares = []
|
||||||
@ -57,14 +60,29 @@ class Engine:
|
|||||||
self.state.graphsearch(self)
|
self.state.graphsearch(self)
|
||||||
self.user.handler(self)
|
self.user.handler(self)
|
||||||
else:
|
else:
|
||||||
|
# went path
|
||||||
|
|
||||||
state = self.user.obj.changeState(self.state.path.pop())
|
state = self.user.obj.changeState(self.state.path.pop())
|
||||||
print("Action:\t{0}\tCost:\t{1}\tCost so far: {2}".format(
|
self.clock_increment(state.cost)
|
||||||
|
|
||||||
|
print("Action:\t{0}\tCost:\t{1}\tCost so far: {2}\tBattery: {3}".format(
|
||||||
state.agent_role,
|
state.agent_role,
|
||||||
state.cost,
|
state.cost,
|
||||||
state.cost_so_far)
|
state.cost_so_far,
|
||||||
|
self.user.obj.battery)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# waiter interaction
|
||||||
|
|
||||||
|
for o in self.objects:
|
||||||
|
if o.compare_pos(self.user.obj.position):
|
||||||
|
o.action(self.user.obj)
|
||||||
|
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
def clock_increment(self, action_time):
|
||||||
|
self.action_clock += action_time
|
||||||
|
|
||||||
def redraw(self):
|
def redraw(self):
|
||||||
self.screen.fill((255, 255, 255))
|
self.screen.fill((255, 255, 255))
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class StateController:
|
|||||||
def build_path(self, goal_state):
|
def build_path(self, goal_state):
|
||||||
total_cost = goal_state.cost
|
total_cost = goal_state.cost
|
||||||
self.path.append(goal_state)
|
self.path.append(goal_state)
|
||||||
while self.path[-1].parent.agent_role != "blank":
|
while self.path[-1].parent.agent_role not in ["blank", "waiter"]:
|
||||||
self.path.append(self.path[-1].parent)
|
self.path.append(self.path[-1].parent)
|
||||||
total_cost += self.path[-1].cost
|
total_cost += self.path[-1].cost
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@ class UserController:
|
|||||||
engine.quit()
|
engine.quit()
|
||||||
elif event.type == pygame.MOUSEBUTTONDOWN:
|
elif event.type == pygame.MOUSEBUTTONDOWN:
|
||||||
pos = pygame.mouse.get_pos()
|
pos = pygame.mouse.get_pos()
|
||||||
pos = (pos[0] // engine.square_size,
|
pos = [pos[0] // engine.square_size,
|
||||||
pos[1] // engine.square_size)
|
pos[1] // engine.square_size]
|
||||||
|
# for o in engine.objects:
|
||||||
|
# if o.compare_pos(pos):
|
||||||
|
# o.set_order(engine.action_clock)
|
||||||
engine.appendGoalPosition(pos)
|
engine.appendGoalPosition(pos)
|
||||||
|
@ -4,3 +4,7 @@ from src.obj.Object import Object
|
|||||||
class Kitchen(Object):
|
class Kitchen(Object):
|
||||||
def __init__(self, position, orientation, square_size, screen_size):
|
def __init__(self, position, orientation, square_size, screen_size):
|
||||||
super().__init__("kitchen", position, orientation, square_size, screen_size)
|
super().__init__("kitchen", position, orientation, square_size, screen_size)
|
||||||
|
|
||||||
|
def action(self, waiter):
|
||||||
|
waiter.combine_orders()
|
||||||
|
waiter.recharge()
|
||||||
|
@ -46,3 +46,14 @@ class Object:
|
|||||||
|
|
||||||
def compare_pos(self, pos) -> bool:
|
def compare_pos(self, pos) -> bool:
|
||||||
return self.position == pos
|
return self.position == pos
|
||||||
|
|
||||||
|
def distance_to(self, pos) -> int:
|
||||||
|
x = abs(self.position[0] - pos[0])
|
||||||
|
y = abs(self.position[1] - pos[1])
|
||||||
|
|
||||||
|
self.h = x + y
|
||||||
|
|
||||||
|
return self.h
|
||||||
|
|
||||||
|
def action(self, obj):
|
||||||
|
pass
|
||||||
|
@ -1,14 +1,62 @@
|
|||||||
|
import random
|
||||||
from src.obj.Object import Object
|
from src.obj.Object import Object
|
||||||
|
|
||||||
|
|
||||||
class Table(Object):
|
class Table(Object):
|
||||||
def __init__(self, position, orientation, square_size, screen_size, current_role=0):
|
def __init__(self, position, orientation, square_size, screen_size):
|
||||||
super().__init__("table", position, orientation, square_size, screen_size)
|
super().__init__("order", position, orientation, square_size, screen_size)
|
||||||
self.roles = ["table", "order", "wait", "done"]
|
self.order_time = 0
|
||||||
self.current_role = current_role
|
self.customers = 0
|
||||||
self.change_role(self.roles[self.current_role])
|
# roles = ["table", "order", "wait", "done"]
|
||||||
|
|
||||||
def next_role(self, waiter):
|
def reset(self):
|
||||||
if waiter.agent_role == "waiter":
|
self.change_role("table")
|
||||||
self.current_role = (self.current_role + 1) % 4
|
self.order_time = 0
|
||||||
self.change_role(self.roles[self.current_role])
|
self.customers = 0
|
||||||
|
|
||||||
|
def set_order(self, current_time):
|
||||||
|
if self.agent_role == "table":
|
||||||
|
self.change_role("order")
|
||||||
|
self.customers = random.randint(1, 6)
|
||||||
|
self.order_time = current_time
|
||||||
|
|
||||||
|
def set_wait(self):
|
||||||
|
if self.agent_role == "order":
|
||||||
|
self.change_role("wait")
|
||||||
|
|
||||||
|
def set_done(self):
|
||||||
|
if self.agent_role == "wait":
|
||||||
|
self.change_role("done")
|
||||||
|
|
||||||
|
def is_order(self):
|
||||||
|
return self.agent_role == "order"
|
||||||
|
|
||||||
|
def is_wait(self):
|
||||||
|
return self.agent_role == "wait"
|
||||||
|
|
||||||
|
def is_done(self):
|
||||||
|
return self.agent_role == "done"
|
||||||
|
|
||||||
|
def waiting_for_dish(self):
|
||||||
|
return self.agent_role in ["wait", "done"]
|
||||||
|
|
||||||
|
def get_customers_count(self) -> int:
|
||||||
|
return self.customers
|
||||||
|
|
||||||
|
def get_mood(self, current_time) -> str:
|
||||||
|
if self.agent_role == "table":
|
||||||
|
return None
|
||||||
|
|
||||||
|
diff = current_time - self.order_time
|
||||||
|
if diff < 200:
|
||||||
|
return "good"
|
||||||
|
elif diff < 400:
|
||||||
|
return "medium"
|
||||||
|
else:
|
||||||
|
return "bad"
|
||||||
|
|
||||||
|
def action(self, waiter):
|
||||||
|
if self.is_order():
|
||||||
|
waiter.collect_order(self)
|
||||||
|
elif self.is_done():
|
||||||
|
waiter.deliver_dish(self)
|
||||||
|
@ -11,11 +11,11 @@ class TemporaryState(Waiter):
|
|||||||
copy.copy(parent.basket))
|
copy.copy(parent.basket))
|
||||||
self.agent_role = action
|
self.agent_role = action
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.change_role(action)
|
|
||||||
self.apply_transformation()
|
|
||||||
self.cost = cost
|
self.cost = cost
|
||||||
self.cost_so_far = cost_so_far
|
self.cost_so_far = cost_so_far
|
||||||
self.h = h
|
self.h = h
|
||||||
|
self.change_role(action)
|
||||||
|
self.apply_transformation()
|
||||||
|
|
||||||
def replace(self, repl):
|
def replace(self, repl):
|
||||||
self.cost_so_far = copy.copy(repl.cost_so_far)
|
self.cost_so_far = copy.copy(repl.cost_so_far)
|
||||||
@ -76,11 +76,7 @@ class TemporaryState(Waiter):
|
|||||||
self.cost = costs[obj.agent_role]
|
self.cost = costs[obj.agent_role]
|
||||||
|
|
||||||
def heuristic(self, goal):
|
def heuristic(self, goal):
|
||||||
x = abs(self.position[0] - goal[0])
|
self.h = self.distance_to(goal)
|
||||||
y = abs(self.position[1] - goal[1])
|
|
||||||
|
|
||||||
self.h = x + y
|
|
||||||
|
|
||||||
return self.h
|
return self.h
|
||||||
|
|
||||||
def current_cost(self):
|
def current_cost(self):
|
||||||
|
@ -3,10 +3,13 @@ from src.obj.Object import Object
|
|||||||
|
|
||||||
|
|
||||||
class Waiter(Object):
|
class Waiter(Object):
|
||||||
def __init__(self, position, orientation, square_size, screen_size, basket=[]):
|
def __init__(self, position, orientation, square_size, screen_size, basket=[], memory=[], battery=300):
|
||||||
super().__init__("waiter", position, orientation, square_size, screen_size)
|
super().__init__("waiter", position, orientation, square_size, screen_size)
|
||||||
self.basket_size = 2
|
self.battery = battery
|
||||||
|
self.basket_size = 4
|
||||||
|
self.memory_size = 4
|
||||||
self.basket = basket
|
self.basket = basket
|
||||||
|
self.memory = memory
|
||||||
self.prev_position = copy.deepcopy(self.position)
|
self.prev_position = copy.deepcopy(self.position)
|
||||||
self.prev_orientation = copy.copy(self.orientation)
|
self.prev_orientation = copy.copy(self.orientation)
|
||||||
|
|
||||||
@ -14,18 +17,56 @@ class Waiter(Object):
|
|||||||
self.position = copy.deepcopy(state.position)
|
self.position = copy.deepcopy(state.position)
|
||||||
self.orientation = copy.copy(state.orientation)
|
self.orientation = copy.copy(state.orientation)
|
||||||
self.basket = copy.copy(state.basket)
|
self.basket = copy.copy(state.basket)
|
||||||
|
self.battery -= state.cost
|
||||||
return state
|
return state
|
||||||
|
|
||||||
def dampState(self):
|
def dish_in_basket(self, table) -> bool:
|
||||||
self.prev_position = copy.deepcopy(self.position)
|
return table in self.basket
|
||||||
self.prev_orientation = copy.copy(self.orientation)
|
|
||||||
|
|
||||||
def rollbackState(self):
|
def basket_is_full(self) -> bool:
|
||||||
self.position = copy.deepcopy(self.prev_position)
|
return self.basket_size == 0
|
||||||
self.orientation = copy.copy(self.prev_orientation)
|
|
||||||
|
|
||||||
def orders_in_basket(self) -> bool:
|
def combine_orders(self):
|
||||||
return self.basket
|
while not self.basket_is_full() and not self.memory_is_empty():
|
||||||
|
dish = self.memory.pop()
|
||||||
|
dish.set_done()
|
||||||
|
self.basket.append(dish)
|
||||||
|
self.basket_size -= 1
|
||||||
|
self.memory_size += 1
|
||||||
|
|
||||||
|
def deliver_dish(self, table):
|
||||||
|
if table in self.basket:
|
||||||
|
table.reset()
|
||||||
|
self.basket.remove(table)
|
||||||
|
self.basket_size += 1
|
||||||
|
|
||||||
|
def order_in_memory(self, table) -> bool:
|
||||||
|
return table in self.memory
|
||||||
|
|
||||||
|
def memory_is_empty(self) -> bool:
|
||||||
|
return not self.memory
|
||||||
|
|
||||||
|
def memory_is_full(self) -> bool:
|
||||||
|
return self.memory_size == 0
|
||||||
|
|
||||||
|
def collect_order(self, table):
|
||||||
|
if self.memory_is_full():
|
||||||
|
return
|
||||||
|
if table.agent_role == "order":
|
||||||
|
table.set_wait()
|
||||||
|
self.memory.append(table)
|
||||||
|
self.memory_size -= 1
|
||||||
|
|
||||||
|
def battary_status(self) -> str:
|
||||||
|
if self.battery >= 200:
|
||||||
|
return "hight"
|
||||||
|
elif self.battery >= 100:
|
||||||
|
return "medium"
|
||||||
|
else:
|
||||||
|
return "low"
|
||||||
|
|
||||||
|
def recharge(self):
|
||||||
|
self.battery = 300
|
||||||
|
|
||||||
def left(self):
|
def left(self):
|
||||||
self.orientation = (self.orientation + 1) % 4
|
self.orientation = (self.orientation + 1) % 4
|
||||||
@ -38,13 +79,3 @@ class Waiter(Object):
|
|||||||
self.position[0] += self.orientation - 2 # x (-1 or +1)
|
self.position[0] += self.orientation - 2 # x (-1 or +1)
|
||||||
else: # y (0 or 2)
|
else: # y (0 or 2)
|
||||||
self.position[1] += self.orientation - 1 # y (-1 or +1)
|
self.position[1] += self.orientation - 1 # y (-1 or +1)
|
||||||
|
|
||||||
def collide_test(self, obj) -> bool:
|
|
||||||
out_of_range = [
|
|
||||||
self.position[0] >= self.square_count,
|
|
||||||
self.position[1] >= self.square_count,
|
|
||||||
self.position[0] < 0,
|
|
||||||
self.position[1] < 0
|
|
||||||
]
|
|
||||||
|
|
||||||
return any(out_of_range)
|
|
||||||
|
Loading…
Reference in New Issue
Block a user