Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

554 changed files with 51 additions and 2344 deletions

3
.gitignore vendored
View File

@ -2,5 +2,4 @@
.idea .idea
bin bin
venv venv
.venv .venv
__pycache__

View File

@ -1,282 +0,0 @@
# Podprojekt indywidualny - raport
**Temat:** Sugerowanie potraw
**Metoda uczenia:** Decision Tree(CART)
**Autor:** Marcin Jerzy Dobrowolski
**Źródła:** https://github.com/random-forests/tutorials/blob/master/decision_tree.ipynb
**Link do repozytorium projektu:** https://git.wmi.amu.edu.pl/s444427/Sztuczna_Inteligencja_2020
## Wstęp
Projekt rozwiązuje problem zasugerowania dania przez kelnera na podstawie danych reprezentujących preferencje gościa. W tym celu wykorzystałem metodę uczenia drzew decyzyjnych CART, którą zaprogramowałem w czystym języku python. Struktura podprojektu:
* [suggestionDecisionTree.py](src/SubprojectMarcinDobrowolski/suggestionDecisionTree.py) - klasa drzew decyzyjnego
* [question.py](src/SubprojectMarcinDobrowolski/question.py) - klasa pytania
* [leaf.py](src/SubprojectMarcinDobrowolski/leaf.py) - klasa liścia
* [decisionNode.py](src/SubprojectMarcinDobrowolski/decisionNode.py) - klasa wierzchołka pytającego
* [utility.py](src/SubprojectMarcinDobrowolski/utility.py) - klasa użytkowa
* [trainingData.csv](src/SubprojectMarcinDobrowolski/Data/trainingData.csv) - zbiór uczący
* [testData.csv](src/SubprojectMarcinDobrowolski/Data/testData.csv) - klasa użytkowa
Struktura danych reprezentujących preferencje gościa:
type, size, money, appetite, name
['meat', 'small', 31, 55, 'schabowy']
* type - typ potrawy: wegańska lub z mięsem
* appetite - apetyt gościa, świadczy o tym jak duża potrawa spełni jego oczekiwania,
np. duże danie będzie inne dla osób o dużym i małym apetycie
* size - rozmiar dania
* money - zawartość portfela gościa, czyli na jak dużo może sobie pozwolić
* name - etykieta potrawy, dopasowana w taki sposób by spełnić powyższe wymagania
## Opis modułów
W pliku *utility* znajdują się podręczne funkcje użytkowe wykorzystywane przez pozostałe moduły programu.
def uniqueValues(rows, column):
return set([row[column] for row in rows])
Znajduje unikalne wartości wyznaczonej kolumny z podanego zbioru danych.
def classCount(rows):
counts = {}
for row in rows:
label = row[-1]
if label not in counts:
counts[label] = 0
counts[label] += 1
return counts
Podlicza ilość elementów każdej etykiety z danego zbioru danych.
def is_numeric(value):
return isinstance(value, int) or isinstance(value, float)
Sprawdza czy podana wartość jest liczbą.
def partition(rows, question):
trueRows, falseRows = [], []
for row in rows:
if question.match(row):
trueRows.append(row)
else:
falseRows.append(row)
return trueRows, falseRows
Dzieli dany zbiór ze względu na zadane pytanie.
def generateTestData(path, quantity):
with open('path', 'w') as csvFile:
csvWriter = csv.writer(csvFile, delimiter=',')
...
Generuje zbiór danych testowych o zadanej wielkości i zapisuje go w pliku o podanej ścieżce. Ze względu na długość kodu nie zamieściłem go w całości. Dane są generowane przy użyciu liczb pseudo losowych w taki sposób by były zgodne z prawami rządzącymi tym zbiorem danych.
def generateTestExample():
example = []
category = random.randrange(0, 1)
size = random.randrange(0, 2)
if category == 0:
example.append('meat')
...
Działa na takiej samej zasadzie jak jej poprzedniczka. Z tym wyjątkiem, że generuje pojedynczy przykład.
Klasa *Question* reprezentuje pytanie, które służy do podziału danych w wierzchołkach decyzyjnych drzewa. Jej atrybuty oznajczają kolejno: etykiete kolumny zbioru danych, indeks wspomnianej kolumny oraz wartość, której dotyczyy pytanie.
class Question:
def __init__(self, columnLabel, column, value):
self.columnLabel = columnLabel
self.column = column
self.value = value
def match(self, example):
val = example[self.column]
if is_numeric(val):
return val <= self.value
else:
return val == self.value
Metoda match decyduje jak na pytanie odpowiada zadany przykład.
Jądro algorytmu znajduje się w klasie *suggestionTree* w pilku *suggestionDecisionTree*. Metoda *readTrainingData* służy do odczytania zbioru uczącego z pliku *trainingData.csv* i zwrócenia przechowywanych w nim danych wraz z ich etykietami.
def readTrainingData(path):
with open(path) as csv_file:
csvReader = csv.reader(csv_file, delimiter=',')
lineCount = 0
trainingData = []
labels = []
for row in csvReader:
example = []
for column in row:
if lineCount == 0:
labels.append(column)
else:
if column.isdigit():
example.append(int(column))
else:
example.append(column)
if lineCount > 0:
trainingData.append(example)
lineCount += 1
print('Processed lines: ', lineCount)
return trainingData, labels
Jest wykorzystana w inicjalizacji zmiennej globalnej *trainigData* oraz *labels*, z których korzystają niektóre z metod tej klasy.
```
trainingData, labels = SuggestionTree.readTrainingData(
'src/SubprojectMarcinDobrowolski/Data/trainingData.csv')
```
Metoda *gini* oblicza tzw. *gini impurity*. Jest to miara, która mówi jak duże jest prawdopodobieństwo by losowo wybrany element ze zbioru został błędnie oznaczony.
def gini(rows):
counts = classCount(rows)
impurity = 1
for lbl in counts:
prob_of_lbl = counts[lbl] / float(len(rows))
impurity -= prob_of_lbl**2
return impurity
def infoGain(left, right, currentUncertainty):
p = float(len(left)) / (len(left) + len(right))
return currentUncertainty - p * SuggestionTree.gini(left) - (1 - p) * SuggestionTree.gini(right)
Natomiast metoda *infoGain* oblicza w jakim stopniu zmniejsza się wskaźnik *gini impurity* ze względu na wybór lewego i prawego podziału zbioru.
Metoda *findBestSplit* znajduje pytanie, które w danej chwili spowoduje jak największy przyrost informacji.
def findBestSplit(rows):
bestGain = 0
bestQuestion = None
currentUncertainty = SuggestionTree.gini(rows)
nFeatures = len(labels) - 1
for column in range(nFeatures):
values = set([row[column] for row in rows])
for value in values:
question = Question(labels[column], column, value)
trueRows, falseRows = partition(rows, question)
if len(trueRows) == 0 or len(falseRows) == 0:
continue
gain = SuggestionTree.infoGain(
trueRows, falseRows, currentUncertainty)
if gain > bestGain:
bestGain, bestQuestion = gain, question
return bestGain, bestQuestion
Klasa *Leaf* jest reprezentacją liścia drzewa czyli najbardziej zewnętrznego wierzchołka. W atrybucie *predictions* przechowuje oszacowanie etykiet/y, które może przyjąć przykład, który doń trafi. Metoda *printLeaf* służy do eleganckiego wyświetlania oszacowania.
class Leaf:
def __init__(self, rows):
self.predictions = classCount(rows)
def printLeaf(self):
total = sum(self.predictions.values()) * 1.0
probs = {}
for label in self.predictions.keys():
probs[label] = str(
int(self.predictions[label] / total * 100)) + '%'
return probs
Klasa *DecisionNode* reprezentuje wierzchołek drzewa, w którym następuje zadanie pytania oraz podział danych. Atrybuty *trueBranch* oraz *falseBranch* reprezentują odpowiednio lewego i prawego potomka.
class DecisionNode:
def __init__(self,
question,
trueBranch,
falseBranch):
self.question = question
self.trueBranch = trueBranch
self.falseBranch = falseBranch
Metoda *buildTree* odpowiada za rekurencyjne skonstruowanie drzewa na bazie przekazanego zbioru danych. Zwraca korzeń drzewa.
def buildTree(rows):
gain, question = SuggestionTree.findBestSplit(rows)
if gain == 0:
return Leaf(rows)
trueRows, falseRows = partition(rows, question)
trueBranch = SuggestionTree.buildTree(trueRows)
falseBranch = SuggestionTree.buildTree(falseRows)
return DecisionNode(question, trueBranch, falseBranch)
Metoda *printTree* wyświetla strukturę drzewa w postaci tekstu w wierszu poleceń.
def printTree(node, spacing=' '):
if isinstance(node, Leaf):
print(spacing + 'Predict', node.predictions)
return
print(spacing + str(node.question))
print(spacing + '--> True:')
SuggestionTree.printTree(node.trueBranch, spacing + ' ')
print(spacing + '--> False:')
SuggestionTree.printTree(node.falseBranch, spacing + ' ')
def classify(row, node):
if isinstance(node, Leaf):
return node
if node.question.match(row):
return SuggestionTree.classify(row, node.trueBranch)
else:
return SuggestionTree.classify(row, node.falseBranch)
Metoda *classify* przyporządkowuje danemu przykładowi odpowiadającą mu etykiete w drzewie.
## Działanie
Drzewo jest budowane na podstawie zbioru uczącego. Algorytm podejmuje decyzje o tym jak podzielić zbiór na podstawie przyrostu informacji wynikającego z potencjalnego podziału. Przerywa działanie gdy przyrost wynosi *0*, co oznacza, że dotarł do liścia drzewa i podział nie jest możliwy. Kończąc swoje działanie zwraca korzeń klasy *DecisionNode*, który zawiera w atrybutach potomków co umożliwia rekurencyjne schodzenie po drzewie.
W projekcie można je wykorzystać poprzez wciśnięcie, któregoś z klawiszy:
* 0 - sprawdzenie poprawności algorytmu na losowo wygenerowanym zbiorze testowym. =
* 1 - sprawdzenie poprawności algorytmu na losowo wygenerowanym przykładzie.
* 2 - wyświetlenie struktury drzewa
Rezultaty zostają wypisane w konsoli.
```
module: pygames
Python: 3.7.7
```
macOS / Linux
```
pygames
python main.py
```
Windows
```
pygames
python main.py
```

View File

@ -1,159 +0,0 @@
# Sztuczna Inteligencja 2020 - Raport z podprojektu
**Autor:** Maksymilian Kierski
**Raportowany okres:** 15.05.2020-26.05.2020
**Wybrana metoda uczenia:** Splotowe sieci neuronowe (CNN)
## Cel podprojektu
Celem podprojektu jest umożliwienie kelnerowi stwierdzenia czy na talerzu znajdującym się na stole jest jeszcze jedzenie, czy już go nie ma. Do tego celu zastosowałem splotowe sieci neuronowe (CNN), oraz biblioteki:
* numpy, cv2 - tworzenie danych wejściowych
* tensorflow keras - tworzenie modelu
* tensorboard - analiza modelów
## Uczenie modelu
### Dane wejściowe
Dane wejściowe składają się z dwóch rodzajów zdjęć talerzy, full - pełnych, oraz empty - pustych.
Na początku, aby nasz model mógł się nauczać potrzebujemy nasze dane wejściowe odpowiednio przetworzyć.
```
for category in CATEGORIES:
path = os.path.join(DATADIR, category)
class_num = CATEGORIES.index(category)
for img in os.listdir(path):
try:
img_array = cv2.imread(os.path.join(path, img),
cv2.IMREAD_GRAYSCALE)
new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))
training_data.append([new_array, class_num])
except Exception as e:
pass
random.shuffle(training_data)
```
Tutaj nasze dane wejściowe są odpowiednio przetwarzane. Na początku zdjęcie jest sczytywane, oraz przetwarzane aby każdy pixel był w skali szarości 0 - 255 (ponieważ kolor w tym zadaniu według mnie, nie odgrywa ważnej roli). Następnie skalowany jest do mniejszych rozmiarów i w końcu jako macierz zadeklarowanych wymiarów trafia do tablicy ze swoją etykietą. Na końcu cała tablica jest przetasowywana, aby umożliwić modelowi lepszą naukę.
Teraz dane zostają podzielone na zestaw cech i zestaw etykiet, oraz zostają zapisane do plików za pomocą **pickle**.
```
for features, label in training_data:
X.append(features)
y.append(label)
pickle_in = open(relative_path + 'SavedData/X.pickle', 'rb')
X = pickle.load(pickle_in)
pickle_in = open(relative_path + 'SavedData/y.pickle', 'rb')
y = pickle.load(pickle_in)
```
### Tworzenie modelu i proces jego nauki
#### Wczytywanie danych potrzebnych do nauki modelu
Na początku sczytywane są odpowiednio przygotowane dane (funkcja load_dataset)
```
pickle_in = open(relative_path + 'SavedData/X.pickle', 'rb')
X = pickle.load(pickle_in)
pickle_in = open(relative_path + 'SavedData/y.pickle', 'rb')
y = pickle.load(pickle_in)
return X, y
```
Wczytywanie danych i normalizacja X, ponieważ używam kolorów w skali szarości 0 - 255, to do normalizacji (skala 0-1) wystarczy przemnożyć każde pole macierzy przez 255. Inicjalizacja tensorboardu, który przyda się nam do analizy stworzonych przez nas modeli.
```
X = load_dataset()[0]
y = load_dataset()[1]
X = np.array(X).reshape(-1, IMG_SIZE, IMG_SIZE, 1)
y = np.array(y)
X = X / 255.0
tenserboard = TensorBoard(log_dir='{}/logs/{}'.format(relative_path, NAME))
```
#### Tworzenie sekwencyjnego modelu splotowych sieci neuronowych
Tutaj inicjalizuje model jako sekwencyjny, czyli w którym każda warstwa wykonywana jest po kolei.
```
model = Sequential()
```
Jako iż tworzę splotową sieć neuronową w której podstawową strukturą jest
```mermaid
graph LR
A((splot)) --> B(suma)
B --> C((splot))
C --> D(suma)
D --> E[w pełni połączona warstwa]
E --> F[wynik]
```
to jako pierwsze tworzę warstwę splotu i sumy.
```
model.add(Conv2D(64, (3, 3),input_shape=X.shape[1:]))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
```
Warstwa splotu opiera się na 64 filtrach, które sprawdzają pola o powierzchni 9 pixeli.
Jak działa splot? Splot to czynność polegająca na pobieraniu oryginalnych danych i tworzeniu z nich mapy cech z pól o zadeklarowanych wymiarach. Jest ich tak dużo jak pozwala na to nam całość naszych danych.
Po czym wykonywana jest funkcja aktywacyjna ReLu.
A na końcu na naszej wykonujemy pooling z atrybutem **max**, czyli z wielkości 2 na 2 z naszej warstwy splotu wybieramy największą wartość.
W tym pod projekcie najbardziej efektywne okazało się zastosowanie dwóch takich warstw.
```
layer size | conv layer | Dense layer |
64 | 1 | 0 | loss: 0.0443 - accuracy: 0.9942 - val_loss: 0.3614 - val_accuracy: 0.7692
64 | 2 | 0 | loss: 0.0931 - accuracy: 0.9625 - val_loss: 0.4772 - val_accuracy: 0.8462
64 | 3 | 0 | loss: 0.2491 - accuracy: 0.9020 - val_loss: 0.3762 - val_accuracy: 0.7949
64 | 1 | 1 | loss: 0.0531 - accuracy: 0.9971 - val_loss: 0.4176 - val_accuracy: 0.8205
64 | 2 | 1 | loss: 0.0644 - accuracy: 0.9798 - val_loss: 0.5606 - val_accuracy: 0.8462
64 | 3 | 1 | loss: 0.1126 - accuracy: 0.9625 - val_loss: 0.5916 - val_accuracy: 0.8205
```
![accuracy](src/SubprojectMaksymilianKierski/Data/LogsIMG/accuracy.png)
![loss](src/SubprojectMaksymilianKierski/Data/LogsIMG/loss.png)
W drugim przypadku nie musimy już zmieniać naszych danych ponieważ pochodzą one z poprzedniej warstwy.
```
model.add(Conv2D(64, (3, 3),input_shape=X.shape[1:]))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
```
Na koniec spłaszczam naszą trójwymiarową tablice, na macierz stosując funkcje Flatten(), oraz używam warstwę Dense z tylko jednym neuronem, który będzie naszym wynikiem. Funkcja aktywacji jest to oczywiście funkcja sigmoid ponieważ chcemy otrzymać wynik (0-1).
```
model.add(Flatten())
model.add(Dense(1))
model.add(Activation('sigmoid'))
```
Następnie zachodzi kompilacja modelu. Używam funkcję straty **binary_crosentropy** , ponieważ mierzymy się z problemem klasyfikacji binarnej. Problem klasyfikacji binarnej jest wtedy, gdy do rozpatrzenia mamy tylko dwa przypadki, w tym zadaniu talerz z jedzeniem(0) oraz bez jedzenia(1). Optymalizator, który użyłem jest to **adam**, a za pomocą **metrics** aktywuje monitorowanie dokładności.
Kilka słów o optymalizatorze **adam** - _Adam_, jest obecnie zalecany przy większości zadań optymalizacyjnych związanych z uczeniem, ponieważ łączy on zalety Adadelty i RMSprop, a zatem lepiej radzi sobie z większością problemów.
Na sam koniec wywołuję funkcję uczenia, oraz zapisuję model do wykorzystania go w projekcie głównym.
```
model.fit(X, y, batch_size=32, epochs=10, validation_split=0.1, callbacks=[tenserboard])
model.save(relative_path + 'SavedModels/{}.model'.format(NAME))
```
## Integracja z projektem
Podprojekt wywołujemy naciskając **m** na klawiaturze, kelner wtedy wybiera losowo stolik i do niego idzie zaimplementowanym wcześniej algorytmem A*. Po dotarciu do wybranego miejsca, możemy wywołać funkcje sprawdzającą talerz **use_model_to_predict('img')**
```
def prepare(filepath):
img_array = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)
new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))
plt.imshow(img_array, cmap=plt.cm.binary)
plt.show()
return new_array.reshape(-1, IMG_SIZE, IMG_SIZE, 1)
model = tf.keras.models.load_model(relative_path + 'SavedModels/plate-64x2-cnn.model')
prediction = model.predict([prepare(relative_path + 'TestData/' + name + '.jpg')])
return int(prediction[0][0])
```
Funkcja ta konwertuję zdjęcie zadeklarowane do wylosowanego stolika oraz odpowiednio je konwertuję. Następnie ładuję zadeklarowany przez nas model, który zwraca nam odpowiednią liczbę, która w int() daje 0 lub 1. Odpowiednio 0 to talerz pełny a 1 to pusty. Dzięki czemu funkcją **text_speech()** możemy wyświetlić odpowiednią informacje na ekranie.

View File

@ -1,56 +0,0 @@
# Kolejkowanie zadań
**Metoda uczenia:** Drzewa decyzyjne
**Autor:** Dominik Zawadzki
Funkcja kolejkowania zadań jak i drzewo decyzyjne znajdują się w pliku:
```sh
decisionTree.py
```
## Funkcje drzewa decyzyjnego:
```sh
BuildDf(self)
```
Buduje Data Frame złożony z trzech atrybutów:
1. actionName - nazwa zadania
2. distance - dystans pomiędzy kelnerem a stolikiem
3. priority - priorytet danej akcji
```sh
FindPriorityEntropy(self,df)
```
Oblicza entropie dla priorytetu za pomocą wzoru:
* ent = pi * log2pi
gdzie i oznacza wartośc priorytetu i = {0, 1, 2, 3, 4}
```sh
FindAttributesEntropy(self, df, attribute)
```
Zwraca entropie danego w parametrze atrybutu, gdzie jako prawdopodobieństwo liczona jest ilość wystąpień tego atrybutu w kolejnych priorytetach.
```sh
FindWinner(self, df):
```
Zwraca atrubut o najwyższym info gain wyliczanym na podstawie wzoru:
* ent(pr) - ent(atr)
gdzie ent(pr) - entropia po priorytecie
a ent(atr) - entropia atrybutu po uwzględnieniu priorytetu
```sh
BuildTree(self, df, tree=None)
```
Rekurencyjna funkcja budująca drzewo decyzyjne. Na początek wyznaczamy atrybut o najwyższym info gain, a następnie budowane jest z niego poddrzewo, jeśli dane poddrzewo jest "puste", dodajemy je do drzewa i kończymy, bo drzewo zostało zbudowane, jesli nie to funkcja wywołuje samą siebie biorąc za parametr poddrzewo.
## Funkcje kolejkowania zadań:
```sh
TasksList(self, name, coordinate):
```
Funkcja oblicza dystans dzielący kelnera od stolika i razem z nazwą zadania dodawane jest do listy zadań.
```sh
Queue(self, tasksList):
```
W tej funkcji wykorzystywane jest drzewo decyzyjne.
Dla każdego zadanie z listy zadań pętla idzie po odpowiednich wierzchołkach i odnajduje priorytet, który z poprzednimi parametrami dodawany jest do listy stanowiącej kolejkę zadań.
Na koniec funkcji kolejka jest sortowana po priorytecie.

255
main.py
View File

@ -1,94 +1,22 @@
import secrets
import sys import sys
from random import randrange from src.graphics import *
from src.decisionTree import * from src.waiter import *
from src.plate import *
from src.SubprojectMaksymilianKierski.PlateRecognition import use_model_to_predict, text_speech
# Marcin Dobrowolski
from src.SubprojectMarcinDobrowolski.suggestionDecisionTree import *
from src.SubprojectMarcinDobrowolski.utility import generateTestData, generateTestExample
from src.guest import *
if __name__ == "__main__": if __name__ == "__main__":
# SETUP # SETUP
pygame.init() pygame.init()
clock = pygame.time.Clock() clock = pygame.time.Clock()
fps = 40
graphics = Graphics() graphics = Graphics()
waiter = Waiter(graphics) waiter = Waiter(graphics)
tree = DecisionTree()
# Init functions # init functions
graphics.drawBackground(waiter.matrix) graphics.drawBackground(waiter.matrix)
graphics.update(waiter) graphics.update(waiter.X, waiter.Y)
# AStar
goal = None
path = ''
# Dominik
queue = []
fromBar = 0
barNode = (3, 12)
node = ()
goalList = [0, 0]
# Marcin Dobrowolski
suggestionTreeRoot = SuggestionTree.buildTree(trainingData)
newGuests = []
actions = []
# Maksymilian
go = 0
randomPlate = None
plate = 0
changePlateVar = 0
waitPos = [[1, 2], [1, 5], [1, 8], [5, 4], [5, 8],
[8, 2], [8, 5], [8, 8], [12, 3], [12, 7]]
tabPos = [[1, 2], [1, 5], [1, 8], [5, 4], [5, 8],
[8, 2], [8, 5], [8, 8], [12, 3], [12, 7]]
pltPos = [[2, 3], [2, 6], [2, 9], [4, 4], [4, 8],
[9, 3], [9, 6], [9, 9], [11, 4], [11, 8]]
plateArr = []
def changePlate():
if plateArr and len(plateArr) > 0:
if randrange(30) == 17:
plate = random.choice(plateArr)
if not plate.empty:
randomPlate = randrange(4) + 11
plate.changePlate('plate-empty.png', 'test-{}'.format(randomPlate))
def addGuest():
if randrange(10) == 5 and path == '':
newGuests.append(Guest(graphics))
guest = newGuests[len(newGuests) - 1]
goal = [0, 0]
goal[0] = guest.cord[0]
goal[1] = guest.cord[1]
tree.TasksList('order', goal, [waiter.X, waiter.Y])
tree.print()
print(actions)
return tree.ReturnQueueList()
while True: while True:
changePlate()
# queue = addGuest()
for event in pygame.event.get(): for event in pygame.event.get():
# rabbit.check(waiter.matrix, waiter.X, waiter.Y)
if event.type == pygame.QUIT: if event.type == pygame.QUIT:
pygame.quit() pygame.quit()
sys.exit() sys.exit()
@ -100,173 +28,8 @@ if __name__ == "__main__":
sys.exit() sys.exit()
break break
if event.key == pygame.K_s: graphics.clear(waiter.X, waiter.Y)
waitPosition = [waiter.X, waiter.Y] waiter.update(event, graphics)
tree.TasksList('check', [2, 3], waitPosition) graphics.update(waiter.X, waiter.Y)
tree.TasksList('eat', [9, 6], waitPosition)
tree.TasksList('order', [4, 8], waitPosition)
tree.TasksList('goToBar', [11, 4], waitPosition)
tree.TasksList('check', [2, 9], waitPosition)
tree.TasksList('eat', [1, 1], waitPosition)
queue = tree.ReturnQueueList()
tree.print()
# Marcin Dobrowolski
if event.key == pygame.K_0:
newGuests.append(Guest(graphics))
# Marcin Dobrowolski
if event.key == pygame.K_1:
guest = newGuests[0]
goal = [0, 0]
if guest.cord[0] == 2 or guest.cord[1] == 9:
goal[0] = guest.cord[0] - 1
goal[1] = guest.cord[1]
else:
goal[0] = guest.cord[0] + 1
goal[1] = guest.cord[1]
actions.append(('takeOrder', goal))
print(actions)
# AStar
if event.key == pygame.K_r:
temp = False
while not temp:
x = secrets.randbelow(graphics.width)
y = secrets.randbelow(graphics.height)
print(x, y)
if waiter.matrix.matrix[x][y].walk_through == 1:
temp = True
goal = (x, y)
path = waiter.findPath(goal)
path = waiter.translatePath(path)
if event.key == pygame.K_a:
if path == '':
newGuests.append(Guest(graphics))
guest = newGuests[len(newGuests) - 1]
goalList[0] = guest.cord[0]
goalList[1] = guest.cord[1]
tree.TasksList('order', goalList, [waiter.X, waiter.Y])
tree.TasksList('goToBar', goalList, [waiter.X, waiter.Y])
queue = tree.ReturnQueueList()
if plateArr and event.key == pygame.K_m:
randomPlate = random.choice(plateArr)
if (not [waiter.X, waiter.Y] == randomPlate.table) or go == 0:
print(waiter.X, waiter.Y)
print(randomPlate.table)
print(go)
print([waiter.X, waiter.Y] in randomPlate.table)
if [waiter.X, waiter.Y] in waitPos:
model = 'waiter_' + waiter.direction
for x in range(-1, 2):
waiterX = waiter.X + (x * 0.1)
graphics.clear(waiterX, waiter.Y - 1)
print(randomPlate)
changePlateVar = 0
# if this plate is exists
goal = (randomPlate.table[0], randomPlate.table[1])
path = waiter.findPath(goal)
path = waiter.translatePath(path)
print('sec-1')
go = 1
plate = 0
else:
if randomPlate.checked:
predict = 'CHECKED'
else:
predict = use_model_to_predict(randomPlate.pictureAI)
if predict == 1:
predict = 'EMPTY'
randomPlate.clearTable()
plateArr.remove(randomPlate)
tree.TasksList('goToBar', barNode, [waiter.X, waiter.Y])
queue = tree.ReturnQueueList()
changePlateVar = 1
else:
predict = 'FOOD'
print('sec-3')
text_speech('arialnarrow.ttf', 25, predict, (255, 255, 255), (0, 128, 0),
(waiter.X * 50 + 25), (waiter.Y * 50 - 25), False, False, screen=graphics.screen)
pygame.display.flip()
go = 0
plate = 0
if plate == 1 and (goalList == [waiter.X - 1, waiter.Y] or goalList == [waiter.X + 1, waiter.Y]):
randTable = goalList
randIndex = pltPos.index(goalList)
tableCord = tabPos[randIndex]
plateCord = pltPos[randIndex]
print('rand{}'.format(randIndex))
pictureAI = 'test-{}'.format(randIndex)
plateArr.append(Plate(graphics, plateCord, tableCord, 'plate-full.png', pictureAI))
tabPos.pop(randIndex)
pltPos.pop(randIndex)
print(plateArr, pltPos)
goal = (plateArr[len(plateArr) - 1].table[0], plateArr[len(plateArr) - 1].table[1])
randGo = len(plateArr) - 1
path = waiter.findPath(goal)
path = waiter.translatePath(path)
print('sec-2')
go = 1
plate = 0
# Dominik
if queue and path == '' and fromBar == 0:
print(queue)
task = queue.pop(0)
print('tasks.{}'.format(task))
tree.RemoveTask()
node = (task[2][0], task[2][1])
if task[0] == "goToBar":
path = waiter.findPath(barNode)
fromBar = 1
else:
changePlateVar = 0
path = waiter.findPath(node)
path = waiter.translatePath(path)
if path == '' and fromBar == 1 and changePlateVar == 0:
path = waiter.findPath(node)
path = waiter.translatePath(path)
fromBar = 0
plate = 1
if path == '' and fromBar == 1:
path = waiter.findPath(node)
path = waiter.translatePath(path)
fromBar = 0
print(plate)
# AStar
if path == '' and actions:
print('Goal: {}'.format(actions[0][1]))
path = waiter.findPath(actions[0][1])
print('Path: {}'.format(path))
path = waiter.translatePath(path)
print('Translated path: {}'.format(path))
if path != '':
nextStep = path[0]
path = path[1:]
waiter.travel(nextStep, graphics)
if path == '':
print('')
# action = actions.pop(0)
# if action[0] == 'takeOrder':
# guest = newGuests.pop(0)
# waiter.takeOrder(suggestionTreeRoot, guest)
# graphics.clearGuest(guest)
# tables.append(guest.cord)
pygame.display.flip() pygame.display.flip()
clock.tick(graphics.fps) clock.tick(fps)

101
path
View File

@ -1,101 +0,0 @@
type,size,money,appetite
meat,regular,29,34
meat,little,38,47
meat,regular,33,34
meat,regular,54,29
meat,regular,47,44
meat,regular,27,15
meat,regular,32,13
meat,little,53,39
meat,little,40,44
meat,regular,25,39
meat,regular,50,52
meat,regular,29,20
meat,little,58,31
meat,regular,36,45
meat,regular,59,20
meat,regular,54,48
meat,regular,25,32
meat,regular,36,23
meat,regular,57,29
meat,little,13,54
meat,little,43,52
meat,little,58,24
meat,little,30,35
meat,little,24,33
meat,regular,24,30
meat,regular,41,48
meat,regular,35,37
meat,little,36,11
meat,regular,22,24
meat,regular,58,14
meat,little,34,29
meat,little,30,38
meat,regular,54,45
meat,regular,31,43
meat,little,58,46
meat,little,48,38
meat,regular,44,44
meat,regular,51,49
meat,little,53,34
meat,regular,51,48
meat,regular,46,35
meat,little,32,22
meat,little,14,37
meat,little,14,37
meat,little,46,13
meat,regular,40,16
meat,regular,40,49
meat,little,47,40
meat,regular,23,33
meat,regular,27,29
meat,regular,49,32
meat,regular,36,15
meat,regular,59,25
meat,little,17,43
meat,regular,39,49
meat,little,35,33
meat,little,10,32
meat,little,11,49
meat,regular,53,15
meat,regular,29,13
meat,little,12,14
meat,little,27,31
meat,regular,31,21
meat,regular,58,13
meat,little,46,19
meat,little,11,27
meat,regular,44,28
meat,regular,40,14
meat,little,57,24
meat,regular,38,52
meat,little,37,31
meat,regular,34,15
meat,little,41,25
meat,regular,30,22
meat,little,58,15
meat,regular,22,12
meat,little,46,44
meat,regular,47,11
meat,little,52,30
meat,little,49,24
meat,little,28,30
meat,regular,27,19
meat,regular,51,43
meat,little,59,10
meat,regular,38,44
meat,regular,30,37
meat,little,44,24
meat,regular,34,45
meat,regular,50,49
meat,regular,36,50
meat,little,13,22
meat,little,28,25
meat,regular,29,14
meat,regular,56,17
meat,regular,57,45
meat,little,28,22
meat,regular,41,53
meat,little,10,19
meat,little,32,53
meat,little,29,22

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

BIN
resources/images/waiter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -1,6 +0,0 @@
0 | price: 0 x: 0 y: 0
1 | price: 100 x: 0 y: 0
0 | price: 0 x: 1 y: 1
1 | price: 100 x: 1 y: 1
0 | price: 0 x: 2 y: 1
1 | price: 100 x: 2 y: 1

View File

@ -1,13 +1,13 @@
______________ ______________
______________ ______________
__PW_____PW___ __PW_____PW___
__SWP____SWP__ _USWP___USWP__
__OWS____OWS__ __OWS____OWSI_
__PWO____PWO__ __PWO____PWO__
__SW_____SW___ _USW____USW___
__OWP____OWP__ __OWP____OWP__
__PWS____PWS__ __PWS____PWSI_
__SWO____SWO__ _USWO___USWO__
__OW_____OW___ __OW_____OW___
______________ ______________
______________ ______________

View File

@ -1,77 +0,0 @@
# Raport 2
Algorytm A* znajduje się w pliku:
```sh
waiter.py
```
jako funkcja
```sh
findPath(self, goal)
```
Rozpoczyna się stworzeniem pustych list i określeniem wierzchołka startowego i końcowego.
Dla startowego wierzchołka określany jest rodzic: *None*
## Pętla główna algorytmu
Główna pętla będzie trwać do momentu gdy *openList* będzie pusta.
Na początek *openList* jest sortowana, następnie usuwany jest z niej pierwszy wierzchołek i dodawany jest do *closedList*.
Następnym krokiem jest dodanie do tabeli *children* wierzchołki sąsiednie - sprawdzając czy takie istnieją tj. czy ich pozycja nie wychodzi poza zakres.
### Wyszukiwanie następnika
Wyszukiwanie następnika polega na znalezieniu następnego wierzchołka do jakiego powinien pójść agent. Zawarte jest ono w pętli:
```sh
for child in children:
```
Na początku sprawdzamy czy danego "dziecka" nie ma w *closedList* tzn. wykluczamy możliwość cofnięcia się agenta po wierzchołkach, które już przeszliśmy.
Potem aktualizowane są parametry wierzchołka:
- ustalamy rodzica jako *currentNode*
- modyfikujemy *startCost* dodając jedynkę do *startCost* obecnego wierzchołka
- ustalamy heurystykę jako suma długości przyprostokątnych
- obliczamy *totalCost* dodając do siebie *startCost* i *heuristic*
Na koniec sprawdzamy jeszcze czy danego dziecka nie ma już w *openList*, a jeśli nie, to dodajemy go do *openList*.
### Zwracanie ścieżki
Zwracanie ścieżki odbywa się gdy *currentNode* jest taki sam jak końcowy wierzchołek.
Tworzymy wtedy ścieżkę cofając się od końcowego wierzchołka do wierzchołka, którego rodzic jest równy: *None*
# Translacja ścieżki
Znajduje się w pliku
```sh
waiter.py
```
jako funkcja
```sh
translatePath(self, path):
```
Przyjmuje jako argument ściężkę zwracaną przez algorytm A*.
Funckja ta sprawdza każdy wierzchołek ścieżki i porównując z obecną pozycją kelnera i kierunkiem w jaki jest odwrócony "tłumaczy" go na odpowiedni ciąg znaków, gdzie:
- F - oznacza ruch do przodu
- R - obrót w prawo
- L - obrót w lewo
Następnie zwraca ciąg *output*
[//]: # (These are reference links used in the body of this note and get stripped out when the markdown processor does its job. There is no need to format nicely because it shouldn't be seen. Thanks SO - http://stackoverflow.com/questions/4823468/store-comments-in-markdown-syntax)
[dill]: <https://github.com/joemccann/dillinger>
[git-repo-url]: <https://github.com/joemccann/dillinger.git>
[john gruber]: <http://daringfireball.net>
[df1]: <http://daringfireball.net/projects/markdown/>
[markdown-it]: <https://github.com/markdown-it/markdown-it>
[Ace Editor]: <http://ace.ajax.org>
[node.js]: <http://nodejs.org>
[Twitter Bootstrap]: <http://twitter.github.com/bootstrap/>
[jQuery]: <http://jquery.com>
[@tjholowaychuk]: <http://twitter.com/tjholowaychuk>
[express]: <http://expressjs.com>
[AngularJS]: <http://angularjs.org>
[Gulp]: <http://gulpjs.com>
[PlDb]: <https://github.com/joemccann/dillinger/tree/master/plugins/dropbox/README.md>
[PlGh]: <https://github.com/joemccann/dillinger/tree/master/plugins/github/README.md>
[PlGd]: <https://github.com/joemccann/dillinger/tree/master/plugins/googledrive/README.md>
[PlOd]: <https://github.com/joemccann/dillinger/tree/master/plugins/onedrive/README.md>
[PlMe]: <https://github.com/joemccann/dillinger/tree/master/plugins/medium/README.md>
[PlGa]: <https://github.com/RahulHP/dillinger/blob/master/plugins/googleanalytics/README.md>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 353 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

Some files were not shown because too many files have changed in this diff Show More