From 80efe4d80092f83a3f137b6f65f1ab318b6e0995 Mon Sep 17 00:00:00 2001 From: Piotr Rychlicki Date: Tue, 12 May 2020 18:46:18 +0000 Subject: [PATCH 01/13] =?UTF-8?q?pe=C5=82en=20algorytm=20genetyczny?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Algorytm genetyczny szukający dla naszego agenta optymalnej trasy przejazdu przez wszystkie pola danego typu --- Piotrek.py | 194 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 152 insertions(+), 42 deletions(-) diff --git a/Piotrek.py b/Piotrek.py index f79ae05..3d8b14f 100644 --- a/Piotrek.py +++ b/Piotrek.py @@ -15,7 +15,7 @@ class main(): for i in self.field.field_matrix: for j in i: if j == 1 or j == 3 or j == 5 or j == 7: #zliczanie zachwaszczonych pól - tabela_wystapien[0] = tabela_wystapien[0] + 1 + tabela_wystapien[0] = tabela_wystapien[0] + 1 elif j == 1 or j == 2 or j == 3: #zliczanie nienawodnionych pól tabela_wystapien[1] = tabela_wystapien[1] + 1 elif j == 4: #zliczanie pól gotowych do zasadzenia @@ -35,7 +35,7 @@ class main(): pola_buraczane.append(k*10+l) l = l + 1 k = k + 1 - pierwsze_szukane_pole = pola_buraczane[0] + pierwsze_szukane_pole = pola_buraczane[0] #początkowa współrzędna, w każdym przypadku pole startowe [0,0] pola_buraczane.append(pierwsze_szukane_pole) print("Współrzędne pól buraczanych: " + str(pola_buraczane)) return pola_buraczane @@ -44,11 +44,13 @@ class main(): self.liczba_pol = len(pola_buraczane) total_cost = 0 i = 0 - while i < (self.liczba_pol-1): + while i < (self.liczba_pol - 1): + # print(str(self.pathfinding.pathfinding_tractorless(self.field,pola_buraczane,i))) total_cost = total_cost + self.pathfinding.pathfinding_tractorless(self.field,pola_buraczane,i) + # print(str(total_cost)) i = i + 1 - #print("Koszt przejścia przez pola buraczane rzędami: " + str(total_cost)) - #print("###################") + # print("Koszt przejścia przez pola buraczane w zadanej kolejności: " + str(total_cost)) + # print("###################") return total_cost def tworzenie_pokolenia(self,pola_buraczane,i): @@ -58,24 +60,34 @@ class main(): wspolrzedne_shuffle.append(pola_buraczane[x]) x = x - 1 x = len(pola_buraczane) - 2 - lista_osobnikow = [] + lista_osobnikow = [] while i > 0: #liczebność pierwszego pokolenia (domyślnie 10) nowy_osobnik = random.sample(wspolrzedne_shuffle, len(wspolrzedne_shuffle)) nowy_osobnik.insert(0,0) #dodanie na początek listy 0, jako współrzenej startowej nowy_osobnik.insert(x,0) #dodanie na koniec listy 0, jako współrzenej końcowej lista_osobnikow.append(nowy_osobnik) i = i - 1 - print(lista_osobnikow) + print("Lista osobników: " + str(lista_osobnikow)) return lista_osobnikow def ocena_przystosowania(self,pokolenia): suma_kosztow_tras = 0 ile_osobnikow = 0 koszty_tras_osobnikow = [] + y = 0 + pierwszy_koszt = self.trasa_buraczana(pokolenia[y]) + najnizszy_koszt = pierwszy_koszt + najwyzszy_koszt = pierwszy_koszt for i in pokolenia: koszty_tras_osobnikow.append(self.trasa_buraczana(i)) suma_kosztow_tras = suma_kosztow_tras + self.trasa_buraczana(i) ile_osobnikow = ile_osobnikow + 1 + if self.trasa_buraczana(i) < najnizszy_koszt: + najnizszy_koszt = self.trasa_buraczana(i) + if self.trasa_buraczana(i) > najwyzszy_koszt: + najwyzszy_koszt = self.trasa_buraczana(i) + print("Najtansza trasa w danym pokoleniu: " + str(najnizszy_koszt)) + print("Najdrozsza trasa w danym pokoleniu: " + str(najwyzszy_koszt)) srednie_przystosowanie = suma_kosztow_tras/ile_osobnikow #parametr potrzebny do oceny przystosowania osobnikow przystosowanie_osobnikow = [] sumaryczne_przystosowanie_osobnikow = 0 @@ -83,12 +95,12 @@ class main(): for i in koszty_tras_osobnikow: przystosowanie_osobnikow.append(round(((srednie_przystosowanie/koszty_tras_osobnikow[l])*10),2)) sumaryczne_przystosowanie_osobnikow += round(((srednie_przystosowanie/koszty_tras_osobnikow[l])*10),2) - l = l + 1 - print(str(round(sumaryczne_przystosowanie_osobnikow,2))) - print("Ocena przystosowania każdego z osobników: " + str(przystosowanie_osobnikow)) - print("Koszty tras każdego z osobników: " + str(koszty_tras_osobnikow)) - print("Średnie przystosowanie wszystkich osobników: " + str(srednie_przystosowanie)) - return(przystosowanie_osobnikow) + l = l + 1 + # print(str(round(sumaryczne_przystosowanie_osobnikow,2))) + # print("Ocena przystosowania każdego z osobników: " + str(przystosowanie_osobnikow)) + # print("Koszty tras każdego z osobników: " + str(koszty_tras_osobnikow)) + # print("Średnie przystosowanie wszystkich osobników: " + str(srednie_przystosowanie)) + return(przystosowanie_osobnikow, najnizszy_koszt, najwyzszy_koszt, srednie_przystosowanie) def wybor_populacji_posredniej(self,pierwsze_pokolenie,przystosowanie_osobnikow): x = len(przystosowanie_osobnikow) @@ -101,7 +113,7 @@ class main(): tabela_ruletki.append(round(przedzial,2)) x = x - 1 i = i + 1 - print(str(tabela_ruletki)) + #print("Tabela ruletki do losowania z przedziałami dla każdego osobnika: " + str(tabela_ruletki)) x = len(przystosowanie_osobnikow)/2 #losowanie połowy liczby osobników populacji początkowej do populacji pośredniej maks = tabela_ruletki[i-1] while x > 0: @@ -109,26 +121,24 @@ class main(): n = random.uniform(0, maks) #losowanie przedziału while n > tabela_ruletki[i]: i = i + 1 - populacja_posrednia.append(pierwsze_pokolenie[i]) + populacja_posrednia.append(pierwsze_pokolenie[i]) x = x - 1 - print(str(populacja_posrednia)) #populacja posrednia, z której zostanie utworzona populacja potomków + # print("Populacja pośrednia (rodziców): " + str(populacja_posrednia)) #populacja posrednia, z której zostanie utworzona populacja potomków return populacja_posrednia def krzyzowanie(self,populacja_posrednia): + populacja_po_krzyzowaniu = [] x = len(populacja_posrednia) - 1 while x > 0: rodzic_1 = populacja_posrednia[x] - print("Rodzic nr 1: " + str(rodzic_1)) + #print("Rodzic nr 1: " + str(rodzic_1)) rodzic_2 = populacja_posrednia[x-1] - print("Rodzic nr 2: " + str(rodzic_2)) + #print("Rodzic nr 2: " + str(rodzic_2)) dziecko_1 = [] dziecko_2 = [] - czy_krzyzowac = random.randint(1,100) #losowanie czy krzyzowac rodzicow, czy nie - if (czy_krzyzowac < 78) and (rodzic_1 != rodzic_2): #jesli krzyzowanie nastepuje - print("Nastąpiło krzyżowanie") + czy_krzyzowac = random.randint(1,100) #losowanie czy krzyzowac rodzicow, czy nie (szanse 10%) + if (czy_krzyzowac < 10) and (rodzic_1 != rodzic_2): #jesli krzyzowanie nastepuje miejsce_krzyzowania = random.randint(1,(len(populacja_posrednia[x])-3)) #wybor miejsca krzyzowania - print(str(miejsce_krzyzowania)) - print(str(rodzic_1[miejsce_krzyzowania])) l = 0 k = miejsce_krzyzowania while k >= 0: #dodawanie do dziecka pierwszej połowy z pierwszego rodzica @@ -155,25 +165,26 @@ class main(): k = k + 1 dziecko_1.append(0) dziecko_2.append(0) - else: #jesli krzyzowanie nie nastepuje, wowczas potencjalni rodzice staja sie dziecmi - print("Krzyżowanie nie nastąpiło") + else: #jesli krzyzowanie nie nastepuje, wowczas potencjalni rodzice staja sie dziecmi dziecko_1 = rodzic_1 dziecko_2 = rodzic_2 - print("Dziecko nr 1: " + str(dziecko_1)) - print("Dziecko nr 2: " + str(dziecko_2)) - x = x - 1 + populacja_po_krzyzowaniu.append(dziecko_1) + populacja_po_krzyzowaniu.append(dziecko_2) + #print("Dziecko nr 1: " + str(dziecko_1)) + #print("Dziecko nr 2: " + str(dziecko_2)) + x = x - 1 + + #ostatnie krzyżowanie, pomiędzy pierwszym a ostatnim rodzicem z listy osobnikow nalezacych do populacji posredniej + rodzic_1 = populacja_posrednia[0] - print("Rodzic nr 1: " + str(rodzic_1)) + #print("Rodzic nr 1: " + str(rodzic_1)) rodzic_2 = populacja_posrednia[(len(populacja_posrednia)-1)] - print("Rodzic nr 2: " + str(rodzic_2)) + #print("Rodzic nr 2: " + str(rodzic_2)) dziecko_1 = [] dziecko_2 = [] - czy_krzyzowac = random.randint(1,100) #losowanie czy krzyzowac rodzicow, czy nie - if (czy_krzyzowac < 78) and (rodzic_1 != rodzic_2): #jesli krzyzowanie nastepuje - print("Nastąpiło krzyżowanie") + czy_krzyzowac = random.randint(1,100) #losowanie czy krzyzowac rodzicow, czy nie (szanse 10%) + if (czy_krzyzowac < 10) and (rodzic_1 != rodzic_2): #jesli krzyzowanie nastepuje miejsce_krzyzowania = random.randint(1,(len(populacja_posrednia[x])-3)) #wybor miejsca krzyzowania - print(str(miejsce_krzyzowania)) - print(str(rodzic_1[miejsce_krzyzowania])) l = 0 k = miejsce_krzyzowania while k >= 0: #dodawanie do dziecka pierwszej połowy z pierwszego rodzica @@ -200,18 +211,117 @@ class main(): k = k + 1 dziecko_1.append(0) dziecko_2.append(0) - else: #jesli krzyzowanie nie nastepuje, wowczas potencjalni rodzice staja sie dziecmi - print("Krzyżowanie nie nastąpiło") + else: #jesli krzyzowanie nie nastepuje, wowczas potencjalni rodzice staja sie dziecmi dziecko_1 = rodzic_1 dziecko_2 = rodzic_2 - print("Dziecko nr 1: " + str(dziecko_1)) - print("Dziecko nr 2: " + str(dziecko_2)) + populacja_po_krzyzowaniu.append(dziecko_1) + populacja_po_krzyzowaniu.append(dziecko_2) + #print("Dziecko nr 1: " + str(dziecko_1)) + #print("Dziecko nr 2: " + str(dziecko_2)) + return populacja_po_krzyzowaniu - def main(self): + def mutacja(self,populacja_po_krzyzowaniu): + k = len(populacja_po_krzyzowaniu) - 1 + while k >= 0: + czy_mutacja = random.randint(0,100) + if czy_mutacja < 3: # Szanse 2% + kogo_mutujemy = populacja_po_krzyzowaniu[k] + populacja_po_krzyzowaniu.remove(kogo_mutujemy) + l = len(kogo_mutujemy) - 1 + #print("Osobnik przed mutacją: " + str(kogo_mutujemy)) + x = random.randint(1,l) + y = random.randint(1,l) + while x == y: + y = random.randint(1,l) + zamiennik = kogo_mutujemy[x] + kogo_mutujemy[x] = kogo_mutujemy[y] + kogo_mutujemy[y] = zamiennik + #print("Osobnik po mutacji: " + str(kogo_mutujemy)) + populacja_po_krzyzowaniu.insert(k,kogo_mutujemy) + else: + pass + k = k - 1 + populacja_po_mutacji = populacja_po_krzyzowaniu + return populacja_po_mutacji + + def optymalizacja(self,populacja_po_mutacji,pola_buraczane): #polega na eliminacji powtarzających się tras + populacja_po_optymalizacji = populacja_po_mutacji + i = len(populacja_po_mutacji) + l = 1 + while l < i: + k = l + while k >= 0: + if populacja_po_mutacji[l] == populacja_po_mutacji[k-1]: + populacja_po_optymalizacji.remove(populacja_po_mutacji[k-1]) + x = len(pola_buraczane) - 2 + wspolrzedne_shuffle = [] + while x > 1: + wspolrzedne_shuffle.append(pola_buraczane[x]) + x = x - 1 + x = len(pola_buraczane) - 2 + nowy_osobnik = random.sample(wspolrzedne_shuffle, len(wspolrzedne_shuffle)) + nowy_osobnik.insert(0,0) #dodanie na początek listy 0, jako współrzenej startowej + nowy_osobnik.insert(x,0) + populacja_po_optymalizacji.append(nowy_osobnik) + # print("Nastąpiła optymalizacja") + else: + pass + k = k - 1 + l = l + 1 + # print("Populacja po optymalizacji: " + str(populacja_po_optymalizacji)) + return populacja_po_optymalizacji + + def algorytm_genetyczny(self): self.zliczanie_wystapien() self.pola_buraczane = self.wspolrzedne() self.koszt_trasy = self.trasa_buraczana(self.pola_buraczane) + # Utworzenie pokolenia self.pierwsze_pokolenie = self.tworzenie_pokolenia(self.pola_buraczane,10) - self.przystosowanie = self.ocena_przystosowania(self.pierwsze_pokolenie) + # Funkcja przystosowania + self.przystosowanie, self.najnizszy_koszt, self.najwyzszy_koszt, self.srednie_przystosowanie_pierwszego_pokolenia = self.ocena_przystosowania(self.pierwsze_pokolenie) + # Populacja pośrednia wybrana metodą ruletki self.populacja_posrednia = self.wybor_populacji_posredniej(self.pierwsze_pokolenie, self.przystosowanie) - self.krzyzowanie(self.populacja_posrednia) \ No newline at end of file + # Krzyżowanie populacji pośredniej + self.populacja_po_krzyzowaniu = self.krzyzowanie(self.populacja_posrednia) + # Mutacja populacji pośredniej + self.populacja_po_mutacji = self.mutacja(self.populacja_po_krzyzowaniu) + # Optymalizacja populacji pośredniej + self.populacja_po_optymalizacji = self.optymalizacja(self.populacja_po_mutacji,self.pola_buraczane) + self.maks_koszt = self.najwyzszy_koszt + self.min_koszt = self.najnizszy_koszt + i = 2 + self.ktore_pokolenie = 1 + while i < 41: + print(" ") + print("*********************") + print("Pokolenie " + str(i)) + print("*********************") + print(" ") + # Funkcja przystosowania + self.przystosowanie, self.najnizszy_koszt, self.najwyzszy_koszt, self.srednie_przystosowanie = self.ocena_przystosowania(self.populacja_po_optymalizacji) + if self.najwyzszy_koszt > self.maks_koszt: + self.maks_koszt = self.najwyzszy_koszt + print("Nowy maksymalny koszt: " + str(self.maks_koszt)) + if self.najnizszy_koszt < self.min_koszt: + self.min_koszt = self.najnizszy_koszt + self.ktore_pokolenie = i + print("Nowy najnizszy koszt: " + str(self.min_koszt)) + # Populacja pośrednia wybrana metodą ruletki + self.populacja_posrednia = self.wybor_populacji_posredniej(self.populacja_po_mutacji, self.przystosowanie) + # Krzyżowanie populacji pośredniej + self.populacja_po_krzyzowaniu = self.krzyzowanie(self.populacja_posrednia) + # Mutacja populacji pośredniej + self.populacja_po_mutacji = self.mutacja(self.populacja_po_krzyzowaniu) + # Optymalizacja populacji pośredniej + self.populacja_po_optymalizacji = self.optymalizacja(self.populacja_po_mutacji,self.pola_buraczane) + i = i + 1 + if (self.min_koszt)/(self.srednie_przystosowanie_pierwszego_pokolenia) < (0.69): + print("Zakończono wykonywanie algorytmu po " + str(i) + " pokoleniach") + break + print("Średnie przygotowanie pierwszego pokolenia: " + str(self.srednie_przystosowanie_pierwszego_pokolenia)) + print(str((self.min_koszt)/(self.srednie_przystosowanie_pierwszego_pokolenia))) + print("Najwyzszy znaleziony koszt: " + str(self.maks_koszt)) + print("Najnizszy znaleziony koszt to " + str(self.min_koszt) + " znaleziony w pokoleniu nr " + str(self.ktore_pokolenie)) + + def main(self): + self.algorytm_genetyczny() \ No newline at end of file From c87c4a06f2fc8ae04e272401ede2643561659be4 Mon Sep 17 00:00:00 2001 From: Piotr Rychlicki Date: Tue, 12 May 2020 22:09:46 +0000 Subject: [PATCH 02/13] =?UTF-8?q?pe=C5=82en=20algorytm=20genetyczny=20wraz?= =?UTF-8?q?=20z=20integracj=C4=85=20z=20ca=C5=82ym=20projektem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Piotrek.py | 65 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/Piotrek.py b/Piotrek.py index 3d8b14f..789e2dc 100644 --- a/Piotrek.py +++ b/Piotrek.py @@ -1,4 +1,4 @@ -import field, pathfinding_tractorless +import field, pathfinding_tractorless, pathfinding_tractor import random class main(): @@ -8,7 +8,8 @@ class main(): self.field = field self.ui = ui self.path = path - self.pathfinding = pathfinding_tractorless.pathfinding_tractorless() + self.pathfinding_tractorless = pathfinding_tractorless.pathfinding_tractorless() + self.pathfinding_tractor = pathfinding_tractor.pathfinding_tractor() def zliczanie_wystapien(self): #zlicza wystepowanie kazdego z rodzajow pol na planszy tabela_wystapien = [0,0,0,0] @@ -28,16 +29,17 @@ class main(): def wspolrzedne(self): #wyznacza wspolrzedne pol danego rodzaju na planszy pola_buraczane = [] k = 0 + ktore_pole = self.traktor.get_modes_values() for i in self.field.field_matrix: l = 0 for j in i: - if j == 8: #w tym przypadku pol z burakami + if j in ktore_pole: #w tym przypadku pol z burakami, stąd 8 pola_buraczane.append(k*10+l) l = l + 1 k = k + 1 pierwsze_szukane_pole = pola_buraczane[0] #początkowa współrzędna, w każdym przypadku pole startowe [0,0] pola_buraczane.append(pierwsze_szukane_pole) - print("Współrzędne pól buraczanych: " + str(pola_buraczane)) + print("Współrzędne szukanych pól: " + str(pola_buraczane)) return pola_buraczane def trasa_buraczana(self,pola_buraczane): #wyznacza koszt trasy przez pola danego rodzaju w zadanej kolejnosci @@ -45,8 +47,8 @@ class main(): total_cost = 0 i = 0 while i < (self.liczba_pol - 1): - # print(str(self.pathfinding.pathfinding_tractorless(self.field,pola_buraczane,i))) - total_cost = total_cost + self.pathfinding.pathfinding_tractorless(self.field,pola_buraczane,i) + # print(str(self.pathfinding_tractorless.pathfinding_tractorless(self.field,pola_buraczane,i))) + total_cost = total_cost + self.pathfinding_tractorless.pathfinding_tractorless(self.field,pola_buraczane,i) # print(str(total_cost)) i = i + 1 # print("Koszt przejścia przez pola buraczane w zadanej kolejności: " + str(total_cost)) @@ -56,10 +58,10 @@ class main(): def tworzenie_pokolenia(self,pola_buraczane,i): x = len(pola_buraczane) - 2 wspolrzedne_shuffle = [] - while x > 1: + while x > 0: wspolrzedne_shuffle.append(pola_buraczane[x]) x = x - 1 - x = len(pola_buraczane) - 2 + x = len(pola_buraczane) - 1 lista_osobnikow = [] while i > 0: #liczebność pierwszego pokolenia (domyślnie 10) nowy_osobnik = random.sample(wspolrzedne_shuffle, len(wspolrzedne_shuffle)) @@ -67,7 +69,7 @@ class main(): nowy_osobnik.insert(x,0) #dodanie na koniec listy 0, jako współrzenej końcowej lista_osobnikow.append(nowy_osobnik) i = i - 1 - print("Lista osobników: " + str(lista_osobnikow)) + # print("Lista osobników: " + str(lista_osobnikow)) return lista_osobnikow def ocena_przystosowania(self,pokolenia): @@ -76,6 +78,7 @@ class main(): koszty_tras_osobnikow = [] y = 0 pierwszy_koszt = self.trasa_buraczana(pokolenia[y]) + najtanszy_osobnik = pokolenia[y] najnizszy_koszt = pierwszy_koszt najwyzszy_koszt = pierwszy_koszt for i in pokolenia: @@ -84,10 +87,11 @@ class main(): ile_osobnikow = ile_osobnikow + 1 if self.trasa_buraczana(i) < najnizszy_koszt: najnizszy_koszt = self.trasa_buraczana(i) + najtanszy_osobnik = i if self.trasa_buraczana(i) > najwyzszy_koszt: najwyzszy_koszt = self.trasa_buraczana(i) - print("Najtansza trasa w danym pokoleniu: " + str(najnizszy_koszt)) - print("Najdrozsza trasa w danym pokoleniu: " + str(najwyzszy_koszt)) + # print("Najtansza trasa w danym pokoleniu: " + str(najnizszy_koszt)) + # print("Najdrozsza trasa w danym pokoleniu: " + str(najwyzszy_koszt)) srednie_przystosowanie = suma_kosztow_tras/ile_osobnikow #parametr potrzebny do oceny przystosowania osobnikow przystosowanie_osobnikow = [] sumaryczne_przystosowanie_osobnikow = 0 @@ -100,7 +104,7 @@ class main(): # print("Ocena przystosowania każdego z osobników: " + str(przystosowanie_osobnikow)) # print("Koszty tras każdego z osobników: " + str(koszty_tras_osobnikow)) # print("Średnie przystosowanie wszystkich osobników: " + str(srednie_przystosowanie)) - return(przystosowanie_osobnikow, najnizszy_koszt, najwyzszy_koszt, srednie_przystosowanie) + return(przystosowanie_osobnikow, najnizszy_koszt, najwyzszy_koszt, srednie_przystosowanie, najtanszy_osobnik) def wybor_populacji_posredniej(self,pierwsze_pokolenie,przystosowanie_osobnikow): x = len(przystosowanie_osobnikow) @@ -170,8 +174,8 @@ class main(): dziecko_2 = rodzic_2 populacja_po_krzyzowaniu.append(dziecko_1) populacja_po_krzyzowaniu.append(dziecko_2) - #print("Dziecko nr 1: " + str(dziecko_1)) - #print("Dziecko nr 2: " + str(dziecko_2)) + # print("Dziecko nr 1: " + str(dziecko_1)) + # print("Dziecko nr 2: " + str(dziecko_2)) x = x - 1 #ostatnie krzyżowanie, pomiędzy pierwszym a ostatnim rodzicem z listy osobnikow nalezacych do populacji posredniej @@ -216,8 +220,8 @@ class main(): dziecko_2 = rodzic_2 populacja_po_krzyzowaniu.append(dziecko_1) populacja_po_krzyzowaniu.append(dziecko_2) - #print("Dziecko nr 1: " + str(dziecko_1)) - #print("Dziecko nr 2: " + str(dziecko_2)) + # print("Dziecko nr 1: " + str(dziecko_1)) + # print("Dziecko nr 2: " + str(dziecko_2)) return populacja_po_krzyzowaniu def mutacja(self,populacja_po_krzyzowaniu): @@ -242,6 +246,7 @@ class main(): pass k = k - 1 populacja_po_mutacji = populacja_po_krzyzowaniu + # print("Populacja po mutacji: " + str(populacja_po_mutacji)) return populacja_po_mutacji def optymalizacja(self,populacja_po_mutacji,pola_buraczane): #polega na eliminacji powtarzających się tras @@ -255,10 +260,10 @@ class main(): populacja_po_optymalizacji.remove(populacja_po_mutacji[k-1]) x = len(pola_buraczane) - 2 wspolrzedne_shuffle = [] - while x > 1: + while x > 0: wspolrzedne_shuffle.append(pola_buraczane[x]) x = x - 1 - x = len(pola_buraczane) - 2 + x = len(pola_buraczane) - 1 nowy_osobnik = random.sample(wspolrzedne_shuffle, len(wspolrzedne_shuffle)) nowy_osobnik.insert(0,0) #dodanie na początek listy 0, jako współrzenej startowej nowy_osobnik.insert(x,0) @@ -278,7 +283,7 @@ class main(): # Utworzenie pokolenia self.pierwsze_pokolenie = self.tworzenie_pokolenia(self.pola_buraczane,10) # Funkcja przystosowania - self.przystosowanie, self.najnizszy_koszt, self.najwyzszy_koszt, self.srednie_przystosowanie_pierwszego_pokolenia = self.ocena_przystosowania(self.pierwsze_pokolenie) + self.przystosowanie, self.najnizszy_koszt, self.najwyzszy_koszt, self.srednie_przystosowanie_pierwszego_pokolenia, self.najtanszy_osobnik = self.ocena_przystosowania(self.pierwsze_pokolenie) # Populacja pośrednia wybrana metodą ruletki self.populacja_posrednia = self.wybor_populacji_posredniej(self.pierwsze_pokolenie, self.przystosowanie) # Krzyżowanie populacji pośredniej @@ -289,23 +294,27 @@ class main(): self.populacja_po_optymalizacji = self.optymalizacja(self.populacja_po_mutacji,self.pola_buraczane) self.maks_koszt = self.najwyzszy_koszt self.min_koszt = self.najnizszy_koszt + self.najtansza_trasa = self.najtanszy_osobnik i = 2 self.ktore_pokolenie = 1 while i < 41: print(" ") print("*********************") + print(" ") print("Pokolenie " + str(i)) + print(" ") print("*********************") print(" ") # Funkcja przystosowania - self.przystosowanie, self.najnizszy_koszt, self.najwyzszy_koszt, self.srednie_przystosowanie = self.ocena_przystosowania(self.populacja_po_optymalizacji) + self.przystosowanie, self.najnizszy_koszt, self.najwyzszy_koszt, self.srednie_przystosowanie, self.najtanszy_osobnik = self.ocena_przystosowania(self.populacja_po_optymalizacji) if self.najwyzszy_koszt > self.maks_koszt: self.maks_koszt = self.najwyzszy_koszt - print("Nowy maksymalny koszt: " + str(self.maks_koszt)) if self.najnizszy_koszt < self.min_koszt: - self.min_koszt = self.najnizszy_koszt + self.min_koszt = self.najnizszy_koszt + self.najtansza_trasa = self.najtanszy_osobnik self.ktore_pokolenie = i print("Nowy najnizszy koszt: " + str(self.min_koszt)) + print("Nowa najtansza trasa: " + str(self.najtansza_trasa)) # Populacja pośrednia wybrana metodą ruletki self.populacja_posrednia = self.wybor_populacji_posredniej(self.populacja_po_mutacji, self.przystosowanie) # Krzyżowanie populacji pośredniej @@ -319,9 +328,15 @@ class main(): print("Zakończono wykonywanie algorytmu po " + str(i) + " pokoleniach") break print("Średnie przygotowanie pierwszego pokolenia: " + str(self.srednie_przystosowanie_pierwszego_pokolenia)) - print(str((self.min_koszt)/(self.srednie_przystosowanie_pierwszego_pokolenia))) - print("Najwyzszy znaleziony koszt: " + str(self.maks_koszt)) + print("Stosunek poprawienia kosztu trasy względem początku: " + str((self.min_koszt)/(self.srednie_przystosowanie_pierwszego_pokolenia))) print("Najnizszy znaleziony koszt to " + str(self.min_koszt) + " znaleziony w pokoleniu nr " + str(self.ktore_pokolenie)) + print("Najtansza znaleziona trasa to " + str(self.najtansza_trasa)) + # print("Najwyzszy znaleziony koszt: " + str(self.maks_koszt)) def main(self): - self.algorytm_genetyczny() \ No newline at end of file + self.algorytm_genetyczny() + i = len(self.najtansza_trasa) - 1 + l = 0 + while l < i: + self.pathfinding_tractor.pathfinding_tractor(self.field, self.traktor, self.ui, self.najtansza_trasa, l) + l = l + 1 \ No newline at end of file From 615a76acca0608dd2536c16e3ae500d0d4653ac9 Mon Sep 17 00:00:00 2001 From: Piotr Rychlicki Date: Tue, 12 May 2020 22:10:52 +0000 Subject: [PATCH 03/13] funkcje dodatkowe do Piotrek.py --- pathfinding_tractor.py | 82 ++++++++++++++++++++++++++++++++++++++ pathfinding_tractorless.py | 68 +++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 pathfinding_tractor.py create mode 100644 pathfinding_tractorless.py diff --git a/pathfinding_tractor.py b/pathfinding_tractor.py new file mode 100644 index 0000000..72876d8 --- /dev/null +++ b/pathfinding_tractor.py @@ -0,0 +1,82 @@ +from queue import PriorityQueue +import time + +class pathfinding_tractor(): + def __init__(self): + pass + + def heuristic(self,a, b): + (x1, y1) = a + (x2, y2) = b + return abs(x1 - x2) + abs(y1 - y2) + + def points(self, point): + self.point = [] + for i in [[point[0],point[1]-1],[point[0]-1,point[1]],[point[0],point[1]+1],[point[0]+1,point[1]]]: + if i[0] in [-1,10] or i[1] in [-1,10]: + pass + else: + self.point.append(i) + return self.point + + def pathfinding_tractor(self,field,traktor,ui,pola_buraczane,i): + self.pola = pola_buraczane + self.ui = ui + self.traktor = traktor + self.start_position = [int(self.pola[i])%10,int(self.pola[i])//10] + # print(str(self.start_position)) + self.field = field + self.end_point = [int(self.pola[i+1])%10,int(self.pola[i+1])//10] + # print(str(self.end_point)) + + if self.start_position == self.end_point: + self.traktor.work() + else: + self.route = self.a_star(self.start_position,self.end_point) + for i in self.route[::-1]: + self.poz = self.traktor.get_poz() + if i[1]> self.poz[1]: + self.traktor.move_down() + elif i[1]< self.poz[1]: + self.traktor.move_up() + elif i[0]> self.poz[0]: + self.traktor.move_right() + elif i[0]< self.poz[0]: + self.traktor.move_left() + self.ui.update() + time.sleep(0.1) + self.traktor.work() + + + def a_star(self,start,end): + self.a_queue = PriorityQueue() + self.a_queue.put(start,0) + self.cost = {tuple(start): 0} + self.path_from = {tuple(start): None} + self.finall_path = [tuple(end)] + self.found = 0 + while not self.a_queue.empty(): + self.current = tuple(self.a_queue.get()) + + if self.current == tuple(end): + break + + for self.next in self.points(self.current): + self.new_cost = self.cost[tuple(self.current)] + self.field.get_value(self.next) + if tuple(self.next) not in self.cost or self.new_cost < self.cost[tuple(self.next)]: + self.cost[tuple(self.next)] = self.new_cost + self.priority = self.new_cost + self.heuristic(end, self.next) + self.a_queue.put(self.next,self.priority) + self.path_from[tuple(self.next)] = self.current + if self.next == end: + self.found = 1 + break + if self.found: + break + + self.pth = self.path_from[tuple(end)] + while not self.pth == tuple(start): + self.finall_path.append(self.pth) + self.pth = self.path_from[self.pth] + + return self.finall_path \ No newline at end of file diff --git a/pathfinding_tractorless.py b/pathfinding_tractorless.py new file mode 100644 index 0000000..e74af5c --- /dev/null +++ b/pathfinding_tractorless.py @@ -0,0 +1,68 @@ +from queue import PriorityQueue +import time + +class pathfinding_tractorless(): + def __init__(self): + pass + + def heuristic(self,a, b): + (x1, y1) = a + (x2, y2) = b + return abs(x1 - x2) + abs(y1 - y2) + + def points(self, point): + self.point = [] + for i in [[point[0],point[1]-1],[point[0]-1,point[1]],[point[0],point[1]+1],[point[0]+1,point[1]]]: + if i[0] in [-1,10] or i[1] in [-1,10]: + pass + else: + self.point.append(i) + return self.point + + def pathfinding_tractorless(self,field,pola_buraczane,i): + self.pola = pola_buraczane + self.start_position = [int(self.pola[i])%10,int(self.pola[i])//10] + # print(str(self.start_position)) + self.field = field + self.end_point = [int(self.pola[i+1])%10,int(self.pola[i+1])//10] + # print(str(self.end_point)) + + if self.start_position == self.end_point: + return 0 + else: + self.route = self.a_star(self.start_position,self.end_point) + return self.route + + + def a_star(self,start,end): + self.a_queue = PriorityQueue() + self.a_queue.put(start,0) + self.cost = {tuple(start): 0} + self.path_from = {tuple(start): None} + self.finall_path = [tuple(end)] + self.found = 0 + while not self.a_queue.empty(): + self.current = tuple(self.a_queue.get()) + + if self.current == tuple(end): + break + + for self.next in self.points(self.current): + self.new_cost = self.cost[tuple(self.current)] + self.field.get_value(self.next) + if tuple(self.next) not in self.cost or self.new_cost < self.cost[tuple(self.next)]: + self.cost[tuple(self.next)] = self.new_cost + self.priority = self.new_cost + self.heuristic(end, self.next) + self.a_queue.put(self.next,self.priority) + self.path_from[tuple(self.next)] = self.current + if self.next == end: + self.found = 1 + break + if self.found: + break + + self.pth = self.path_from[tuple(end)] + while not self.pth == tuple(start): + self.finall_path.append(self.pth) + self.pth = self.path_from[self.pth] + + return self.new_cost \ No newline at end of file From d57428a5e092bbb78401ff159724a7db0b2201de Mon Sep 17 00:00:00 2001 From: Piotr Rychlicki Date: Wed, 13 May 2020 07:16:59 +0000 Subject: [PATCH 04/13] =?UTF-8?q?pe=C5=82en=20od=C5=9Bwie=C5=BCony=20algor?= =?UTF-8?q?ytm=20genetyczny=20wraz=20z=20integracj=C4=85=20z=20ca=C5=82ym?= =?UTF-8?q?=20projektem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Piotrek.py | 99 ++++++++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 56 deletions(-) diff --git a/Piotrek.py b/Piotrek.py index 789e2dc..13f76ce 100644 --- a/Piotrek.py +++ b/Piotrek.py @@ -11,57 +11,42 @@ class main(): self.pathfinding_tractorless = pathfinding_tractorless.pathfinding_tractorless() self.pathfinding_tractor = pathfinding_tractor.pathfinding_tractor() - def zliczanie_wystapien(self): #zlicza wystepowanie kazdego z rodzajow pol na planszy - tabela_wystapien = [0,0,0,0] - for i in self.field.field_matrix: - for j in i: - if j == 1 or j == 3 or j == 5 or j == 7: #zliczanie zachwaszczonych pól - tabela_wystapien[0] = tabela_wystapien[0] + 1 - elif j == 1 or j == 2 or j == 3: #zliczanie nienawodnionych pól - tabela_wystapien[1] = tabela_wystapien[1] + 1 - elif j == 4: #zliczanie pól gotowych do zasadzenia - tabela_wystapien[2] = tabela_wystapien[2] + 1 - elif j == 8: #zliczanie pól gotowych do zbiorów - tabela_wystapien[3] = tabela_wystapien[3] + 1 - else: - pass - def wspolrzedne(self): #wyznacza wspolrzedne pol danego rodzaju na planszy - pola_buraczane = [] + znalezione_pola = [] k = 0 - ktore_pole = self.traktor.get_modes_values() + ktore_pole = self.traktor.get_modes_values() #rodzaj pól zależy od ustawionego trybu pracy agenta for i in self.field.field_matrix: l = 0 for j in i: - if j in ktore_pole: #w tym przypadku pol z burakami, stąd 8 - pola_buraczane.append(k*10+l) + if j in ktore_pole: + znalezione_pola.append(k*10+l) l = l + 1 k = k + 1 - pierwsze_szukane_pole = pola_buraczane[0] #początkowa współrzędna, w każdym przypadku pole startowe [0,0] - pola_buraczane.append(pierwsze_szukane_pole) - print("Współrzędne szukanych pól: " + str(pola_buraczane)) - return pola_buraczane + pierwsze_szukane_pole = znalezione_pola[0] #początkowa współrzędna, w każdym przypadku pole startowe [0,0] + znalezione_pola.append(pierwsze_szukane_pole) + print("Współrzędne szukanych pól: " + str(znalezione_pola)) + return znalezione_pola - def trasa_buraczana(self,pola_buraczane): #wyznacza koszt trasy przez pola danego rodzaju w zadanej kolejnosci - self.liczba_pol = len(pola_buraczane) + def koszt_przejazdu(self,znalezione_pola): #wyznacza koszt trasy przez pola danego rodzaju w zadanej kolejnosci + self.liczba_pol = len(znalezione_pola) total_cost = 0 i = 0 while i < (self.liczba_pol - 1): - # print(str(self.pathfinding_tractorless.pathfinding_tractorless(self.field,pola_buraczane,i))) - total_cost = total_cost + self.pathfinding_tractorless.pathfinding_tractorless(self.field,pola_buraczane,i) + # print(str(self.pathfinding_tractorless.pathfinding_tractorless(self.field,znalezione_pola,i))) + total_cost = total_cost + self.pathfinding_tractorless.pathfinding_tractorless(self.field,znalezione_pola,i) # print(str(total_cost)) i = i + 1 - # print("Koszt przejścia przez pola buraczane w zadanej kolejności: " + str(total_cost)) + # print("Koszt przejścia przez pola w zadanej kolejności: " + str(total_cost)) # print("###################") return total_cost - def tworzenie_pokolenia(self,pola_buraczane,i): - x = len(pola_buraczane) - 2 + def tworzenie_pokolenia(self,znalezione_pola,i): + x = len(znalezione_pola) - 2 wspolrzedne_shuffle = [] while x > 0: - wspolrzedne_shuffle.append(pola_buraczane[x]) + wspolrzedne_shuffle.append(znalezione_pola[x]) x = x - 1 - x = len(pola_buraczane) - 1 + x = len(znalezione_pola) - 1 lista_osobnikow = [] while i > 0: #liczebność pierwszego pokolenia (domyślnie 10) nowy_osobnik = random.sample(wspolrzedne_shuffle, len(wspolrzedne_shuffle)) @@ -77,19 +62,19 @@ class main(): ile_osobnikow = 0 koszty_tras_osobnikow = [] y = 0 - pierwszy_koszt = self.trasa_buraczana(pokolenia[y]) + pierwszy_koszt = self.koszt_przejazdu(pokolenia[y]) najtanszy_osobnik = pokolenia[y] najnizszy_koszt = pierwszy_koszt najwyzszy_koszt = pierwszy_koszt for i in pokolenia: - koszty_tras_osobnikow.append(self.trasa_buraczana(i)) - suma_kosztow_tras = suma_kosztow_tras + self.trasa_buraczana(i) + koszty_tras_osobnikow.append(self.koszt_przejazdu(i)) + suma_kosztow_tras = suma_kosztow_tras + self.koszt_przejazdu(i) ile_osobnikow = ile_osobnikow + 1 - if self.trasa_buraczana(i) < najnizszy_koszt: - najnizszy_koszt = self.trasa_buraczana(i) + if self.koszt_przejazdu(i) < najnizszy_koszt: + najnizszy_koszt = self.koszt_przejazdu(i) najtanszy_osobnik = i - if self.trasa_buraczana(i) > najwyzszy_koszt: - najwyzszy_koszt = self.trasa_buraczana(i) + if self.koszt_przejazdu(i) > najwyzszy_koszt: + najwyzszy_koszt = self.koszt_przejazdu(i) # print("Najtansza trasa w danym pokoleniu: " + str(najnizszy_koszt)) # print("Najdrozsza trasa w danym pokoleniu: " + str(najwyzszy_koszt)) srednie_przystosowanie = suma_kosztow_tras/ile_osobnikow #parametr potrzebny do oceny przystosowania osobnikow @@ -141,7 +126,7 @@ class main(): dziecko_1 = [] dziecko_2 = [] czy_krzyzowac = random.randint(1,100) #losowanie czy krzyzowac rodzicow, czy nie (szanse 10%) - if (czy_krzyzowac < 10) and (rodzic_1 != rodzic_2): #jesli krzyzowanie nastepuje + if (czy_krzyzowac < 11) and (rodzic_1 != rodzic_2): #jesli krzyzowanie nastepuje miejsce_krzyzowania = random.randint(1,(len(populacja_posrednia[x])-3)) #wybor miejsca krzyzowania l = 0 k = miejsce_krzyzowania @@ -187,7 +172,7 @@ class main(): dziecko_1 = [] dziecko_2 = [] czy_krzyzowac = random.randint(1,100) #losowanie czy krzyzowac rodzicow, czy nie (szanse 10%) - if (czy_krzyzowac < 10) and (rodzic_1 != rodzic_2): #jesli krzyzowanie nastepuje + if (czy_krzyzowac < 11) and (rodzic_1 != rodzic_2): #jesli krzyzowanie nastepuje miejsce_krzyzowania = random.randint(1,(len(populacja_posrednia[x])-3)) #wybor miejsca krzyzowania l = 0 k = miejsce_krzyzowania @@ -232,7 +217,7 @@ class main(): kogo_mutujemy = populacja_po_krzyzowaniu[k] populacja_po_krzyzowaniu.remove(kogo_mutujemy) l = len(kogo_mutujemy) - 1 - #print("Osobnik przed mutacją: " + str(kogo_mutujemy)) + # print("Osobnik przed mutacją: " + str(kogo_mutujemy)) x = random.randint(1,l) y = random.randint(1,l) while x == y: @@ -240,7 +225,7 @@ class main(): zamiennik = kogo_mutujemy[x] kogo_mutujemy[x] = kogo_mutujemy[y] kogo_mutujemy[y] = zamiennik - #print("Osobnik po mutacji: " + str(kogo_mutujemy)) + # print("Osobnik po mutacji: " + str(kogo_mutujemy)) populacja_po_krzyzowaniu.insert(k,kogo_mutujemy) else: pass @@ -249,7 +234,7 @@ class main(): # print("Populacja po mutacji: " + str(populacja_po_mutacji)) return populacja_po_mutacji - def optymalizacja(self,populacja_po_mutacji,pola_buraczane): #polega na eliminacji powtarzających się tras + def optymalizacja(self,populacja_po_mutacji,znalezione_pola): #polega na eliminacji powtarzających się tras populacja_po_optymalizacji = populacja_po_mutacji i = len(populacja_po_mutacji) l = 1 @@ -258,12 +243,12 @@ class main(): while k >= 0: if populacja_po_mutacji[l] == populacja_po_mutacji[k-1]: populacja_po_optymalizacji.remove(populacja_po_mutacji[k-1]) - x = len(pola_buraczane) - 2 + x = len(znalezione_pola) - 2 wspolrzedne_shuffle = [] while x > 0: - wspolrzedne_shuffle.append(pola_buraczane[x]) + wspolrzedne_shuffle.append(znalezione_pola[x]) x = x - 1 - x = len(pola_buraczane) - 1 + x = len(znalezione_pola) - 1 nowy_osobnik = random.sample(wspolrzedne_shuffle, len(wspolrzedne_shuffle)) nowy_osobnik.insert(0,0) #dodanie na początek listy 0, jako współrzenej startowej nowy_osobnik.insert(x,0) @@ -277,11 +262,10 @@ class main(): return populacja_po_optymalizacji def algorytm_genetyczny(self): - self.zliczanie_wystapien() - self.pola_buraczane = self.wspolrzedne() - self.koszt_trasy = self.trasa_buraczana(self.pola_buraczane) + self.znalezione_pola = self.wspolrzedne() + self.koszt_trasy = self.koszt_przejazdu(self.znalezione_pola) # Utworzenie pokolenia - self.pierwsze_pokolenie = self.tworzenie_pokolenia(self.pola_buraczane,10) + self.pierwsze_pokolenie = self.tworzenie_pokolenia(self.znalezione_pola,10) # Funkcja przystosowania self.przystosowanie, self.najnizszy_koszt, self.najwyzszy_koszt, self.srednie_przystosowanie_pierwszego_pokolenia, self.najtanszy_osobnik = self.ocena_przystosowania(self.pierwsze_pokolenie) # Populacja pośrednia wybrana metodą ruletki @@ -291,7 +275,7 @@ class main(): # Mutacja populacji pośredniej self.populacja_po_mutacji = self.mutacja(self.populacja_po_krzyzowaniu) # Optymalizacja populacji pośredniej - self.populacja_po_optymalizacji = self.optymalizacja(self.populacja_po_mutacji,self.pola_buraczane) + self.populacja_po_optymalizacji = self.optymalizacja(self.populacja_po_mutacji,self.znalezione_pola) self.maks_koszt = self.najwyzszy_koszt self.min_koszt = self.najnizszy_koszt self.najtansza_trasa = self.najtanszy_osobnik @@ -322,7 +306,7 @@ class main(): # Mutacja populacji pośredniej self.populacja_po_mutacji = self.mutacja(self.populacja_po_krzyzowaniu) # Optymalizacja populacji pośredniej - self.populacja_po_optymalizacji = self.optymalizacja(self.populacja_po_mutacji,self.pola_buraczane) + self.populacja_po_optymalizacji = self.optymalizacja(self.populacja_po_mutacji,self.znalezione_pola) i = i + 1 if (self.min_koszt)/(self.srednie_przystosowanie_pierwszego_pokolenia) < (0.69): print("Zakończono wykonywanie algorytmu po " + str(i) + " pokoleniach") @@ -333,10 +317,13 @@ class main(): print("Najtansza znaleziona trasa to " + str(self.najtansza_trasa)) # print("Najwyzszy znaleziony koszt: " + str(self.maks_koszt)) - def main(self): - self.algorytm_genetyczny() + def wykonanie_trasy(self): i = len(self.najtansza_trasa) - 1 l = 0 while l < i: self.pathfinding_tractor.pathfinding_tractor(self.field, self.traktor, self.ui, self.najtansza_trasa, l) - l = l + 1 \ No newline at end of file + l = l + 1 + + def main(self): + self.algorytm_genetyczny() + self.wykonanie_trasy() \ No newline at end of file From 2bd0c27fdd55edd873f4156415e9a99f2c194e22 Mon Sep 17 00:00:00 2001 From: Piotr Rychlicki Date: Wed, 13 May 2020 07:17:24 +0000 Subject: [PATCH 05/13] Zaktualizuj 'pathfinding_tractor.py' --- pathfinding_tractor.py | 162 ++++++++++++++++++++--------------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/pathfinding_tractor.py b/pathfinding_tractor.py index 72876d8..06ac39f 100644 --- a/pathfinding_tractor.py +++ b/pathfinding_tractor.py @@ -1,82 +1,82 @@ -from queue import PriorityQueue -import time - -class pathfinding_tractor(): - def __init__(self): - pass - - def heuristic(self,a, b): - (x1, y1) = a - (x2, y2) = b - return abs(x1 - x2) + abs(y1 - y2) - - def points(self, point): - self.point = [] - for i in [[point[0],point[1]-1],[point[0]-1,point[1]],[point[0],point[1]+1],[point[0]+1,point[1]]]: - if i[0] in [-1,10] or i[1] in [-1,10]: - pass - else: - self.point.append(i) - return self.point - - def pathfinding_tractor(self,field,traktor,ui,pola_buraczane,i): - self.pola = pola_buraczane - self.ui = ui - self.traktor = traktor - self.start_position = [int(self.pola[i])%10,int(self.pola[i])//10] - # print(str(self.start_position)) - self.field = field - self.end_point = [int(self.pola[i+1])%10,int(self.pola[i+1])//10] - # print(str(self.end_point)) - - if self.start_position == self.end_point: - self.traktor.work() - else: - self.route = self.a_star(self.start_position,self.end_point) - for i in self.route[::-1]: - self.poz = self.traktor.get_poz() - if i[1]> self.poz[1]: - self.traktor.move_down() - elif i[1]< self.poz[1]: - self.traktor.move_up() - elif i[0]> self.poz[0]: - self.traktor.move_right() - elif i[0]< self.poz[0]: - self.traktor.move_left() - self.ui.update() - time.sleep(0.1) - self.traktor.work() - - - def a_star(self,start,end): - self.a_queue = PriorityQueue() - self.a_queue.put(start,0) - self.cost = {tuple(start): 0} - self.path_from = {tuple(start): None} - self.finall_path = [tuple(end)] - self.found = 0 - while not self.a_queue.empty(): - self.current = tuple(self.a_queue.get()) - - if self.current == tuple(end): - break - - for self.next in self.points(self.current): - self.new_cost = self.cost[tuple(self.current)] + self.field.get_value(self.next) - if tuple(self.next) not in self.cost or self.new_cost < self.cost[tuple(self.next)]: - self.cost[tuple(self.next)] = self.new_cost - self.priority = self.new_cost + self.heuristic(end, self.next) - self.a_queue.put(self.next,self.priority) - self.path_from[tuple(self.next)] = self.current - if self.next == end: - self.found = 1 - break - if self.found: - break - - self.pth = self.path_from[tuple(end)] - while not self.pth == tuple(start): - self.finall_path.append(self.pth) - self.pth = self.path_from[self.pth] - +from queue import PriorityQueue +import time + +class pathfinding_tractor(): + def __init__(self): + pass + + def heuristic(self,a, b): + (x1, y1) = a + (x2, y2) = b + return abs(x1 - x2) + abs(y1 - y2) + + def points(self, point): + self.point = [] + for i in [[point[0],point[1]-1],[point[0]-1,point[1]],[point[0],point[1]+1],[point[0]+1,point[1]]]: + if i[0] in [-1,10] or i[1] in [-1,10]: + pass + else: + self.point.append(i) + return self.point + + def pathfinding_tractor(self,field,traktor,ui,pola_buraczane,i): + self.pola = pola_buraczane + self.ui = ui + self.traktor = traktor + self.start_position = [int(self.pola[i])%10,int(self.pola[i])//10] + # print(str(self.start_position)) + self.field = field + self.end_point = [int(self.pola[i+1])%10,int(self.pola[i+1])//10] + # print(str(self.end_point)) + + if self.start_position == self.end_point: + self.traktor.work() + else: + self.route = self.a_star(self.start_position,self.end_point) + for i in self.route[::-1]: + self.poz = self.traktor.get_poz() + if i[1]> self.poz[1]: + self.traktor.move_down() + elif i[1]< self.poz[1]: + self.traktor.move_up() + elif i[0]> self.poz[0]: + self.traktor.move_right() + elif i[0]< self.poz[0]: + self.traktor.move_left() + self.ui.update() + time.sleep(0.1) + self.traktor.work() + + + def a_star(self,start,end): + self.a_queue = PriorityQueue() + self.a_queue.put(start,0) + self.cost = {tuple(start): 0} + self.path_from = {tuple(start): None} + self.finall_path = [tuple(end)] + self.found = 0 + while not self.a_queue.empty(): + self.current = tuple(self.a_queue.get()) + + if self.current == tuple(end): + break + + for self.next in self.points(self.current): + self.new_cost = self.cost[tuple(self.current)] + self.field.get_value(self.next) + if tuple(self.next) not in self.cost or self.new_cost < self.cost[tuple(self.next)]: + self.cost[tuple(self.next)] = self.new_cost + self.priority = self.new_cost + self.heuristic(end, self.next) + self.a_queue.put(self.next,self.priority) + self.path_from[tuple(self.next)] = self.current + if self.next == end: + self.found = 1 + break + if self.found: + break + + self.pth = self.path_from[tuple(end)] + while not self.pth == tuple(start): + self.finall_path.append(self.pth) + self.pth = self.path_from[self.pth] + return self.finall_path \ No newline at end of file From 445b6098ee8e32710880d38e415951d48aa53480 Mon Sep 17 00:00:00 2001 From: Piotr Rychlicki Date: Wed, 13 May 2020 07:17:52 +0000 Subject: [PATCH 06/13] funkcja dodatkowa do Piotrek.py --- pathfinding_tractorless.py | 134 ++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/pathfinding_tractorless.py b/pathfinding_tractorless.py index e74af5c..346be43 100644 --- a/pathfinding_tractorless.py +++ b/pathfinding_tractorless.py @@ -1,68 +1,68 @@ -from queue import PriorityQueue -import time - -class pathfinding_tractorless(): - def __init__(self): - pass - - def heuristic(self,a, b): - (x1, y1) = a - (x2, y2) = b - return abs(x1 - x2) + abs(y1 - y2) - - def points(self, point): - self.point = [] - for i in [[point[0],point[1]-1],[point[0]-1,point[1]],[point[0],point[1]+1],[point[0]+1,point[1]]]: - if i[0] in [-1,10] or i[1] in [-1,10]: - pass - else: - self.point.append(i) - return self.point - - def pathfinding_tractorless(self,field,pola_buraczane,i): - self.pola = pola_buraczane - self.start_position = [int(self.pola[i])%10,int(self.pola[i])//10] - # print(str(self.start_position)) - self.field = field - self.end_point = [int(self.pola[i+1])%10,int(self.pola[i+1])//10] - # print(str(self.end_point)) - - if self.start_position == self.end_point: - return 0 - else: - self.route = self.a_star(self.start_position,self.end_point) - return self.route - - - def a_star(self,start,end): - self.a_queue = PriorityQueue() - self.a_queue.put(start,0) - self.cost = {tuple(start): 0} - self.path_from = {tuple(start): None} - self.finall_path = [tuple(end)] - self.found = 0 - while not self.a_queue.empty(): - self.current = tuple(self.a_queue.get()) - - if self.current == tuple(end): - break - - for self.next in self.points(self.current): - self.new_cost = self.cost[tuple(self.current)] + self.field.get_value(self.next) - if tuple(self.next) not in self.cost or self.new_cost < self.cost[tuple(self.next)]: - self.cost[tuple(self.next)] = self.new_cost - self.priority = self.new_cost + self.heuristic(end, self.next) - self.a_queue.put(self.next,self.priority) - self.path_from[tuple(self.next)] = self.current - if self.next == end: - self.found = 1 - break - if self.found: - break - - self.pth = self.path_from[tuple(end)] - while not self.pth == tuple(start): - self.finall_path.append(self.pth) - self.pth = self.path_from[self.pth] - +from queue import PriorityQueue +import time + +class pathfinding_tractorless(): + def __init__(self): + pass + + def heuristic(self,a, b): + (x1, y1) = a + (x2, y2) = b + return abs(x1 - x2) + abs(y1 - y2) + + def points(self, point): + self.point = [] + for i in [[point[0],point[1]-1],[point[0]-1,point[1]],[point[0],point[1]+1],[point[0]+1,point[1]]]: + if i[0] in [-1,10] or i[1] in [-1,10]: + pass + else: + self.point.append(i) + return self.point + + def pathfinding_tractorless(self,field,pola_buraczane,i): + self.pola = pola_buraczane + self.start_position = [int(self.pola[i])%10,int(self.pola[i])//10] + # print(str(self.start_position)) + self.field = field + self.end_point = [int(self.pola[i+1])%10,int(self.pola[i+1])//10] + # print(str(self.end_point)) + + if self.start_position == self.end_point: + return 0 + else: + self.route = self.a_star(self.start_position,self.end_point) + return self.route + + + def a_star(self,start,end): + self.a_queue = PriorityQueue() + self.a_queue.put(start,0) + self.cost = {tuple(start): 0} + self.path_from = {tuple(start): None} + self.finall_path = [tuple(end)] + self.found = 0 + while not self.a_queue.empty(): + self.current = tuple(self.a_queue.get()) + + if self.current == tuple(end): + break + + for self.next in self.points(self.current): + self.new_cost = self.cost[tuple(self.current)] + self.field.get_value(self.next) + if tuple(self.next) not in self.cost or self.new_cost < self.cost[tuple(self.next)]: + self.cost[tuple(self.next)] = self.new_cost + self.priority = self.new_cost + self.heuristic(end, self.next) + self.a_queue.put(self.next,self.priority) + self.path_from[tuple(self.next)] = self.current + if self.next == end: + self.found = 1 + break + if self.found: + break + + self.pth = self.path_from[tuple(end)] + while not self.pth == tuple(start): + self.finall_path.append(self.pth) + self.pth = self.path_from[self.pth] + return self.new_cost \ No newline at end of file From 464e085ecd183e5b9af840feae206f7fdd156038 Mon Sep 17 00:00:00 2001 From: Piotr Rychlicki Date: Wed, 13 May 2020 07:18:36 +0000 Subject: [PATCH 07/13] Piotr Rychlicki - RAPORT --- geneticalgorithm.md | 61 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 geneticalgorithm.md diff --git a/geneticalgorithm.md b/geneticalgorithm.md new file mode 100644 index 0000000..103b6b5 --- /dev/null +++ b/geneticalgorithm.md @@ -0,0 +1,61 @@ +# Sztuczna Inteligencja - Raport 3 + +**Członkowie zespołu:** Marcin Kwapisz, Kamila Matysiak, Piotr Rychlicki, Justyna Zarzycka + +**Temat podprojektu:** Szukanie najkrótszej trasy za pomocą algorytmu genetycznego + +**Autor podprojektu:** Piotr Rychlicki + + +### Algorytm genetyczny + +**Algorytm genetyczny** jest jednym z algorytmów służących do optymalizacji rozwiązania pewnego problemu. Sprawdza się on najlepiej wówczas, gdy nie jest znany lub ściśle określony prosty sposób rozwiązania problemu, a także gdy stosunkowo trudno otrzymać najlepsze rozwiązanie, lecz gdy łatwo można ocenić jakość otrzymanego rozwiązania i je zaakceptować. +Ogólna zasada działania algorytmu (który w kolejnej części zostanie dokładniej omówiony) polega na wygenerowaniu zbioru potencjalnych rozwiązań, które następnie podlegają ocenie. Spośród nich wybierane są te najlepsze, by potem za pomocą operacji genetycznych stworzyć nową grupę, które ponownie przejdzie przez ten cykl. Wynikiem działania takiego algorytmu powinno być otrzymanie optymalnego rozwiązania, spełniającego warunek zakończenia działania algorytmu. + +### Problem + +W tym podprojekcie algorytm genetyczny został użyty do szukania optymalnej trasy przejazdu agenta (dalej zwanego traktorem) przez wszystkie pola danego typu począwszy i skończywszy na polu startowym (o współrzędnych **(0,0)**). +Po uruchomieniu programu, w swoim środowisku traktor zastaje określoną konfigurację pól, z których każde (pole nienawodnione, zachwaszczone, niezasadzone, gotowe do zbiorów) występuje określoną liczbę razy. Naturalnym jest, by traktor wykonując określone zadanie (np. zebranie plonu z pola), przemieszczając się między różnymi polami, zrobił to jak najmniejszym kosztem. Stąd też idea i potrzeba właśnie takiego zastosowania algorytmu genetycznego. +Ten problem, nazywany problemem komiwojażera, należy do problemów NP-zupełnych, czyli takich, które pomimo prostego ich zdefiniowania, są bardzo czasochłonne do rozwiązania. Dla liczby pól z warzywami, na których testowałem swój algorytm i których jest w środowisku testowym 13, liczba potencjalnych rozwiązań wynosi 12!, czyli 479001600 możliwych tras. +Algorytm genetyczny, z powodów wymienionych na początku raportu, jako rodzaj algorytmu heurystycznego (oferującego rozwiązanie przybliżone do idealnego), sprawdza się przy problemie komiwojażera bardzo dobrze. + +### Pojęcia + +* Osobnik - pojedyncze rozwiązanie problemu +* Populacja - zbiór osobników, którymi operuje algorytm +* Pokolenie - populacja przetwarzana w jednej iteracji algorytmu +* Genotyp - to informacja dziedziczna, którą zawiera pojedynczy osobnik +* Gen - to najmniejszy element informacji zawarty w genotypie + +### Algorytm + +``` + def main(self): + self.algorytm_genetyczny() + self.wykonanie_trasy() +``` + +Cały algorytm jest wykonywany w funckji self.algorytm_genetyczny, natomiast funkcja self.wykonanie_trasy odpowiada integrację podprojektu w projekcie, realizując wyznaczoną przez algorytm trasę wraz z odpowiednią akcją agenta. + +``` +self.pola_buraczane = self.wspolrzedne() +``` + +Pierwszy krokiem całego programu jest wyznaczenie współrzędnych pól, przez które będziemy chcieli przejść w najkrótszej trasie. Współrzedne te są reprezentowane macierzą zawierającą liczby dwucyfrową [0,99]: np. pole 32 oznacza współrzędne [2,3]. + +``` +self.koszt_trasy = self.koszt_przejazdu(self.znalezione_pola) +``` + +Następnie wyznaczany jest pierwotny koszt trasy wiodącej przez wszystkie pola danego typu w porządku rosnącym (z góry na dół i z prawa na lewo). + +Poniżej przestawiony został już właściwy algorytm: + +``` + +``` + + +``` + +``` From 8cdc229409e44cb3c42ce96221a91549470e60dc Mon Sep 17 00:00:00 2001 From: Piotr Rychlicki Date: Wed, 13 May 2020 08:39:30 +0000 Subject: [PATCH 08/13] Zaktualizowany raport geneticalgorithm.md --- geneticalgorithm.md | 193 ++++++++++++++++++++++++++++++-------------- 1 file changed, 132 insertions(+), 61 deletions(-) diff --git a/geneticalgorithm.md b/geneticalgorithm.md index 103b6b5..4d397cd 100644 --- a/geneticalgorithm.md +++ b/geneticalgorithm.md @@ -1,61 +1,132 @@ -# Sztuczna Inteligencja - Raport 3 - -**Członkowie zespołu:** Marcin Kwapisz, Kamila Matysiak, Piotr Rychlicki, Justyna Zarzycka - -**Temat podprojektu:** Szukanie najkrótszej trasy za pomocą algorytmu genetycznego - -**Autor podprojektu:** Piotr Rychlicki - - -### Algorytm genetyczny - -**Algorytm genetyczny** jest jednym z algorytmów służących do optymalizacji rozwiązania pewnego problemu. Sprawdza się on najlepiej wówczas, gdy nie jest znany lub ściśle określony prosty sposób rozwiązania problemu, a także gdy stosunkowo trudno otrzymać najlepsze rozwiązanie, lecz gdy łatwo można ocenić jakość otrzymanego rozwiązania i je zaakceptować. -Ogólna zasada działania algorytmu (który w kolejnej części zostanie dokładniej omówiony) polega na wygenerowaniu zbioru potencjalnych rozwiązań, które następnie podlegają ocenie. Spośród nich wybierane są te najlepsze, by potem za pomocą operacji genetycznych stworzyć nową grupę, które ponownie przejdzie przez ten cykl. Wynikiem działania takiego algorytmu powinno być otrzymanie optymalnego rozwiązania, spełniającego warunek zakończenia działania algorytmu. - -### Problem - -W tym podprojekcie algorytm genetyczny został użyty do szukania optymalnej trasy przejazdu agenta (dalej zwanego traktorem) przez wszystkie pola danego typu począwszy i skończywszy na polu startowym (o współrzędnych **(0,0)**). -Po uruchomieniu programu, w swoim środowisku traktor zastaje określoną konfigurację pól, z których każde (pole nienawodnione, zachwaszczone, niezasadzone, gotowe do zbiorów) występuje określoną liczbę razy. Naturalnym jest, by traktor wykonując określone zadanie (np. zebranie plonu z pola), przemieszczając się między różnymi polami, zrobił to jak najmniejszym kosztem. Stąd też idea i potrzeba właśnie takiego zastosowania algorytmu genetycznego. -Ten problem, nazywany problemem komiwojażera, należy do problemów NP-zupełnych, czyli takich, które pomimo prostego ich zdefiniowania, są bardzo czasochłonne do rozwiązania. Dla liczby pól z warzywami, na których testowałem swój algorytm i których jest w środowisku testowym 13, liczba potencjalnych rozwiązań wynosi 12!, czyli 479001600 możliwych tras. -Algorytm genetyczny, z powodów wymienionych na początku raportu, jako rodzaj algorytmu heurystycznego (oferującego rozwiązanie przybliżone do idealnego), sprawdza się przy problemie komiwojażera bardzo dobrze. - -### Pojęcia - -* Osobnik - pojedyncze rozwiązanie problemu -* Populacja - zbiór osobników, którymi operuje algorytm -* Pokolenie - populacja przetwarzana w jednej iteracji algorytmu -* Genotyp - to informacja dziedziczna, którą zawiera pojedynczy osobnik -* Gen - to najmniejszy element informacji zawarty w genotypie - -### Algorytm - -``` - def main(self): - self.algorytm_genetyczny() - self.wykonanie_trasy() -``` - -Cały algorytm jest wykonywany w funckji self.algorytm_genetyczny, natomiast funkcja self.wykonanie_trasy odpowiada integrację podprojektu w projekcie, realizując wyznaczoną przez algorytm trasę wraz z odpowiednią akcją agenta. - -``` -self.pola_buraczane = self.wspolrzedne() -``` - -Pierwszy krokiem całego programu jest wyznaczenie współrzędnych pól, przez które będziemy chcieli przejść w najkrótszej trasie. Współrzedne te są reprezentowane macierzą zawierającą liczby dwucyfrową [0,99]: np. pole 32 oznacza współrzędne [2,3]. - -``` -self.koszt_trasy = self.koszt_przejazdu(self.znalezione_pola) -``` - -Następnie wyznaczany jest pierwotny koszt trasy wiodącej przez wszystkie pola danego typu w porządku rosnącym (z góry na dół i z prawa na lewo). - -Poniżej przestawiony został już właściwy algorytm: - -``` - -``` - - -``` - -``` +# Sztuczna Inteligencja - Raport 3 + +**Członkowie zespołu:** Marcin Kwapisz, Kamila Matysiak, Piotr Rychlicki, Justyna Zarzycka + +**Temat podprojektu:** Szukanie najkrótszej trasy za pomocą algorytmu genetycznego + +**Autor podprojektu:** Piotr Rychlicki + + +### Algorytm genetyczny + +**Algorytm genetyczny** jest jednym z algorytmów służących do optymalizacji rozwiązania pewnego problemu. Sprawdza się on najlepiej wówczas, gdy nie jest znany lub ściśle określony prosty sposób rozwiązania problemu, a także gdy stosunkowo trudno otrzymać najlepsze rozwiązanie, lecz gdy łatwo można ocenić jakość otrzymanego rozwiązania i je zaakceptować. +Ogólna zasada działania algorytmu (który w kolejnej części zostanie dokładniej omówiony) polega na wygenerowaniu zbioru potencjalnych rozwiązań, które następnie podlegają ocenie. Spośród nich wybierane są te najlepsze, by potem za pomocą operacji genetycznych stworzyć nową grupę, które ponownie przejdzie przez ten cykl. Wynikiem działania takiego algorytmu powinno być otrzymanie optymalnego rozwiązania, spełniającego warunek zakończenia działania algorytmu. + +### Problem + +W tym podprojekcie algorytm genetyczny został użyty do szukania optymalnej trasy przejazdu agenta (dalej zwanego traktorem) przez wszystkie pola danego typu począwszy i skończywszy na polu startowym (o współrzędnych **(0,0)**). +Po uruchomieniu programu, w swoim środowisku traktor zastaje określoną konfigurację pól, z których każde (pole nienawodnione, zachwaszczone, niezasadzone, gotowe do zbiorów) występuje określoną liczbę razy. Naturalnym jest, by traktor wykonując określone zadanie (np. zebranie plonu z pola), przemieszczając się między różnymi polami, zrobił to jak najmniejszym kosztem. Stąd też idea i potrzeba właśnie takiego zastosowania algorytmu genetycznego. +Ten problem, nazywany problemem komiwojażera, należy do problemów NP-zupełnych, czyli takich, które pomimo prostego ich zdefiniowania, są bardzo czasochłonne do rozwiązania. Dla liczby pól z warzywami, na których testowałem swój algorytm i których jest w środowisku testowym 13, liczba potencjalnych rozwiązań wynosi 12!, czyli 479001600 możliwych tras. +Algorytm genetyczny, z powodów wymienionych na początku raportu, jako rodzaj algorytmu heurystycznego (oferującego rozwiązanie przybliżone do idealnego), sprawdza się przy problemie komiwojażera bardzo dobrze. + +### Pojęcia + +* Osobnik - pojedyncze rozwiązanie problemu +* Populacja - zbiór osobników, którymi operuje algorytm +* Pokolenie - populacja przetwarzana w jednej iteracji algorytmu +* Genotyp - to informacja dziedziczna, którą zawiera pojedynczy osobnik +* Gen - to najmniejszy element informacji zawarty w genotypie + +### Algorytm + +``` +def main(self): + self.algorytm_genetyczny() + self.wykonanie_trasy() +``` + +Cały algorytm jest wykonywany w funckji self.algorytm_genetyczny, natomiast funkcja self.wykonanie_trasy odpowiada integrację podprojektu w projekcie, realizując wyznaczoną przez algorytm trasę wraz z odpowiednią akcją agenta. + +``` +self.znalezione_pola = self.wspolrzedne() +``` + +Pierwszy krokiem całego programu jest wyznaczenie współrzędnych pól, przez które będziemy chcieli przejść w najkrótszej trasie. Współrzedne te są reprezentowane macierzą zawierającą liczby dwucyfrową [0,99]: np. pole 32 oznacza współrzędne [2,3]. + +``` +self.koszt_trasy = self.koszt_przejazdu(self.znalezione_pola) +``` + +Następnie wyznaczany jest pierwotny koszt trasy wiodącej przez wszystkie pola danego typu w porządku rosnącym (z góry na dół i z prawa na lewo). + +Poniżej przestawiony został już właściwy algorytm: + +``` +# Utworzenie pokolenia +self.pierwsze_pokolenie = self.tworzenie_pokolenia(self.znalezione_pola,10) + +# Funkcja przystosowania +self.przystosowanie, self.najnizszy_koszt, self.najwyzszy_koszt, self.srednie_przystosowanie_pierwszego_pokolenia, self.najtanszy_osobnik = self.ocena_przystosowania(self.pierwsze_pokolenie) + +# Populacja pośrednia wybrana metodą ruletki +self.populacja_posrednia = self.wybor_populacji_posredniej(self.pierwsze_pokolenie, self.przystosowanie) + +# Krzyżowanie populacji pośredniej +self.populacja_po_krzyzowaniu = self.krzyzowanie(self.populacja_posrednia) + +# Mutacja populacji pośredniej +self.populacja_po_mutacji = self.mutacja(self.populacja_po_krzyzowaniu) + +# Optymalizacja populacji pośredniej +self.populacja_po_optymalizacji = self.optymalizacja(self.populacja_po_mutacji,self.znalezione_pola) + +if (self.min_koszt)/(self.srednie_przystosowanie_pierwszego_pokolenia) < (0.69): + print("Zakończono wykonywanie algorytmu po " + str(i) + " pokoleniach") + break +``` + +Pierwszym krokiem każdego algorytmu genetycznego jest utworzenie pierwszego pokolenia osobników. Każde pokolenie w podprojekcie liczy sobie 10 osobników, z których każdy jest permutacją bez powtórzeń współrzędnych zawartych w tablicy self.znalezione_pola wraz z dodaną na koniec współrzędną 0, jako polem, do którego agent ma powrócić na końcu. +Następnie wykonywana jest tzw. funkcja przystosowania, której zadaniem jest ocenić jakość każdego osobnika (czyli potencjalnego rozwiazania): + +``` +przystosowanie_osobnikow.append(round(((srednie_przystosowanie/koszty_tras_osobnikow[l])*10),2)) +``` + +Przystosowanie każdego z osobników przechowywane jest w tablicy przystosowanie_osobnikow i wyliczane za pomocą ilorazu średniego przystosowania wszystkich osobników w danym pokoleniu i kosztu konkretnego osobnika. Im lepsza jakość osobnika (czyli im niższy koszt proponowanej przez niego trasy), tym wyższy wynik funkcji przystosowania. +Po ocenie przystosowania dokonuje się wyboru osobników do populacji pośredniej, z której otrzymamy potomków osobników obecnego pokolenia. Tutaj zdecydowano się na wybór tzw. metodą ruletki, w której każdemu osobnikowi przydziela się zakres należący do przedziału [1,100], proporcjonalny do jego przystosowania. Im większe przystosowanie, tym większy przedział zostanie danemu osobnikowy przydzielony. Następnie losowane jest pięć liczb, właśnie z przedziału [1,100] i do populacji pośredniej trafiają osobnicy, w których zakresach mieszczą się wylosowane liczby. Grupa takich pięciu osobników (do której osobnik może trafić więcej niż raz) staje się populacją pośrednią, która przystąpi do operacji genetycznych w celu poprawienia genotypu. +Tymi operacjami genetycznymi są krzyżowanie, mutacja i dodatkowa optymalizacja. + +``` +czy_krzyzowac = random.randint(1,100) + if (czy_krzyzowac < 11) and (rodzic_1 != rodzic_2): +``` + +Prawdopodobieństwo krzyżowania dwóch kolejnych osobników populacji pośredniej wyznaczono na 10%. Jeśli krzyżowanie nie nastąpi lub osobnicy są identyczni, wówczas przechodzą oni do kolejnego etapu w niezmienionej postaci. +Jeśli krzyżowanie dojdzie do skutki, wówczas dla obu osobników wykonuje się następującą operację: wybiera się losowe miejsce krzyżowania w tablicy zawierającej genotyp, sprzed którego wszystkie geny przechodzą w niezmienionej kolejności do potomka. Następnie brakujące geny potomka uzupełnia się genami drugiego osobnika, których jeszcze nie zawiera potomek (tak by geny, czyli współrzędne, się nie powtórzyły w genotypie) + +``` +k = len(populacja_po_krzyzowaniu) - 1 + while k >= 0: + czy_mutacja = random.randint(0,100) + if czy_mutacja < 3: + kogo_mutujemy = populacja_po_krzyzowaniu[k] +``` + +Jeśli chodzi o mutację, tu prawdopodobieństwo jej zajścia dla każdego osobnika ustalono na 2%. Mutacja polega na wylosowaniu dwóch różnych genów osobnika i zamienieniu ich miejscami. +Na koniec procesu tworzenia potomków dochodzi do opcjonalnej operacji optymalizacji. Jest to nieobowiązkowa funkcja zaimplemetowana w celu dywersyfikacji potomków. Polega ona na usunięciu z populacji pośredniej potwórzeń wśród osobników i uzupełnienie braku nowym, losowym osobnikiem. Po optymalizacji, pokolenie nadal będzie liczyło 10 osobników, lecz każdy z nich z pewnością będzie różny od pozostałych. +Te 10 osobników storzy nową populację potomków. Tę populację poddaje się ocenie, czyli sprawdzeniu warunku końca działania algorytmu. + +``` +if (self.min_koszt)/(self.srednie_przystosowanie_pierwszego_pokolenia) < (0.69): + print("Zakończono wykonywanie algorytmu po " + str(i) + " pokoleniach") + break +``` + +Jeśli zostanie spełniony warunek znacznego poprawienia kosztu najtańszej trasy najnowszego pokolenia względem średniej długości tras pierwszego pokolenia, wówczas można uznać, że znalezione rozwiazanie jest zadowalające i algorytm zostaje przerwany. +Jeśli jednak warunek nie jest spełniony, wtedy algorytm wykonuje się na nowo, począwszy od etapu oceny przystosowania nowego pokolenia. + +``` +def wykonanie_trasy(self): + i = len(self.najtansza_trasa) - 1 + l = 0 + while l < i: + self.pathfinding_tractor.pathfinding_tractor(self.field, self.traktor, self.ui, self.najtansza_trasa, l) + l = l + 1 +``` + +Ostatnim elementem mojego programu jest ,,wcielenie w życie" znalezionej trasy. Taką trasę podaje się funkcji pathfinding_tractor, która następnie egzekwuje agentem wykonanie konkretnej akcji na polach danego typu w zadanej kolejności. + + +### Dobrane parametry + + From cdb0f145bb59adc4919ff4a8aea41ea122922287 Mon Sep 17 00:00:00 2001 From: Piotr Rychlicki Date: Wed, 13 May 2020 09:27:56 +0000 Subject: [PATCH 09/13] =?UTF-8?q?pe=C5=82en=20algorytm=20genetyczny=20wraz?= =?UTF-8?q?=20z=20integracj=C4=85=20z=20ca=C5=82ym=20projektem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Piotrek.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Piotrek.py b/Piotrek.py index 13f76ce..fc1244d 100644 --- a/Piotrek.py +++ b/Piotrek.py @@ -284,9 +284,7 @@ class main(): while i < 41: print(" ") print("*********************") - print(" ") print("Pokolenie " + str(i)) - print(" ") print("*********************") print(" ") # Funkcja przystosowania From a29210a2ea8dbeb69fa49e07912279c288297daa Mon Sep 17 00:00:00 2001 From: Piotr Rychlicki Date: Wed, 13 May 2020 09:28:35 +0000 Subject: [PATCH 10/13] Zaktualizuj 'geneticalgorithm.md' --- geneticalgorithm.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/geneticalgorithm.md b/geneticalgorithm.md index 4d397cd..5836f93 100644 --- a/geneticalgorithm.md +++ b/geneticalgorithm.md @@ -113,7 +113,7 @@ if (self.min_koszt)/(self.srednie_przystosowanie_pierwszego_pokolenia) < (0.69): ``` Jeśli zostanie spełniony warunek znacznego poprawienia kosztu najtańszej trasy najnowszego pokolenia względem średniej długości tras pierwszego pokolenia, wówczas można uznać, że znalezione rozwiazanie jest zadowalające i algorytm zostaje przerwany. -Jeśli jednak warunek nie jest spełniony, wtedy algorytm wykonuje się na nowo, począwszy od etapu oceny przystosowania nowego pokolenia. +Jeśli jednak warunek nie jest spełniony, wtedy algorytm wykonuje się na nowo, (zaczynając od etapu oceny przystosowania nowego pokolenia), aż do momentu przejścia przez x zadanych pokoleń (w mojej iplementacji jest to 40 pokoleń) ``` def wykonanie_trasy(self): @@ -124,9 +124,23 @@ def wykonanie_trasy(self): l = l + 1 ``` -Ostatnim elementem mojego programu jest ,,wcielenie w życie" znalezionej trasy. Taką trasę podaje się funkcji pathfinding_tractor, która następnie egzekwuje agentem wykonanie konkretnej akcji na polach danego typu w zadanej kolejności. +Ostatnim elementem mojego programu jest ,,wcielenie w życie" znalezionej trasy za pomocą powyższej funkcji wykonanie_trasy. Taką trasę podaje się funkcji pathfinding_tractor, która następnie egzekwuje agentem wykonanie konkretnej akcji na polach danego typu w zadanej kolejności. ### Dobrane parametry +Na sprawność działania algorytmu i jakość zwracanych rozwiązań wpływ mają dobrane parametry. Do najważniejszych należą: +* Liczba pokoleń +* Liczebność pokolenia +* Prawdopodobieństwo zajścia krzyzowania +* Prawdopodobieństwo zajścia mutacji +* Warunek zatrzymania algorytmu + +Na początek ustalono prawdopodobieństwa zajścia operacji genetycznych: +Prawdopodobieństwo krzyżowania to 10%. Zazwyczaj jest ono większe, lecz dla klasycznego wariantu ułożenia genów, gdzie geny nie zmieniają pozycji w genotypie, lecz wartość. Tutaj użyto permutacyjnego wariantu ułożenia genów, a zatem krzyżowanie nie prowadzi do satysfakcjonujących wyników z dużą częstotliwością. +Prawdopodobieństwo mutacji dla każdego osobnika to 2%, ponieważ przy permutacjnym ułożeniu genów nie mamy pewności co do korzystności takiego zabiegu. Ma on na celu jedynie dywersyfikację genotypu w celu hipotetycznego znalezienia lepszych rozwiazań. + +Liczba pokoleń - tu jej wartość ustawiono na 40. Wartość tę otrzymano wywołując algorytm 10 razy dla każdej z trzech różnych wartości liczby pokoleń: 20, 50 oraz 100 i sprawdzaniu, w którym pokoleniu otrzymano najkrótszą trasę. Okazało się, że dla 50 i 100 pokoleń wartość ta była zbliżona i wynosiła odpowiednio 34 i 27. Zdecydowano zatem o doborze 40 pokoleń. +Liczebność pokolenia - ta została dobrana losowo na wartość 10, choć oczywiście nie ostatecznie. Jednak rezultaty przy tej konkretnej wartości okazały się na tyle zadowalające, że postanowiono jej nie zmieniać. +Warunek zatrzymania algorytmu - ten ustalono na 69% wartości średniej długości wszystkich tras z pierwszego pokolenia. Wybrano taką wartość ponownie, na podstawie wywoływanych wcześniej algorytmów dla 20, 50, 100 i ostatecznych 40 pokoleń. Za każdym razem iloraz najlepszego rozwiazania ze średnim kosztem tras pierwszego pokolenia oscylował między 0,67 a 0,7. \ No newline at end of file From fb7be6f86707e028f970471493e114c3db333e74 Mon Sep 17 00:00:00 2001 From: Piotr Rychlicki Date: Wed, 13 May 2020 09:29:23 +0000 Subject: [PATCH 11/13] Zaktualizowany raport geneticalgorithm.md --- geneticalgorithm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geneticalgorithm.md b/geneticalgorithm.md index 5836f93..a478fb1 100644 --- a/geneticalgorithm.md +++ b/geneticalgorithm.md @@ -98,7 +98,7 @@ Jeśli krzyżowanie dojdzie do skutki, wówczas dla obu osobników wykonuje się k = len(populacja_po_krzyzowaniu) - 1 while k >= 0: czy_mutacja = random.randint(0,100) - if czy_mutacja < 3: + if czy_mutacja < 3: kogo_mutujemy = populacja_po_krzyzowaniu[k] ``` From db88e677d65e969d17d100b7fa3f8cebe7a0b606 Mon Sep 17 00:00:00 2001 From: Piotr Rychlicki Date: Wed, 13 May 2020 09:30:08 +0000 Subject: [PATCH 12/13] Zaktualizowany raport geneticalgorithm.md --- geneticalgorithm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geneticalgorithm.md b/geneticalgorithm.md index a478fb1..130fa8f 100644 --- a/geneticalgorithm.md +++ b/geneticalgorithm.md @@ -137,7 +137,7 @@ Na sprawność działania algorytmu i jakość zwracanych rozwiązań wpływ maj * Prawdopodobieństwo zajścia mutacji * Warunek zatrzymania algorytmu -Na początek ustalono prawdopodobieństwa zajścia operacji genetycznych: +Na początek ustalono prawdopodobieństwa zajścia operacji genetycznych: Prawdopodobieństwo krzyżowania to 10%. Zazwyczaj jest ono większe, lecz dla klasycznego wariantu ułożenia genów, gdzie geny nie zmieniają pozycji w genotypie, lecz wartość. Tutaj użyto permutacyjnego wariantu ułożenia genów, a zatem krzyżowanie nie prowadzi do satysfakcjonujących wyników z dużą częstotliwością. Prawdopodobieństwo mutacji dla każdego osobnika to 2%, ponieważ przy permutacjnym ułożeniu genów nie mamy pewności co do korzystności takiego zabiegu. Ma on na celu jedynie dywersyfikację genotypu w celu hipotetycznego znalezienia lepszych rozwiazań. From 77d2cb7740f30fd916a70f835d9b9621690adfa8 Mon Sep 17 00:00:00 2001 From: Marcin Kwapisz Date: Wed, 13 May 2020 11:56:28 +0200 Subject: [PATCH 13/13] Gotowy podprojekt --- Marcin.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/Marcin.py b/Marcin.py index c62a460..db3fb80 100644 --- a/Marcin.py +++ b/Marcin.py @@ -1,5 +1,7 @@ -# import keras -import numpy +import numpy as np +import cv2 +import pygame + class main(): def __init__(self,traktor,field,ui,path): @@ -8,5 +10,62 @@ class main(): self.ui = ui self.path = path + def get_output_layers(self,net): + layer_names = net.getLayerNames() + output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()] + return output_layers + + def recognition(self,photo): + image = photo + + Width = image.shape[1] + Height = image.shape[0] + scale = 0.00392 + + with open("si.names", 'r') as f: + classes = [line.strip() for line in f.readlines()] + + COLORS = np.random.uniform(0, 255, size=(len(classes), 3)) + + net = cv2.dnn.readNet("si_final.weights", "si.cfg") + + blob = cv2.dnn.blobFromImage(image, scale, (416, 416), (0, 0, 0), True, crop=False) + + net.setInput(blob) + + outs = net.forward(self.get_output_layers(net)) + + class_ids = [] + confidences = [] + boxes = [] + conf_threshold = 0.5 + nms_threshold = 0.4 + + for out in outs: + for detection in out: + scores = detection[5:] + class_id = np.argmax(scores) + confidence = scores[class_id] + if confidence > 0.5: + class_ids.append(class_id) + print(class_id) + print(scores) + return class_id + def main(self): - pass + self.pole = self.ui.field_images[self.field.get_value(self.traktor.get_poz())] + self.img = pygame.surfarray.array3d(self.pole) + self.img = self.img.transpose([1,0,2]) + self.img = cv2.cvtColor(self.img, cv2.COLOR_RGB2BGR) + self.traktor.set_mode(self.mode(self.recognition(self.img))) + + def mode(self,mode): + self.mode_value = mode + if self.mode_value in [0, 1, 2, 3]: + return 0 + elif self.mode_value in [1, 3, 5, 7]: + return 1 + elif self.mode_value in [0, 1, 4, 5]: + return 2 + elif self.mode_value in [8]: + return 3