Лабораторная работа №4. Поиск пути в среде с преградами#
Цель работы - закрепить знания и получить опыт решения задачи поиска кратчайшего пути в дискретном двумерном пространстве с препятствиями.
Описание задачи#
Дано клеточное поле размером \(m \times n\). Шаг между соседними клетками равен 1.
Поле заполнено заданным числом препятствий, расположенных случайным образом. Каждое препятствие имеет ширину в одну клетку и случайную длину в диапазоне длин от \(l_{\rm min}\) до \(l_{\rm max}\) клеток. Длина является случайной величиной, распределённой по равномерному закону. Ориентация преграды на поле выбирается также случайным образом согласно равномерному закону распределения. Вариантов ориентации всего два: горизонтальная или вертикальная.
В районе левой части поля случайным образом выбирается свободная клетка. Данную точку (клетку) обозначим как A. Её радиус-вектор \(\vec{r}_{\rm A}\). В правой части аналогичным образом определяется точка B с радиус-вектором \(\vec{r}_{\rm B}\).
Размеры левой области, где генерируется точка \(\vec{r}_{\rm A}\):
Размеры правой области, где генерируется точка \(\vec{r}_{\rm B}\):
Из каждой клетки возможны четыре перемещения: вверх, вниз, вправо, влево. Или в географической формулировке: север (N), юг (S), восток (E), запад (W).
Задачи работы:
Найти кратчайший путь из точки A в точку B, используя алгоритм эвристического поиска A*, и найти длину этого пути. При этом суммарное количество клеток поля (\(m \cdot n\)) не должно быть меньше 5000.
Показать решение графически. Пример оформления графика показан на рисунке ниже.
Требования к содержанию и оформлению отчёту всё те же.
Шаблон кода#
Подключение библиотек:
from numpy.random import Generator, PCG64
import matplotlib.pyplot as plt
import numpy as np
# Добавляйте др. необходимые вам пакеты
...
Для воспроизведения и сравнения результатов необходим генератор случайных чисел.
rs = Generator(PCG64(seed=1747))
Note
Если seed != None
, а есть любое неотрицательное число, то при каждом запуске программы генератор будет выдавать одну и ту же последовательность чисел.
Функция создания карты (сетки)^
def create_empty_grid(size: tuple):
"""Создать пустую сетку размера size = (m, n)."""
pass
Функция заполнения сетки препятствиями:
def fill_obstacles(grid, n, min_len, max_len):
"""Заполнить клеточное поле grid n препятствиями.
Препятствие имеет случайную длину в диапазоне от min_len до max_len
и единичную ширину.
"""
pass
Функция генерации точки в свободной ячейке в заданной области:
def gen_point_in_area(grid, xlim, ylim, state):
"""Сгенерировать случайную точку в заданной области поля grid.
Параметры xlim и ylim определяют размеры и положение области генерации точки.
Параметр state определяет, является ли генерируемая точка исходной
точкой A или целевой точкой B.
"""
pass
Реализация алгоритма A*:
def calc_shortest_path(problem, w=1):
"""Поиск кратчайшего пути с помощью алгоритма A*.
* problem - проблемное пространство (клеточное поле).
* w - вес эвристики.
"""
pass
Ниже приведены заделки функций, которые могут быть полезными в плане разбиения программы для улучшения читаемости:
def expand(problem, node, w):
"""Раскрыть узел node поля problem.
w - весовой множитель эвристической функции.
"""
pass
def calc_cost(s, d, c, w):
"""Рассчитать стоимость действия агента.
* s - индекс (координата) (i, j) текущей ячейки.
* d - индекс (i, j) целевой ячейки.
* c - расстояние до текущей ячейки ("стоимость" текущей ячейки)
от начальной.
* w - весовой множитель эвристической функции.
"""
pass
def heuristic(s, d):
"""Функция эвристики - расстояние до целевой ячейки d из текущей s."""
pass
Пример исходных данных#
# Размеры (ширина и длина) поля
m, n = 100, 100
# Число препятствий
n_obs = 250
# min и max длины препятствий
obs_len = 3, 7
# Область пространства появления (точки A) и...
xlim0, ylim0 = [0, n // 5], [0, m]
# назначения объекта (точки B)
xlim1, ylim1 = [n - n // 5, n], [0, m]
Моделирование#
Функция запуска решателя задачи:
def simulate(*args):
"""Найти кратчайший путь из точки A в точку B."""
pass
Вместо *args
напишите свои аргументы.
Моделирование и получение результатов:
results = simulate(...)
Здесь вместо ...
также ваши переменные и параметры.
Обработка результатов и визуализация#
Пример функции построения итогового графика:
def plot_grid(grid, ax=None, **kw):
"""Визуализировать клеточное поле grid`."""
if ax is None:
fig, ax = plt.subplots()
...
return ax
Результат должен выглядеть примерно, как на рисунке ниже.
См. также#
В книге “Искусственный интеллект. Современный подход. Том 1” в главе 3 содержится подробная информация (описание и блок-схема) алгоритма А*. Эти знания могут сильно помочь вам в решении данной задачи.