From e9b3a685e6528f9dfac46d1d22ac0c5de75a631f Mon Sep 17 00:00:00 2001 From: Vadzim Valchkovich Date: Thu, 1 Jun 2023 12:44:29 +0200 Subject: [PATCH] upgrade decision tree model --- .gitignore | 8 +- README.MD | 14 +- TreeConcept.py | 38 ---- dataset/Dataset.csv | 201 ------------------ dataset/converted_dataset.csv | 200 ----------------- dataset/datasetGenerator.py | 57 ----- requirements.txt | 3 + src/Engine.py | 50 +++++ src/UserController.py | 7 +- src/decisionTree/TreeConcept.py | 70 ++++++ .../decisionTree}/datasetConverter.py | 49 ++--- src/decisionTree/datasetGenerator.py | 111 ++++++++++ src/decisionTree/dataset_generator.py | 33 --- src/obj/Table.py | 13 +- src/obj/Waiter.py | 87 +------- 15 files changed, 281 insertions(+), 660 deletions(-) delete mode 100644 TreeConcept.py delete mode 100644 dataset/Dataset.csv delete mode 100644 dataset/converted_dataset.csv delete mode 100644 dataset/datasetGenerator.py create mode 100644 src/decisionTree/TreeConcept.py rename {dataset => src/decisionTree}/datasetConverter.py (60%) create mode 100644 src/decisionTree/datasetGenerator.py delete mode 100644 src/decisionTree/dataset_generator.py diff --git a/.gitignore b/.gitignore index 56bad65..aa80176 100644 --- a/.gitignore +++ b/.gitignore @@ -57,8 +57,6 @@ docs/_build/ Pipfile Pipfile.lock -decision_tree -decision_tree.pdf -Source.gv.pdf -Source.gv -decision_tree.txt + +# output +/out \ No newline at end of file diff --git a/README.MD b/README.MD index 2a6bec2..b75c27a 100644 --- a/README.MD +++ b/README.MD @@ -41,8 +41,14 @@ --- -- [ ] **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. +- [x] **Drzewa decyzyjne: wymagania dot. trzeciego przyrostu** + - [x] 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ń. + - [x] Należy przygotować zbiór uczący złożony z co najmniej 200 przykładów. - [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). + - [x] Powinna pojawić się opcja podglądu wyuczonego drzewa (np. w logach lub w pliku z graficzną reprezentacją drzewa). + +--- + +- [ ] **Sieci neuronowe: wymagania dot. czwartego przyrostu** + - [ ] Należy przygotować zbiór uczący zawierający co najmniej 1000 przykładów dla każdej klasy. + - [ ] Agent powinien wykorzystywać wyuczoną sieć w procesie podejmowania decyzji. diff --git a/TreeConcept.py b/TreeConcept.py deleted file mode 100644 index 6f6e857..0000000 --- a/TreeConcept.py +++ /dev/null @@ -1,38 +0,0 @@ -from sklearn import tree -import pandas as pd #for manipulating the csv data -import numpy as np -import graphviz -import os -os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz/bin/' - -#importing the dataset from the disk -train_data_m=np.genfromtxt("dataset/converted_dataset.csv", delimiter=",",skip_header=1); - -# Separate the attributes and labels -X_train = [data[:-1] for data in train_data_m] -y_train = [data[-1] for data in train_data_m] - -# Create the decision tree classifier using the ID3 algorithm -clf = tree.DecisionTreeClassifier(criterion='entropy') -#clf = tree.DecisionTreeClassifier(criterion='gini') - -# Train the decision tree on the training data -clf.fit(X_train, y_train) - -# Visualize the trained decision tree -tree_text = tree.export_text(clf,feature_names=['Battery Charge', 'Fullness', 'Ready orders', 'Waiting tables','Availability', 'Cleanliness', 'Error']) -with open('decision_tree.txt', 'w') as f: - f.write(tree_text) # Save the visualization as a text file -dot_data = tree.export_graphviz(clf, out_file=None, feature_names=['Battery Charge', 'Fullness', 'Ready orders', 'Waiting tables','Availability', 'Cleanliness', 'Error'], class_names=['NO', 'YES'], filled=True,rounded=True) -graph = graphviz.Source(dot_data) -graph.render("decision_tree") # Save the visualization as a PDF file - -# Test the decision tree with a new example -#Battery Charge,Fullness,Ready orders,Waiting tables,Availability,Cleanliness,Error -new_example = [2, 0, 1, 1, 1 ,2, 0] -predicted_label = clf.predict([new_example]) -if predicted_label[0]>0: - result="YES" -else: - result="NO" -print("Predicted Label:", result) \ No newline at end of file diff --git a/dataset/Dataset.csv b/dataset/Dataset.csv deleted file mode 100644 index ab034bb..0000000 --- a/dataset/Dataset.csv +++ /dev/null @@ -1,201 +0,0 @@ -Battery Charge,Fullness,Ready orders,Waiting tables,Availability,Cleanliness,Error,To go -high,full,none,none,available,low,yes,no -low,full,none,none,unavailable,medium,yes,no -high,full,none,none,unavailable,medium,no,no -medium,empty,none,none,unavailable,low,no,no -high,full,none,none,available,medium,no,no -low,full,none,available,unavailable,medium,yes,no -medium,empty,none,available,unavailable,high,yes,no -medium,full,none,available,available,low,yes,no -medium,full,available,none,unavailable,low,yes,no -high,empty,none,none,unavailable,medium,yes,no -medium,empty,none,available,unavailable,medium,yes,no -low,empty,available,none,available,high,no,no -high,full,available,none,available,low,yes,no -medium,full,none,available,available,low,no,no -medium,full,none,available,available,medium,no,yes -empty,full,none,none,unavailable,high,yes,no -low,full,none,none,unavailable,medium,no,no -low,full,available,none,unavailable,low,no,no -medium,empty,none,available,unavailable,medium,no,no -low,empty,available,available,unavailable,medium,no,no -medium,empty,available,available,unavailable,medium,yes,no -low,empty,none,none,unavailable,high,no,no -medium,full,available,available,unavailable,medium,yes,no -high,empty,available,none,available,medium,no,yes -empty,empty,available,available,unavailable,low,yes,no -high,empty,none,none,unavailable,high,yes,no -medium,empty,available,available,available,medium,no,yes -medium,full,available,available,available,low,no,no -empty,full,none,available,available,high,no,no -empty,empty,none,none,unavailable,low,no,no -medium,full,none,none,unavailable,medium,no,no -medium,empty,available,available,unavailable,high,yes,no -high,full,available,none,available,medium,yes,no -medium,empty,none,available,unavailable,low,yes,no -low,empty,none,none,available,low,no,no -high,full,available,available,available,low,yes,no -high,full,available,available,unavailable,high,yes,no -low,full,available,available,unavailable,high,yes,no -low,full,none,none,unavailable,low,yes,no -medium,full,none,none,unavailable,medium,yes,no -high,full,none,available,available,medium,yes,no -low,empty,none,none,unavailable,low,no,no -high,empty,available,none,unavailable,low,yes,no -medium,full,none,available,available,high,no,yes -low,empty,available,available,available,high,yes,no -low,full,available,none,unavailable,high,yes,no -medium,full,available,none,unavailable,low,no,no -medium,full,available,available,unavailable,high,no,no -medium,full,none,available,unavailable,low,yes,no -medium,empty,available,none,unavailable,low,yes,no -medium,empty,none,none,available,high,no,no -empty,full,none,none,available,low,no,no -low,full,available,available,available,medium,yes,no -low,full,available,none,unavailable,high,no,no -high,full,available,none,available,medium,no,no -low,full,none,available,available,medium,no,no -empty,empty,none,available,available,high,no,no -low,full,none,available,unavailable,low,no,no -high,full,none,none,unavailable,high,no,no -medium,full,none,none,available,high,yes,no -low,empty,none,available,available,medium,no,no -empty,empty,none,available,unavailable,low,no,no -empty,full,available,none,available,low,yes,no -empty,empty,available,available,available,medium,no,no -empty,empty,available,none,unavailable,medium,no,no -empty,empty,none,none,unavailable,high,no,no -medium,empty,available,none,unavailable,high,no,no -empty,empty,available,none,available,medium,yes,no -empty,empty,none,none,unavailable,high,yes,no -high,full,available,available,unavailable,low,no,no -high,empty,available,available,available,high,yes,no -high,empty,available,none,available,low,no,no -low,empty,none,available,unavailable,medium,no,no -medium,full,none,available,unavailable,low,no,no -medium,empty,none,available,available,high,yes,no -medium,empty,available,available,available,high,no,yes -high,empty,none,available,unavailable,low,yes,no -low,full,available,available,available,high,no,no -medium,empty,none,available,available,high,no,no -medium,empty,available,none,available,high,no,yes -empty,full,available,available,unavailable,high,no,no -low,empty,none,available,available,low,no,no -high,full,none,available,available,low,yes,no -high,empty,none,none,available,medium,yes,no -empty,empty,available,none,unavailable,low,no,no -high,full,none,available,unavailable,low,yes,no -empty,full,none,available,unavailable,high,no,no -empty,full,available,none,available,low,no,no -medium,full,none,none,available,high,no,no -medium,full,available,available,unavailable,low,yes,no -empty,full,available,available,unavailable,low,yes,no -low,empty,none,none,unavailable,medium,no,no -low,full,none,none,unavailable,low,no,no -low,full,available,available,unavailable,low,yes,no -low,empty,none,available,available,low,yes,no -empty,full,available,none,unavailable,high,no,no -low,full,available,none,available,high,no,no -high,full,available,available,available,medium,yes,no -empty,full,none,available,available,medium,yes,no -low,full,none,none,available,medium,no,no -empty,full,available,available,available,low,no,no -medium,full,available,none,unavailable,medium,yes,no -empty,empty,none,none,available,medium,no,no -high,full,none,available,unavailable,low,no,no -low,empty,available,available,available,high,no,no -low,empty,none,available,available,high,yes,no -high,full,none,available,available,medium,no,yes -empty,full,available,none,available,medium,yes,no -high,full,none,none,available,low,no,no -low,empty,available,available,unavailable,high,no,no -low,full,available,none,available,medium,yes,no -high,empty,none,none,unavailable,low,no,no -low,full,none,none,unavailable,high,yes,no -high,empty,none,available,available,low,yes,no -empty,full,available,available,unavailable,low,no,no -low,empty,available,available,unavailable,low,no,no -low,full,available,none,unavailable,low,yes,no -empty,empty,available,available,unavailable,high,no,no -medium,full,available,none,available,medium,yes,no -high,full,available,none,available,high,no,no -low,full,none,available,available,medium,yes,no -low,empty,none,available,unavailable,medium,yes,no -high,full,available,available,unavailable,medium,yes,no -high,full,none,none,unavailable,medium,yes,no -low,full,available,available,available,low,yes,no -low,full,available,available,unavailable,high,no,no -empty,full,none,none,available,medium,no,no -empty,empty,available,none,available,low,yes,no -high,full,available,none,unavailable,high,no,no -high,full,none,available,unavailable,high,no,no -low,empty,available,available,unavailable,medium,yes,no -high,empty,available,available,available,low,yes,no -empty,full,none,none,unavailable,low,no,no -high,full,none,available,unavailable,medium,yes,no -high,empty,available,none,unavailable,medium,no,no -empty,empty,available,none,available,high,yes,no -high,empty,available,none,unavailable,medium,yes,no -empty,empty,none,none,unavailable,medium,no,no -high,empty,none,available,available,high,no,no -medium,empty,none,none,unavailable,low,yes,no -medium,full,available,none,unavailable,high,no,no -high,full,none,none,unavailable,low,no,no -high,empty,none,none,unavailable,medium,no,no -medium,full,available,none,available,low,no,no -high,empty,none,none,available,high,yes,no -empty,full,available,available,available,high,no,no -medium,full,available,available,unavailable,low,no,no -empty,full,available,none,available,medium,no,no -empty,full,available,available,unavailable,medium,yes,no -empty,empty,available,none,available,high,no,no -low,empty,none,none,available,high,yes,no -empty,full,none,available,unavailable,medium,yes,no -medium,full,none,available,unavailable,medium,yes,no -medium,full,available,none,available,low,yes,no -medium,full,available,none,unavailable,high,yes,no -medium,full,available,available,available,high,no,yes -medium,full,none,none,available,low,no,no -high,full,none,available,available,high,no,yes -low,empty,available,available,unavailable,low,yes,no -low,full,none,available,unavailable,high,yes,no -medium,full,available,available,available,high,yes,no -high,full,available,available,available,low,no,no -medium,full,none,none,unavailable,high,yes,no -medium,full,none,available,unavailable,high,no,no -high,empty,none,available,unavailable,high,yes,no -empty,empty,none,available,available,medium,no,no -empty,empty,available,none,unavailable,high,no,no -high,empty,available,available,unavailable,high,yes,no -medium,empty,available,available,unavailable,low,yes,no -medium,full,none,none,unavailable,low,no,no -high,empty,none,none,available,low,no,no -high,full,available,none,unavailable,medium,no,no -high,full,available,none,unavailable,low,yes,no -empty,empty,available,available,available,low,yes,no -high,empty,none,none,unavailable,low,yes,no -medium,empty,none,none,available,low,no,no -low,full,none,available,unavailable,medium,no,no -low,full,none,available,available,high,yes,no -high,full,none,available,unavailable,high,yes,no -medium,full,none,available,available,medium,yes,no -empty,empty,none,available,unavailable,high,yes,no -medium,empty,available,none,unavailable,medium,yes,no -empty,empty,none,available,unavailable,low,yes,no -high,empty,none,available,unavailable,medium,no,no -medium,empty,available,none,available,low,yes,no -medium,full,available,available,available,medium,no,yes -high,full,available,none,unavailable,medium,yes,no -high,full,available,available,unavailable,medium,no,no -low,full,available,none,available,medium,no,no -medium,empty,available,none,unavailable,high,yes,no -medium,empty,available,none,available,medium,yes,no -high,empty,none,none,available,high,no,no -empty,full,available,none,unavailable,high,yes,no -low,empty,available,none,unavailable,low,yes,no -empty,full,available,available,available,low,yes,no -medium,empty,available,available,unavailable,medium,no,no -medium,empty,none,none,unavailable,high,no,no -medium,full,available,available,unavailable,medium,no,no -empty,full,available,available,available,medium,no,no -low,empty,available,none,available,low,no,no diff --git a/dataset/converted_dataset.csv b/dataset/converted_dataset.csv deleted file mode 100644 index ff324f2..0000000 --- a/dataset/converted_dataset.csv +++ /dev/null @@ -1,200 +0,0 @@ -3,1,0,0,1,0,1,0 -1,1,0,0,0,1,1,0 -3,1,0,0,0,1,0,0 -2,0,0,0,0,0,0,0 -3,1,0,0,1,1,0,0 -1,1,0,1,0,1,1,0 -2,0,0,1,0,2,1,0 -2,1,0,1,1,0,1,0 -2,1,1,0,0,0,1,0 -3,0,0,0,0,1,1,0 -2,0,0,1,0,1,1,0 -1,0,1,0,1,2,0,0 -3,1,1,0,1,0,1,0 -2,1,0,1,1,0,0,0 -2,1,0,1,1,1,0,1 -0,1,0,0,0,2,1,0 -1,1,0,0,0,1,0,0 -1,1,1,0,0,0,0,0 -2,0,0,1,0,1,0,0 -1,0,1,1,0,1,0,0 -2,0,1,1,0,1,1,0 -1,0,0,0,0,2,0,0 -2,1,1,1,0,1,1,0 -3,0,1,0,1,1,0,1 -0,0,1,1,0,0,1,0 -3,0,0,0,0,2,1,0 -2,0,1,1,1,1,0,1 -2,1,1,1,1,0,0,0 -0,1,0,1,1,2,0,0 -0,0,0,0,0,0,0,0 -2,1,0,0,0,1,0,0 -2,0,1,1,0,2,1,0 -3,1,1,0,1,1,1,0 -2,0,0,1,0,0,1,0 -1,0,0,0,1,0,0,0 -3,1,1,1,1,0,1,0 -3,1,1,1,0,2,1,0 -1,1,1,1,0,2,1,0 -1,1,0,0,0,0,1,0 -2,1,0,0,0,1,1,0 -3,1,0,1,1,1,1,0 -1,0,0,0,0,0,0,0 -3,0,1,0,0,0,1,0 -2,1,0,1,1,2,0,1 -1,0,1,1,1,2,1,0 -1,1,1,0,0,2,1,0 -2,1,1,0,0,0,0,0 -2,1,1,1,0,2,0,0 -2,1,0,1,0,0,1,0 -2,0,1,0,0,0,1,0 -2,0,0,0,1,2,0,0 -0,1,0,0,1,0,0,0 -1,1,1,1,1,1,1,0 -1,1,1,0,0,2,0,0 -3,1,1,0,1,1,0,0 -1,1,0,1,1,1,0,0 -0,0,0,1,1,2,0,0 -1,1,0,1,0,0,0,0 -3,1,0,0,0,2,0,0 -2,1,0,0,1,2,1,0 -1,0,0,1,1,1,0,0 -0,0,0,1,0,0,0,0 -0,1,1,0,1,0,1,0 -0,0,1,1,1,1,0,0 -0,0,1,0,0,1,0,0 -0,0,0,0,0,2,0,0 -2,0,1,0,0,2,0,0 -0,0,1,0,1,1,1,0 -0,0,0,0,0,2,1,0 -3,1,1,1,0,0,0,0 -3,0,1,1,1,2,1,0 -3,0,1,0,1,0,0,0 -1,0,0,1,0,1,0,0 -2,1,0,1,0,0,0,0 -2,0,0,1,1,2,1,0 -2,0,1,1,1,2,0,1 -3,0,0,1,0,0,1,0 -1,1,1,1,1,2,0,0 -2,0,0,1,1,2,0,0 -2,0,1,0,1,2,0,1 -0,1,1,1,0,2,0,0 -1,0,0,1,1,0,0,0 -3,1,0,1,1,0,1,0 -3,0,0,0,1,1,1,0 -0,0,1,0,0,0,0,0 -3,1,0,1,0,0,1,0 -0,1,0,1,0,2,0,0 -0,1,1,0,1,0,0,0 -2,1,0,0,1,2,0,0 -2,1,1,1,0,0,1,0 -0,1,1,1,0,0,1,0 -1,0,0,0,0,1,0,0 -1,1,0,0,0,0,0,0 -1,1,1,1,0,0,1,0 -1,0,0,1,1,0,1,0 -0,1,1,0,0,2,0,0 -1,1,1,0,1,2,0,0 -3,1,1,1,1,1,1,0 -0,1,0,1,1,1,1,0 -1,1,0,0,1,1,0,0 -0,1,1,1,1,0,0,0 -2,1,1,0,0,1,1,0 -0,0,0,0,1,1,0,0 -3,1,0,1,0,0,0,0 -1,0,1,1,1,2,0,0 -1,0,0,1,1,2,1,0 -3,1,0,1,1,1,0,1 -0,1,1,0,1,1,1,0 -3,1,0,0,1,0,0,0 -1,0,1,1,0,2,0,0 -1,1,1,0,1,1,1,0 -3,0,0,0,0,0,0,0 -1,1,0,0,0,2,1,0 -3,0,0,1,1,0,1,0 -0,1,1,1,0,0,0,0 -1,0,1,1,0,0,0,0 -1,1,1,0,0,0,1,0 -0,0,1,1,0,2,0,0 -2,1,1,0,1,1,1,0 -3,1,1,0,1,2,0,0 -1,1,0,1,1,1,1,0 -1,0,0,1,0,1,1,0 -3,1,1,1,0,1,1,0 -3,1,0,0,0,1,1,0 -1,1,1,1,1,0,1,0 -1,1,1,1,0,2,0,0 -0,1,0,0,1,1,0,0 -0,0,1,0,1,0,1,0 -3,1,1,0,0,2,0,0 -3,1,0,1,0,2,0,0 -1,0,1,1,0,1,1,0 -3,0,1,1,1,0,1,0 -0,1,0,0,0,0,0,0 -3,1,0,1,0,1,1,0 -3,0,1,0,0,1,0,0 -0,0,1,0,1,2,1,0 -3,0,1,0,0,1,1,0 -0,0,0,0,0,1,0,0 -3,0,0,1,1,2,0,0 -2,0,0,0,0,0,1,0 -2,1,1,0,0,2,0,0 -3,1,0,0,0,0,0,0 -3,0,0,0,0,1,0,0 -2,1,1,0,1,0,0,0 -3,0,0,0,1,2,1,0 -0,1,1,1,1,2,0,0 -2,1,1,1,0,0,0,0 -0,1,1,0,1,1,0,0 -0,1,1,1,0,1,1,0 -0,0,1,0,1,2,0,0 -1,0,0,0,1,2,1,0 -0,1,0,1,0,1,1,0 -2,1,0,1,0,1,1,0 -2,1,1,0,1,0,1,0 -2,1,1,0,0,2,1,0 -2,1,1,1,1,2,0,1 -2,1,0,0,1,0,0,0 -3,1,0,1,1,2,0,1 -1,0,1,1,0,0,1,0 -1,1,0,1,0,2,1,0 -2,1,1,1,1,2,1,0 -3,1,1,1,1,0,0,0 -2,1,0,0,0,2,1,0 -2,1,0,1,0,2,0,0 -3,0,0,1,0,2,1,0 -0,0,0,1,1,1,0,0 -0,0,1,0,0,2,0,0 -3,0,1,1,0,2,1,0 -2,0,1,1,0,0,1,0 -2,1,0,0,0,0,0,0 -3,0,0,0,1,0,0,0 -3,1,1,0,0,1,0,0 -3,1,1,0,0,0,1,0 -0,0,1,1,1,0,1,0 -3,0,0,0,0,0,1,0 -2,0,0,0,1,0,0,0 -1,1,0,1,0,1,0,0 -1,1,0,1,1,2,1,0 -3,1,0,1,0,2,1,0 -2,1,0,1,1,1,1,0 -0,0,0,1,0,2,1,0 -2,0,1,0,0,1,1,0 -0,0,0,1,0,0,1,0 -3,0,0,1,0,1,0,0 -2,0,1,0,1,0,1,0 -2,1,1,1,1,1,0,1 -3,1,1,0,0,1,1,0 -3,1,1,1,0,1,0,0 -1,1,1,0,1,1,0,0 -2,0,1,0,0,2,1,0 -2,0,1,0,1,1,1,0 -3,0,0,0,1,2,0,0 -0,1,1,0,0,2,1,0 -1,0,1,0,0,0,1,0 -0,1,1,1,1,0,1,0 -2,0,1,1,0,1,0,0 -2,0,0,0,0,2,0,0 -2,1,1,1,0,1,0,0 -0,1,1,1,1,1,0,0 -1,0,1,0,1,0,0,0 diff --git a/dataset/datasetGenerator.py b/dataset/datasetGenerator.py deleted file mode 100644 index b525b04..0000000 --- a/dataset/datasetGenerator.py +++ /dev/null @@ -1,57 +0,0 @@ -import random -import csv - -attributes = { - 1: ["empty", "low", "medium", "high"], - 2: ["empty", "full"], - 3: ["none", "available"], - 4: ["none", "available"], - 5: ["unavailable", "available"], - 6: ["low", "medium", "high"], - 7: ["no", "yes"], - 8: ["no", "yes"] -} - -dataset = [] -while len(dataset) < 200: - data = {} - - # Generate random values for attributes 1-7 - for attr in range(1, 8): - data[attr] = random.choice(attributes[attr]) - - # Apply the rules to determine the value of attribute 8 - if data[1] in ["empty", "low"]: - data[8] = "no" - elif data[2] == "full" and data[4] == "none": - data[8] = "no" - elif data[2] == "empty" and data[3] == "none": - data[8] = "no" - elif data[3] == "none" and data[4] == "none": - data[8] = "no" - elif data[5] == "unavailable": - data[8] = "no" - elif data[6] == "low": - data[8] = "no" - elif data[7] == "yes": - data[8] = "no" - else: - data[8] = "yes" - - # Check if the generated data already exists in the dataset - if data not in dataset: - dataset.append(data) - -# Print the generated dataset -for data in dataset: - print(data) -with open("dataset/Dataset.csv", "w", newline="") as csvfile: - writer = csv.writer(csvfile) - - # Write the header row - writer.writerow(["Battery Charge", "Fullness", "Ready orders", "Waiting tables","Availability", "Cleanliness", "Error", "To go"]) - - # Write the data rows - for data in dataset: - row = [data[attr] for attr in range(1, 9)] - writer.writerow(row) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 8ae1323..513e519 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,5 @@ -i https://pypi.org/simple pygame==2.3.0 +pandas +scikit-learn +graphviz \ No newline at end of file diff --git a/src/Engine.py b/src/Engine.py index e020f39..a75a378 100644 --- a/src/Engine.py +++ b/src/Engine.py @@ -4,6 +4,8 @@ from .obj.Object import Object from .obj.Waiter import Waiter from .UserController import UserController from .StateController import StateController +from .decisionTree.TreeConcept import TreeEngine +from queue import PriorityQueue class Engine: @@ -12,6 +14,7 @@ class Engine: pygame.display.set_caption('Waiter Agent') self.action_clock = 0 + self.tree = TreeEngine() self.user: Waiter = user self.state: StateController = state @@ -59,6 +62,7 @@ class Engine: if self.goals: self.state.graphsearch(self) self.user.handler(self) + self.predict() else: # went path @@ -105,3 +109,49 @@ class Engine: def appendGoalPosition(self, position): self.goals.append(position) + + def predict(self): + + goal_queue = PriorityQueue() + + for o in self.objects: + + condition = o.agent_role in [ + "order", + "wait", + "done" + ] + + if not condition or o.compare_pos(self.user.obj.position): + continue + + battery = self.user.obj.battary_status()[0] + distance = o.distance_to( + self.user.obj.position) // (self.num_squares // 2) + mood = o.get_mood(self.action_clock)[0] if condition else 0 + memory = self.user.obj.memory_size + dishes_held = self.user.obj.basket_size + customers = o.customers if condition else 0 + waiting_for_order = o.is_order() if condition else 0 + waiting_for_dish = o.is_done() if condition else 0 + + p = self.tree.make_predict( + battery, + distance, + mood, + memory, + dishes_held, + customers, + waiting_for_order, + waiting_for_dish + ) + + goal_queue.put((p, o.position)) + + if len(goal_queue.queue): + priority, goal = goal_queue.queue.pop() + if priority: + print(goal, priority, end='\r') + self.appendGoalPosition(goal) + else: + print(goal, priority, end='\r') diff --git a/src/UserController.py b/src/UserController.py index 1136df3..d9d6e70 100644 --- a/src/UserController.py +++ b/src/UserController.py @@ -13,7 +13,6 @@ class UserController: pos = pygame.mouse.get_pos() 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) + for o in engine.objects: + if o.compare_pos(pos): + o.set_order(engine.action_clock) diff --git a/src/decisionTree/TreeConcept.py b/src/decisionTree/TreeConcept.py new file mode 100644 index 0000000..b77fb39 --- /dev/null +++ b/src/decisionTree/TreeConcept.py @@ -0,0 +1,70 @@ +import time +from sklearn import tree +import numpy as np +import graphviz +from src.decisionTree.datasetGenerator import generateRawDataset +from src.decisionTree.datasetConverter import convertDataset + + +class TreeEngine(): + def __init__(self): + generateRawDataset() + convertDataset() + + # importing the dataset from the disk + train_data_m = np.genfromtxt( + "out/dataset.csv", delimiter=",", skip_header=1) + + # Separate the attributes and labels + self.X_train = [data[:-1] for data in train_data_m] + self.y_train = [data[-1] for data in train_data_m] + + # Create the decision tree classifier using the ID3 algorithm + self.clf = tree.DecisionTreeClassifier( + criterion='entropy', splitter="best") + # clf = tree.DecisionTreeClassifier(criterion='gini') + + # Train the decision tree on the training data + self.clf.fit(self.X_train, self.y_train) + + self.exportText() + self.exportPdf() + + def exportText(self): + # Visualize the trained decision tree + tree_text = tree.export_text(self.clf, feature_names=[ + "Battery level", + "Distance between kitchen and table", + "Customers mood", + "Basket is empty", + "Dish is ready", + "Dish in basket", + "Table status", + "Is actual", + ]) + + with open('out/decision_tree.txt', 'w') as f: + f.write(tree_text) # Save the visualization as a text file + + def exportPdf(self): + dot_data = tree.export_graphviz(self.clf, out_file=None, feature_names=[ + "Battery level", + "Distance between kitchen and table", + "Customers mood", + "Basket is empty", + "Dish is ready", + "Dish in basket", + "Table status", + "Is actual", + ], class_names=[ + 'High priority', + 'Low priority', + 'Return to kitchen', + ], filled=True, rounded=True) + + graph = graphviz.Source(dot_data) + # Save the visualization as a PDF file + graph.render("out/decision_tree") + + def make_predict(self, dataset): + return self.clf.predict([dataset]) diff --git a/dataset/datasetConverter.py b/src/decisionTree/datasetConverter.py similarity index 60% rename from dataset/datasetConverter.py rename to src/decisionTree/datasetConverter.py index ade5bca..48fe3fe 100644 --- a/dataset/datasetConverter.py +++ b/src/decisionTree/datasetConverter.py @@ -1,30 +1,33 @@ import csv -def convert_dataset(input_file, output_file): + +def convertDataset(): attributes = { - 1: ["empty", "low", "medium", "high"], - 2: ["empty", "full"], - 3: ["none", "available"], - 4: ["none", "available"], - 5: ["unavailable", "available"], - 6: ["low", "medium", "high"], - 7: ["no", "yes"], - 8: ["no", "yes"] + 1: ["low", "high"], + 2: ["far", "close"], + 3: ['bad', 'good', 'undefined'], + 4: ["no", "yes"], + 5: ["no", "yes"], + 6: ["no", "yes"], + 7: ["empty", "new order", "waiting for dish", "have a dish"], + 8: ["no", "yes"], + 9: ["high priority", "low priority", "return to kitchen"] } - + # Create a mapping dictionary for attribute values mapping = {} for attr, values in attributes.items(): mapping[attr] = {value: index for index, value in enumerate(values)} - + converted_dataset = [] - + # Read the input CSV file - with open(input_file, "r") as csvfile: + with open("out/rawDataset.csv", "r") as csvfile: reader = csv.reader(csvfile) - + header = next(reader) # Skip the header row - + converted_dataset.append(header) + # Convert the data rows for row in reader: converted_row = [] @@ -34,21 +37,15 @@ def convert_dataset(input_file, output_file): converted_value = mapping[i + 1][value] else: converted_value = value - + converted_row.append(converted_value) - + converted_dataset.append(converted_row) - + # Write the converted dataset to a new CSV file - with open(output_file, "w", newline="") as csvfile: + with open("out/dataset.csv", "w", newline="") as csvfile: writer = csv.writer(csvfile) - - # Write the header row - #writer.writerow(header) - + # Write the converted data rows for row in converted_dataset: writer.writerow(row) - -# Example usage: -convert_dataset("dataset/Dataset.csv", "dataset/converted_dataset.csv") \ No newline at end of file diff --git a/src/decisionTree/datasetGenerator.py b/src/decisionTree/datasetGenerator.py new file mode 100644 index 0000000..cbf2873 --- /dev/null +++ b/src/decisionTree/datasetGenerator.py @@ -0,0 +1,111 @@ +import csv +from pathlib import Path + + +def generateRawDataset(): + battery_values = ['high', 'low'] + distance_values = ['far', 'close'] + mood_values = ['undefined', 'good', 'bad'] + status_values = ['empty', 'new order', 'waiting for dish', 'have a dish'] + other = ['no', 'yes'] + + training_data = [] + training_data.append([ + "Battery level", + "Distance between kitchen and table", + "Customers mood", + "Basket is empty", + "Dish is ready", + "Dish in basket", + "Table status", + "Is actual", + "Priority" + ]) + + for battery in battery_values: + for distance in distance_values: + for mood in mood_values: + for basket in other: + for ready in other: + for dish in other: + for status in status_values: + for actual in other: + + dataset = buildDataset( + battery, + distance, + mood, + basket, + ready, + dish, + status, + actual + ) + + training_data.append(dataset) + + Path("out/").mkdir(parents=True, exist_ok=True) + with open('out/rawDataset.csv', 'w', newline='') as file: + writer = csv.writer(file) + writer.writerows(training_data) + + +def buildDataset(b, d, m, e, r, i, s, a) -> list: + dataset = [ + b, # battery + d, # distance + m, # mood + e, # basket is empty + r, # ready + i, # dish in basket + s, # status + a, # actual + ] + + dataset.append(getPriority(dataset)) + + return dataset + + +def getPriority(dataset) -> str: + PRIORITY = { + 'high': 'high priority', + 'low': 'low priority', + 'kitchen': 'return to kitchen' + } + + BATTERY_LEVEL = dataset[0] + DISTANCE_TO_OBJECT = dataset[1] + MOOD = dataset[2] + BASKET_IS_EMPTY = dataset[3] + DISH_IS_READY = dataset[4] + DISH_IN_BASKET = dataset[5] + STATUS_OF_TABLE = dataset[6] + IS_ACTUAL = dataset[7] + + def mood_and_distance() -> str: + if MOOD == "undefined": + return PRIORITY['kitchen'] + elif MOOD == "good": + return PRIORITY['low'] + elif DISTANCE_TO_OBJECT == "far": + return PRIORITY['high'] + else: + return PRIORITY['low'] + + if BATTERY_LEVEL == "low": + return PRIORITY['kitchen'] + elif IS_ACTUAL == "no": + return PRIORITY['high'] + elif STATUS_OF_TABLE == "empty" or STATUS_OF_TABLE == "have a dish": + return PRIORITY['kitchen'] + elif STATUS_OF_TABLE == "new order": + return mood_and_distance() + elif BASKET_IS_EMPTY == "yes": + return PRIORITY['kitchen'] + elif DISH_IS_READY == "no": + return PRIORITY['kitchen'] + elif DISH_IN_BASKET == "no": + return PRIORITY['kitchen'] + else: + return mood_and_distance() diff --git a/src/decisionTree/dataset_generator.py b/src/decisionTree/dataset_generator.py deleted file mode 100644 index 99b7a1f..0000000 --- a/src/decisionTree/dataset_generator.py +++ /dev/null @@ -1,33 +0,0 @@ -import csv -import random - -battery_values = ['high', 'medium', 'low'] -distance_values = ['far', 'medium', 'close'] -mood_values = ['good', 'medium', 'bad'] -other = ['yes', 'no'] - - -training_data = [] - -for _ in range(200): - battery = random.choice(battery_values) - distance = random.choice(distance_values) - mood = random.choice(mood_values) - memory = random.randint(0,4) - dishes_held = random.randint(0,4) - """empty_basket = random.choice(other) - if empty_basket == 'yes': - dish_in_basket = 'no' - else: - dish_in_basket = random.choice(other) - dish_in_basket = random.choice(other)""" - waiting_for_order = random.choice(other) - waiting_for_dish = random.choice(other) - - example = [battery, distance, mood, memory, dishes_held, waiting_for_order, waiting_for_dish] - training_data.append(example) - -with open('data.csv', 'w', newline='') as file: - writer = csv.writer(file) - writer.writerows(training_data) - diff --git a/src/obj/Table.py b/src/obj/Table.py index d6b58f1..c254642 100644 --- a/src/obj/Table.py +++ b/src/obj/Table.py @@ -37,9 +37,6 @@ class Table(Object): 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 @@ -48,12 +45,12 @@ class Table(Object): return None diff = current_time - self.order_time - if diff < 200: - return "good" - elif diff < 400: - return "medium" + if diff < 100: + return (0, "good") + elif diff < 200: + return (1, "medium") else: - return "bad" + return (2, "bad") def action(self, waiter): if self.is_order(): diff --git a/src/obj/Waiter.py b/src/obj/Waiter.py index c80c4dc..fb52b48 100644 --- a/src/obj/Waiter.py +++ b/src/obj/Waiter.py @@ -18,92 +18,11 @@ class Waiter(Object): self.orientation = copy.copy(state.orientation) self.basket = copy.copy(state.basket) self.battery -= state.cost - # self.calcTree() return state def dish_in_basket(self, table) -> bool: return table in self.basket - ''' - def calcTree(self): - from sklearn import tree - import pandas as pd # for manipulating the csv data - import numpy as np - import os - - # importing the dataset from the disk - train_data_m = np.genfromtxt( - "dataset/converted_dataset.csv", delimiter=",", skip_header=1) - - X_train = [data[:-1] for data in train_data_m] - y_train = [data[-1] for data in train_data_m] - # Create the decision tree classifier using the ID3 algorithm - clf = tree.DecisionTreeClassifier(criterion='entropy') - - # Train the decision tree on the training data - clf.fit(X_train, y_train) - - # Visualize the trained decision tree - tree_text = tree.export_text(clf, feature_names=[ - 'Battery Charge', 'Fullness', 'Ready orders', 'Waiting tables', 'Availability', 'Cleanliness', 'Error']) - with open('decision_tree.txt', 'w') as f: - f.write(tree_text) # Save the visualization as a text file - - # Test the decision tree with a new example - # Battery Charge,Fullness,Ready orders,Waiting tables,Availability,Cleanliness,Error - new_example = [self.battery, 0, self.orderReadiness, - self.waitingTables, self.availability, self.cleanliness, self.error] - predicted_label = clf.predict([new_example]) - if predicted_label[0] > 0: - result = "YES" - else: - result = "NO" - print("Predicted Label:", result) - - def calcTreePDF(self): - from sklearn import tree - import pandas as pd # for manipulating the csv data - import numpy as np - import graphviz - import os - os.environ["PATH"] += os.pathsep + \ - 'C:/Program Files (x86)/Graphviz/bin/' - - # importing the dataset from the disk - train_data_m = np.genfromtxt( - "dataset/converted_dataset.csv", delimiter=",", skip_header=1) - - X_train = [data[:-1] for data in train_data_m] - y_train = [data[-1] for data in train_data_m] - # Create the decision tree classifier using the ID3 algorithm - clf = tree.DecisionTreeClassifier(criterion='entropy') - - # Train the decision tree on the training data - clf.fit(X_train, y_train) - - # Visualize the trained decision tree - tree_text = tree.export_text(clf, feature_names=[ - 'Battery Charge', 'Fullness', 'Ready orders', 'Waiting tables', 'Availability', 'Cleanliness', 'Error']) - with open('decision_tree.txt', 'w') as f: - f.write(tree_text) # Save the visualization as a text file - dot_data = tree.export_graphviz(clf, out_file=None, feature_names=[ - 'Battery Charge', 'Fullness', 'Ready orders', 'Waiting tables', 'Availability', 'Cleanliness', 'Error'], class_names=['NO', 'YES'], filled=True, rounded=True) - graph = graphviz.Source(dot_data) - graph.render("decision_tree") # Save the visualization as a PDF file - - # Test the decision tree with a new example - # Battery Charge,Fullness,Ready orders,Waiting tables,Availability,Cleanliness,Error - new_example = [self.battery, 0, self.orderReadiness, - self.waitingTables, self.availability, self.cleanliness, self.error] - predicted_label = clf.predict([new_example]) - if predicted_label[0] > 0: - result = "YES" - else: - result = "NO" - print("Predicted Label:", result) - - ''' - def basket_is_full(self) -> bool: return self.basket_size == 0 @@ -140,11 +59,11 @@ class Waiter(Object): def battary_status(self) -> str: if self.battery >= 200: - return "hight" + return (2, "hight") elif self.battery >= 100: - return "medium" + return (1, "medium") else: - return "low" + return (0, "low") def recharge(self): self.battery = 300