96 lines
3.7 KiB
Markdown
Executable File
96 lines
3.7 KiB
Markdown
Executable File
#### Definicja pętli głównej przeszukiwania:
|
|
W algorytmie znajdowania najlepszej ścieżki wykorzystana została kolejka priorytetowa *PriorityQueue()* służąca do przechowywania wierzchołków do odwiedzenia. Dopóki nie jest ona pusta, działa pętla główna przeszukiwania. W pętli kolejno:
|
|
|
|
1. z kolejki wybierany jest wierzchołek o najniższym priorytecie
|
|
```python
|
|
while self.open:
|
|
_, current_node = self.open.get()
|
|
```
|
|
|
|
2. dodawany jest on do listy już przeszukanych wierzchołków
|
|
```python
|
|
self.closed.append(current_node)
|
|
```
|
|
|
|
3. sprawdzane jest czy aktualny wierzchołek jest jednocześnie celem, który miał zostać osiągnięty przez agenta
|
|
```python
|
|
if current_node.x == self.dest.x and current_node.y == self.dest.y:
|
|
while current_node.x != start_node.x or current_node.y != start_node.y:
|
|
self.path.append(current_node)
|
|
current_node = current_node.parent
|
|
return True
|
|
```
|
|
|
|
>(jeśli tak, od strony celu odtwarzana jest najkrótsza ścieżka prowadząca z aktualnego punktu do celu)
|
|
|
|
4. znajdowani są sąsiedzi danego wierzchołka, a następnie dla każdego z nich:
|
|
|
|
+ liczony jest koszt za pomocą funkcji heurystyki
|
|
```python
|
|
cost = current_node.g_cost + self.heuristic(current_node, neighbour)
|
|
```
|
|
|
|
+ sprawdane jest czy nie należy on do listy już przeszukanych wierzchołkow (jeśli tak, zostaje on pominięty)
|
|
```python
|
|
if self.check_if_closed(neighbour):
|
|
continue
|
|
```
|
|
|
|
+ jeśli znajduje się on już w kolejce priorytetowej ale z większym kosztem niż ten obecnie wyliczony, uaktualniony zostaje jego koszt oraz rodzic
|
|
```python
|
|
if self.check_if_open(neighbour):
|
|
if neighbour.g_cost > cost:
|
|
neighbour.g_cost = cost
|
|
neighbour.parent = current_node
|
|
```
|
|
|
|
+ w przeciwnym przypadku, zostaje on dodany do kolejki priorytetowej wraz ze swoim rodzicem oraz wyliczonym kosztem.
|
|
```python
|
|
else:
|
|
neighbour.g_cost = cost
|
|
neighbour.h_cost = self.heuristic(neighbour, self.dest)
|
|
neighbour.parent = current_node
|
|
self.open.put((neighbour.g_cost, neighbour))
|
|
```
|
|
|
|
#### Definicja funkcji następnika:
|
|
|
|
```python
|
|
def get_neighbours(self, node: Node):
|
|
neighbours = []
|
|
if self.check_if_can_move(Coordinates(node.x + 1, node.y)):
|
|
neighbours.append(Node(node.x + 1, node.y))
|
|
if self.check_if_can_move(Coordinates(node.x - 1, node.y)):
|
|
neighbours.append(Node(node.x - 1, node.y))
|
|
if self.check_if_can_move(Coordinates(node.x, node.y + 1)):
|
|
neighbours.append(Node(node.x, node.y + 1))
|
|
if self.check_if_can_move(Coordinates(node.x, node.y - 1)):
|
|
neighbours.append(Node(node.x, node.y - 1))
|
|
return neighbours
|
|
```
|
|
Funkcja zwracająca następników w naszym projekcie wykorzystuje sąsiedztwo von Neumanna. Sąsiadami danej płytki, są 4 najbliższe płytki znajdujące się od niej powyżej, poniżej, na prawo oraz na lewo.
|
|
|
|
Dla każdego z 4 potencjalnych sąsiadów sprawdzane jest najpierw czy takowy istnieje za pomocą funkcji *check_if_can_move*:
|
|
|
|
```python
|
|
def check_if_can_move(self, next_coords: Coordinates):
|
|
tile_on_map = 0 <= next_coords.x < self.warehouse.width and 0 <= next_coords.y < self.warehouse.height
|
|
if not tile_on_map:
|
|
return False
|
|
next_tile = self.warehouse.tiles[next_coords.x][next_coords.y]
|
|
tile_passable = isinstance(next_tile, Tile) and next_tile.category.passable
|
|
return tile_passable
|
|
```
|
|
|
|
Funkcja ta sprawdza czy wybrany sąsiad znajduje się w obrębie magazynu i czy jest on płytką po której może przemieszczać się agent.
|
|
|
|
#### Definicja funkcji heurystyki:
|
|
|
|
```python
|
|
def heuristic(self, start: Node, goal: Node):
|
|
diff_x = pow(goal.x - start.x, 2)
|
|
diff_y = pow(goal.y - start.y, 2)
|
|
return round(sqrt(diff_x + diff_y), 3)
|
|
```
|
|
w naszym projekcie jako heurystyki używamy funkcji liczącej odległość euklidesową pomiędzy dwoma wybranymi punktami, z których drugi jest aktualnym celem który agent ma osiągnąć.
|