code refactoring, preparation to decision tree integration

This commit is contained in:
Vadzim Valchkovich 2023-05-26 03:02:16 +02:00
parent c74d1f0925
commit 51bab9921d
10 changed files with 160 additions and 50 deletions

View File

@ -44,5 +44,5 @@
- [ ] **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 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).

View File

@ -7,7 +7,7 @@ from src.obj.Table import Table
from src.UserController import UserController
from src.StateController import StateController
SCREEN_SIZE = (800, 800)
SCREEN_SIZE = [800, 800]
SQUARE_SIZE = 40
waiter = Waiter([0, 0], 0, SQUARE_SIZE, SCREEN_SIZE)
@ -26,8 +26,7 @@ for i in range(150):
if (random.randint(0, 1)):
objects.append(Block(pos, 0, SQUARE_SIZE, SCREEN_SIZE))
else:
objects.append(Table(pos, 0, SQUARE_SIZE,
SCREEN_SIZE, random.randint(0, 3)))
objects.append(Table(pos, 0, SQUARE_SIZE, SCREEN_SIZE))
user = UserController(waiter)
state = StateController(waiter)

View File

@ -1,6 +1,7 @@
import time
import pygame
from .obj.Object import Object
from .obj.Waiter import Waiter
from .UserController import UserController
from .StateController import StateController
@ -10,12 +11,14 @@ class Engine:
def __init__(self, screen_size, square_size, user: UserController, state: StateController):
pygame.display.set_caption('Waiter Agent')
self.user = user
self.state = state
self.screen_size = screen_size
self.action_clock = 0
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.square_size = square_size
self.square_size: int = square_size
self.num_squares = self.screen_size[0] // self.square_size
self.squares = self.__init_squares_field__(
self.num_squares, self.square_size)
@ -23,7 +26,7 @@ class Engine:
self.objects: list[Object] = []
self.goals: list = []
self.runnin = False
self.runnin: bool = False
def __init_squares_field__(self, num_squares, square_size):
squares = []
@ -57,14 +60,29 @@ class Engine:
self.state.graphsearch(self)
self.user.handler(self)
else:
# went path
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.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)
def clock_increment(self, action_time):
self.action_clock += action_time
def redraw(self):
self.screen.fill((255, 255, 255))

View File

@ -18,7 +18,7 @@ class StateController:
def build_path(self, goal_state):
total_cost = goal_state.cost
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)
total_cost += self.path[-1].cost

View File

@ -11,6 +11,9 @@ class UserController:
engine.quit()
elif event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
pos = (pos[0] // engine.square_size,
pos[1] // engine.square_size)
pos = [pos[0] // 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)

View File

@ -4,3 +4,7 @@ from src.obj.Object import Object
class Kitchen(Object):
def __init__(self, position, orientation, square_size, screen_size):
super().__init__("kitchen", position, orientation, square_size, screen_size)
def action(self, waiter):
waiter.combine_orders()
waiter.recharge()

View File

@ -46,3 +46,14 @@ class Object:
def compare_pos(self, pos) -> bool:
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

View File

@ -1,14 +1,62 @@
import random
from src.obj.Object import Object
class Table(Object):
def __init__(self, position, orientation, square_size, screen_size, current_role=0):
super().__init__("table", position, orientation, square_size, screen_size)
self.roles = ["table", "order", "wait", "done"]
self.current_role = current_role
self.change_role(self.roles[self.current_role])
def __init__(self, position, orientation, square_size, screen_size):
super().__init__("order", position, orientation, square_size, screen_size)
self.order_time = 0
self.customers = 0
# roles = ["table", "order", "wait", "done"]
def next_role(self, waiter):
if waiter.agent_role == "waiter":
self.current_role = (self.current_role + 1) % 4
self.change_role(self.roles[self.current_role])
def reset(self):
self.change_role("table")
self.order_time = 0
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)

View File

@ -11,11 +11,11 @@ class TemporaryState(Waiter):
copy.copy(parent.basket))
self.agent_role = action
self.parent = parent
self.change_role(action)
self.apply_transformation()
self.cost = cost
self.cost_so_far = cost_so_far
self.h = h
self.change_role(action)
self.apply_transformation()
def replace(self, repl):
self.cost_so_far = copy.copy(repl.cost_so_far)
@ -76,11 +76,7 @@ class TemporaryState(Waiter):
self.cost = costs[obj.agent_role]
def heuristic(self, goal):
x = abs(self.position[0] - goal[0])
y = abs(self.position[1] - goal[1])
self.h = x + y
self.h = self.distance_to(goal)
return self.h
def current_cost(self):

View File

@ -3,10 +3,13 @@ from src.obj.Object import 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)
self.basket_size = 2
self.battery = battery
self.basket_size = 4
self.memory_size = 4
self.basket = basket
self.memory = memory
self.prev_position = copy.deepcopy(self.position)
self.prev_orientation = copy.copy(self.orientation)
@ -14,18 +17,56 @@ class Waiter(Object):
self.position = copy.deepcopy(state.position)
self.orientation = copy.copy(state.orientation)
self.basket = copy.copy(state.basket)
self.battery -= state.cost
return state
def dampState(self):
self.prev_position = copy.deepcopy(self.position)
self.prev_orientation = copy.copy(self.orientation)
def dish_in_basket(self, table) -> bool:
return table in self.basket
def rollbackState(self):
self.position = copy.deepcopy(self.prev_position)
self.orientation = copy.copy(self.prev_orientation)
def basket_is_full(self) -> bool:
return self.basket_size == 0
def orders_in_basket(self) -> bool:
return self.basket
def combine_orders(self):
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):
self.orientation = (self.orientation + 1) % 4
@ -38,13 +79,3 @@ class Waiter(Object):
self.position[0] += self.orientation - 2 # x (-1 or +1)
else: # y (0 or 2)
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)