Zaktualizuj 'route-planning.md'

This commit is contained in:
Aleksandra Jonas 2020-04-28 21:13:38 +00:00
parent ab046705c8
commit ce9956ee17

View File

@ -1,159 +1,159 @@
# *Sztuczna inteligencja - projekt zespołowy - Autonomiczny Traktor* # *Sztuczna inteligencja - projekt zespołowy - Autonomiczny Traktor*
#### autorzy: Aleksandra Werda, Natalia Wiśniewska, Kinga Jagodzińska, Aleksandra Jonas #### autorzy: Aleksandra Werda, Natalia Wiśniewska, Kinga Jagodzińska, Aleksandra Jonas
*** ***
## Planowanie ruchu ## Planowanie ruchu
- schemat procedury przeszukiwania grafu stanów z uwzględnieniem kosztu - schemat procedury przeszukiwania grafu stanów z uwzględnieniem kosztu
- strategia A* - strategia A*
___ ___
Drugim zadaniem dotyczącym projektu jest zastosowanie strategii przeszukiwania przestrzeni stanów do problemu planowania ruchu agenta na kracie. Drugim zadaniem dotyczącym projektu jest zastosowanie strategii przeszukiwania przestrzeni stanów do problemu planowania ruchu agenta na kracie.
___
## Heurystyka ## Heurystyka
- założenie — odległość pomiędzy sąsiadującymi polami wynosi 2, tyle samo co koszt wjazdu na puste pole - założenie — odległość pomiędzy sąsiadującymi polami wynosi 2, tyle samo co koszt wjazdu na puste pole
- s — pole, na którym jesteśmy - s — pole, na którym jesteśmy
- f — pole końcowe - f — pole końcowe
- dla s = f program kończy pracę, bo znajdujemy się już w położeniu końcowym, dlatego pominęłyśmy ten przypadek w definicji heurystyki. - dla s = f program kończy pracę, bo znajdujemy się już w położeniu końcowym, dlatego pominęłyśmy ten przypadek w definicji heurystyki.
``` ```
def hscore(self, s, f): def hscore(self, s, f):
if f > s: if f > s:
a_h = (f - s) // 5 a_h = (f - s) // 5
else: else:
a_h = (s - f) // 5 a_h = (s - f) // 5
if f % 5 >= s % 5: if f % 5 >= s % 5:
b_h = f % 5 - s % 5 b_h = f % 5 - s % 5
else: else:
b_h = s % 5 - f % 5 + 1 b_h = s % 5 - f % 5 + 1
return 2 * m.sqrt(a_h * 2 + b_h * 2) return 2 * m.sqrt(a_h * 2 + b_h * 2)
``` ```
Wpierw obliczamy wysokość trójkąta, jaki tworzą obecne i końcowe pole, w celu wyznaczenia przeciwprostokątnej — odległość między s i f. Wpierw obliczamy wysokość trójkąta, jaki tworzą obecne i końcowe pole, w celu wyznaczenia przeciwprostokątnej — odległość między s i f.
___
## Funkcja następnika ## Funkcja następnika
Tworzymy listę, do której będziemy kolejno generować sąsiadów dla danego x. Tworzymy listę, do której będziemy kolejno generować sąsiadów dla danego x.
``` ```
def neighbours(self): def neighbours(self):
self.neighbours = list(range(25)) self.neighbours = list(range(25))
self.neighbours[0] = [1, 5] self.neighbours[0] = [1, 5]
self.neighbours[4] = [3, 9] self.neighbours[4] = [3, 9]
self.neighbours[20] = [15, 21] self.neighbours[20] = [15, 21]
self.neighbours[24] = [19, 23] self.neighbours[24] = [19, 23]
for x in range(1, 4): for x in range(1, 4):
self.neighbours[x] = [x - 1, x + 5, x + 1] self.neighbours[x] = [x - 1, x + 5, x + 1]
for x in range(5, 16, 5): for x in range(5, 16, 5):
self.neighbours[x] = [x - 5, x + 1, x + 5] self.neighbours[x] = [x - 5, x + 1, x + 5]
for x in range(9, 20, 5): for x in range(9, 20, 5):
self.neighbours[x] = [x - 5, x - 1, x + 5] self.neighbours[x] = [x - 5, x - 1, x + 5]
for x in range(21, 24): for x in range(21, 24):
self.neighbours[x] = [x - 1, x - 5, x + 1] self.neighbours[x] = [x - 1, x - 5, x + 1]
for x in [6, 7, 8, 11, 12, 13, 16, 17, 18]: for x in [6, 7, 8, 11, 12, 13, 16, 17, 18]:
self.neighbours[x] = [x - 5, x - 1, x + 1, x + 5] self.neighbours[x] = [x - 5, x - 1, x + 1, x + 5]
``` ```
___
## Główna pętla strategii przeszukiwania ## Główna pętla strategii przeszukiwania
Zaczynamy od znalezienia w open_set pola o najniższym f. Zaczynamy od znalezienia w open_set pola o najniższym f.
``` ```
while open_set: while open_set:
# Szukanie pola w open_set z najniższym f # Szukanie pola w open_set z najniższym f
temp1 = max(self.f_score) + 1 temp1 = max(self.f_score) + 1
x = 0 x = 0
for i in range(len(open_set)): for i in range(len(open_set)):
if self.f_score[open_set[i]] <= temp1: if self.f_score[open_set[i]] <= temp1:
x = open_set[i] x = open_set[i]
temp1 = self.f_score[open_set[i]] temp1 = self.f_score[open_set[i]]
``` ```
Jeżeli to pole odpowiada temu, do którego chcemy dojść — wywołujemy funkcję tworzącą ścieżkę z pola wyjściowego. Póki nie — pomijamy. Jeżeli to pole odpowiada temu, do którego chcemy dojść — wywołujemy funkcję tworzącą ścieżkę z pola wyjściowego. Póki nie — pomijamy.
``` ```
if x == koniec: if x == koniec:
return self.reconstruct_path(self.came_from, koniec) return self.reconstruct_path(self.came_from, koniec)
``` ```
Usuwamy x z open_set i wrzucamy do closed_set, aby upewnić się, że nie będziemy go ponownie sprawdzać. Usuwamy x z open_set i wrzucamy do closed_set, aby upewnić się, że nie będziemy go ponownie sprawdzać.
``` ```
open_set.remove(x) open_set.remove(x)
closed_set.append(x) closed_set.append(x)
``` ```
Następnie sprawdzamy sąsiadów: Następnie sprawdzamy sąsiadów:
``` ```
for y in self.neighbours[x]: for y in self.neighbours[x]:
``` ```
To tutaj chcieliśmy mieć pewność, że nie trafimy ponownie na x. To tutaj chcieliśmy mieć pewność, że nie trafimy ponownie na x.
``` ```
if y in closed_set: if y in closed_set:
continue continue
``` ```
Chcemy również sprawdzić, czy jeżeli y jest już w open_set, to nie istnieje krótsze przejście np. z pola startowego przez inne pole na y, niż bezpośrednio na pole y. Chcemy również sprawdzić, czy jeżeli y jest już w open_set, to nie istnieje krótsze przejście np. z pola startowego przez inne pole na y, niż bezpośrednio na pole y.
``` ```
tentative_g_score = self.g_score[x] + self.game.fields[y][3] tentative_g_score = self.g_score[x] + self.game.fields[y][3]
if y not in open_set: if y not in open_set:
open_set.append(y) open_set.append(y)
tentative_is_better = True tentative_is_better = True
elif tentative_g_score < self.g_score[y]: elif tentative_g_score < self.g_score[y]:
tentative_is_better = True tentative_is_better = True
``` ```
Wyliczamy g i f — przewidywany dystans od startu do celu, dla y. Wyliczamy g i f — przewidywany dystans od startu do celu, dla y.
``` ```
if tentative_is_better == True: if tentative_is_better == True:
self.came_from[y] = x self.came_from[y] = x
self.g_score[y] = tentative_g_score self.g_score[y] = tentative_g_score
self.f_score[y] = self.g_score[y] + self.hscore(y, koniec) self.f_score[y] = self.g_score[y] + self.hscore(y, koniec)
``` ```
___
## Tworzenie ścieżki ## Tworzenie ścieżki
Przechodzimy po tablicy poprzedników, aż dojdziemy do początku — pola, które nie ma poprzednika. Przechodzimy po tablicy poprzedników, aż dojdziemy do początku — pola, które nie ma poprzednika.
``` ```
def reconstruct_path(self, came_from, current): def reconstruct_path(self, came_from, current):
total_path = [current] total_path = [current]
while came_from[current] != 0: while came_from[current] != 0:
current = came_from[current] current = came_from[current]
total_path.insert(0, current) total_path.insert(0, current)
return total_path return total_path
``` ```
___
## Koszt podróży na pola uprawne ## Koszt podróży na pola uprawne
Zmiany w projekcie zaszły również w pliku run.py, gdzie generujemy losowo pola — każdy kolor odpowiada innej uprawie i etapie jej wzrostu. Zmiany w projekcie zaszły również w pliku run.py, gdzie generujemy losowo pola — każdy kolor odpowiada innej uprawie i etapie jej wzrostu.
Mamy tutaj tablicę tablic. Każda z nich zawiera kolejno informacje o: rodzaju upraw, glebie, nawodnieniu pola oraz koszcie podróży na pole z daną uprawą. Mamy tutaj tablicę tablic. Każda z nich zawiera kolejno informacje o: rodzaju upraw, glebie, nawodnieniu pola oraz koszcie podróży na pole z daną uprawą.
``` ```
def randomize_field(self): def randomize_field(self):
for x in range(25): for x in range(25):
temp = [] temp = []
# nasiona # nasiona
temp.append(random.choice(["żyto", "jęczmień", "owies", "marchew", "rzodkiew", "pietruszka", "puste"])) temp.append(random.choice(["żyto", "jęczmień", "owies", "marchew", "rzodkiew", "pietruszka", "puste"]))
# gleba # gleba
temp.append(random.choice([True, False])) temp.append(random.choice([True, False]))
# woda # woda
temp.append(random.choice([True, False])) temp.append(random.choice([True, False]))
# # growth rate # # growth rate
# temp.append(random) # temp.append(random)
# # cost # # cost
if temp[0] == "żyto": if temp[0] == "żyto":
temp.append(10) temp.append(10)
elif temp[0] == "jęczmień": elif temp[0] == "jęczmień":
temp.append(12) temp.append(12)
elif temp[0] == "owies": elif temp[0] == "owies":
temp.append(8) temp.append(8)
elif temp[0] == "marchew": elif temp[0] == "marchew":
temp.append(14) temp.append(14)
elif temp[0] == "rzodkiew": elif temp[0] == "rzodkiew":
temp.append(7) temp.append(7)
elif temp[0] == "pietruszka": elif temp[0] == "pietruszka":
temp.append(6) temp.append(6)
elif temp[0] == "puste": elif temp[0] == "puste":
temp.append(2) temp.append(2)
else: else:
temp.append(0) temp.append(0)
self.fields.append(temp) self.fields.append(temp)
``` ```