Самый короткий путь на графике, где расстояния изменяются динамически? (максимальный энергетический путь)

Я пытаюсь найти кратчайший путь между двумя максимумами на дискретном энергетическом ландшафте, причем самым коротким путем является то, что уменьшает наименьшее по высоте в течение всего пути. Вероятно, максимальный путь энергии является более правильной терминологией, но, другими словами, даже если путь перемещается на большое расстояние вокруг ландшафта, но не спускается в долины, это считалось бы хорошим.

Моя первоначальная идея состояла в том, чтобы создать график пейзажа, в котором вес был разницей в высоте ландшафта между соседями, либо положительными отрицательными для восхождения и спуска соответственно. Я только что понял, что это не даст результат, который мне нужен, и на самом деле все пути между локальными максимумами будут иметь одинаковую стоимость.

Тогда я понял, что если расстояние между узлами на этом графике зависит от текущей позиции и истории пути, я мог бы получить нужный мне результат. например если путь спустился вниз и поднялся из долины, тогда я не назначил бы никаких дополнительных затрат для спуска в другую долину (пока путь не превышает минимумов, которые он не имел раньше).

Итак, существуют ли алгоритмы поиска графа, где расстояние может изменяться динамически по мере изучения путей?

Или есть ли другие предложения по атаке этой проблемы?

Ответ 1

Это известно как проблема кратчайшего пути в узком месте. Это на самом деле проще, чем проблема кратчайшего пути, и может быть решено за линейное время на неориентированных графах. Смотрите, например, здесь.

Ответ 2

Идея

Я предлагаю алгоритм, который строит вспомогательное дерево (T), в котором каждый узел содержит список вершин. Каждое поддерево будет содержать набор вершин, отделенных от остальной части графа долиной. Чтобы найти расстояние между любыми двумя узлами, нужно просто найти их самого низкого общего предка в дереве.

Алгоритм

Инициализация:

  1. Сортировка вершин по возрастанию (пробел: O(V), время: O(V log V))
  2. Пусть T состоит только из корневого узла r

MakeTree(G, r):

  1. Возьмите самую низкую вершину в графе G, удалите ее из графа и добавьте в список в корне r (стоимость времени на вершину: O(1 + E/V))
  2. Повторите вышеуказанный шаг до тех пор, пока график подключен
  3. Для каждого связанного компонента G' графика G:
    1. создайте новый узел n в T, присоедините узел как дочерний элемент корня
    2. рекурсивно запустить MakeTree(G', n)

Теперь у вас есть дерево с таким свойством, что если вы хотите перейти от вершины A к B, ваш путь максимальной энергии будет проходить через самую верхнюю из вершин, хранящихся в наименьшем общем предке A, и B. Чтобы найти расстояние, просто найдите наименьшего общего предка и возьмите наивысшую сохраненную там вершину C и рассчитайте max(abs(h(A) - h(C)), abs(h(B) - h(C))).

Пример

Ниже приведен пример графика и соответствующее дерево (для краткости метки вершин являются их высотами). Например, если вы хотите перейти с 22 на 14, вам нужно пройти через 10 (самая высокая вершина у самого низкого общего предка в дереве, расстояние = 22 - 10). Если вы хотите перейти с 22 на 20, вам нужно пройти через 13 (расстояние = 22 - 13).

                                    Example

Ответ 3

Может быть, следующие работы:

Создайте график ландшафта с весами dist + abs (height_a - height_b).

Функция abs делает подъем или падение дорогостоящим, и, как вы уже заметили, одной разницы в высоте недостаточно, поскольку она постоянна для любых двух точек на карте, независимо от того, по какому маршруту вы идете.

Dist - это обычное расстояние (или даже постоянная 1 во всех случаях), которое может быть опущено, но если вы хотите получить короткие пути, это должно отдавать предпочтение коротким по длинным с другими такими же затратами.

Это конечно не проверено. :-)

Ответ 4

Учитывая, что конечные точки в максимумах, ваша проблема эквивалентна этой:

Для x на графике пусть h (x) будет расстоянием ниже начальной точки. (По постановке задачи все точки находятся ниже начальной точки).

Найдите путь, который минимизирует: max (h (x) для x в пути).

Вы можете использовать вариант кратчайшего пути Дейкстры, чтобы решить эту проблему. Я скопировал и изменил описание алгоритма из Википедии (изменяется только вычисление расстояния на шаге 3).

  1. Назначьте каждому узлу значение расстояния. Установите его в ноль для нашего начального узла и в бесконечность для всех остальных узлов.

  2. Отметить все узлы как не посещенные. Установить начальный узел как текущий.

  3. Для текущего узла рассмотрите все его не посещенные соседи и вычислите их предварительное расстояние (от начального узла). Например, если текущий узел (A) имеет расстояние 6 и подключен к другому узлу (B) с h (B) = 7, расстояние от B до A будет max (6, 7) = 7. Если это расстояние меньше ранее записанного расстояния (бесконечность в начале, ноль для начального узла), перезапишите расстояние.

  4. Когда мы закончим с учетом всех соседей текущего узла, отметьте его как посещенный. Посещенный узел больше не будет проверяться; записанное в настоящее время расстояние является окончательным и минимальным. Если все узлы были посещены, закончите. В противном случае установите не посещаемый узел с наименьшим расстоянием (от начального узла) в качестве следующего "текущего узла" и продолжайте с шага 3.

Ответ 5

Так что вас не волнует общая длина пути, верно? Какое минимальное значение вы встретите на пути?

Если это так, то вы не должны использовать "расстояние" в традиционном смысле как стоимость для Дейкстры. Ваша очередь приоритетов должна возвращать узел с самым высоким значением энергии - таким образом, вы гарантированно никогда не пройдете путь через более низкое значение, если существует лучший путь.

Я считаю, что это отличается от того, что @Paul Hankin предлагает в своем ответе. Это, вероятно, откроет много узлов в графе; Я думаю, что вы можете оптимизировать следующим образом:

  1. Используйте [евклидово или манхэттенское] расстояние до цели в качестве тай-брейка в функции сравнения. Таким образом, если два узла имеют одинаковую энергию, вы попробуете тот, который быстрее достигает цели.

  2. При добавлении узлов в очередь с приоритетами вместо того, чтобы использовать их фактическую энергию для своей "стоимости", используйте минимум ее энергии и наименьшую энергию, встречающуюся до сих пор. Поскольку вы заботитесь только о минимальных глобальных затратах, после того как вы вынуждены использовать узел с низким энергопотреблением, все, что выше, "стоит" одинаково. Это заставляет поиск вести себя как обычный поиск A * в окрестности цели.

  3. Начинаем поиск с нижних локальных максимумов (я не уверен, но думаю, что это будет быстрее).

Использование расстояния в качестве разрыва связи в # 1 не повлияет на минимальную энергию, но оно должно заставить вещи работать быстрее (это похоже на поиск A *).


Изменить: здесь совершенно другой (но, вероятно, более медленный) способ мышления.

Сначала выберите порог энергии. Выполните стандартный поиск Dijkstra/A *, но отклоните все узлы, энергия которых ниже порога. Если у вас нет пути, выберите больший порог и попробуйте снова. "Безопасным" начальным предположением будет минимум E на простом пути (например, поверните налево, затем поднимитесь) от начала до цели.

Теперь увеличьте порог и повторите Dijkstra/A *. Продолжайте, пока не найдете путь. Последний путь перед тем, как вы больше не сможете найти путь, - это кратчайший путь с наибольшей минимальной энергией на пути.

Вы также можете повторно использовать стоимость пути из одного поиска в качестве улучшенной эвристики A * для следующего поиска. Поскольку увеличение порога приведет только к увеличению длины путей, это допустимая эвристика.


Надеюсь, это поможет. Дайте мне знать, если что-то неясно.

Ответ 6

Две возможности.

a) В частности. версия http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm существует линия, которая позволяет улучшить расстояние до точки v, используя маршрут через точку u:

alt: = dist [u] + dist_between (u, v)

14, если alt < dist [v]://Relax (u, v, a)

15 dist [v]: = alt

16 previous [v]: = u

Кажется, вам нужна версия, которая идет alt: = K - min (высота [u], высота [v]). Это работает по той же причине, что и версия с добавлением: в любое время набор вершин, удаленных из Q, имеет минимальную стоимость, разработанную правильно для любого маршрута из источника. Каждый раз, когда вы удаляете вершину из Q, потому что вы удаляете ее с минимальным расстоянием, нет никаких шансов на ее короткое сокращение, используя другие вершины, все еще находящиеся в Q.

b) Возьмите любой способ для разработки, если есть маршрут от источника. Используйте график, содержащий только точку с высотой >= H и посмотрите, есть ли решение. Попробуйте различные H, пока не найдете тот, который просто работает. Вы можете отсортировать все высоты заблаговременно, а затем использовать бинарный отбой в этом массиве.