diff --git a/.idea/misc.xml b/.idea/misc.xml index 715ed69..adaa126 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/.idea/wozek.iml b/.idea/wozek.iml index a9742fc..904114b 100644 --- a/.idea/wozek.iml +++ b/.idea/wozek.iml @@ -4,7 +4,7 @@ - + diff --git a/Raport_444420.md b/Raport_444420.md new file mode 100644 index 0000000..45706d9 --- /dev/null +++ b/Raport_444420.md @@ -0,0 +1,165 @@ +# Tomasz Kuczyński Raport - mcda + +### Opis podprojektu +Podprojekt ma za zadanie wybrać określoną liczbę najlepszych produktów z dostawy. +Wykorzystuj on zmodyfikowaną motodę MCDA - Multiple Criteria Decision Analysis. + +#### Uczenie modelu +Zbiór uczenia składa się z zdefiniowania wartości atrybutów: + +```javascript +color = {'black': 16, 'gold': 10, 'purple': 5, 'brown': 7, 'blue': 12, 'white': 14, 'red': 13, 'orange': 11} +shape = {'rectangle': 15, 'pack': 19, 'square': 9, 'jar': 7} +size = {'small': 7, 'medium': 16, 'big': 13} +``` +oraz ich wyliczenia: +```javascript +def sizeValue(X): + if X.size == 'small': + return X.mass/5 + if X.size == 'medium': + return X.mass/10 + if X.size == 'big': + return X.mass/20 +``` + +Składa się róznierz z parametrów: + +`weights` - waga danego parametru + +`q` - współczynik pomyłki (granicy błędu) pomiędzy atrybutami + +`p` - maksymalna dopuszczalna różnica pomiędy atrybutami + +```javascript +parameters = { + 'color': {'weights': 3, 'q': 1, 'p': 5}, + 'shape': {'weights': 4, 'q': 1, 'p': 6}, + 'mass': {'weights': 0.5, 'q': 2, 'p': 10}, + 'size': {'weights': 1, 'q': 1, 'p': 8} +} +``` + +#### Opis kodu w wspólnym projekcie +W wspólnym projekcie w pliku main.py wywołuje funkcję wybierania 5 produktów z dostawy: + +```javascript +produsctsFromSupply = choseProducts(5) +``` + +próbna dostawa jest zapisana w pliku supply.py: + +```javascript +def create_data_products(): + allProducts = [] + + product = Product('black', 'rectangle', 51, 'small') + allProducts.append(product) + product = Product('black', 'rectangle', 51, 'small') + allProducts.append(product) + product = Product('gold', 'pack', 100, 'big') + allProducts.append(product) + ... + return allProducts + +``` + +Cały algorytm selekcji produktów znajduje się w pliku mcda.py. + +Funkcja `getConcordance(gA, gB, q, p):` ma za zadanie wyliczyć `Concordance` czyli jakość produktu A względem produktu B, za pomocą wartości atrybutów A, B odpowiednio gA, gB oraz parametrów tego atrybutu q, p i zwrócić liczbę z zakresu [0,1]. + +```javascript +def getConcordance(gA, gB, q, p): + if gB <= gA + q: + return 1 + if gB <= gA + p: + return (p - gB + gA) / (p - q) + return 0 +``` + +Funkcja `getAllTypeConcordance(A, B)` ma za zadanie wyliczyć wszystkie typy `Concordance` oraz wyliczyć ich średnią ważoną: + +```javascript +def getAllTypeConcordance(A, B): + concordance = 0.0 + weight_sum = 0 + + parameter = parameters['color'] + w, q, p = parameter['weights'], parameter['q'], parameter['p'] + concordance += getConcordance(color[A.color], color[B.color], q, p) * w + weight_sum += w + + parameter = parameters['shape'] + w, q, p = parameter['weights'], parameter['q'], parameter['p'] + concordance += getConcordance(shape[A.shape], shape[B.shape], q, p) * w + weight_sum += w + ... + concordance /= weight_sum + return concordance +``` + +Funkcja `getConcordanceAllProducts()` ma za zadanie przy pomocy funkcji `getAllTypeConcordance(A, B)` wyliczyć `Concordance` dla wszystkich produktów i zwrócić wynik w postaci listy: + +```javascript +def getConcordanceAllProducts(): + C = [] + + for i in range(len(allProducts)): + c = 0 + for j in range(len(allProducts)): + if j==i: + continue + else: + c += getAllTypeConcordance(allProducts[i], allProducts[j]) + c /= len(allProducts)-1 + C.append(c) + return C +``` + +Funkcja `choseProducts(number)` ma za zadanie wybrać `number` produktów z dostawy na podstawie listy `Concordance` zwróconej przez funkcję `getConcordanceAllProducts()`. + +```javascript +def choseProducts(number): + C = getConcordanceAllProducts() + products = [] + prev = -1 + if number > len(allProducts): + return allProducts + while number > 0: + max = -1 + if prev == -1: + max = 0 + for j in range(len(allProducts)): + if prev == -1: + if C[max]C[j]: + max = j + elif C[max] < C[j] and C[j] < C[prev]: + max = j + prev = max + for j in range(len(allProducts)): + if C[max] == C[j]: + products.append(allProducts[j]) + print(C[j]) + number -= 1 + if number == 0: + break + print(C) + return products +``` + +`print(C[j])` oraz `print(C)` służy do sprawdzenia poprawności algorytmu. + +### Uruchomienie algorytmu i jego działanie +Film przedstawiający uruchomienie aplikacji: +https://www.youtube.com/watch?v=DmwDlJkjtjs + +Parametry pojawiające się w terminalu: + +1.Concordance `number` najlepszych produktów (`print(C[j])`). + +2.Lista wszystkich Concordance ( `print(C)`). + + diff --git a/__pycache__/agent.cpython-38.pyc b/__pycache__/agent.cpython-38.pyc new file mode 100644 index 0000000..7eee450 Binary files /dev/null and b/__pycache__/agent.cpython-38.pyc differ diff --git a/__pycache__/board.cpython-38.pyc b/__pycache__/board.cpython-38.pyc new file mode 100644 index 0000000..a0ab288 Binary files /dev/null and b/__pycache__/board.cpython-38.pyc differ diff --git a/__pycache__/data.cpython-38.pyc b/__pycache__/data.cpython-38.pyc new file mode 100644 index 0000000..82c5772 Binary files /dev/null and b/__pycache__/data.cpython-38.pyc differ diff --git a/__pycache__/decision_tree.cpython-38.pyc b/__pycache__/decision_tree.cpython-38.pyc new file mode 100644 index 0000000..281b85f Binary files /dev/null and b/__pycache__/decision_tree.cpython-38.pyc differ diff --git a/__pycache__/field.cpython-38.pyc b/__pycache__/field.cpython-38.pyc new file mode 100644 index 0000000..4413c80 Binary files /dev/null and b/__pycache__/field.cpython-38.pyc differ diff --git a/__pycache__/functions.cpython-38.pyc b/__pycache__/functions.cpython-38.pyc new file mode 100644 index 0000000..e39b7f4 Binary files /dev/null and b/__pycache__/functions.cpython-38.pyc differ diff --git a/__pycache__/mcda.cpython-38.pyc b/__pycache__/mcda.cpython-38.pyc new file mode 100644 index 0000000..79e10a9 Binary files /dev/null and b/__pycache__/mcda.cpython-38.pyc differ diff --git a/__pycache__/product.cpython-38.pyc b/__pycache__/product.cpython-38.pyc new file mode 100644 index 0000000..61b31f2 Binary files /dev/null and b/__pycache__/product.cpython-38.pyc differ diff --git a/__pycache__/settings.cpython-38.pyc b/__pycache__/settings.cpython-38.pyc new file mode 100644 index 0000000..19a5bce Binary files /dev/null and b/__pycache__/settings.cpython-38.pyc differ diff --git a/__pycache__/shelf.cpython-38.pyc b/__pycache__/shelf.cpython-38.pyc new file mode 100644 index 0000000..16977ed Binary files /dev/null and b/__pycache__/shelf.cpython-38.pyc differ diff --git a/__pycache__/supply.cpython-38.pyc b/__pycache__/supply.cpython-38.pyc new file mode 100644 index 0000000..8dba534 Binary files /dev/null and b/__pycache__/supply.cpython-38.pyc differ diff --git a/__pycache__/sweets.cpython-38.pyc b/__pycache__/sweets.cpython-38.pyc new file mode 100644 index 0000000..8bdc65f Binary files /dev/null and b/__pycache__/sweets.cpython-38.pyc differ diff --git a/main.py b/main.py index 0f4925b..cb61a47 100644 --- a/main.py +++ b/main.py @@ -9,7 +9,7 @@ from agent import Agent from settings import Settings from board import create_board, draw_board from random import randint, choice - +from mcda import choseProducts # Inicjalizacja programu i utworzenie obiektu ekrany def run(): @@ -21,6 +21,8 @@ def run(): board = create_board(screen) my_tree = decision_tree.build_tree(data.learning_data) + produsctsFromSupply = choseProducts(5) + # for row in board: # for field in row: # print(field.cost_of_travel) diff --git a/mcda.py b/mcda.py new file mode 100644 index 0000000..68dd463 --- /dev/null +++ b/mcda.py @@ -0,0 +1,99 @@ +from supply import * + +allProducts = create_data_products() + +color = {'black': 16, 'gold': 10, 'purple': 5, 'brown': 7, 'blue': 12, 'white': 14, 'red': 13, 'orange': 11} +shape = {'rectangle': 15, 'pack': 19, 'square': 9, 'jar': 7} +size = {'small': 7, 'medium': 16, 'big': 13} + +def sizeValue(X): + if X.size == 'small': + return X.mass/5 + if X.size == 'medium': + return X.mass/10 + if X.size == 'big': + return X.mass/20 +parameters = { + 'color': {'weights': 3, 'q': 1, 'p': 5}, + 'shape': {'weights': 4, 'q': 1, 'p': 6}, + 'mass': {'weights': 0.5, 'q': 2, 'p': 10}, + 'size': {'weights': 1, 'q': 1, 'p': 8} + +} +def getConcordance(gA, gB, q, p): + if gB <= gA + q: + return 1 + if gB <= gA + p: + return (p - gB + gA) / (p - q) + return 0 + +def getAllTypeConcordance(A, B): + concordance = 0.0 + weight_sum = 0 + + parameter = parameters['color'] + w, q, p = parameter['weights'], parameter['q'], parameter['p'] + concordance += getConcordance(color[A.color], color[B.color], q, p) * w + weight_sum += w + + parameter = parameters['shape'] + w, q, p = parameter['weights'], parameter['q'], parameter['p'] + concordance += getConcordance(shape[A.shape], shape[B.shape], q, p) * w + weight_sum += w + + parameter = parameters['mass'] + w, q, p = parameter['weights'], parameter['q'], parameter['p'] + concordance += getConcordance(sizeValue(A), sizeValue(B), q, p) * w + weight_sum += w + + parameter = parameters['size'] + w, q, p = parameter['weights'], parameter['q'], parameter['p'] + concordance += getConcordance(size[A.size], size[B.size], q, p) * w + weight_sum += w + + concordance /= weight_sum + return concordance + +def getConcordanceAllProducts(): + C = [] + + for i in range(len(allProducts)): + c = 0 + for j in range(len(allProducts)): + if j==i: + continue + else: + c += getAllTypeConcordance(allProducts[i], allProducts[j]) + c /= len(allProducts)-1 + C.append(c) + return C + +def choseProducts(number): + C = getConcordanceAllProducts() + products = [] + prev = -1 + if number > len(allProducts): + return allProducts + while number > 0: + max = -1 + if prev == -1: + max = 0 + for j in range(len(allProducts)): + if prev == -1: + if C[max]C[j]: + max = j + elif C[max] < C[j] and C[j] < C[prev]: + max = j + prev = max + for j in range(len(allProducts)): + if C[max] == C[j]: + products.append(allProducts[j]) + print(C[j]) + number -= 1 + if number == 0: + break + print(C) + return products \ No newline at end of file diff --git a/product.py b/product.py new file mode 100644 index 0000000..e2acbe5 --- /dev/null +++ b/product.py @@ -0,0 +1,7 @@ +class Product: + + def __init__(self, color, shape, mass, size): + self.color = color + self.shape = shape + self.mass = mass + self.size = size \ No newline at end of file diff --git a/supply.py b/supply.py new file mode 100644 index 0000000..673b31a --- /dev/null +++ b/supply.py @@ -0,0 +1,64 @@ +from product import Product + + +def create_data_products(): + allProducts = [] + + product = Product('black', 'rectangle', 51, 'small') + allProducts.append(product) + product = Product('black', 'rectangle', 51, 'small') + allProducts.append(product) + product = Product('gold', 'pack', 100, 'big') + allProducts.append(product) + product = Product('purple', 'rectangle', 100, 'big') + allProducts.append(product) + product = Product('brown', 'pack', 45, 'small') + allProducts.append(product) + product = Product('blue', 'rectangle', 50, 'medium') + allProducts.append(product) + product = Product('blue', 'square', 40, 'small') + allProducts.append(product) + product = Product('blue', 'rectangle', 35, 'small') + allProducts.append(product) + product = Product('gold', 'rectangle', 40, 'medium') + allProducts.append(product) + product = Product('gold', 'rectangle', 50, 'medium') + allProducts.append(product) + product = Product('brown', 'rectangle', 55, 'medium') + allProducts.append(product) + product = Product('brown', 'rectangle', 45, 'medium') + allProducts.append(product) + product = Product('white', 'rectangle', 40, 'medium') + allProducts.append(product) + product = Product('red', 'rectangle', 50, 'medium') + allProducts.append(product) + product = Product('blue', 'rectangle', 115, 'big') + allProducts.append(product) + product = Product('white', 'rectangle', 15, 'small') + allProducts.append(product) + product = Product('red', 'pack', 70, 'medium') + allProducts.append(product) + product = Product('orange', 'rectangle', 45, 'medium') + allProducts.append(product) + product = Product('blue', 'rectangle', 55, 'medium') + allProducts.append(product) + product = Product('gold', 'rectangle', 120, 'big') + allProducts.append(product) + product = Product('white', 'rectangle', 120, 'big') + allProducts.append(product) + product = Product('white', 'jar', 600, 'big') + allProducts.append(product) + product = Product('white', 'rectangle', 25, 'small') + allProducts.append(product) + product = Product('brown', 'jar', 500, 'big') + allProducts.append(product) + product = Product('brown', 'jar', 470, 'big') + allProducts.append(product) + product = Product('red', 'jar', 250, 'medium') + allProducts.append(product) + product = Product('black', 'jar', 250, 'medium') + allProducts.append(product) + product = Product('orange', 'jar', 250, 'medium') + allProducts.append(product) + + return allProducts \ No newline at end of file