import field, pathfinding_tractorless, pathfinding_tractor import random class main(): def __init__(self,traktor,field,ui,path): self.traktor = traktor self.field = field self.ui = ui self.path = path self.pathfinding_tractorless = pathfinding_tractorless.pathfinding_tractorless() self.pathfinding_tractor = pathfinding_tractor.pathfinding_tractor() def wspolrzedne(self): #wyznacza wspolrzedne pol danego rodzaju na planszy znalezione_pola = [] k = 0 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: znalezione_pola.append(k*10+l) l = l + 1 k = k + 1 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 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,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 w zadanej kolejności: " + str(total_cost)) # print("###################") return total_cost def tworzenie_pokolenia(self,znalezione_pola,i): x = len(znalezione_pola) - 2 wspolrzedne_shuffle = [] while x > 0: wspolrzedne_shuffle.append(znalezione_pola[x]) x = x - 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)) 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 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.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.koszt_przejazdu(i)) suma_kosztow_tras = suma_kosztow_tras + self.koszt_przejazdu(i) ile_osobnikow = ile_osobnikow + 1 if self.koszt_przejazdu(i) < najnizszy_koszt: najnizszy_koszt = self.koszt_przejazdu(i) najtanszy_osobnik = 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 przystosowanie_osobnikow = [] sumaryczne_przystosowanie_osobnikow = 0 l = 0 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, najnizszy_koszt, najwyzszy_koszt, srednie_przystosowanie, najtanszy_osobnik) def wybor_populacji_posredniej(self,pierwsze_pokolenie,przystosowanie_osobnikow): x = len(przystosowanie_osobnikow) tabela_ruletki = [] populacja_posrednia = [] i = 0 przedzial = 0 while x > 0: #stworzenie "koła ruletki" do selecji osobników populacji pośredniej przedzial = przedzial + przystosowanie_osobnikow[i] tabela_ruletki.append(round(przedzial,2)) x = x - 1 i = i + 1 #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: i = 0 n = random.uniform(0, maks) #losowanie przedziału while n > tabela_ruletki[i]: i = i + 1 populacja_posrednia.append(pierwsze_pokolenie[i]) x = x - 1 # 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)) rodzic_2 = populacja_posrednia[x-1] #print("Rodzic nr 2: " + str(rodzic_2)) dziecko_1 = [] dziecko_2 = [] czy_krzyzowac = random.randint(1,100) #losowanie czy krzyzowac rodzicow, czy nie (szanse 10%) 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 while k >= 0: #dodawanie do dziecka pierwszej połowy z pierwszego rodzica dziecko_1.append(rodzic_1[l]) l = l + 1 k = k - 1 k = miejsce_krzyzowania while k < (len(rodzic_1)-2): #dodawanie do dziecka drugiej połowy z drugiego rodzica for i in rodzic_2: if i not in dziecko_1: dziecko_1.append(i) k = k + 1 l = 0 k = miejsce_krzyzowania while k >= 0: #dodawanie do dziecka pierwszej połowy z pierwszego rodzica dziecko_2.append(rodzic_2[l]) l = l + 1 k = k - 1 k = miejsce_krzyzowania while k < (len(rodzic_1)-2): #dodawanie do dziecka drugiej połowy z drugiego rodzica for i in rodzic_1: if i not in dziecko_2: dziecko_2.append(i) k = k + 1 dziecko_1.append(0) dziecko_2.append(0) else: #jesli krzyzowanie nie nastepuje, wowczas potencjalni rodzice staja sie dziecmi dziecko_1 = rodzic_1 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)) 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)) rodzic_2 = populacja_posrednia[(len(populacja_posrednia)-1)] #print("Rodzic nr 2: " + str(rodzic_2)) dziecko_1 = [] dziecko_2 = [] czy_krzyzowac = random.randint(1,100) #losowanie czy krzyzowac rodzicow, czy nie (szanse 10%) 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 while k >= 0: #dodawanie do dziecka pierwszej połowy z pierwszego rodzica dziecko_1.append(rodzic_1[l]) l = l + 1 k = k - 1 k = miejsce_krzyzowania while k < (len(rodzic_1)-2): #dodawanie do dziecka drugiej połowy z drugiego rodzica for i in rodzic_2: if i not in dziecko_1: dziecko_1.append(i) k = k + 1 l = 0 k = miejsce_krzyzowania while k >= 0: #dodawanie do dziecka pierwszej połowy z pierwszego rodzica dziecko_2.append(rodzic_2[l]) l = l + 1 k = k - 1 k = miejsce_krzyzowania while k < (len(rodzic_1)-2): #dodawanie do dziecka drugiej połowy z drugiego rodzica for i in rodzic_1: if i not in dziecko_2: dziecko_2.append(i) k = k + 1 dziecko_1.append(0) dziecko_2.append(0) else: #jesli krzyzowanie nie nastepuje, wowczas potencjalni rodzice staja sie dziecmi dziecko_1 = rodzic_1 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)) return populacja_po_krzyzowaniu 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 # print("Populacja po mutacji: " + str(populacja_po_mutacji)) return populacja_po_mutacji 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 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(znalezione_pola) - 2 wspolrzedne_shuffle = [] while x > 0: wspolrzedne_shuffle.append(znalezione_pola[x]) x = x - 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) 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.znalezione_pola = self.wspolrzedne() self.koszt_trasy = self.koszt_przejazdu(self.znalezione_pola) # 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) 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.najtanszy_osobnik = self.ocena_przystosowania(self.populacja_po_optymalizacji) if self.najwyzszy_koszt > self.maks_koszt: self.maks_koszt = self.najwyzszy_koszt if self.najnizszy_koszt < self.min_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 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) 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("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 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 def main(self): self.algorytm_genetyczny() self.wykonanie_trasy()